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->data,
185 packet->buffer->len);
187 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
188 silc_buffer_free(packet->buffer);
189 silc_packet_context_free(packet);
190 silc_socket_free(ctx->sock);
194 ctx->args = silc_command_get_args(ctx->payload);
196 /* Get the command */
197 command = silc_command_get(ctx->payload);
198 for (cmd = silc_command_list; cmd->cb; cmd++)
199 if (cmd->cmd == command)
203 silc_server_command_send_status_reply(ctx, command,
204 SILC_STATUS_ERR_UNKNOWN_COMMAND);
205 silc_server_command_free(ctx);
209 /* Execute client's commands always with timeout. Normally they are
210 executed with zero (0) timeout but if client is sending command more
211 frequently than once in 2 seconds, then the timeout may be 0 to 2
213 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
214 SilcClientEntry client = (SilcClientEntry)sock->user_data;
215 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
221 if (client->last_command && (time(NULL) - client->last_command) < 2) {
222 client->fast_command++;
225 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
226 client->fast_command--);
230 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
231 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
232 silc_schedule_task_add(server->schedule, sock->sock,
233 silc_server_command_process_timeout,
235 2 - (time(NULL) - client->last_command), 0,
237 SILC_TASK_PRI_NORMAL);
239 silc_schedule_task_add(server->schedule, sock->sock,
240 silc_server_command_process_timeout,
244 SILC_TASK_PRI_NORMAL);
248 /* Execute for server */
250 if (!(cmd->flags & SILC_CF_REG))
252 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
256 /* Allocate Command Context */
258 SilcServerCommandContext silc_server_command_alloc()
260 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
265 /* Free's the command context allocated before executing the command */
267 void silc_server_command_free(SilcServerCommandContext ctx)
270 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
272 if (ctx->users < 1) {
274 silc_command_payload_free(ctx->payload);
276 silc_packet_context_free(ctx->packet);
278 silc_socket_free(ctx->sock); /* Decrease reference counter */
283 /* Duplicate Command Context by adding reference counter. The context won't
284 be free'd untill it hits zero. */
286 SilcServerCommandContext
287 silc_server_command_dup(SilcServerCommandContext ctx)
290 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
295 /* Add new pending command to be executed when reply to a command has been
296 received. The `reply_cmd' is the command that will call the `callback'
297 with `context' when reply has been received. It can be SILC_COMMAND_NONE
298 to match any command with the `ident'. If `ident' is non-zero
299 the `callback' will be executed when received reply with command
300 identifier `ident'. */
302 void silc_server_command_pending(SilcServer server,
303 SilcCommand reply_cmd,
305 SilcServerPendingDestructor destructor,
306 SilcCommandCb callback,
309 SilcServerCommandPending *reply;
311 reply = silc_calloc(1, sizeof(*reply));
312 reply->reply_cmd = reply_cmd;
313 reply->ident = ident;
314 reply->context = context;
315 reply->callback = callback;
316 reply->destructor = destructor;
317 silc_dlist_add(server->pending_commands, reply);
320 /* Deletes pending command by reply command type. */
322 void silc_server_command_pending_del(SilcServer server,
323 SilcCommand reply_cmd,
326 SilcServerCommandPending *r;
328 silc_dlist_start(server->pending_commands);
329 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
330 if (r->reply_cmd == reply_cmd && r->ident == ident) {
331 silc_dlist_del(server->pending_commands, r);
337 /* Checks for pending commands and marks callbacks to be called from
338 the command reply function. Returns TRUE if there were pending command. */
340 SilcServerCommandPendingCallbacks
341 silc_server_command_pending_check(SilcServer server,
342 SilcServerCommandReplyContext ctx,
345 uint32 *callbacks_count)
347 SilcServerCommandPending *r;
348 SilcServerCommandPendingCallbacks callbacks = NULL;
351 silc_dlist_start(server->pending_commands);
352 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
353 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
354 && r->ident == ident) {
355 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
356 callbacks[i].context = r->context;
357 callbacks[i].callback = r->callback;
358 callbacks[i].destructor = r->destructor;
364 *callbacks_count = i;
368 /* Destructor function for pending callbacks. This is called when using
369 pending commands to free the context given for the pending command. */
371 static void silc_server_command_destructor(void *context)
373 silc_server_command_free((SilcServerCommandContext)context);
376 /* Sends simple status message as command reply packet */
379 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
381 SilcCommandStatus status)
385 SILC_LOG_DEBUG(("Sending command status %d", status));
388 silc_command_reply_payload_encode_va(command, status,
389 silc_command_get_ident(cmd->payload),
391 silc_server_packet_send(cmd->server, cmd->sock,
392 SILC_PACKET_COMMAND_REPLY, 0,
393 buffer->data, buffer->len, FALSE);
394 silc_buffer_free(buffer);
397 /* Sends command status reply with one extra argument. The argument
398 type must be sent as argument. */
401 silc_server_command_send_status_data(SilcServerCommandContext cmd,
403 SilcCommandStatus status,
410 SILC_LOG_DEBUG(("Sending command status %d", status));
413 silc_command_reply_payload_encode_va(command, status,
414 silc_command_get_ident(cmd->payload),
415 1, arg_type, arg, arg_len);
416 silc_server_packet_send(cmd->server, cmd->sock,
417 SILC_PACKET_COMMAND_REPLY, 0,
418 buffer->data, buffer->len, FALSE);
419 silc_buffer_free(buffer);
422 /* This function can be called to check whether in the command reply
423 an error occurred. This function has no effect if this is called
424 when the command function was not called as pending command callback.
425 This returns TRUE if error had occurred. */
428 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
429 SilcServerCommandReplyContext cmdr,
432 SilcCommandStatus status;
434 if (!cmd->pending || !cmdr)
437 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
438 if (status != SILC_STATUS_OK &&
439 status != SILC_STATUS_LIST_START &&
440 status != SILC_STATUS_LIST_ITEM &&
441 status != SILC_STATUS_LIST_END) {
444 /* Send the same command reply payload */
445 silc_command_set_ident(cmdr->payload,
446 silc_command_get_ident(cmd->payload));
447 buffer = silc_command_payload_encode_payload(cmdr->payload);
448 silc_server_packet_send(cmd->server, cmd->sock,
449 SILC_PACKET_COMMAND_REPLY, 0,
450 buffer->data, buffer->len, FALSE);
451 silc_buffer_free(buffer);
458 /******************************************************************************
462 ******************************************************************************/
465 silc_server_command_whois_parse(SilcServerCommandContext cmd,
466 SilcClientID ***client_id,
467 uint32 *client_id_count,
475 uint32 argc = silc_argument_get_arg_num(cmd->args);
478 /* If client ID is in the command it must be used instead of nickname */
479 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
481 /* No ID, get the nickname@server string and parse it. */
482 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
484 silc_parse_userfqdn(tmp, nickname, server_name);
486 silc_server_command_send_status_reply(cmd, command,
487 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
491 /* Command includes ID, we must use that. Also check whether the command
492 has more than one ID set - take them all. */
494 *client_id = silc_calloc(1, sizeof(**client_id));
495 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
496 if ((*client_id)[0] == NULL) {
497 silc_free(*client_id);
500 *client_id_count = 1;
502 /* Take all ID's from the command packet */
504 for (k = 1, i = 1; i < argc; i++) {
505 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
507 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
508 (*client_id_count + 1));
509 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
510 if ((*client_id)[k] == NULL) {
511 /* Cleanup all and fail */
512 for (i = 0; i < *client_id_count; i++)
513 silc_free((*client_id)[i]);
514 silc_free(*client_id);
517 (*client_id_count)++;
524 /* Get the max count of reply messages allowed */
525 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
534 /* Resolve context used by both WHOIS and IDENTIFY commands */
536 SilcServerEntry router;
538 unsigned char **res_argv;
539 uint32 *res_argv_lens;
540 uint32 *res_argv_types;
542 } *SilcServerResolveContext;
545 silc_server_command_whois_check(SilcServerCommandContext cmd,
546 SilcClientEntry *clients,
547 uint32 clients_count)
549 SilcServer server = cmd->server;
550 SilcClientEntry entry;
551 SilcServerResolveContext resolve = NULL, r = NULL;
552 uint32 resolve_count = 0;
556 for (i = 0; i < clients_count; i++) {
561 if ((entry->nickname && entry->username && entry->userinfo) ||
562 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
566 /* If we are normal server, and we've not resolved this client from
567 router and it is global client, we'll check whether it is on some
568 channel. If not then we cannot be sure about its validity, and
569 we'll resolve it from router. */
570 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
571 entry->connection || silc_hash_table_count(entry->channels))
575 /* We need to resolve this entry since it is not complete */
577 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
578 /* The entry is being resolved (and we are not the resolver) so attach
579 to the command reply and we're done with this one. */
580 silc_server_command_pending(server, SILC_COMMAND_NONE,
581 entry->resolve_cmd_ident,
582 silc_server_command_destructor,
583 silc_server_command_whois,
584 silc_server_command_dup(cmd));
587 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
588 /* We've resolved this and it still is not ready. We'll return
589 and are that this will be handled again after it is resolved. */
590 for (i = 0; i < resolve_count; i++) {
591 for (k = 0; k < r->res_argc; k++)
592 silc_free(r->res_argv[k]);
593 silc_free(r->res_argv);
594 silc_free(r->res_argv_lens);
595 silc_free(r->res_argv_types);
600 /* We'll resolve this client */
604 for (k = 0; k < resolve_count; k++) {
605 if (resolve[k].router == entry->router) {
612 resolve = silc_realloc(resolve, sizeof(*resolve) *
613 (resolve_count + 1));
614 r = &resolve[resolve_count];
615 memset(r, 0, sizeof(*r));
616 r->router = entry->router;
617 r->ident = ++server->cmd_ident;
621 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
623 r->res_argv_lens = silc_realloc(r->res_argv_lens,
624 sizeof(*r->res_argv_lens) *
626 r->res_argv_types = silc_realloc(r->res_argv_types,
627 sizeof(*r->res_argv_types) *
629 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
630 r->res_argv[r->res_argc] = silc_calloc(idp->len,
631 sizeof(**r->res_argv));
632 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
633 r->res_argv_lens[r->res_argc] = idp->len;
634 r->res_argv_types[r->res_argc] = r->res_argc + 3;
636 silc_buffer_free(idp);
638 entry->resolve_cmd_ident = r->ident;
639 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
640 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
645 /* Do the resolving */
646 for (i = 0; i < resolve_count; i++) {
651 /* Send WHOIS request. We send WHOIS since we're doing the requesting
652 now anyway so make it a good one. */
653 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
654 r->res_argc, r->res_argv,
658 silc_server_packet_send(server, r->router->connection,
659 SILC_PACKET_COMMAND, cmd->packet->flags,
660 res_cmd->data, res_cmd->len, FALSE);
662 /* Reprocess this packet after received reply */
663 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
665 silc_server_command_destructor,
666 silc_server_command_whois,
667 silc_server_command_dup(cmd));
670 silc_buffer_free(res_cmd);
671 for (k = 0; k < r->res_argc; k++)
672 silc_free(r->res_argv[k]);
673 silc_free(r->res_argv);
674 silc_free(r->res_argv_lens);
675 silc_free(r->res_argv_types);
684 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
685 SilcClientEntry *clients,
686 uint32 clients_count,
689 SilcServer server = cmd->server;
692 SilcBuffer packet, idp, channels;
693 SilcClientEntry entry;
694 SilcCommandStatus status;
695 uint16 ident = silc_command_get_ident(cmd->payload);
696 char nh[256], uh[256];
697 unsigned char idle[4], mode[4];
698 unsigned char *fingerprint;
699 SilcSocketConnection hsock;
702 for (i = 0; i < clients_count; i++)
703 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
706 if (len == 0 && clients_count) {
708 if (entry->nickname) {
709 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
710 SILC_STATUS_ERR_NO_SUCH_NICK,
712 strlen(entry->nickname));
714 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
715 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
716 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
717 2, idp->data, idp->len);
718 silc_buffer_free(idp);
724 status = SILC_STATUS_OK;
726 status = SILC_STATUS_LIST_START;
728 for (i = 0, k = 0; i < clients_count; i++) {
731 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
732 if (clients_count == 1) {
733 if (entry->nickname) {
734 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
735 SILC_STATUS_ERR_NO_SUCH_NICK,
737 strlen(entry->nickname));
739 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
740 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
741 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
742 2, idp->data, idp->len);
743 silc_buffer_free(idp);
750 status = SILC_STATUS_LIST_ITEM;
752 if (clients_count > 1 && k == clients_count - 1)
753 status = SILC_STATUS_LIST_END;
755 if (count && k - 1 == count)
756 status = SILC_STATUS_LIST_END;
758 if (count && k - 1 > count)
761 /* Sanity check, however these should never fail. However, as
762 this sanity check has been added here they have failed. */
763 if (!entry->nickname || !entry->username || !entry->userinfo)
766 /* Send WHOIS reply */
767 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
768 tmp = silc_argument_get_first_arg(cmd->args, NULL);
770 memset(uh, 0, sizeof(uh));
771 memset(nh, 0, sizeof(nh));
772 memset(idle, 0, sizeof(idle));
774 strncat(nh, entry->nickname, strlen(entry->nickname));
775 if (!strchr(entry->nickname, '@')) {
777 if (entry->servername) {
778 strncat(nh, entry->servername, strlen(entry->servername));
780 len = entry->router ? strlen(entry->router->server_name) :
781 strlen(server->server_name);
782 strncat(nh, entry->router ? entry->router->server_name :
783 server->server_name, len);
787 strncat(uh, entry->username, strlen(entry->username));
788 if (!strchr(entry->username, '@')) {
790 hsock = (SilcSocketConnection)entry->connection;
791 len = strlen(hsock->hostname);
792 strncat(uh, hsock->hostname, len);
795 channels = silc_server_get_client_channel_list(server, entry);
797 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
798 fingerprint = entry->data.fingerprint;
802 SILC_PUT32_MSB(entry->mode, mode);
804 if (entry->connection) {
805 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
809 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
811 2, idp->data, idp->len,
815 strlen(entry->userinfo),
816 6, channels ? channels->data : NULL,
817 channels ? channels->len : 0,
821 fingerprint ? 20 : 0);
823 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
824 0, packet->data, packet->len, FALSE);
826 silc_buffer_free(packet);
827 silc_buffer_free(idp);
829 silc_buffer_free(channels);
836 silc_server_command_whois_process(SilcServerCommandContext cmd)
838 SilcServer server = cmd->server;
839 char *nick = NULL, *server_name = NULL;
841 SilcClientEntry *clients = NULL, entry;
842 SilcClientID **client_id = NULL;
843 uint32 client_id_count = 0, clients_count = 0;
845 bool check_global = FALSE;
847 /* Parse the whois request */
848 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
849 &nick, &server_name, &count,
853 /* Send the WHOIS request to the router only if it included nickname.
854 Since nicknames can be expanded into many clients we need to send it
855 to router. If the WHOIS included only client ID's we will check them
856 first locally since we just might have them. */
857 if (nick && !client_id_count &&
858 cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
859 server->server_type == SILC_SERVER && !cmd->pending &&
860 !server->standalone) {
864 old_ident = silc_command_get_ident(cmd->payload);
865 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
866 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
868 /* Send WHOIS command to our router */
869 silc_server_packet_send(server, (SilcSocketConnection)
870 server->router->connection,
871 SILC_PACKET_COMMAND, cmd->packet->flags,
872 tmpbuf->data, tmpbuf->len, TRUE);
874 /* Reprocess this packet after received reply from router */
875 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
876 silc_command_get_ident(cmd->payload),
877 silc_server_command_destructor,
878 silc_server_command_whois,
879 silc_server_command_dup(cmd));
882 silc_command_set_ident(cmd->payload, old_ident);
884 silc_buffer_free(tmpbuf);
889 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
891 else if (server->server_type != SILC_SERVER)
894 /* Get all clients matching that ID or nickname from local list */
895 if (client_id_count) {
896 /* Check all Client ID's received in the command packet */
897 for (i = 0; i < client_id_count; i++) {
898 entry = silc_idlist_find_client_by_id(server->local_list,
899 client_id[i], TRUE, NULL);
900 if (!entry && check_global)
901 entry = silc_idlist_find_client_by_id(server->global_list,
902 client_id[i], TRUE, NULL);
904 clients = silc_realloc(clients, sizeof(*clients) *
905 (clients_count + 1));
906 clients[clients_count++] = entry;
910 if (!silc_idlist_get_clients_by_hash(server->local_list,
911 nick, server->md5hash,
912 &clients, &clients_count))
913 silc_idlist_get_clients_by_nickname(server->local_list,
915 &clients, &clients_count);
917 if (!silc_idlist_get_clients_by_hash(server->global_list,
918 nick, server->md5hash,
919 &clients, &clients_count))
920 silc_idlist_get_clients_by_nickname(server->global_list,
922 &clients, &clients_count);
927 /* Such client(s) really does not exist in the SILC network. */
928 if (!client_id_count) {
929 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
930 SILC_STATUS_ERR_NO_SUCH_NICK,
931 3, nick, strlen(nick));
933 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
934 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
935 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
936 2, idp->data, idp->len);
937 silc_buffer_free(idp);
942 /* Router always finds the client entry if it exists in the SILC network.
943 However, it might be incomplete entry and does not include all the
944 mandatory fields that WHOIS command reply requires. Check for these and
945 make query from the server who owns the client if some fields are
947 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
952 /* Send the command reply */
953 silc_server_command_whois_send_reply(cmd, clients, clients_count,
957 if (client_id_count) {
958 for (i = 0; i < client_id_count; i++)
959 silc_free(client_id[i]);
960 silc_free(client_id);
964 silc_free(server_name);
969 /* Server side of command WHOIS. Processes user's query and sends found
970 results as command replies back to the client. */
972 SILC_SERVER_CMD_FUNC(whois)
974 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
977 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
979 ret = silc_server_command_whois_process(cmd);
982 silc_server_command_free(cmd);
985 /******************************************************************************
989 ******************************************************************************/
992 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1000 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1003 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1007 /* Get the nickname@server string and parse it. */
1008 silc_parse_userfqdn(tmp, nickname, server_name);
1010 /* Get the max count of reply messages allowed */
1011 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1021 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1022 SilcClientEntry *clients,
1023 uint32 clients_count)
1025 SilcServer server = cmd->server;
1027 SilcClientEntry entry;
1029 for (i = 0; i < clients_count; i++) {
1032 if (!entry->nickname || !entry->username) {
1039 old_ident = silc_command_get_ident(cmd->payload);
1040 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1041 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1043 /* Send WHOWAS command */
1044 silc_server_packet_send(server, entry->router->connection,
1045 SILC_PACKET_COMMAND, cmd->packet->flags,
1046 tmpbuf->data, tmpbuf->len, TRUE);
1048 /* Reprocess this packet after received reply */
1049 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1050 silc_command_get_ident(cmd->payload),
1051 silc_server_command_destructor,
1052 silc_server_command_whowas,
1053 silc_server_command_dup(cmd));
1054 cmd->pending = TRUE;
1056 silc_command_set_ident(cmd->payload, old_ident);
1058 silc_buffer_free(tmpbuf);
1067 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1068 SilcClientEntry *clients,
1069 uint32 clients_count)
1071 SilcServer server = cmd->server;
1073 int i, count = 0, len;
1074 SilcBuffer packet, idp;
1075 SilcClientEntry entry = NULL;
1076 SilcCommandStatus status;
1077 uint16 ident = silc_command_get_ident(cmd->payload);
1079 char nh[256], uh[256];
1081 status = SILC_STATUS_OK;
1082 if (clients_count > 1)
1083 status = SILC_STATUS_LIST_START;
1085 for (i = 0; i < clients_count; i++) {
1088 /* We will take only clients that are not valid anymore. They are the
1089 ones that are not registered anymore but still have a ID. They
1090 have disconnected us, and thus valid for WHOWAS. */
1091 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED)
1093 if (entry->id == NULL)
1096 if (count && i - 1 == count)
1101 if (clients_count > 2)
1102 status = SILC_STATUS_LIST_ITEM;
1104 if (clients_count > 1 && i == clients_count - 1)
1105 status = SILC_STATUS_LIST_END;
1107 /* Sanity check, however these should never fail. However, as
1108 this sanity check has been added here they have failed. */
1109 if (!entry->nickname || !entry->username)
1112 /* Send WHOWAS reply */
1113 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1114 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1116 memset(uh, 0, sizeof(uh));
1117 memset(nh, 0, sizeof(nh));
1119 strncat(nh, entry->nickname, strlen(entry->nickname));
1120 if (!strchr(entry->nickname, '@')) {
1121 strncat(nh, "@", 1);
1122 if (entry->servername) {
1123 strncat(nh, entry->servername, strlen(entry->servername));
1125 len = entry->router ? strlen(entry->router->server_name) :
1126 strlen(server->server_name);
1127 strncat(nh, entry->router ? entry->router->server_name :
1128 server->server_name, len);
1132 strncat(uh, entry->username, strlen(entry->username));
1133 if (!strchr(entry->username, '@')) {
1134 strncat(uh, "@", 1);
1135 strcat(uh, "*private*");
1139 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1141 2, idp->data, idp->len,
1146 strlen(entry->userinfo) : 0);
1147 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1148 0, packet->data, packet->len, FALSE);
1150 silc_buffer_free(packet);
1151 silc_buffer_free(idp);
1154 if (found == FALSE && entry)
1155 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1156 SILC_STATUS_ERR_NO_SUCH_NICK,
1158 strlen(entry->nickname));
1162 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1164 SilcServer server = cmd->server;
1165 char *nick = NULL, *server_name = NULL;
1167 SilcClientEntry *clients = NULL;
1168 uint32 clients_count = 0;
1170 bool check_global = FALSE;
1172 /* Protocol dictates that we must always send the received WHOWAS request
1173 to our router if we are normal server, so let's do it now unless we
1174 are standalone. We will not send any replies to the client until we
1175 have received reply from the router. */
1176 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1177 server->server_type == SILC_SERVER && !cmd->pending &&
1178 !server->standalone) {
1182 old_ident = silc_command_get_ident(cmd->payload);
1183 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1184 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1186 /* Send WHOWAS command to our router */
1187 silc_server_packet_send(server, (SilcSocketConnection)
1188 server->router->connection,
1189 SILC_PACKET_COMMAND, cmd->packet->flags,
1190 tmpbuf->data, tmpbuf->len, TRUE);
1192 /* Reprocess this packet after received reply from router */
1193 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1194 silc_command_get_ident(cmd->payload),
1195 silc_server_command_destructor,
1196 silc_server_command_whowas,
1197 silc_server_command_dup(cmd));
1198 cmd->pending = TRUE;
1200 silc_command_set_ident(cmd->payload, old_ident);
1202 silc_buffer_free(tmpbuf);
1207 /* We are ready to process the command request. Let's search for the
1208 requested client and send reply to the requesting client. */
1210 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1211 check_global = TRUE;
1212 else if (server->server_type != SILC_SERVER)
1213 check_global = TRUE;
1215 /* Parse the whowas request */
1216 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1219 /* Get all clients matching that nickname from local list */
1220 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1222 &clients, &clients_count))
1223 silc_idlist_get_clients_by_hash(server->local_list,
1224 nick, server->md5hash,
1225 &clients, &clients_count);
1227 /* Check global list as well */
1229 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1231 &clients, &clients_count))
1232 silc_idlist_get_clients_by_hash(server->global_list,
1233 nick, server->md5hash,
1234 &clients, &clients_count);
1238 /* Such a client really does not exist in the SILC network. */
1239 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1240 SILC_STATUS_ERR_NO_SUCH_NICK,
1241 3, nick, strlen(nick));
1245 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1250 /* Send the command reply to the client */
1251 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1256 silc_free(server_name);
1261 /* Server side of command WHOWAS. */
1263 SILC_SERVER_CMD_FUNC(whowas)
1265 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1268 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1270 ret = silc_server_command_whowas_process(cmd);
1273 silc_server_command_free(cmd);
1276 /******************************************************************************
1280 ******************************************************************************/
1283 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1284 SilcClientEntry **clients,
1285 uint32 *clients_count,
1286 SilcServerEntry **servers,
1287 uint32 *servers_count,
1288 SilcChannelEntry **channels,
1289 uint32 *channels_count,
1293 SilcServer server = cmd->server;
1296 uint32 argc = silc_argument_get_arg_num(cmd->args);
1298 bool check_global = FALSE;
1303 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1304 check_global = TRUE;
1305 else if (server->server_type != SILC_SERVER)
1306 check_global = TRUE;
1308 /* If ID Payload is in the command it must be used instead of names */
1309 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1311 /* No ID, get the names. */
1314 /* Try to get nickname@server. */
1315 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1318 char *nick_server = NULL;
1320 silc_parse_userfqdn(tmp, &nick, &nick_server);
1322 if (!silc_idlist_get_clients_by_hash(server->local_list,
1323 nick, server->md5hash,
1324 clients, clients_count))
1325 silc_idlist_get_clients_by_nickname(server->local_list,
1327 clients, clients_count);
1329 if (!silc_idlist_get_clients_by_hash(server->global_list,
1330 nick, server->md5hash,
1331 clients, clients_count))
1332 silc_idlist_get_clients_by_nickname(server->global_list,
1334 clients, clients_count);
1338 silc_free(nick_server);
1341 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1342 SILC_STATUS_ERR_NO_SUCH_NICK,
1343 3, tmp, strlen(tmp));
1348 /* Try to get server name */
1349 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1351 entry = silc_idlist_find_server_by_name(server->local_list,
1353 if (!entry && check_global)
1354 entry = silc_idlist_find_server_by_name(server->global_list,
1357 *servers = silc_realloc(*servers, sizeof(**servers) *
1358 (*servers_count + 1));
1359 (*servers)[(*servers_count)++] = entry;
1363 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1364 SILC_STATUS_ERR_NO_SUCH_SERVER,
1365 3, tmp, strlen(tmp));
1370 /* Try to get channel name */
1371 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1373 entry = silc_idlist_find_channel_by_name(server->local_list,
1375 if (!entry && check_global)
1376 entry = silc_idlist_find_channel_by_name(server->global_list,
1379 *channels = silc_realloc(*channels, sizeof(**channels) *
1380 (*channels_count + 1));
1381 (*channels)[(*channels_count)++] = entry;
1385 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1386 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1387 3, tmp, strlen(tmp));
1392 if (!(*clients) && !(*servers) && !(*channels)) {
1393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1394 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1398 /* Command includes ID, we must use that. Also check whether the command
1399 has more than one ID set - take them all. */
1402 /* Take all ID's from the command packet */
1403 for (i = 0; i < argc; i++) {
1406 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1410 idp = silc_id_payload_parse(tmp, len);
1412 silc_free(*clients);
1413 silc_free(*servers);
1414 silc_free(*channels);
1415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1416 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1420 id = silc_id_payload_get_id(idp);
1422 switch (silc_id_payload_get_type(idp)) {
1424 case SILC_ID_CLIENT:
1425 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1427 if (!entry && check_global)
1428 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1431 *clients = silc_realloc(*clients, sizeof(**clients) *
1432 (*clients_count + 1));
1433 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1435 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1436 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1443 case SILC_ID_SERVER:
1444 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1446 if (!entry && check_global)
1447 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1450 *servers = silc_realloc(*servers, sizeof(**servers) *
1451 (*servers_count + 1));
1452 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1454 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1455 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1461 case SILC_ID_CHANNEL:
1462 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1464 if (!entry && check_global)
1465 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1468 *channels = silc_realloc(*channels, sizeof(**channels) *
1469 (*channels_count + 1));
1470 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1472 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1473 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1485 silc_free(*clients);
1486 silc_free(*servers);
1487 silc_free(*channels);
1491 /* Get the max count of reply messages allowed */
1492 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1501 /* Checks that all mandatory fields in client entry are present. If not
1502 then send WHOIS request to the server who owns the client. We use
1503 WHOIS because we want to get as much information as possible at once. */
1506 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1507 SilcClientEntry *clients,
1508 uint32 clients_count)
1510 SilcServer server = cmd->server;
1511 SilcClientEntry entry;
1512 SilcServerResolveContext resolve = NULL, r = NULL;
1513 uint32 resolve_count = 0;
1517 for (i = 0; i < clients_count; i++) {
1522 if (entry->nickname ||
1523 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1527 /* If we are normal server, and we've not resolved this client from
1528 router and it is global client, we'll check whether it is on some
1529 channel. If not then we cannot be sure about its validity, and
1530 we'll resolve it from router. */
1531 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1532 entry->connection || silc_hash_table_count(entry->channels))
1536 /* We need to resolve this entry since it is not complete */
1538 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1539 /* The entry is being resolved (and we are not the resolver) so attach
1540 to the command reply and we're done with this one. */
1541 silc_server_command_pending(server, SILC_COMMAND_NONE,
1542 entry->resolve_cmd_ident,
1543 silc_server_command_destructor,
1544 silc_server_command_identify,
1545 silc_server_command_dup(cmd));
1548 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1549 /* We've resolved this and it still is not ready. We'll return
1550 and are that this will be handled again after it is resolved. */
1551 for (i = 0; i < resolve_count; i++) {
1552 for (k = 0; k < r->res_argc; k++)
1553 silc_free(r->res_argv[k]);
1554 silc_free(r->res_argv);
1555 silc_free(r->res_argv_lens);
1556 silc_free(r->res_argv_types);
1561 /* We'll resolve this client */
1565 for (k = 0; k < resolve_count; k++) {
1566 if (resolve[k].router == entry->router) {
1573 resolve = silc_realloc(resolve, sizeof(*resolve) *
1574 (resolve_count + 1));
1575 r = &resolve[resolve_count];
1576 memset(r, 0, sizeof(*r));
1577 r->router = entry->router;
1578 r->ident = ++server->cmd_ident;
1582 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1584 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1585 sizeof(*r->res_argv_lens) *
1587 r->res_argv_types = silc_realloc(r->res_argv_types,
1588 sizeof(*r->res_argv_types) *
1590 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1591 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1592 sizeof(**r->res_argv));
1593 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1594 r->res_argv_lens[r->res_argc] = idp->len;
1595 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1597 silc_buffer_free(idp);
1599 entry->resolve_cmd_ident = r->ident;
1600 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1601 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1606 /* Do the resolving */
1607 for (i = 0; i < resolve_count; i++) {
1612 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1613 now anyway so make it a good one. */
1614 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1615 r->res_argc, r->res_argv,
1619 silc_server_packet_send(server, r->router->connection,
1620 SILC_PACKET_COMMAND, cmd->packet->flags,
1621 res_cmd->data, res_cmd->len, FALSE);
1623 /* Reprocess this packet after received reply */
1624 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1626 silc_server_command_destructor,
1627 silc_server_command_identify,
1628 silc_server_command_dup(cmd));
1629 cmd->pending = TRUE;
1631 silc_buffer_free(res_cmd);
1632 for (k = 0; k < r->res_argc; k++)
1633 silc_free(r->res_argv[k]);
1634 silc_free(r->res_argv);
1635 silc_free(r->res_argv_lens);
1636 silc_free(r->res_argv_types);
1645 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1646 SilcClientEntry *clients,
1647 uint32 clients_count,
1648 SilcServerEntry *servers,
1649 uint32 servers_count,
1650 SilcChannelEntry *channels,
1651 uint32 channels_count,
1654 SilcServer server = cmd->server;
1656 SilcBuffer packet, idp;
1657 SilcCommandStatus status;
1658 uint16 ident = silc_command_get_ident(cmd->payload);
1659 char nh[256], uh[256];
1660 SilcSocketConnection hsock;
1662 status = SILC_STATUS_OK;
1665 SilcClientEntry entry;
1668 for (i = 0; i < clients_count; i++)
1669 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1672 if (len == 0 && clients_count) {
1674 if (entry->nickname) {
1675 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1676 SILC_STATUS_ERR_NO_SUCH_NICK,
1678 strlen(entry->nickname));
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);
1691 status = SILC_STATUS_LIST_START;
1693 for (i = 0, k = 0; i < clients_count; i++) {
1696 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1697 if (clients_count == 1) {
1698 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1699 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1700 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1701 2, idp->data, idp->len);
1702 silc_buffer_free(idp);
1708 status = SILC_STATUS_LIST_ITEM;
1709 if (clients_count > 1 && k == clients_count - 1
1710 && !servers_count && !channels_count)
1711 status = SILC_STATUS_LIST_END;
1712 if (count && k - 1 == count)
1713 status = SILC_STATUS_LIST_END;
1714 if (count && k - 1 > count)
1717 /* Send IDENTIFY reply */
1718 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1720 memset(uh, 0, sizeof(uh));
1721 memset(nh, 0, sizeof(nh));
1723 strncat(nh, entry->nickname, strlen(entry->nickname));
1724 if (!strchr(entry->nickname, '@')) {
1725 strncat(nh, "@", 1);
1726 if (entry->servername) {
1727 strncat(nh, entry->servername, strlen(entry->servername));
1729 len = entry->router ? strlen(entry->router->server_name) :
1730 strlen(server->server_name);
1731 strncat(nh, entry->router ? entry->router->server_name :
1732 server->server_name, len);
1736 if (!entry->username) {
1737 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1739 2, idp->data, idp->len,
1742 strncat(uh, entry->username, strlen(entry->username));
1743 if (!strchr(entry->username, '@')) {
1744 strncat(uh, "@", 1);
1745 hsock = (SilcSocketConnection)entry->connection;
1746 len = strlen(hsock->hostname);
1747 strncat(uh, hsock->hostname, len);
1750 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1752 2, idp->data, idp->len,
1757 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1758 0, packet->data, packet->len, FALSE);
1760 silc_buffer_free(packet);
1761 silc_buffer_free(idp);
1767 status = (status == SILC_STATUS_LIST_ITEM ?
1768 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1771 SilcServerEntry entry;
1773 if (status == SILC_STATUS_OK && servers_count > 1)
1774 status = SILC_STATUS_LIST_START;
1776 for (i = 0, k = 0; i < servers_count; i++) {
1780 status = SILC_STATUS_LIST_ITEM;
1781 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1782 status = SILC_STATUS_LIST_END;
1783 if (count && k - 1 == count)
1784 status = SILC_STATUS_LIST_END;
1785 if (count && k - 1 > count)
1788 /* Send IDENTIFY reply */
1789 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1791 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1793 2, idp->data, idp->len,
1794 3, entry->server_name,
1795 entry->server_name ?
1796 strlen(entry->server_name) : 0);
1797 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1798 0, packet->data, packet->len, FALSE);
1800 silc_buffer_free(packet);
1801 silc_buffer_free(idp);
1807 status = (status == SILC_STATUS_LIST_ITEM ?
1808 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1811 SilcChannelEntry entry;
1813 if (status == SILC_STATUS_OK && channels_count > 1)
1814 status = SILC_STATUS_LIST_START;
1816 for (i = 0, k = 0; i < channels_count; i++) {
1817 entry = channels[i];
1820 status = SILC_STATUS_LIST_ITEM;
1821 if (channels_count > 1 && k == channels_count - 1)
1822 status = SILC_STATUS_LIST_END;
1823 if (count && k - 1 == count)
1824 status = SILC_STATUS_LIST_END;
1825 if (count && k - 1 > count)
1828 /* Send IDENTIFY reply */
1829 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1831 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1833 2, idp->data, idp->len,
1834 3, entry->channel_name,
1835 entry->channel_name ?
1836 strlen(entry->channel_name): 0);
1837 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1838 0, packet->data, packet->len, FALSE);
1840 silc_buffer_free(packet);
1841 silc_buffer_free(idp);
1849 silc_server_command_identify_process(SilcServerCommandContext cmd)
1851 SilcServer server = cmd->server;
1854 SilcClientEntry *clients = NULL;
1855 SilcServerEntry *servers = NULL;
1856 SilcChannelEntry *channels = NULL;
1857 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1860 /* Parse the IDENTIFY request */
1861 if (!silc_server_command_identify_parse(cmd,
1862 &clients, &clients_count,
1863 &servers, &servers_count,
1864 &channels, &channels_count,
1868 /* Send the IDENTIFY request to the router only if it included nickname.
1869 Since nicknames can be expanded into many clients we need to send it
1870 to router. If the IDENTIFY included only client ID's we will check them
1871 first locally since we just might have them. */
1872 if (names && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1873 server->server_type == SILC_SERVER && !cmd->pending &&
1874 !server->standalone) {
1878 old_ident = silc_command_get_ident(cmd->payload);
1879 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1880 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1882 /* Send IDENTIFY command to our router */
1883 silc_server_packet_send(server, (SilcSocketConnection)
1884 server->router->connection,
1885 SILC_PACKET_COMMAND, cmd->packet->flags,
1886 tmpbuf->data, tmpbuf->len, TRUE);
1888 /* Reprocess this packet after received reply from router */
1889 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1890 silc_command_get_ident(cmd->payload),
1891 silc_server_command_destructor,
1892 silc_server_command_identify,
1893 silc_server_command_dup(cmd));
1894 cmd->pending = TRUE;
1896 silc_command_set_ident(cmd->payload, old_ident);
1898 silc_buffer_free(tmpbuf);
1903 /* Check that all mandatory fields are present and request those data
1904 from the server who owns the client if necessary. */
1905 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1911 /* Send the command reply to the client */
1912 silc_server_command_identify_send_reply(cmd,
1913 clients, clients_count,
1914 servers, servers_count,
1915 channels, channels_count,
1921 silc_free(channels);
1926 SILC_SERVER_CMD_FUNC(identify)
1928 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1931 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1933 ret = silc_server_command_identify_process(cmd);
1936 silc_server_command_free(cmd);
1939 /* Checks string for bad characters and returns TRUE if they are found. */
1941 static int silc_server_command_bad_chars(char *nick)
1945 for (i = 0; i < strlen(nick); i++) {
1946 if (!isascii(nick[i]))
1948 if (nick[i] <= 32) return TRUE;
1949 if (nick[i] == ' ') return TRUE;
1950 if (nick[i] == '*') return TRUE;
1951 if (nick[i] == '?') return TRUE;
1952 if (nick[i] == ',') return TRUE;
1958 /* Server side of command NICK. Sets nickname for user. Setting
1959 nickname causes generation of a new client ID for the client. The
1960 new client ID is sent to the client after changing the nickname. */
1962 SILC_SERVER_CMD_FUNC(nick)
1964 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1965 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1966 SilcServer server = cmd->server;
1967 SilcBuffer packet, nidp, oidp = NULL;
1968 SilcClientID *new_id;
1970 uint16 ident = silc_command_get_ident(cmd->payload);
1973 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1976 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1978 /* Check nickname */
1979 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1980 if (silc_server_command_bad_chars(nick) == TRUE) {
1981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1982 SILC_STATUS_ERR_BAD_NICKNAME);
1986 if (strlen(nick) > 128)
1989 /* Check for same nickname */
1990 if (!strcmp(client->nickname, nick)) {
1991 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1995 /* Create new Client ID */
1996 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1998 cmd->server->md5hash, nick,
2001 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2004 /* Send notify about nickname change to our router. We send the new
2005 ID and ask to replace it with the old one. If we are router the
2006 packet is broadcasted. Send NICK_CHANGE notify. */
2007 if (!server->standalone)
2008 silc_server_send_notify_nick_change(server, server->router->connection,
2009 server->server_type == SILC_SERVER ?
2010 FALSE : TRUE, client->id,
2013 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2015 /* Remove old cache entry */
2016 silc_idcache_del_by_context(server->local_list->clients, client);
2019 silc_free(client->id);
2021 /* Save the nickname as this client is our local client */
2022 silc_free(client->nickname);
2024 client->nickname = strdup(nick);
2025 client->id = new_id;
2027 /* Update client cache */
2028 silc_idcache_add(server->local_list->clients, client->nickname,
2029 client->id, (void *)client, 0, NULL);
2031 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2033 /* Send NICK_CHANGE notify to the client's channels */
2034 silc_server_send_notify_on_channels(server, NULL, client,
2035 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2036 oidp->data, oidp->len,
2037 nidp->data, nidp->len);
2040 /* Send the new Client ID as reply command back to client */
2041 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2042 SILC_STATUS_OK, ident, 1,
2043 2, nidp->data, nidp->len);
2044 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2045 0, packet->data, packet->len, FALSE);
2047 silc_buffer_free(packet);
2048 silc_buffer_free(nidp);
2050 silc_buffer_free(oidp);
2053 silc_server_command_free(cmd);
2056 /* Sends the LIST command reply */
2059 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2060 SilcChannelEntry *lch,
2062 SilcChannelEntry *gch,
2066 SilcBuffer packet, idp;
2067 SilcChannelEntry entry;
2068 SilcCommandStatus status;
2069 uint16 ident = silc_command_get_ident(cmd->payload);
2071 unsigned char usercount[4];
2074 for (i = 0; i < lch_count; i++)
2075 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2077 for (i = 0; i < gch_count; i++)
2078 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2081 status = SILC_STATUS_OK;
2082 if ((lch_count + gch_count) > 1)
2083 status = SILC_STATUS_LIST_START;
2086 for (i = 0; i < lch_count; i++) {
2092 status = SILC_STATUS_LIST_ITEM;
2093 if (i >= 1 && i == lch_count - 1 && !gch_count)
2094 status = SILC_STATUS_LIST_END;
2096 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2098 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2099 topic = "*private*";
2100 memset(usercount, 0, sizeof(usercount));
2102 topic = entry->topic;
2103 users = silc_hash_table_count(entry->user_list);
2104 SILC_PUT32_MSB(users, usercount);
2107 /* Send the reply */
2109 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2111 2, idp->data, idp->len,
2112 3, entry->channel_name,
2113 strlen(entry->channel_name),
2114 4, topic, topic ? strlen(topic) : 0,
2116 silc_server_packet_send(cmd->server, cmd->sock,
2117 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2118 packet->len, FALSE);
2119 silc_buffer_free(packet);
2120 silc_buffer_free(idp);
2124 for (i = 0; i < gch_count; i++) {
2130 status = SILC_STATUS_LIST_ITEM;
2131 if (i >= 1 && i == gch_count - 1)
2132 status = SILC_STATUS_LIST_END;
2134 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2136 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2137 topic = "*private*";
2138 memset(usercount, 0, sizeof(usercount));
2140 topic = entry->topic;
2141 users = silc_hash_table_count(entry->user_list);
2142 SILC_PUT32_MSB(users, usercount);
2145 /* Send the reply */
2147 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2149 2, idp->data, idp->len,
2150 3, entry->channel_name,
2151 strlen(entry->channel_name),
2152 4, topic, topic ? strlen(topic) : 0,
2154 silc_server_packet_send(cmd->server, cmd->sock,
2155 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2156 packet->len, FALSE);
2157 silc_buffer_free(packet);
2158 silc_buffer_free(idp);
2162 /* Server side of LIST command. This lists the channel of the requested
2163 server. Secret channels are not listed. */
2165 SILC_SERVER_CMD_FUNC(list)
2167 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2168 SilcServer server = cmd->server;
2169 SilcChannelID *channel_id = NULL;
2172 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2173 uint32 lch_count = 0, gch_count = 0;
2175 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2177 /* If we are normal server, send the command to router, since we
2178 want to know all channels in the network. */
2179 if (!cmd->pending && server->server_type == SILC_SERVER &&
2180 !server->standalone) {
2184 old_ident = silc_command_get_ident(cmd->payload);
2185 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2186 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2187 silc_server_packet_send(server, server->router->connection,
2188 SILC_PACKET_COMMAND, cmd->packet->flags,
2189 tmpbuf->data, tmpbuf->len, TRUE);
2191 /* Reprocess this packet after received reply from router */
2192 silc_server_command_pending(server, SILC_COMMAND_LIST,
2193 silc_command_get_ident(cmd->payload),
2194 silc_server_command_destructor,
2195 silc_server_command_list,
2196 silc_server_command_dup(cmd));
2197 cmd->pending = TRUE;
2198 silc_command_set_ident(cmd->payload, old_ident);
2199 silc_buffer_free(tmpbuf);
2203 /* Get Channel ID */
2204 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2206 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2209 SILC_STATUS_ERR_NO_CHANNEL_ID);
2214 /* Get the channels from local list */
2215 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2218 /* Get the channels from global list */
2219 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2222 /* Send the reply */
2223 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2224 gchannels, gch_count);
2226 silc_free(lchannels);
2227 silc_free(gchannels);
2230 silc_server_command_free(cmd);
2233 /* Server side of TOPIC command. Sets topic for channel and/or returns
2234 current topic to client. */
2236 SILC_SERVER_CMD_FUNC(topic)
2238 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2239 SilcServer server = cmd->server;
2240 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2241 SilcChannelID *channel_id;
2242 SilcChannelEntry channel;
2243 SilcChannelClientEntry chl;
2244 SilcBuffer packet, idp;
2246 uint32 argc, tmp_len;
2247 uint16 ident = silc_command_get_ident(cmd->payload);
2249 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2251 argc = silc_argument_get_arg_num(cmd->args);
2253 /* Get Channel ID */
2254 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2257 SILC_STATUS_ERR_NO_CHANNEL_ID);
2260 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2263 SILC_STATUS_ERR_NO_CHANNEL_ID);
2267 /* Check whether the channel exists */
2268 channel = silc_idlist_find_channel_by_id(server->local_list,
2271 channel = silc_idlist_find_channel_by_id(server->global_list,
2274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2275 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2282 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2285 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2289 if (strlen(tmp) > 256) {
2290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2291 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2295 /* See whether the client is on channel and has rights to change topic */
2296 if (!silc_hash_table_find(channel->user_list, client, NULL,
2298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2299 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2303 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2304 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2306 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2311 /* Set the topic for channel */
2312 silc_free(channel->topic);
2313 channel->topic = strdup(tmp);
2315 /* Send TOPIC_SET notify type to the network */
2316 if (!server->standalone)
2317 silc_server_send_notify_topic_set(server, server->router->connection,
2318 server->server_type == SILC_ROUTER ?
2319 TRUE : FALSE, channel,
2320 client->id, SILC_ID_CLIENT,
2323 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2325 /* Send notify about topic change to all clients on the channel */
2326 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2327 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2328 idp->data, idp->len,
2329 channel->topic, strlen(channel->topic));
2330 silc_buffer_free(idp);
2333 /* Send the topic to client as reply packet */
2334 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2335 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2336 SILC_STATUS_OK, ident, 2,
2337 2, idp->data, idp->len,
2340 strlen(channel->topic) : 0);
2341 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2342 0, packet->data, packet->len, FALSE);
2344 silc_buffer_free(packet);
2345 silc_buffer_free(idp);
2346 silc_free(channel_id);
2349 silc_server_command_free(cmd);
2352 /* Server side of INVITE command. Invites some client to join some channel.
2353 This command is also used to manage the invite list of the channel. */
2355 SILC_SERVER_CMD_FUNC(invite)
2357 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2358 SilcServer server = cmd->server;
2359 SilcSocketConnection sock = cmd->sock, dest_sock;
2360 SilcChannelClientEntry chl;
2361 SilcClientEntry sender, dest;
2362 SilcClientID *dest_id = NULL;
2363 SilcChannelEntry channel;
2364 SilcChannelID *channel_id = NULL;
2365 SilcIDListData idata;
2366 SilcBuffer idp, idp2, packet;
2367 unsigned char *tmp, *add, *del;
2369 uint16 ident = silc_command_get_ident(cmd->payload);
2371 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2373 /* Get Channel ID */
2374 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2377 SILC_STATUS_ERR_NO_CHANNEL_ID);
2380 channel_id = silc_id_payload_parse_id(tmp, len);
2382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2383 SILC_STATUS_ERR_NO_CHANNEL_ID);
2387 /* Get the channel entry */
2388 channel = silc_idlist_find_channel_by_id(server->local_list,
2391 channel = silc_idlist_find_channel_by_id(server->global_list,
2394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2395 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2400 /* Check whether the sender of this command is on the channel. */
2401 sender = (SilcClientEntry)sock->user_data;
2402 if (!silc_server_client_on_channel(sender, channel)) {
2403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2404 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2408 /* Check whether the channel is invite-only channel. If yes then the
2409 sender of this command must be at least channel operator. */
2410 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2411 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2412 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2414 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2419 /* Get destination client ID */
2420 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2424 dest_id = silc_id_payload_parse_id(tmp, len);
2426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2427 SILC_STATUS_ERR_NO_CLIENT_ID);
2431 /* Get the client entry */
2432 dest = silc_server_get_client_resolve(server, dest_id);
2434 if (server->server_type != SILC_SERVER) {
2435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2436 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2440 /* The client info is being resolved. Reprocess this packet after
2441 receiving the reply to the query. */
2442 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2444 silc_server_command_destructor,
2445 silc_server_command_invite,
2446 silc_server_command_dup(cmd));
2447 cmd->pending = TRUE;
2448 silc_free(channel_id);
2453 /* Check whether the requested client is already on the channel. */
2454 if (silc_server_client_on_channel(dest, channel)) {
2455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2456 SILC_STATUS_ERR_USER_ON_CHANNEL);
2460 /* Get route to the client */
2461 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2464 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2468 memset(invite, 0, sizeof(invite));
2469 strncat(invite, dest->nickname, strlen(dest->nickname));
2470 strncat(invite, "!", 1);
2471 strncat(invite, dest->username, strlen(dest->username));
2472 if (!strchr(dest->username, '@')) {
2473 strncat(invite, "@", 1);
2474 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2477 len = strlen(invite);
2478 if (!channel->invite_list)
2479 channel->invite_list = silc_calloc(len + 2,
2480 sizeof(*channel->invite_list));
2482 channel->invite_list = silc_realloc(channel->invite_list,
2483 sizeof(*channel->invite_list) *
2485 strlen(channel->invite_list) + 2));
2486 strncat(channel->invite_list, invite, len);
2487 strncat(channel->invite_list, ",", 1);
2489 /* Send notify to the client that is invited to the channel */
2490 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2491 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2492 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2494 SILC_NOTIFY_TYPE_INVITE, 3,
2495 idp->data, idp->len,
2496 channel->channel_name,
2497 strlen(channel->channel_name),
2498 idp2->data, idp2->len);
2499 silc_buffer_free(idp);
2500 silc_buffer_free(idp2);
2503 /* Add the client to the invite list of the channel */
2504 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2506 if (!channel->invite_list)
2507 channel->invite_list = silc_calloc(len + 2,
2508 sizeof(*channel->invite_list));
2510 channel->invite_list = silc_realloc(channel->invite_list,
2511 sizeof(*channel->invite_list) *
2513 strlen(channel->invite_list) + 2));
2514 if (add[len - 1] == ',')
2515 add[len - 1] = '\0';
2517 strncat(channel->invite_list, add, len);
2518 strncat(channel->invite_list, ",", 1);
2521 /* Get the invite to be removed and remove it from the list */
2522 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2523 if (del && channel->invite_list) {
2524 char *start, *end, *n;
2526 if (!strncmp(channel->invite_list, del,
2527 strlen(channel->invite_list) - 1)) {
2528 silc_free(channel->invite_list);
2529 channel->invite_list = NULL;
2531 start = strstr(channel->invite_list, del);
2532 if (start && strlen(start) >= len) {
2534 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2535 strncat(n, channel->invite_list, start - channel->invite_list);
2536 strncat(n, end + 1, ((channel->invite_list +
2537 strlen(channel->invite_list)) - end) - 1);
2538 silc_free(channel->invite_list);
2539 channel->invite_list = n;
2544 /* Send notify to the primary router */
2545 if (!server->standalone)
2546 silc_server_send_notify_invite(server, server->router->connection,
2547 server->server_type == SILC_ROUTER ?
2548 TRUE : FALSE, channel,
2549 sender->id, add, del);
2551 /* Send command reply */
2552 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2556 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2557 SILC_STATUS_OK, ident, 2,
2559 3, channel->invite_list,
2560 channel->invite_list ?
2561 strlen(channel->invite_list) : 0);
2564 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2565 SILC_STATUS_OK, ident, 1,
2567 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2568 packet->data, packet->len, FALSE);
2569 silc_buffer_free(packet);
2573 silc_free(channel_id);
2574 silc_server_command_free(cmd);
2579 SilcSocketConnection sock;
2583 /* Quits connection to client. This gets called if client won't
2584 close the connection even when it has issued QUIT command. */
2586 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2588 QuitInternal q = (QuitInternal)context;
2590 /* Free all client specific data, such as client entry and entires
2591 on channels this client may be on. */
2592 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2594 q->sock->user_data = NULL;
2596 /* Close the connection on our side */
2597 silc_server_close_connection(q->server, q->sock);
2599 silc_free(q->signoff);
2603 /* Quits SILC session. This is the normal way to disconnect client. */
2605 SILC_SERVER_CMD_FUNC(quit)
2607 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2608 SilcServer server = cmd->server;
2609 SilcSocketConnection sock = cmd->sock;
2611 unsigned char *tmp = NULL;
2614 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2616 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2619 /* Get destination ID */
2620 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2624 q = silc_calloc(1, sizeof(*q));
2627 q->signoff = tmp ? strdup(tmp) : NULL;
2629 /* We quit the connection with little timeout */
2630 silc_schedule_task_add(server->schedule, sock->sock,
2631 silc_server_command_quit_cb, (void *)q,
2632 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2635 silc_server_command_free(cmd);
2638 /* Server side of command KILL. This command is used by router operator
2639 to remove an client from the SILC Network temporarily. */
2641 SILC_SERVER_CMD_FUNC(kill)
2643 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2644 SilcServer server = cmd->server;
2645 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2646 SilcClientEntry remote_client;
2647 SilcClientID *client_id;
2648 unsigned char *tmp, *comment;
2649 uint32 tmp_len, tmp_len2;
2651 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2653 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2656 /* KILL command works only on router */
2657 if (server->server_type != SILC_ROUTER) {
2658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2659 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2663 /* Check whether client has the permissions. */
2664 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2666 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2670 /* Get the client ID */
2671 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2674 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2677 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2680 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2684 /* Get the client entry */
2685 remote_client = silc_idlist_find_client_by_id(server->local_list,
2686 client_id, TRUE, NULL);
2687 if (!remote_client) {
2688 remote_client = silc_idlist_find_client_by_id(server->global_list,
2689 client_id, TRUE, NULL);
2690 if (!remote_client) {
2691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2692 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2698 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2702 /* Send reply to the sender */
2703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2706 /* Send the KILL notify packets. First send it to the channel, then
2707 to our primary router and then directly to the client who is being
2708 killed right now. */
2710 /* Send KILLED notify to the channels. It is not sent to the client
2711 as it will be sent differently destined directly to the client and not
2713 silc_server_send_notify_on_channels(server, remote_client,
2714 remote_client, SILC_NOTIFY_TYPE_KILLED,
2717 comment, comment ? tmp_len2 : 0);
2719 /* Send KILLED notify to primary route */
2720 if (!server->standalone)
2721 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2722 remote_client->id, comment);
2724 /* Send KILLED notify to the client directly */
2725 silc_server_send_notify_killed(server, remote_client->connection ?
2726 remote_client->connection :
2727 remote_client->router->connection, FALSE,
2728 remote_client->id, comment);
2730 /* Remove the client from all channels. This generates new keys to the
2731 channels as well. */
2732 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2735 /* Remove the client entry, If it is locally connected then we will also
2736 disconnect the client here */
2737 if (remote_client->connection) {
2738 /* Remove locally conneted client */
2739 SilcSocketConnection sock = remote_client->connection;
2740 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2741 silc_server_close_connection(server, sock);
2743 /* Remove remote client */
2744 if (!silc_idlist_del_client(server->global_list, remote_client))
2745 silc_idlist_del_client(server->local_list, remote_client);
2749 silc_server_command_free(cmd);
2752 /* Server side of command INFO. This sends information about us to
2753 the client. If client requested specific server we will send the
2754 command to that server. */
2756 SILC_SERVER_CMD_FUNC(info)
2758 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2759 SilcServer server = cmd->server;
2760 SilcBuffer packet, idp;
2763 char *dest_server, *server_info = NULL, *server_name;
2764 uint16 ident = silc_command_get_ident(cmd->payload);
2765 SilcServerEntry entry = NULL;
2766 SilcServerID *server_id = NULL;
2768 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2770 /* Get server name */
2771 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2774 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2776 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2779 SILC_STATUS_ERR_NO_SERVER_ID);
2785 /* Check whether we have this server cached */
2786 entry = silc_idlist_find_server_by_id(server->local_list,
2787 server_id, TRUE, NULL);
2789 entry = silc_idlist_find_server_by_id(server->global_list,
2790 server_id, TRUE, NULL);
2791 if (!entry && server->server_type != SILC_SERVER) {
2792 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2793 SILC_STATUS_ERR_NO_SUCH_SERVER);
2799 /* Some buggy servers has sent request to router about themselves. */
2800 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2803 if ((!dest_server && !server_id && !entry) || (entry &&
2804 entry == server->id_entry) ||
2805 (dest_server && !cmd->pending &&
2806 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2807 /* Send our reply */
2808 char info_string[256];
2810 memset(info_string, 0, sizeof(info_string));
2811 snprintf(info_string, sizeof(info_string),
2812 "location: %s server: %s admin: %s <%s>",
2813 server->config->admin_info->location,
2814 server->config->admin_info->server_type,
2815 server->config->admin_info->admin_name,
2816 server->config->admin_info->admin_email);
2818 server_info = info_string;
2819 entry = server->id_entry;
2821 /* Check whether we have this server cached */
2822 if (!entry && dest_server) {
2823 entry = silc_idlist_find_server_by_name(server->global_list,
2824 dest_server, TRUE, NULL);
2826 entry = silc_idlist_find_server_by_name(server->local_list,
2827 dest_server, TRUE, NULL);
2831 if (!cmd->pending &&
2832 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2833 /* Send to the server */
2837 old_ident = silc_command_get_ident(cmd->payload);
2838 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2839 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2841 silc_server_packet_send(server, entry->connection,
2842 SILC_PACKET_COMMAND, cmd->packet->flags,
2843 tmpbuf->data, tmpbuf->len, TRUE);
2845 /* Reprocess this packet after received reply from router */
2846 silc_server_command_pending(server, SILC_COMMAND_INFO,
2847 silc_command_get_ident(cmd->payload),
2848 silc_server_command_destructor,
2849 silc_server_command_info,
2850 silc_server_command_dup(cmd));
2851 cmd->pending = TRUE;
2852 silc_command_set_ident(cmd->payload, old_ident);
2853 silc_buffer_free(tmpbuf);
2857 if (!entry && !cmd->pending && !server->standalone) {
2858 /* Send to the primary router */
2862 old_ident = silc_command_get_ident(cmd->payload);
2863 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2864 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2866 silc_server_packet_send(server, server->router->connection,
2867 SILC_PACKET_COMMAND, cmd->packet->flags,
2868 tmpbuf->data, tmpbuf->len, TRUE);
2870 /* Reprocess this packet after received reply from router */
2871 silc_server_command_pending(server, SILC_COMMAND_INFO,
2872 silc_command_get_ident(cmd->payload),
2873 silc_server_command_destructor,
2874 silc_server_command_info,
2875 silc_server_command_dup(cmd));
2876 cmd->pending = TRUE;
2877 silc_command_set_ident(cmd->payload, old_ident);
2878 silc_buffer_free(tmpbuf);
2883 silc_free(server_id);
2886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2887 SILC_STATUS_ERR_NO_SUCH_SERVER);
2891 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2893 server_info = entry->server_info;
2894 server_name = entry->server_name;
2896 /* Send the reply */
2897 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2898 SILC_STATUS_OK, ident, 3,
2899 2, idp->data, idp->len,
2901 strlen(server_name),
2904 strlen(server_info) : 0);
2905 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2906 packet->data, packet->len, FALSE);
2908 silc_buffer_free(packet);
2909 silc_buffer_free(idp);
2912 silc_server_command_free(cmd);
2915 /* Server side of command PING. This just replies to the ping. */
2917 SILC_SERVER_CMD_FUNC(ping)
2919 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2920 SilcServer server = cmd->server;
2925 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2928 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2931 SILC_STATUS_ERR_NO_SERVER_ID);
2934 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2938 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2939 /* Send our reply */
2940 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2944 SILC_STATUS_ERR_NO_SUCH_SERVER);
2951 silc_server_command_free(cmd);
2954 /* Internal routine to join channel. The channel sent to this function
2955 has been either created or resolved from ID lists. This joins the sent
2956 client to the channel. */
2958 static void silc_server_command_join_channel(SilcServer server,
2959 SilcServerCommandContext cmd,
2960 SilcChannelEntry channel,
2961 SilcClientID *client_id,
2965 const unsigned char *auth,
2968 SilcSocketConnection sock = cmd->sock;
2970 uint32 tmp_len, user_count;
2971 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2972 SilcClientEntry client;
2973 SilcChannelClientEntry chl;
2974 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2975 uint16 ident = silc_command_get_ident(cmd->payload);
2976 char check[512], check2[512];
2977 bool founder = FALSE;
2979 SILC_LOG_DEBUG(("Start"));
2984 /* Get the client entry */
2985 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2986 client = (SilcClientEntry)sock->user_data;
2988 client = silc_server_get_client_resolve(server, client_id);
2993 /* The client info is being resolved. Reprocess this packet after
2994 receiving the reply to the query. */
2995 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2996 server->cmd_ident, NULL,
2997 silc_server_command_join,
2998 silc_server_command_dup(cmd));
2999 cmd->pending = TRUE;
3003 cmd->pending = FALSE;
3007 * Check founder auth payload if provided. If client can gain founder
3008 * privileges it can override various conditions on joining the channel,
3009 * and can have directly the founder mode set on the channel.
3011 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3012 SilcIDListData idata = (SilcIDListData)client;
3014 if (channel->founder_key && idata->public_key &&
3015 silc_pkcs_public_key_compare(channel->founder_key,
3016 idata->public_key)) {
3017 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3018 (void *)channel->founder_passwd :
3019 (void *)channel->founder_key);
3020 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3021 channel->founder_passwd_len : 0);
3023 /* Check whether the client is to become founder */
3024 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3025 auth_data, auth_data_len,
3026 idata->hash, client->id, SILC_ID_CLIENT)) {
3027 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3034 * Check channel modes
3038 memset(check, 0, sizeof(check));
3039 memset(check2, 0, sizeof(check2));
3040 strncat(check, client->nickname, strlen(client->nickname));
3041 strncat(check, "!", 1);
3042 strncat(check, client->username, strlen(client->username));
3043 if (!strchr(client->username, '@')) {
3044 strncat(check, "@", 1);
3045 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3048 strncat(check2, client->nickname, strlen(client->nickname));
3049 if (!strchr(client->nickname, '@')) {
3050 strncat(check2, "@", 1);
3051 strncat(check2, server->server_name, strlen(server->server_name));
3053 strncat(check2, "!", 1);
3054 strncat(check2, client->username, strlen(client->username));
3055 if (!strchr(client->username, '@')) {
3056 strncat(check2, "@", 1);
3057 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3060 /* Check invite list if channel is invite-only channel */
3061 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3062 if (!channel->invite_list ||
3063 (!silc_string_match(channel->invite_list, check) &&
3064 !silc_string_match(channel->invite_list, check2))) {
3065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3066 SILC_STATUS_ERR_NOT_INVITED);
3071 /* Check ban list if it exists. If the client's nickname, server,
3072 username and/or hostname is in the ban list the access to the
3073 channel is denied. */
3074 if (channel->ban_list) {
3075 if (!channel->ban_list ||
3076 silc_string_match(channel->ban_list, check) ||
3077 silc_string_match(channel->ban_list, check2)) {
3078 silc_server_command_send_status_reply(
3079 cmd, SILC_COMMAND_JOIN,
3080 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3085 /* Check user count limit if set. */
3086 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3087 if (silc_hash_table_count(channel->user_list) + 1 >
3088 channel->user_limit) {
3089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3090 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3096 /* Check the channel passphrase if set. */
3097 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3098 /* Get passphrase */
3099 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3101 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3102 memcpy(passphrase, tmp, tmp_len);
3105 if (!passphrase || !channel->passphrase ||
3106 memcmp(channel->passphrase, passphrase,
3107 strlen(channel->passphrase))) {
3108 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3109 SILC_STATUS_ERR_BAD_PASSWORD);
3115 * Client is allowed to join to the channel. Make it happen.
3118 /* Check whether the client already is on the channel */
3119 if (silc_server_client_on_channel(client, channel)) {
3120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3121 SILC_STATUS_ERR_USER_ON_CHANNEL);
3125 /* Generate new channel key as protocol dictates */
3127 if (!silc_server_create_channel_key(server, channel, 0))
3130 /* Send the channel key. This is broadcasted to the channel but is not
3131 sent to the client who is joining to the channel. */
3132 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3133 silc_server_send_channel_key(server, NULL, channel,
3134 server->server_type == SILC_ROUTER ?
3135 FALSE : !server->standalone);
3138 /* Join the client to the channel by adding it to channel's user list.
3139 Add also the channel to client entry's channels list for fast cross-
3141 chl = silc_calloc(1, sizeof(*chl));
3143 chl->client = client;
3144 chl->channel = channel;
3145 silc_hash_table_add(channel->user_list, client, chl);
3146 silc_hash_table_add(client->channels, channel, chl);
3148 /* Get users on the channel */
3149 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3152 /* Encode Client ID Payload of the original client who wants to join */
3153 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3155 /* Encode command reply packet */
3156 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3157 SILC_PUT32_MSB(channel->mode, mode);
3158 SILC_PUT32_MSB(created, tmp2);
3159 SILC_PUT32_MSB(user_count, tmp3);
3161 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3162 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3163 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3164 strlen(channel->channel_key->
3166 channel->channel_key->cipher->name,
3167 channel->key_len / 8, channel->key);
3172 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3173 SILC_STATUS_OK, ident, 13,
3174 2, channel->channel_name,
3175 strlen(channel->channel_name),
3176 3, chidp->data, chidp->len,
3177 4, clidp->data, clidp->len,
3180 7, keyp ? keyp->data : NULL,
3181 keyp ? keyp->len : 0,
3182 8, channel->ban_list,
3184 strlen(channel->ban_list) : 0,
3185 9, channel->invite_list,
3186 channel->invite_list ?
3187 strlen(channel->invite_list) : 0,
3190 strlen(channel->topic) : 0,
3191 11, silc_hmac_get_name(channel->hmac),
3192 strlen(silc_hmac_get_name(channel->
3195 13, user_list->data, user_list->len,
3196 14, mode_list->data,
3199 /* Send command reply */
3200 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3201 reply->data, reply->len, FALSE);
3203 /* Send JOIN notify to locally connected clients on the channel. If
3204 we are normal server then router will send or have sent JOIN notify
3205 already. However since we've added the client already to our channel
3206 we'll ignore it (in packet_receive.c) so we must send it here. If
3207 we are router then this will send it to local clients and local
3209 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3210 SILC_NOTIFY_TYPE_JOIN, 2,
3211 clidp->data, clidp->len,
3212 chidp->data, chidp->len);
3214 if (!cmd->pending) {
3215 /* Send JOIN notify packet to our primary router */
3216 if (!server->standalone)
3217 silc_server_send_notify_join(server, server->router->connection,
3218 server->server_type == SILC_ROUTER ?
3219 TRUE : FALSE, channel, client->id);
3222 /* Distribute the channel key to all backup routers. */
3223 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3224 keyp->data, keyp->len, FALSE, TRUE);
3226 /* If client became founder by providing correct founder auth data
3227 notify the mode change to the channel. */
3229 SILC_PUT32_MSB(chl->mode, mode);
3230 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3231 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3232 clidp->data, clidp->len,
3233 mode, 4, clidp->data, clidp->len);
3235 /* Set CUMODE notify type to network */
3236 if (!server->standalone)
3237 silc_server_send_notify_cumode(server, server->router->connection,
3238 server->server_type == SILC_ROUTER ?
3239 TRUE : FALSE, channel,
3240 chl->mode, client->id, SILC_ID_CLIENT,
3245 silc_buffer_free(reply);
3246 silc_buffer_free(clidp);
3247 silc_buffer_free(chidp);
3248 silc_buffer_free(keyp);
3249 silc_buffer_free(user_list);
3250 silc_buffer_free(mode_list);
3253 silc_free(passphrase);
3256 /* Server side of command JOIN. Joins client into requested channel. If
3257 the channel does not exist it will be created. */
3259 SILC_SERVER_CMD_FUNC(join)
3261 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3262 SilcServer server = cmd->server;
3263 unsigned char *auth;
3264 uint32 tmp_len, auth_len;
3265 char *tmp, *channel_name = NULL, *cipher, *hmac;
3266 SilcChannelEntry channel;
3268 bool created = FALSE, create_key = TRUE;
3269 SilcClientID *client_id;
3271 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3273 /* Get channel name */
3274 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3282 if (strlen(channel_name) > 256)
3283 channel_name[255] = '\0';
3285 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3287 SILC_STATUS_ERR_BAD_CHANNEL);
3291 /* Get Client ID of the client who is joining to the channel */
3292 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3295 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3298 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3301 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3305 /* Get cipher, hmac name and auth payload */
3306 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3307 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3308 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3310 /* See if the channel exists */
3311 channel = silc_idlist_find_channel_by_name(server->local_list,
3312 channel_name, NULL);
3314 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3315 /* If this is coming from client the Client ID in the command packet must
3316 be same as the client's ID. */
3317 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3318 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3319 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3321 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3326 if (!channel || channel->disabled) {
3327 /* Channel not found */
3329 /* If we are standalone server we don't have a router, we just create
3330 the channel by ourselves. */
3331 if (server->standalone) {
3332 channel = silc_server_create_new_channel(server, server->id, cipher,
3333 hmac, channel_name, TRUE);
3335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3336 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3340 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3346 /* The channel does not exist on our server. If we are normal server
3347 we will send JOIN command to our router which will handle the
3348 joining procedure (either creates the channel if it doesn't exist
3349 or joins the client to it). */
3350 if (server->server_type != SILC_ROUTER) {
3354 /* If this is pending command callback then we've resolved
3355 it and it didn't work, return since we've notified the
3356 client already in the command reply callback. */
3360 old_ident = silc_command_get_ident(cmd->payload);
3361 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3362 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3364 /* Send JOIN command to our router */
3365 silc_server_packet_send(server, (SilcSocketConnection)
3366 server->router->connection,
3367 SILC_PACKET_COMMAND, cmd->packet->flags,
3368 tmpbuf->data, tmpbuf->len, TRUE);
3370 /* Reprocess this packet after received reply from router */
3371 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3372 silc_command_get_ident(cmd->payload),
3373 silc_server_command_destructor,
3374 silc_server_command_join,
3375 silc_server_command_dup(cmd));
3376 cmd->pending = TRUE;
3380 /* We are router and the channel does not seem exist so we will check
3381 our global list as well for the channel. */
3382 channel = silc_idlist_find_channel_by_name(server->global_list,
3383 channel_name, NULL);
3385 /* Channel really does not exist, create it */
3386 channel = silc_server_create_new_channel(server, server->id, cipher,
3387 hmac, channel_name, TRUE);
3389 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3390 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3394 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3402 /* Channel not found */
3404 /* If the command came from router and we are normal server then
3405 something went wrong with the joining as the channel was not found.
3406 We can't do anything else but ignore this. */
3407 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3408 server->server_type != SILC_ROUTER)
3411 /* We are router and the channel does not seem exist so we will check
3412 our global list as well for the channel. */
3413 channel = silc_idlist_find_channel_by_name(server->global_list,
3414 channel_name, NULL);
3416 /* Channel really does not exist, create it */
3417 channel = silc_server_create_new_channel(server, server->id, cipher,
3418 hmac, channel_name, TRUE);
3420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3421 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3425 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3432 /* Check whether the channel was created by our router */
3433 if (cmd->pending && context2) {
3434 SilcServerCommandReplyContext reply =
3435 (SilcServerCommandReplyContext)context2;
3436 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3437 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3438 SILC_GET32_MSB(created, tmp);
3439 create_key = FALSE; /* Router returned the key already */
3443 /* If the channel does not have global users and is also empty the client
3444 will be the channel founder and operator. */
3445 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3446 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3448 /* Join to the channel */
3449 silc_server_command_join_channel(server, cmd, channel, client_id,
3450 created, create_key, umode,
3453 silc_free(client_id);
3456 silc_server_command_free(cmd);
3459 /* Server side of command MOTD. Sends server's current "message of the
3460 day" to the client. */
3462 SILC_SERVER_CMD_FUNC(motd)
3464 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3465 SilcServer server = cmd->server;
3466 SilcBuffer packet, idp;
3467 char *motd, *dest_server;
3469 uint16 ident = silc_command_get_ident(cmd->payload);
3471 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3473 /* Get server name */
3474 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3477 SILC_STATUS_ERR_NO_SUCH_SERVER);
3481 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3484 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3486 if (server->config && server->config->motd &&
3487 server->config->motd->motd_file) {
3489 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3494 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3495 SILC_STATUS_OK, ident, 2,
3500 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3501 SILC_STATUS_OK, ident, 1,
3505 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3506 packet->data, packet->len, FALSE);
3507 silc_buffer_free(packet);
3508 silc_buffer_free(idp);
3510 SilcServerEntry entry;
3512 /* Check whether we have this server cached */
3513 entry = silc_idlist_find_server_by_name(server->global_list,
3514 dest_server, TRUE, NULL);
3516 entry = silc_idlist_find_server_by_name(server->local_list,
3517 dest_server, TRUE, NULL);
3520 if (server->server_type != SILC_SERVER && !cmd->pending &&
3521 entry && !entry->motd) {
3522 /* Send to the server */
3526 old_ident = silc_command_get_ident(cmd->payload);
3527 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3528 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3530 silc_server_packet_send(server, entry->connection,
3531 SILC_PACKET_COMMAND, cmd->packet->flags,
3532 tmpbuf->data, tmpbuf->len, TRUE);
3534 /* Reprocess this packet after received reply from router */
3535 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3536 silc_command_get_ident(cmd->payload),
3537 silc_server_command_destructor,
3538 silc_server_command_motd,
3539 silc_server_command_dup(cmd));
3540 cmd->pending = TRUE;
3541 silc_command_set_ident(cmd->payload, old_ident);
3542 silc_buffer_free(tmpbuf);
3546 if (!entry && !cmd->pending && !server->standalone) {
3547 /* Send to the primary router */
3551 old_ident = silc_command_get_ident(cmd->payload);
3552 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3553 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3555 silc_server_packet_send(server, server->router->connection,
3556 SILC_PACKET_COMMAND, cmd->packet->flags,
3557 tmpbuf->data, tmpbuf->len, TRUE);
3559 /* Reprocess this packet after received reply from router */
3560 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3561 silc_command_get_ident(cmd->payload),
3562 silc_server_command_destructor,
3563 silc_server_command_motd,
3564 silc_server_command_dup(cmd));
3565 cmd->pending = TRUE;
3566 silc_command_set_ident(cmd->payload, old_ident);
3567 silc_buffer_free(tmpbuf);
3572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3573 SILC_STATUS_ERR_NO_SUCH_SERVER);
3577 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3578 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3579 SILC_STATUS_OK, ident, 2,
3583 strlen(entry->motd) : 0);
3584 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3585 packet->data, packet->len, FALSE);
3586 silc_buffer_free(packet);
3587 silc_buffer_free(idp);
3591 silc_server_command_free(cmd);
3594 /* Server side of command UMODE. Client can use this command to set/unset
3595 user mode. Client actually cannot set itself to be as server/router
3596 operator so this can be used only to unset the modes. */
3598 SILC_SERVER_CMD_FUNC(umode)
3600 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3601 SilcServer server = cmd->server;
3602 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3604 unsigned char *tmp_mask;
3606 uint16 ident = silc_command_get_ident(cmd->payload);
3608 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3611 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3613 /* Get the client's mode mask */
3614 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3617 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3620 SILC_GET32_MSB(mask, tmp_mask);
3626 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3627 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3628 /* Cannot operator mode */
3629 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3630 SILC_STATUS_ERR_PERM_DENIED);
3634 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3635 /* Remove the server operator rights */
3636 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3639 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3640 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3641 /* Cannot operator mode */
3642 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3643 SILC_STATUS_ERR_PERM_DENIED);
3647 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3648 /* Remove the router operator rights */
3649 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3652 if (mask & SILC_UMODE_GONE) {
3653 client->mode |= SILC_UMODE_GONE;
3655 if (client->mode & SILC_UMODE_GONE)
3656 /* Remove the gone status */
3657 client->mode &= ~SILC_UMODE_GONE;
3660 /* Send UMODE change to primary router */
3661 if (!server->standalone)
3662 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3663 client->id, client->mode);
3665 /* Send command reply to sender */
3666 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3667 SILC_STATUS_OK, ident, 1,
3669 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3670 packet->data, packet->len, FALSE);
3671 silc_buffer_free(packet);
3674 silc_server_command_free(cmd);
3677 /* Checks that client has rights to add or remove channel modes. If any
3678 of the checks fails FALSE is returned. */
3680 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3681 SilcChannelClientEntry client,
3684 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3685 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3687 /* Check whether has rights to change anything */
3688 if (!is_op && !is_fo)
3691 /* Check whether has rights to change everything */
3695 /* We know that client is channel operator, check that they are not
3696 changing anything that requires channel founder rights. Rest of the
3697 modes are available automatically for channel operator. */
3699 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3700 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3701 if (is_op && !is_fo)
3704 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3705 if (is_op && !is_fo)
3710 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3711 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3712 if (is_op && !is_fo)
3715 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3716 if (is_op && !is_fo)
3721 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3722 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3723 if (is_op && !is_fo)
3726 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3727 if (is_op && !is_fo)
3732 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3733 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3734 if (is_op && !is_fo)
3737 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3738 if (is_op && !is_fo)
3746 /* Server side command of CMODE. Changes channel mode */
3748 SILC_SERVER_CMD_FUNC(cmode)
3750 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3751 SilcServer server = cmd->server;
3752 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3753 SilcIDListData idata = (SilcIDListData)client;
3754 SilcChannelID *channel_id;
3755 SilcChannelEntry channel;
3756 SilcChannelClientEntry chl;
3757 SilcBuffer packet, cidp;
3758 unsigned char *tmp, *tmp_id, *tmp_mask;
3759 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3760 uint32 mode_mask, tmp_len, tmp_len2;
3761 uint16 ident = silc_command_get_ident(cmd->payload);
3763 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3765 /* Get Channel ID */
3766 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3769 SILC_STATUS_ERR_NO_CHANNEL_ID);
3772 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3775 SILC_STATUS_ERR_NO_CHANNEL_ID);
3779 /* Get the channel mode mask */
3780 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3783 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3786 SILC_GET32_MSB(mode_mask, tmp_mask);
3788 /* Get channel entry */
3789 channel = silc_idlist_find_channel_by_id(server->local_list,
3792 channel = silc_idlist_find_channel_by_id(server->global_list,
3795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3796 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3801 /* Check whether this client is on the channel */
3802 if (!silc_server_client_on_channel(client, channel)) {
3803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3804 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3808 /* Get entry to the channel user list */
3809 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3811 /* Check that client has rights to change any requested channel modes */
3812 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3814 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3819 * Check the modes. Modes that requires nothing special operation are
3823 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3824 /* Channel uses private keys to protect traffic. Client(s) has set the
3825 key locally they want to use, server does not know that key. */
3826 /* Nothing interesting to do here */
3828 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3829 /* The mode is removed and we need to generate and distribute
3830 new channel key. Clients are not using private channel keys
3831 anymore after this. */
3833 /* Re-generate channel key */
3834 if (!silc_server_create_channel_key(server, channel, 0))
3837 /* Send the channel key. This sends it to our local clients and if
3838 we are normal server to our router as well. */
3839 silc_server_send_channel_key(server, NULL, channel,
3840 server->server_type == SILC_ROUTER ?
3841 FALSE : !server->standalone);
3843 cipher = channel->channel_key->cipher->name;
3844 hmac = (char *)silc_hmac_get_name(channel->hmac);
3848 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3849 /* User limit is set on channel */
3852 /* Get user limit */
3853 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3855 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3857 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3861 SILC_GET32_MSB(user_limit, tmp);
3862 channel->user_limit = user_limit;
3865 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3866 /* User limit mode is unset. Remove user limit */
3867 channel->user_limit = 0;
3870 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3871 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3872 /* Passphrase has been set to channel */
3874 /* Get the passphrase */
3875 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3878 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3882 /* Save the passphrase */
3883 passphrase = channel->passphrase = strdup(tmp);
3886 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3887 /* Passphrase mode is unset. remove the passphrase */
3888 if (channel->passphrase) {
3889 silc_free(channel->passphrase);
3890 channel->passphrase = NULL;
3895 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3896 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3897 /* Cipher to use protect the traffic */
3898 SilcCipher newkey, oldkey;
3901 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3904 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3908 /* Delete old cipher and allocate the new one */
3909 if (!silc_cipher_alloc(cipher, &newkey)) {
3910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3911 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3915 oldkey = channel->channel_key;
3916 channel->channel_key = newkey;
3918 /* Re-generate channel key */
3919 if (!silc_server_create_channel_key(server, channel, 0)) {
3920 /* We don't have new key, revert to old one */
3921 channel->channel_key = oldkey;
3925 /* Remove old channel key for good */
3926 silc_cipher_free(oldkey);
3928 /* Send the channel key. This sends it to our local clients and if
3929 we are normal server to our router as well. */
3930 silc_server_send_channel_key(server, NULL, channel,
3931 server->server_type == SILC_ROUTER ?
3932 FALSE : !server->standalone);
3935 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3936 /* Cipher mode is unset. Remove the cipher and revert back to
3938 SilcCipher newkey, oldkey;
3939 cipher = channel->cipher;
3941 /* Delete old cipher and allocate default one */
3942 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3944 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3948 oldkey = channel->channel_key;
3949 channel->channel_key = newkey;
3951 /* Re-generate channel key */
3952 if (!silc_server_create_channel_key(server, channel, 0)) {
3953 /* We don't have new key, revert to old one */
3954 channel->channel_key = oldkey;
3958 /* Remove old channel key for good */
3959 silc_cipher_free(oldkey);
3961 /* Send the channel key. This sends it to our local clients and if
3962 we are normal server to our router as well. */
3963 silc_server_send_channel_key(server, NULL, channel,
3964 server->server_type == SILC_ROUTER ?
3965 FALSE : !server->standalone);
3969 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3970 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3971 /* HMAC to use protect the traffic */
3972 unsigned char hash[32];
3976 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3978 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3979 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3983 /* Delete old hmac and allocate the new one */
3984 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3985 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3986 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3990 silc_hmac_free(channel->hmac);
3991 channel->hmac = newhmac;
3993 /* Set the HMAC key out of current channel key. The client must do
3995 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3996 channel->key_len / 8, hash);
3997 silc_hmac_set_key(channel->hmac, hash,
3998 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3999 memset(hash, 0, sizeof(hash));
4002 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4003 /* Hmac mode is unset. Remove the hmac and revert back to
4006 unsigned char hash[32];
4007 hmac = channel->hmac_name;
4009 /* Delete old hmac and allocate default one */
4010 silc_hmac_free(channel->hmac);
4011 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4013 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4017 silc_hmac_free(channel->hmac);
4018 channel->hmac = newhmac;
4020 /* Set the HMAC key out of current channel key. The client must do
4022 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4023 channel->key_len / 8,
4025 silc_hmac_set_key(channel->hmac, hash,
4026 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4027 memset(hash, 0, sizeof(hash));
4031 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4032 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4033 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4034 /* Set the founder authentication */
4035 SilcAuthPayload auth;
4037 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4040 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4044 auth = silc_auth_payload_parse(tmp, tmp_len);
4046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4047 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4051 /* Save the public key */
4052 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4053 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4056 channel->founder_method = silc_auth_get_method(auth);
4058 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4059 tmp = silc_auth_get_data(auth, &tmp_len);
4060 channel->founder_passwd =
4061 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4062 memcpy(channel->founder_passwd, tmp, tmp_len);
4063 channel->founder_passwd_len = tmp_len;
4065 /* Verify the payload before setting the mode */
4066 if (!silc_auth_verify(auth, channel->founder_method,
4067 channel->founder_key, 0, idata->hash,
4068 client->id, SILC_ID_CLIENT)) {
4069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4070 SILC_STATUS_ERR_AUTH_FAILED);
4075 silc_auth_payload_free(auth);
4079 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4080 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4081 if (channel->founder_key)
4082 silc_pkcs_public_key_free(channel->founder_key);
4083 if (channel->founder_passwd) {
4084 silc_free(channel->founder_passwd);
4085 channel->founder_passwd = NULL;
4091 /* Finally, set the mode */
4092 channel->mode = mode_mask;
4094 /* Send CMODE_CHANGE notify. */
4095 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4096 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4097 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4098 cidp->data, cidp->len,
4100 cipher, cipher ? strlen(cipher) : 0,
4101 hmac, hmac ? strlen(hmac) : 0,
4102 passphrase, passphrase ?
4103 strlen(passphrase) : 0);
4105 /* Set CMODE notify type to network */
4106 if (!server->standalone)
4107 silc_server_send_notify_cmode(server, server->router->connection,
4108 server->server_type == SILC_ROUTER ?
4109 TRUE : FALSE, channel,
4110 mode_mask, client->id, SILC_ID_CLIENT,
4111 cipher, hmac, passphrase);
4113 /* Send command reply to sender */
4114 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4115 SILC_STATUS_OK, ident, 2,
4116 2, tmp_id, tmp_len2,
4118 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4119 packet->data, packet->len, FALSE);
4121 silc_buffer_free(packet);
4122 silc_free(channel_id);
4123 silc_buffer_free(cidp);
4126 silc_server_command_free(cmd);
4129 /* Server side of CUMODE command. Changes client's mode on a channel. */
4131 SILC_SERVER_CMD_FUNC(cumode)
4133 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4134 SilcServer server = cmd->server;
4135 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4136 SilcIDListData idata = (SilcIDListData)client;
4137 SilcChannelID *channel_id;
4138 SilcClientID *client_id;
4139 SilcChannelEntry channel;
4140 SilcClientEntry target_client;
4141 SilcChannelClientEntry chl;
4142 SilcBuffer packet, idp;
4143 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4144 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4146 uint16 ident = silc_command_get_ident(cmd->payload);
4148 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4150 /* Get Channel ID */
4151 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4153 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4154 SILC_STATUS_ERR_NO_CHANNEL_ID);
4157 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4160 SILC_STATUS_ERR_NO_CHANNEL_ID);
4164 /* Get channel entry */
4165 channel = silc_idlist_find_channel_by_id(server->local_list,
4168 channel = silc_idlist_find_channel_by_id(server->global_list,
4171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4172 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4177 /* Check whether sender is on the channel */
4178 if (!silc_server_client_on_channel(client, channel)) {
4179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4180 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4184 /* Check that client has rights to change other's rights */
4185 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4186 sender_mask = chl->mode;
4188 /* Get the target client's channel mode mask */
4189 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4192 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4195 SILC_GET32_MSB(target_mask, tmp_mask);
4197 /* Get target Client ID */
4198 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4201 SILC_STATUS_ERR_NO_CLIENT_ID);
4204 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4206 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4207 SILC_STATUS_ERR_NO_CLIENT_ID);
4211 /* Get target client's entry */
4212 target_client = silc_idlist_find_client_by_id(server->local_list,
4213 client_id, TRUE, NULL);
4214 if (!target_client) {
4215 target_client = silc_idlist_find_client_by_id(server->global_list,
4216 client_id, TRUE, NULL);
4219 if (target_client != client &&
4220 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4221 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4223 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4227 /* Check whether target client is on the channel */
4228 if (target_client != client) {
4229 if (!silc_server_client_on_channel(target_client, channel)) {
4230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4231 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4235 /* Get entry to the channel user list */
4236 silc_hash_table_find(channel->user_list, target_client, NULL,
4244 /* If the target client is founder, no one else can change their mode
4246 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4247 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4248 SILC_STATUS_ERR_NOT_YOU);
4252 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4253 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4254 /* The client tries to claim the founder rights. */
4255 unsigned char *tmp_auth;
4256 uint32 tmp_auth_len, auth_len;
4259 if (target_client != client) {
4260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4261 SILC_STATUS_ERR_NOT_YOU);
4265 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4266 !channel->founder_key || !idata->public_key ||
4267 !silc_pkcs_public_key_compare(channel->founder_key,
4268 idata->public_key)) {
4269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4270 SILC_STATUS_ERR_NOT_YOU);
4274 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4281 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4282 (void *)channel->founder_passwd : (void *)channel->founder_key);
4283 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4284 channel->founder_passwd_len : 0);
4286 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4287 channel->founder_method, auth, auth_len,
4288 idata->hash, client->id, SILC_ID_CLIENT)) {
4289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4290 SILC_STATUS_ERR_AUTH_FAILED);
4294 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4298 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4299 if (target_client == client) {
4300 /* Remove channel founder rights from itself */
4301 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4305 SILC_STATUS_ERR_NOT_YOU);
4311 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4312 /* Promote to operator */
4313 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4314 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4315 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4317 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4321 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4325 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4326 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4327 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4329 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4333 /* Demote to normal user */
4334 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4339 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4340 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4342 /* Send notify to channel, notify only if mode was actually changed. */
4344 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4345 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4346 idp->data, idp->len,
4350 /* Set CUMODE notify type to network */
4351 if (!server->standalone)
4352 silc_server_send_notify_cumode(server, server->router->connection,
4353 server->server_type == SILC_ROUTER ?
4354 TRUE : FALSE, channel,
4355 target_mask, client->id,
4360 /* Send command reply to sender */
4361 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4362 SILC_STATUS_OK, ident, 3,
4364 3, tmp_ch_id, tmp_ch_len,
4365 4, tmp_id, tmp_len);
4366 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4367 packet->data, packet->len, FALSE);
4369 silc_buffer_free(packet);
4370 silc_free(channel_id);
4371 silc_free(client_id);
4372 silc_buffer_free(idp);
4375 silc_server_command_free(cmd);
4378 /* Server side of KICK command. Kicks client out of channel. */
4380 SILC_SERVER_CMD_FUNC(kick)
4382 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4383 SilcServer server = cmd->server;
4384 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4385 SilcClientEntry target_client;
4386 SilcChannelID *channel_id;
4387 SilcClientID *client_id;
4388 SilcChannelEntry channel;
4389 SilcChannelClientEntry chl;
4391 uint32 tmp_len, target_idp_len;
4392 unsigned char *tmp, *comment, *target_idp;
4394 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4396 /* Get Channel ID */
4397 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4400 SILC_STATUS_ERR_NO_CHANNEL_ID);
4403 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4406 SILC_STATUS_ERR_NO_CHANNEL_ID);
4410 /* Get channel entry */
4411 channel = silc_idlist_find_channel_by_id(server->local_list,
4414 channel = silc_idlist_find_channel_by_id(server->local_list,
4417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4418 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4423 /* Check whether sender is on the channel */
4424 if (!silc_server_client_on_channel(client, channel)) {
4425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4426 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4430 /* Check that the kicker is channel operator or channel founder */
4431 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4432 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4434 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4438 /* Get target Client ID */
4439 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4442 SILC_STATUS_ERR_NO_CLIENT_ID);
4445 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4448 SILC_STATUS_ERR_NO_CLIENT_ID);
4452 /* Get target client's entry */
4453 target_client = silc_idlist_find_client_by_id(server->local_list,
4454 client_id, TRUE, NULL);
4455 if (!target_client) {
4456 target_client = silc_idlist_find_client_by_id(server->global_list,
4457 client_id, TRUE, NULL);
4460 /* Check that the target client is not channel founder. Channel founder
4461 cannot be kicked from the channel. */
4462 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4463 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4465 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4469 /* Check whether target client is on the channel */
4470 if (!silc_server_client_on_channel(target_client, channel)) {
4471 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4472 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4478 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4482 /* Send command reply to sender */
4483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4486 /* Send KICKED notify to local clients on the channel */
4487 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4488 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4489 SILC_NOTIFY_TYPE_KICKED, 3,
4490 target_idp, target_idp_len,
4491 comment, comment ? strlen(comment) : 0,
4492 idp->data, idp->len);
4493 silc_buffer_free(idp);
4495 /* Remove the client from the channel. If the channel does not exist
4496 after removing the client then the client kicked itself off the channel
4497 and we don't have to send anything after that. */
4498 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4499 target_client, FALSE))
4502 /* Send KICKED notify to primary route */
4503 if (!server->standalone)
4504 silc_server_send_notify_kicked(server, server->router->connection,
4505 server->server_type == SILC_ROUTER ?
4506 TRUE : FALSE, channel,
4507 target_client->id, comment);
4509 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4510 /* Re-generate channel key */
4511 if (!silc_server_create_channel_key(server, channel, 0))
4514 /* Send the channel key to the channel. The key of course is not sent
4515 to the client who was kicked off the channel. */
4516 silc_server_send_channel_key(server, target_client->connection, channel,
4517 server->server_type == SILC_ROUTER ?
4518 FALSE : !server->standalone);
4522 silc_server_command_free(cmd);
4525 /* Server side of OPER command. Client uses this comand to obtain server
4526 operator privileges to this server/router. */
4528 SILC_SERVER_CMD_FUNC(oper)
4530 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4531 SilcServer server = cmd->server;
4532 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4533 unsigned char *username, *auth;
4535 SilcServerConfigSectionAdminConnection *admin;
4536 SilcIDListData idata = (SilcIDListData)client;
4538 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4540 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4543 /* Get the username */
4544 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4547 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4551 /* Get the admin configuration */
4552 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4553 username, client->nickname);
4555 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4556 username, client->nickname);
4558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4559 SILC_STATUS_ERR_AUTH_FAILED);
4564 /* Get the authentication payload */
4565 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4568 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4572 /* Verify the authentication data */
4573 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4574 admin->auth_data, admin->auth_data_len,
4575 idata->hash, client->id, SILC_ID_CLIENT)) {
4576 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4577 SILC_STATUS_ERR_AUTH_FAILED);
4581 /* Client is now server operator */
4582 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4584 /* Send UMODE change to primary router */
4585 if (!server->standalone)
4586 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4587 client->id, client->mode);
4589 /* Send reply to the sender */
4590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4594 silc_server_command_free(cmd);
4597 /* Server side of SILCOPER command. Client uses this comand to obtain router
4598 operator privileges to this router. */
4600 SILC_SERVER_CMD_FUNC(silcoper)
4602 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4603 SilcServer server = cmd->server;
4604 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4605 unsigned char *username, *auth;
4607 SilcServerConfigSectionAdminConnection *admin;
4608 SilcIDListData idata = (SilcIDListData)client;
4610 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4612 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4615 if (server->server_type != SILC_ROUTER) {
4616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4617 SILC_STATUS_ERR_AUTH_FAILED);
4621 /* Get the username */
4622 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4624 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4625 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4629 /* Get the admin configuration */
4630 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4631 username, client->nickname);
4633 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4634 username, client->nickname);
4636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4637 SILC_STATUS_ERR_AUTH_FAILED);
4642 /* Get the authentication payload */
4643 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4646 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4650 /* Verify the authentication data */
4651 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4652 admin->auth_data, admin->auth_data_len,
4653 idata->hash, client->id, SILC_ID_CLIENT)) {
4654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4655 SILC_STATUS_ERR_AUTH_FAILED);
4659 /* Client is now router operator */
4660 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4662 /* Send UMODE change to primary router */
4663 if (!server->standalone)
4664 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4665 client->id, client->mode);
4667 /* Send reply to the sender */
4668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4672 silc_server_command_free(cmd);
4675 /* Server side command of CONNECT. Connects us to the specified remote
4676 server or router. */
4678 SILC_SERVER_CMD_FUNC(connect)
4680 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4681 SilcServer server = cmd->server;
4682 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4683 unsigned char *tmp, *host;
4685 uint32 port = SILC_PORT;
4687 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4689 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4692 /* Check whether client has the permissions. */
4693 if (client->mode == SILC_UMODE_NONE) {
4694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4695 SILC_STATUS_ERR_NO_SERVER_PRIV);
4699 if (server->server_type == SILC_ROUTER &&
4700 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4702 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4706 /* Get the remote server */
4707 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4710 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4715 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4717 SILC_GET32_MSB(port, tmp);
4719 /* Create the connection. It is done with timeout and is async. */
4720 silc_server_create_connection(server, host, port);
4722 /* Send reply to the sender */
4723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4727 silc_server_command_free(cmd);
4730 /* Server side of command BAN. This is used to manage the ban list of the
4731 channel. To add clients and remove clients from the ban list. */
4733 SILC_SERVER_CMD_FUNC(ban)
4735 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4736 SilcServer server = cmd->server;
4737 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4739 SilcChannelEntry channel;
4740 SilcChannelClientEntry chl;
4741 SilcChannelID *channel_id = NULL;
4742 unsigned char *id, *add, *del;
4743 uint32 id_len, tmp_len;
4744 uint16 ident = silc_command_get_ident(cmd->payload);
4746 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4749 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4751 /* Get Channel ID */
4752 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4754 channel_id = silc_id_payload_parse_id(id, id_len);
4756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4757 SILC_STATUS_ERR_NO_CHANNEL_ID);
4762 /* Get channel entry. The server must know about the channel since the
4763 client is expected to be on the channel. */
4764 channel = silc_idlist_find_channel_by_id(server->local_list,
4767 channel = silc_idlist_find_channel_by_id(server->global_list,
4770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4771 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4776 /* Check whether this client is on the channel */
4777 if (!silc_server_client_on_channel(client, channel)) {
4778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4779 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4783 /* Get entry to the channel user list */
4784 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4786 /* The client must be at least channel operator. */
4787 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4789 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4793 /* Get the new ban and add it to the ban list */
4794 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4796 if (!channel->ban_list)
4797 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4799 channel->ban_list = silc_realloc(channel->ban_list,
4800 sizeof(*channel->ban_list) *
4802 strlen(channel->ban_list) + 2));
4803 if (add[tmp_len - 1] == ',')
4804 add[tmp_len - 1] = '\0';
4806 strncat(channel->ban_list, add, tmp_len);
4807 strncat(channel->ban_list, ",", 1);
4810 /* Get the ban to be removed and remove it from the list */
4811 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4812 if (del && channel->ban_list) {
4813 char *start, *end, *n;
4815 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4816 silc_free(channel->ban_list);
4817 channel->ban_list = NULL;
4819 start = strstr(channel->ban_list, del);
4820 if (start && strlen(start) >= tmp_len) {
4821 end = start + tmp_len;
4822 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4823 strncat(n, channel->ban_list, start - channel->ban_list);
4824 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4826 silc_free(channel->ban_list);
4827 channel->ban_list = n;
4832 /* Send the BAN notify type to our primary router. */
4833 if (!server->standalone && (add || del))
4834 silc_server_send_notify_ban(server, server->router->connection,
4835 server->server_type == SILC_ROUTER ?
4836 TRUE : FALSE, channel, add, del);
4838 /* Send the reply back to the client */
4840 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4841 SILC_STATUS_OK, ident, 2,
4843 3, channel->ban_list,
4845 strlen(channel->ban_list) - 1 : 0);
4846 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4847 packet->data, packet->len, FALSE);
4849 silc_buffer_free(packet);
4852 silc_free(channel_id);
4853 silc_server_command_free(cmd);
4856 /* Server side command of CLOSE. Closes connection to a specified server. */
4858 SILC_SERVER_CMD_FUNC(close)
4860 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4861 SilcServer server = cmd->server;
4862 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4863 SilcServerEntry server_entry;
4864 SilcSocketConnection sock;
4867 unsigned char *name;
4868 uint32 port = SILC_PORT;
4870 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4872 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4875 /* Check whether client has the permissions. */
4876 if (client->mode == SILC_UMODE_NONE) {
4877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4878 SILC_STATUS_ERR_NO_SERVER_PRIV);
4882 /* Get the remote server */
4883 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4886 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4891 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4893 SILC_GET32_MSB(port, tmp);
4895 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4896 name, port, FALSE, NULL);
4898 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4899 name, port, FALSE, NULL);
4900 if (!server_entry) {
4901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4902 SILC_STATUS_ERR_NO_SERVER_ID);
4906 /* Send reply to the sender */
4907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4910 /* Close the connection to the server */
4911 sock = (SilcSocketConnection)server_entry->connection;
4913 /* If we shutdown primary router connection manually then don't trigger
4914 any reconnect or backup router connections, by setting the router
4916 if (server->router == server_entry) {
4917 server->id_entry->router = NULL;
4918 server->router = NULL;
4919 server->standalone = TRUE;
4921 silc_server_free_sock_user_data(server, sock);
4922 silc_server_close_connection(server, sock);
4925 silc_server_command_free(cmd);
4928 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4929 active connections. */
4931 SILC_SERVER_CMD_FUNC(shutdown)
4933 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4934 SilcServer server = cmd->server;
4935 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4937 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4939 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4942 /* Check whether client has the permission. */
4943 if (client->mode == SILC_UMODE_NONE) {
4944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4945 SILC_STATUS_ERR_NO_SERVER_PRIV);
4949 /* Send reply to the sender */
4950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4953 /* Then, gracefully, or not, bring the server down. */
4954 silc_server_stop(server);
4958 silc_server_command_free(cmd);
4961 /* Server side command of LEAVE. Removes client from a channel. */
4963 SILC_SERVER_CMD_FUNC(leave)
4965 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4966 SilcServer server = cmd->server;
4967 SilcSocketConnection sock = cmd->sock;
4968 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4969 SilcChannelID *id = NULL;
4970 SilcChannelEntry channel;
4974 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4976 /* Get Channel ID */
4977 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4980 SILC_STATUS_ERR_NO_CHANNEL_ID);
4983 id = silc_id_payload_parse_id(tmp, len);
4985 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4986 SILC_STATUS_ERR_NO_CHANNEL_ID);
4990 /* Get channel entry */
4991 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4993 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4996 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5001 /* Check whether this client is on the channel */
5002 if (!silc_server_client_on_channel(id_entry, channel)) {
5003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5004 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5008 /* Notify routers that they should remove this client from their list
5009 of clients on the channel. Send LEAVE notify type. */
5010 if (!server->standalone)
5011 silc_server_send_notify_leave(server, server->router->connection,
5012 server->server_type == SILC_ROUTER ?
5013 TRUE : FALSE, channel, id_entry->id);
5015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5018 /* Remove client from channel */
5019 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5021 /* If the channel does not exist anymore we won't send anything */
5024 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5025 /* Re-generate channel key */
5026 if (!silc_server_create_channel_key(server, channel, 0))
5029 /* Send the channel key */
5030 silc_server_send_channel_key(server, NULL, channel,
5031 server->server_type == SILC_ROUTER ?
5032 FALSE : !server->standalone);
5037 silc_server_command_free(cmd);
5040 /* Server side of command USERS. Resolves clients and their USERS currently
5041 joined on the requested channel. The list of Client ID's and their modes
5042 on the channel is sent back. */
5044 SILC_SERVER_CMD_FUNC(users)
5046 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5047 SilcServer server = cmd->server;
5048 SilcChannelEntry channel;
5049 SilcChannelID *id = NULL;
5050 SilcBuffer packet, idp;
5051 unsigned char *channel_id;
5052 uint32 channel_id_len;
5053 SilcBuffer client_id_list;
5054 SilcBuffer client_mode_list;
5055 unsigned char lc[4];
5056 uint32 list_count = 0;
5057 uint16 ident = silc_command_get_ident(cmd->payload);
5060 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5062 /* Get Channel ID */
5063 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5065 /* Get channel name */
5066 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5068 if (!channel_id && !channel_name) {
5069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5070 SILC_STATUS_ERR_NO_CHANNEL_ID);
5075 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5078 SILC_STATUS_ERR_NO_CHANNEL_ID);
5083 /* If we are server and we don't know about this channel we will send
5084 the command to our router. If we know about the channel then we also
5085 have the list of users already. */
5087 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5089 channel = silc_idlist_find_channel_by_name(server->local_list,
5090 channel_name, NULL);
5092 if (!channel || channel->disabled) {
5093 if (server->server_type != SILC_ROUTER && !server->standalone &&
5097 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5098 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5100 /* Send USERS command */
5101 silc_server_packet_send(server, server->router->connection,
5102 SILC_PACKET_COMMAND, cmd->packet->flags,
5103 tmpbuf->data, tmpbuf->len, TRUE);
5105 /* Reprocess this packet after received reply */
5106 silc_server_command_pending(server, SILC_COMMAND_USERS,
5107 silc_command_get_ident(cmd->payload),
5108 silc_server_command_destructor,
5109 silc_server_command_users,
5110 silc_server_command_dup(cmd));
5111 cmd->pending = TRUE;
5112 silc_command_set_ident(cmd->payload, ident);
5114 silc_buffer_free(tmpbuf);
5119 /* Check the global list as well. */
5121 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5123 channel = silc_idlist_find_channel_by_name(server->global_list,
5124 channel_name, NULL);
5126 /* Channel really does not exist */
5127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5128 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5133 /* If the channel is private or secret do not send anything, unless the
5134 user requesting this command is on the channel. */
5135 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5136 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5137 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5139 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5144 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5145 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5146 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5151 /* Get the users list */
5152 silc_server_get_users_on_channel(server, channel, &client_id_list,
5153 &client_mode_list, &list_count);
5156 SILC_PUT32_MSB(list_count, lc);
5159 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5160 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5161 SILC_STATUS_OK, ident, 4,
5162 2, idp->data, idp->len,
5164 4, client_id_list->data,
5165 client_id_list->len,
5166 5, client_mode_list->data,
5167 client_mode_list->len);
5168 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5169 packet->data, packet->len, FALSE);
5171 silc_buffer_free(idp);
5172 silc_buffer_free(packet);
5173 silc_buffer_free(client_id_list);
5174 silc_buffer_free(client_mode_list);
5178 silc_server_command_free(cmd);
5181 /* Server side of command GETKEY. This fetches the client's public key
5182 from the server where to the client is connected. */
5184 SILC_SERVER_CMD_FUNC(getkey)
5186 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5187 SilcServer server = cmd->server;
5189 SilcClientEntry client;
5190 SilcServerEntry server_entry;
5191 SilcClientID *client_id = NULL;
5192 SilcServerID *server_id = NULL;
5193 SilcIDPayload idp = NULL;
5194 uint16 ident = silc_command_get_ident(cmd->payload);
5195 unsigned char *tmp, *pkdata;
5196 uint32 tmp_len, pklen;
5197 SilcBuffer pk = NULL;
5200 SILC_LOG_DEBUG(("Start"));
5202 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5205 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5208 idp = silc_id_payload_parse(tmp, tmp_len);
5210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5211 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5215 id_type = silc_id_payload_get_type(idp);
5216 if (id_type == SILC_ID_CLIENT) {
5217 client_id = silc_id_payload_get_id(idp);
5219 /* If the client is not found from local list there is no chance it
5220 would be locally connected client so send the command further. */
5221 client = silc_idlist_find_client_by_id(server->local_list,
5222 client_id, TRUE, NULL);
5224 client = silc_idlist_find_client_by_id(server->global_list,
5225 client_id, TRUE, NULL);
5227 if ((!client && !cmd->pending && !server->standalone) ||
5228 (client && !client->connection && !cmd->pending) ||
5229 (client && !client->data.public_key && !cmd->pending)) {
5232 SilcSocketConnection dest_sock;
5234 dest_sock = silc_server_get_client_route(server, NULL, 0,
5239 old_ident = silc_command_get_ident(cmd->payload);
5240 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5241 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5243 silc_server_packet_send(server, dest_sock,
5244 SILC_PACKET_COMMAND, cmd->packet->flags,
5245 tmpbuf->data, tmpbuf->len, TRUE);
5247 /* Reprocess this packet after received reply from router */
5248 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5249 silc_command_get_ident(cmd->payload),
5250 silc_server_command_destructor,
5251 silc_server_command_getkey,
5252 silc_server_command_dup(cmd));
5253 cmd->pending = TRUE;
5255 silc_command_set_ident(cmd->payload, old_ident);
5256 silc_buffer_free(tmpbuf);
5261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5262 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5266 /* The client is locally connected, just get the public key and
5267 send it back. If they key does not exist then do not send it,
5268 send just OK reply */
5269 if (!client->data.public_key) {
5273 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5274 pk = silc_buffer_alloc(4 + tmp_len);
5275 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5276 silc_buffer_format(pk,
5277 SILC_STR_UI_SHORT(tmp_len),
5278 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5279 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5285 } else if (id_type == SILC_ID_SERVER) {
5286 server_id = silc_id_payload_get_id(idp);
5288 /* If the server is not found from local list there is no chance it
5289 would be locally connected server so send the command further. */
5290 server_entry = silc_idlist_find_server_by_id(server->local_list,
5291 server_id, TRUE, NULL);
5293 server_entry = silc_idlist_find_server_by_id(server->global_list,
5294 server_id, TRUE, NULL);
5296 if (server_entry != server->id_entry &&
5297 ((!server_entry && !cmd->pending && !server->standalone) ||
5298 (server_entry && !server_entry->connection && !cmd->pending &&
5299 !server->standalone) ||
5300 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5301 !server->standalone))) {
5305 old_ident = silc_command_get_ident(cmd->payload);
5306 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5307 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5309 silc_server_packet_send(server, server->router->connection,
5310 SILC_PACKET_COMMAND, cmd->packet->flags,
5311 tmpbuf->data, tmpbuf->len, TRUE);
5313 /* Reprocess this packet after received reply from router */
5314 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5315 silc_command_get_ident(cmd->payload),
5316 silc_server_command_destructor,
5317 silc_server_command_getkey,
5318 silc_server_command_dup(cmd));
5319 cmd->pending = TRUE;
5321 silc_command_set_ident(cmd->payload, old_ident);
5322 silc_buffer_free(tmpbuf);
5326 if (!server_entry) {
5327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5328 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5332 /* If they key does not exist then do not send it, send just OK reply */
5333 if (!server_entry->data.public_key) {
5337 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5339 pk = silc_buffer_alloc(4 + tmp_len);
5340 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5341 silc_buffer_format(pk,
5342 SILC_STR_UI_SHORT(tmp_len),
5343 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5344 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5354 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5355 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5356 SILC_STATUS_OK, ident,
5360 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5361 packet->data, packet->len, FALSE);
5362 silc_buffer_free(packet);
5365 silc_buffer_free(pk);
5369 silc_id_payload_free(idp);
5370 silc_free(client_id);
5371 silc_free(server_id);
5372 silc_server_command_free(cmd);