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 SilcSocketConnection hsock;
681 for (i = 0; i < clients_count; i++)
682 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
685 if (len == 0 && clients_count) {
687 if (entry->nickname) {
688 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
689 SILC_STATUS_ERR_NO_SUCH_NICK,
691 strlen(entry->nickname));
693 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
694 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
695 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
696 2, idp->data, idp->len);
697 silc_buffer_free(idp);
703 status = SILC_STATUS_OK;
705 status = SILC_STATUS_LIST_START;
707 for (i = 0, k = 0; i < clients_count; i++) {
710 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
711 if (clients_count == 1) {
712 if (entry->nickname) {
713 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
714 SILC_STATUS_ERR_NO_SUCH_NICK,
716 strlen(entry->nickname));
718 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
719 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
720 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
721 2, idp->data, idp->len);
722 silc_buffer_free(idp);
729 status = SILC_STATUS_LIST_ITEM;
731 if (clients_count > 1 && k == clients_count - 1)
732 status = SILC_STATUS_LIST_END;
734 if (count && k - 1 == count)
735 status = SILC_STATUS_LIST_END;
737 if (count && k - 1 > count)
740 /* Sanity check, however these should never fail. However, as
741 this sanity check has been added here they have failed. */
742 if (!entry->nickname || !entry->username || !entry->userinfo)
745 /* Send WHOIS reply */
746 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
747 tmp = silc_argument_get_first_arg(cmd->args, NULL);
749 memset(uh, 0, sizeof(uh));
750 memset(nh, 0, sizeof(nh));
751 memset(idle, 0, sizeof(idle));
753 strncat(nh, entry->nickname, strlen(entry->nickname));
754 if (!strchr(entry->nickname, '@')) {
756 if (entry->servername) {
757 strncat(nh, entry->servername, strlen(entry->servername));
759 len = entry->router ? strlen(entry->router->server_name) :
760 strlen(server->server_name);
761 strncat(nh, entry->router ? entry->router->server_name :
762 server->server_name, len);
766 strncat(uh, entry->username, strlen(entry->username));
767 if (!strchr(entry->username, '@')) {
769 hsock = (SilcSocketConnection)entry->connection;
770 len = strlen(hsock->hostname);
771 strncat(uh, hsock->hostname, len);
774 channels = silc_server_get_client_channel_list(server, entry);
776 SILC_PUT32_MSB(entry->mode, mode);
778 if (entry->connection) {
779 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
783 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
785 2, idp->data, idp->len,
789 strlen(entry->userinfo),
795 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
797 2, idp->data, idp->len,
801 strlen(entry->userinfo),
805 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
806 0, packet->data, packet->len, FALSE);
808 silc_buffer_free(packet);
809 silc_buffer_free(idp);
811 silc_buffer_free(channels);
818 silc_server_command_whois_process(SilcServerCommandContext cmd)
820 SilcServer server = cmd->server;
821 char *nick = NULL, *server_name = NULL;
823 SilcClientEntry *clients = NULL, entry;
824 SilcClientID **client_id = NULL;
825 uint32 client_id_count = 0, clients_count = 0;
827 bool check_global = FALSE;
829 /* Protocol dictates that we must always send the received WHOIS request
830 to our router if we are normal server, so let's do it now unless we
831 are standalone. We will not send any replies to the client until we
832 have received reply from the router. */
833 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
834 server->server_type == SILC_SERVER && !cmd->pending &&
835 !server->standalone) {
839 old_ident = silc_command_get_ident(cmd->payload);
840 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
841 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
843 /* Send WHOIS command to our router */
844 silc_server_packet_send(server, (SilcSocketConnection)
845 server->router->connection,
846 SILC_PACKET_COMMAND, cmd->packet->flags,
847 tmpbuf->data, tmpbuf->len, TRUE);
849 /* Reprocess this packet after received reply from router */
850 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
851 silc_command_get_ident(cmd->payload),
852 silc_server_command_destructor,
853 silc_server_command_whois,
854 silc_server_command_dup(cmd));
857 silc_command_set_ident(cmd->payload, old_ident);
859 silc_buffer_free(tmpbuf);
864 /* We are ready to process the command request. Let's search for the
865 requested client and send reply to the requesting client. */
867 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
869 else if (server->server_type == SILC_ROUTER)
872 /* Parse the whois request */
873 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
874 &nick, &server_name, &count,
878 /* Get all clients matching that ID or nickname from local list */
879 if (client_id_count) {
880 /* Check all Client ID's received in the command packet */
881 for (i = 0; i < client_id_count; i++) {
882 entry = silc_idlist_find_client_by_id(server->local_list,
883 client_id[i], TRUE, NULL);
884 if (!entry && check_global)
885 entry = silc_idlist_find_client_by_id(server->global_list,
886 client_id[i], TRUE, NULL);
888 clients = silc_realloc(clients, sizeof(*clients) *
889 (clients_count + 1));
890 clients[clients_count++] = entry;
894 if (!silc_idlist_get_clients_by_hash(server->local_list,
895 nick, server->md5hash,
896 &clients, &clients_count))
897 silc_idlist_get_clients_by_nickname(server->local_list,
899 &clients, &clients_count);
901 if (!silc_idlist_get_clients_by_hash(server->global_list,
902 nick, server->md5hash,
903 &clients, &clients_count))
904 silc_idlist_get_clients_by_nickname(server->global_list,
906 &clients, &clients_count);
911 /* Such client(s) really does not exist in the SILC network. */
912 if (!client_id_count) {
913 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
914 SILC_STATUS_ERR_NO_SUCH_NICK,
915 3, nick, strlen(nick));
917 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
918 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
919 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
920 2, idp->data, idp->len);
921 silc_buffer_free(idp);
926 /* Router always finds the client entry if it exists in the SILC network.
927 However, it might be incomplete entry and does not include all the
928 mandatory fields that WHOIS command reply requires. Check for these and
929 make query from the server who owns the client if some fields are
931 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
936 /* Send the command reply */
937 silc_server_command_whois_send_reply(cmd, clients, clients_count,
941 if (client_id_count) {
942 for (i = 0; i < client_id_count; i++)
943 silc_free(client_id[i]);
944 silc_free(client_id);
951 silc_free(server_name);
956 /* Server side of command WHOIS. Processes user's query and sends found
957 results as command replies back to the client. */
959 SILC_SERVER_CMD_FUNC(whois)
961 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
964 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
966 ret = silc_server_command_whois_process(cmd);
969 silc_server_command_free(cmd);
972 /******************************************************************************
976 ******************************************************************************/
979 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
987 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
990 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
994 /* Get the nickname@server string and parse it. */
995 silc_parse_userfqdn(tmp, nickname, server_name);
997 /* Get the max count of reply messages allowed */
998 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1008 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1009 SilcClientEntry *clients,
1010 uint32 clients_count)
1012 SilcServer server = cmd->server;
1014 SilcClientEntry entry;
1016 for (i = 0; i < clients_count; i++) {
1019 if (!entry->nickname || !entry->username) {
1026 old_ident = silc_command_get_ident(cmd->payload);
1027 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1028 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1030 /* Send WHOWAS command */
1031 silc_server_packet_send(server, entry->router->connection,
1032 SILC_PACKET_COMMAND, cmd->packet->flags,
1033 tmpbuf->data, tmpbuf->len, TRUE);
1035 /* Reprocess this packet after received reply */
1036 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1037 silc_command_get_ident(cmd->payload),
1038 silc_server_command_destructor,
1039 silc_server_command_whowas,
1040 silc_server_command_dup(cmd));
1041 cmd->pending = TRUE;
1043 silc_command_set_ident(cmd->payload, old_ident);
1045 silc_buffer_free(tmpbuf);
1054 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1055 SilcClientEntry *clients,
1056 uint32 clients_count)
1058 SilcServer server = cmd->server;
1060 int i, count = 0, len;
1061 SilcBuffer packet, idp;
1062 SilcClientEntry entry = NULL;
1063 SilcCommandStatus status;
1064 uint16 ident = silc_command_get_ident(cmd->payload);
1066 char nh[256], uh[256];
1068 status = SILC_STATUS_OK;
1069 if (clients_count > 1)
1070 status = SILC_STATUS_LIST_START;
1072 for (i = 0; i < clients_count; i++) {
1075 /* We will take only clients that are not valid anymore. They are the
1076 ones that are not registered anymore but still have a ID. They
1077 have disconnected us, and thus valid for WHOWAS. */
1078 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED)
1080 if (entry->id == NULL)
1083 if (count && i - 1 == count)
1088 if (clients_count > 2)
1089 status = SILC_STATUS_LIST_ITEM;
1091 if (clients_count > 1 && i == clients_count - 1)
1092 status = SILC_STATUS_LIST_END;
1094 /* Sanity check, however these should never fail. However, as
1095 this sanity check has been added here they have failed. */
1096 if (!entry->nickname || !entry->username)
1099 /* Send WHOWAS reply */
1100 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1101 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1103 memset(uh, 0, sizeof(uh));
1104 memset(nh, 0, sizeof(nh));
1106 strncat(nh, entry->nickname, strlen(entry->nickname));
1107 if (!strchr(entry->nickname, '@')) {
1108 strncat(nh, "@", 1);
1109 if (entry->servername) {
1110 strncat(nh, entry->servername, strlen(entry->servername));
1112 len = entry->router ? strlen(entry->router->server_name) :
1113 strlen(server->server_name);
1114 strncat(nh, entry->router ? entry->router->server_name :
1115 server->server_name, len);
1119 strncat(uh, entry->username, strlen(entry->username));
1120 if (!strchr(entry->username, '@')) {
1121 strncat(uh, "@", 1);
1122 strcat(uh, "*private*");
1125 if (entry->userinfo)
1127 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1129 2, idp->data, idp->len,
1133 strlen(entry->userinfo));
1136 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1138 2, idp->data, idp->len,
1142 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1143 0, packet->data, packet->len, FALSE);
1145 silc_buffer_free(packet);
1146 silc_buffer_free(idp);
1149 if (found == FALSE && entry)
1150 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1151 SILC_STATUS_ERR_NO_SUCH_NICK,
1153 strlen(entry->nickname));
1157 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1159 SilcServer server = cmd->server;
1160 char *nick = NULL, *server_name = NULL;
1162 SilcClientEntry *clients = NULL;
1163 uint32 clients_count = 0;
1165 bool check_global = FALSE;
1167 /* Protocol dictates that we must always send the received WHOWAS request
1168 to our router if we are normal server, so let's do it now unless we
1169 are standalone. We will not send any replies to the client until we
1170 have received reply from the router. */
1171 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1172 server->server_type == SILC_SERVER && !cmd->pending &&
1173 !server->standalone) {
1177 old_ident = silc_command_get_ident(cmd->payload);
1178 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1179 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1181 /* Send WHOWAS command to our router */
1182 silc_server_packet_send(server, (SilcSocketConnection)
1183 server->router->connection,
1184 SILC_PACKET_COMMAND, cmd->packet->flags,
1185 tmpbuf->data, tmpbuf->len, TRUE);
1187 /* Reprocess this packet after received reply from router */
1188 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1189 silc_command_get_ident(cmd->payload),
1190 silc_server_command_destructor,
1191 silc_server_command_whowas,
1192 silc_server_command_dup(cmd));
1193 cmd->pending = TRUE;
1195 silc_command_set_ident(cmd->payload, old_ident);
1197 silc_buffer_free(tmpbuf);
1202 /* We are ready to process the command request. Let's search for the
1203 requested client and send reply to the requesting client. */
1205 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1206 check_global = TRUE;
1207 else if (server->server_type == SILC_ROUTER)
1208 check_global = TRUE;
1210 /* Parse the whowas request */
1211 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1214 /* Get all clients matching that nickname from local list */
1215 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1217 &clients, &clients_count))
1218 silc_idlist_get_clients_by_hash(server->local_list,
1219 nick, server->md5hash,
1220 &clients, &clients_count);
1222 /* Check global list as well */
1224 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1226 &clients, &clients_count))
1227 silc_idlist_get_clients_by_hash(server->global_list,
1228 nick, server->md5hash,
1229 &clients, &clients_count);
1233 /* Such a client really does not exist in the SILC network. */
1234 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1235 SILC_STATUS_ERR_NO_SUCH_NICK,
1236 3, nick, strlen(nick));
1240 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1241 !silc_server_command_whowas_check(cmd, clients, clients_count)) {
1246 /* Send the command reply to the client */
1247 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1252 silc_free(server_name);
1257 /* Server side of command WHOWAS. */
1259 SILC_SERVER_CMD_FUNC(whowas)
1261 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1264 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1266 ret = silc_server_command_whowas_process(cmd);
1269 silc_server_command_free(cmd);
1272 /******************************************************************************
1276 ******************************************************************************/
1279 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1280 SilcClientEntry **clients,
1281 uint32 *clients_count,
1282 SilcServerEntry **servers,
1283 uint32 *servers_count,
1284 SilcChannelEntry **channels,
1285 uint32 *channels_count,
1288 SilcServer server = cmd->server;
1291 uint32 argc = silc_argument_get_arg_num(cmd->args);
1293 bool check_global = FALSE;
1298 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1299 check_global = TRUE;
1300 else if (server->server_type == SILC_ROUTER)
1301 check_global = TRUE;
1303 /* If ID Payload is in the command it must be used instead of names */
1304 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1306 /* No ID, get the names. */
1308 /* Try to get nickname@server. */
1309 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1312 char *nick_server = NULL;
1314 silc_parse_userfqdn(tmp, &nick, &nick_server);
1316 if (!silc_idlist_get_clients_by_hash(server->local_list,
1317 nick, server->md5hash,
1318 clients, clients_count))
1319 silc_idlist_get_clients_by_nickname(server->local_list,
1321 clients, clients_count);
1323 if (!silc_idlist_get_clients_by_hash(server->global_list,
1324 nick, server->md5hash,
1325 clients, clients_count))
1326 silc_idlist_get_clients_by_nickname(server->global_list,
1328 clients, clients_count);
1332 silc_free(nick_server);
1335 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1336 SILC_STATUS_ERR_NO_SUCH_NICK,
1337 3, tmp, strlen(tmp));
1342 /* Try to get server name */
1343 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1345 entry = silc_idlist_find_server_by_name(server->local_list,
1347 if (!entry && check_global)
1348 entry = silc_idlist_find_server_by_name(server->local_list,
1351 *servers = silc_realloc(*servers, sizeof(**servers) *
1352 (*servers_count + 1));
1353 (*servers)[(*servers_count)++] = entry;
1357 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1358 SILC_STATUS_ERR_NO_SUCH_SERVER,
1359 3, tmp, strlen(tmp));
1364 /* Try to get channel name */
1365 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1367 entry = silc_idlist_find_channel_by_name(server->local_list,
1369 if (!entry && check_global)
1370 entry = silc_idlist_find_channel_by_name(server->local_list,
1373 *channels = silc_realloc(*channels, sizeof(**channels) *
1374 (*channels_count + 1));
1375 (*channels)[(*channels_count)++] = entry;
1379 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1380 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1381 3, tmp, strlen(tmp));
1386 if (!(*clients) && !(*servers) && !(*channels)) {
1387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1388 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1392 /* Command includes ID, we must use that. Also check whether the command
1393 has more than one ID set - take them all. */
1395 /* Take all ID's from the command packet */
1396 for (i = 0; i < argc; i++) {
1399 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1403 idp = silc_id_payload_parse_data(tmp, len);
1405 silc_free(*clients);
1406 silc_free(*servers);
1407 silc_free(*channels);
1408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1409 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1413 id = silc_id_payload_get_id(idp);
1415 switch (silc_id_payload_get_type(idp)) {
1417 case SILC_ID_CLIENT:
1418 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1420 if (!entry && check_global)
1421 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1424 *clients = silc_realloc(*clients, sizeof(**clients) *
1425 (*clients_count + 1));
1426 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1428 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1429 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1436 case SILC_ID_SERVER:
1437 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1439 if (!entry && check_global)
1440 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1443 *servers = silc_realloc(*servers, sizeof(**servers) *
1444 (*servers_count + 1));
1445 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1447 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1448 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1454 case SILC_ID_CHANNEL:
1455 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1457 if (!entry && check_global)
1458 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1461 *channels = silc_realloc(*channels, sizeof(**channels) *
1462 (*channels_count + 1));
1463 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1465 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1466 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1478 silc_free(*clients);
1479 silc_free(*servers);
1480 silc_free(*channels);
1484 /* Get the max count of reply messages allowed */
1485 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1494 /* Checks that all mandatory fields in client entry are present. If not
1495 then send WHOIS request to the server who owns the client. We use
1496 WHOIS because we want to get as much information as possible at once. */
1499 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1500 SilcClientEntry *clients,
1501 uint32 clients_count)
1503 SilcServer server = cmd->server;
1504 SilcClientEntry entry;
1505 SilcServerResolveContext resolve = NULL, r = NULL;
1506 uint32 resolve_count = 0;
1510 for (i = 0; i < clients_count; i++) {
1513 if (!entry || entry->nickname ||
1514 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
1518 /* We need to resolve this entry since it is not complete */
1520 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1521 /* The entry is being resolved (and we are not the resolver) so attach
1522 to the command reply and we're done with this one. */
1523 silc_server_command_pending(server, SILC_COMMAND_NONE,
1524 entry->resolve_cmd_ident,
1525 silc_server_command_destructor,
1526 silc_server_command_identify,
1527 silc_server_command_dup(cmd));
1530 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1531 /* We've resolved this and it still is not ready. We'll return
1532 and are that this will be handled again after it is resolved. */
1533 for (i = 0; i < resolve_count; i++) {
1534 for (k = 0; k < r->res_argc; k++)
1535 silc_free(r->res_argv[k]);
1536 silc_free(r->res_argv);
1537 silc_free(r->res_argv_lens);
1538 silc_free(r->res_argv_types);
1543 /* We'll resolve this client */
1547 for (k = 0; k < resolve_count; k++) {
1548 if (resolve[k].router == entry->router) {
1555 resolve = silc_realloc(resolve, sizeof(*resolve) *
1556 (resolve_count + 1));
1557 r = &resolve[resolve_count];
1558 memset(r, 0, sizeof(*r));
1559 r->router = entry->router;
1560 r->ident = ++server->cmd_ident;
1564 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1566 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1567 sizeof(*r->res_argv_lens) *
1569 r->res_argv_types = silc_realloc(r->res_argv_types,
1570 sizeof(*r->res_argv_types) *
1572 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1573 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1574 sizeof(**r->res_argv));
1575 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1576 r->res_argv_lens[r->res_argc] = idp->len;
1577 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1579 silc_buffer_free(idp);
1581 entry->resolve_cmd_ident = r->ident;
1582 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1583 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1588 /* Do the resolving */
1589 for (i = 0; i < resolve_count; i++) {
1594 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1595 now anyway so make it a good one. */
1596 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1597 r->res_argc, r->res_argv,
1601 silc_server_packet_send(server, r->router->connection,
1602 SILC_PACKET_COMMAND, cmd->packet->flags,
1603 res_cmd->data, res_cmd->len, FALSE);
1605 /* Reprocess this packet after received reply */
1606 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1608 silc_server_command_destructor,
1609 silc_server_command_identify,
1610 silc_server_command_dup(cmd));
1611 cmd->pending = TRUE;
1613 silc_buffer_free(res_cmd);
1614 for (k = 0; k < r->res_argc; k++)
1615 silc_free(r->res_argv[k]);
1616 silc_free(r->res_argv);
1617 silc_free(r->res_argv_lens);
1618 silc_free(r->res_argv_types);
1627 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1628 SilcClientEntry *clients,
1629 uint32 clients_count,
1630 SilcServerEntry *servers,
1631 uint32 servers_count,
1632 SilcChannelEntry *channels,
1633 uint32 channels_count,
1636 SilcServer server = cmd->server;
1638 SilcBuffer packet, idp;
1639 SilcCommandStatus status;
1640 uint16 ident = silc_command_get_ident(cmd->payload);
1641 char nh[256], uh[256];
1642 SilcSocketConnection hsock;
1644 status = SILC_STATUS_OK;
1647 SilcClientEntry entry;
1650 for (i = 0; i < clients_count; i++)
1651 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1654 if (len == 0 && clients_count) {
1656 if (entry->nickname) {
1657 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1658 SILC_STATUS_ERR_NO_SUCH_NICK,
1660 strlen(entry->nickname));
1662 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1663 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1664 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1665 2, idp->data, idp->len);
1666 silc_buffer_free(idp);
1673 status = SILC_STATUS_LIST_START;
1675 for (i = 0, k = 0; i < clients_count; i++) {
1678 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1679 if (clients_count == 1) {
1680 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1681 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1682 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1683 2, idp->data, idp->len);
1684 silc_buffer_free(idp);
1690 status = SILC_STATUS_LIST_ITEM;
1691 if (clients_count > 1 && k == clients_count - 1
1692 && !servers_count && !channels_count)
1693 status = SILC_STATUS_LIST_END;
1694 if (count && k - 1 == count)
1695 status = SILC_STATUS_LIST_END;
1696 if (count && k - 1 > count)
1699 /* Send IDENTIFY reply */
1700 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1702 memset(uh, 0, sizeof(uh));
1703 memset(nh, 0, sizeof(nh));
1705 strncat(nh, entry->nickname, strlen(entry->nickname));
1706 if (!strchr(entry->nickname, '@')) {
1707 strncat(nh, "@", 1);
1708 if (entry->servername) {
1709 strncat(nh, entry->servername, strlen(entry->servername));
1711 len = entry->router ? strlen(entry->router->server_name) :
1712 strlen(server->server_name);
1713 strncat(nh, entry->router ? entry->router->server_name :
1714 server->server_name, len);
1718 if (!entry->username) {
1719 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1721 2, idp->data, idp->len,
1724 strncat(uh, entry->username, strlen(entry->username));
1725 if (!strchr(entry->username, '@')) {
1726 strncat(uh, "@", 1);
1727 hsock = (SilcSocketConnection)entry->connection;
1728 len = strlen(hsock->hostname);
1729 strncat(uh, hsock->hostname, len);
1732 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1734 2, idp->data, idp->len,
1739 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1740 0, packet->data, packet->len, FALSE);
1742 silc_buffer_free(packet);
1743 silc_buffer_free(idp);
1749 status = (status == SILC_STATUS_LIST_ITEM ?
1750 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1753 SilcServerEntry entry;
1755 if (status == SILC_STATUS_OK && servers_count > 1)
1756 status = SILC_STATUS_LIST_START;
1758 for (i = 0, k = 0; i < servers_count; i++) {
1762 status = SILC_STATUS_LIST_ITEM;
1763 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1764 status = SILC_STATUS_LIST_END;
1765 if (count && k - 1 == count)
1766 status = SILC_STATUS_LIST_END;
1767 if (count && k - 1 > count)
1770 /* Send IDENTIFY reply */
1771 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1772 if (entry->server_name) {
1774 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1776 2, idp->data, idp->len,
1777 3, entry->server_name,
1778 strlen(entry->server_name));
1780 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1782 2, idp->data, idp->len);
1785 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1786 0, packet->data, packet->len, FALSE);
1788 silc_buffer_free(packet);
1789 silc_buffer_free(idp);
1795 status = (status == SILC_STATUS_LIST_ITEM ?
1796 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1799 SilcChannelEntry entry;
1801 if (status == SILC_STATUS_OK && channels_count > 1)
1802 status = SILC_STATUS_LIST_START;
1804 for (i = 0, k = 0; i < channels_count; i++) {
1805 entry = channels[i];
1808 status = SILC_STATUS_LIST_ITEM;
1809 if (channels_count > 1 && k == channels_count - 1)
1810 status = SILC_STATUS_LIST_END;
1811 if (count && k - 1 == count)
1812 status = SILC_STATUS_LIST_END;
1813 if (count && k - 1 > count)
1816 /* Send IDENTIFY reply */
1817 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1818 if (entry->channel_name) {
1820 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1822 2, idp->data, idp->len,
1823 3, entry->channel_name,
1824 strlen(entry->channel_name));
1826 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1828 2, idp->data, idp->len);
1831 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1832 0, packet->data, packet->len, FALSE);
1834 silc_buffer_free(packet);
1835 silc_buffer_free(idp);
1843 silc_server_command_identify_process(SilcServerCommandContext cmd)
1845 SilcServer server = cmd->server;
1848 SilcClientEntry *clients = NULL;
1849 SilcServerEntry *servers = NULL;
1850 SilcChannelEntry *channels = NULL;
1851 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1853 /* Protocol dictates that we must always send the received IDENTIFY request
1854 to our router if we are normal server, so let's do it now unless we
1855 are standalone. We will not send any replies to the client until we
1856 have received reply from the router. */
1857 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1858 server->server_type == SILC_SERVER && !cmd->pending &&
1859 !server->standalone) {
1863 old_ident = silc_command_get_ident(cmd->payload);
1864 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1865 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1867 /* Send IDENTIFY command to our router */
1868 silc_server_packet_send(server, (SilcSocketConnection)
1869 server->router->connection,
1870 SILC_PACKET_COMMAND, cmd->packet->flags,
1871 tmpbuf->data, tmpbuf->len, TRUE);
1873 /* Reprocess this packet after received reply from router */
1874 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1875 silc_command_get_ident(cmd->payload),
1876 silc_server_command_destructor,
1877 silc_server_command_identify,
1878 silc_server_command_dup(cmd));
1879 cmd->pending = TRUE;
1881 silc_command_set_ident(cmd->payload, old_ident);
1883 silc_buffer_free(tmpbuf);
1888 /* We are ready to process the command request. Let's search for the
1889 requested client and send reply to the requesting client. */
1891 /* Parse the IDENTIFY request */
1892 if (!silc_server_command_identify_parse(cmd,
1893 &clients, &clients_count,
1894 &servers, &servers_count,
1895 &channels, &channels_count,
1899 /* Check that all mandatory fields are present and request those data
1900 from the server who owns the client if necessary. */
1901 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1907 /* Send the command reply to the client */
1908 silc_server_command_identify_send_reply(cmd,
1909 clients, clients_count,
1910 servers, servers_count,
1911 channels, channels_count,
1917 silc_free(channels);
1922 SILC_SERVER_CMD_FUNC(identify)
1924 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1927 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1929 ret = silc_server_command_identify_process(cmd);
1932 silc_server_command_free(cmd);
1935 /* Checks string for bad characters and returns TRUE if they are found. */
1937 static int silc_server_command_bad_chars(char *nick)
1941 for (i = 0; i < strlen(nick); i++) {
1942 if (!isalpha(nick[i]))
1944 if (nick[i] == ' ') return TRUE;
1945 if (nick[i] == '\\') return TRUE;
1946 if (nick[i] == '\"') return TRUE;
1947 if (nick[i] == '*') return TRUE;
1948 if (nick[i] == '?') return TRUE;
1949 if (nick[i] == ',') return TRUE;
1950 if (nick[i] == '@') return TRUE;
1956 /* Server side of command NICK. Sets nickname for user. Setting
1957 nickname causes generation of a new client ID for the client. The
1958 new client ID is sent to the client after changing the nickname. */
1960 SILC_SERVER_CMD_FUNC(nick)
1962 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1963 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1964 SilcServer server = cmd->server;
1965 SilcBuffer packet, nidp, oidp;
1966 SilcClientID *new_id;
1968 uint16 ident = silc_command_get_ident(cmd->payload);
1971 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1974 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1976 /* Check nickname */
1977 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1978 if (silc_server_command_bad_chars(nick) == TRUE) {
1979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1980 SILC_STATUS_ERR_BAD_NICKNAME);
1984 if (strlen(nick) > 128)
1987 /* Create new Client ID */
1988 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1990 cmd->server->md5hash, nick,
1993 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
1996 /* Send notify about nickname change to our router. We send the new
1997 ID and ask to replace it with the old one. If we are router the
1998 packet is broadcasted. Send NICK_CHANGE notify. */
1999 if (!server->standalone)
2000 silc_server_send_notify_nick_change(server, server->router->connection,
2001 server->server_type == SILC_SERVER ?
2002 FALSE : TRUE, client->id,
2005 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2007 /* Remove old cache entry */
2008 silc_idcache_del_by_context(server->local_list->clients, client);
2011 silc_free(client->id);
2013 /* Save the nickname as this client is our local client */
2014 silc_free(client->nickname);
2016 client->nickname = strdup(nick);
2017 client->id = new_id;
2019 /* Update client cache */
2020 silc_idcache_add(server->local_list->clients, client->nickname,
2021 client->id, (void *)client, FALSE);
2023 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2025 /* Send NICK_CHANGE notify to the client's channels */
2026 silc_server_send_notify_on_channels(server, NULL, client,
2027 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2028 oidp->data, oidp->len,
2029 nidp->data, nidp->len);
2031 /* Send the new Client ID as reply command back to client */
2032 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2033 SILC_STATUS_OK, ident, 1,
2034 2, nidp->data, nidp->len);
2035 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2036 0, packet->data, packet->len, FALSE);
2038 silc_buffer_free(packet);
2039 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 (i == lch_count - 1 && gch_count)
2087 if (lch_count > 1 && i == lch_count - 1)
2088 status = SILC_STATUS_LIST_END;
2090 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2092 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2093 topic = "*private*";
2094 memset(usercount, 0, sizeof(usercount));
2096 topic = entry->topic;
2097 users = silc_hash_table_count(entry->user_list);
2098 SILC_PUT32_MSB(users, usercount);
2101 /* Send the reply */
2104 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2106 2, idp->data, idp->len,
2107 3, entry->channel_name,
2108 strlen(entry->channel_name),
2109 4, topic, strlen(topic),
2113 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2115 2, idp->data, idp->len,
2116 3, entry->channel_name,
2117 strlen(entry->channel_name),
2119 silc_server_packet_send(cmd->server, cmd->sock,
2120 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2121 packet->len, FALSE);
2122 silc_buffer_free(packet);
2123 silc_buffer_free(idp);
2126 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
2129 for (i = 0; i < gch_count; i++) {
2136 status = SILC_STATUS_LIST_ITEM;
2138 if (gch_count > 1 && i == lch_count - 1)
2139 status = SILC_STATUS_LIST_END;
2141 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2143 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2144 topic = "*private*";
2145 memset(usercount, 0, sizeof(usercount));
2147 topic = entry->topic;
2148 users = silc_hash_table_count(entry->user_list);
2149 SILC_PUT32_MSB(users, usercount);
2152 /* Send the reply */
2155 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2157 2, idp->data, idp->len,
2158 3, entry->channel_name,
2159 strlen(entry->channel_name),
2160 4, topic, strlen(topic),
2164 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2166 2, idp->data, idp->len,
2167 3, entry->channel_name,
2168 strlen(entry->channel_name),
2170 silc_server_packet_send(cmd->server, cmd->sock,
2171 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2172 packet->len, FALSE);
2173 silc_buffer_free(packet);
2174 silc_buffer_free(idp);
2178 /* Server side of LIST command. This lists the channel of the requested
2179 server. Secret channels are not listed. */
2181 SILC_SERVER_CMD_FUNC(list)
2183 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2184 SilcServer server = cmd->server;
2185 SilcChannelID *channel_id = NULL;
2188 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2189 uint32 lch_count = 0, gch_count = 0;
2191 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 2);
2193 /* Get Channel ID */
2194 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2196 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2199 SILC_STATUS_ERR_NO_CHANNEL_ID);
2204 /* Get the channels from local list */
2205 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2208 /* Get the channels from global list if we are router */
2209 if (server->server_type == SILC_ROUTER)
2210 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2213 /* Send the reply */
2214 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2215 gchannels, gch_count);
2218 silc_server_command_free(cmd);
2221 /* Server side of TOPIC command. Sets topic for channel and/or returns
2222 current topic to client. */
2224 SILC_SERVER_CMD_FUNC(topic)
2226 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2227 SilcServer server = cmd->server;
2228 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2229 SilcChannelID *channel_id;
2230 SilcChannelEntry channel;
2231 SilcChannelClientEntry chl;
2232 SilcBuffer packet, idp;
2234 uint32 argc, tmp_len;
2235 uint16 ident = silc_command_get_ident(cmd->payload);
2237 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2239 argc = silc_argument_get_arg_num(cmd->args);
2241 /* Get Channel ID */
2242 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2245 SILC_STATUS_ERR_NO_CHANNEL_ID);
2248 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2251 SILC_STATUS_ERR_NO_CHANNEL_ID);
2255 /* Check whether the channel exists */
2256 channel = silc_idlist_find_channel_by_id(server->local_list,
2259 channel = silc_idlist_find_channel_by_id(server->global_list,
2262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2263 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2270 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2273 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2277 if (strlen(tmp) > 256) {
2278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2279 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2283 /* See whether the client is on channel and has rights to change topic */
2284 if (!silc_hash_table_find(channel->user_list, client, NULL,
2286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2287 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2291 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2292 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2294 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2299 /* Set the topic for channel */
2301 silc_free(channel->topic);
2302 channel->topic = strdup(tmp);
2304 /* Send TOPIC_SET notify type to the network */
2305 if (!server->standalone)
2306 silc_server_send_notify_topic_set(server, server->router->connection,
2307 server->server_type == SILC_ROUTER ?
2308 TRUE : FALSE, channel, client->id,
2311 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2313 /* Send notify about topic change to all clients on the channel */
2314 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2315 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2316 idp->data, idp->len,
2317 channel->topic, strlen(channel->topic));
2318 silc_buffer_free(idp);
2321 /* Send the topic to client as reply packet */
2322 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2324 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2325 SILC_STATUS_OK, ident, 2,
2326 2, idp->data, idp->len,
2328 strlen(channel->topic));
2330 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2331 SILC_STATUS_OK, ident, 1,
2332 2, idp->data, idp->len);
2333 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2334 0, packet->data, packet->len, FALSE);
2336 silc_buffer_free(packet);
2337 silc_buffer_free(idp);
2338 silc_free(channel_id);
2341 silc_server_command_free(cmd);
2344 /* Server side of INVITE command. Invites some client to join some channel.
2345 This command is also used to manage the invite list of the channel. */
2347 SILC_SERVER_CMD_FUNC(invite)
2349 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2350 SilcServer server = cmd->server;
2351 SilcSocketConnection sock = cmd->sock, dest_sock;
2352 SilcChannelClientEntry chl;
2353 SilcClientEntry sender, dest;
2354 SilcClientID *dest_id = NULL;
2355 SilcChannelEntry channel;
2356 SilcChannelID *channel_id = NULL;
2357 SilcIDListData idata;
2358 SilcBuffer idp, idp2, packet;
2359 unsigned char *tmp, *add, *del;
2361 uint16 ident = silc_command_get_ident(cmd->payload);
2363 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2365 /* Get Channel ID */
2366 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2369 SILC_STATUS_ERR_NO_CHANNEL_ID);
2372 channel_id = silc_id_payload_parse_id(tmp, len);
2374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2375 SILC_STATUS_ERR_NO_CHANNEL_ID);
2379 /* Get the channel entry */
2380 channel = silc_idlist_find_channel_by_id(server->local_list,
2383 channel = silc_idlist_find_channel_by_id(server->global_list,
2386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2387 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2392 /* Check whether the sender of this command is on the channel. */
2393 sender = (SilcClientEntry)sock->user_data;
2394 if (!silc_server_client_on_channel(sender, channel)) {
2395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2396 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2400 /* Check whether the channel is invite-only channel. If yes then the
2401 sender of this command must be at least channel operator. */
2402 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2403 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2404 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2411 /* Get destination client ID */
2412 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2416 dest_id = silc_id_payload_parse_id(tmp, len);
2418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2419 SILC_STATUS_ERR_NO_CLIENT_ID);
2423 /* Get the client entry */
2424 dest = silc_server_get_client_resolve(server, dest_id);
2426 if (server->server_type == SILC_ROUTER) {
2427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2428 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2432 /* The client info is being resolved. Reprocess this packet after
2433 receiving the reply to the query. */
2434 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2436 silc_server_command_destructor,
2437 silc_server_command_invite,
2438 silc_server_command_dup(cmd));
2439 cmd->pending = TRUE;
2440 silc_free(channel_id);
2445 /* Check whether the requested client is already on the channel. */
2446 if (silc_server_client_on_channel(dest, channel)) {
2447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2448 SILC_STATUS_ERR_USER_ON_CHANNEL);
2452 /* Get route to the client */
2453 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2456 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2460 memset(invite, 0, sizeof(invite));
2461 strncat(invite, dest->nickname, strlen(dest->nickname));
2462 strncat(invite, "!", 1);
2463 strncat(invite, dest->username, strlen(dest->username));
2464 if (!strchr(dest->username, '@')) {
2465 strncat(invite, "@", 1);
2466 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2469 len = strlen(invite);
2470 if (!channel->invite_list)
2471 channel->invite_list = silc_calloc(len + 2,
2472 sizeof(*channel->invite_list));
2474 channel->invite_list = silc_realloc(channel->invite_list,
2475 sizeof(*channel->invite_list) *
2477 strlen(channel->invite_list) + 2));
2478 strncat(channel->invite_list, invite, len);
2479 strncat(channel->invite_list, ",", 1);
2481 /* Send notify to the client that is invited to the channel */
2482 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2483 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2484 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2486 SILC_NOTIFY_TYPE_INVITE, 3,
2487 idp->data, idp->len,
2488 channel->channel_name,
2489 strlen(channel->channel_name),
2490 idp2->data, idp2->len);
2491 silc_buffer_free(idp);
2492 silc_buffer_free(idp2);
2495 /* Add the client to the invite list of the channel */
2496 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2498 if (!channel->invite_list)
2499 channel->invite_list = silc_calloc(len + 2,
2500 sizeof(*channel->invite_list));
2502 channel->invite_list = silc_realloc(channel->invite_list,
2503 sizeof(*channel->invite_list) *
2505 strlen(channel->invite_list) + 2));
2506 if (add[len - 1] == ',')
2507 add[len - 1] = '\0';
2509 strncat(channel->invite_list, add, len);
2510 strncat(channel->invite_list, ",", 1);
2513 /* Get the invite to be removed and remove it from the list */
2514 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2515 if (del && channel->invite_list) {
2516 char *start, *end, *n;
2518 if (!strncmp(channel->invite_list, del,
2519 strlen(channel->invite_list) - 1)) {
2520 silc_free(channel->invite_list);
2521 channel->invite_list = NULL;
2523 start = strstr(channel->invite_list, del);
2524 if (start && strlen(start) >= len) {
2526 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2527 strncat(n, channel->invite_list, start - channel->invite_list);
2528 strncat(n, end + 1, ((channel->invite_list +
2529 strlen(channel->invite_list)) - end) - 1);
2530 silc_free(channel->invite_list);
2531 channel->invite_list = n;
2536 /* Send notify to the primary router */
2537 if (!server->standalone)
2538 silc_server_send_notify_invite(server, server->router->connection,
2539 server->server_type == SILC_ROUTER ?
2540 TRUE : FALSE, channel,
2541 sender->id, add, del);
2543 /* Send command reply */
2544 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2548 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2549 SILC_STATUS_OK, ident, 2,
2551 3, channel->invite_list,
2552 channel->invite_list ?
2553 strlen(channel->invite_list) : 0);
2556 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2557 SILC_STATUS_OK, ident, 1,
2559 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2560 packet->data, packet->len, FALSE);
2561 silc_buffer_free(packet);
2567 silc_free(channel_id);
2568 silc_server_command_free(cmd);
2573 SilcSocketConnection sock;
2577 /* Quits connection to client. This gets called if client won't
2578 close the connection even when it has issued QUIT command. */
2580 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2582 QuitInternal q = (QuitInternal)context;
2584 /* Free all client specific data, such as client entry and entires
2585 on channels this client may be on. */
2586 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2588 q->sock->user_data = NULL;
2590 /* Close the connection on our side */
2591 silc_server_close_connection(q->server, q->sock);
2593 silc_free(q->signoff);
2597 /* Quits SILC session. This is the normal way to disconnect client. */
2599 SILC_SERVER_CMD_FUNC(quit)
2601 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2602 SilcServer server = cmd->server;
2603 SilcSocketConnection sock = cmd->sock;
2605 unsigned char *tmp = NULL;
2608 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2610 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2613 /* Get destination ID */
2614 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2618 q = silc_calloc(1, sizeof(*q));
2621 q->signoff = tmp ? strdup(tmp) : NULL;
2623 /* We quit the connection with little timeout */
2624 silc_schedule_task_add(server->schedule, sock->sock,
2625 silc_server_command_quit_cb, (void *)q,
2626 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2629 silc_server_command_free(cmd);
2632 /* Server side of command KILL. This command is used by router operator
2633 to remove an client from the SILC Network temporarily. */
2635 SILC_SERVER_CMD_FUNC(kill)
2637 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2638 SilcServer server = cmd->server;
2639 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2640 SilcClientEntry remote_client;
2641 SilcClientID *client_id;
2642 unsigned char *tmp, *comment;
2643 uint32 tmp_len, tmp_len2;
2645 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2647 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2650 /* KILL command works only on router */
2651 if (server->server_type != SILC_ROUTER) {
2652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2653 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2657 /* Check whether client has the permissions. */
2658 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2660 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2664 /* Get the client ID */
2665 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2668 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2671 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2674 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2678 /* Get the client entry */
2679 remote_client = silc_idlist_find_client_by_id(server->local_list,
2680 client_id, TRUE, NULL);
2681 if (!remote_client) {
2682 remote_client = silc_idlist_find_client_by_id(server->global_list,
2683 client_id, TRUE, NULL);
2684 if (!remote_client) {
2685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2686 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2692 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2696 /* Send reply to the sender */
2697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2700 /* Send the KILL notify packets. First send it to the channel, then
2701 to our primary router and then directly to the client who is being
2702 killed right now. */
2704 /* Send KILLED notify to the channels. It is not sent to the client
2705 as it will be sent differently destined directly to the client and not
2707 silc_server_send_notify_on_channels(server, remote_client,
2708 remote_client, SILC_NOTIFY_TYPE_KILLED,
2711 comment, comment ? tmp_len2 : 0);
2713 /* Send KILLED notify to primary route */
2714 if (!server->standalone)
2715 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2716 remote_client->id, comment);
2718 /* Send KILLED notify to the client directly */
2719 silc_server_send_notify_killed(server, remote_client->connection ?
2720 remote_client->connection :
2721 remote_client->router->connection, FALSE,
2722 remote_client->id, comment);
2724 /* Remove the client from all channels. This generates new keys to the
2725 channels as well. */
2726 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2729 /* Remove the client entry, If it is locally connected then we will also
2730 disconnect the client here */
2731 if (remote_client->connection) {
2732 /* Remove locally conneted client */
2733 SilcSocketConnection sock = remote_client->connection;
2734 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2735 silc_server_close_connection(server, sock);
2737 /* Remove remote client */
2738 if (!silc_idlist_del_client(server->global_list, remote_client))
2739 silc_idlist_del_client(server->local_list, remote_client);
2743 silc_server_command_free(cmd);
2746 /* Server side of command INFO. This sends information about us to
2747 the client. If client requested specific server we will send the
2748 command to that server. */
2750 SILC_SERVER_CMD_FUNC(info)
2752 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2753 SilcServer server = cmd->server;
2754 SilcBuffer packet, idp;
2757 char *dest_server, *server_info = NULL, *server_name;
2758 uint16 ident = silc_command_get_ident(cmd->payload);
2759 SilcServerEntry entry = NULL;
2760 SilcServerID *server_id = NULL;
2762 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2764 /* Get server name */
2765 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2768 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2770 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2773 SILC_STATUS_ERR_NO_SERVER_ID);
2779 /* Check whether we have this server cached */
2780 entry = silc_idlist_find_server_by_id(server->local_list,
2781 server_id, TRUE, NULL);
2783 entry = silc_idlist_find_server_by_id(server->global_list,
2784 server_id, TRUE, NULL);
2785 if (!entry && server->server_type == SILC_ROUTER) {
2786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2787 SILC_STATUS_ERR_NO_SUCH_SERVER);
2793 /* Some buggy servers has sent request to router about themselves. */
2794 if (server->server_type == SILC_ROUTER && cmd->sock->user_data == entry)
2797 if ((!dest_server && !server_id && !entry) || (entry &&
2798 entry == server->id_entry) ||
2799 (dest_server && !cmd->pending &&
2800 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2801 /* Send our reply */
2802 char info_string[256];
2804 memset(info_string, 0, sizeof(info_string));
2805 snprintf(info_string, sizeof(info_string),
2806 "location: %s server: %s admin: %s <%s>",
2807 server->config->admin_info->location,
2808 server->config->admin_info->server_type,
2809 server->config->admin_info->admin_name,
2810 server->config->admin_info->admin_email);
2812 server_info = info_string;
2813 entry = server->id_entry;
2815 /* Check whether we have this server cached */
2816 if (!entry && dest_server) {
2817 entry = silc_idlist_find_server_by_name(server->global_list,
2818 dest_server, TRUE, NULL);
2820 entry = silc_idlist_find_server_by_name(server->local_list,
2821 dest_server, TRUE, NULL);
2825 if (!cmd->pending &&
2826 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2827 /* Send to the server */
2831 old_ident = silc_command_get_ident(cmd->payload);
2832 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2833 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2835 silc_server_packet_send(server, entry->connection,
2836 SILC_PACKET_COMMAND, cmd->packet->flags,
2837 tmpbuf->data, tmpbuf->len, TRUE);
2839 /* Reprocess this packet after received reply from router */
2840 silc_server_command_pending(server, SILC_COMMAND_INFO,
2841 silc_command_get_ident(cmd->payload),
2842 silc_server_command_destructor,
2843 silc_server_command_info,
2844 silc_server_command_dup(cmd));
2845 cmd->pending = TRUE;
2846 silc_command_set_ident(cmd->payload, old_ident);
2847 silc_buffer_free(tmpbuf);
2851 if (!entry && !cmd->pending && !server->standalone) {
2852 /* Send to the primary router */
2856 old_ident = silc_command_get_ident(cmd->payload);
2857 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2858 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2860 silc_server_packet_send(server, server->router->connection,
2861 SILC_PACKET_COMMAND, cmd->packet->flags,
2862 tmpbuf->data, tmpbuf->len, TRUE);
2864 /* Reprocess this packet after received reply from router */
2865 silc_server_command_pending(server, SILC_COMMAND_INFO,
2866 silc_command_get_ident(cmd->payload),
2867 silc_server_command_destructor,
2868 silc_server_command_info,
2869 silc_server_command_dup(cmd));
2870 cmd->pending = TRUE;
2871 silc_command_set_ident(cmd->payload, old_ident);
2872 silc_buffer_free(tmpbuf);
2878 silc_free(server_id);
2881 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2882 SILC_STATUS_ERR_NO_SUCH_SERVER);
2886 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2888 server_info = entry->server_info;
2889 server_name = entry->server_name;
2891 /* Send the reply */
2893 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2894 SILC_STATUS_OK, ident, 3,
2895 2, idp->data, idp->len,
2897 strlen(server_name),
2899 strlen(server_info));
2901 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2902 SILC_STATUS_OK, ident, 2,
2903 2, idp->data, idp->len,
2905 strlen(server_name));
2906 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2907 packet->data, packet->len, FALSE);
2909 silc_buffer_free(packet);
2910 silc_buffer_free(idp);
2913 silc_server_command_free(cmd);
2916 /* Server side of command PING. This just replies to the ping. */
2918 SILC_SERVER_CMD_FUNC(ping)
2920 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2921 SilcServer server = cmd->server;
2926 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2929 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2932 SILC_STATUS_ERR_NO_SERVER_ID);
2935 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2939 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2940 /* Send our reply */
2941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2945 SILC_STATUS_ERR_NO_SUCH_SERVER);
2952 silc_server_command_free(cmd);
2955 /* Internal routine to join channel. The channel sent to this function
2956 has been either created or resolved from ID lists. This joins the sent
2957 client to the channel. */
2959 static void silc_server_command_join_channel(SilcServer server,
2960 SilcServerCommandContext cmd,
2961 SilcChannelEntry channel,
2962 SilcClientID *client_id,
2966 SilcSocketConnection sock = cmd->sock;
2968 uint32 tmp_len, user_count;
2969 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2970 SilcClientEntry client;
2971 SilcChannelClientEntry chl;
2972 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2973 uint16 ident = silc_command_get_ident(cmd->payload);
2974 char check[512], check2[512];
2976 SILC_LOG_DEBUG(("Start"));
2981 /* Get the client entry */
2982 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2983 client = (SilcClientEntry)sock->user_data;
2985 client = silc_server_get_client_resolve(server, client_id);
2990 /* The client info is being resolved. Reprocess this packet after
2991 receiving the reply to the query. */
2992 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2993 server->cmd_ident, NULL,
2994 silc_server_command_join,
2995 silc_server_command_dup(cmd));
2996 cmd->pending = TRUE;
3000 cmd->pending = FALSE;
3004 * Check channel modes
3007 memset(check, 0, sizeof(check));
3008 memset(check2, 0, sizeof(check2));
3009 strncat(check, client->nickname, strlen(client->nickname));
3010 strncat(check, "!", 1);
3011 strncat(check, client->username, strlen(client->username));
3012 if (!strchr(client->username, '@')) {
3013 strncat(check, "@", 1);
3014 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3017 strncat(check2, client->nickname, strlen(client->nickname));
3018 if (!strchr(client->nickname, '@')) {
3019 strncat(check2, "@", 1);
3020 strncat(check2, server->server_name, strlen(server->server_name));
3022 strncat(check2, "!", 1);
3023 strncat(check2, client->username, strlen(client->username));
3024 if (!strchr(client->username, '@')) {
3025 strncat(check2, "@", 1);
3026 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3029 /* Check invite list if channel is invite-only channel */
3030 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3031 if (!channel->invite_list ||
3032 (!silc_string_match(channel->invite_list, check) &&
3033 !silc_string_match(channel->invite_list, check2))) {
3034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3035 SILC_STATUS_ERR_NOT_INVITED);
3040 /* Check ban list if it exists. If the client's nickname, server,
3041 username and/or hostname is in the ban list the access to the
3042 channel is denied. */
3043 if (channel->ban_list) {
3044 if (silc_string_match(channel->ban_list, check) ||
3045 silc_string_match(channel->ban_list, check2)) {
3046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3047 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3052 /* Get passphrase */
3053 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3055 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3056 memcpy(passphrase, tmp, tmp_len);
3059 /* Check the channel passphrase if set. */
3060 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3061 if (!passphrase || memcmp(channel->passphrase, passphrase,
3062 strlen(channel->passphrase))) {
3063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3064 SILC_STATUS_ERR_BAD_PASSWORD);
3069 /* Check user count limit if set. */
3070 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3071 if (silc_hash_table_count(channel->user_list) + 1 >
3072 channel->user_limit) {
3073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3074 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3080 * Client is allowed to join to the channel. Make it happen.
3083 /* Check whether the client already is on the channel */
3084 if (silc_server_client_on_channel(client, channel)) {
3085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3086 SILC_STATUS_ERR_USER_ON_CHANNEL);
3090 /* Generate new channel key as protocol dictates */
3091 if ((!created && silc_hash_table_count(channel->user_list) > 0) ||
3092 !channel->channel_key)
3093 if (!silc_server_create_channel_key(server, channel, 0))
3096 /* Send the channel key. This is broadcasted to the channel but is not
3097 sent to the client who is joining to the channel. */
3098 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3099 silc_server_send_channel_key(server, NULL, channel,
3100 server->server_type == SILC_ROUTER ?
3101 FALSE : !server->standalone);
3103 /* Join the client to the channel by adding it to channel's user list.
3104 Add also the channel to client entry's channels list for fast cross-
3106 chl = silc_calloc(1, sizeof(*chl));
3108 chl->client = client;
3109 chl->channel = channel;
3110 silc_hash_table_add(channel->user_list, client, chl);
3111 silc_hash_table_add(client->channels, channel, chl);
3113 /* Get users on the channel */
3114 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3117 /* Encode Client ID Payload of the original client who wants to join */
3118 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3120 /* Encode command reply packet */
3121 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3122 SILC_PUT32_MSB(channel->mode, mode);
3123 SILC_PUT32_MSB(created, tmp2);
3124 SILC_PUT32_MSB(user_count, tmp3);
3126 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3127 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3128 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3129 strlen(channel->channel_key->
3131 channel->channel_key->cipher->name,
3132 channel->key_len / 8, channel->key);
3137 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3138 SILC_STATUS_OK, ident, 13,
3139 2, channel->channel_name,
3140 strlen(channel->channel_name),
3141 3, chidp->data, chidp->len,
3142 4, clidp->data, clidp->len,
3145 7, keyp ? keyp->data : NULL,
3146 keyp ? keyp->len : 0,
3147 8, channel->ban_list,
3149 strlen(channel->ban_list) : 0,
3150 9, channel->invite_list,
3151 channel->invite_list ?
3152 strlen(channel->invite_list) : 0,
3155 strlen(channel->topic) : 0,
3156 11, channel->hmac->hmac->name,
3157 strlen(channel->hmac->hmac->name),
3159 13, user_list->data, user_list->len,
3160 14, mode_list->data,
3163 /* Send command reply */
3164 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3165 reply->data, reply->len, FALSE);
3167 if (!cmd->pending) {
3168 /* Send JOIN notify to locally connected clients on the channel */
3169 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3170 SILC_NOTIFY_TYPE_JOIN, 2,
3171 clidp->data, clidp->len,
3172 chidp->data, chidp->len);
3174 /* Send JOIN notify packet to our primary router */
3175 if (!server->standalone)
3176 silc_server_send_notify_join(server, server->router->connection,
3177 server->server_type == SILC_ROUTER ?
3178 TRUE : FALSE, channel, client->id);
3181 silc_buffer_free(reply);
3182 silc_buffer_free(clidp);
3183 silc_buffer_free(chidp);
3184 silc_buffer_free(keyp);
3185 silc_buffer_free(user_list);
3186 silc_buffer_free(mode_list);
3190 silc_free(passphrase);
3193 /* Server side of command JOIN. Joins client into requested channel. If
3194 the channel does not exist it will be created. */
3196 SILC_SERVER_CMD_FUNC(join)
3198 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3199 SilcServer server = cmd->server;
3201 char *tmp, *channel_name = NULL, *cipher, *hmac;
3202 SilcChannelEntry channel;
3204 int created = FALSE;
3205 SilcClientID *client_id;
3207 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3209 /* Get channel name */
3210 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3213 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3218 if (strlen(channel_name) > 256)
3219 channel_name[255] = '\0';
3221 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3223 SILC_STATUS_ERR_BAD_CHANNEL);
3227 /* Get Client ID of the client who is joining to the channel */
3228 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3231 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3234 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3237 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3241 /* Get cipher and hmac name */
3242 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3243 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3245 /* See if the channel exists */
3246 channel = silc_idlist_find_channel_by_name(server->local_list,
3247 channel_name, NULL);
3249 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3250 /* If this is coming from client the Client ID in the command packet must
3251 be same as the client's ID. */
3252 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3253 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3254 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3256 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3261 if (!channel || !channel->id) {
3262 /* Channel not found */
3264 /* If we are standalone server we don't have a router, we just create
3265 the channel by ourselves. */
3266 if (server->standalone) {
3267 channel = silc_server_create_new_channel(server, server->id, cipher,
3268 hmac, channel_name, TRUE);
3270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3271 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3275 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3280 /* The channel does not exist on our server. If we are normal server
3281 we will send JOIN command to our router which will handle the
3282 joining procedure (either creates the channel if it doesn't exist
3283 or joins the client to it). */
3284 if (server->server_type == SILC_SERVER) {
3288 /* If this is pending command callback then we've resolved
3289 it and it didn't work, return since we've notified the
3290 client already in the command reply callback. */
3294 old_ident = silc_command_get_ident(cmd->payload);
3295 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3296 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3298 /* Send JOIN command to our router */
3299 silc_server_packet_send(server, (SilcSocketConnection)
3300 server->router->connection,
3301 SILC_PACKET_COMMAND, cmd->packet->flags,
3302 tmpbuf->data, tmpbuf->len, TRUE);
3304 /* Reprocess this packet after received reply from router */
3305 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3306 silc_command_get_ident(cmd->payload),
3307 silc_server_command_destructor,
3308 silc_server_command_join,
3309 silc_server_command_dup(cmd));
3310 cmd->pending = TRUE;
3314 /* We are router and the channel does not seem exist so we will check
3315 our global list as well for the channel. */
3316 channel = silc_idlist_find_channel_by_name(server->global_list,
3317 channel_name, NULL);
3319 /* Channel really does not exist, create it */
3320 channel = silc_server_create_new_channel(server, server->id, cipher,
3321 hmac, channel_name, TRUE);
3323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3324 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3328 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3335 /* Channel not found */
3337 /* If the command came from router and/or we are normal server then
3338 something went wrong with the joining as the channel was not found.
3339 We can't do anything else but ignore this. */
3340 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3341 server->server_type == SILC_SERVER)
3344 /* We are router and the channel does not seem exist so we will check
3345 our global list as well for the channel. */
3346 channel = silc_idlist_find_channel_by_name(server->global_list,
3347 channel_name, NULL);
3349 /* Channel really does not exist, create it */
3350 channel = silc_server_create_new_channel(server, server->id, cipher,
3351 hmac, channel_name, TRUE);
3353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3354 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3358 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3364 /* If the channel does not have global users and is also empty it means the
3365 channel was created globally (by our router) and the client will be the
3366 channel founder and operator. */
3367 if (!channel->global_users && !silc_hash_table_count(channel->user_list)) {
3368 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3369 created = TRUE; /* Created globally by our router */
3372 /* Join to the channel */
3373 silc_server_command_join_channel(server, cmd, channel, client_id,
3376 silc_free(client_id);
3379 silc_server_command_free(cmd);
3382 /* Server side of command MOTD. Sends server's current "message of the
3383 day" to the client. */
3385 SILC_SERVER_CMD_FUNC(motd)
3387 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3388 SilcServer server = cmd->server;
3389 SilcBuffer packet, idp;
3390 char *motd, *dest_server;
3392 uint16 ident = silc_command_get_ident(cmd->payload);
3394 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3396 /* Get server name */
3397 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3400 SILC_STATUS_ERR_NO_SUCH_SERVER);
3404 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3407 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3409 if (server->config && server->config->motd &&
3410 server->config->motd->motd_file) {
3412 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3417 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3418 SILC_STATUS_OK, ident, 2,
3424 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3425 SILC_STATUS_OK, ident, 1,
3429 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3430 packet->data, packet->len, FALSE);
3431 silc_buffer_free(packet);
3432 silc_buffer_free(idp);
3434 SilcServerEntry entry;
3436 /* Check whether we have this server cached */
3437 entry = silc_idlist_find_server_by_name(server->global_list,
3438 dest_server, TRUE, NULL);
3440 entry = silc_idlist_find_server_by_name(server->local_list,
3441 dest_server, TRUE, NULL);
3444 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3445 entry && !entry->motd) {
3446 /* Send to the server */
3450 old_ident = silc_command_get_ident(cmd->payload);
3451 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3452 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3454 silc_server_packet_send(server, entry->connection,
3455 SILC_PACKET_COMMAND, cmd->packet->flags,
3456 tmpbuf->data, tmpbuf->len, TRUE);
3458 /* Reprocess this packet after received reply from router */
3459 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3460 silc_command_get_ident(cmd->payload),
3461 silc_server_command_destructor,
3462 silc_server_command_motd,
3463 silc_server_command_dup(cmd));
3464 cmd->pending = TRUE;
3465 silc_command_set_ident(cmd->payload, old_ident);
3466 silc_buffer_free(tmpbuf);
3470 if (!entry && !cmd->pending && !server->standalone) {
3471 /* Send to the primary router */
3475 old_ident = silc_command_get_ident(cmd->payload);
3476 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3477 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3479 silc_server_packet_send(server, server->router->connection,
3480 SILC_PACKET_COMMAND, cmd->packet->flags,
3481 tmpbuf->data, tmpbuf->len, TRUE);
3483 /* Reprocess this packet after received reply from router */
3484 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3485 silc_command_get_ident(cmd->payload),
3486 silc_server_command_destructor,
3487 silc_server_command_motd,
3488 silc_server_command_dup(cmd));
3489 cmd->pending = TRUE;
3490 silc_command_set_ident(cmd->payload, old_ident);
3491 silc_buffer_free(tmpbuf);
3496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3497 SILC_STATUS_ERR_NO_SUCH_SERVER);
3501 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3504 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3505 SILC_STATUS_OK, ident, 2,
3508 strlen(entry->motd));
3510 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3511 SILC_STATUS_OK, ident, 1,
3514 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3515 packet->data, packet->len, FALSE);
3516 silc_buffer_free(packet);
3517 silc_buffer_free(idp);
3521 silc_server_command_free(cmd);
3524 /* Server side of command UMODE. Client can use this command to set/unset
3525 user mode. Client actually cannot set itself to be as server/router
3526 operator so this can be used only to unset the modes. */
3528 SILC_SERVER_CMD_FUNC(umode)
3530 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3531 SilcServer server = cmd->server;
3532 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3534 unsigned char *tmp_mask;
3536 uint16 ident = silc_command_get_ident(cmd->payload);
3538 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3541 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3543 /* Get the client's mode mask */
3544 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3547 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3550 SILC_GET32_MSB(mask, tmp_mask);
3556 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3557 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3558 /* Cannot operator mode */
3559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3560 SILC_STATUS_ERR_PERM_DENIED);
3564 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3565 /* Remove the server operator rights */
3566 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3569 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3570 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3571 /* Cannot operator mode */
3572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3573 SILC_STATUS_ERR_PERM_DENIED);
3577 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3578 /* Remove the router operator rights */
3579 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3582 if (mask & SILC_UMODE_GONE) {
3583 client->mode |= SILC_UMODE_GONE;
3585 if (client->mode & SILC_UMODE_GONE)
3586 /* Remove the gone status */
3587 client->mode &= ~SILC_UMODE_GONE;
3590 /* Send UMODE change to primary router */
3591 if (!server->standalone)
3592 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3593 client->id, client->mode);
3595 /* Send command reply to sender */
3596 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3597 SILC_STATUS_OK, ident, 1,
3599 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3600 packet->data, packet->len, FALSE);
3601 silc_buffer_free(packet);
3604 silc_server_command_free(cmd);
3607 /* Checks that client has rights to add or remove channel modes. If any
3608 of the checks fails FALSE is returned. */
3610 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3611 SilcChannelClientEntry client,
3614 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3615 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3617 /* Check whether has rights to change anything */
3618 if (!is_op && !is_fo)
3621 /* Check whether has rights to change everything */
3625 /* We know that client is channel operator, check that they are not
3626 changing anything that requires channel founder rights. Rest of the
3627 modes are available automatically for channel operator. */
3629 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3630 if (is_op && !is_fo)
3633 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3634 if (is_op && !is_fo)
3639 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3640 if (is_op && !is_fo)
3643 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3644 if (is_op && !is_fo)
3649 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3650 if (is_op && !is_fo)
3653 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3654 if (is_op && !is_fo)
3659 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3660 if (is_op && !is_fo)
3663 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3664 if (is_op && !is_fo)
3672 /* Server side command of CMODE. Changes channel mode */
3674 SILC_SERVER_CMD_FUNC(cmode)
3676 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3677 SilcServer server = cmd->server;
3678 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3679 SilcIDListData idata = (SilcIDListData)client;
3680 SilcChannelID *channel_id;
3681 SilcChannelEntry channel;
3682 SilcChannelClientEntry chl;
3683 SilcBuffer packet, cidp;
3684 unsigned char *tmp, *tmp_id, *tmp_mask;
3685 char *cipher = NULL, *hmac = NULL;
3686 uint32 mode_mask, tmp_len, tmp_len2;
3687 uint16 ident = silc_command_get_ident(cmd->payload);
3689 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3691 /* Get Channel ID */
3692 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3695 SILC_STATUS_ERR_NO_CHANNEL_ID);
3698 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3701 SILC_STATUS_ERR_NO_CHANNEL_ID);
3705 /* Get the channel mode mask */
3706 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3709 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3712 SILC_GET32_MSB(mode_mask, tmp_mask);
3714 /* Get channel entry */
3715 channel = silc_idlist_find_channel_by_id(server->local_list,
3718 channel = silc_idlist_find_channel_by_id(server->global_list,
3721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3722 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3727 /* Check whether this client is on the channel */
3728 if (!silc_server_client_on_channel(client, channel)) {
3729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3730 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3734 /* Get entry to the channel user list */
3735 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3737 /* Check that client has rights to change any requested channel modes */
3738 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3739 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3740 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3745 * Check the modes. Modes that requires nothing special operation are
3749 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3750 /* Channel uses private keys to protect traffic. Client(s) has set the
3751 key locally they want to use, server does not know that key. */
3752 /* Nothing interesting to do here */
3754 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3755 /* The mode is removed and we need to generate and distribute
3756 new channel key. Clients are not using private channel keys
3757 anymore after this. */
3759 /* Re-generate channel key */
3760 if (!silc_server_create_channel_key(server, channel, 0))
3763 /* Send the channel key. This sends it to our local clients and if
3764 we are normal server to our router as well. */
3765 silc_server_send_channel_key(server, NULL, channel,
3766 server->server_type == SILC_ROUTER ?
3767 FALSE : !server->standalone);
3769 cipher = channel->channel_key->cipher->name;
3770 hmac = channel->hmac->hmac->name;
3774 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3775 /* User limit is set on channel */
3778 /* Get user limit */
3779 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3781 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3783 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3787 SILC_GET32_MSB(user_limit, tmp);
3788 channel->user_limit = user_limit;
3791 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3792 /* User limit mode is unset. Remove user limit */
3793 channel->user_limit = 0;
3796 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3797 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3798 /* Passphrase has been set to channel */
3800 /* Get the passphrase */
3801 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3804 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3808 /* Save the passphrase */
3809 channel->passphrase = strdup(tmp);
3812 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3813 /* Passphrase mode is unset. remove the passphrase */
3814 if (channel->passphrase) {
3815 silc_free(channel->passphrase);
3816 channel->passphrase = NULL;
3821 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3822 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3823 /* Cipher to use protect the traffic */
3826 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3829 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3833 /* Delete old cipher and allocate the new one */
3834 silc_cipher_free(channel->channel_key);
3835 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3837 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3841 /* Re-generate channel key */
3842 if (!silc_server_create_channel_key(server, channel, 0))
3845 /* Send the channel key. This sends it to our local clients and if
3846 we are normal server to our router as well. */
3847 silc_server_send_channel_key(server, NULL, channel,
3848 server->server_type == SILC_ROUTER ?
3849 FALSE : !server->standalone);
3852 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3853 /* Cipher mode is unset. Remove the cipher and revert back to
3855 cipher = channel->cipher;
3857 /* Delete old cipher and allocate default one */
3858 silc_cipher_free(channel->channel_key);
3859 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3860 &channel->channel_key)) {
3861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3862 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3866 /* Re-generate channel key */
3867 if (!silc_server_create_channel_key(server, channel, 0))
3870 /* Send the channel key. This sends it to our local clients and if
3871 we are normal server to our router as well. */
3872 silc_server_send_channel_key(server, NULL, channel,
3873 server->server_type == SILC_ROUTER ?
3874 FALSE : !server->standalone);
3878 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3879 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3880 /* HMAC to use protect the traffic */
3881 unsigned char hash[32];
3884 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3887 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3891 /* Delete old hmac and allocate the new one */
3892 silc_hmac_free(channel->hmac);
3893 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3895 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3899 /* Set the HMAC key out of current channel key. The client must do
3901 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3903 silc_hmac_set_key(channel->hmac, hash,
3904 silc_hash_len(channel->hmac->hash));
3905 memset(hash, 0, sizeof(hash));
3908 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3909 /* Hmac mode is unset. Remove the hmac and revert back to
3911 unsigned char hash[32];
3912 hmac = channel->hmac_name;
3914 /* Delete old hmac and allocate default one */
3915 silc_hmac_free(channel->hmac);
3916 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL,
3918 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3919 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3923 /* Set the HMAC key out of current channel key. The client must do
3925 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3927 silc_hmac_set_key(channel->hmac, hash,
3928 silc_hash_len(channel->hmac->hash));
3929 memset(hash, 0, sizeof(hash));
3933 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3934 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3935 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3936 /* Set the founder authentication */
3937 SilcAuthPayload auth;
3939 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3942 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3946 auth = silc_auth_payload_parse(tmp, tmp_len);
3948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3949 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3953 /* Save the public key */
3954 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3955 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3958 channel->founder_method = silc_auth_get_method(auth);
3960 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3961 tmp = silc_auth_get_data(auth, &tmp_len);
3962 channel->founder_passwd =
3963 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3964 memcpy(channel->founder_passwd, tmp, tmp_len);
3965 channel->founder_passwd_len = tmp_len;
3967 /* Verify the payload before setting the mode */
3968 if (!silc_auth_verify(auth, channel->founder_method,
3969 channel->founder_key, 0, idata->hash,
3970 client->id, SILC_ID_CLIENT)) {
3971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3972 SILC_STATUS_ERR_AUTH_FAILED);
3977 silc_auth_payload_free(auth);
3981 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3982 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3983 if (channel->founder_key)
3984 silc_pkcs_public_key_free(channel->founder_key);
3985 if (channel->founder_passwd) {
3986 silc_free(channel->founder_passwd);
3987 channel->founder_passwd = NULL;
3993 /* Finally, set the mode */
3994 channel->mode = mode_mask;
3996 /* Send CMODE_CHANGE notify */
3997 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3998 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3999 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
4000 cidp->data, cidp->len,
4002 cipher, cipher ? strlen(cipher) : 0,
4003 hmac, hmac ? strlen(hmac) : 0);
4005 /* Set CMODE notify type to network */
4006 if (!server->standalone)
4007 silc_server_send_notify_cmode(server, server->router->connection,
4008 server->server_type == SILC_ROUTER ?
4009 TRUE : FALSE, channel,
4010 mode_mask, client->id, SILC_ID_CLIENT,
4013 /* Send command reply to sender */
4014 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4015 SILC_STATUS_OK, ident, 2,
4016 2, tmp_id, tmp_len2,
4018 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4019 packet->data, packet->len, FALSE);
4021 silc_buffer_free(packet);
4022 silc_free(channel_id);
4026 silc_server_command_free(cmd);
4029 /* Server side of CUMODE command. Changes client's mode on a channel. */
4031 SILC_SERVER_CMD_FUNC(cumode)
4033 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4034 SilcServer server = cmd->server;
4035 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4036 SilcIDListData idata = (SilcIDListData)client;
4037 SilcChannelID *channel_id;
4038 SilcClientID *client_id;
4039 SilcChannelEntry channel;
4040 SilcClientEntry target_client;
4041 SilcChannelClientEntry chl;
4042 SilcBuffer packet, idp;
4043 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4044 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4046 uint16 ident = silc_command_get_ident(cmd->payload);
4048 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4050 /* Get Channel ID */
4051 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4054 SILC_STATUS_ERR_NO_CHANNEL_ID);
4057 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4060 SILC_STATUS_ERR_NO_CHANNEL_ID);
4064 /* Get channel entry */
4065 channel = silc_idlist_find_channel_by_id(server->local_list,
4068 channel = silc_idlist_find_channel_by_id(server->global_list,
4071 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4072 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4077 /* Check whether sender is on the channel */
4078 if (!silc_server_client_on_channel(client, channel)) {
4079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4080 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4084 /* Check that client has rights to change other's rights */
4085 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4086 sender_mask = chl->mode;
4088 /* Get the target client's channel mode mask */
4089 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4092 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4095 SILC_GET32_MSB(target_mask, tmp_mask);
4097 /* Get target Client ID */
4098 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4101 SILC_STATUS_ERR_NO_CLIENT_ID);
4104 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4107 SILC_STATUS_ERR_NO_CLIENT_ID);
4111 /* Get target client's entry */
4112 target_client = silc_idlist_find_client_by_id(server->local_list,
4113 client_id, TRUE, NULL);
4114 if (!target_client) {
4115 target_client = silc_idlist_find_client_by_id(server->global_list,
4116 client_id, TRUE, NULL);
4119 if (target_client != client &&
4120 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4121 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4123 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4127 /* Check whether target client is on the channel */
4128 if (target_client != client) {
4129 if (!silc_server_client_on_channel(target_client, channel)) {
4130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4131 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4135 /* Get entry to the channel user list */
4136 silc_hash_table_find(channel->user_list, target_client, NULL,
4144 /* If the target client is founder, no one else can change their mode
4146 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4147 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4148 SILC_STATUS_ERR_NOT_YOU);
4152 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4153 /* The client tries to claim the founder rights. */
4154 unsigned char *tmp_auth;
4155 uint32 tmp_auth_len, auth_len;
4158 if (target_client != client) {
4159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4160 SILC_STATUS_ERR_NOT_YOU);
4164 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4165 !channel->founder_key) {
4166 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4167 SILC_STATUS_ERR_NOT_YOU);
4171 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4174 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4178 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4179 (void *)channel->founder_passwd : (void *)channel->founder_key);
4180 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4181 channel->founder_passwd_len : 0);
4183 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4184 channel->founder_method, auth, auth_len,
4185 idata->hash, client->id, SILC_ID_CLIENT)) {
4186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4187 SILC_STATUS_ERR_AUTH_FAILED);
4191 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4194 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4195 if (target_client == client) {
4196 /* Remove channel founder rights from itself */
4197 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4201 SILC_STATUS_ERR_NOT_YOU);
4207 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4208 /* Promote to operator */
4209 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4210 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4211 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4213 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4217 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4221 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4222 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4223 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4225 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4229 /* Demote to normal user */
4230 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4235 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4236 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4238 /* Send notify to channel, notify only if mode was actually changed. */
4240 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4241 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4242 idp->data, idp->len,
4246 /* Set CUMODE notify type to network */
4247 if (!server->standalone)
4248 silc_server_send_notify_cumode(server, server->router->connection,
4249 server->server_type == SILC_ROUTER ?
4250 TRUE : FALSE, channel,
4251 target_mask, client->id,
4256 /* Send command reply to sender */
4257 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4258 SILC_STATUS_OK, ident, 3,
4260 3, tmp_ch_id, tmp_ch_len,
4261 4, tmp_id, tmp_len);
4262 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4263 packet->data, packet->len, FALSE);
4265 silc_buffer_free(packet);
4266 silc_free(channel_id);
4267 silc_free(client_id);
4268 silc_buffer_free(idp);
4271 silc_server_command_free(cmd);
4274 /* Server side of KICK command. Kicks client out of channel. */
4276 SILC_SERVER_CMD_FUNC(kick)
4278 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4279 SilcServer server = cmd->server;
4280 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4281 SilcClientEntry target_client;
4282 SilcChannelID *channel_id;
4283 SilcClientID *client_id;
4284 SilcChannelEntry channel;
4285 SilcChannelClientEntry chl;
4288 unsigned char *tmp, *comment;
4290 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4292 /* Get Channel ID */
4293 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4296 SILC_STATUS_ERR_NO_CHANNEL_ID);
4299 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4302 SILC_STATUS_ERR_NO_CHANNEL_ID);
4306 /* Get channel entry */
4307 channel = silc_idlist_find_channel_by_id(server->local_list,
4310 channel = silc_idlist_find_channel_by_id(server->local_list,
4313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4314 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4319 /* Check whether sender is on the channel */
4320 if (!silc_server_client_on_channel(client, channel)) {
4321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4322 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4326 /* Check that the kicker is channel operator or channel founder */
4327 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4328 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4330 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4334 /* Get target Client ID */
4335 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4338 SILC_STATUS_ERR_NO_CLIENT_ID);
4341 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4344 SILC_STATUS_ERR_NO_CLIENT_ID);
4348 /* Get target client's entry */
4349 target_client = silc_idlist_find_client_by_id(server->local_list,
4350 client_id, TRUE, NULL);
4351 if (!target_client) {
4352 target_client = silc_idlist_find_client_by_id(server->global_list,
4353 client_id, TRUE, NULL);
4356 /* Check that the target client is not channel founder. Channel founder
4357 cannot be kicked from the channel. */
4358 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4359 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4361 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4365 /* Check whether target client is on the channel */
4366 if (!silc_server_client_on_channel(target_client, channel)) {
4367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4368 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4374 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4378 /* Send command reply to sender */
4379 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4382 /* Send KICKED notify to local clients on the channel */
4383 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4384 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4385 SILC_NOTIFY_TYPE_KICKED,
4387 idp->data, idp->len,
4388 comment, comment ? strlen(comment) : 0);
4389 silc_buffer_free(idp);
4391 /* Remove the client from the channel. If the channel does not exist
4392 after removing the client then the client kicked itself off the channel
4393 and we don't have to send anything after that. */
4394 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4395 target_client, FALSE))
4398 /* Send KICKED notify to primary route */
4399 if (!server->standalone)
4400 silc_server_send_notify_kicked(server, server->router->connection,
4401 server->server_type == SILC_ROUTER ?
4402 TRUE : FALSE, channel,
4403 target_client->id, comment);
4405 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4406 /* Re-generate channel key */
4407 if (!silc_server_create_channel_key(server, channel, 0))
4410 /* Send the channel key to the channel. The key of course is not sent
4411 to the client who was kicked off the channel. */
4412 silc_server_send_channel_key(server, target_client->connection, channel,
4413 server->server_type == SILC_ROUTER ?
4414 FALSE : !server->standalone);
4418 silc_server_command_free(cmd);
4421 /* Server side of OPER command. Client uses this comand to obtain server
4422 operator privileges to this server/router. */
4424 SILC_SERVER_CMD_FUNC(oper)
4426 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4427 SilcServer server = cmd->server;
4428 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4429 unsigned char *username, *auth;
4431 SilcServerConfigSectionAdminConnection *admin;
4432 SilcIDListData idata = (SilcIDListData)client;
4434 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4436 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4439 /* Get the username */
4440 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4443 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4447 /* Get the admin configuration */
4448 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4449 username, client->nickname);
4451 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4452 username, client->nickname);
4454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4455 SILC_STATUS_ERR_AUTH_FAILED);
4460 /* Get the authentication payload */
4461 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4464 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4468 /* Verify the authentication data */
4469 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4470 admin->auth_data, admin->auth_data_len,
4471 idata->hash, client->id, SILC_ID_CLIENT)) {
4472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4473 SILC_STATUS_ERR_AUTH_FAILED);
4477 /* Client is now server operator */
4478 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4480 /* Send UMODE change to primary router */
4481 if (!server->standalone)
4482 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4483 client->id, client->mode);
4485 /* Send reply to the sender */
4486 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4490 silc_server_command_free(cmd);
4493 /* Server side of SILCOPER command. Client uses this comand to obtain router
4494 operator privileges to this router. */
4496 SILC_SERVER_CMD_FUNC(silcoper)
4498 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4499 SilcServer server = cmd->server;
4500 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4501 unsigned char *username, *auth;
4503 SilcServerConfigSectionAdminConnection *admin;
4504 SilcIDListData idata = (SilcIDListData)client;
4506 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4508 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4511 if (server->server_type == SILC_SERVER) {
4512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4513 SILC_STATUS_ERR_AUTH_FAILED);
4517 /* Get the username */
4518 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4521 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4525 /* Get the admin configuration */
4526 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4527 username, client->nickname);
4529 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4530 username, client->nickname);
4532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4533 SILC_STATUS_ERR_AUTH_FAILED);
4538 /* Get the authentication payload */
4539 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4542 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4546 /* Verify the authentication data */
4547 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4548 admin->auth_data, admin->auth_data_len,
4549 idata->hash, client->id, SILC_ID_CLIENT)) {
4550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4551 SILC_STATUS_ERR_AUTH_FAILED);
4555 /* Client is now router operator */
4556 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4558 /* Send UMODE change to primary router */
4559 if (!server->standalone)
4560 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4561 client->id, client->mode);
4563 /* Send reply to the sender */
4564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4568 silc_server_command_free(cmd);
4571 /* Server side command of CONNECT. Connects us to the specified remote
4572 server or router. */
4574 SILC_SERVER_CMD_FUNC(connect)
4576 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4577 SilcServer server = cmd->server;
4578 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4579 unsigned char *tmp, *host;
4581 uint32 port = SILC_PORT;
4583 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4585 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4588 /* Check whether client has the permissions. */
4589 if (client->mode == SILC_UMODE_NONE) {
4590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4591 SILC_STATUS_ERR_NO_SERVER_PRIV);
4595 if (server->server_type == SILC_ROUTER &&
4596 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4597 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4598 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4602 /* Get the remote server */
4603 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4606 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4611 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4613 SILC_GET32_MSB(port, tmp);
4615 /* Create the connection. It is done with timeout and is async. */
4616 silc_server_create_connection(server, host, port);
4618 /* Send reply to the sender */
4619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4623 silc_server_command_free(cmd);
4626 /* Server side of command BAN. This is used to manage the ban list of the
4627 channel. To add clients and remove clients from the ban list. */
4629 SILC_SERVER_CMD_FUNC(ban)
4631 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4632 SilcServer server = cmd->server;
4633 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4635 SilcChannelEntry channel;
4636 SilcChannelClientEntry chl;
4637 SilcChannelID *channel_id = NULL;
4638 unsigned char *id, *add, *del;
4639 uint32 id_len, tmp_len;
4640 uint16 ident = silc_command_get_ident(cmd->payload);
4642 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4645 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4647 /* Get Channel ID */
4648 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4650 channel_id = silc_id_payload_parse_id(id, id_len);
4652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4653 SILC_STATUS_ERR_NO_CHANNEL_ID);
4658 /* Get channel entry. The server must know about the channel since the
4659 client is expected to be on the channel. */
4660 channel = silc_idlist_find_channel_by_id(server->local_list,
4663 channel = silc_idlist_find_channel_by_id(server->global_list,
4666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4667 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4672 /* Check whether this client is on the channel */
4673 if (!silc_server_client_on_channel(client, channel)) {
4674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4675 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4679 /* Get entry to the channel user list */
4680 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4682 /* The client must be at least channel operator. */
4683 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4685 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4689 /* Get the new ban and add it to the ban list */
4690 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4692 if (!channel->ban_list)
4693 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4695 channel->ban_list = silc_realloc(channel->ban_list,
4696 sizeof(*channel->ban_list) *
4698 strlen(channel->ban_list) + 2));
4699 if (add[tmp_len - 1] == ',')
4700 add[tmp_len - 1] = '\0';
4702 strncat(channel->ban_list, add, tmp_len);
4703 strncat(channel->ban_list, ",", 1);
4706 /* Get the ban to be removed and remove it from the list */
4707 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4708 if (del && channel->ban_list) {
4709 char *start, *end, *n;
4711 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4712 silc_free(channel->ban_list);
4713 channel->ban_list = NULL;
4715 start = strstr(channel->ban_list, del);
4716 if (start && strlen(start) >= tmp_len) {
4717 end = start + tmp_len;
4718 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4719 strncat(n, channel->ban_list, start - channel->ban_list);
4720 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4722 silc_free(channel->ban_list);
4723 channel->ban_list = n;
4728 /* Send the BAN notify type to our primary router. */
4729 if (!server->standalone && (add || del))
4730 silc_server_send_notify_ban(server, server->router->connection,
4731 server->server_type == SILC_ROUTER ?
4732 TRUE : FALSE, channel, add, del);
4734 /* Send the reply back to the client */
4735 if (channel->ban_list)
4737 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4738 SILC_STATUS_OK, ident, 2,
4740 3, channel->ban_list,
4741 strlen(channel->ban_list) - 1);
4744 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4745 SILC_STATUS_OK, ident, 1,
4748 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4749 packet->data, packet->len, FALSE);
4751 silc_buffer_free(packet);
4755 silc_free(channel_id);
4756 silc_server_command_free(cmd);
4759 /* Server side command of CLOSE. Closes connection to a specified server. */
4761 SILC_SERVER_CMD_FUNC(close)
4763 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4764 SilcServer server = cmd->server;
4765 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4766 SilcServerEntry server_entry;
4767 SilcSocketConnection sock;
4770 unsigned char *name;
4771 uint32 port = SILC_PORT;
4773 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4775 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4778 /* Check whether client has the permissions. */
4779 if (client->mode == SILC_UMODE_NONE) {
4780 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4781 SILC_STATUS_ERR_NO_SERVER_PRIV);
4785 /* Get the remote server */
4786 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4789 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4794 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4796 SILC_GET32_MSB(port, tmp);
4798 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4799 name, port, FALSE, NULL);
4800 if (!server_entry) {
4801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4802 SILC_STATUS_ERR_NO_SERVER_ID);
4806 /* Send reply to the sender */
4807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4810 /* Close the connection to the server */
4811 sock = (SilcSocketConnection)server_entry->connection;
4812 silc_server_free_sock_user_data(server, sock);
4813 silc_server_close_connection(server, sock);
4816 silc_server_command_free(cmd);
4819 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4820 active connections. */
4822 SILC_SERVER_CMD_FUNC(shutdown)
4824 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4825 SilcServer server = cmd->server;
4826 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4828 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4830 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4833 /* Check whether client has the permission. */
4834 if (client->mode == SILC_UMODE_NONE) {
4835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4836 SILC_STATUS_ERR_NO_SERVER_PRIV);
4840 /* Send reply to the sender */
4841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4844 /* Then, gracefully, or not, bring the server down. */
4845 silc_server_stop(server);
4849 silc_server_command_free(cmd);
4852 /* Server side command of LEAVE. Removes client from a channel. */
4854 SILC_SERVER_CMD_FUNC(leave)
4856 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4857 SilcServer server = cmd->server;
4858 SilcSocketConnection sock = cmd->sock;
4859 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4860 SilcChannelID *id = NULL;
4861 SilcChannelEntry channel;
4865 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4867 /* Get Channel ID */
4868 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4870 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4871 SILC_STATUS_ERR_NO_CHANNEL_ID);
4874 id = silc_id_payload_parse_id(tmp, len);
4876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4877 SILC_STATUS_ERR_NO_CHANNEL_ID);
4881 /* Get channel entry */
4882 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4884 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4887 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4892 /* Check whether this client is on the channel */
4893 if (!silc_server_client_on_channel(id_entry, channel)) {
4894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4895 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4899 /* Notify routers that they should remove this client from their list
4900 of clients on the channel. Send LEAVE notify type. */
4901 if (!server->standalone)
4902 silc_server_send_notify_leave(server, server->router->connection,
4903 server->server_type == SILC_ROUTER ?
4904 TRUE : FALSE, channel, id_entry->id);
4906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4909 /* Remove client from channel */
4910 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4912 /* If the channel does not exist anymore we won't send anything */
4915 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4916 /* Re-generate channel key */
4917 if (!silc_server_create_channel_key(server, channel, 0))
4920 /* Send the channel key */
4921 silc_server_send_channel_key(server, NULL, channel,
4922 server->server_type == SILC_ROUTER ?
4923 FALSE : !server->standalone);
4929 silc_server_command_free(cmd);
4932 /* Server side of command USERS. Resolves clients and their USERS currently
4933 joined on the requested channel. The list of Client ID's and their modes
4934 on the channel is sent back. */
4936 SILC_SERVER_CMD_FUNC(users)
4938 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4939 SilcServer server = cmd->server;
4940 SilcChannelEntry channel;
4941 SilcChannelID *id = NULL;
4942 SilcBuffer packet, idp;
4943 unsigned char *channel_id;
4944 uint32 channel_id_len;
4945 SilcBuffer client_id_list;
4946 SilcBuffer client_mode_list;
4947 unsigned char lc[4];
4948 uint32 list_count = 0;
4949 uint16 ident = silc_command_get_ident(cmd->payload);
4952 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4954 /* Get Channel ID */
4955 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4957 /* Get channel name */
4958 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4960 if (!channel_id && !channel_name) {
4961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4962 SILC_STATUS_ERR_NO_CHANNEL_ID);
4967 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4970 SILC_STATUS_ERR_NO_CHANNEL_ID);
4975 /* If we are server and we don't know about this channel we will send
4976 the command to our router. If we know about the channel then we also
4977 have the list of users already. */
4979 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4981 channel = silc_idlist_find_channel_by_name(server->local_list,
4982 channel_name, NULL);
4985 if (server->server_type == SILC_SERVER && !server->standalone &&
4989 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4990 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4992 /* Send USERS command */
4993 silc_server_packet_send(server, server->router->connection,
4994 SILC_PACKET_COMMAND, cmd->packet->flags,
4995 tmpbuf->data, tmpbuf->len, TRUE);
4997 /* Reprocess this packet after received reply */
4998 silc_server_command_pending(server, SILC_COMMAND_USERS,
4999 silc_command_get_ident(cmd->payload),
5000 silc_server_command_destructor,
5001 silc_server_command_users,
5002 silc_server_command_dup(cmd));
5003 cmd->pending = TRUE;
5004 silc_command_set_ident(cmd->payload, ident);
5006 silc_buffer_free(tmpbuf);
5011 /* Check the global list as well. */
5013 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5015 channel = silc_idlist_find_channel_by_name(server->global_list,
5016 channel_name, NULL);
5018 /* Channel really does not exist */
5019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5020 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5025 /* If the channel is private or secret do not send anything, unless the
5026 user requesting this command is on the channel. */
5027 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5028 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5029 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5031 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5036 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5038 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5043 /* Get the users list */
5044 silc_server_get_users_on_channel(server, channel, &client_id_list,
5045 &client_mode_list, &list_count);
5048 SILC_PUT32_MSB(list_count, lc);
5051 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5052 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5053 SILC_STATUS_OK, ident, 4,
5054 2, idp->data, idp->len,
5056 4, client_id_list->data,
5057 client_id_list->len,
5058 5, client_mode_list->data,
5059 client_mode_list->len);
5060 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5061 packet->data, packet->len, FALSE);
5063 silc_buffer_free(idp);
5064 silc_buffer_free(packet);
5065 silc_buffer_free(client_id_list);
5066 silc_buffer_free(client_mode_list);
5071 silc_server_command_free(cmd);
5074 /* Server side of command GETKEY. This fetches the client's public key
5075 from the server where to the client is connected. */
5077 SILC_SERVER_CMD_FUNC(getkey)
5079 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5080 SilcServer server = cmd->server;
5082 SilcClientEntry client;
5083 SilcServerEntry server_entry;
5084 SilcClientID *client_id = NULL;
5085 SilcServerID *server_id = NULL;
5086 SilcIDPayload idp = NULL;
5087 uint16 ident = silc_command_get_ident(cmd->payload);
5088 unsigned char *tmp, *pkdata;
5089 uint32 tmp_len, pklen;
5090 SilcBuffer pk = NULL;
5093 SILC_LOG_DEBUG(("Start"));
5095 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5098 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5101 idp = silc_id_payload_parse_data(tmp, tmp_len);
5103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5108 id_type = silc_id_payload_get_type(idp);
5109 if (id_type == SILC_ID_CLIENT) {
5110 client_id = silc_id_payload_get_id(idp);
5112 /* If the client is not found from local list there is no chance it
5113 would be locally connected client so send the command further. */
5114 client = silc_idlist_find_client_by_id(server->local_list,
5115 client_id, TRUE, NULL);
5117 client = silc_idlist_find_client_by_id(server->global_list,
5118 client_id, TRUE, NULL);
5120 if ((!client && !cmd->pending && !server->standalone) ||
5121 (client && !client->connection && !cmd->pending) ||
5122 (client && !client->data.public_key && !cmd->pending)) {
5125 SilcSocketConnection dest_sock;
5127 dest_sock = silc_server_get_client_route(server, NULL, 0,
5132 old_ident = silc_command_get_ident(cmd->payload);
5133 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5134 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5136 silc_server_packet_send(server, dest_sock,
5137 SILC_PACKET_COMMAND, cmd->packet->flags,
5138 tmpbuf->data, tmpbuf->len, TRUE);
5140 /* Reprocess this packet after received reply from router */
5141 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5142 silc_command_get_ident(cmd->payload),
5143 silc_server_command_destructor,
5144 silc_server_command_getkey,
5145 silc_server_command_dup(cmd));
5146 cmd->pending = TRUE;
5148 silc_command_set_ident(cmd->payload, old_ident);
5149 silc_buffer_free(tmpbuf);
5154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5155 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5159 /* The client is locally connected, just get the public key and
5160 send it back. If they key does not exist then do not send it,
5161 send just OK reply */
5162 if (!client->data.public_key) {
5166 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5167 pk = silc_buffer_alloc(4 + tmp_len);
5168 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5169 silc_buffer_format(pk,
5170 SILC_STR_UI_SHORT(tmp_len),
5171 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5172 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5178 } else if (id_type == SILC_ID_SERVER) {
5179 server_id = silc_id_payload_get_id(idp);
5181 /* If the server is not found from local list there is no chance it
5182 would be locally connected server so send the command further. */
5183 server_entry = silc_idlist_find_server_by_id(server->local_list,
5184 server_id, TRUE, NULL);
5186 server_entry = silc_idlist_find_server_by_id(server->global_list,
5187 server_id, TRUE, NULL);
5189 if (server_entry != server->id_entry &&
5190 ((!server_entry && !cmd->pending && !server->standalone) ||
5191 (server_entry && !server_entry->connection && !cmd->pending &&
5192 !server->standalone) ||
5193 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5194 !server->standalone))) {
5198 old_ident = silc_command_get_ident(cmd->payload);
5199 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5200 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5202 silc_server_packet_send(server, server->router->connection,
5203 SILC_PACKET_COMMAND, cmd->packet->flags,
5204 tmpbuf->data, tmpbuf->len, TRUE);
5206 /* Reprocess this packet after received reply from router */
5207 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5208 silc_command_get_ident(cmd->payload),
5209 silc_server_command_destructor,
5210 silc_server_command_getkey,
5211 silc_server_command_dup(cmd));
5212 cmd->pending = TRUE;
5214 silc_command_set_ident(cmd->payload, old_ident);
5215 silc_buffer_free(tmpbuf);
5219 if (!server_entry) {
5220 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5221 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5225 /* If they key does not exist then do not send it, send just OK reply */
5226 if (!server_entry->data.public_key) {
5230 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5232 pk = silc_buffer_alloc(4 + tmp_len);
5233 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5234 silc_buffer_format(pk,
5235 SILC_STR_UI_SHORT(tmp_len),
5236 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5237 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5247 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5248 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5249 SILC_STATUS_OK, ident,
5253 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5254 packet->data, packet->len, FALSE);
5255 silc_buffer_free(packet);
5258 silc_buffer_free(pk);
5262 silc_id_payload_free(idp);
5263 silc_free(client_id);
5264 silc_free(server_id);
5265 silc_server_command_free(cmd);