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,
38 const unsigned char *arg,
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,
405 const unsigned char *arg,
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,
688 const char *nickname,
689 SilcClientID **client_ids)
691 SilcServer server = cmd->server;
693 int i, k, len, valid_count;
694 SilcBuffer packet, idp, channels;
695 SilcClientEntry entry;
696 SilcCommandStatus status;
697 uint16 ident = silc_command_get_ident(cmd->payload);
698 char nh[256], uh[256];
699 unsigned char idle[4], mode[4];
700 unsigned char *fingerprint;
701 SilcSocketConnection hsock;
703 /* Process only valid clients and ignore those that are not registered. */
705 for (i = 0; i < clients_count; i++) {
706 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
713 /* No valid clients found, send error reply */
715 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
716 SILC_STATUS_ERR_NO_SUCH_NICK,
717 3, nickname, strlen(nickname));
718 } else if (client_ids && client_ids[0]) {
719 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
720 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
721 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
722 2, idp->data, idp->len);
723 silc_buffer_free(idp);
728 /* Start processing found clients. */
730 status = SILC_STATUS_LIST_START;
732 status = SILC_STATUS_OK;
734 for (i = 0, k = 0; i < clients_count; i++) {
741 /* Sanity check, however these should never fail. However, as
742 this sanity check has been added here they have failed. */
743 if (!entry->nickname || !entry->username || !entry->userinfo) {
744 SILC_LOG_ERROR(("********* if (!entry->nickname || !entry->username "
745 "|| !entry->userinfo) triggered: should have not!"));
751 status = SILC_STATUS_LIST_ITEM;
752 if (valid_count > 1 && k == valid_count - 1)
753 status = SILC_STATUS_LIST_END;
754 if (count && k - 1 == count)
755 status = SILC_STATUS_LIST_END;
757 /* Send WHOIS reply */
758 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
759 tmp = silc_argument_get_first_arg(cmd->args, NULL);
761 memset(uh, 0, sizeof(uh));
762 memset(nh, 0, sizeof(nh));
763 memset(idle, 0, sizeof(idle));
765 strncat(nh, entry->nickname, strlen(entry->nickname));
766 if (!strchr(entry->nickname, '@')) {
768 if (entry->servername) {
769 strncat(nh, entry->servername, strlen(entry->servername));
771 len = entry->router ? strlen(entry->router->server_name) :
772 strlen(server->server_name);
773 strncat(nh, entry->router ? entry->router->server_name :
774 server->server_name, len);
778 strncat(uh, entry->username, strlen(entry->username));
779 if (!strchr(entry->username, '@')) {
781 hsock = (SilcSocketConnection)entry->connection;
782 len = strlen(hsock->hostname);
783 strncat(uh, hsock->hostname, len);
786 channels = silc_server_get_client_channel_list(server, entry);
788 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
789 fingerprint = entry->data.fingerprint;
793 SILC_PUT32_MSB(entry->mode, mode);
795 if (entry->connection) {
796 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
800 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
802 2, idp->data, idp->len,
806 strlen(entry->userinfo),
807 6, channels ? channels->data : NULL,
808 channels ? channels->len : 0,
812 fingerprint ? 20 : 0);
814 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
815 0, packet->data, packet->len, FALSE);
817 silc_buffer_free(packet);
818 silc_buffer_free(idp);
820 silc_buffer_free(channels);
827 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
829 SilcServer server = cmd->server;
833 old_ident = silc_command_get_ident(cmd->payload);
834 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
835 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
837 /* Send WHOIS command to our router */
838 silc_server_packet_send(server, (SilcSocketConnection)
839 server->router->connection,
840 SILC_PACKET_COMMAND, cmd->packet->flags,
841 tmpbuf->data, tmpbuf->len, TRUE);
843 /* Reprocess this packet after received reply from router */
844 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
845 silc_command_get_ident(cmd->payload),
846 silc_server_command_destructor,
847 silc_server_command_whois,
848 silc_server_command_dup(cmd));
850 silc_command_set_ident(cmd->payload, old_ident);
851 silc_buffer_free(tmpbuf);
855 silc_server_command_whois_process(SilcServerCommandContext cmd)
857 SilcServer server = cmd->server;
858 char *nick = NULL, *server_name = NULL;
860 SilcClientEntry *clients = NULL, entry;
861 SilcClientID **client_id = NULL;
862 uint32 client_id_count = 0, clients_count = 0;
864 bool check_global = FALSE;
866 /* Parse the whois request */
867 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
868 &nick, &server_name, &count,
872 /* Send the WHOIS request to the router only if it included nickname.
873 Since nicknames can be expanded into many clients we need to send it
874 to router. If the WHOIS included only client ID's we will check them
875 first locally since we just might have them. */
876 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
877 server->server_type == SILC_SERVER && !cmd->pending &&
878 !server->standalone) {
879 silc_server_command_whois_send_router(cmd);
884 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
886 else if (server->server_type != SILC_SERVER)
889 /* Get all clients matching that ID or nickname from local list */
890 if (client_id_count) {
891 /* Check all Client ID's received in the command packet */
892 for (i = 0; i < client_id_count; i++) {
893 entry = silc_idlist_find_client_by_id(server->local_list,
894 client_id[i], TRUE, NULL);
895 if (!entry && check_global)
896 entry = silc_idlist_find_client_by_id(server->global_list,
897 client_id[i], TRUE, NULL);
899 clients = silc_realloc(clients, sizeof(*clients) *
900 (clients_count + 1));
901 clients[clients_count++] = entry;
903 /* If we are normal server and did not send the request first to router
904 do it now, since we do not have the Client ID information. */
905 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
906 server->server_type == SILC_SERVER && !cmd->pending &&
907 !server->standalone) {
908 silc_server_command_whois_send_router(cmd);
915 /* Find by nickname */
916 if (!silc_idlist_get_clients_by_hash(server->local_list,
917 nick, server->md5hash,
918 &clients, &clients_count))
919 silc_idlist_get_clients_by_nickname(server->local_list,
921 &clients, &clients_count);
923 if (!silc_idlist_get_clients_by_hash(server->global_list,
924 nick, server->md5hash,
925 &clients, &clients_count))
926 silc_idlist_get_clients_by_nickname(server->global_list,
928 &clients, &clients_count);
933 /* If we are normal server and did not send the request first to router
934 do it now, since we do not have the information. */
935 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
936 server->server_type == SILC_SERVER && !cmd->pending &&
937 !server->standalone) {
938 silc_server_command_whois_send_router(cmd);
943 /* Such client(s) really does not exist in the SILC network. */
944 if (!client_id_count) {
945 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
946 SILC_STATUS_ERR_NO_SUCH_NICK,
947 3, nick, strlen(nick));
949 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
950 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
951 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
952 2, idp->data, idp->len);
953 silc_buffer_free(idp);
958 /* Router always finds the client entry if it exists in the SILC network.
959 However, it might be incomplete entry and does not include all the
960 mandatory fields that WHOIS command reply requires. Check for these and
961 make query from the server who owns the client if some fields are
963 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
968 /* Send the command reply */
969 silc_server_command_whois_send_reply(cmd, clients, clients_count,
970 count, nick, client_id);
973 if (client_id_count) {
974 for (i = 0; i < client_id_count; i++)
975 silc_free(client_id[i]);
976 silc_free(client_id);
980 silc_free(server_name);
985 /* Server side of command WHOIS. Processes user's query and sends found
986 results as command replies back to the client. */
988 SILC_SERVER_CMD_FUNC(whois)
990 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
993 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
995 ret = silc_server_command_whois_process(cmd);
998 silc_server_command_free(cmd);
1001 /******************************************************************************
1005 ******************************************************************************/
1008 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1016 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1019 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1023 /* Get the nickname@server string and parse it. */
1024 silc_parse_userfqdn(tmp, nickname, server_name);
1026 /* Get the max count of reply messages allowed */
1027 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1037 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1038 SilcClientEntry *clients,
1039 uint32 clients_count)
1041 SilcServer server = cmd->server;
1043 SilcClientEntry entry;
1045 for (i = 0; i < clients_count; i++) {
1048 if (!entry->nickname || !entry->username) {
1055 old_ident = silc_command_get_ident(cmd->payload);
1056 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1057 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1059 /* Send WHOWAS command */
1060 silc_server_packet_send(server, entry->router->connection,
1061 SILC_PACKET_COMMAND, cmd->packet->flags,
1062 tmpbuf->data, tmpbuf->len, TRUE);
1064 /* Reprocess this packet after received reply */
1065 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1066 silc_command_get_ident(cmd->payload),
1067 silc_server_command_destructor,
1068 silc_server_command_whowas,
1069 silc_server_command_dup(cmd));
1070 cmd->pending = TRUE;
1072 silc_command_set_ident(cmd->payload, old_ident);
1074 silc_buffer_free(tmpbuf);
1083 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1084 SilcClientEntry *clients,
1085 uint32 clients_count)
1087 SilcServer server = cmd->server;
1089 int i, count = 0, len;
1090 SilcBuffer packet, idp;
1091 SilcClientEntry entry = NULL;
1092 SilcCommandStatus status;
1093 uint16 ident = silc_command_get_ident(cmd->payload);
1095 char nh[256], uh[256];
1097 status = SILC_STATUS_OK;
1098 if (clients_count > 1)
1099 status = SILC_STATUS_LIST_START;
1101 for (i = 0; i < clients_count; i++) {
1104 /* We will take only clients that are not valid anymore. They are the
1105 ones that are not registered anymore but still have a ID. They
1106 have disconnected us, and thus valid for WHOWAS. */
1107 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1110 if (count && i - 1 == count)
1115 if (clients_count > 2)
1116 status = SILC_STATUS_LIST_ITEM;
1117 if (clients_count > 1 && i == clients_count - 1)
1118 status = SILC_STATUS_LIST_END;
1120 /* Sanity check, however these should never fail. However, as
1121 this sanity check has been added here they have failed. */
1122 if (!entry->nickname || !entry->username || !entry->userinfo) {
1123 SILC_LOG_ERROR(("********* if (!entry->nickname || !entry->username "
1124 "|| !entry->userinfo) triggered: should have not!"));
1130 /* Sanity check, however these should never fail. However, as
1131 this sanity check has been added here they have failed. */
1132 if (!entry->nickname || !entry->username) {
1133 SILC_LOG_ERROR(("********* if (!entry->nickname || !entry->username) "
1134 "triggered: should have not!"));
1139 /* Send WHOWAS reply */
1140 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1141 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1142 memset(uh, 0, sizeof(uh));
1143 memset(nh, 0, sizeof(nh));
1145 strncat(nh, entry->nickname, strlen(entry->nickname));
1146 if (!strchr(entry->nickname, '@')) {
1147 strncat(nh, "@", 1);
1148 if (entry->servername) {
1149 strncat(nh, entry->servername, strlen(entry->servername));
1151 len = entry->router ? strlen(entry->router->server_name) :
1152 strlen(server->server_name);
1153 strncat(nh, entry->router ? entry->router->server_name :
1154 server->server_name, len);
1158 strncat(uh, entry->username, strlen(entry->username));
1159 if (!strchr(entry->username, '@')) {
1160 strncat(uh, "@", 1);
1161 strcat(uh, "*private*");
1165 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1167 2, idp->data, idp->len,
1172 strlen(entry->userinfo) : 0);
1173 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1174 0, packet->data, packet->len, FALSE);
1176 silc_buffer_free(packet);
1177 silc_buffer_free(idp);
1180 if (found == FALSE && entry)
1181 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1182 SILC_STATUS_ERR_NO_SUCH_NICK,
1184 strlen(entry->nickname));
1188 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1190 SilcServer server = cmd->server;
1191 char *nick = NULL, *server_name = NULL;
1193 SilcClientEntry *clients = NULL;
1194 uint32 clients_count = 0;
1196 bool check_global = FALSE;
1198 /* Protocol dictates that we must always send the received WHOWAS request
1199 to our router if we are normal server, so let's do it now unless we
1200 are standalone. We will not send any replies to the client until we
1201 have received reply from the router. */
1202 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1203 server->server_type == SILC_SERVER && !cmd->pending &&
1204 !server->standalone) {
1208 old_ident = silc_command_get_ident(cmd->payload);
1209 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1210 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1212 /* Send WHOWAS command to our router */
1213 silc_server_packet_send(server, (SilcSocketConnection)
1214 server->router->connection,
1215 SILC_PACKET_COMMAND, cmd->packet->flags,
1216 tmpbuf->data, tmpbuf->len, TRUE);
1218 /* Reprocess this packet after received reply from router */
1219 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1220 silc_command_get_ident(cmd->payload),
1221 silc_server_command_destructor,
1222 silc_server_command_whowas,
1223 silc_server_command_dup(cmd));
1224 cmd->pending = TRUE;
1226 silc_command_set_ident(cmd->payload, old_ident);
1228 silc_buffer_free(tmpbuf);
1233 /* We are ready to process the command request. Let's search for the
1234 requested client and send reply to the requesting client. */
1236 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1237 check_global = TRUE;
1238 else if (server->server_type != SILC_SERVER)
1239 check_global = TRUE;
1241 /* Parse the whowas request */
1242 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1245 /* Get all clients matching that nickname from local list */
1246 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1248 &clients, &clients_count))
1249 silc_idlist_get_clients_by_hash(server->local_list,
1250 nick, server->md5hash,
1251 &clients, &clients_count);
1253 /* Check global list as well */
1255 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1257 &clients, &clients_count))
1258 silc_idlist_get_clients_by_hash(server->global_list,
1259 nick, server->md5hash,
1260 &clients, &clients_count);
1264 /* Such a client really does not exist in the SILC network. */
1265 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1266 SILC_STATUS_ERR_NO_SUCH_NICK,
1267 3, nick, strlen(nick));
1271 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1276 /* Send the command reply to the client */
1277 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1282 silc_free(server_name);
1287 /* Server side of command WHOWAS. */
1289 SILC_SERVER_CMD_FUNC(whowas)
1291 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1294 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1296 ret = silc_server_command_whowas_process(cmd);
1299 silc_server_command_free(cmd);
1302 /******************************************************************************
1306 ******************************************************************************/
1309 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1311 SilcServer server = cmd->server;
1315 old_ident = silc_command_get_ident(cmd->payload);
1316 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1317 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1319 /* Send IDENTIFY command to our router */
1320 silc_server_packet_send(server, (SilcSocketConnection)
1321 server->router->connection,
1322 SILC_PACKET_COMMAND, cmd->packet->flags,
1323 tmpbuf->data, tmpbuf->len, TRUE);
1325 /* Reprocess this packet after received reply from router */
1326 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1327 silc_command_get_ident(cmd->payload),
1328 silc_server_command_destructor,
1329 silc_server_command_identify,
1330 silc_server_command_dup(cmd));
1331 cmd->pending = TRUE;
1332 silc_command_set_ident(cmd->payload, old_ident);
1333 silc_buffer_free(tmpbuf);
1337 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1338 SilcClientEntry **clients,
1339 uint32 *clients_count,
1340 SilcServerEntry **servers,
1341 uint32 *servers_count,
1342 SilcChannelEntry **channels,
1343 uint32 *channels_count,
1346 SilcServer server = cmd->server;
1349 uint32 argc = silc_argument_get_arg_num(cmd->args);
1351 bool check_global = FALSE;
1356 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1357 check_global = TRUE;
1358 else if (server->server_type != SILC_SERVER)
1359 check_global = TRUE;
1361 /* If ID Payload is in the command it must be used instead of names */
1362 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1364 /* No ID, get the names. */
1366 /* If we are normal server and have not resolved information from
1367 router yet, do so now. */
1368 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1369 server->server_type == SILC_SERVER && !cmd->pending &&
1370 !server->standalone) {
1371 silc_server_command_identify_send_router(cmd);
1375 /* Try to get nickname@server. */
1376 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1379 char *nick_server = NULL;
1381 silc_parse_userfqdn(tmp, &nick, &nick_server);
1383 if (!silc_idlist_get_clients_by_hash(server->local_list,
1384 nick, server->md5hash,
1385 clients, clients_count))
1386 silc_idlist_get_clients_by_nickname(server->local_list,
1388 clients, clients_count);
1390 if (!silc_idlist_get_clients_by_hash(server->global_list,
1391 nick, server->md5hash,
1392 clients, clients_count))
1393 silc_idlist_get_clients_by_nickname(server->global_list,
1395 clients, clients_count);
1399 silc_free(nick_server);
1402 /* the nickname does not exist, send error reply */
1403 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1404 SILC_STATUS_ERR_NO_SUCH_NICK,
1405 3, tmp, strlen(tmp));
1410 /* Try to get server name */
1411 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1413 entry = silc_idlist_find_server_by_name(server->local_list,
1415 if (!entry && check_global)
1416 entry = silc_idlist_find_server_by_name(server->global_list,
1419 *servers = silc_realloc(*servers, sizeof(**servers) *
1420 (*servers_count + 1));
1421 (*servers)[(*servers_count)++] = entry;
1425 /* the server does not exist, send error reply */
1426 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1427 SILC_STATUS_ERR_NO_SUCH_SERVER,
1428 3, tmp, strlen(tmp));
1433 /* Try to get channel name */
1434 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1436 entry = silc_idlist_find_channel_by_name(server->local_list,
1438 if (!entry && check_global)
1439 entry = silc_idlist_find_channel_by_name(server->global_list,
1442 *channels = silc_realloc(*channels, sizeof(**channels) *
1443 (*channels_count + 1));
1444 (*channels)[(*channels_count)++] = entry;
1448 /* The channel does not exist, send error reply */
1449 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1450 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1451 3, tmp, strlen(tmp));
1456 if (!(*clients) && !(*servers) && !(*channels)) {
1457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1458 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1462 /* Command includes ID, we must use that. Also check whether the command
1463 has more than one ID set - take them all. */
1465 /* Take all ID's from the command packet */
1466 for (i = 0; i < argc; i++) {
1469 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1473 idp = silc_id_payload_parse(tmp, len);
1475 silc_free(*clients);
1476 silc_free(*servers);
1477 silc_free(*channels);
1478 silc_server_command_send_status_reply(
1479 cmd, SILC_COMMAND_IDENTIFY,
1480 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1484 id = silc_id_payload_get_id(idp);
1486 switch (silc_id_payload_get_type(idp)) {
1488 case SILC_ID_CLIENT:
1489 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1491 if (!entry && check_global)
1492 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1495 *clients = silc_realloc(*clients, sizeof(**clients) *
1496 (*clients_count + 1));
1497 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1499 /* If we are normal server and have not resolved information from
1500 router yet, do so now. */
1501 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1502 server->server_type == SILC_SERVER && !cmd->pending &&
1503 !server->standalone) {
1504 silc_server_command_identify_send_router(cmd);
1505 silc_free(*clients);
1506 silc_free(*servers);
1507 silc_free(*channels);
1510 silc_server_command_send_status_data(
1511 cmd, SILC_COMMAND_IDENTIFY,
1512 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1520 case SILC_ID_SERVER:
1521 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1523 if (!entry && check_global)
1524 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1527 *servers = silc_realloc(*servers, sizeof(**servers) *
1528 (*servers_count + 1));
1529 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1531 /* If we are normal server and have not resolved information from
1532 router yet, do so now. */
1533 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1534 server->server_type == SILC_SERVER && !cmd->pending &&
1535 !server->standalone) {
1536 silc_server_command_identify_send_router(cmd);
1537 silc_free(*clients);
1538 silc_free(*servers);
1539 silc_free(*channels);
1542 silc_server_command_send_status_data(
1543 cmd, SILC_COMMAND_IDENTIFY,
1544 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1551 case SILC_ID_CHANNEL:
1552 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1554 if (!entry && check_global)
1555 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1558 *channels = silc_realloc(*channels, sizeof(**channels) *
1559 (*channels_count + 1));
1560 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1562 /* If we are normal server and have not resolved information from
1563 router yet, do so now. */
1564 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1565 server->server_type == SILC_SERVER && !cmd->pending &&
1566 !server->standalone) {
1567 silc_server_command_identify_send_router(cmd);
1568 silc_free(*clients);
1569 silc_free(*servers);
1570 silc_free(*channels);
1573 silc_server_command_send_status_data(
1574 cmd, SILC_COMMAND_IDENTIFY,
1575 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1588 silc_free(*clients);
1589 silc_free(*servers);
1590 silc_free(*channels);
1594 /* Get the max count of reply messages allowed */
1595 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1604 /* Checks that all mandatory fields in client entry are present. If not
1605 then send WHOIS request to the server who owns the client. We use
1606 WHOIS because we want to get as much information as possible at once. */
1609 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1610 SilcClientEntry *clients,
1611 uint32 clients_count)
1613 SilcServer server = cmd->server;
1614 SilcClientEntry entry;
1615 SilcServerResolveContext resolve = NULL, r = NULL;
1616 uint32 resolve_count = 0;
1620 for (i = 0; i < clients_count; i++) {
1625 if (entry->nickname ||
1626 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1630 /* If we are normal server, and we've not resolved this client from
1631 router and it is global client, we'll check whether it is on some
1632 channel. If not then we cannot be sure about its validity, and
1633 we'll resolve it from router. */
1634 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1635 entry->connection || silc_hash_table_count(entry->channels))
1639 /* We need to resolve this entry since it is not complete */
1641 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1642 /* The entry is being resolved (and we are not the resolver) so attach
1643 to the command reply and we're done with this one. */
1644 silc_server_command_pending(server, SILC_COMMAND_NONE,
1645 entry->resolve_cmd_ident,
1646 silc_server_command_destructor,
1647 silc_server_command_identify,
1648 silc_server_command_dup(cmd));
1651 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1652 /* We've resolved this and it still is not ready. We'll return
1653 and are that this will be handled again after it is resolved. */
1654 for (i = 0; i < resolve_count; i++) {
1655 for (k = 0; k < r->res_argc; k++)
1656 silc_free(r->res_argv[k]);
1657 silc_free(r->res_argv);
1658 silc_free(r->res_argv_lens);
1659 silc_free(r->res_argv_types);
1664 /* We'll resolve this client */
1668 for (k = 0; k < resolve_count; k++) {
1669 if (resolve[k].router == entry->router) {
1676 resolve = silc_realloc(resolve, sizeof(*resolve) *
1677 (resolve_count + 1));
1678 r = &resolve[resolve_count];
1679 memset(r, 0, sizeof(*r));
1680 r->router = entry->router;
1681 r->ident = ++server->cmd_ident;
1685 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1687 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1688 sizeof(*r->res_argv_lens) *
1690 r->res_argv_types = silc_realloc(r->res_argv_types,
1691 sizeof(*r->res_argv_types) *
1693 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1694 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1695 sizeof(**r->res_argv));
1696 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1697 r->res_argv_lens[r->res_argc] = idp->len;
1698 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1700 silc_buffer_free(idp);
1702 entry->resolve_cmd_ident = r->ident;
1703 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1704 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1709 /* Do the resolving */
1710 for (i = 0; i < resolve_count; i++) {
1715 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1716 now anyway so make it a good one. */
1717 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1718 r->res_argc, r->res_argv,
1722 silc_server_packet_send(server, r->router->connection,
1723 SILC_PACKET_COMMAND, cmd->packet->flags,
1724 res_cmd->data, res_cmd->len, FALSE);
1726 /* Reprocess this packet after received reply */
1727 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1729 silc_server_command_destructor,
1730 silc_server_command_identify,
1731 silc_server_command_dup(cmd));
1732 cmd->pending = TRUE;
1734 silc_buffer_free(res_cmd);
1735 for (k = 0; k < r->res_argc; k++)
1736 silc_free(r->res_argv[k]);
1737 silc_free(r->res_argv);
1738 silc_free(r->res_argv_lens);
1739 silc_free(r->res_argv_types);
1748 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1749 SilcClientEntry *clients,
1750 uint32 clients_count,
1751 SilcServerEntry *servers,
1752 uint32 servers_count,
1753 SilcChannelEntry *channels,
1754 uint32 channels_count,
1757 SilcServer server = cmd->server;
1758 int i, k, len, valid_count;
1759 SilcBuffer packet, idp;
1760 SilcCommandStatus status;
1761 uint16 ident = silc_command_get_ident(cmd->payload);
1762 char nh[256], uh[256];
1763 SilcSocketConnection hsock;
1765 status = SILC_STATUS_OK;
1768 SilcClientEntry entry;
1770 /* Process only valid entries. */
1772 for (i = 0; i < clients_count; i++) {
1773 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1780 /* No valid entries found at all, just send error */
1783 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1785 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1786 SILC_STATUS_ERR_NO_SUCH_NICK,
1787 3, tmp, strlen(tmp));
1789 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1790 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1791 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1797 /* Process all valid client entries and send command replies */
1800 status = SILC_STATUS_LIST_START;
1802 for (i = 0, k = 0; i < clients_count; i++) {
1808 status = SILC_STATUS_LIST_ITEM;
1809 if (valid_count > 1 && k == valid_count - 1
1810 && !servers_count && !channels_count)
1811 status = SILC_STATUS_LIST_END;
1812 if (count && k - 1 == count)
1813 status = SILC_STATUS_LIST_END;
1814 if (count && k - 1 > count)
1817 /* Send IDENTIFY reply */
1819 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1820 memset(uh, 0, sizeof(uh));
1821 memset(nh, 0, sizeof(nh));
1822 strncat(nh, entry->nickname, strlen(entry->nickname));
1823 if (!strchr(entry->nickname, '@')) {
1824 strncat(nh, "@", 1);
1825 if (entry->servername) {
1826 strncat(nh, entry->servername, strlen(entry->servername));
1828 len = entry->router ? strlen(entry->router->server_name) :
1829 strlen(server->server_name);
1830 strncat(nh, entry->router ? entry->router->server_name :
1831 server->server_name, len);
1835 if (!entry->username) {
1836 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1838 2, idp->data, idp->len,
1841 strncat(uh, entry->username, strlen(entry->username));
1842 if (!strchr(entry->username, '@')) {
1843 strncat(uh, "@", 1);
1844 hsock = (SilcSocketConnection)entry->connection;
1845 len = strlen(hsock->hostname);
1846 strncat(uh, hsock->hostname, len);
1849 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1851 2, idp->data, idp->len,
1856 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1857 0, packet->data, packet->len, FALSE);
1859 silc_buffer_free(packet);
1860 silc_buffer_free(idp);
1867 SilcServerEntry entry;
1869 if (status == SILC_STATUS_OK && servers_count > 1)
1870 status = SILC_STATUS_LIST_START;
1872 for (i = 0, k = 0; i < servers_count; i++) {
1876 status = SILC_STATUS_LIST_ITEM;
1877 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1878 status = SILC_STATUS_LIST_END;
1879 if (count && k - 1 == count)
1880 status = SILC_STATUS_LIST_END;
1881 if (count && k - 1 > count)
1884 /* Send IDENTIFY reply */
1885 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1887 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1889 2, idp->data, idp->len,
1890 3, entry->server_name,
1891 entry->server_name ?
1892 strlen(entry->server_name) : 0);
1893 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1894 0, packet->data, packet->len, FALSE);
1896 silc_buffer_free(packet);
1897 silc_buffer_free(idp);
1904 SilcChannelEntry entry;
1906 if (status == SILC_STATUS_OK && channels_count > 1)
1907 status = SILC_STATUS_LIST_START;
1909 for (i = 0, k = 0; i < channels_count; i++) {
1910 entry = channels[i];
1913 status = SILC_STATUS_LIST_ITEM;
1914 if (channels_count > 1 && k == channels_count - 1)
1915 status = SILC_STATUS_LIST_END;
1916 if (count && k - 1 == count)
1917 status = SILC_STATUS_LIST_END;
1918 if (count && k - 1 > count)
1921 /* Send IDENTIFY reply */
1922 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1924 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1926 2, idp->data, idp->len,
1927 3, entry->channel_name,
1928 entry->channel_name ?
1929 strlen(entry->channel_name): 0);
1930 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1931 0, packet->data, packet->len, FALSE);
1933 silc_buffer_free(packet);
1934 silc_buffer_free(idp);
1942 silc_server_command_identify_process(SilcServerCommandContext cmd)
1946 SilcClientEntry *clients = NULL;
1947 SilcServerEntry *servers = NULL;
1948 SilcChannelEntry *channels = NULL;
1949 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1951 /* Parse the IDENTIFY request */
1952 ret = silc_server_command_identify_parse(cmd,
1953 &clients, &clients_count,
1954 &servers, &servers_count,
1955 &channels, &channels_count,
1960 /* Check that all mandatory fields are present and request those data
1961 from the server who owns the client if necessary. */
1962 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1968 /* Send the command reply to the client */
1969 silc_server_command_identify_send_reply(cmd,
1970 clients, clients_count,
1971 servers, servers_count,
1972 channels, channels_count,
1978 silc_free(channels);
1982 SILC_SERVER_CMD_FUNC(identify)
1984 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1987 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1989 ret = silc_server_command_identify_process(cmd);
1992 silc_server_command_free(cmd);
1995 /* Checks string for bad characters and returns TRUE if they are found. */
1997 static int silc_server_command_bad_chars(char *nick)
2001 for (i = 0; i < strlen(nick); i++) {
2002 if (!isascii(nick[i]))
2004 if (nick[i] <= 32) return TRUE;
2005 if (nick[i] == ' ') return TRUE;
2006 if (nick[i] == '*') return TRUE;
2007 if (nick[i] == '?') return TRUE;
2008 if (nick[i] == ',') return TRUE;
2014 /* Server side of command NICK. Sets nickname for user. Setting
2015 nickname causes generation of a new client ID for the client. The
2016 new client ID is sent to the client after changing the nickname. */
2018 SILC_SERVER_CMD_FUNC(nick)
2020 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2021 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2022 SilcServer server = cmd->server;
2023 SilcBuffer packet, nidp, oidp = NULL;
2024 SilcClientID *new_id;
2026 uint16 ident = silc_command_get_ident(cmd->payload);
2029 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2032 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2034 /* Check nickname */
2035 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
2036 if (silc_server_command_bad_chars(nick) == TRUE) {
2037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2038 SILC_STATUS_ERR_BAD_NICKNAME);
2042 if (strlen(nick) > 128)
2045 /* Check for same nickname */
2046 if (!strcmp(client->nickname, nick)) {
2047 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2051 /* Create new Client ID */
2052 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2054 cmd->server->md5hash, nick,
2057 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2060 /* Send notify about nickname change to our router. We send the new
2061 ID and ask to replace it with the old one. If we are router the
2062 packet is broadcasted. Send NICK_CHANGE notify. */
2063 if (!server->standalone)
2064 silc_server_send_notify_nick_change(server, server->router->connection,
2065 server->server_type == SILC_SERVER ?
2066 FALSE : TRUE, client->id,
2069 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2071 /* Remove old cache entry */
2072 silc_idcache_del_by_context(server->local_list->clients, client);
2075 silc_free(client->id);
2077 /* Save the nickname as this client is our local client */
2078 silc_free(client->nickname);
2080 client->nickname = strdup(nick);
2081 client->id = new_id;
2083 /* Update client cache */
2084 silc_idcache_add(server->local_list->clients, client->nickname,
2085 client->id, (void *)client, 0, NULL);
2087 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2089 /* Send NICK_CHANGE notify to the client's channels */
2090 silc_server_send_notify_on_channels(server, NULL, client,
2091 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2092 oidp->data, oidp->len,
2093 nidp->data, nidp->len);
2096 /* Send the new Client ID as reply command back to client */
2097 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2098 SILC_STATUS_OK, ident, 1,
2099 2, nidp->data, nidp->len);
2100 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2101 0, packet->data, packet->len, FALSE);
2103 silc_buffer_free(packet);
2104 silc_buffer_free(nidp);
2106 silc_buffer_free(oidp);
2109 silc_server_command_free(cmd);
2112 /* Sends the LIST command reply */
2115 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2116 SilcChannelEntry *lch,
2118 SilcChannelEntry *gch,
2122 SilcBuffer packet, idp;
2123 SilcChannelEntry entry;
2124 SilcCommandStatus status;
2125 uint16 ident = silc_command_get_ident(cmd->payload);
2127 unsigned char usercount[4];
2130 for (i = 0; i < lch_count; i++)
2131 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2133 for (i = 0; i < gch_count; i++)
2134 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2137 status = SILC_STATUS_OK;
2138 if ((lch_count + gch_count) > 1)
2139 status = SILC_STATUS_LIST_START;
2142 for (i = 0; i < lch_count; i++) {
2148 status = SILC_STATUS_LIST_ITEM;
2149 if (i >= 1 && i == lch_count - 1 && !gch_count)
2150 status = SILC_STATUS_LIST_END;
2152 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2154 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2155 topic = "*private*";
2156 memset(usercount, 0, sizeof(usercount));
2158 topic = entry->topic;
2159 users = silc_hash_table_count(entry->user_list);
2160 SILC_PUT32_MSB(users, usercount);
2163 /* Send the reply */
2165 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2167 2, idp->data, idp->len,
2168 3, entry->channel_name,
2169 strlen(entry->channel_name),
2170 4, topic, topic ? strlen(topic) : 0,
2172 silc_server_packet_send(cmd->server, cmd->sock,
2173 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2174 packet->len, FALSE);
2175 silc_buffer_free(packet);
2176 silc_buffer_free(idp);
2180 for (i = 0; i < gch_count; i++) {
2186 status = SILC_STATUS_LIST_ITEM;
2187 if (i >= 1 && i == gch_count - 1)
2188 status = SILC_STATUS_LIST_END;
2190 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2192 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2193 topic = "*private*";
2194 memset(usercount, 0, sizeof(usercount));
2196 topic = entry->topic;
2197 users = silc_hash_table_count(entry->user_list);
2198 SILC_PUT32_MSB(users, usercount);
2201 /* Send the reply */
2203 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2205 2, idp->data, idp->len,
2206 3, entry->channel_name,
2207 strlen(entry->channel_name),
2208 4, topic, topic ? strlen(topic) : 0,
2210 silc_server_packet_send(cmd->server, cmd->sock,
2211 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2212 packet->len, FALSE);
2213 silc_buffer_free(packet);
2214 silc_buffer_free(idp);
2218 /* Server side of LIST command. This lists the channel of the requested
2219 server. Secret channels are not listed. */
2221 SILC_SERVER_CMD_FUNC(list)
2223 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2224 SilcServer server = cmd->server;
2225 SilcChannelID *channel_id = NULL;
2228 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2229 uint32 lch_count = 0, gch_count = 0;
2231 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2233 /* If we are normal server, send the command to router, since we
2234 want to know all channels in the network. */
2235 if (!cmd->pending && server->server_type == SILC_SERVER &&
2236 !server->standalone) {
2240 old_ident = silc_command_get_ident(cmd->payload);
2241 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2242 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2243 silc_server_packet_send(server, server->router->connection,
2244 SILC_PACKET_COMMAND, cmd->packet->flags,
2245 tmpbuf->data, tmpbuf->len, TRUE);
2247 /* Reprocess this packet after received reply from router */
2248 silc_server_command_pending(server, SILC_COMMAND_LIST,
2249 silc_command_get_ident(cmd->payload),
2250 silc_server_command_destructor,
2251 silc_server_command_list,
2252 silc_server_command_dup(cmd));
2253 cmd->pending = TRUE;
2254 silc_command_set_ident(cmd->payload, old_ident);
2255 silc_buffer_free(tmpbuf);
2259 /* Get Channel ID */
2260 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2262 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2265 SILC_STATUS_ERR_NO_CHANNEL_ID);
2270 /* Get the channels from local list */
2271 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2274 /* Get the channels from global list */
2275 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2278 /* Send the reply */
2279 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2280 gchannels, gch_count);
2282 silc_free(lchannels);
2283 silc_free(gchannels);
2286 silc_server_command_free(cmd);
2289 /* Server side of TOPIC command. Sets topic for channel and/or returns
2290 current topic to client. */
2292 SILC_SERVER_CMD_FUNC(topic)
2294 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2295 SilcServer server = cmd->server;
2296 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2297 SilcChannelID *channel_id;
2298 SilcChannelEntry channel;
2299 SilcChannelClientEntry chl;
2300 SilcBuffer packet, idp;
2302 uint32 argc, tmp_len;
2303 uint16 ident = silc_command_get_ident(cmd->payload);
2305 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2307 argc = silc_argument_get_arg_num(cmd->args);
2309 /* Get Channel ID */
2310 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2313 SILC_STATUS_ERR_NO_CHANNEL_ID);
2316 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2319 SILC_STATUS_ERR_NO_CHANNEL_ID);
2323 /* Check whether the channel exists */
2324 channel = silc_idlist_find_channel_by_id(server->local_list,
2327 channel = silc_idlist_find_channel_by_id(server->global_list,
2330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2331 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2338 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2341 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2345 if (strlen(tmp) > 256) {
2346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2347 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2351 /* See whether the client is on channel and has rights to change topic */
2352 if (!silc_hash_table_find(channel->user_list, client, NULL,
2354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2355 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2359 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2360 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2362 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2367 /* Set the topic for channel */
2368 silc_free(channel->topic);
2369 channel->topic = strdup(tmp);
2371 /* Send TOPIC_SET notify type to the network */
2372 if (!server->standalone)
2373 silc_server_send_notify_topic_set(server, server->router->connection,
2374 server->server_type == SILC_ROUTER ?
2375 TRUE : FALSE, channel,
2376 client->id, SILC_ID_CLIENT,
2379 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2381 /* Send notify about topic change to all clients on the channel */
2382 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2383 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2384 idp->data, idp->len,
2385 channel->topic, strlen(channel->topic));
2386 silc_buffer_free(idp);
2389 /* Send the topic to client as reply packet */
2390 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2391 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2392 SILC_STATUS_OK, ident, 2,
2393 2, idp->data, idp->len,
2396 strlen(channel->topic) : 0);
2397 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2398 0, packet->data, packet->len, FALSE);
2400 silc_buffer_free(packet);
2401 silc_buffer_free(idp);
2402 silc_free(channel_id);
2405 silc_server_command_free(cmd);
2408 /* Server side of INVITE command. Invites some client to join some channel.
2409 This command is also used to manage the invite list of the channel. */
2411 SILC_SERVER_CMD_FUNC(invite)
2413 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2414 SilcServer server = cmd->server;
2415 SilcSocketConnection sock = cmd->sock, dest_sock;
2416 SilcChannelClientEntry chl;
2417 SilcClientEntry sender, dest;
2418 SilcClientID *dest_id = NULL;
2419 SilcChannelEntry channel;
2420 SilcChannelID *channel_id = NULL;
2421 SilcIDListData idata;
2422 SilcBuffer idp, idp2, packet;
2423 unsigned char *tmp, *add, *del;
2425 uint16 ident = silc_command_get_ident(cmd->payload);
2427 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2429 /* Get Channel ID */
2430 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2433 SILC_STATUS_ERR_NO_CHANNEL_ID);
2436 channel_id = silc_id_payload_parse_id(tmp, len);
2438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2439 SILC_STATUS_ERR_NO_CHANNEL_ID);
2443 /* Get the channel entry */
2444 channel = silc_idlist_find_channel_by_id(server->local_list,
2447 channel = silc_idlist_find_channel_by_id(server->global_list,
2450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2451 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2456 /* Check whether the sender of this command is on the channel. */
2457 sender = (SilcClientEntry)sock->user_data;
2458 if (!silc_server_client_on_channel(sender, channel)) {
2459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2460 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2464 /* Check whether the channel is invite-only channel. If yes then the
2465 sender of this command must be at least channel operator. */
2466 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2467 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2468 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2470 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2475 /* Get destination client ID */
2476 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2480 dest_id = silc_id_payload_parse_id(tmp, len);
2482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2483 SILC_STATUS_ERR_NO_CLIENT_ID);
2487 /* Get the client entry */
2488 dest = silc_server_get_client_resolve(server, dest_id);
2490 if (server->server_type != SILC_SERVER) {
2491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2492 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2496 /* The client info is being resolved. Reprocess this packet after
2497 receiving the reply to the query. */
2498 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2500 silc_server_command_destructor,
2501 silc_server_command_invite,
2502 silc_server_command_dup(cmd));
2503 cmd->pending = TRUE;
2504 silc_free(channel_id);
2509 /* Check whether the requested client is already on the channel. */
2510 if (silc_server_client_on_channel(dest, channel)) {
2511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2512 SILC_STATUS_ERR_USER_ON_CHANNEL);
2516 /* Get route to the client */
2517 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2520 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2524 memset(invite, 0, sizeof(invite));
2525 strncat(invite, dest->nickname, strlen(dest->nickname));
2526 strncat(invite, "!", 1);
2527 strncat(invite, dest->username, strlen(dest->username));
2528 if (!strchr(dest->username, '@')) {
2529 strncat(invite, "@", 1);
2530 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2533 len = strlen(invite);
2534 if (!channel->invite_list)
2535 channel->invite_list = silc_calloc(len + 2,
2536 sizeof(*channel->invite_list));
2538 channel->invite_list = silc_realloc(channel->invite_list,
2539 sizeof(*channel->invite_list) *
2541 strlen(channel->invite_list) + 2));
2542 strncat(channel->invite_list, invite, len);
2543 strncat(channel->invite_list, ",", 1);
2545 /* Send notify to the client that is invited to the channel */
2546 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2547 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2548 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2550 SILC_NOTIFY_TYPE_INVITE, 3,
2551 idp->data, idp->len,
2552 channel->channel_name,
2553 strlen(channel->channel_name),
2554 idp2->data, idp2->len);
2555 silc_buffer_free(idp);
2556 silc_buffer_free(idp2);
2559 /* Add the client to the invite list of the channel */
2560 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2562 if (!channel->invite_list)
2563 channel->invite_list = silc_calloc(len + 2,
2564 sizeof(*channel->invite_list));
2566 channel->invite_list = silc_realloc(channel->invite_list,
2567 sizeof(*channel->invite_list) *
2569 strlen(channel->invite_list) + 2));
2570 if (add[len - 1] == ',')
2571 add[len - 1] = '\0';
2573 strncat(channel->invite_list, add, len);
2574 strncat(channel->invite_list, ",", 1);
2577 /* Get the invite to be removed and remove it from the list */
2578 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2579 if (del && channel->invite_list) {
2580 char *start, *end, *n;
2582 if (!strncmp(channel->invite_list, del,
2583 strlen(channel->invite_list) - 1)) {
2584 silc_free(channel->invite_list);
2585 channel->invite_list = NULL;
2587 start = strstr(channel->invite_list, del);
2588 if (start && strlen(start) >= len) {
2590 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2591 strncat(n, channel->invite_list, start - channel->invite_list);
2592 strncat(n, end + 1, ((channel->invite_list +
2593 strlen(channel->invite_list)) - end) - 1);
2594 silc_free(channel->invite_list);
2595 channel->invite_list = n;
2600 /* Send notify to the primary router */
2601 if (!server->standalone)
2602 silc_server_send_notify_invite(server, server->router->connection,
2603 server->server_type == SILC_ROUTER ?
2604 TRUE : FALSE, channel,
2605 sender->id, add, del);
2607 /* Send command reply */
2608 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2612 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2613 SILC_STATUS_OK, ident, 2,
2615 3, channel->invite_list,
2616 channel->invite_list ?
2617 strlen(channel->invite_list) : 0);
2620 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2621 SILC_STATUS_OK, ident, 1,
2623 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2624 packet->data, packet->len, FALSE);
2625 silc_buffer_free(packet);
2629 silc_free(channel_id);
2630 silc_server_command_free(cmd);
2635 SilcSocketConnection sock;
2639 /* Quits connection to client. This gets called if client won't
2640 close the connection even when it has issued QUIT command. */
2642 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2644 QuitInternal q = (QuitInternal)context;
2646 /* Free all client specific data, such as client entry and entires
2647 on channels this client may be on. */
2648 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2650 q->sock->user_data = NULL;
2652 /* Close the connection on our side */
2653 silc_server_close_connection(q->server, q->sock);
2655 silc_free(q->signoff);
2659 /* Quits SILC session. This is the normal way to disconnect client. */
2661 SILC_SERVER_CMD_FUNC(quit)
2663 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2664 SilcServer server = cmd->server;
2665 SilcSocketConnection sock = cmd->sock;
2667 unsigned char *tmp = NULL;
2670 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2672 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2675 /* Get destination ID */
2676 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2680 q = silc_calloc(1, sizeof(*q));
2683 q->signoff = tmp ? strdup(tmp) : NULL;
2685 /* We quit the connection with little timeout */
2686 silc_schedule_task_add(server->schedule, sock->sock,
2687 silc_server_command_quit_cb, (void *)q,
2688 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2691 silc_server_command_free(cmd);
2694 /* Server side of command KILL. This command is used by router operator
2695 to remove an client from the SILC Network temporarily. */
2697 SILC_SERVER_CMD_FUNC(kill)
2699 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2700 SilcServer server = cmd->server;
2701 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2702 SilcClientEntry remote_client;
2703 SilcClientID *client_id;
2704 unsigned char *tmp, *comment;
2705 uint32 tmp_len, tmp_len2;
2707 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2709 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2712 /* KILL command works only on router */
2713 if (server->server_type != SILC_ROUTER) {
2714 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2715 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2719 /* Check whether client has the permissions. */
2720 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2722 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2726 /* Get the client ID */
2727 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2730 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2733 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2736 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2740 /* Get the client entry */
2741 remote_client = silc_idlist_find_client_by_id(server->local_list,
2742 client_id, TRUE, NULL);
2743 if (!remote_client) {
2744 remote_client = silc_idlist_find_client_by_id(server->global_list,
2745 client_id, TRUE, NULL);
2746 if (!remote_client) {
2747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2748 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2754 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2758 /* Send reply to the sender */
2759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2762 /* Send the KILL notify packets. First send it to the channel, then
2763 to our primary router and then directly to the client who is being
2764 killed right now. */
2766 /* Send KILLED notify to the channels. It is not sent to the client
2767 as it will be sent differently destined directly to the client and not
2769 silc_server_send_notify_on_channels(server, remote_client,
2770 remote_client, SILC_NOTIFY_TYPE_KILLED,
2773 comment, comment ? tmp_len2 : 0);
2775 /* Send KILLED notify to primary route */
2776 if (!server->standalone)
2777 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2778 remote_client->id, comment);
2780 /* Send KILLED notify to the client directly */
2781 silc_server_send_notify_killed(server, remote_client->connection ?
2782 remote_client->connection :
2783 remote_client->router->connection, FALSE,
2784 remote_client->id, comment);
2786 /* Remove the client from all channels. This generates new keys to the
2787 channels as well. */
2788 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2791 /* Remove the client entry, If it is locally connected then we will also
2792 disconnect the client here */
2793 if (remote_client->connection) {
2794 /* Remove locally conneted client */
2795 SilcSocketConnection sock = remote_client->connection;
2796 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2797 silc_server_close_connection(server, sock);
2799 /* Remove remote client */
2800 if (!silc_idlist_del_client(server->global_list, remote_client))
2801 silc_idlist_del_client(server->local_list, remote_client);
2805 silc_server_command_free(cmd);
2808 /* Server side of command INFO. This sends information about us to
2809 the client. If client requested specific server we will send the
2810 command to that server. */
2812 SILC_SERVER_CMD_FUNC(info)
2814 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2815 SilcServer server = cmd->server;
2816 SilcBuffer packet, idp;
2819 char *dest_server, *server_info = NULL, *server_name;
2820 uint16 ident = silc_command_get_ident(cmd->payload);
2821 SilcServerEntry entry = NULL;
2822 SilcServerID *server_id = NULL;
2824 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2826 /* Get server name */
2827 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2830 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2832 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2835 SILC_STATUS_ERR_NO_SERVER_ID);
2841 /* Check whether we have this server cached */
2842 entry = silc_idlist_find_server_by_id(server->local_list,
2843 server_id, TRUE, NULL);
2845 entry = silc_idlist_find_server_by_id(server->global_list,
2846 server_id, TRUE, NULL);
2847 if (!entry && server->server_type != SILC_SERVER) {
2848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2849 SILC_STATUS_ERR_NO_SUCH_SERVER);
2855 /* Some buggy servers has sent request to router about themselves. */
2856 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2859 if ((!dest_server && !server_id && !entry) || (entry &&
2860 entry == server->id_entry) ||
2861 (dest_server && !cmd->pending &&
2862 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2863 /* Send our reply */
2864 char info_string[256];
2866 memset(info_string, 0, sizeof(info_string));
2867 snprintf(info_string, sizeof(info_string),
2868 "location: %s server: %s admin: %s <%s>",
2869 server->config->admin_info->location,
2870 server->config->admin_info->server_type,
2871 server->config->admin_info->admin_name,
2872 server->config->admin_info->admin_email);
2874 server_info = info_string;
2875 entry = server->id_entry;
2877 /* Check whether we have this server cached */
2878 if (!entry && dest_server) {
2879 entry = silc_idlist_find_server_by_name(server->global_list,
2880 dest_server, TRUE, NULL);
2882 entry = silc_idlist_find_server_by_name(server->local_list,
2883 dest_server, TRUE, NULL);
2887 if (!cmd->pending &&
2888 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2889 /* Send to the server */
2893 old_ident = silc_command_get_ident(cmd->payload);
2894 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2895 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2897 silc_server_packet_send(server, entry->connection,
2898 SILC_PACKET_COMMAND, cmd->packet->flags,
2899 tmpbuf->data, tmpbuf->len, TRUE);
2901 /* Reprocess this packet after received reply from router */
2902 silc_server_command_pending(server, SILC_COMMAND_INFO,
2903 silc_command_get_ident(cmd->payload),
2904 silc_server_command_destructor,
2905 silc_server_command_info,
2906 silc_server_command_dup(cmd));
2907 cmd->pending = TRUE;
2908 silc_command_set_ident(cmd->payload, old_ident);
2909 silc_buffer_free(tmpbuf);
2913 if (!entry && !cmd->pending && !server->standalone) {
2914 /* Send to the primary router */
2918 old_ident = silc_command_get_ident(cmd->payload);
2919 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2920 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2922 silc_server_packet_send(server, server->router->connection,
2923 SILC_PACKET_COMMAND, cmd->packet->flags,
2924 tmpbuf->data, tmpbuf->len, TRUE);
2926 /* Reprocess this packet after received reply from router */
2927 silc_server_command_pending(server, SILC_COMMAND_INFO,
2928 silc_command_get_ident(cmd->payload),
2929 silc_server_command_destructor,
2930 silc_server_command_info,
2931 silc_server_command_dup(cmd));
2932 cmd->pending = TRUE;
2933 silc_command_set_ident(cmd->payload, old_ident);
2934 silc_buffer_free(tmpbuf);
2939 silc_free(server_id);
2942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2943 SILC_STATUS_ERR_NO_SUCH_SERVER);
2947 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2949 server_info = entry->server_info;
2950 server_name = entry->server_name;
2952 /* Send the reply */
2953 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2954 SILC_STATUS_OK, ident, 3,
2955 2, idp->data, idp->len,
2957 strlen(server_name),
2960 strlen(server_info) : 0);
2961 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2962 packet->data, packet->len, FALSE);
2964 silc_buffer_free(packet);
2965 silc_buffer_free(idp);
2968 silc_server_command_free(cmd);
2971 /* Server side of command PING. This just replies to the ping. */
2973 SILC_SERVER_CMD_FUNC(ping)
2975 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2976 SilcServer server = cmd->server;
2981 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2984 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2986 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2987 SILC_STATUS_ERR_NO_SERVER_ID);
2990 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2994 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2995 /* Send our reply */
2996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3000 SILC_STATUS_ERR_NO_SUCH_SERVER);
3007 silc_server_command_free(cmd);
3010 /* Internal routine to join channel. The channel sent to this function
3011 has been either created or resolved from ID lists. This joins the sent
3012 client to the channel. */
3014 static void silc_server_command_join_channel(SilcServer server,
3015 SilcServerCommandContext cmd,
3016 SilcChannelEntry channel,
3017 SilcClientID *client_id,
3021 const unsigned char *auth,
3024 SilcSocketConnection sock = cmd->sock;
3026 uint32 tmp_len, user_count;
3027 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3028 SilcClientEntry client;
3029 SilcChannelClientEntry chl;
3030 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3031 uint16 ident = silc_command_get_ident(cmd->payload);
3032 char check[512], check2[512];
3033 bool founder = FALSE;
3035 SILC_LOG_DEBUG(("Start"));
3040 /* Get the client entry */
3041 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3042 client = (SilcClientEntry)sock->user_data;
3044 client = silc_server_get_client_resolve(server, client_id);
3049 /* The client info is being resolved. Reprocess this packet after
3050 receiving the reply to the query. */
3051 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3052 server->cmd_ident, NULL,
3053 silc_server_command_join,
3054 silc_server_command_dup(cmd));
3055 cmd->pending = TRUE;
3059 cmd->pending = FALSE;
3063 * Check founder auth payload if provided. If client can gain founder
3064 * privileges it can override various conditions on joining the channel,
3065 * and can have directly the founder mode set on the channel.
3067 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3068 SilcIDListData idata = (SilcIDListData)client;
3070 if (channel->founder_key && idata->public_key &&
3071 silc_pkcs_public_key_compare(channel->founder_key,
3072 idata->public_key)) {
3073 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3074 (void *)channel->founder_passwd :
3075 (void *)channel->founder_key);
3076 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3077 channel->founder_passwd_len : 0);
3079 /* Check whether the client is to become founder */
3080 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3081 auth_data, auth_data_len,
3082 idata->hash, client->id, SILC_ID_CLIENT)) {
3083 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3090 * Check channel modes
3094 memset(check, 0, sizeof(check));
3095 memset(check2, 0, sizeof(check2));
3096 strncat(check, client->nickname, strlen(client->nickname));
3097 strncat(check, "!", 1);
3098 strncat(check, client->username, strlen(client->username));
3099 if (!strchr(client->username, '@')) {
3100 strncat(check, "@", 1);
3101 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3104 strncat(check2, client->nickname, strlen(client->nickname));
3105 if (!strchr(client->nickname, '@')) {
3106 strncat(check2, "@", 1);
3107 strncat(check2, server->server_name, strlen(server->server_name));
3109 strncat(check2, "!", 1);
3110 strncat(check2, client->username, strlen(client->username));
3111 if (!strchr(client->username, '@')) {
3112 strncat(check2, "@", 1);
3113 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3116 /* Check invite list if channel is invite-only channel */
3117 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3118 if (!channel->invite_list ||
3119 (!silc_string_match(channel->invite_list, check) &&
3120 !silc_string_match(channel->invite_list, check2))) {
3121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3122 SILC_STATUS_ERR_NOT_INVITED);
3127 /* Check ban list if it exists. If the client's nickname, server,
3128 username and/or hostname is in the ban list the access to the
3129 channel is denied. */
3130 if (channel->ban_list) {
3131 if (!channel->ban_list ||
3132 silc_string_match(channel->ban_list, check) ||
3133 silc_string_match(channel->ban_list, check2)) {
3134 silc_server_command_send_status_reply(
3135 cmd, SILC_COMMAND_JOIN,
3136 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3141 /* Check user count limit if set. */
3142 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3143 if (silc_hash_table_count(channel->user_list) + 1 >
3144 channel->user_limit) {
3145 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3146 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3152 /* Check the channel passphrase if set. */
3153 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3154 /* Get passphrase */
3155 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3157 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3158 memcpy(passphrase, tmp, tmp_len);
3161 if (!passphrase || !channel->passphrase ||
3162 memcmp(channel->passphrase, passphrase,
3163 strlen(channel->passphrase))) {
3164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3165 SILC_STATUS_ERR_BAD_PASSWORD);
3171 * Client is allowed to join to the channel. Make it happen.
3174 /* Check whether the client already is on the channel */
3175 if (silc_server_client_on_channel(client, channel)) {
3176 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3177 SILC_STATUS_ERR_USER_ON_CHANNEL);
3181 /* Generate new channel key as protocol dictates */
3183 if (!silc_server_create_channel_key(server, channel, 0))
3186 /* Send the channel key. This is broadcasted to the channel but is not
3187 sent to the client who is joining to the channel. */
3188 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3189 silc_server_send_channel_key(server, NULL, channel,
3190 server->server_type == SILC_ROUTER ?
3191 FALSE : !server->standalone);
3194 /* Join the client to the channel by adding it to channel's user list.
3195 Add also the channel to client entry's channels list for fast cross-
3197 chl = silc_calloc(1, sizeof(*chl));
3199 chl->client = client;
3200 chl->channel = channel;
3201 silc_hash_table_add(channel->user_list, client, chl);
3202 silc_hash_table_add(client->channels, channel, chl);
3204 /* Get users on the channel */
3205 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3208 /* Encode Client ID Payload of the original client who wants to join */
3209 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3211 /* Encode command reply packet */
3212 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3213 SILC_PUT32_MSB(channel->mode, mode);
3214 SILC_PUT32_MSB(created, tmp2);
3215 SILC_PUT32_MSB(user_count, tmp3);
3217 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3218 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3219 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3220 strlen(channel->channel_key->
3222 channel->channel_key->cipher->name,
3223 channel->key_len / 8, channel->key);
3228 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3229 SILC_STATUS_OK, ident, 13,
3230 2, channel->channel_name,
3231 strlen(channel->channel_name),
3232 3, chidp->data, chidp->len,
3233 4, clidp->data, clidp->len,
3236 7, keyp ? keyp->data : NULL,
3237 keyp ? keyp->len : 0,
3238 8, channel->ban_list,
3240 strlen(channel->ban_list) : 0,
3241 9, channel->invite_list,
3242 channel->invite_list ?
3243 strlen(channel->invite_list) : 0,
3246 strlen(channel->topic) : 0,
3247 11, silc_hmac_get_name(channel->hmac),
3248 strlen(silc_hmac_get_name(channel->
3251 13, user_list->data, user_list->len,
3252 14, mode_list->data,
3255 /* Send command reply */
3256 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3257 reply->data, reply->len, FALSE);
3259 /* Send JOIN notify to locally connected clients on the channel. If
3260 we are normal server then router will send or have sent JOIN notify
3261 already. However since we've added the client already to our channel
3262 we'll ignore it (in packet_receive.c) so we must send it here. If
3263 we are router then this will send it to local clients and local
3265 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3266 SILC_NOTIFY_TYPE_JOIN, 2,
3267 clidp->data, clidp->len,
3268 chidp->data, chidp->len);
3270 if (!cmd->pending) {
3271 /* Send JOIN notify packet to our primary router */
3272 if (!server->standalone)
3273 silc_server_send_notify_join(server, server->router->connection,
3274 server->server_type == SILC_ROUTER ?
3275 TRUE : FALSE, channel, client->id);
3278 /* Distribute the channel key to all backup routers. */
3279 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3280 keyp->data, keyp->len, FALSE, TRUE);
3282 /* If client became founder by providing correct founder auth data
3283 notify the mode change to the channel. */
3285 SILC_PUT32_MSB(chl->mode, mode);
3286 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3287 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3288 clidp->data, clidp->len,
3289 mode, 4, clidp->data, clidp->len);
3291 /* Set CUMODE notify type to network */
3292 if (!server->standalone)
3293 silc_server_send_notify_cumode(server, server->router->connection,
3294 server->server_type == SILC_ROUTER ?
3295 TRUE : FALSE, channel,
3296 chl->mode, client->id, SILC_ID_CLIENT,
3301 silc_buffer_free(reply);
3302 silc_buffer_free(clidp);
3303 silc_buffer_free(chidp);
3304 silc_buffer_free(keyp);
3305 silc_buffer_free(user_list);
3306 silc_buffer_free(mode_list);
3309 silc_free(passphrase);
3312 /* Server side of command JOIN. Joins client into requested channel. If
3313 the channel does not exist it will be created. */
3315 SILC_SERVER_CMD_FUNC(join)
3317 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3318 SilcServer server = cmd->server;
3319 unsigned char *auth;
3320 uint32 tmp_len, auth_len;
3321 char *tmp, *channel_name = NULL, *cipher, *hmac;
3322 SilcChannelEntry channel;
3324 bool created = FALSE, create_key = TRUE;
3325 SilcClientID *client_id;
3327 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3329 /* Get channel name */
3330 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3333 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3338 if (strlen(channel_name) > 256)
3339 channel_name[255] = '\0';
3341 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3343 SILC_STATUS_ERR_BAD_CHANNEL);
3347 /* Get Client ID of the client who is joining to the channel */
3348 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3350 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3351 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3354 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3357 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3361 /* Get cipher, hmac name and auth payload */
3362 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3363 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3364 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3366 /* See if the channel exists */
3367 channel = silc_idlist_find_channel_by_name(server->local_list,
3368 channel_name, NULL);
3370 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3371 /* If this is coming from client the Client ID in the command packet must
3372 be same as the client's ID. */
3373 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3374 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3375 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3377 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3382 if (!channel || channel->disabled) {
3383 /* Channel not found */
3385 /* If we are standalone server we don't have a router, we just create
3386 the channel by ourselves. */
3387 if (server->standalone) {
3388 channel = silc_server_create_new_channel(server, server->id, cipher,
3389 hmac, channel_name, TRUE);
3391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3392 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3396 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3402 /* The channel does not exist on our server. If we are normal server
3403 we will send JOIN command to our router which will handle the
3404 joining procedure (either creates the channel if it doesn't exist
3405 or joins the client to it). */
3406 if (server->server_type != SILC_ROUTER) {
3410 /* If this is pending command callback then we've resolved
3411 it and it didn't work, return since we've notified the
3412 client already in the command reply callback. */
3416 old_ident = silc_command_get_ident(cmd->payload);
3417 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3418 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3420 /* Send JOIN command to our router */
3421 silc_server_packet_send(server, (SilcSocketConnection)
3422 server->router->connection,
3423 SILC_PACKET_COMMAND, cmd->packet->flags,
3424 tmpbuf->data, tmpbuf->len, TRUE);
3426 /* Reprocess this packet after received reply from router */
3427 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3428 silc_command_get_ident(cmd->payload),
3429 silc_server_command_destructor,
3430 silc_server_command_join,
3431 silc_server_command_dup(cmd));
3432 cmd->pending = TRUE;
3436 /* We are router and the channel does not seem exist so we will check
3437 our global list as well for the channel. */
3438 channel = silc_idlist_find_channel_by_name(server->global_list,
3439 channel_name, NULL);
3441 /* Channel really does not exist, create it */
3442 channel = silc_server_create_new_channel(server, server->id, cipher,
3443 hmac, channel_name, TRUE);
3445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3446 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3450 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3458 /* Channel not found */
3460 /* If the command came from router and we are normal server then
3461 something went wrong with the joining as the channel was not found.
3462 We can't do anything else but ignore this. */
3463 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3464 server->server_type != SILC_ROUTER)
3467 /* We are router and the channel does not seem exist so we will check
3468 our global list as well for the channel. */
3469 channel = silc_idlist_find_channel_by_name(server->global_list,
3470 channel_name, NULL);
3472 /* Channel really does not exist, create it */
3473 channel = silc_server_create_new_channel(server, server->id, cipher,
3474 hmac, channel_name, TRUE);
3476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3477 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3481 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3488 /* Check whether the channel was created by our router */
3489 if (cmd->pending && context2) {
3490 SilcServerCommandReplyContext reply =
3491 (SilcServerCommandReplyContext)context2;
3492 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3493 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3494 SILC_GET32_MSB(created, tmp);
3495 create_key = FALSE; /* Router returned the key already */
3499 /* If the channel does not have global users and is also empty the client
3500 will be the channel founder and operator. */
3501 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3502 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3504 /* Join to the channel */
3505 silc_server_command_join_channel(server, cmd, channel, client_id,
3506 created, create_key, umode,
3509 silc_free(client_id);
3512 silc_server_command_free(cmd);
3515 /* Server side of command MOTD. Sends server's current "message of the
3516 day" to the client. */
3518 SILC_SERVER_CMD_FUNC(motd)
3520 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3521 SilcServer server = cmd->server;
3522 SilcBuffer packet, idp;
3523 char *motd, *dest_server;
3525 uint16 ident = silc_command_get_ident(cmd->payload);
3527 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3529 /* Get server name */
3530 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3533 SILC_STATUS_ERR_NO_SUCH_SERVER);
3537 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3540 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3542 if (server->config && server->config->motd &&
3543 server->config->motd->motd_file) {
3545 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3550 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3551 SILC_STATUS_OK, ident, 2,
3556 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3557 SILC_STATUS_OK, ident, 1,
3561 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3562 packet->data, packet->len, FALSE);
3563 silc_buffer_free(packet);
3564 silc_buffer_free(idp);
3566 SilcServerEntry entry;
3568 /* Check whether we have this server cached */
3569 entry = silc_idlist_find_server_by_name(server->global_list,
3570 dest_server, TRUE, NULL);
3572 entry = silc_idlist_find_server_by_name(server->local_list,
3573 dest_server, TRUE, NULL);
3576 if (server->server_type != SILC_SERVER && !cmd->pending &&
3577 entry && !entry->motd) {
3578 /* Send to the server */
3582 old_ident = silc_command_get_ident(cmd->payload);
3583 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3584 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3586 silc_server_packet_send(server, entry->connection,
3587 SILC_PACKET_COMMAND, cmd->packet->flags,
3588 tmpbuf->data, tmpbuf->len, TRUE);
3590 /* Reprocess this packet after received reply from router */
3591 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3592 silc_command_get_ident(cmd->payload),
3593 silc_server_command_destructor,
3594 silc_server_command_motd,
3595 silc_server_command_dup(cmd));
3596 cmd->pending = TRUE;
3597 silc_command_set_ident(cmd->payload, old_ident);
3598 silc_buffer_free(tmpbuf);
3602 if (!entry && !cmd->pending && !server->standalone) {
3603 /* Send to the primary router */
3607 old_ident = silc_command_get_ident(cmd->payload);
3608 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3609 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3611 silc_server_packet_send(server, server->router->connection,
3612 SILC_PACKET_COMMAND, cmd->packet->flags,
3613 tmpbuf->data, tmpbuf->len, TRUE);
3615 /* Reprocess this packet after received reply from router */
3616 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3617 silc_command_get_ident(cmd->payload),
3618 silc_server_command_destructor,
3619 silc_server_command_motd,
3620 silc_server_command_dup(cmd));
3621 cmd->pending = TRUE;
3622 silc_command_set_ident(cmd->payload, old_ident);
3623 silc_buffer_free(tmpbuf);
3628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3629 SILC_STATUS_ERR_NO_SUCH_SERVER);
3633 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3634 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3635 SILC_STATUS_OK, ident, 2,
3639 strlen(entry->motd) : 0);
3640 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3641 packet->data, packet->len, FALSE);
3642 silc_buffer_free(packet);
3643 silc_buffer_free(idp);
3647 silc_server_command_free(cmd);
3650 /* Server side of command UMODE. Client can use this command to set/unset
3651 user mode. Client actually cannot set itself to be as server/router
3652 operator so this can be used only to unset the modes. */
3654 SILC_SERVER_CMD_FUNC(umode)
3656 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3657 SilcServer server = cmd->server;
3658 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3660 unsigned char *tmp_mask;
3662 uint16 ident = silc_command_get_ident(cmd->payload);
3664 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3667 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3669 /* Get the client's mode mask */
3670 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3673 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3676 SILC_GET32_MSB(mask, tmp_mask);
3682 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3683 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3684 /* Cannot operator mode */
3685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3686 SILC_STATUS_ERR_PERM_DENIED);
3690 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3691 /* Remove the server operator rights */
3692 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3695 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3696 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3697 /* Cannot operator mode */
3698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3699 SILC_STATUS_ERR_PERM_DENIED);
3703 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3704 /* Remove the router operator rights */
3705 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3708 if (mask & SILC_UMODE_GONE) {
3709 client->mode |= SILC_UMODE_GONE;
3711 if (client->mode & SILC_UMODE_GONE)
3712 /* Remove the gone status */
3713 client->mode &= ~SILC_UMODE_GONE;
3716 /* Send UMODE change to primary router */
3717 if (!server->standalone)
3718 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3719 client->id, client->mode);
3721 /* Send command reply to sender */
3722 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3723 SILC_STATUS_OK, ident, 1,
3725 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3726 packet->data, packet->len, FALSE);
3727 silc_buffer_free(packet);
3730 silc_server_command_free(cmd);
3733 /* Checks that client has rights to add or remove channel modes. If any
3734 of the checks fails FALSE is returned. */
3736 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3737 SilcChannelClientEntry client,
3740 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3741 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3743 /* Check whether has rights to change anything */
3744 if (!is_op && !is_fo)
3747 /* Check whether has rights to change everything */
3751 /* We know that client is channel operator, check that they are not
3752 changing anything that requires channel founder rights. Rest of the
3753 modes are available automatically for channel operator. */
3755 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3756 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3757 if (is_op && !is_fo)
3760 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3761 if (is_op && !is_fo)
3766 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3767 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3768 if (is_op && !is_fo)
3771 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3772 if (is_op && !is_fo)
3777 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3778 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3779 if (is_op && !is_fo)
3782 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3783 if (is_op && !is_fo)
3788 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3789 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3790 if (is_op && !is_fo)
3793 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3794 if (is_op && !is_fo)
3802 /* Server side command of CMODE. Changes channel mode */
3804 SILC_SERVER_CMD_FUNC(cmode)
3806 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3807 SilcServer server = cmd->server;
3808 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3809 SilcIDListData idata = (SilcIDListData)client;
3810 SilcChannelID *channel_id;
3811 SilcChannelEntry channel;
3812 SilcChannelClientEntry chl;
3813 SilcBuffer packet, cidp;
3814 unsigned char *tmp, *tmp_id, *tmp_mask;
3815 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3816 uint32 mode_mask, tmp_len, tmp_len2;
3817 uint16 ident = silc_command_get_ident(cmd->payload);
3819 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3821 /* Get Channel ID */
3822 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3824 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3825 SILC_STATUS_ERR_NO_CHANNEL_ID);
3828 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3831 SILC_STATUS_ERR_NO_CHANNEL_ID);
3835 /* Get the channel mode mask */
3836 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3839 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3842 SILC_GET32_MSB(mode_mask, tmp_mask);
3844 /* Get channel entry */
3845 channel = silc_idlist_find_channel_by_id(server->local_list,
3848 channel = silc_idlist_find_channel_by_id(server->global_list,
3851 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3852 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3857 /* Check whether this client is on the channel */
3858 if (!silc_server_client_on_channel(client, channel)) {
3859 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3860 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3864 /* Get entry to the channel user list */
3865 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3867 /* Check that client has rights to change any requested channel modes */
3868 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3869 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3870 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3875 * Check the modes. Modes that requires nothing special operation are
3879 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3880 /* Channel uses private keys to protect traffic. Client(s) has set the
3881 key locally they want to use, server does not know that key. */
3882 /* Nothing interesting to do here */
3884 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3885 /* The mode is removed and we need to generate and distribute
3886 new channel key. Clients are not using private channel keys
3887 anymore after this. */
3889 /* Re-generate channel key */
3890 if (!silc_server_create_channel_key(server, channel, 0))
3893 /* Send the channel key. This sends it to our local clients and if
3894 we are normal server to our router as well. */
3895 silc_server_send_channel_key(server, NULL, channel,
3896 server->server_type == SILC_ROUTER ?
3897 FALSE : !server->standalone);
3899 cipher = channel->channel_key->cipher->name;
3900 hmac = (char *)silc_hmac_get_name(channel->hmac);
3904 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3905 /* User limit is set on channel */
3908 /* Get user limit */
3909 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3911 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3913 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3917 SILC_GET32_MSB(user_limit, tmp);
3918 channel->user_limit = user_limit;
3921 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3922 /* User limit mode is unset. Remove user limit */
3923 channel->user_limit = 0;
3926 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3927 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3928 /* Passphrase has been set to channel */
3930 /* Get the passphrase */
3931 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3934 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3938 /* Save the passphrase */
3939 passphrase = channel->passphrase = strdup(tmp);
3942 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3943 /* Passphrase mode is unset. remove the passphrase */
3944 if (channel->passphrase) {
3945 silc_free(channel->passphrase);
3946 channel->passphrase = NULL;
3951 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3952 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3953 /* Cipher to use protect the traffic */
3954 SilcCipher newkey, oldkey;
3957 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3960 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3964 /* Delete old cipher and allocate the new one */
3965 if (!silc_cipher_alloc(cipher, &newkey)) {
3966 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3967 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3971 oldkey = channel->channel_key;
3972 channel->channel_key = newkey;
3974 /* Re-generate channel key */
3975 if (!silc_server_create_channel_key(server, channel, 0)) {
3976 /* We don't have new key, revert to old one */
3977 channel->channel_key = oldkey;
3981 /* Remove old channel key for good */
3982 silc_cipher_free(oldkey);
3984 /* Send the channel key. This sends it to our local clients and if
3985 we are normal server to our router as well. */
3986 silc_server_send_channel_key(server, NULL, channel,
3987 server->server_type == SILC_ROUTER ?
3988 FALSE : !server->standalone);
3991 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3992 /* Cipher mode is unset. Remove the cipher and revert back to
3994 SilcCipher newkey, oldkey;
3995 cipher = channel->cipher;
3997 /* Delete old cipher and allocate default one */
3998 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4000 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4004 oldkey = channel->channel_key;
4005 channel->channel_key = newkey;
4007 /* Re-generate channel key */
4008 if (!silc_server_create_channel_key(server, channel, 0)) {
4009 /* We don't have new key, revert to old one */
4010 channel->channel_key = oldkey;
4014 /* Remove old channel key for good */
4015 silc_cipher_free(oldkey);
4017 /* Send the channel key. This sends it to our local clients and if
4018 we are normal server to our router as well. */
4019 silc_server_send_channel_key(server, NULL, channel,
4020 server->server_type == SILC_ROUTER ?
4021 FALSE : !server->standalone);
4025 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4026 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4027 /* HMAC to use protect the traffic */
4028 unsigned char hash[32];
4032 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4035 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4039 /* Delete old hmac and allocate the new one */
4040 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4042 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4046 silc_hmac_free(channel->hmac);
4047 channel->hmac = newhmac;
4049 /* Set the HMAC key out of current channel key. The client must do
4051 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4052 channel->key_len / 8, hash);
4053 silc_hmac_set_key(channel->hmac, hash,
4054 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4055 memset(hash, 0, sizeof(hash));
4058 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4059 /* Hmac mode is unset. Remove the hmac and revert back to
4062 unsigned char hash[32];
4063 hmac = channel->hmac_name;
4065 /* Delete old hmac and allocate default one */
4066 silc_hmac_free(channel->hmac);
4067 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4069 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4073 silc_hmac_free(channel->hmac);
4074 channel->hmac = newhmac;
4076 /* Set the HMAC key out of current channel key. The client must do
4078 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4079 channel->key_len / 8,
4081 silc_hmac_set_key(channel->hmac, hash,
4082 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4083 memset(hash, 0, sizeof(hash));
4087 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4088 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4089 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4090 /* Set the founder authentication */
4091 SilcAuthPayload auth;
4093 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4096 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4100 auth = silc_auth_payload_parse(tmp, tmp_len);
4102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4103 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4107 /* Save the public key */
4108 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4109 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4112 channel->founder_method = silc_auth_get_method(auth);
4114 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4115 tmp = silc_auth_get_data(auth, &tmp_len);
4116 channel->founder_passwd =
4117 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4118 memcpy(channel->founder_passwd, tmp, tmp_len);
4119 channel->founder_passwd_len = tmp_len;
4121 /* Verify the payload before setting the mode */
4122 if (!silc_auth_verify(auth, channel->founder_method,
4123 channel->founder_key, 0, idata->hash,
4124 client->id, SILC_ID_CLIENT)) {
4125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4126 SILC_STATUS_ERR_AUTH_FAILED);
4131 silc_auth_payload_free(auth);
4135 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4136 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4137 if (channel->founder_key)
4138 silc_pkcs_public_key_free(channel->founder_key);
4139 if (channel->founder_passwd) {
4140 silc_free(channel->founder_passwd);
4141 channel->founder_passwd = NULL;
4147 /* Finally, set the mode */
4148 channel->mode = mode_mask;
4150 /* Send CMODE_CHANGE notify. */
4151 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4152 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4153 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4154 cidp->data, cidp->len,
4156 cipher, cipher ? strlen(cipher) : 0,
4157 hmac, hmac ? strlen(hmac) : 0,
4158 passphrase, passphrase ?
4159 strlen(passphrase) : 0);
4161 /* Set CMODE notify type to network */
4162 if (!server->standalone)
4163 silc_server_send_notify_cmode(server, server->router->connection,
4164 server->server_type == SILC_ROUTER ?
4165 TRUE : FALSE, channel,
4166 mode_mask, client->id, SILC_ID_CLIENT,
4167 cipher, hmac, passphrase);
4169 /* Send command reply to sender */
4170 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4171 SILC_STATUS_OK, ident, 2,
4172 2, tmp_id, tmp_len2,
4174 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4175 packet->data, packet->len, FALSE);
4177 silc_buffer_free(packet);
4178 silc_free(channel_id);
4179 silc_buffer_free(cidp);
4182 silc_server_command_free(cmd);
4185 /* Server side of CUMODE command. Changes client's mode on a channel. */
4187 SILC_SERVER_CMD_FUNC(cumode)
4189 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4190 SilcServer server = cmd->server;
4191 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4192 SilcIDListData idata = (SilcIDListData)client;
4193 SilcChannelID *channel_id;
4194 SilcClientID *client_id;
4195 SilcChannelEntry channel;
4196 SilcClientEntry target_client;
4197 SilcChannelClientEntry chl;
4198 SilcBuffer packet, idp;
4199 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4200 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4202 uint16 ident = silc_command_get_ident(cmd->payload);
4204 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4206 /* Get Channel ID */
4207 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4210 SILC_STATUS_ERR_NO_CHANNEL_ID);
4213 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4216 SILC_STATUS_ERR_NO_CHANNEL_ID);
4220 /* Get channel entry */
4221 channel = silc_idlist_find_channel_by_id(server->local_list,
4224 channel = silc_idlist_find_channel_by_id(server->global_list,
4227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4228 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4233 /* Check whether sender is on the channel */
4234 if (!silc_server_client_on_channel(client, channel)) {
4235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4236 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4240 /* Check that client has rights to change other's rights */
4241 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4242 sender_mask = chl->mode;
4244 /* Get the target client's channel mode mask */
4245 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4247 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4248 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4251 SILC_GET32_MSB(target_mask, tmp_mask);
4253 /* Get target Client ID */
4254 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4257 SILC_STATUS_ERR_NO_CLIENT_ID);
4260 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4263 SILC_STATUS_ERR_NO_CLIENT_ID);
4267 /* Get target client's entry */
4268 target_client = silc_idlist_find_client_by_id(server->local_list,
4269 client_id, TRUE, NULL);
4270 if (!target_client) {
4271 target_client = silc_idlist_find_client_by_id(server->global_list,
4272 client_id, TRUE, NULL);
4275 if (target_client != client &&
4276 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4277 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4279 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4283 /* Check whether target client is on the channel */
4284 if (target_client != client) {
4285 if (!silc_server_client_on_channel(target_client, channel)) {
4286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4287 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4291 /* Get entry to the channel user list */
4292 silc_hash_table_find(channel->user_list, target_client, NULL,
4300 /* If the target client is founder, no one else can change their mode
4302 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4304 SILC_STATUS_ERR_NOT_YOU);
4308 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4309 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4310 /* The client tries to claim the founder rights. */
4311 unsigned char *tmp_auth;
4312 uint32 tmp_auth_len, auth_len;
4315 if (target_client != client) {
4316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4317 SILC_STATUS_ERR_NOT_YOU);
4321 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4322 !channel->founder_key || !idata->public_key ||
4323 !silc_pkcs_public_key_compare(channel->founder_key,
4324 idata->public_key)) {
4325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4326 SILC_STATUS_ERR_NOT_YOU);
4330 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4333 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4337 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4338 (void *)channel->founder_passwd : (void *)channel->founder_key);
4339 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4340 channel->founder_passwd_len : 0);
4342 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4343 channel->founder_method, auth, auth_len,
4344 idata->hash, client->id, SILC_ID_CLIENT)) {
4345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4346 SILC_STATUS_ERR_AUTH_FAILED);
4350 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4354 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4355 if (target_client == client) {
4356 /* Remove channel founder rights from itself */
4357 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4361 SILC_STATUS_ERR_NOT_YOU);
4367 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4368 /* Promote to operator */
4369 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4370 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4371 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4373 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4377 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4381 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4382 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4383 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4385 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4389 /* Demote to normal user */
4390 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4395 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4396 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4398 /* Send notify to channel, notify only if mode was actually changed. */
4400 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4401 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4402 idp->data, idp->len,
4406 /* Set CUMODE notify type to network */
4407 if (!server->standalone)
4408 silc_server_send_notify_cumode(server, server->router->connection,
4409 server->server_type == SILC_ROUTER ?
4410 TRUE : FALSE, channel,
4411 target_mask, client->id,
4416 /* Send command reply to sender */
4417 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4418 SILC_STATUS_OK, ident, 3,
4420 3, tmp_ch_id, tmp_ch_len,
4421 4, tmp_id, tmp_len);
4422 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4423 packet->data, packet->len, FALSE);
4425 silc_buffer_free(packet);
4426 silc_free(channel_id);
4427 silc_free(client_id);
4428 silc_buffer_free(idp);
4431 silc_server_command_free(cmd);
4434 /* Server side of KICK command. Kicks client out of channel. */
4436 SILC_SERVER_CMD_FUNC(kick)
4438 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4439 SilcServer server = cmd->server;
4440 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4441 SilcClientEntry target_client;
4442 SilcChannelID *channel_id;
4443 SilcClientID *client_id;
4444 SilcChannelEntry channel;
4445 SilcChannelClientEntry chl;
4447 uint32 tmp_len, target_idp_len;
4448 unsigned char *tmp, *comment, *target_idp;
4450 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4452 /* Get Channel ID */
4453 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4456 SILC_STATUS_ERR_NO_CHANNEL_ID);
4459 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4462 SILC_STATUS_ERR_NO_CHANNEL_ID);
4466 /* Get channel entry */
4467 channel = silc_idlist_find_channel_by_id(server->local_list,
4470 channel = silc_idlist_find_channel_by_id(server->local_list,
4473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4474 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4479 /* Check whether sender is on the channel */
4480 if (!silc_server_client_on_channel(client, channel)) {
4481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4482 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4486 /* Check that the kicker is channel operator or channel founder */
4487 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4488 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4490 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4494 /* Get target Client ID */
4495 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4497 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4498 SILC_STATUS_ERR_NO_CLIENT_ID);
4501 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4504 SILC_STATUS_ERR_NO_CLIENT_ID);
4508 /* Get target client's entry */
4509 target_client = silc_idlist_find_client_by_id(server->local_list,
4510 client_id, TRUE, NULL);
4511 if (!target_client) {
4512 target_client = silc_idlist_find_client_by_id(server->global_list,
4513 client_id, TRUE, NULL);
4516 /* Check that the target client is not channel founder. Channel founder
4517 cannot be kicked from the channel. */
4518 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4519 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4521 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4525 /* Check whether target client is on the channel */
4526 if (!silc_server_client_on_channel(target_client, channel)) {
4527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4528 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4534 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4538 /* Send command reply to sender */
4539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4542 /* Send KICKED notify to local clients on the channel */
4543 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4544 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4545 SILC_NOTIFY_TYPE_KICKED, 3,
4546 target_idp, target_idp_len,
4547 comment, comment ? strlen(comment) : 0,
4548 idp->data, idp->len);
4549 silc_buffer_free(idp);
4551 /* Remove the client from the channel. If the channel does not exist
4552 after removing the client then the client kicked itself off the channel
4553 and we don't have to send anything after that. */
4554 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4555 target_client, FALSE))
4558 /* Send KICKED notify to primary route */
4559 if (!server->standalone)
4560 silc_server_send_notify_kicked(server, server->router->connection,
4561 server->server_type == SILC_ROUTER ?
4562 TRUE : FALSE, channel,
4563 target_client->id, comment);
4565 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4566 /* Re-generate channel key */
4567 if (!silc_server_create_channel_key(server, channel, 0))
4570 /* Send the channel key to the channel. The key of course is not sent
4571 to the client who was kicked off the channel. */
4572 silc_server_send_channel_key(server, target_client->connection, channel,
4573 server->server_type == SILC_ROUTER ?
4574 FALSE : !server->standalone);
4578 silc_server_command_free(cmd);
4581 /* Server side of OPER command. Client uses this comand to obtain server
4582 operator privileges to this server/router. */
4584 SILC_SERVER_CMD_FUNC(oper)
4586 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4587 SilcServer server = cmd->server;
4588 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4589 unsigned char *username, *auth;
4591 SilcServerConfigSectionAdminConnection *admin;
4592 SilcIDListData idata = (SilcIDListData)client;
4594 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4596 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4599 /* Get the username */
4600 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4603 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4607 /* Get the admin configuration */
4608 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4609 username, client->nickname);
4611 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4612 username, client->nickname);
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4615 SILC_STATUS_ERR_AUTH_FAILED);
4620 /* Get the authentication payload */
4621 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4624 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4628 /* Verify the authentication data */
4629 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4630 admin->auth_data, admin->auth_data_len,
4631 idata->hash, client->id, SILC_ID_CLIENT)) {
4632 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4633 SILC_STATUS_ERR_AUTH_FAILED);
4637 /* Client is now server operator */
4638 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4640 /* Send UMODE change to primary router */
4641 if (!server->standalone)
4642 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4643 client->id, client->mode);
4645 /* Send reply to the sender */
4646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4650 silc_server_command_free(cmd);
4653 /* Server side of SILCOPER command. Client uses this comand to obtain router
4654 operator privileges to this router. */
4656 SILC_SERVER_CMD_FUNC(silcoper)
4658 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4659 SilcServer server = cmd->server;
4660 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4661 unsigned char *username, *auth;
4663 SilcServerConfigSectionAdminConnection *admin;
4664 SilcIDListData idata = (SilcIDListData)client;
4666 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4668 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4671 if (server->server_type != SILC_ROUTER) {
4672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4673 SILC_STATUS_ERR_AUTH_FAILED);
4677 /* Get the username */
4678 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4681 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4685 /* Get the admin configuration */
4686 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4687 username, client->nickname);
4689 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4690 username, client->nickname);
4692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4693 SILC_STATUS_ERR_AUTH_FAILED);
4698 /* Get the authentication payload */
4699 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4702 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4706 /* Verify the authentication data */
4707 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4708 admin->auth_data, admin->auth_data_len,
4709 idata->hash, client->id, SILC_ID_CLIENT)) {
4710 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4711 SILC_STATUS_ERR_AUTH_FAILED);
4715 /* Client is now router operator */
4716 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4718 /* Send UMODE change to primary router */
4719 if (!server->standalone)
4720 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4721 client->id, client->mode);
4723 /* Send reply to the sender */
4724 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4728 silc_server_command_free(cmd);
4731 /* Server side command of CONNECT. Connects us to the specified remote
4732 server or router. */
4734 SILC_SERVER_CMD_FUNC(connect)
4736 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4737 SilcServer server = cmd->server;
4738 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4739 unsigned char *tmp, *host;
4741 uint32 port = SILC_PORT;
4743 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4745 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4748 /* Check whether client has the permissions. */
4749 if (client->mode == SILC_UMODE_NONE) {
4750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4751 SILC_STATUS_ERR_NO_SERVER_PRIV);
4755 if (server->server_type == SILC_ROUTER &&
4756 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4757 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4758 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4762 /* Get the remote server */
4763 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4766 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4771 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4773 SILC_GET32_MSB(port, tmp);
4775 /* Create the connection. It is done with timeout and is async. */
4776 silc_server_create_connection(server, host, port);
4778 /* Send reply to the sender */
4779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4783 silc_server_command_free(cmd);
4786 /* Server side of command BAN. This is used to manage the ban list of the
4787 channel. To add clients and remove clients from the ban list. */
4789 SILC_SERVER_CMD_FUNC(ban)
4791 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4792 SilcServer server = cmd->server;
4793 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4795 SilcChannelEntry channel;
4796 SilcChannelClientEntry chl;
4797 SilcChannelID *channel_id = NULL;
4798 unsigned char *id, *add, *del;
4799 uint32 id_len, tmp_len;
4800 uint16 ident = silc_command_get_ident(cmd->payload);
4802 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4805 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4807 /* Get Channel ID */
4808 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4810 channel_id = silc_id_payload_parse_id(id, id_len);
4812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4813 SILC_STATUS_ERR_NO_CHANNEL_ID);
4818 /* Get channel entry. The server must know about the channel since the
4819 client is expected to be on the channel. */
4820 channel = silc_idlist_find_channel_by_id(server->local_list,
4823 channel = silc_idlist_find_channel_by_id(server->global_list,
4826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4827 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4832 /* Check whether this client is on the channel */
4833 if (!silc_server_client_on_channel(client, channel)) {
4834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4835 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4839 /* Get entry to the channel user list */
4840 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4842 /* The client must be at least channel operator. */
4843 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4845 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4849 /* Get the new ban and add it to the ban list */
4850 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4852 if (!channel->ban_list)
4853 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4855 channel->ban_list = silc_realloc(channel->ban_list,
4856 sizeof(*channel->ban_list) *
4858 strlen(channel->ban_list) + 2));
4859 if (add[tmp_len - 1] == ',')
4860 add[tmp_len - 1] = '\0';
4862 strncat(channel->ban_list, add, tmp_len);
4863 strncat(channel->ban_list, ",", 1);
4866 /* Get the ban to be removed and remove it from the list */
4867 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4868 if (del && channel->ban_list) {
4869 char *start, *end, *n;
4871 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4872 silc_free(channel->ban_list);
4873 channel->ban_list = NULL;
4875 start = strstr(channel->ban_list, del);
4876 if (start && strlen(start) >= tmp_len) {
4877 end = start + tmp_len;
4878 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4879 strncat(n, channel->ban_list, start - channel->ban_list);
4880 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4882 silc_free(channel->ban_list);
4883 channel->ban_list = n;
4888 /* Send the BAN notify type to our primary router. */
4889 if (!server->standalone && (add || del))
4890 silc_server_send_notify_ban(server, server->router->connection,
4891 server->server_type == SILC_ROUTER ?
4892 TRUE : FALSE, channel, add, del);
4894 /* Send the reply back to the client */
4896 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4897 SILC_STATUS_OK, ident, 2,
4899 3, channel->ban_list,
4901 strlen(channel->ban_list) - 1 : 0);
4902 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4903 packet->data, packet->len, FALSE);
4905 silc_buffer_free(packet);
4908 silc_free(channel_id);
4909 silc_server_command_free(cmd);
4912 /* Server side command of CLOSE. Closes connection to a specified server. */
4914 SILC_SERVER_CMD_FUNC(close)
4916 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4917 SilcServer server = cmd->server;
4918 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4919 SilcServerEntry server_entry;
4920 SilcSocketConnection sock;
4923 unsigned char *name;
4924 uint32 port = SILC_PORT;
4926 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4928 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4931 /* Check whether client has the permissions. */
4932 if (client->mode == SILC_UMODE_NONE) {
4933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4934 SILC_STATUS_ERR_NO_SERVER_PRIV);
4938 /* Get the remote server */
4939 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4942 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4947 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4949 SILC_GET32_MSB(port, tmp);
4951 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4952 name, port, FALSE, NULL);
4954 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4955 name, port, FALSE, NULL);
4956 if (!server_entry) {
4957 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4958 SILC_STATUS_ERR_NO_SERVER_ID);
4962 /* Send reply to the sender */
4963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4966 /* Close the connection to the server */
4967 sock = (SilcSocketConnection)server_entry->connection;
4969 /* If we shutdown primary router connection manually then don't trigger
4970 any reconnect or backup router connections, by setting the router
4972 if (server->router == server_entry) {
4973 server->id_entry->router = NULL;
4974 server->router = NULL;
4975 server->standalone = TRUE;
4977 silc_server_free_sock_user_data(server, sock);
4978 silc_server_close_connection(server, sock);
4981 silc_server_command_free(cmd);
4984 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4985 active connections. */
4987 SILC_SERVER_CMD_FUNC(shutdown)
4989 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4990 SilcServer server = cmd->server;
4991 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4993 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4995 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4998 /* Check whether client has the permission. */
4999 if (client->mode == SILC_UMODE_NONE) {
5000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5001 SILC_STATUS_ERR_NO_SERVER_PRIV);
5005 /* Send reply to the sender */
5006 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5009 /* Then, gracefully, or not, bring the server down. */
5010 silc_server_stop(server);
5014 silc_server_command_free(cmd);
5017 /* Server side command of LEAVE. Removes client from a channel. */
5019 SILC_SERVER_CMD_FUNC(leave)
5021 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5022 SilcServer server = cmd->server;
5023 SilcSocketConnection sock = cmd->sock;
5024 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5025 SilcChannelID *id = NULL;
5026 SilcChannelEntry channel;
5030 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5032 /* Get Channel ID */
5033 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5036 SILC_STATUS_ERR_NO_CHANNEL_ID);
5039 id = silc_id_payload_parse_id(tmp, len);
5041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5042 SILC_STATUS_ERR_NO_CHANNEL_ID);
5046 /* Get channel entry */
5047 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5049 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5052 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5057 /* Check whether this client is on the channel */
5058 if (!silc_server_client_on_channel(id_entry, channel)) {
5059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5060 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5064 /* Notify routers that they should remove this client from their list
5065 of clients on the channel. Send LEAVE notify type. */
5066 if (!server->standalone)
5067 silc_server_send_notify_leave(server, server->router->connection,
5068 server->server_type == SILC_ROUTER ?
5069 TRUE : FALSE, channel, id_entry->id);
5071 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5074 /* Remove client from channel */
5075 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5077 /* If the channel does not exist anymore we won't send anything */
5080 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5081 /* Re-generate channel key */
5082 if (!silc_server_create_channel_key(server, channel, 0))
5085 /* Send the channel key */
5086 silc_server_send_channel_key(server, NULL, channel,
5087 server->server_type == SILC_ROUTER ?
5088 FALSE : !server->standalone);
5093 silc_server_command_free(cmd);
5096 /* Server side of command USERS. Resolves clients and their USERS currently
5097 joined on the requested channel. The list of Client ID's and their modes
5098 on the channel is sent back. */
5100 SILC_SERVER_CMD_FUNC(users)
5102 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5103 SilcServer server = cmd->server;
5104 SilcChannelEntry channel;
5105 SilcChannelID *id = NULL;
5106 SilcBuffer packet, idp;
5107 unsigned char *channel_id;
5108 uint32 channel_id_len;
5109 SilcBuffer client_id_list;
5110 SilcBuffer client_mode_list;
5111 unsigned char lc[4];
5112 uint32 list_count = 0;
5113 uint16 ident = silc_command_get_ident(cmd->payload);
5116 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5118 /* Get Channel ID */
5119 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5121 /* Get channel name */
5122 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5124 if (!channel_id && !channel_name) {
5125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5126 SILC_STATUS_ERR_NO_CHANNEL_ID);
5131 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5134 SILC_STATUS_ERR_NO_CHANNEL_ID);
5139 /* If we are server and we don't know about this channel we will send
5140 the command to our router. If we know about the channel then we also
5141 have the list of users already. */
5143 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5145 channel = silc_idlist_find_channel_by_name(server->local_list,
5146 channel_name, NULL);
5148 if (!channel || channel->disabled) {
5149 if (server->server_type != SILC_ROUTER && !server->standalone &&
5153 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5154 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5156 /* Send USERS command */
5157 silc_server_packet_send(server, server->router->connection,
5158 SILC_PACKET_COMMAND, cmd->packet->flags,
5159 tmpbuf->data, tmpbuf->len, TRUE);
5161 /* Reprocess this packet after received reply */
5162 silc_server_command_pending(server, SILC_COMMAND_USERS,
5163 silc_command_get_ident(cmd->payload),
5164 silc_server_command_destructor,
5165 silc_server_command_users,
5166 silc_server_command_dup(cmd));
5167 cmd->pending = TRUE;
5168 silc_command_set_ident(cmd->payload, ident);
5170 silc_buffer_free(tmpbuf);
5175 /* Check the global list as well. */
5177 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5179 channel = silc_idlist_find_channel_by_name(server->global_list,
5180 channel_name, NULL);
5182 /* Channel really does not exist */
5183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5184 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5189 /* If the channel is private or secret do not send anything, unless the
5190 user requesting this command is on the channel. */
5191 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5192 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5193 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5195 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5200 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5202 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5207 /* Get the users list */
5208 silc_server_get_users_on_channel(server, channel, &client_id_list,
5209 &client_mode_list, &list_count);
5212 SILC_PUT32_MSB(list_count, lc);
5215 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5216 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5217 SILC_STATUS_OK, ident, 4,
5218 2, idp->data, idp->len,
5220 4, client_id_list->data,
5221 client_id_list->len,
5222 5, client_mode_list->data,
5223 client_mode_list->len);
5224 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5225 packet->data, packet->len, FALSE);
5227 silc_buffer_free(idp);
5228 silc_buffer_free(packet);
5229 silc_buffer_free(client_id_list);
5230 silc_buffer_free(client_mode_list);
5234 silc_server_command_free(cmd);
5237 /* Server side of command GETKEY. This fetches the client's public key
5238 from the server where to the client is connected. */
5240 SILC_SERVER_CMD_FUNC(getkey)
5242 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5243 SilcServer server = cmd->server;
5245 SilcClientEntry client;
5246 SilcServerEntry server_entry;
5247 SilcClientID *client_id = NULL;
5248 SilcServerID *server_id = NULL;
5249 SilcIDPayload idp = NULL;
5250 uint16 ident = silc_command_get_ident(cmd->payload);
5251 unsigned char *tmp, *pkdata;
5252 uint32 tmp_len, pklen;
5253 SilcBuffer pk = NULL;
5256 SILC_LOG_DEBUG(("Start"));
5258 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5261 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5264 idp = silc_id_payload_parse(tmp, tmp_len);
5266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5267 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5271 id_type = silc_id_payload_get_type(idp);
5272 if (id_type == SILC_ID_CLIENT) {
5273 client_id = silc_id_payload_get_id(idp);
5275 /* If the client is not found from local list there is no chance it
5276 would be locally connected client so send the command further. */
5277 client = silc_idlist_find_client_by_id(server->local_list,
5278 client_id, TRUE, NULL);
5280 client = silc_idlist_find_client_by_id(server->global_list,
5281 client_id, TRUE, NULL);
5283 if ((!client && !cmd->pending && !server->standalone) ||
5284 (client && !client->connection && !cmd->pending) ||
5285 (client && !client->data.public_key && !cmd->pending)) {
5288 SilcSocketConnection dest_sock;
5290 dest_sock = silc_server_get_client_route(server, NULL, 0,
5295 old_ident = silc_command_get_ident(cmd->payload);
5296 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5297 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5299 silc_server_packet_send(server, dest_sock,
5300 SILC_PACKET_COMMAND, cmd->packet->flags,
5301 tmpbuf->data, tmpbuf->len, TRUE);
5303 /* Reprocess this packet after received reply from router */
5304 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5305 silc_command_get_ident(cmd->payload),
5306 silc_server_command_destructor,
5307 silc_server_command_getkey,
5308 silc_server_command_dup(cmd));
5309 cmd->pending = TRUE;
5311 silc_command_set_ident(cmd->payload, old_ident);
5312 silc_buffer_free(tmpbuf);
5317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5318 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5322 /* The client is locally connected, just get the public key and
5323 send it back. If they key does not exist then do not send it,
5324 send just OK reply */
5325 if (!client->data.public_key) {
5329 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5330 pk = silc_buffer_alloc(4 + tmp_len);
5331 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5332 silc_buffer_format(pk,
5333 SILC_STR_UI_SHORT(tmp_len),
5334 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5335 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5341 } else if (id_type == SILC_ID_SERVER) {
5342 server_id = silc_id_payload_get_id(idp);
5344 /* If the server is not found from local list there is no chance it
5345 would be locally connected server so send the command further. */
5346 server_entry = silc_idlist_find_server_by_id(server->local_list,
5347 server_id, TRUE, NULL);
5349 server_entry = silc_idlist_find_server_by_id(server->global_list,
5350 server_id, TRUE, NULL);
5352 if (server_entry != server->id_entry &&
5353 ((!server_entry && !cmd->pending && !server->standalone) ||
5354 (server_entry && !server_entry->connection && !cmd->pending &&
5355 !server->standalone) ||
5356 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5357 !server->standalone))) {
5361 old_ident = silc_command_get_ident(cmd->payload);
5362 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5363 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5365 silc_server_packet_send(server, server->router->connection,
5366 SILC_PACKET_COMMAND, cmd->packet->flags,
5367 tmpbuf->data, tmpbuf->len, TRUE);
5369 /* Reprocess this packet after received reply from router */
5370 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5371 silc_command_get_ident(cmd->payload),
5372 silc_server_command_destructor,
5373 silc_server_command_getkey,
5374 silc_server_command_dup(cmd));
5375 cmd->pending = TRUE;
5377 silc_command_set_ident(cmd->payload, old_ident);
5378 silc_buffer_free(tmpbuf);
5382 if (!server_entry) {
5383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5384 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5388 /* If they key does not exist then do not send it, send just OK reply */
5389 if (!server_entry->data.public_key) {
5393 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5395 pk = silc_buffer_alloc(4 + tmp_len);
5396 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5397 silc_buffer_format(pk,
5398 SILC_STR_UI_SHORT(tmp_len),
5399 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5400 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5410 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5411 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5412 SILC_STATUS_OK, ident,
5416 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5417 packet->data, packet->len, FALSE);
5418 silc_buffer_free(packet);
5421 silc_buffer_free(pk);
5425 silc_id_payload_free(idp);
5426 silc_free(client_id);
5427 silc_free(server_id);
5428 silc_server_command_free(cmd);