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'. If there already exists pending command for the
301 specified command, ident, callback and context this function has no
304 bool silc_server_command_pending(SilcServer server,
305 SilcCommand reply_cmd,
307 SilcCommandCb callback,
310 SilcServerCommandPending *reply;
312 /* Check whether identical pending already exists for same command,
313 ident, callback and callback context. If it does then it would be
314 error to register it again. */
315 silc_dlist_start(server->pending_commands);
316 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
317 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
318 reply->callback == callback && reply->context == context)
322 reply = silc_calloc(1, sizeof(*reply));
323 reply->reply_cmd = reply_cmd;
324 reply->ident = ident;
325 reply->context = context;
326 reply->callback = callback;
327 silc_dlist_add(server->pending_commands, reply);
332 /* Deletes pending command by reply command type. */
334 void silc_server_command_pending_del(SilcServer server,
335 SilcCommand reply_cmd,
338 SilcServerCommandPending *r;
340 silc_dlist_start(server->pending_commands);
341 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
342 if (r->reply_cmd == reply_cmd && r->ident == ident) {
343 silc_dlist_del(server->pending_commands, r);
349 /* Checks for pending commands and marks callbacks to be called from
350 the command reply function. Returns TRUE if there were pending command. */
352 SilcServerCommandPendingCallbacks
353 silc_server_command_pending_check(SilcServer server,
354 SilcServerCommandReplyContext ctx,
357 uint32 *callbacks_count)
359 SilcServerCommandPending *r;
360 SilcServerCommandPendingCallbacks callbacks = NULL;
363 silc_dlist_start(server->pending_commands);
364 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
365 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
366 && r->ident == ident) {
367 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
368 callbacks[i].context = r->context;
369 callbacks[i].callback = r->callback;
375 *callbacks_count = i;
379 /* Sends simple status message as command reply packet */
382 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
384 SilcCommandStatus status)
388 SILC_LOG_DEBUG(("Sending command status %d", status));
391 silc_command_reply_payload_encode_va(command, status,
392 silc_command_get_ident(cmd->payload),
394 silc_server_packet_send(cmd->server, cmd->sock,
395 SILC_PACKET_COMMAND_REPLY, 0,
396 buffer->data, buffer->len, FALSE);
397 silc_buffer_free(buffer);
400 /* Sends command status reply with one extra argument. The argument
401 type must be sent as argument. */
404 silc_server_command_send_status_data(SilcServerCommandContext cmd,
406 SilcCommandStatus status,
408 const unsigned char *arg,
413 SILC_LOG_DEBUG(("Sending command status %d", status));
416 silc_command_reply_payload_encode_va(command, status,
417 silc_command_get_ident(cmd->payload),
418 1, arg_type, arg, arg_len);
419 silc_server_packet_send(cmd->server, cmd->sock,
420 SILC_PACKET_COMMAND_REPLY, 0,
421 buffer->data, buffer->len, FALSE);
422 silc_buffer_free(buffer);
425 /* This function can be called to check whether in the command reply
426 an error occurred. This function has no effect if this is called
427 when the command function was not called as pending command callback.
428 This returns TRUE if error had occurred. */
431 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
432 SilcServerCommandReplyContext cmdr,
435 SilcCommandStatus status;
437 if (!cmd->pending || !cmdr)
440 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
441 if (status != SILC_STATUS_OK &&
442 status != SILC_STATUS_LIST_START &&
443 status != SILC_STATUS_LIST_ITEM &&
444 status != SILC_STATUS_LIST_END) {
447 /* Send the same command reply payload */
448 silc_command_set_ident(cmdr->payload,
449 silc_command_get_ident(cmd->payload));
450 buffer = silc_command_payload_encode_payload(cmdr->payload);
451 silc_server_packet_send(cmd->server, cmd->sock,
452 SILC_PACKET_COMMAND_REPLY, 0,
453 buffer->data, buffer->len, FALSE);
454 silc_buffer_free(buffer);
461 /******************************************************************************
465 ******************************************************************************/
468 silc_server_command_whois_parse(SilcServerCommandContext cmd,
469 SilcClientID ***client_id,
470 uint32 *client_id_count,
478 uint32 argc = silc_argument_get_arg_num(cmd->args);
481 /* If client ID is in the command it must be used instead of nickname */
482 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
484 /* No ID, get the nickname@server string and parse it. */
485 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
487 silc_parse_userfqdn(tmp, nickname, server_name);
489 silc_server_command_send_status_reply(cmd, command,
490 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
494 /* Command includes ID, we must use that. Also check whether the command
495 has more than one ID set - take them all. */
497 *client_id = silc_calloc(1, sizeof(**client_id));
498 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
499 if ((*client_id)[0] == NULL) {
500 silc_free(*client_id);
501 silc_server_command_send_status_reply(cmd, command,
502 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
505 *client_id_count = 1;
507 /* Take all ID's from the command packet */
509 for (k = 1, i = 1; i < argc; i++) {
510 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
512 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
513 (*client_id_count + 1));
514 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
515 if ((*client_id)[k] == NULL) {
516 /* Cleanup all and fail */
517 for (i = 0; i < *client_id_count; i++)
518 silc_free((*client_id)[i]);
519 silc_free(*client_id);
520 silc_server_command_send_status_reply(
522 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
525 (*client_id_count)++;
532 /* Get the max count of reply messages allowed */
533 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
542 /* Resolve context used by both WHOIS and IDENTIFY commands */
544 SilcServerEntry router;
546 unsigned char **res_argv;
547 uint32 *res_argv_lens;
548 uint32 *res_argv_types;
550 } *SilcServerResolveContext;
553 silc_server_command_whois_check(SilcServerCommandContext cmd,
554 SilcClientEntry *clients,
555 uint32 clients_count)
557 SilcServer server = cmd->server;
558 SilcClientEntry entry;
559 SilcServerResolveContext resolve = NULL, r = NULL;
560 uint32 resolve_count = 0;
564 SILC_LOG_DEBUG(("Start"));
566 for (i = 0; i < clients_count; i++) {
571 if ((entry->nickname && entry->username && entry->userinfo) ||
572 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
576 /* If we are normal server, and we've not resolved this client from
577 router and it is global client, we'll check whether it is on some
578 channel. If not then we cannot be sure about its validity, and
579 we'll resolve it from router. */
580 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
581 entry->connection || silc_hash_table_count(entry->channels))
585 /* We need to resolve this entry since it is not complete */
587 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
588 /* The entry is being resolved (and we are not the resolver) so attach
589 to the command reply and we're done with this one. */
590 silc_server_command_pending(server, SILC_COMMAND_NONE,
591 entry->resolve_cmd_ident,
592 silc_server_command_whois,
593 silc_server_command_dup(cmd));
596 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
597 /* We've resolved this and it still is not ready. We'll return
598 and are that this will be handled again after it is resolved. */
599 for (i = 0; i < resolve_count; i++) {
600 for (k = 0; k < r->res_argc; k++)
601 silc_free(r->res_argv[k]);
602 silc_free(r->res_argv);
603 silc_free(r->res_argv_lens);
604 silc_free(r->res_argv_types);
609 /* We'll resolve this client */
613 for (k = 0; k < resolve_count; k++) {
614 if (resolve[k].router == entry->router) {
621 resolve = silc_realloc(resolve, sizeof(*resolve) *
622 (resolve_count + 1));
623 r = &resolve[resolve_count];
624 memset(r, 0, sizeof(*r));
625 r->router = entry->router;
626 r->ident = ++server->cmd_ident;
630 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
632 r->res_argv_lens = silc_realloc(r->res_argv_lens,
633 sizeof(*r->res_argv_lens) *
635 r->res_argv_types = silc_realloc(r->res_argv_types,
636 sizeof(*r->res_argv_types) *
638 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
639 r->res_argv[r->res_argc] = silc_calloc(idp->len,
640 sizeof(**r->res_argv));
641 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
642 r->res_argv_lens[r->res_argc] = idp->len;
643 r->res_argv_types[r->res_argc] = r->res_argc + 3;
645 silc_buffer_free(idp);
647 entry->resolve_cmd_ident = r->ident;
648 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
649 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
654 /* Do the resolving */
655 for (i = 0; i < resolve_count; i++) {
660 /* Send WHOIS request. We send WHOIS since we're doing the requesting
661 now anyway so make it a good one. */
662 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
663 r->res_argc, r->res_argv,
667 silc_server_packet_send(server, r->router->connection,
668 SILC_PACKET_COMMAND, cmd->packet->flags,
669 res_cmd->data, res_cmd->len, FALSE);
671 /* Reprocess this packet after received reply */
672 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
674 silc_server_command_whois,
675 silc_server_command_dup(cmd));
678 silc_buffer_free(res_cmd);
679 for (k = 0; k < r->res_argc; k++)
680 silc_free(r->res_argv[k]);
681 silc_free(r->res_argv);
682 silc_free(r->res_argv_lens);
683 silc_free(r->res_argv_types);
692 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
693 SilcClientEntry *clients,
694 uint32 clients_count,
696 const char *nickname,
697 SilcClientID **client_ids)
699 SilcServer server = cmd->server;
701 int i, k, len, valid_count;
702 SilcBuffer packet, idp, channels;
703 SilcClientEntry entry;
704 SilcCommandStatus status;
705 uint16 ident = silc_command_get_ident(cmd->payload);
706 char nh[256], uh[256];
707 unsigned char idle[4], mode[4];
708 unsigned char *fingerprint;
709 SilcSocketConnection hsock;
711 /* Process only valid clients and ignore those that are not registered. */
713 for (i = 0; i < clients_count; i++) {
714 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
721 /* No valid clients found, send error reply */
723 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
724 SILC_STATUS_ERR_NO_SUCH_NICK,
725 3, nickname, strlen(nickname));
726 } else if (client_ids && client_ids[0]) {
727 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
728 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
729 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
730 2, idp->data, idp->len);
731 silc_buffer_free(idp);
736 /* Start processing found clients. */
738 status = SILC_STATUS_LIST_START;
740 status = SILC_STATUS_OK;
742 for (i = 0, k = 0; i < clients_count; i++) {
748 status = SILC_STATUS_LIST_ITEM;
749 if (valid_count > 1 && k == valid_count - 1)
750 status = SILC_STATUS_LIST_END;
751 if (count && k - 1 == count)
752 status = SILC_STATUS_LIST_END;
754 /* Send WHOIS reply */
755 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
756 tmp = silc_argument_get_first_arg(cmd->args, NULL);
758 memset(uh, 0, sizeof(uh));
759 memset(nh, 0, sizeof(nh));
760 memset(idle, 0, sizeof(idle));
762 strncat(nh, entry->nickname, strlen(entry->nickname));
763 if (!strchr(entry->nickname, '@')) {
765 if (entry->servername) {
766 strncat(nh, entry->servername, strlen(entry->servername));
768 len = entry->router ? strlen(entry->router->server_name) :
769 strlen(server->server_name);
770 strncat(nh, entry->router ? entry->router->server_name :
771 server->server_name, len);
775 strncat(uh, entry->username, strlen(entry->username));
776 if (!strchr(entry->username, '@')) {
778 hsock = (SilcSocketConnection)entry->connection;
779 len = strlen(hsock->hostname);
780 strncat(uh, hsock->hostname, len);
783 channels = silc_server_get_client_channel_list(server, entry);
785 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
786 fingerprint = entry->data.fingerprint;
790 SILC_PUT32_MSB(entry->mode, mode);
792 if (entry->connection) {
793 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
797 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
799 2, idp->data, idp->len,
803 strlen(entry->userinfo),
804 6, channels ? channels->data : NULL,
805 channels ? channels->len : 0,
809 fingerprint ? 20 : 0);
811 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
812 0, packet->data, packet->len, FALSE);
814 silc_buffer_free(packet);
815 silc_buffer_free(idp);
817 silc_buffer_free(channels);
824 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
826 SilcServer server = cmd->server;
830 old_ident = silc_command_get_ident(cmd->payload);
831 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
832 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
834 /* Send WHOIS command to our router */
835 silc_server_packet_send(server, (SilcSocketConnection)
836 server->router->connection,
837 SILC_PACKET_COMMAND, cmd->packet->flags,
838 tmpbuf->data, tmpbuf->len, TRUE);
840 /* Reprocess this packet after received reply from router */
841 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
842 silc_command_get_ident(cmd->payload),
843 silc_server_command_whois,
844 silc_server_command_dup(cmd));
846 silc_command_set_ident(cmd->payload, old_ident);
847 silc_buffer_free(tmpbuf);
851 silc_server_command_whois_process(SilcServerCommandContext cmd)
853 SilcServer server = cmd->server;
854 char *nick = NULL, *server_name = NULL;
856 SilcClientEntry *clients = NULL, entry;
857 SilcClientID **client_id = NULL;
858 uint32 client_id_count = 0, clients_count = 0;
860 bool check_global = FALSE;
862 /* Parse the whois request */
863 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
864 &nick, &server_name, &count,
868 /* Send the WHOIS request to the router only if it included nickname.
869 Since nicknames can be expanded into many clients we need to send it
870 to router. If the WHOIS included only client ID's we will check them
871 first locally since we just might have them. */
872 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
873 server->server_type == SILC_SERVER && !cmd->pending &&
874 !server->standalone) {
875 silc_server_command_whois_send_router(cmd);
880 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
882 else if (server->server_type != SILC_SERVER)
885 /* Get all clients matching that ID or nickname from local list */
886 if (client_id_count) {
887 /* Check all Client ID's received in the command packet */
888 for (i = 0; i < client_id_count; i++) {
889 entry = silc_idlist_find_client_by_id(server->local_list,
890 client_id[i], TRUE, NULL);
891 if (!entry && check_global)
892 entry = silc_idlist_find_client_by_id(server->global_list,
893 client_id[i], TRUE, NULL);
895 clients = silc_realloc(clients, sizeof(*clients) *
896 (clients_count + 1));
897 clients[clients_count++] = entry;
899 /* If we are normal server and did not send the request first to router
900 do it now, since we do not have the Client ID information. */
901 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
902 server->server_type == SILC_SERVER && !cmd->pending &&
903 !server->standalone) {
904 silc_server_command_whois_send_router(cmd);
911 /* Find by nickname */
912 if (!silc_idlist_get_clients_by_hash(server->local_list,
913 nick, server->md5hash,
914 &clients, &clients_count))
915 silc_idlist_get_clients_by_nickname(server->local_list,
917 &clients, &clients_count);
919 if (!silc_idlist_get_clients_by_hash(server->global_list,
920 nick, server->md5hash,
921 &clients, &clients_count))
922 silc_idlist_get_clients_by_nickname(server->global_list,
924 &clients, &clients_count);
929 /* If we are normal server and did not send the request first to router
930 do it now, since we do not have the information. */
931 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
932 server->server_type == SILC_SERVER && !cmd->pending &&
933 !server->standalone) {
934 silc_server_command_whois_send_router(cmd);
939 /* Such client(s) really does not exist in the SILC network. */
940 if (!client_id_count) {
941 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
942 SILC_STATUS_ERR_NO_SUCH_NICK,
943 3, nick, strlen(nick));
945 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
946 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
947 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
948 2, idp->data, idp->len);
949 silc_buffer_free(idp);
954 /* Router always finds the client entry if it exists in the SILC network.
955 However, it might be incomplete entry and does not include all the
956 mandatory fields that WHOIS command reply requires. Check for these and
957 make query from the server who owns the client if some fields are
959 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
964 /* Send the command reply */
965 silc_server_command_whois_send_reply(cmd, clients, clients_count,
966 count, nick, client_id);
969 if (client_id_count) {
970 for (i = 0; i < client_id_count; i++)
971 silc_free(client_id[i]);
972 silc_free(client_id);
976 silc_free(server_name);
981 /* Server side of command WHOIS. Processes user's query and sends found
982 results as command replies back to the client. */
984 SILC_SERVER_CMD_FUNC(whois)
986 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
989 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
991 ret = silc_server_command_whois_process(cmd);
992 silc_server_command_free(cmd);
995 /******************************************************************************
999 ******************************************************************************/
1002 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1010 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1013 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1017 /* Get the nickname@server string and parse it. */
1018 silc_parse_userfqdn(tmp, nickname, server_name);
1020 /* Get the max count of reply messages allowed */
1021 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1031 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1032 SilcClientEntry *clients,
1033 uint32 clients_count)
1035 SilcServer server = cmd->server;
1037 SilcClientEntry entry;
1039 for (i = 0; i < clients_count; i++) {
1042 if (!entry->nickname || !entry->username) {
1049 old_ident = silc_command_get_ident(cmd->payload);
1050 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1051 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1053 /* Send WHOWAS command */
1054 silc_server_packet_send(server, entry->router->connection,
1055 SILC_PACKET_COMMAND, cmd->packet->flags,
1056 tmpbuf->data, tmpbuf->len, TRUE);
1058 /* Reprocess this packet after received reply */
1059 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1060 silc_command_get_ident(cmd->payload),
1061 silc_server_command_whowas,
1062 silc_server_command_dup(cmd));
1063 cmd->pending = TRUE;
1065 silc_command_set_ident(cmd->payload, old_ident);
1067 silc_buffer_free(tmpbuf);
1076 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1077 SilcClientEntry *clients,
1078 uint32 clients_count)
1080 SilcServer server = cmd->server;
1082 int i, count = 0, len;
1083 SilcBuffer packet, idp;
1084 SilcClientEntry entry = NULL;
1085 SilcCommandStatus status;
1086 uint16 ident = silc_command_get_ident(cmd->payload);
1088 char nh[256], uh[256];
1090 status = SILC_STATUS_OK;
1091 if (clients_count > 1)
1092 status = SILC_STATUS_LIST_START;
1094 for (i = 0; i < clients_count; i++) {
1097 /* We will take only clients that are not valid anymore. They are the
1098 ones that are not registered anymore but still have a ID. They
1099 have disconnected us, and thus valid for WHOWAS. */
1100 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1103 if (count && i - 1 == count)
1108 if (clients_count > 2)
1109 status = SILC_STATUS_LIST_ITEM;
1110 if (clients_count > 1 && i == clients_count - 1)
1111 status = SILC_STATUS_LIST_END;
1113 /* Send WHOWAS reply */
1114 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1115 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1116 memset(uh, 0, sizeof(uh));
1117 memset(nh, 0, sizeof(nh));
1119 strncat(nh, entry->nickname, strlen(entry->nickname));
1120 if (!strchr(entry->nickname, '@')) {
1121 strncat(nh, "@", 1);
1122 if (entry->servername) {
1123 strncat(nh, entry->servername, strlen(entry->servername));
1125 len = entry->router ? strlen(entry->router->server_name) :
1126 strlen(server->server_name);
1127 strncat(nh, entry->router ? entry->router->server_name :
1128 server->server_name, len);
1132 strncat(uh, entry->username, strlen(entry->username));
1133 if (!strchr(entry->username, '@')) {
1134 strncat(uh, "@", 1);
1135 strcat(uh, "*private*");
1139 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1141 2, idp->data, idp->len,
1146 strlen(entry->userinfo) : 0);
1147 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1148 0, packet->data, packet->len, FALSE);
1150 silc_buffer_free(packet);
1151 silc_buffer_free(idp);
1154 if (found == FALSE && entry)
1155 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1156 SILC_STATUS_ERR_NO_SUCH_NICK,
1158 strlen(entry->nickname));
1162 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1164 SilcServer server = cmd->server;
1165 char *nick = NULL, *server_name = NULL;
1167 SilcClientEntry *clients = NULL;
1168 uint32 clients_count = 0;
1170 bool check_global = FALSE;
1172 /* Protocol dictates that we must always send the received WHOWAS request
1173 to our router if we are normal server, so let's do it now unless we
1174 are standalone. We will not send any replies to the client until we
1175 have received reply from the router. */
1176 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1177 server->server_type == SILC_SERVER && !cmd->pending &&
1178 !server->standalone) {
1182 old_ident = silc_command_get_ident(cmd->payload);
1183 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1184 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1186 /* Send WHOWAS command to our router */
1187 silc_server_packet_send(server, (SilcSocketConnection)
1188 server->router->connection,
1189 SILC_PACKET_COMMAND, cmd->packet->flags,
1190 tmpbuf->data, tmpbuf->len, TRUE);
1192 /* Reprocess this packet after received reply from router */
1193 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1194 silc_command_get_ident(cmd->payload),
1195 silc_server_command_whowas,
1196 silc_server_command_dup(cmd));
1197 cmd->pending = TRUE;
1199 silc_command_set_ident(cmd->payload, old_ident);
1201 silc_buffer_free(tmpbuf);
1206 /* We are ready to process the command request. Let's search for the
1207 requested client and send reply to the requesting client. */
1209 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1210 check_global = TRUE;
1211 else if (server->server_type != SILC_SERVER)
1212 check_global = TRUE;
1214 /* Parse the whowas request */
1215 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1218 /* Get all clients matching that nickname from local list */
1219 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1221 &clients, &clients_count))
1222 silc_idlist_get_clients_by_hash(server->local_list,
1223 nick, server->md5hash,
1224 &clients, &clients_count);
1226 /* Check global list as well */
1228 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1230 &clients, &clients_count))
1231 silc_idlist_get_clients_by_hash(server->global_list,
1232 nick, server->md5hash,
1233 &clients, &clients_count);
1237 /* Such a client really does not exist in the SILC network. */
1238 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1239 SILC_STATUS_ERR_NO_SUCH_NICK,
1240 3, nick, strlen(nick));
1244 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1249 /* Send the command reply to the client */
1250 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1255 silc_free(server_name);
1259 /* Server side of command WHOWAS. */
1261 SILC_SERVER_CMD_FUNC(whowas)
1263 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1266 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1268 ret = silc_server_command_whowas_process(cmd);
1269 silc_server_command_free(cmd);
1272 /******************************************************************************
1276 ******************************************************************************/
1279 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1281 SilcServer server = cmd->server;
1285 old_ident = silc_command_get_ident(cmd->payload);
1286 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1287 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1289 /* Send IDENTIFY command to our router */
1290 silc_server_packet_send(server, (SilcSocketConnection)
1291 server->router->connection,
1292 SILC_PACKET_COMMAND, cmd->packet->flags,
1293 tmpbuf->data, tmpbuf->len, TRUE);
1295 /* Reprocess this packet after received reply from router */
1296 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1297 silc_command_get_ident(cmd->payload),
1298 silc_server_command_identify,
1299 silc_server_command_dup(cmd));
1300 cmd->pending = TRUE;
1301 silc_command_set_ident(cmd->payload, old_ident);
1302 silc_buffer_free(tmpbuf);
1306 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1307 SilcClientEntry **clients,
1308 uint32 *clients_count,
1309 SilcServerEntry **servers,
1310 uint32 *servers_count,
1311 SilcChannelEntry **channels,
1312 uint32 *channels_count,
1315 SilcServer server = cmd->server;
1318 uint32 argc = silc_argument_get_arg_num(cmd->args);
1320 bool check_global = FALSE;
1325 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1326 check_global = TRUE;
1327 else if (server->server_type != SILC_SERVER)
1328 check_global = TRUE;
1330 /* If ID Payload is in the command it must be used instead of names */
1331 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1333 /* No ID, get the names. */
1335 /* If we are normal server and have not resolved information from
1336 router yet, do so now. */
1337 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1338 server->server_type == SILC_SERVER && !cmd->pending &&
1339 !server->standalone) {
1340 silc_server_command_identify_send_router(cmd);
1344 /* Try to get nickname@server. */
1345 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1348 char *nick_server = NULL;
1350 silc_parse_userfqdn(tmp, &nick, &nick_server);
1352 if (!silc_idlist_get_clients_by_hash(server->local_list,
1353 nick, server->md5hash,
1354 clients, clients_count))
1355 silc_idlist_get_clients_by_nickname(server->local_list,
1357 clients, clients_count);
1359 if (!silc_idlist_get_clients_by_hash(server->global_list,
1360 nick, server->md5hash,
1361 clients, clients_count))
1362 silc_idlist_get_clients_by_nickname(server->global_list,
1364 clients, clients_count);
1368 silc_free(nick_server);
1371 /* the nickname does not exist, send error reply */
1372 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1373 SILC_STATUS_ERR_NO_SUCH_NICK,
1374 3, tmp, strlen(tmp));
1379 /* Try to get server name */
1380 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1382 entry = silc_idlist_find_server_by_name(server->local_list,
1384 if (!entry && check_global)
1385 entry = silc_idlist_find_server_by_name(server->global_list,
1388 *servers = silc_realloc(*servers, sizeof(**servers) *
1389 (*servers_count + 1));
1390 (*servers)[(*servers_count)++] = entry;
1394 /* the server does not exist, send error reply */
1395 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1396 SILC_STATUS_ERR_NO_SUCH_SERVER,
1397 3, tmp, strlen(tmp));
1402 /* Try to get channel name */
1403 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1405 entry = silc_idlist_find_channel_by_name(server->local_list,
1407 if (!entry && check_global)
1408 entry = silc_idlist_find_channel_by_name(server->global_list,
1411 *channels = silc_realloc(*channels, sizeof(**channels) *
1412 (*channels_count + 1));
1413 (*channels)[(*channels_count)++] = entry;
1417 /* The channel does not exist, send error reply */
1418 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1419 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1420 3, tmp, strlen(tmp));
1425 if (!(*clients) && !(*servers) && !(*channels)) {
1426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1427 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1431 /* Command includes ID, we must use that. Also check whether the command
1432 has more than one ID set - take them all. */
1434 /* Take all ID's from the command packet */
1435 for (i = 0; i < argc; i++) {
1438 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1442 idp = silc_id_payload_parse(tmp, len);
1444 silc_free(*clients);
1445 silc_free(*servers);
1446 silc_free(*channels);
1447 silc_server_command_send_status_reply(
1448 cmd, SILC_COMMAND_IDENTIFY,
1449 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1453 id = silc_id_payload_get_id(idp);
1455 switch (silc_id_payload_get_type(idp)) {
1457 case SILC_ID_CLIENT:
1458 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1460 if (!entry && check_global)
1461 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1464 *clients = silc_realloc(*clients, sizeof(**clients) *
1465 (*clients_count + 1));
1466 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1468 /* If we are normal server and have not resolved information from
1469 router yet, do so now. */
1470 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1471 server->server_type == SILC_SERVER && !cmd->pending &&
1472 !server->standalone) {
1473 silc_server_command_identify_send_router(cmd);
1474 silc_free(*clients);
1475 silc_free(*servers);
1476 silc_free(*channels);
1479 silc_server_command_send_status_data(
1480 cmd, SILC_COMMAND_IDENTIFY,
1481 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1489 case SILC_ID_SERVER:
1490 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1492 if (!entry && check_global)
1493 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1496 *servers = silc_realloc(*servers, sizeof(**servers) *
1497 (*servers_count + 1));
1498 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1500 /* If we are normal server and have not resolved information from
1501 router yet, do so now. */
1502 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1503 server->server_type == SILC_SERVER && !cmd->pending &&
1504 !server->standalone) {
1505 silc_server_command_identify_send_router(cmd);
1506 silc_free(*clients);
1507 silc_free(*servers);
1508 silc_free(*channels);
1511 silc_server_command_send_status_data(
1512 cmd, SILC_COMMAND_IDENTIFY,
1513 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1520 case SILC_ID_CHANNEL:
1521 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1523 if (!entry && check_global)
1524 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1527 *channels = silc_realloc(*channels, sizeof(**channels) *
1528 (*channels_count + 1));
1529 (*channels)[(*channels_count)++] = (SilcChannelEntry)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_CHANNEL_ID,
1557 silc_free(*clients);
1558 silc_free(*servers);
1559 silc_free(*channels);
1563 /* Get the max count of reply messages allowed */
1564 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1573 /* Checks that all mandatory fields in client entry are present. If not
1574 then send WHOIS request to the server who owns the client. We use
1575 WHOIS because we want to get as much information as possible at once. */
1578 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1579 SilcClientEntry *clients,
1580 uint32 clients_count)
1582 SilcServer server = cmd->server;
1583 SilcClientEntry entry;
1584 SilcServerResolveContext resolve = NULL, r = NULL;
1585 uint32 resolve_count = 0;
1589 for (i = 0; i < clients_count; i++) {
1594 if (entry->nickname ||
1595 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1599 /* If we are normal server, and we've not resolved this client from
1600 router and it is global client, we'll check whether it is on some
1601 channel. If not then we cannot be sure about its validity, and
1602 we'll resolve it from router. */
1603 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1604 entry->connection || silc_hash_table_count(entry->channels))
1608 /* We need to resolve this entry since it is not complete */
1610 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1611 /* The entry is being resolved (and we are not the resolver) so attach
1612 to the command reply and we're done with this one. */
1613 silc_server_command_pending(server, SILC_COMMAND_NONE,
1614 entry->resolve_cmd_ident,
1615 silc_server_command_identify,
1616 silc_server_command_dup(cmd));
1619 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1620 /* We've resolved this and it still is not ready. We'll return
1621 and are that this will be handled again after it is resolved. */
1622 for (i = 0; i < resolve_count; i++) {
1623 for (k = 0; k < r->res_argc; k++)
1624 silc_free(r->res_argv[k]);
1625 silc_free(r->res_argv);
1626 silc_free(r->res_argv_lens);
1627 silc_free(r->res_argv_types);
1632 /* We'll resolve this client */
1636 for (k = 0; k < resolve_count; k++) {
1637 if (resolve[k].router == entry->router) {
1644 resolve = silc_realloc(resolve, sizeof(*resolve) *
1645 (resolve_count + 1));
1646 r = &resolve[resolve_count];
1647 memset(r, 0, sizeof(*r));
1648 r->router = entry->router;
1649 r->ident = ++server->cmd_ident;
1653 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1655 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1656 sizeof(*r->res_argv_lens) *
1658 r->res_argv_types = silc_realloc(r->res_argv_types,
1659 sizeof(*r->res_argv_types) *
1661 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1662 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1663 sizeof(**r->res_argv));
1664 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1665 r->res_argv_lens[r->res_argc] = idp->len;
1666 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1668 silc_buffer_free(idp);
1670 entry->resolve_cmd_ident = r->ident;
1671 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1672 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1677 /* Do the resolving */
1678 for (i = 0; i < resolve_count; i++) {
1683 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1684 now anyway so make it a good one. */
1685 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1686 r->res_argc, r->res_argv,
1690 silc_server_packet_send(server, r->router->connection,
1691 SILC_PACKET_COMMAND, cmd->packet->flags,
1692 res_cmd->data, res_cmd->len, FALSE);
1694 /* Reprocess this packet after received reply */
1695 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1697 silc_server_command_identify,
1698 silc_server_command_dup(cmd));
1699 cmd->pending = TRUE;
1701 silc_buffer_free(res_cmd);
1702 for (k = 0; k < r->res_argc; k++)
1703 silc_free(r->res_argv[k]);
1704 silc_free(r->res_argv);
1705 silc_free(r->res_argv_lens);
1706 silc_free(r->res_argv_types);
1715 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1716 SilcClientEntry *clients,
1717 uint32 clients_count,
1718 SilcServerEntry *servers,
1719 uint32 servers_count,
1720 SilcChannelEntry *channels,
1721 uint32 channels_count,
1724 SilcServer server = cmd->server;
1725 int i, k, len, valid_count;
1726 SilcBuffer packet, idp;
1727 SilcCommandStatus status;
1728 uint16 ident = silc_command_get_ident(cmd->payload);
1729 char nh[256], uh[256];
1730 SilcSocketConnection hsock;
1732 status = SILC_STATUS_OK;
1735 SilcClientEntry entry;
1737 /* Process only valid entries. */
1739 for (i = 0; i < clients_count; i++) {
1740 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1747 /* No valid entries found at all, just send error */
1750 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1752 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1753 SILC_STATUS_ERR_NO_SUCH_NICK,
1754 3, tmp, strlen(tmp));
1756 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1757 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1758 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1764 /* Process all valid client entries and send command replies */
1766 if (valid_count > 1)
1767 status = SILC_STATUS_LIST_START;
1769 for (i = 0, k = 0; i < clients_count; i++) {
1775 status = SILC_STATUS_LIST_ITEM;
1776 if (valid_count > 1 && k == valid_count - 1
1777 && !servers_count && !channels_count)
1778 status = SILC_STATUS_LIST_END;
1779 if (count && k - 1 == count)
1780 status = SILC_STATUS_LIST_END;
1781 if (count && k - 1 > count)
1784 /* Send IDENTIFY reply */
1786 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1787 memset(uh, 0, sizeof(uh));
1788 memset(nh, 0, sizeof(nh));
1789 strncat(nh, entry->nickname, strlen(entry->nickname));
1790 if (!strchr(entry->nickname, '@')) {
1791 strncat(nh, "@", 1);
1792 if (entry->servername) {
1793 strncat(nh, entry->servername, strlen(entry->servername));
1795 len = entry->router ? strlen(entry->router->server_name) :
1796 strlen(server->server_name);
1797 strncat(nh, entry->router ? entry->router->server_name :
1798 server->server_name, len);
1802 if (!entry->username) {
1803 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1805 2, idp->data, idp->len,
1808 strncat(uh, entry->username, strlen(entry->username));
1809 if (!strchr(entry->username, '@')) {
1810 strncat(uh, "@", 1);
1811 hsock = (SilcSocketConnection)entry->connection;
1812 len = strlen(hsock->hostname);
1813 strncat(uh, hsock->hostname, len);
1816 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1818 2, idp->data, idp->len,
1823 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1824 0, packet->data, packet->len, FALSE);
1826 silc_buffer_free(packet);
1827 silc_buffer_free(idp);
1834 SilcServerEntry entry;
1836 if (status == SILC_STATUS_OK && servers_count > 1)
1837 status = SILC_STATUS_LIST_START;
1839 for (i = 0, k = 0; i < servers_count; i++) {
1843 status = SILC_STATUS_LIST_ITEM;
1844 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1845 status = SILC_STATUS_LIST_END;
1846 if (count && k - 1 == count)
1847 status = SILC_STATUS_LIST_END;
1848 if (count && k - 1 > count)
1851 /* Send IDENTIFY reply */
1852 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1854 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1856 2, idp->data, idp->len,
1857 3, entry->server_name,
1858 entry->server_name ?
1859 strlen(entry->server_name) : 0);
1860 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1861 0, packet->data, packet->len, FALSE);
1863 silc_buffer_free(packet);
1864 silc_buffer_free(idp);
1871 SilcChannelEntry entry;
1873 if (status == SILC_STATUS_OK && channels_count > 1)
1874 status = SILC_STATUS_LIST_START;
1876 for (i = 0, k = 0; i < channels_count; i++) {
1877 entry = channels[i];
1880 status = SILC_STATUS_LIST_ITEM;
1881 if (channels_count > 1 && k == channels_count - 1)
1882 status = SILC_STATUS_LIST_END;
1883 if (count && k - 1 == count)
1884 status = SILC_STATUS_LIST_END;
1885 if (count && k - 1 > count)
1888 /* Send IDENTIFY reply */
1889 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1891 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1893 2, idp->data, idp->len,
1894 3, entry->channel_name,
1895 entry->channel_name ?
1896 strlen(entry->channel_name): 0);
1897 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1898 0, packet->data, packet->len, FALSE);
1900 silc_buffer_free(packet);
1901 silc_buffer_free(idp);
1909 silc_server_command_identify_process(SilcServerCommandContext cmd)
1913 SilcClientEntry *clients = NULL;
1914 SilcServerEntry *servers = NULL;
1915 SilcChannelEntry *channels = NULL;
1916 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1918 /* Parse the IDENTIFY request */
1919 ret = silc_server_command_identify_parse(cmd,
1920 &clients, &clients_count,
1921 &servers, &servers_count,
1922 &channels, &channels_count,
1928 /* Check that all mandatory fields are present and request those data
1929 from the server who owns the client if necessary. */
1930 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1936 /* Send the command reply to the client */
1937 silc_server_command_identify_send_reply(cmd,
1938 clients, clients_count,
1939 servers, servers_count,
1940 channels, channels_count,
1946 silc_free(channels);
1950 SILC_SERVER_CMD_FUNC(identify)
1952 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1955 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1957 ret = silc_server_command_identify_process(cmd);
1958 silc_server_command_free(cmd);
1961 /* Server side of command NICK. Sets nickname for user. Setting
1962 nickname causes generation of a new client ID for the client. The
1963 new client ID is sent to the client after changing the nickname. */
1965 SILC_SERVER_CMD_FUNC(nick)
1967 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1968 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1969 SilcServer server = cmd->server;
1970 SilcBuffer packet, nidp, oidp = NULL;
1971 SilcClientID *new_id;
1974 uint16 ident = silc_command_get_ident(cmd->payload);
1977 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1980 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1982 /* Check nickname */
1983 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
1986 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
1987 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1988 SILC_STATUS_ERR_BAD_NICKNAME);
1992 /* Check for same nickname */
1993 if (!strcmp(client->nickname, nick)) {
1994 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1998 /* Create new Client ID */
1999 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2001 cmd->server->md5hash, nick,
2004 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2007 /* Send notify about nickname change to our router. We send the new
2008 ID and ask to replace it with the old one. If we are router the
2009 packet is broadcasted. Send NICK_CHANGE notify. */
2010 if (!server->standalone)
2011 silc_server_send_notify_nick_change(server, server->router->connection,
2012 server->server_type == SILC_SERVER ?
2013 FALSE : TRUE, client->id,
2016 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2018 /* Remove old cache entry */
2019 silc_idcache_del_by_context(server->local_list->clients, client);
2022 silc_free(client->id);
2024 /* Save the nickname as this client is our local client */
2025 silc_free(client->nickname);
2027 client->nickname = strdup(nick);
2028 client->id = new_id;
2030 /* Update client cache */
2031 silc_idcache_add(server->local_list->clients, client->nickname,
2032 client->id, (void *)client, 0, NULL);
2034 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2036 /* Send NICK_CHANGE notify to the client's channels */
2037 silc_server_send_notify_on_channels(server, NULL, client,
2038 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2039 oidp->data, oidp->len,
2040 nidp->data, nidp->len);
2043 /* Send the new Client ID as reply command back to client */
2044 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2045 SILC_STATUS_OK, ident, 1,
2046 2, nidp->data, nidp->len);
2047 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2048 0, packet->data, packet->len, FALSE);
2050 silc_buffer_free(packet);
2051 silc_buffer_free(nidp);
2053 silc_buffer_free(oidp);
2056 silc_server_command_free(cmd);
2059 /* Sends the LIST command reply */
2062 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2063 SilcChannelEntry *lch,
2065 SilcChannelEntry *gch,
2069 SilcBuffer packet, idp;
2070 SilcChannelEntry entry;
2071 SilcCommandStatus status;
2072 uint16 ident = silc_command_get_ident(cmd->payload);
2074 unsigned char usercount[4];
2076 int valid_lcount = 0, valid_rcount = 0;
2078 for (i = 0; i < lch_count; i++) {
2079 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2084 for (i = 0; i < gch_count; i++) {
2085 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2091 status = SILC_STATUS_OK;
2092 if ((lch_count + gch_count) > 1)
2093 status = SILC_STATUS_LIST_START;
2096 for (i = 0, k = 0; i < lch_count; i++) {
2102 status = SILC_STATUS_LIST_ITEM;
2103 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2104 status = SILC_STATUS_LIST_END;
2106 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2108 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2109 topic = "*private*";
2110 memset(usercount, 0, sizeof(usercount));
2112 topic = entry->topic;
2113 users = silc_hash_table_count(entry->user_list);
2114 SILC_PUT32_MSB(users, usercount);
2117 /* Send the reply */
2119 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2121 2, idp->data, idp->len,
2122 3, entry->channel_name,
2123 strlen(entry->channel_name),
2124 4, topic, topic ? strlen(topic) : 0,
2126 silc_server_packet_send(cmd->server, cmd->sock,
2127 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2128 packet->len, FALSE);
2129 silc_buffer_free(packet);
2130 silc_buffer_free(idp);
2135 for (i = 0, k = 0; i < gch_count; i++) {
2141 status = SILC_STATUS_LIST_ITEM;
2142 if (valid_rcount > 1 && k == valid_rcount - 1)
2143 status = SILC_STATUS_LIST_END;
2145 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2147 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2148 topic = "*private*";
2149 memset(usercount, 0, sizeof(usercount));
2151 topic = entry->topic;
2152 users = silc_hash_table_count(entry->user_list);
2153 SILC_PUT32_MSB(users, usercount);
2156 /* Send the reply */
2158 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2160 2, idp->data, idp->len,
2161 3, entry->channel_name,
2162 strlen(entry->channel_name),
2163 4, topic, topic ? strlen(topic) : 0,
2165 silc_server_packet_send(cmd->server, cmd->sock,
2166 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2167 packet->len, FALSE);
2168 silc_buffer_free(packet);
2169 silc_buffer_free(idp);
2174 /* Server side of LIST command. This lists the channel of the requested
2175 server. Secret channels are not listed. */
2177 SILC_SERVER_CMD_FUNC(list)
2179 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2180 SilcServer server = cmd->server;
2181 SilcChannelID *channel_id = NULL;
2184 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2185 uint32 lch_count = 0, gch_count = 0;
2187 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2189 /* If we are normal server, send the command to router, since we
2190 want to know all channels in the network. */
2191 if (!cmd->pending && server->server_type == SILC_SERVER &&
2192 !server->standalone) {
2196 old_ident = silc_command_get_ident(cmd->payload);
2197 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2198 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2199 silc_server_packet_send(server, server->router->connection,
2200 SILC_PACKET_COMMAND, cmd->packet->flags,
2201 tmpbuf->data, tmpbuf->len, TRUE);
2203 /* Reprocess this packet after received reply from router */
2204 silc_server_command_pending(server, SILC_COMMAND_LIST,
2205 silc_command_get_ident(cmd->payload),
2206 silc_server_command_list,
2207 silc_server_command_dup(cmd));
2208 cmd->pending = TRUE;
2209 silc_command_set_ident(cmd->payload, old_ident);
2210 silc_buffer_free(tmpbuf);
2214 /* Get Channel ID */
2215 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2217 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2219 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2220 SILC_STATUS_ERR_NO_CHANNEL_ID);
2225 /* Get the channels from local list */
2226 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2229 /* Get the channels from global list */
2230 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2233 /* Send the reply */
2234 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2235 gchannels, gch_count);
2237 silc_free(lchannels);
2238 silc_free(gchannels);
2241 silc_server_command_free(cmd);
2244 /* Server side of TOPIC command. Sets topic for channel and/or returns
2245 current topic to client. */
2247 SILC_SERVER_CMD_FUNC(topic)
2249 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2250 SilcServer server = cmd->server;
2251 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2252 SilcChannelID *channel_id;
2253 SilcChannelEntry channel;
2254 SilcChannelClientEntry chl;
2255 SilcBuffer packet, idp;
2257 uint32 argc, tmp_len;
2258 uint16 ident = silc_command_get_ident(cmd->payload);
2260 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2262 argc = silc_argument_get_arg_num(cmd->args);
2264 /* Get Channel ID */
2265 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2268 SILC_STATUS_ERR_NO_CHANNEL_ID);
2271 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2274 SILC_STATUS_ERR_NO_CHANNEL_ID);
2278 /* Check whether the channel exists */
2279 channel = silc_idlist_find_channel_by_id(server->local_list,
2282 channel = silc_idlist_find_channel_by_id(server->global_list,
2285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2286 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2293 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2296 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2300 if (strlen(tmp) > 256) {
2301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2302 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2306 /* See whether the client is on channel and has rights to change topic */
2307 if (!silc_hash_table_find(channel->user_list, client, NULL,
2309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2310 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2314 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2315 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2317 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2322 /* Set the topic for channel */
2323 silc_free(channel->topic);
2324 channel->topic = strdup(tmp);
2326 /* Send TOPIC_SET notify type to the network */
2327 if (!server->standalone)
2328 silc_server_send_notify_topic_set(server, server->router->connection,
2329 server->server_type == SILC_ROUTER ?
2330 TRUE : FALSE, channel,
2331 client->id, SILC_ID_CLIENT,
2334 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2336 /* Send notify about topic change to all clients on the channel */
2337 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2338 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2339 idp->data, idp->len,
2340 channel->topic, strlen(channel->topic));
2341 silc_buffer_free(idp);
2344 /* Send the topic to client as reply packet */
2345 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2346 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2347 SILC_STATUS_OK, ident, 2,
2348 2, idp->data, idp->len,
2351 strlen(channel->topic) : 0);
2352 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2353 0, packet->data, packet->len, FALSE);
2355 silc_buffer_free(packet);
2356 silc_buffer_free(idp);
2357 silc_free(channel_id);
2360 silc_server_command_free(cmd);
2363 /* Server side of INVITE command. Invites some client to join some channel.
2364 This command is also used to manage the invite list of the channel. */
2366 SILC_SERVER_CMD_FUNC(invite)
2368 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2369 SilcServer server = cmd->server;
2370 SilcSocketConnection sock = cmd->sock, dest_sock;
2371 SilcChannelClientEntry chl;
2372 SilcClientEntry sender, dest;
2373 SilcClientID *dest_id = NULL;
2374 SilcChannelEntry channel;
2375 SilcChannelID *channel_id = NULL;
2376 SilcIDListData idata;
2377 SilcBuffer idp, idp2, packet;
2378 unsigned char *tmp, *add, *del;
2380 uint16 ident = silc_command_get_ident(cmd->payload);
2382 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2384 /* Get Channel ID */
2385 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2388 SILC_STATUS_ERR_NO_CHANNEL_ID);
2391 channel_id = silc_id_payload_parse_id(tmp, len);
2393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2394 SILC_STATUS_ERR_NO_CHANNEL_ID);
2398 /* Get the channel entry */
2399 channel = silc_idlist_find_channel_by_id(server->local_list,
2402 channel = silc_idlist_find_channel_by_id(server->global_list,
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2411 /* Check whether the sender of this command is on the channel. */
2412 sender = (SilcClientEntry)sock->user_data;
2413 if (!silc_server_client_on_channel(sender, channel)) {
2414 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2415 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2419 /* Check whether the channel is invite-only channel. If yes then the
2420 sender of this command must be at least channel operator. */
2421 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2422 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2423 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2425 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2430 /* Get destination client ID */
2431 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2436 dest_id = silc_id_payload_parse_id(tmp, len);
2438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2439 SILC_STATUS_ERR_NO_CLIENT_ID);
2443 /* Get the client entry */
2444 dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2446 if (server->server_type != SILC_SERVER || !resolve) {
2447 silc_server_command_send_status_reply(
2448 cmd, SILC_COMMAND_INVITE,
2449 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2453 /* The client info is being resolved. Reprocess this packet after
2454 receiving the reply to the query. */
2455 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2457 silc_server_command_invite,
2458 silc_server_command_dup(cmd));
2459 cmd->pending = TRUE;
2460 silc_free(channel_id);
2465 /* Check whether the requested client is already on the channel. */
2466 if (silc_server_client_on_channel(dest, channel)) {
2467 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2468 SILC_STATUS_ERR_USER_ON_CHANNEL);
2472 /* Get route to the client */
2473 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2476 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2480 memset(invite, 0, sizeof(invite));
2481 strncat(invite, dest->nickname, strlen(dest->nickname));
2482 strncat(invite, "!", 1);
2483 strncat(invite, dest->username, strlen(dest->username));
2484 if (!strchr(dest->username, '@')) {
2485 strncat(invite, "@", 1);
2486 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2489 len = strlen(invite);
2490 if (!channel->invite_list)
2491 channel->invite_list = silc_calloc(len + 2,
2492 sizeof(*channel->invite_list));
2494 channel->invite_list = silc_realloc(channel->invite_list,
2495 sizeof(*channel->invite_list) *
2497 strlen(channel->invite_list) + 2));
2498 strncat(channel->invite_list, invite, len);
2499 strncat(channel->invite_list, ",", 1);
2501 /* Send notify to the client that is invited to the channel */
2502 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2503 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2504 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2506 SILC_NOTIFY_TYPE_INVITE, 3,
2507 idp->data, idp->len,
2508 channel->channel_name,
2509 strlen(channel->channel_name),
2510 idp2->data, idp2->len);
2511 silc_buffer_free(idp);
2512 silc_buffer_free(idp2);
2515 /* Add the client to the invite list of the channel */
2516 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2518 if (!channel->invite_list)
2519 channel->invite_list = silc_calloc(len + 2,
2520 sizeof(*channel->invite_list));
2522 channel->invite_list = silc_realloc(channel->invite_list,
2523 sizeof(*channel->invite_list) *
2525 strlen(channel->invite_list) + 2));
2526 if (add[len - 1] == ',')
2527 add[len - 1] = '\0';
2529 strncat(channel->invite_list, add, len);
2530 strncat(channel->invite_list, ",", 1);
2533 /* Get the invite to be removed and remove it from the list */
2534 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2535 if (del && channel->invite_list) {
2536 char *start, *end, *n;
2538 if (!strncmp(channel->invite_list, del,
2539 strlen(channel->invite_list) - 1)) {
2540 silc_free(channel->invite_list);
2541 channel->invite_list = NULL;
2543 start = strstr(channel->invite_list, del);
2544 if (start && strlen(start) >= len) {
2546 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2547 strncat(n, channel->invite_list, start - channel->invite_list);
2548 strncat(n, end + 1, ((channel->invite_list +
2549 strlen(channel->invite_list)) - end) - 1);
2550 silc_free(channel->invite_list);
2551 channel->invite_list = n;
2556 /* Send notify to the primary router */
2557 if (!server->standalone)
2558 silc_server_send_notify_invite(server, server->router->connection,
2559 server->server_type == SILC_ROUTER ?
2560 TRUE : FALSE, channel,
2561 sender->id, add, del);
2563 /* Send command reply */
2564 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2568 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2569 SILC_STATUS_OK, ident, 2,
2571 3, channel->invite_list,
2572 channel->invite_list ?
2573 strlen(channel->invite_list) : 0);
2576 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2577 SILC_STATUS_OK, ident, 1,
2579 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2580 packet->data, packet->len, FALSE);
2581 silc_buffer_free(packet);
2585 silc_free(channel_id);
2586 silc_server_command_free(cmd);
2591 SilcSocketConnection sock;
2595 /* Quits connection to client. This gets called if client won't
2596 close the connection even when it has issued QUIT command. */
2598 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2600 QuitInternal q = (QuitInternal)context;
2602 /* Free all client specific data, such as client entry and entires
2603 on channels this client may be on. */
2604 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2606 q->sock->user_data = NULL;
2608 /* Close the connection on our side */
2609 silc_server_close_connection(q->server, q->sock);
2611 silc_free(q->signoff);
2615 /* Quits SILC session. This is the normal way to disconnect client. */
2617 SILC_SERVER_CMD_FUNC(quit)
2619 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2620 SilcServer server = cmd->server;
2621 SilcSocketConnection sock = cmd->sock;
2623 unsigned char *tmp = NULL;
2626 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2628 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2631 /* Get destination ID */
2632 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2636 q = silc_calloc(1, sizeof(*q));
2639 q->signoff = tmp ? strdup(tmp) : NULL;
2641 /* We quit the connection with little timeout */
2642 silc_schedule_task_add(server->schedule, sock->sock,
2643 silc_server_command_quit_cb, (void *)q,
2644 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2647 silc_server_command_free(cmd);
2650 /* Server side of command KILL. This command is used by router operator
2651 to remove an client from the SILC Network temporarily. */
2653 SILC_SERVER_CMD_FUNC(kill)
2655 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2656 SilcServer server = cmd->server;
2657 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2658 SilcClientEntry remote_client;
2659 SilcClientID *client_id;
2660 unsigned char *tmp, *comment;
2661 uint32 tmp_len, tmp_len2;
2664 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2666 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2669 /* KILL command works only on router */
2670 if (server->server_type != SILC_ROUTER) {
2671 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2672 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2676 /* Check whether client has the permissions. */
2677 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2678 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2679 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2683 /* Get the client ID */
2684 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2687 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2690 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2693 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2697 /* Get the client entry */
2698 remote_client = silc_idlist_find_client_by_id(server->local_list,
2699 client_id, TRUE, NULL);
2701 if (!remote_client) {
2702 remote_client = silc_idlist_find_client_by_id(server->global_list,
2703 client_id, TRUE, NULL);
2705 if (!remote_client) {
2706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2707 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2713 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2717 /* Send reply to the sender */
2718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2721 /* Send the KILL notify packets. First send it to the channel, then
2722 to our primary router and then directly to the client who is being
2723 killed right now. */
2725 /* Send KILLED notify to the channels. It is not sent to the client
2726 as it will be sent differently destined directly to the client and not
2728 silc_server_send_notify_on_channels(server, remote_client,
2729 remote_client, SILC_NOTIFY_TYPE_KILLED,
2732 comment, comment ? tmp_len2 : 0);
2734 /* Send KILLED notify to primary route */
2735 if (!server->standalone)
2736 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2737 remote_client->id, comment);
2739 /* Send KILLED notify to the client directly */
2740 silc_server_send_notify_killed(server, remote_client->connection ?
2741 remote_client->connection :
2742 remote_client->router->connection, FALSE,
2743 remote_client->id, comment);
2745 /* Remove the client from all channels. This generates new keys to the
2746 channels as well. */
2747 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2750 /* Remove the client entry, If it is locally connected then we will also
2751 disconnect the client here */
2752 if (remote_client->connection) {
2753 /* Remove locally conneted client */
2754 SilcSocketConnection sock = remote_client->connection;
2755 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2756 silc_server_close_connection(server, sock);
2758 /* Update statistics */
2759 if (remote_client->connection)
2760 server->stat.my_clients--;
2761 if (server->server_type == SILC_ROUTER)
2762 server->stat.cell_clients--;
2763 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2764 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2766 /* Remove remote client */
2767 silc_idlist_del_client(local ? server->local_list :
2768 server->global_list, remote_client);
2772 silc_server_command_free(cmd);
2775 /* Server side of command INFO. This sends information about us to
2776 the client. If client requested specific server we will send the
2777 command to that server. */
2779 SILC_SERVER_CMD_FUNC(info)
2781 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2782 SilcServer server = cmd->server;
2783 SilcBuffer packet, idp;
2786 char *dest_server, *server_info = NULL, *server_name;
2787 uint16 ident = silc_command_get_ident(cmd->payload);
2788 SilcServerEntry entry = NULL;
2789 SilcServerID *server_id = NULL;
2791 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2793 /* Get server name */
2794 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2797 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2799 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2802 SILC_STATUS_ERR_NO_SERVER_ID);
2808 /* Check whether we have this server cached */
2809 entry = silc_idlist_find_server_by_id(server->local_list,
2810 server_id, TRUE, NULL);
2812 entry = silc_idlist_find_server_by_id(server->global_list,
2813 server_id, TRUE, NULL);
2814 if (!entry && server->server_type != SILC_SERVER) {
2815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2816 SILC_STATUS_ERR_NO_SUCH_SERVER);
2822 /* Some buggy servers has sent request to router about themselves. */
2823 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2826 if ((!dest_server && !server_id && !entry) || (entry &&
2827 entry == server->id_entry) ||
2828 (dest_server && !cmd->pending &&
2829 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2830 /* Send our reply */
2831 char info_string[256];
2833 memset(info_string, 0, sizeof(info_string));
2834 snprintf(info_string, sizeof(info_string),
2835 "location: %s server: %s admin: %s <%s>",
2836 server->config->admin_info->location,
2837 server->config->admin_info->server_type,
2838 server->config->admin_info->admin_name,
2839 server->config->admin_info->admin_email);
2841 server_info = info_string;
2842 entry = server->id_entry;
2844 /* Check whether we have this server cached */
2845 if (!entry && dest_server) {
2846 entry = silc_idlist_find_server_by_name(server->global_list,
2847 dest_server, TRUE, NULL);
2849 entry = silc_idlist_find_server_by_name(server->local_list,
2850 dest_server, TRUE, NULL);
2854 if (!cmd->pending &&
2855 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2856 /* Send to the server */
2860 old_ident = silc_command_get_ident(cmd->payload);
2861 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2862 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2864 silc_server_packet_send(server, entry->connection,
2865 SILC_PACKET_COMMAND, cmd->packet->flags,
2866 tmpbuf->data, tmpbuf->len, TRUE);
2868 /* Reprocess this packet after received reply from router */
2869 silc_server_command_pending(server, SILC_COMMAND_INFO,
2870 silc_command_get_ident(cmd->payload),
2871 silc_server_command_info,
2872 silc_server_command_dup(cmd));
2873 cmd->pending = TRUE;
2874 silc_command_set_ident(cmd->payload, old_ident);
2875 silc_buffer_free(tmpbuf);
2879 if (!entry && !cmd->pending && !server->standalone) {
2880 /* Send to the primary router */
2884 old_ident = silc_command_get_ident(cmd->payload);
2885 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2886 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2888 silc_server_packet_send(server, server->router->connection,
2889 SILC_PACKET_COMMAND, cmd->packet->flags,
2890 tmpbuf->data, tmpbuf->len, TRUE);
2892 /* Reprocess this packet after received reply from router */
2893 silc_server_command_pending(server, SILC_COMMAND_INFO,
2894 silc_command_get_ident(cmd->payload),
2895 silc_server_command_info,
2896 silc_server_command_dup(cmd));
2897 cmd->pending = TRUE;
2898 silc_command_set_ident(cmd->payload, old_ident);
2899 silc_buffer_free(tmpbuf);
2904 silc_free(server_id);
2907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2908 SILC_STATUS_ERR_NO_SUCH_SERVER);
2912 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2914 server_info = entry->server_info;
2915 server_name = entry->server_name;
2917 /* Send the reply */
2918 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2919 SILC_STATUS_OK, ident, 3,
2920 2, idp->data, idp->len,
2922 strlen(server_name),
2925 strlen(server_info) : 0);
2926 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2927 packet->data, packet->len, FALSE);
2929 silc_buffer_free(packet);
2930 silc_buffer_free(idp);
2933 silc_server_command_free(cmd);
2936 /* Server side of command PING. This just replies to the ping. */
2938 SILC_SERVER_CMD_FUNC(ping)
2940 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2941 SilcServer server = cmd->server;
2946 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2949 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2951 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2952 SILC_STATUS_ERR_NO_SERVER_ID);
2955 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2959 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2960 /* Send our reply */
2961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2965 SILC_STATUS_ERR_NO_SUCH_SERVER);
2972 silc_server_command_free(cmd);
2975 /* Internal routine to join channel. The channel sent to this function
2976 has been either created or resolved from ID lists. This joins the sent
2977 client to the channel. */
2979 static void silc_server_command_join_channel(SilcServer server,
2980 SilcServerCommandContext cmd,
2981 SilcChannelEntry channel,
2982 SilcClientID *client_id,
2986 const unsigned char *auth,
2989 SilcSocketConnection sock = cmd->sock;
2991 uint32 tmp_len, user_count;
2992 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2993 SilcClientEntry client;
2994 SilcChannelClientEntry chl;
2995 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2996 uint16 ident = silc_command_get_ident(cmd->payload);
2997 char check[512], check2[512];
2998 bool founder = FALSE;
3001 SILC_LOG_DEBUG(("Start"));
3006 /* Get the client entry */
3007 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3008 client = (SilcClientEntry)sock->user_data;
3010 client = silc_server_get_client_resolve(server, client_id, &resolve);
3016 silc_server_command_send_status_reply(
3017 cmd, SILC_COMMAND_JOIN,
3018 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3022 /* The client info is being resolved. Reprocess this packet after
3023 receiving the reply to the query. */
3024 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3026 silc_server_command_join,
3027 silc_server_command_dup(cmd));
3028 cmd->pending = TRUE;
3032 cmd->pending = FALSE;
3036 * Check founder auth payload if provided. If client can gain founder
3037 * privileges it can override various conditions on joining the channel,
3038 * and can have directly the founder mode set on the channel.
3040 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3041 SilcIDListData idata = (SilcIDListData)client;
3043 if (channel->founder_key && idata->public_key &&
3044 silc_pkcs_public_key_compare(channel->founder_key,
3045 idata->public_key)) {
3046 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3047 (void *)channel->founder_passwd :
3048 (void *)channel->founder_key);
3049 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3050 channel->founder_passwd_len : 0);
3052 /* Check whether the client is to become founder */
3053 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3054 auth_data, auth_data_len,
3055 idata->hash, client->id, SILC_ID_CLIENT)) {
3056 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3063 * Check channel modes
3067 memset(check, 0, sizeof(check));
3068 memset(check2, 0, sizeof(check2));
3069 strncat(check, client->nickname, strlen(client->nickname));
3070 strncat(check, "!", 1);
3071 strncat(check, client->username, strlen(client->username));
3072 if (!strchr(client->username, '@')) {
3073 strncat(check, "@", 1);
3074 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3077 strncat(check2, client->nickname, strlen(client->nickname));
3078 if (!strchr(client->nickname, '@')) {
3079 strncat(check2, "@", 1);
3080 strncat(check2, server->server_name, strlen(server->server_name));
3082 strncat(check2, "!", 1);
3083 strncat(check2, client->username, strlen(client->username));
3084 if (!strchr(client->username, '@')) {
3085 strncat(check2, "@", 1);
3086 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3089 /* Check invite list if channel is invite-only channel */
3090 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3091 if (!channel->invite_list ||
3092 (!silc_string_match(channel->invite_list, check) &&
3093 !silc_string_match(channel->invite_list, check2))) {
3094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3095 SILC_STATUS_ERR_NOT_INVITED);
3100 /* Check ban list if it exists. If the client's nickname, server,
3101 username and/or hostname is in the ban list the access to the
3102 channel is denied. */
3103 if (channel->ban_list) {
3104 if (silc_string_match(channel->ban_list, check) ||
3105 silc_string_match(channel->ban_list, check2)) {
3106 silc_server_command_send_status_reply(
3107 cmd, SILC_COMMAND_JOIN,
3108 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3113 /* Check user count limit if set. */
3114 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3115 if (silc_hash_table_count(channel->user_list) + 1 >
3116 channel->user_limit) {
3117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3118 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3124 /* Check the channel passphrase if set. */
3125 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3126 /* Get passphrase */
3127 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3129 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3130 memcpy(passphrase, tmp, tmp_len);
3133 if (!passphrase || !channel->passphrase ||
3134 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3135 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3136 SILC_STATUS_ERR_BAD_PASSWORD);
3142 * Client is allowed to join to the channel. Make it happen.
3145 /* Check whether the client already is on the channel */
3146 if (silc_server_client_on_channel(client, channel)) {
3147 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3148 SILC_STATUS_ERR_USER_ON_CHANNEL);
3152 /* Generate new channel key as protocol dictates */
3154 if (!silc_server_create_channel_key(server, channel, 0))
3157 /* Send the channel key. This is broadcasted to the channel but is not
3158 sent to the client who is joining to the channel. */
3159 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3160 silc_server_send_channel_key(server, NULL, channel,
3161 server->server_type == SILC_ROUTER ?
3162 FALSE : !server->standalone);
3165 /* Join the client to the channel by adding it to channel's user list.
3166 Add also the channel to client entry's channels list for fast cross-
3168 chl = silc_calloc(1, sizeof(*chl));
3170 chl->client = client;
3171 chl->channel = channel;
3172 silc_hash_table_add(channel->user_list, client, chl);
3173 silc_hash_table_add(client->channels, channel, chl);
3175 /* Get users on the channel */
3176 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3179 /* Encode Client ID Payload of the original client who wants to join */
3180 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3182 /* Encode command reply packet */
3183 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3184 SILC_PUT32_MSB(channel->mode, mode);
3185 SILC_PUT32_MSB(created, tmp2);
3186 SILC_PUT32_MSB(user_count, tmp3);
3188 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3189 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3190 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3191 strlen(channel->channel_key->
3193 channel->channel_key->cipher->name,
3194 channel->key_len / 8, channel->key);
3199 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3200 SILC_STATUS_OK, ident, 13,
3201 2, channel->channel_name,
3202 strlen(channel->channel_name),
3203 3, chidp->data, chidp->len,
3204 4, clidp->data, clidp->len,
3207 7, keyp ? keyp->data : NULL,
3208 keyp ? keyp->len : 0,
3209 8, channel->ban_list,
3211 strlen(channel->ban_list) : 0,
3212 9, channel->invite_list,
3213 channel->invite_list ?
3214 strlen(channel->invite_list) : 0,
3217 strlen(channel->topic) : 0,
3218 11, silc_hmac_get_name(channel->hmac),
3219 strlen(silc_hmac_get_name(channel->
3222 13, user_list->data, user_list->len,
3223 14, mode_list->data,
3226 /* Send command reply */
3227 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3228 reply->data, reply->len, FALSE);
3230 /* Send JOIN notify to locally connected clients on the channel. If
3231 we are normal server then router will send or have sent JOIN notify
3232 already. However since we've added the client already to our channel
3233 we'll ignore it (in packet_receive.c) so we must send it here. If
3234 we are router then this will send it to local clients and local
3236 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3237 SILC_NOTIFY_TYPE_JOIN, 2,
3238 clidp->data, clidp->len,
3239 chidp->data, chidp->len);
3241 if (!cmd->pending) {
3242 /* Send JOIN notify packet to our primary router */
3243 if (!server->standalone)
3244 silc_server_send_notify_join(server, server->router->connection,
3245 server->server_type == SILC_ROUTER ?
3246 TRUE : FALSE, channel, client->id);
3249 /* Distribute the channel key to all backup routers. */
3250 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3251 keyp->data, keyp->len, FALSE, TRUE);
3253 /* If client became founder by providing correct founder auth data
3254 notify the mode change to the channel. */
3256 SILC_PUT32_MSB(chl->mode, mode);
3257 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3258 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3259 clidp->data, clidp->len,
3260 mode, 4, clidp->data, clidp->len);
3262 /* Set CUMODE notify type to network */
3263 if (!server->standalone)
3264 silc_server_send_notify_cumode(server, server->router->connection,
3265 server->server_type == SILC_ROUTER ?
3266 TRUE : FALSE, channel,
3267 chl->mode, client->id, SILC_ID_CLIENT,
3272 silc_buffer_free(reply);
3273 silc_buffer_free(clidp);
3274 silc_buffer_free(chidp);
3275 silc_buffer_free(keyp);
3276 silc_buffer_free(user_list);
3277 silc_buffer_free(mode_list);
3280 silc_free(passphrase);
3283 /* Server side of command JOIN. Joins client into requested channel. If
3284 the channel does not exist it will be created. */
3286 SILC_SERVER_CMD_FUNC(join)
3288 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3289 SilcServer server = cmd->server;
3290 unsigned char *auth;
3291 uint32 tmp_len, auth_len;
3292 char *tmp, *channel_name = NULL, *cipher, *hmac;
3293 SilcChannelEntry channel;
3295 bool created = FALSE, create_key = TRUE;
3296 SilcClientID *client_id;
3298 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3300 /* Get channel name */
3301 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3304 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3310 channel_name[255] = '\0';
3312 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3314 SILC_STATUS_ERR_BAD_CHANNEL);
3318 /* Get Client ID of the client who is joining to the channel */
3319 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3322 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3325 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3328 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3332 /* Get cipher, hmac name and auth payload */
3333 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3334 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3335 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3337 /* See if the channel exists */
3338 channel = silc_idlist_find_channel_by_name(server->local_list,
3339 channel_name, NULL);
3341 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3342 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3343 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3345 if (!channel || channel->disabled) {
3346 /* Channel not found */
3348 /* If we are standalone server we don't have a router, we just create
3349 the channel by ourselves. */
3350 if (server->standalone) {
3351 channel = silc_server_create_new_channel(server, server->id, cipher,
3352 hmac, channel_name, TRUE);
3354 silc_server_command_send_status_reply(
3355 cmd, SILC_COMMAND_JOIN,
3356 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3360 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3366 /* The channel does not exist on our server. If we are normal server
3367 we will send JOIN command to our router which will handle the
3368 joining procedure (either creates the channel if it doesn't exist
3369 or joins the client to it). */
3370 if (server->server_type != SILC_ROUTER) {
3374 /* If this is pending command callback then we've resolved
3375 it and it didn't work, return since we've notified the
3376 client already in the command reply callback. */
3380 old_ident = silc_command_get_ident(cmd->payload);
3381 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3382 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3384 /* Send JOIN command to our router */
3385 silc_server_packet_send(server, (SilcSocketConnection)
3386 server->router->connection,
3387 SILC_PACKET_COMMAND, cmd->packet->flags,
3388 tmpbuf->data, tmpbuf->len, TRUE);
3390 /* Reprocess this packet after received reply from router */
3391 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3392 silc_command_get_ident(cmd->payload),
3393 silc_server_command_join,
3394 silc_server_command_dup(cmd));
3395 cmd->pending = TRUE;
3399 /* We are router and the channel does not seem exist so we will check
3400 our global list as well for the channel. */
3401 channel = silc_idlist_find_channel_by_name(server->global_list,
3402 channel_name, NULL);
3404 /* Channel really does not exist, create it */
3405 channel = silc_server_create_new_channel(server, server->id, cipher,
3406 hmac, channel_name, TRUE);
3408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3409 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3413 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3421 /* Channel not found */
3423 /* If the command came from router and we are normal server then
3424 something went wrong with the joining as the channel was not found.
3425 We can't do anything else but ignore this. */
3426 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3427 server->server_type != SILC_ROUTER)
3430 /* We are router and the channel does not seem exist so we will check
3431 our global list as well for the channel. */
3432 channel = silc_idlist_find_channel_by_name(server->global_list,
3433 channel_name, NULL);
3435 /* Channel really does not exist, create it */
3436 channel = silc_server_create_new_channel(server, server->id, cipher,
3437 hmac, channel_name, TRUE);
3439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3440 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3444 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3451 /* Check whether the channel was created by our router */
3452 if (cmd->pending && context2) {
3453 SilcServerCommandReplyContext reply =
3454 (SilcServerCommandReplyContext)context2;
3456 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3457 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3458 SILC_GET32_MSB(created, tmp);
3459 create_key = FALSE; /* Router returned the key already */
3462 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3463 !silc_hash_table_count(channel->user_list))
3467 /* If the channel does not have global users and is also empty the client
3468 will be the channel founder and operator. */
3469 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3470 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3472 /* Join to the channel */
3473 silc_server_command_join_channel(server, cmd, channel, client_id,
3474 created, create_key, umode,
3477 silc_free(client_id);
3480 silc_server_command_free(cmd);
3483 /* Server side of command MOTD. Sends server's current "message of the
3484 day" to the client. */
3486 SILC_SERVER_CMD_FUNC(motd)
3488 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3489 SilcServer server = cmd->server;
3490 SilcBuffer packet, idp;
3491 char *motd, *dest_server;
3493 uint16 ident = silc_command_get_ident(cmd->payload);
3495 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3497 /* Get server name */
3498 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3500 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3501 SILC_STATUS_ERR_NO_SUCH_SERVER);
3505 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3508 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3510 if (server->config && server->config->motd &&
3511 server->config->motd->motd_file) {
3513 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3518 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3519 SILC_STATUS_OK, ident, 2,
3524 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3525 SILC_STATUS_OK, ident, 1,
3529 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3530 packet->data, packet->len, FALSE);
3531 silc_buffer_free(packet);
3532 silc_buffer_free(idp);
3534 SilcServerEntry entry;
3536 /* Check whether we have this server cached */
3537 entry = silc_idlist_find_server_by_name(server->global_list,
3538 dest_server, TRUE, NULL);
3540 entry = silc_idlist_find_server_by_name(server->local_list,
3541 dest_server, TRUE, NULL);
3544 if (server->server_type != SILC_SERVER && !cmd->pending &&
3545 entry && !entry->motd) {
3546 /* Send to the server */
3550 old_ident = silc_command_get_ident(cmd->payload);
3551 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3552 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3554 silc_server_packet_send(server, entry->connection,
3555 SILC_PACKET_COMMAND, cmd->packet->flags,
3556 tmpbuf->data, tmpbuf->len, TRUE);
3558 /* Reprocess this packet after received reply from router */
3559 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3560 silc_command_get_ident(cmd->payload),
3561 silc_server_command_motd,
3562 silc_server_command_dup(cmd));
3563 cmd->pending = TRUE;
3564 silc_command_set_ident(cmd->payload, old_ident);
3565 silc_buffer_free(tmpbuf);
3569 if (!entry && !cmd->pending && !server->standalone) {
3570 /* Send to the primary router */
3574 old_ident = silc_command_get_ident(cmd->payload);
3575 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3576 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3578 silc_server_packet_send(server, server->router->connection,
3579 SILC_PACKET_COMMAND, cmd->packet->flags,
3580 tmpbuf->data, tmpbuf->len, TRUE);
3582 /* Reprocess this packet after received reply from router */
3583 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3584 silc_command_get_ident(cmd->payload),
3585 silc_server_command_motd,
3586 silc_server_command_dup(cmd));
3587 cmd->pending = TRUE;
3588 silc_command_set_ident(cmd->payload, old_ident);
3589 silc_buffer_free(tmpbuf);
3594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3595 SILC_STATUS_ERR_NO_SUCH_SERVER);
3599 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3600 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3601 SILC_STATUS_OK, ident, 2,
3605 strlen(entry->motd) : 0);
3606 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3607 packet->data, packet->len, FALSE);
3608 silc_buffer_free(packet);
3609 silc_buffer_free(idp);
3613 silc_server_command_free(cmd);
3616 /* Server side of command UMODE. Client can use this command to set/unset
3617 user mode. Client actually cannot set itself to be as server/router
3618 operator so this can be used only to unset the modes. */
3620 SILC_SERVER_CMD_FUNC(umode)
3622 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3623 SilcServer server = cmd->server;
3624 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3626 unsigned char *tmp_mask;
3628 uint16 ident = silc_command_get_ident(cmd->payload);
3630 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3633 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3635 /* Get the client's mode mask */
3636 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3638 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3639 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3642 SILC_GET32_MSB(mask, tmp_mask);
3648 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3649 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3650 /* Cannot operator mode */
3651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3652 SILC_STATUS_ERR_PERM_DENIED);
3656 /* Remove the server operator rights */
3657 if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
3658 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3659 if (client->connection)
3660 server->stat.my_server_ops--;
3661 if (server->server_type == SILC_ROUTER)
3662 server->stat.server_ops--;
3666 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3667 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3668 /* Cannot operator mode */
3669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3670 SILC_STATUS_ERR_PERM_DENIED);
3674 /* Remove the router operator rights */
3675 if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
3676 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3677 if (client->connection)
3678 server->stat.my_router_ops--;
3679 if (server->server_type == SILC_ROUTER)
3680 server->stat.router_ops--;
3684 if (mask & SILC_UMODE_GONE) {
3685 client->mode |= SILC_UMODE_GONE;
3687 if (client->mode & SILC_UMODE_GONE)
3688 /* Remove the gone status */
3689 client->mode &= ~SILC_UMODE_GONE;
3692 /* Send UMODE change to primary router */
3693 if (!server->standalone)
3694 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3695 client->id, client->mode);
3697 /* Send command reply to sender */
3698 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3699 SILC_STATUS_OK, ident, 1,
3701 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3702 packet->data, packet->len, FALSE);
3703 silc_buffer_free(packet);
3706 silc_server_command_free(cmd);
3709 /* Checks that client has rights to add or remove channel modes. If any
3710 of the checks fails FALSE is returned. */
3712 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3713 SilcChannelClientEntry client,
3716 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3717 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3719 /* Check whether has rights to change anything */
3720 if (!is_op && !is_fo)
3723 /* Check whether has rights to change everything */
3727 /* We know that client is channel operator, check that they are not
3728 changing anything that requires channel founder rights. Rest of the
3729 modes are available automatically for channel operator. */
3731 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3732 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3733 if (is_op && !is_fo)
3736 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3737 if (is_op && !is_fo)
3742 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3743 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3744 if (is_op && !is_fo)
3747 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3748 if (is_op && !is_fo)
3753 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3754 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3755 if (is_op && !is_fo)
3758 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3759 if (is_op && !is_fo)
3764 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3765 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3766 if (is_op && !is_fo)
3769 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3770 if (is_op && !is_fo)
3778 /* Server side command of CMODE. Changes channel mode */
3780 SILC_SERVER_CMD_FUNC(cmode)
3782 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3783 SilcServer server = cmd->server;
3784 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3785 SilcIDListData idata = (SilcIDListData)client;
3786 SilcChannelID *channel_id;
3787 SilcChannelEntry channel;
3788 SilcChannelClientEntry chl;
3789 SilcBuffer packet, cidp;
3790 unsigned char *tmp, *tmp_id, *tmp_mask;
3791 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3792 uint32 mode_mask, tmp_len, tmp_len2;
3793 uint16 ident = silc_command_get_ident(cmd->payload);
3795 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3797 /* Get Channel ID */
3798 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3801 SILC_STATUS_ERR_NO_CHANNEL_ID);
3804 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3807 SILC_STATUS_ERR_NO_CHANNEL_ID);
3811 /* Get the channel mode mask */
3812 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3815 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3818 SILC_GET32_MSB(mode_mask, tmp_mask);
3820 /* Get channel entry */
3821 channel = silc_idlist_find_channel_by_id(server->local_list,
3824 channel = silc_idlist_find_channel_by_id(server->global_list,
3827 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3828 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3833 /* Check whether this client is on the channel */
3834 if (!silc_server_client_on_channel(client, channel)) {
3835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3836 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3840 /* Get entry to the channel user list */
3841 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3843 /* Check that client has rights to change any requested channel modes */
3844 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3846 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3851 * Check the modes. Modes that requires nothing special operation are
3855 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3856 /* Channel uses private keys to protect traffic. Client(s) has set the
3857 key locally they want to use, server does not know that key. */
3858 /* Nothing interesting to do here */
3860 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3861 /* The mode is removed and we need to generate and distribute
3862 new channel key. Clients are not using private channel keys
3863 anymore after this. */
3865 /* Re-generate channel key */
3866 if (!silc_server_create_channel_key(server, channel, 0))
3869 /* Send the channel key. This sends it to our local clients and if
3870 we are normal server to our router as well. */
3871 silc_server_send_channel_key(server, NULL, channel,
3872 server->server_type == SILC_ROUTER ?
3873 FALSE : !server->standalone);
3875 cipher = channel->channel_key->cipher->name;
3876 hmac = (char *)silc_hmac_get_name(channel->hmac);
3880 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3881 /* User limit is set on channel */
3884 /* Get user limit */
3885 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3887 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3888 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3889 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3893 SILC_GET32_MSB(user_limit, tmp);
3894 channel->user_limit = user_limit;
3897 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3898 /* User limit mode is unset. Remove user limit */
3899 channel->user_limit = 0;
3902 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3903 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3904 /* Passphrase has been set to channel */
3906 /* Get the passphrase */
3907 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3910 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3914 /* Save the passphrase */
3915 passphrase = channel->passphrase = strdup(tmp);
3918 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3919 /* Passphrase mode is unset. remove the passphrase */
3920 if (channel->passphrase) {
3921 silc_free(channel->passphrase);
3922 channel->passphrase = NULL;
3927 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3928 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3929 /* Cipher to use protect the traffic */
3930 SilcCipher newkey, oldkey;
3933 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3936 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3940 /* Delete old cipher and allocate the new one */
3941 if (!silc_cipher_alloc(cipher, &newkey)) {
3942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3943 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3947 oldkey = channel->channel_key;
3948 channel->channel_key = newkey;
3950 /* Re-generate channel key */
3951 if (!silc_server_create_channel_key(server, channel, 0)) {
3952 /* We don't have new key, revert to old one */
3953 channel->channel_key = oldkey;
3957 /* Remove old channel key for good */
3958 silc_cipher_free(oldkey);
3960 /* Send the channel key. This sends it to our local clients and if
3961 we are normal server to our router as well. */
3962 silc_server_send_channel_key(server, NULL, channel,
3963 server->server_type == SILC_ROUTER ?
3964 FALSE : !server->standalone);
3967 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3968 /* Cipher mode is unset. Remove the cipher and revert back to
3970 SilcCipher newkey, oldkey;
3971 cipher = channel->cipher;
3973 /* Delete old cipher and allocate default one */
3974 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3976 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3980 oldkey = channel->channel_key;
3981 channel->channel_key = newkey;
3983 /* Re-generate channel key */
3984 if (!silc_server_create_channel_key(server, channel, 0)) {
3985 /* We don't have new key, revert to old one */
3986 channel->channel_key = oldkey;
3990 /* Remove old channel key for good */
3991 silc_cipher_free(oldkey);
3993 /* Send the channel key. This sends it to our local clients and if
3994 we are normal server to our router as well. */
3995 silc_server_send_channel_key(server, NULL, channel,
3996 server->server_type == SILC_ROUTER ?
3997 FALSE : !server->standalone);
4001 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4002 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4003 /* HMAC to use protect the traffic */
4004 unsigned char hash[32];
4008 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4011 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4015 /* Delete old hmac and allocate the new one */
4016 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4018 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4022 silc_hmac_free(channel->hmac);
4023 channel->hmac = newhmac;
4025 /* Set the HMAC key out of current channel key. The client must do
4027 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4028 channel->key_len / 8, hash);
4029 silc_hmac_set_key(channel->hmac, hash,
4030 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4031 memset(hash, 0, sizeof(hash));
4034 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4035 /* Hmac mode is unset. Remove the hmac and revert back to
4038 unsigned char hash[32];
4039 hmac = channel->hmac_name;
4041 /* Delete old hmac and allocate default one */
4042 silc_hmac_free(channel->hmac);
4043 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4045 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4049 silc_hmac_free(channel->hmac);
4050 channel->hmac = newhmac;
4052 /* Set the HMAC key out of current channel key. The client must do
4054 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4055 channel->key_len / 8,
4057 silc_hmac_set_key(channel->hmac, hash,
4058 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4059 memset(hash, 0, sizeof(hash));
4063 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4064 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4065 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4066 /* Set the founder authentication */
4067 SilcAuthPayload auth;
4069 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4071 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4072 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4076 auth = silc_auth_payload_parse(tmp, tmp_len);
4078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4079 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4083 /* Save the public key */
4084 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4085 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4088 channel->founder_method = silc_auth_get_method(auth);
4090 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4091 tmp = silc_auth_get_data(auth, &tmp_len);
4092 channel->founder_passwd =
4093 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4094 memcpy(channel->founder_passwd, tmp, tmp_len);
4095 channel->founder_passwd_len = tmp_len;
4097 /* Verify the payload before setting the mode */
4098 if (!silc_auth_verify(auth, channel->founder_method,
4099 channel->founder_key, 0, idata->hash,
4100 client->id, SILC_ID_CLIENT)) {
4101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4102 SILC_STATUS_ERR_AUTH_FAILED);
4107 silc_auth_payload_free(auth);
4111 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4112 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4113 if (channel->founder_key)
4114 silc_pkcs_public_key_free(channel->founder_key);
4115 if (channel->founder_passwd) {
4116 silc_free(channel->founder_passwd);
4117 channel->founder_passwd = NULL;
4123 /* Finally, set the mode */
4124 channel->mode = mode_mask;
4126 /* Send CMODE_CHANGE notify. */
4127 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4128 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4129 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4130 cidp->data, cidp->len,
4132 cipher, cipher ? strlen(cipher) : 0,
4133 hmac, hmac ? strlen(hmac) : 0,
4134 passphrase, passphrase ?
4135 strlen(passphrase) : 0);
4137 /* Set CMODE notify type to network */
4138 if (!server->standalone)
4139 silc_server_send_notify_cmode(server, server->router->connection,
4140 server->server_type == SILC_ROUTER ?
4141 TRUE : FALSE, channel,
4142 mode_mask, client->id, SILC_ID_CLIENT,
4143 cipher, hmac, passphrase);
4145 /* Send command reply to sender */
4146 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4147 SILC_STATUS_OK, ident, 2,
4148 2, tmp_id, tmp_len2,
4150 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4151 packet->data, packet->len, FALSE);
4153 silc_buffer_free(packet);
4154 silc_free(channel_id);
4155 silc_buffer_free(cidp);
4158 silc_server_command_free(cmd);
4161 /* Server side of CUMODE command. Changes client's mode on a channel. */
4163 SILC_SERVER_CMD_FUNC(cumode)
4165 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4166 SilcServer server = cmd->server;
4167 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4168 SilcIDListData idata = (SilcIDListData)client;
4169 SilcChannelID *channel_id;
4170 SilcClientID *client_id;
4171 SilcChannelEntry channel;
4172 SilcClientEntry target_client;
4173 SilcChannelClientEntry chl;
4174 SilcBuffer packet, idp;
4175 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4176 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4178 uint16 ident = silc_command_get_ident(cmd->payload);
4180 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4182 /* Get Channel ID */
4183 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4186 SILC_STATUS_ERR_NO_CHANNEL_ID);
4189 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4192 SILC_STATUS_ERR_NO_CHANNEL_ID);
4196 /* Get channel entry */
4197 channel = silc_idlist_find_channel_by_id(server->local_list,
4200 channel = silc_idlist_find_channel_by_id(server->global_list,
4203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4204 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4209 /* Check whether sender is on the channel */
4210 if (!silc_server_client_on_channel(client, channel)) {
4211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4212 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4216 /* Check that client has rights to change other's rights */
4217 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4218 sender_mask = chl->mode;
4220 /* Get the target client's channel mode mask */
4221 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4224 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4227 SILC_GET32_MSB(target_mask, tmp_mask);
4229 /* Get target Client ID */
4230 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4233 SILC_STATUS_ERR_NO_CLIENT_ID);
4236 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4239 SILC_STATUS_ERR_NO_CLIENT_ID);
4243 /* Get target client's entry */
4244 target_client = silc_idlist_find_client_by_id(server->local_list,
4245 client_id, TRUE, NULL);
4246 if (!target_client) {
4247 target_client = silc_idlist_find_client_by_id(server->global_list,
4248 client_id, TRUE, NULL);
4251 if (target_client != client &&
4252 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4253 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4254 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4255 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4259 /* Check whether target client is on the channel */
4260 if (target_client != client) {
4261 if (!silc_server_client_on_channel(target_client, channel)) {
4262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4263 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4267 /* Get entry to the channel user list */
4268 silc_hash_table_find(channel->user_list, target_client, NULL,
4276 /* If the target client is founder, no one else can change their mode
4278 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4280 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4284 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4285 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4286 /* The client tries to claim the founder rights. */
4287 unsigned char *tmp_auth;
4288 uint32 tmp_auth_len, auth_len;
4291 if (target_client != client) {
4292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4293 SILC_STATUS_ERR_NOT_YOU);
4297 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4298 !channel->founder_key || !idata->public_key ||
4299 !silc_pkcs_public_key_compare(channel->founder_key,
4300 idata->public_key)) {
4301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4302 SILC_STATUS_ERR_NOT_YOU);
4306 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4309 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4313 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4314 (void *)channel->founder_passwd : (void *)channel->founder_key);
4315 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4316 channel->founder_passwd_len : 0);
4318 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4319 channel->founder_method, auth, auth_len,
4320 idata->hash, client->id, SILC_ID_CLIENT)) {
4321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4322 SILC_STATUS_ERR_AUTH_FAILED);
4326 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4330 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4331 if (target_client == client) {
4332 /* Remove channel founder rights from itself */
4333 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4337 SILC_STATUS_ERR_NOT_YOU);
4343 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4344 /* Promote to operator */
4345 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4346 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4347 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4349 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4353 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4357 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4358 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4359 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4361 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4365 /* Demote to normal user */
4366 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4371 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4372 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4374 /* Send notify to channel, notify only if mode was actually changed. */
4376 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4377 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4378 idp->data, idp->len,
4382 /* Set CUMODE notify type to network */
4383 if (!server->standalone)
4384 silc_server_send_notify_cumode(server, server->router->connection,
4385 server->server_type == SILC_ROUTER ?
4386 TRUE : FALSE, channel,
4387 target_mask, client->id,
4392 /* Send command reply to sender */
4393 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4394 SILC_STATUS_OK, ident, 3,
4396 3, tmp_ch_id, tmp_ch_len,
4397 4, tmp_id, tmp_len);
4398 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4399 packet->data, packet->len, FALSE);
4401 silc_buffer_free(packet);
4402 silc_free(channel_id);
4403 silc_free(client_id);
4404 silc_buffer_free(idp);
4407 silc_server_command_free(cmd);
4410 /* Server side of KICK command. Kicks client out of channel. */
4412 SILC_SERVER_CMD_FUNC(kick)
4414 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4415 SilcServer server = cmd->server;
4416 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4417 SilcClientEntry target_client;
4418 SilcChannelID *channel_id;
4419 SilcClientID *client_id;
4420 SilcChannelEntry channel;
4421 SilcChannelClientEntry chl;
4423 uint32 tmp_len, target_idp_len;
4424 unsigned char *tmp, *comment, *target_idp;
4426 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4428 /* Get Channel ID */
4429 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4432 SILC_STATUS_ERR_NO_CHANNEL_ID);
4435 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4438 SILC_STATUS_ERR_NO_CHANNEL_ID);
4442 /* Get channel entry */
4443 channel = silc_idlist_find_channel_by_id(server->local_list,
4446 channel = silc_idlist_find_channel_by_id(server->local_list,
4449 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4450 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4455 /* Check whether sender is on the channel */
4456 if (!silc_server_client_on_channel(client, channel)) {
4457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4458 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4462 /* Check that the kicker is channel operator or channel founder */
4463 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4464 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4466 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4470 /* Get target Client ID */
4471 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4474 SILC_STATUS_ERR_NO_CLIENT_ID);
4477 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4480 SILC_STATUS_ERR_NO_CLIENT_ID);
4484 /* Get target client's entry */
4485 target_client = silc_idlist_find_client_by_id(server->local_list,
4486 client_id, TRUE, NULL);
4487 if (!target_client) {
4488 target_client = silc_idlist_find_client_by_id(server->global_list,
4489 client_id, TRUE, NULL);
4492 /* Check that the target client is not channel founder. Channel founder
4493 cannot be kicked from the channel. */
4494 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4495 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4497 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4501 /* Check whether target client is on the channel */
4502 if (!silc_server_client_on_channel(target_client, channel)) {
4503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4504 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4510 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4514 /* Send command reply to sender */
4515 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4518 /* Send KICKED notify to local clients on the channel */
4519 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4520 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4521 SILC_NOTIFY_TYPE_KICKED, 3,
4522 target_idp, target_idp_len,
4523 comment, comment ? strlen(comment) : 0,
4524 idp->data, idp->len);
4525 silc_buffer_free(idp);
4527 /* Remove the client from the channel. If the channel does not exist
4528 after removing the client then the client kicked itself off the channel
4529 and we don't have to send anything after that. */
4530 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4531 target_client, FALSE))
4534 /* Send KICKED notify to primary route */
4535 if (!server->standalone)
4536 silc_server_send_notify_kicked(server, server->router->connection,
4537 server->server_type == SILC_ROUTER ?
4538 TRUE : FALSE, channel,
4539 target_client->id, client->id, comment);
4541 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4542 /* Re-generate channel key */
4543 if (!silc_server_create_channel_key(server, channel, 0))
4546 /* Send the channel key to the channel. The key of course is not sent
4547 to the client who was kicked off the channel. */
4548 silc_server_send_channel_key(server, target_client->connection, channel,
4549 server->server_type == SILC_ROUTER ?
4550 FALSE : !server->standalone);
4554 silc_server_command_free(cmd);
4557 /* Server side of OPER command. Client uses this comand to obtain server
4558 operator privileges to this server/router. */
4560 SILC_SERVER_CMD_FUNC(oper)
4562 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4563 SilcServer server = cmd->server;
4564 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4565 unsigned char *username, *auth;
4567 SilcServerConfigSectionAdminConnection *admin;
4568 SilcIDListData idata = (SilcIDListData)client;
4570 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4572 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4575 /* Get the username */
4576 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4579 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4583 /* Get the admin configuration */
4584 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4585 username, client->nickname);
4587 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4588 username, client->nickname);
4590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4591 SILC_STATUS_ERR_AUTH_FAILED);
4596 /* Get the authentication payload */
4597 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4600 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4604 /* Verify the authentication data */
4605 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4606 admin->auth_data, admin->auth_data_len,
4607 idata->hash, client->id, SILC_ID_CLIENT)) {
4608 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4609 SILC_STATUS_ERR_AUTH_FAILED);
4613 /* Client is now server operator */
4614 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4616 /* Update statistics */
4617 if (client->connection)
4618 server->stat.my_server_ops++;
4619 if (server->server_type == SILC_ROUTER)
4620 server->stat.server_ops++;
4622 /* Send UMODE change to primary router */
4623 if (!server->standalone)
4624 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4625 client->id, client->mode);
4627 /* Send reply to the sender */
4628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4632 silc_server_command_free(cmd);
4635 /* Server side of SILCOPER command. Client uses this comand to obtain router
4636 operator privileges to this router. */
4638 SILC_SERVER_CMD_FUNC(silcoper)
4640 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4641 SilcServer server = cmd->server;
4642 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4643 unsigned char *username, *auth;
4645 SilcServerConfigSectionAdminConnection *admin;
4646 SilcIDListData idata = (SilcIDListData)client;
4648 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4650 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4653 if (server->server_type != SILC_ROUTER) {
4654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4655 SILC_STATUS_ERR_AUTH_FAILED);
4659 /* Get the username */
4660 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4663 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4667 /* Get the admin configuration */
4668 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4669 username, client->nickname);
4671 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4672 username, client->nickname);
4674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4675 SILC_STATUS_ERR_AUTH_FAILED);
4680 /* Get the authentication payload */
4681 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4684 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4688 /* Verify the authentication data */
4689 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4690 admin->auth_data, admin->auth_data_len,
4691 idata->hash, client->id, SILC_ID_CLIENT)) {
4692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4693 SILC_STATUS_ERR_AUTH_FAILED);
4697 /* Client is now router operator */
4698 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4700 /* Update statistics */
4701 if (client->connection)
4702 server->stat.my_router_ops++;
4703 if (server->server_type == SILC_ROUTER)
4704 server->stat.router_ops++;
4706 /* Send UMODE change to primary router */
4707 if (!server->standalone)
4708 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4709 client->id, client->mode);
4711 /* Send reply to the sender */
4712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4716 silc_server_command_free(cmd);
4719 /* Server side command of CONNECT. Connects us to the specified remote
4720 server or router. */
4722 SILC_SERVER_CMD_FUNC(connect)
4724 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4725 SilcServer server = cmd->server;
4726 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4727 unsigned char *tmp, *host;
4729 uint32 port = SILC_PORT;
4731 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4733 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4736 /* Check whether client has the permissions. */
4737 if (client->mode == SILC_UMODE_NONE) {
4738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4739 SILC_STATUS_ERR_NO_SERVER_PRIV);
4743 if (server->server_type == SILC_ROUTER &&
4744 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4745 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4746 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4750 /* Get the remote server */
4751 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4754 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4759 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4761 SILC_GET32_MSB(port, tmp);
4763 /* Create the connection. It is done with timeout and is async. */
4764 silc_server_create_connection(server, host, port);
4766 /* Send reply to the sender */
4767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4771 silc_server_command_free(cmd);
4774 /* Server side of command BAN. This is used to manage the ban list of the
4775 channel. To add clients and remove clients from the ban list. */
4777 SILC_SERVER_CMD_FUNC(ban)
4779 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4780 SilcServer server = cmd->server;
4781 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4783 SilcChannelEntry channel;
4784 SilcChannelClientEntry chl;
4785 SilcChannelID *channel_id = NULL;
4786 unsigned char *id, *add, *del;
4787 uint32 id_len, tmp_len;
4788 uint16 ident = silc_command_get_ident(cmd->payload);
4790 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4793 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4795 /* Get Channel ID */
4796 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4798 channel_id = silc_id_payload_parse_id(id, id_len);
4800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4801 SILC_STATUS_ERR_NO_CHANNEL_ID);
4806 /* Get channel entry. The server must know about the channel since the
4807 client is expected to be on the channel. */
4808 channel = silc_idlist_find_channel_by_id(server->local_list,
4811 channel = silc_idlist_find_channel_by_id(server->global_list,
4814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4815 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4820 /* Check whether this client is on the channel */
4821 if (!silc_server_client_on_channel(client, channel)) {
4822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4823 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4827 /* Get entry to the channel user list */
4828 if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
4829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4830 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4834 /* The client must be at least channel operator. */
4835 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4837 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4841 /* Get the new ban and add it to the ban list */
4842 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4844 if (!channel->ban_list)
4845 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4847 channel->ban_list = silc_realloc(channel->ban_list,
4848 sizeof(*channel->ban_list) *
4850 strlen(channel->ban_list) + 2));
4851 if (add[tmp_len - 1] == ',')
4852 add[tmp_len - 1] = '\0';
4854 strncat(channel->ban_list, add, tmp_len);
4855 strncat(channel->ban_list, ",", 1);
4858 /* Get the ban to be removed and remove it from the list */
4859 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4860 if (del && channel->ban_list) {
4861 char *start, *end, *n;
4863 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4864 silc_free(channel->ban_list);
4865 channel->ban_list = NULL;
4867 start = strstr(channel->ban_list, del);
4868 if (start && strlen(start) >= tmp_len) {
4869 end = start + tmp_len;
4870 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4871 strncat(n, channel->ban_list, start - channel->ban_list);
4872 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4874 silc_free(channel->ban_list);
4875 channel->ban_list = n;
4880 /* Send the BAN notify type to our primary router. */
4881 if (!server->standalone && (add || del))
4882 silc_server_send_notify_ban(server, server->router->connection,
4883 server->server_type == SILC_ROUTER ?
4884 TRUE : FALSE, channel, add, del);
4886 /* Send the reply back to the client */
4888 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4889 SILC_STATUS_OK, ident, 2,
4891 3, channel->ban_list,
4893 strlen(channel->ban_list) : 0);
4894 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4895 packet->data, packet->len, FALSE);
4897 silc_buffer_free(packet);
4900 silc_free(channel_id);
4901 silc_server_command_free(cmd);
4904 /* Server side command of CLOSE. Closes connection to a specified server. */
4906 SILC_SERVER_CMD_FUNC(close)
4908 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4909 SilcServer server = cmd->server;
4910 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4911 SilcServerEntry server_entry;
4912 SilcSocketConnection sock;
4915 unsigned char *name;
4916 uint32 port = SILC_PORT;
4918 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4920 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4923 /* Check whether client has the permissions. */
4924 if (client->mode == SILC_UMODE_NONE) {
4925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4926 SILC_STATUS_ERR_NO_SERVER_PRIV);
4930 /* Get the remote server */
4931 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4934 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4939 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4941 SILC_GET32_MSB(port, tmp);
4943 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4944 name, port, FALSE, NULL);
4946 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4947 name, port, FALSE, NULL);
4948 if (!server_entry) {
4949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4950 SILC_STATUS_ERR_NO_SERVER_ID);
4954 /* Send reply to the sender */
4955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4958 /* Close the connection to the server */
4959 sock = (SilcSocketConnection)server_entry->connection;
4961 /* If we shutdown primary router connection manually then don't trigger
4962 any reconnect or backup router connections, by setting the router
4964 if (server->router == server_entry) {
4965 server->id_entry->router = NULL;
4966 server->router = NULL;
4967 server->standalone = TRUE;
4969 silc_server_free_sock_user_data(server, sock, NULL);
4970 silc_server_close_connection(server, sock);
4973 silc_server_command_free(cmd);
4976 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4977 active connections. */
4979 SILC_SERVER_CMD_FUNC(shutdown)
4981 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4982 SilcServer server = cmd->server;
4983 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4985 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4987 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4990 /* Check whether client has the permission. */
4991 if (client->mode == SILC_UMODE_NONE) {
4992 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4993 SILC_STATUS_ERR_NO_SERVER_PRIV);
4997 /* Send reply to the sender */
4998 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5001 /* Then, gracefully, or not, bring the server down. */
5002 silc_server_stop(server);
5006 silc_server_command_free(cmd);
5009 /* Server side command of LEAVE. Removes client from a channel. */
5011 SILC_SERVER_CMD_FUNC(leave)
5013 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5014 SilcServer server = cmd->server;
5015 SilcSocketConnection sock = cmd->sock;
5016 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5017 SilcChannelID *id = NULL;
5018 SilcChannelEntry channel;
5022 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5024 /* Get Channel ID */
5025 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5028 SILC_STATUS_ERR_NO_CHANNEL_ID);
5031 id = silc_id_payload_parse_id(tmp, len);
5033 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5034 SILC_STATUS_ERR_NO_CHANNEL_ID);
5038 /* Get channel entry */
5039 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5041 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5044 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5049 /* Check whether this client is on the channel */
5050 if (!silc_server_client_on_channel(id_entry, channel)) {
5051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5052 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5056 /* Notify routers that they should remove this client from their list
5057 of clients on the channel. Send LEAVE notify type. */
5058 if (!server->standalone)
5059 silc_server_send_notify_leave(server, server->router->connection,
5060 server->server_type == SILC_ROUTER ?
5061 TRUE : FALSE, channel, id_entry->id);
5063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5066 /* Remove client from channel */
5067 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5069 /* If the channel does not exist anymore we won't send anything */
5072 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5073 /* Re-generate channel key */
5074 if (!silc_server_create_channel_key(server, channel, 0))
5077 /* Send the channel key */
5078 silc_server_send_channel_key(server, NULL, channel,
5079 server->server_type == SILC_ROUTER ?
5080 FALSE : !server->standalone);
5085 silc_server_command_free(cmd);
5088 /* Server side of command USERS. Resolves clients and their USERS currently
5089 joined on the requested channel. The list of Client ID's and their modes
5090 on the channel is sent back. */
5092 SILC_SERVER_CMD_FUNC(users)
5094 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5095 SilcServer server = cmd->server;
5096 SilcChannelEntry channel;
5097 SilcChannelID *id = NULL;
5098 SilcBuffer packet, idp;
5099 unsigned char *channel_id;
5100 uint32 channel_id_len;
5101 SilcBuffer client_id_list;
5102 SilcBuffer client_mode_list;
5103 unsigned char lc[4];
5104 uint32 list_count = 0;
5105 uint16 ident = silc_command_get_ident(cmd->payload);
5108 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5110 /* Get Channel ID */
5111 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5113 /* Get channel name */
5114 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5116 if (!channel_id && !channel_name) {
5117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5118 SILC_STATUS_ERR_NO_CHANNEL_ID);
5123 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5126 SILC_STATUS_ERR_NO_CHANNEL_ID);
5131 /* If we are server and we don't know about this channel we will send
5132 the command to our router. If we know about the channel then we also
5133 have the list of users already. */
5135 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5137 channel = silc_idlist_find_channel_by_name(server->local_list,
5138 channel_name, NULL);
5140 if (!channel || channel->disabled) {
5141 if (server->server_type != SILC_ROUTER && !server->standalone &&
5145 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5146 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5148 /* Send USERS command */
5149 silc_server_packet_send(server, server->router->connection,
5150 SILC_PACKET_COMMAND, cmd->packet->flags,
5151 tmpbuf->data, tmpbuf->len, TRUE);
5153 /* Reprocess this packet after received reply */
5154 silc_server_command_pending(server, SILC_COMMAND_USERS,
5155 silc_command_get_ident(cmd->payload),
5156 silc_server_command_users,
5157 silc_server_command_dup(cmd));
5158 cmd->pending = TRUE;
5159 silc_command_set_ident(cmd->payload, ident);
5160 silc_buffer_free(tmpbuf);
5165 /* Check the global list as well. */
5167 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5169 channel = silc_idlist_find_channel_by_name(server->global_list,
5170 channel_name, NULL);
5172 /* Channel really does not exist */
5173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5174 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5179 /* If the channel is private or secret do not send anything, unless the
5180 user requesting this command is on the channel. */
5181 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5182 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5183 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5184 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5185 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5190 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5192 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5197 /* Get the users list */
5198 silc_server_get_users_on_channel(server, channel, &client_id_list,
5199 &client_mode_list, &list_count);
5202 SILC_PUT32_MSB(list_count, lc);
5205 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5206 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5207 SILC_STATUS_OK, ident, 4,
5208 2, idp->data, idp->len,
5210 4, client_id_list->data,
5211 client_id_list->len,
5212 5, client_mode_list->data,
5213 client_mode_list->len);
5214 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5215 packet->data, packet->len, FALSE);
5217 silc_buffer_free(idp);
5218 silc_buffer_free(packet);
5219 silc_buffer_free(client_id_list);
5220 silc_buffer_free(client_mode_list);
5224 silc_server_command_free(cmd);
5227 /* Server side of command GETKEY. This fetches the client's public key
5228 from the server where to the client is connected. */
5230 SILC_SERVER_CMD_FUNC(getkey)
5232 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5233 SilcServer server = cmd->server;
5235 SilcClientEntry client;
5236 SilcServerEntry server_entry;
5237 SilcClientID *client_id = NULL;
5238 SilcServerID *server_id = NULL;
5239 SilcIDPayload idp = NULL;
5240 uint16 ident = silc_command_get_ident(cmd->payload);
5241 unsigned char *tmp, *pkdata;
5242 uint32 tmp_len, pklen;
5243 SilcBuffer pk = NULL;
5245 SilcPublicKey public_key;
5247 SILC_LOG_DEBUG(("Start"));
5249 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5252 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5255 idp = silc_id_payload_parse(tmp, tmp_len);
5257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5258 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5262 id_type = silc_id_payload_get_type(idp);
5263 if (id_type == SILC_ID_CLIENT) {
5264 client_id = silc_id_payload_get_id(idp);
5266 /* If the client is not found from local list there is no chance it
5267 would be locally connected client so send the command further. */
5268 client = silc_idlist_find_client_by_id(server->local_list,
5269 client_id, TRUE, NULL);
5271 client = silc_idlist_find_client_by_id(server->global_list,
5272 client_id, TRUE, NULL);
5274 if ((!client && !cmd->pending && !server->standalone) ||
5275 (client && !client->connection && !cmd->pending) ||
5276 (client && !client->data.public_key && !cmd->pending)) {
5279 SilcSocketConnection dest_sock;
5281 dest_sock = silc_server_get_client_route(server, NULL, 0,
5286 old_ident = silc_command_get_ident(cmd->payload);
5287 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5288 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5290 silc_server_packet_send(server, dest_sock,
5291 SILC_PACKET_COMMAND, cmd->packet->flags,
5292 tmpbuf->data, tmpbuf->len, TRUE);
5294 /* Reprocess this packet after received reply from router */
5295 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5296 silc_command_get_ident(cmd->payload),
5297 silc_server_command_getkey,
5298 silc_server_command_dup(cmd));
5299 cmd->pending = TRUE;
5300 silc_command_set_ident(cmd->payload, old_ident);
5301 silc_buffer_free(tmpbuf);
5306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5307 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5311 /* The client is locally connected, just get the public key and
5312 send it back. If they key does not exist then do not send it,
5313 send just OK reply */
5314 public_key = client->data.public_key;
5319 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5320 pk = silc_buffer_alloc(4 + tmp_len);
5321 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5322 silc_buffer_format(pk,
5323 SILC_STR_UI_SHORT(tmp_len),
5324 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5325 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5331 } else if (id_type == SILC_ID_SERVER) {
5332 server_id = silc_id_payload_get_id(idp);
5334 /* If the server is not found from local list there is no chance it
5335 would be locally connected server so send the command further. */
5336 server_entry = silc_idlist_find_server_by_id(server->local_list,
5337 server_id, TRUE, NULL);
5339 server_entry = silc_idlist_find_server_by_id(server->global_list,
5340 server_id, TRUE, NULL);
5342 if (server_entry != server->id_entry &&
5343 ((!server_entry && !cmd->pending && !server->standalone) ||
5344 (server_entry && !server_entry->connection && !cmd->pending &&
5345 !server->standalone) ||
5346 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5347 !server->standalone))) {
5351 old_ident = silc_command_get_ident(cmd->payload);
5352 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5353 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5355 silc_server_packet_send(server, server->router->connection,
5356 SILC_PACKET_COMMAND, cmd->packet->flags,
5357 tmpbuf->data, tmpbuf->len, TRUE);
5359 /* Reprocess this packet after received reply from router */
5360 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5361 silc_command_get_ident(cmd->payload),
5362 silc_server_command_getkey,
5363 silc_server_command_dup(cmd));
5364 cmd->pending = TRUE;
5366 silc_command_set_ident(cmd->payload, old_ident);
5367 silc_buffer_free(tmpbuf);
5371 if (!server_entry) {
5372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5373 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5377 /* If they key does not exist then do not send it, send just OK reply */
5378 public_key = (!server_entry->data.public_key ?
5379 (server_entry == server->id_entry ? server->public_key :
5380 NULL) : server_entry->data.public_key);
5385 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5386 pk = silc_buffer_alloc(4 + tmp_len);
5387 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5388 silc_buffer_format(pk,
5389 SILC_STR_UI_SHORT(tmp_len),
5390 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5391 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5401 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5402 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5403 SILC_STATUS_OK, ident,
5407 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5408 packet->data, packet->len, FALSE);
5409 silc_buffer_free(packet);
5412 silc_buffer_free(pk);
5416 silc_id_payload_free(idp);
5417 silc_free(client_id);
5418 silc_free(server_id);
5419 silc_server_command_free(cmd);