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;
1064 silc_command_set_ident(cmd->payload, old_ident);
1066 silc_buffer_free(tmpbuf);
1075 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1076 SilcClientEntry *clients,
1077 uint32 clients_count)
1079 SilcServer server = cmd->server;
1081 int i, count = 0, len;
1082 SilcBuffer packet, idp;
1083 SilcClientEntry entry = NULL;
1084 SilcCommandStatus status;
1085 uint16 ident = silc_command_get_ident(cmd->payload);
1087 char nh[256], uh[256];
1089 status = SILC_STATUS_OK;
1090 if (clients_count > 1)
1091 status = SILC_STATUS_LIST_START;
1093 for (i = 0; i < clients_count; i++) {
1096 /* We will take only clients that are not valid anymore. They are the
1097 ones that are not registered anymore but still have a ID. They
1098 have disconnected us, and thus valid for WHOWAS. */
1099 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1102 if (count && i - 1 == count)
1107 if (clients_count > 2)
1108 status = SILC_STATUS_LIST_ITEM;
1109 if (clients_count > 1 && i == clients_count - 1)
1110 status = SILC_STATUS_LIST_END;
1112 /* Send WHOWAS reply */
1113 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1114 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1115 memset(uh, 0, sizeof(uh));
1116 memset(nh, 0, sizeof(nh));
1118 strncat(nh, entry->nickname, strlen(entry->nickname));
1119 if (!strchr(entry->nickname, '@')) {
1120 strncat(nh, "@", 1);
1121 if (entry->servername) {
1122 strncat(nh, entry->servername, strlen(entry->servername));
1124 len = entry->router ? strlen(entry->router->server_name) :
1125 strlen(server->server_name);
1126 strncat(nh, entry->router ? entry->router->server_name :
1127 server->server_name, len);
1131 strncat(uh, entry->username, strlen(entry->username));
1132 if (!strchr(entry->username, '@')) {
1133 strncat(uh, "@", 1);
1134 strcat(uh, "*private*");
1138 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1140 2, idp->data, idp->len,
1145 strlen(entry->userinfo) : 0);
1146 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1147 0, packet->data, packet->len, FALSE);
1149 silc_buffer_free(packet);
1150 silc_buffer_free(idp);
1153 if (found == FALSE && entry)
1154 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1155 SILC_STATUS_ERR_NO_SUCH_NICK,
1157 strlen(entry->nickname));
1161 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1163 SilcServer server = cmd->server;
1164 char *nick = NULL, *server_name = NULL;
1166 SilcClientEntry *clients = NULL;
1167 uint32 clients_count = 0;
1169 bool check_global = FALSE;
1171 /* Protocol dictates that we must always send the received WHOWAS request
1172 to our router if we are normal server, so let's do it now unless we
1173 are standalone. We will not send any replies to the client until we
1174 have received reply from the router. */
1175 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1176 server->server_type == SILC_SERVER && !cmd->pending &&
1177 !server->standalone) {
1181 old_ident = silc_command_get_ident(cmd->payload);
1182 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1183 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1185 /* Send WHOWAS command to our router */
1186 silc_server_packet_send(server, (SilcSocketConnection)
1187 server->router->connection,
1188 SILC_PACKET_COMMAND, cmd->packet->flags,
1189 tmpbuf->data, tmpbuf->len, TRUE);
1191 /* Reprocess this packet after received reply from router */
1192 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1193 silc_command_get_ident(cmd->payload),
1194 silc_server_command_whowas,
1195 silc_server_command_dup(cmd));
1196 cmd->pending = TRUE;
1197 silc_command_set_ident(cmd->payload, old_ident);
1199 silc_buffer_free(tmpbuf);
1204 /* We are ready to process the command request. Let's search for the
1205 requested client and send reply to the requesting client. */
1207 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1208 check_global = TRUE;
1209 else if (server->server_type != SILC_SERVER)
1210 check_global = TRUE;
1212 /* Parse the whowas request */
1213 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1216 /* Get all clients matching that nickname from local list */
1217 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1219 &clients, &clients_count))
1220 silc_idlist_get_clients_by_hash(server->local_list,
1221 nick, server->md5hash,
1222 &clients, &clients_count);
1224 /* Check global list as well */
1226 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1228 &clients, &clients_count))
1229 silc_idlist_get_clients_by_hash(server->global_list,
1230 nick, server->md5hash,
1231 &clients, &clients_count);
1235 /* Such a client really does not exist in the SILC network. */
1236 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1237 SILC_STATUS_ERR_NO_SUCH_NICK,
1238 3, nick, strlen(nick));
1242 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1247 /* Send the command reply to the client */
1248 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1253 silc_free(server_name);
1257 /* Server side of command WHOWAS. */
1259 SILC_SERVER_CMD_FUNC(whowas)
1261 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1264 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1266 ret = silc_server_command_whowas_process(cmd);
1267 silc_server_command_free(cmd);
1270 /******************************************************************************
1274 ******************************************************************************/
1277 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1279 SilcServer server = cmd->server;
1283 old_ident = silc_command_get_ident(cmd->payload);
1284 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1285 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1287 /* Send IDENTIFY command to our router */
1288 silc_server_packet_send(server, (SilcSocketConnection)
1289 server->router->connection,
1290 SILC_PACKET_COMMAND, cmd->packet->flags,
1291 tmpbuf->data, tmpbuf->len, TRUE);
1293 /* Reprocess this packet after received reply from router */
1294 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1295 silc_command_get_ident(cmd->payload),
1296 silc_server_command_identify,
1297 silc_server_command_dup(cmd));
1298 cmd->pending = TRUE;
1299 silc_command_set_ident(cmd->payload, old_ident);
1300 silc_buffer_free(tmpbuf);
1304 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1305 SilcClientEntry **clients,
1306 uint32 *clients_count,
1307 SilcServerEntry **servers,
1308 uint32 *servers_count,
1309 SilcChannelEntry **channels,
1310 uint32 *channels_count,
1313 SilcServer server = cmd->server;
1316 uint32 argc = silc_argument_get_arg_num(cmd->args);
1318 bool check_global = FALSE;
1323 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1324 check_global = TRUE;
1325 else if (server->server_type != SILC_SERVER)
1326 check_global = TRUE;
1328 /* If ID Payload is in the command it must be used instead of names */
1329 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1331 /* No ID, get the names. */
1333 /* If we are normal server and have not resolved information from
1334 router yet, do so now. */
1335 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1336 server->server_type == SILC_SERVER && !cmd->pending &&
1337 !server->standalone) {
1338 silc_server_command_identify_send_router(cmd);
1342 /* Try to get nickname@server. */
1343 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1346 char *nick_server = NULL;
1348 silc_parse_userfqdn(tmp, &nick, &nick_server);
1350 if (!silc_idlist_get_clients_by_hash(server->local_list,
1351 nick, server->md5hash,
1352 clients, clients_count))
1353 silc_idlist_get_clients_by_nickname(server->local_list,
1355 clients, clients_count);
1357 if (!silc_idlist_get_clients_by_hash(server->global_list,
1358 nick, server->md5hash,
1359 clients, clients_count))
1360 silc_idlist_get_clients_by_nickname(server->global_list,
1362 clients, clients_count);
1366 silc_free(nick_server);
1369 /* the nickname does not exist, send error reply */
1370 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1371 SILC_STATUS_ERR_NO_SUCH_NICK,
1372 3, tmp, strlen(tmp));
1377 /* Try to get server name */
1378 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1380 entry = silc_idlist_find_server_by_name(server->local_list,
1382 if (!entry && check_global)
1383 entry = silc_idlist_find_server_by_name(server->global_list,
1386 *servers = silc_realloc(*servers, sizeof(**servers) *
1387 (*servers_count + 1));
1388 (*servers)[(*servers_count)++] = entry;
1392 /* the server does not exist, send error reply */
1393 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1394 SILC_STATUS_ERR_NO_SUCH_SERVER,
1395 3, tmp, strlen(tmp));
1400 /* Try to get channel name */
1401 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1403 entry = silc_idlist_find_channel_by_name(server->local_list,
1405 if (!entry && check_global)
1406 entry = silc_idlist_find_channel_by_name(server->global_list,
1409 *channels = silc_realloc(*channels, sizeof(**channels) *
1410 (*channels_count + 1));
1411 (*channels)[(*channels_count)++] = entry;
1415 /* The channel does not exist, send error reply */
1416 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1417 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1418 3, tmp, strlen(tmp));
1423 if (!(*clients) && !(*servers) && !(*channels)) {
1424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1425 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1429 /* Command includes ID, we must use that. Also check whether the command
1430 has more than one ID set - take them all. */
1432 /* Take all ID's from the command packet */
1433 for (i = 0; i < argc; i++) {
1436 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1440 idp = silc_id_payload_parse(tmp, len);
1442 silc_free(*clients);
1443 silc_free(*servers);
1444 silc_free(*channels);
1445 silc_server_command_send_status_reply(
1446 cmd, SILC_COMMAND_IDENTIFY,
1447 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1451 id = silc_id_payload_get_id(idp);
1453 switch (silc_id_payload_get_type(idp)) {
1455 case SILC_ID_CLIENT:
1456 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1458 if (!entry && check_global)
1459 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1462 *clients = silc_realloc(*clients, sizeof(**clients) *
1463 (*clients_count + 1));
1464 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1466 /* If we are normal server and have not resolved information from
1467 router yet, do so now. */
1468 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1469 server->server_type == SILC_SERVER && !cmd->pending &&
1470 !server->standalone) {
1471 silc_server_command_identify_send_router(cmd);
1472 silc_free(*clients);
1473 silc_free(*servers);
1474 silc_free(*channels);
1477 silc_server_command_send_status_data(
1478 cmd, SILC_COMMAND_IDENTIFY,
1479 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1487 case SILC_ID_SERVER:
1488 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1490 if (!entry && check_global)
1491 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1494 *servers = silc_realloc(*servers, sizeof(**servers) *
1495 (*servers_count + 1));
1496 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1498 /* If we are normal server and have not resolved information from
1499 router yet, do so now. */
1500 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1501 server->server_type == SILC_SERVER && !cmd->pending &&
1502 !server->standalone) {
1503 silc_server_command_identify_send_router(cmd);
1504 silc_free(*clients);
1505 silc_free(*servers);
1506 silc_free(*channels);
1509 silc_server_command_send_status_data(
1510 cmd, SILC_COMMAND_IDENTIFY,
1511 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1518 case SILC_ID_CHANNEL:
1519 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1521 if (!entry && check_global)
1522 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1525 *channels = silc_realloc(*channels, sizeof(**channels) *
1526 (*channels_count + 1));
1527 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1529 /* If we are normal server and have not resolved information from
1530 router yet, do so now. */
1531 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1532 server->server_type == SILC_SERVER && !cmd->pending &&
1533 !server->standalone) {
1534 silc_server_command_identify_send_router(cmd);
1535 silc_free(*clients);
1536 silc_free(*servers);
1537 silc_free(*channels);
1540 silc_server_command_send_status_data(
1541 cmd, SILC_COMMAND_IDENTIFY,
1542 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1555 silc_free(*clients);
1556 silc_free(*servers);
1557 silc_free(*channels);
1561 /* Get the max count of reply messages allowed */
1562 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1571 /* Checks that all mandatory fields in client entry are present. If not
1572 then send WHOIS request to the server who owns the client. We use
1573 WHOIS because we want to get as much information as possible at once. */
1576 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1577 SilcClientEntry *clients,
1578 uint32 clients_count)
1580 SilcServer server = cmd->server;
1581 SilcClientEntry entry;
1582 SilcServerResolveContext resolve = NULL, r = NULL;
1583 uint32 resolve_count = 0;
1587 for (i = 0; i < clients_count; i++) {
1592 if (entry->nickname ||
1593 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1597 /* If we are normal server, and we've not resolved this client from
1598 router and it is global client, we'll check whether it is on some
1599 channel. If not then we cannot be sure about its validity, and
1600 we'll resolve it from router. */
1601 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1602 entry->connection || silc_hash_table_count(entry->channels))
1606 /* We need to resolve this entry since it is not complete */
1608 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1609 /* The entry is being resolved (and we are not the resolver) so attach
1610 to the command reply and we're done with this one. */
1611 silc_server_command_pending(server, SILC_COMMAND_NONE,
1612 entry->resolve_cmd_ident,
1613 silc_server_command_identify,
1614 silc_server_command_dup(cmd));
1617 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1618 /* We've resolved this and it still is not ready. We'll return
1619 and are that this will be handled again after it is resolved. */
1620 for (i = 0; i < resolve_count; i++) {
1621 for (k = 0; k < r->res_argc; k++)
1622 silc_free(r->res_argv[k]);
1623 silc_free(r->res_argv);
1624 silc_free(r->res_argv_lens);
1625 silc_free(r->res_argv_types);
1630 /* We'll resolve this client */
1634 for (k = 0; k < resolve_count; k++) {
1635 if (resolve[k].router == entry->router) {
1642 resolve = silc_realloc(resolve, sizeof(*resolve) *
1643 (resolve_count + 1));
1644 r = &resolve[resolve_count];
1645 memset(r, 0, sizeof(*r));
1646 r->router = entry->router;
1647 r->ident = ++server->cmd_ident;
1651 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1653 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1654 sizeof(*r->res_argv_lens) *
1656 r->res_argv_types = silc_realloc(r->res_argv_types,
1657 sizeof(*r->res_argv_types) *
1659 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1660 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1661 sizeof(**r->res_argv));
1662 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1663 r->res_argv_lens[r->res_argc] = idp->len;
1664 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1666 silc_buffer_free(idp);
1668 entry->resolve_cmd_ident = r->ident;
1669 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1670 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1675 /* Do the resolving */
1676 for (i = 0; i < resolve_count; i++) {
1681 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1682 now anyway so make it a good one. */
1683 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1684 r->res_argc, r->res_argv,
1688 silc_server_packet_send(server, r->router->connection,
1689 SILC_PACKET_COMMAND, cmd->packet->flags,
1690 res_cmd->data, res_cmd->len, FALSE);
1692 /* Reprocess this packet after received reply */
1693 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1695 silc_server_command_identify,
1696 silc_server_command_dup(cmd));
1697 cmd->pending = TRUE;
1699 silc_buffer_free(res_cmd);
1700 for (k = 0; k < r->res_argc; k++)
1701 silc_free(r->res_argv[k]);
1702 silc_free(r->res_argv);
1703 silc_free(r->res_argv_lens);
1704 silc_free(r->res_argv_types);
1713 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1714 SilcClientEntry *clients,
1715 uint32 clients_count,
1716 SilcServerEntry *servers,
1717 uint32 servers_count,
1718 SilcChannelEntry *channels,
1719 uint32 channels_count,
1722 SilcServer server = cmd->server;
1723 int i, k, len, valid_count;
1724 SilcBuffer packet, idp;
1725 SilcCommandStatus status;
1726 uint16 ident = silc_command_get_ident(cmd->payload);
1727 char nh[256], uh[256];
1728 SilcSocketConnection hsock;
1730 status = SILC_STATUS_OK;
1733 SilcClientEntry entry;
1735 /* Process only valid entries. */
1737 for (i = 0; i < clients_count; i++) {
1738 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1745 /* No valid entries found at all, just send error */
1748 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1750 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1751 SILC_STATUS_ERR_NO_SUCH_NICK,
1752 3, tmp, strlen(tmp));
1754 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1755 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1756 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1762 /* Process all valid client entries and send command replies */
1764 if (valid_count > 1)
1765 status = SILC_STATUS_LIST_START;
1767 for (i = 0, k = 0; i < clients_count; i++) {
1773 status = SILC_STATUS_LIST_ITEM;
1774 if (valid_count > 1 && k == valid_count - 1
1775 && !servers_count && !channels_count)
1776 status = SILC_STATUS_LIST_END;
1777 if (count && k - 1 == count)
1778 status = SILC_STATUS_LIST_END;
1779 if (count && k - 1 > count)
1782 /* Send IDENTIFY reply */
1784 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1785 memset(uh, 0, sizeof(uh));
1786 memset(nh, 0, sizeof(nh));
1787 strncat(nh, entry->nickname, strlen(entry->nickname));
1788 if (!strchr(entry->nickname, '@')) {
1789 strncat(nh, "@", 1);
1790 if (entry->servername) {
1791 strncat(nh, entry->servername, strlen(entry->servername));
1793 len = entry->router ? strlen(entry->router->server_name) :
1794 strlen(server->server_name);
1795 strncat(nh, entry->router ? entry->router->server_name :
1796 server->server_name, len);
1800 if (!entry->username) {
1801 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1803 2, idp->data, idp->len,
1806 strncat(uh, entry->username, strlen(entry->username));
1807 if (!strchr(entry->username, '@')) {
1808 strncat(uh, "@", 1);
1809 hsock = (SilcSocketConnection)entry->connection;
1810 len = strlen(hsock->hostname);
1811 strncat(uh, hsock->hostname, len);
1814 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1816 2, idp->data, idp->len,
1821 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1822 0, packet->data, packet->len, FALSE);
1824 silc_buffer_free(packet);
1825 silc_buffer_free(idp);
1832 SilcServerEntry entry;
1834 if (status == SILC_STATUS_OK && servers_count > 1)
1835 status = SILC_STATUS_LIST_START;
1837 for (i = 0, k = 0; i < servers_count; i++) {
1841 status = SILC_STATUS_LIST_ITEM;
1842 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1843 status = SILC_STATUS_LIST_END;
1844 if (count && k - 1 == count)
1845 status = SILC_STATUS_LIST_END;
1846 if (count && k - 1 > count)
1849 /* Send IDENTIFY reply */
1850 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1852 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1854 2, idp->data, idp->len,
1855 3, entry->server_name,
1856 entry->server_name ?
1857 strlen(entry->server_name) : 0);
1858 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1859 0, packet->data, packet->len, FALSE);
1861 silc_buffer_free(packet);
1862 silc_buffer_free(idp);
1869 SilcChannelEntry entry;
1871 if (status == SILC_STATUS_OK && channels_count > 1)
1872 status = SILC_STATUS_LIST_START;
1874 for (i = 0, k = 0; i < channels_count; i++) {
1875 entry = channels[i];
1878 status = SILC_STATUS_LIST_ITEM;
1879 if (channels_count > 1 && k == channels_count - 1)
1880 status = SILC_STATUS_LIST_END;
1881 if (count && k - 1 == count)
1882 status = SILC_STATUS_LIST_END;
1883 if (count && k - 1 > count)
1886 /* Send IDENTIFY reply */
1887 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1889 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1891 2, idp->data, idp->len,
1892 3, entry->channel_name,
1893 entry->channel_name ?
1894 strlen(entry->channel_name): 0);
1895 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1896 0, packet->data, packet->len, FALSE);
1898 silc_buffer_free(packet);
1899 silc_buffer_free(idp);
1907 silc_server_command_identify_process(SilcServerCommandContext cmd)
1911 SilcClientEntry *clients = NULL;
1912 SilcServerEntry *servers = NULL;
1913 SilcChannelEntry *channels = NULL;
1914 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1916 /* Parse the IDENTIFY request */
1917 ret = silc_server_command_identify_parse(cmd,
1918 &clients, &clients_count,
1919 &servers, &servers_count,
1920 &channels, &channels_count,
1926 /* Check that all mandatory fields are present and request those data
1927 from the server who owns the client if necessary. */
1928 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1934 /* Send the command reply to the client */
1935 silc_server_command_identify_send_reply(cmd,
1936 clients, clients_count,
1937 servers, servers_count,
1938 channels, channels_count,
1944 silc_free(channels);
1948 SILC_SERVER_CMD_FUNC(identify)
1950 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1953 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1955 ret = silc_server_command_identify_process(cmd);
1956 silc_server_command_free(cmd);
1959 /* Server side of command NICK. Sets nickname for user. Setting
1960 nickname causes generation of a new client ID for the client. The
1961 new client ID is sent to the client after changing the nickname. */
1963 SILC_SERVER_CMD_FUNC(nick)
1965 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1966 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1967 SilcServer server = cmd->server;
1968 SilcBuffer packet, nidp, oidp = NULL;
1969 SilcClientID *new_id;
1972 uint16 ident = silc_command_get_ident(cmd->payload);
1975 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1978 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1980 /* Check nickname */
1981 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
1984 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
1985 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1986 SILC_STATUS_ERR_BAD_NICKNAME);
1990 /* Check for same nickname */
1991 if (!strcmp(client->nickname, nick)) {
1992 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1996 /* Create new Client ID */
1997 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1999 cmd->server->md5hash, nick,
2002 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2005 /* Send notify about nickname change to our router. We send the new
2006 ID and ask to replace it with the old one. If we are router the
2007 packet is broadcasted. Send NICK_CHANGE notify. */
2008 if (!server->standalone)
2009 silc_server_send_notify_nick_change(server, server->router->connection,
2010 server->server_type == SILC_SERVER ?
2011 FALSE : TRUE, client->id,
2014 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2016 /* Remove old cache entry */
2017 silc_idcache_del_by_context(server->local_list->clients, client);
2020 silc_free(client->id);
2022 /* Save the nickname as this client is our local client */
2023 silc_free(client->nickname);
2025 client->nickname = strdup(nick);
2026 client->id = new_id;
2028 /* Update client cache */
2029 silc_idcache_add(server->local_list->clients, client->nickname,
2030 client->id, (void *)client, 0, NULL);
2032 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2034 /* Send NICK_CHANGE notify to the client's channels */
2035 silc_server_send_notify_on_channels(server, NULL, client,
2036 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2037 oidp->data, oidp->len,
2038 nidp->data, nidp->len);
2041 /* Send the new Client ID as reply command back to client */
2042 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2043 SILC_STATUS_OK, ident, 1,
2044 2, nidp->data, nidp->len);
2045 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2046 0, packet->data, packet->len, FALSE);
2048 silc_buffer_free(packet);
2049 silc_buffer_free(nidp);
2051 silc_buffer_free(oidp);
2054 silc_server_command_free(cmd);
2057 /* Sends the LIST command reply */
2060 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2061 SilcChannelEntry *lch,
2063 SilcChannelEntry *gch,
2067 SilcBuffer packet, idp;
2068 SilcChannelEntry entry;
2069 SilcCommandStatus status;
2070 uint16 ident = silc_command_get_ident(cmd->payload);
2072 unsigned char usercount[4];
2074 int valid_lcount = 0, valid_rcount = 0;
2076 for (i = 0; i < lch_count; i++) {
2077 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2082 for (i = 0; i < gch_count; i++) {
2083 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2089 status = SILC_STATUS_OK;
2090 if ((lch_count + gch_count) > 1)
2091 status = SILC_STATUS_LIST_START;
2094 for (i = 0, k = 0; i < lch_count; i++) {
2100 status = SILC_STATUS_LIST_ITEM;
2101 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2102 status = SILC_STATUS_LIST_END;
2104 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2106 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2107 topic = "*private*";
2108 memset(usercount, 0, sizeof(usercount));
2110 topic = entry->topic;
2111 users = silc_hash_table_count(entry->user_list);
2112 SILC_PUT32_MSB(users, usercount);
2115 /* Send the reply */
2117 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2119 2, idp->data, idp->len,
2120 3, entry->channel_name,
2121 strlen(entry->channel_name),
2122 4, topic, topic ? strlen(topic) : 0,
2124 silc_server_packet_send(cmd->server, cmd->sock,
2125 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2126 packet->len, FALSE);
2127 silc_buffer_free(packet);
2128 silc_buffer_free(idp);
2133 for (i = 0, k = 0; i < gch_count; i++) {
2139 status = SILC_STATUS_LIST_ITEM;
2140 if (valid_rcount > 1 && k == valid_rcount - 1)
2141 status = SILC_STATUS_LIST_END;
2143 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2145 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2146 topic = "*private*";
2147 memset(usercount, 0, sizeof(usercount));
2149 topic = entry->topic;
2150 users = silc_hash_table_count(entry->user_list);
2151 SILC_PUT32_MSB(users, usercount);
2154 /* Send the reply */
2156 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2158 2, idp->data, idp->len,
2159 3, entry->channel_name,
2160 strlen(entry->channel_name),
2161 4, topic, topic ? strlen(topic) : 0,
2163 silc_server_packet_send(cmd->server, cmd->sock,
2164 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2165 packet->len, FALSE);
2166 silc_buffer_free(packet);
2167 silc_buffer_free(idp);
2172 /* Server side of LIST command. This lists the channel of the requested
2173 server. Secret channels are not listed. */
2175 SILC_SERVER_CMD_FUNC(list)
2177 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2178 SilcServer server = cmd->server;
2179 SilcChannelID *channel_id = NULL;
2182 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2183 uint32 lch_count = 0, gch_count = 0;
2185 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2187 /* If we are normal server, send the command to router, since we
2188 want to know all channels in the network. */
2189 if (!cmd->pending && server->server_type == SILC_SERVER &&
2190 !server->standalone) {
2194 old_ident = silc_command_get_ident(cmd->payload);
2195 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2196 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2197 silc_server_packet_send(server, server->router->connection,
2198 SILC_PACKET_COMMAND, cmd->packet->flags,
2199 tmpbuf->data, tmpbuf->len, TRUE);
2201 /* Reprocess this packet after received reply from router */
2202 silc_server_command_pending(server, SILC_COMMAND_LIST,
2203 silc_command_get_ident(cmd->payload),
2204 silc_server_command_list,
2205 silc_server_command_dup(cmd));
2206 cmd->pending = TRUE;
2207 silc_command_set_ident(cmd->payload, old_ident);
2208 silc_buffer_free(tmpbuf);
2212 /* Get Channel ID */
2213 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2215 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2218 SILC_STATUS_ERR_NO_CHANNEL_ID);
2223 /* Get the channels from local list */
2224 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2227 /* Get the channels from global list */
2228 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2231 /* Send the reply */
2232 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2233 gchannels, gch_count);
2235 silc_free(lchannels);
2236 silc_free(gchannels);
2239 silc_server_command_free(cmd);
2242 /* Server side of TOPIC command. Sets topic for channel and/or returns
2243 current topic to client. */
2245 SILC_SERVER_CMD_FUNC(topic)
2247 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2248 SilcServer server = cmd->server;
2249 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2250 SilcChannelID *channel_id;
2251 SilcChannelEntry channel;
2252 SilcChannelClientEntry chl;
2253 SilcBuffer packet, idp;
2255 uint32 argc, tmp_len;
2256 uint16 ident = silc_command_get_ident(cmd->payload);
2258 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2260 argc = silc_argument_get_arg_num(cmd->args);
2262 /* Get Channel ID */
2263 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2266 SILC_STATUS_ERR_NO_CHANNEL_ID);
2269 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2272 SILC_STATUS_ERR_NO_CHANNEL_ID);
2276 /* Check whether the channel exists */
2277 channel = silc_idlist_find_channel_by_id(server->local_list,
2280 channel = silc_idlist_find_channel_by_id(server->global_list,
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2284 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2291 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2294 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2298 if (strlen(tmp) > 256) {
2299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2300 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2304 /* See whether the client is on channel and has rights to change topic */
2305 if (!silc_hash_table_find(channel->user_list, client, NULL,
2307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2308 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2312 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2313 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2315 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2320 /* Set the topic for channel */
2321 silc_free(channel->topic);
2322 channel->topic = strdup(tmp);
2324 /* Send TOPIC_SET notify type to the network */
2325 if (!server->standalone)
2326 silc_server_send_notify_topic_set(server, server->router->connection,
2327 server->server_type == SILC_ROUTER ?
2328 TRUE : FALSE, channel,
2329 client->id, SILC_ID_CLIENT,
2332 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2334 /* Send notify about topic change to all clients on the channel */
2335 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2336 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2337 idp->data, idp->len,
2338 channel->topic, strlen(channel->topic));
2339 silc_buffer_free(idp);
2342 /* Send the topic to client as reply packet */
2343 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2344 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2345 SILC_STATUS_OK, ident, 2,
2346 2, idp->data, idp->len,
2349 strlen(channel->topic) : 0);
2350 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2351 0, packet->data, packet->len, FALSE);
2353 silc_buffer_free(packet);
2354 silc_buffer_free(idp);
2355 silc_free(channel_id);
2358 silc_server_command_free(cmd);
2361 /* Server side of INVITE command. Invites some client to join some channel.
2362 This command is also used to manage the invite list of the channel. */
2364 SILC_SERVER_CMD_FUNC(invite)
2366 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2367 SilcServer server = cmd->server;
2368 SilcSocketConnection sock = cmd->sock, dest_sock;
2369 SilcChannelClientEntry chl;
2370 SilcClientEntry sender, dest;
2371 SilcClientID *dest_id = NULL;
2372 SilcChannelEntry channel;
2373 SilcChannelID *channel_id = NULL;
2374 SilcIDListData idata;
2375 SilcBuffer idp, idp2, packet;
2376 unsigned char *tmp, *add, *del;
2378 uint16 ident = silc_command_get_ident(cmd->payload);
2380 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2382 /* Get Channel ID */
2383 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2386 SILC_STATUS_ERR_NO_CHANNEL_ID);
2389 channel_id = silc_id_payload_parse_id(tmp, len);
2391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2392 SILC_STATUS_ERR_NO_CHANNEL_ID);
2396 /* Get the channel entry */
2397 channel = silc_idlist_find_channel_by_id(server->local_list,
2400 channel = silc_idlist_find_channel_by_id(server->global_list,
2403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2404 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2409 /* Check whether the sender of this command is on the channel. */
2410 sender = (SilcClientEntry)sock->user_data;
2411 if (!silc_server_client_on_channel(sender, channel)) {
2412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2413 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2417 /* Check whether the channel is invite-only channel. If yes then the
2418 sender of this command must be at least channel operator. */
2419 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2420 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2421 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2423 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2428 /* Get destination client ID */
2429 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2434 dest_id = silc_id_payload_parse_id(tmp, len);
2436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2437 SILC_STATUS_ERR_NO_CLIENT_ID);
2441 /* Get the client entry */
2442 dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2444 if (server->server_type != SILC_SERVER || !resolve) {
2445 silc_server_command_send_status_reply(
2446 cmd, SILC_COMMAND_INVITE,
2447 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2451 /* The client info is being resolved. Reprocess this packet after
2452 receiving the reply to the query. */
2453 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2455 silc_server_command_invite,
2456 silc_server_command_dup(cmd));
2457 cmd->pending = TRUE;
2458 silc_free(channel_id);
2463 /* Check whether the requested client is already on the channel. */
2464 if (silc_server_client_on_channel(dest, channel)) {
2465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2466 SILC_STATUS_ERR_USER_ON_CHANNEL);
2470 /* Get route to the client */
2471 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2474 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2478 memset(invite, 0, sizeof(invite));
2479 strncat(invite, dest->nickname, strlen(dest->nickname));
2480 strncat(invite, "!", 1);
2481 strncat(invite, dest->username, strlen(dest->username));
2482 if (!strchr(dest->username, '@')) {
2483 strncat(invite, "@", 1);
2484 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2487 len = strlen(invite);
2488 if (!channel->invite_list)
2489 channel->invite_list = silc_calloc(len + 2,
2490 sizeof(*channel->invite_list));
2492 channel->invite_list = silc_realloc(channel->invite_list,
2493 sizeof(*channel->invite_list) *
2495 strlen(channel->invite_list) + 2));
2496 strncat(channel->invite_list, invite, len);
2497 strncat(channel->invite_list, ",", 1);
2499 /* Send notify to the client that is invited to the channel */
2500 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2501 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2502 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2504 SILC_NOTIFY_TYPE_INVITE, 3,
2505 idp->data, idp->len,
2506 channel->channel_name,
2507 strlen(channel->channel_name),
2508 idp2->data, idp2->len);
2509 silc_buffer_free(idp);
2510 silc_buffer_free(idp2);
2513 /* Add the client to the invite list of the channel */
2514 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2516 if (!channel->invite_list)
2517 channel->invite_list = silc_calloc(len + 2,
2518 sizeof(*channel->invite_list));
2520 channel->invite_list = silc_realloc(channel->invite_list,
2521 sizeof(*channel->invite_list) *
2523 strlen(channel->invite_list) + 2));
2524 if (add[len - 1] == ',')
2525 add[len - 1] = '\0';
2527 strncat(channel->invite_list, add, len);
2528 strncat(channel->invite_list, ",", 1);
2531 /* Get the invite to be removed and remove it from the list */
2532 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2533 if (del && channel->invite_list) {
2534 char *start, *end, *n;
2536 if (!strncmp(channel->invite_list, del,
2537 strlen(channel->invite_list) - 1)) {
2538 silc_free(channel->invite_list);
2539 channel->invite_list = NULL;
2541 start = strstr(channel->invite_list, del);
2542 if (start && strlen(start) >= len) {
2544 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2545 strncat(n, channel->invite_list, start - channel->invite_list);
2546 strncat(n, end + 1, ((channel->invite_list +
2547 strlen(channel->invite_list)) - end) - 1);
2548 silc_free(channel->invite_list);
2549 channel->invite_list = n;
2554 /* Send notify to the primary router */
2555 if (!server->standalone)
2556 silc_server_send_notify_invite(server, server->router->connection,
2557 server->server_type == SILC_ROUTER ?
2558 TRUE : FALSE, channel,
2559 sender->id, add, del);
2561 /* Send command reply */
2562 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2566 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2567 SILC_STATUS_OK, ident, 2,
2569 3, channel->invite_list,
2570 channel->invite_list ?
2571 strlen(channel->invite_list) : 0);
2574 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2575 SILC_STATUS_OK, ident, 1,
2577 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2578 packet->data, packet->len, FALSE);
2579 silc_buffer_free(packet);
2583 silc_free(channel_id);
2584 silc_server_command_free(cmd);
2589 SilcSocketConnection sock;
2593 /* Quits connection to client. This gets called if client won't
2594 close the connection even when it has issued QUIT command. */
2596 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2598 QuitInternal q = (QuitInternal)context;
2600 /* Free all client specific data, such as client entry and entires
2601 on channels this client may be on. */
2602 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2604 q->sock->user_data = NULL;
2606 /* Close the connection on our side */
2607 silc_server_close_connection(q->server, q->sock);
2609 silc_free(q->signoff);
2613 /* Quits SILC session. This is the normal way to disconnect client. */
2615 SILC_SERVER_CMD_FUNC(quit)
2617 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2618 SilcServer server = cmd->server;
2619 SilcSocketConnection sock = cmd->sock;
2621 unsigned char *tmp = NULL;
2624 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2626 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2629 /* Get destination ID */
2630 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2634 q = silc_calloc(1, sizeof(*q));
2637 q->signoff = tmp ? strdup(tmp) : NULL;
2639 /* We quit the connection with little timeout */
2640 silc_schedule_task_add(server->schedule, sock->sock,
2641 silc_server_command_quit_cb, (void *)q,
2642 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2645 silc_server_command_free(cmd);
2648 /* Server side of command KILL. This command is used by router operator
2649 to remove an client from the SILC Network temporarily. */
2651 SILC_SERVER_CMD_FUNC(kill)
2653 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2654 SilcServer server = cmd->server;
2655 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2656 SilcClientEntry remote_client;
2657 SilcClientID *client_id;
2658 unsigned char *tmp, *comment;
2659 uint32 tmp_len, tmp_len2;
2662 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2664 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2667 /* KILL command works only on router */
2668 if (server->server_type != SILC_ROUTER) {
2669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2670 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2674 /* Check whether client has the permissions. */
2675 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2677 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2681 /* Get the client ID */
2682 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2685 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2688 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2691 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2695 /* Get the client entry */
2696 remote_client = silc_idlist_find_client_by_id(server->local_list,
2697 client_id, TRUE, NULL);
2699 if (!remote_client) {
2700 remote_client = silc_idlist_find_client_by_id(server->global_list,
2701 client_id, TRUE, NULL);
2703 if (!remote_client) {
2704 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2705 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2711 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2715 /* Send reply to the sender */
2716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2719 /* Send the KILL notify packets. First send it to the channel, then
2720 to our primary router and then directly to the client who is being
2721 killed right now. */
2723 /* Send KILLED notify to the channels. It is not sent to the client
2724 as it will be sent differently destined directly to the client and not
2726 silc_server_send_notify_on_channels(server, remote_client,
2727 remote_client, SILC_NOTIFY_TYPE_KILLED,
2730 comment, comment ? tmp_len2 : 0);
2732 /* Send KILLED notify to primary route */
2733 if (!server->standalone)
2734 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2735 remote_client->id, comment);
2737 /* Send KILLED notify to the client directly */
2738 silc_server_send_notify_killed(server, remote_client->connection ?
2739 remote_client->connection :
2740 remote_client->router->connection, FALSE,
2741 remote_client->id, comment);
2743 /* Remove the client from all channels. This generates new keys to the
2744 channels as well. */
2745 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2748 /* Remove the client entry, If it is locally connected then we will also
2749 disconnect the client here */
2750 if (remote_client->connection) {
2751 /* Remove locally conneted client */
2752 SilcSocketConnection sock = remote_client->connection;
2753 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2754 silc_server_close_connection(server, sock);
2756 /* Update statistics */
2757 if (remote_client->connection)
2758 server->stat.my_clients--;
2759 if (server->server_type == SILC_ROUTER)
2760 server->stat.cell_clients--;
2761 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2762 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2764 /* Remove remote client */
2765 silc_idlist_del_client(local ? server->local_list :
2766 server->global_list, remote_client);
2770 silc_server_command_free(cmd);
2773 /* Server side of command INFO. This sends information about us to
2774 the client. If client requested specific server we will send the
2775 command to that server. */
2777 SILC_SERVER_CMD_FUNC(info)
2779 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2780 SilcServer server = cmd->server;
2781 SilcBuffer packet, idp;
2784 char *dest_server, *server_info = NULL, *server_name;
2785 uint16 ident = silc_command_get_ident(cmd->payload);
2786 SilcServerEntry entry = NULL;
2787 SilcServerID *server_id = NULL;
2789 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2791 /* Get server name */
2792 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2795 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2797 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2800 SILC_STATUS_ERR_NO_SERVER_ID);
2806 /* Check whether we have this server cached */
2807 entry = silc_idlist_find_server_by_id(server->local_list,
2808 server_id, TRUE, NULL);
2810 entry = silc_idlist_find_server_by_id(server->global_list,
2811 server_id, TRUE, NULL);
2812 if (!entry && server->server_type != SILC_SERVER) {
2813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2814 SILC_STATUS_ERR_NO_SUCH_SERVER);
2820 /* Some buggy servers has sent request to router about themselves. */
2821 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2824 if ((!dest_server && !server_id && !entry) || (entry &&
2825 entry == server->id_entry) ||
2826 (dest_server && !cmd->pending &&
2827 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2828 /* Send our reply */
2829 char info_string[256];
2831 memset(info_string, 0, sizeof(info_string));
2832 snprintf(info_string, sizeof(info_string),
2833 "location: %s server: %s admin: %s <%s>",
2834 server->config->admin_info->location,
2835 server->config->admin_info->server_type,
2836 server->config->admin_info->admin_name,
2837 server->config->admin_info->admin_email);
2839 server_info = info_string;
2840 entry = server->id_entry;
2842 /* Check whether we have this server cached */
2843 if (!entry && dest_server) {
2844 entry = silc_idlist_find_server_by_name(server->global_list,
2845 dest_server, TRUE, NULL);
2847 entry = silc_idlist_find_server_by_name(server->local_list,
2848 dest_server, TRUE, NULL);
2852 if (!cmd->pending &&
2853 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2854 /* Send to the server */
2858 old_ident = silc_command_get_ident(cmd->payload);
2859 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2860 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2862 silc_server_packet_send(server, entry->connection,
2863 SILC_PACKET_COMMAND, cmd->packet->flags,
2864 tmpbuf->data, tmpbuf->len, TRUE);
2866 /* Reprocess this packet after received reply from router */
2867 silc_server_command_pending(server, SILC_COMMAND_INFO,
2868 silc_command_get_ident(cmd->payload),
2869 silc_server_command_info,
2870 silc_server_command_dup(cmd));
2871 cmd->pending = TRUE;
2872 silc_command_set_ident(cmd->payload, old_ident);
2873 silc_buffer_free(tmpbuf);
2877 if (!entry && !cmd->pending && !server->standalone) {
2878 /* Send to the primary router */
2882 old_ident = silc_command_get_ident(cmd->payload);
2883 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2884 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2886 silc_server_packet_send(server, server->router->connection,
2887 SILC_PACKET_COMMAND, cmd->packet->flags,
2888 tmpbuf->data, tmpbuf->len, TRUE);
2890 /* Reprocess this packet after received reply from router */
2891 silc_server_command_pending(server, SILC_COMMAND_INFO,
2892 silc_command_get_ident(cmd->payload),
2893 silc_server_command_info,
2894 silc_server_command_dup(cmd));
2895 cmd->pending = TRUE;
2896 silc_command_set_ident(cmd->payload, old_ident);
2897 silc_buffer_free(tmpbuf);
2902 silc_free(server_id);
2905 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2906 SILC_STATUS_ERR_NO_SUCH_SERVER);
2910 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2912 server_info = entry->server_info;
2913 server_name = entry->server_name;
2915 /* Send the reply */
2916 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2917 SILC_STATUS_OK, ident, 3,
2918 2, idp->data, idp->len,
2920 strlen(server_name),
2923 strlen(server_info) : 0);
2924 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2925 packet->data, packet->len, FALSE);
2927 silc_buffer_free(packet);
2928 silc_buffer_free(idp);
2931 silc_server_command_free(cmd);
2934 /* Server side of command PING. This just replies to the ping. */
2936 SILC_SERVER_CMD_FUNC(ping)
2938 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2939 SilcServer server = cmd->server;
2944 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2947 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2950 SILC_STATUS_ERR_NO_SERVER_ID);
2953 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2957 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2958 /* Send our reply */
2959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2963 SILC_STATUS_ERR_NO_SUCH_SERVER);
2970 silc_server_command_free(cmd);
2973 /* Internal routine to join channel. The channel sent to this function
2974 has been either created or resolved from ID lists. This joins the sent
2975 client to the channel. */
2977 static void silc_server_command_join_channel(SilcServer server,
2978 SilcServerCommandContext cmd,
2979 SilcChannelEntry channel,
2980 SilcClientID *client_id,
2984 const unsigned char *auth,
2987 SilcSocketConnection sock = cmd->sock;
2989 uint32 tmp_len, user_count;
2990 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2991 SilcClientEntry client;
2992 SilcChannelClientEntry chl;
2993 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2994 uint16 ident = silc_command_get_ident(cmd->payload);
2995 char check[512], check2[512];
2996 bool founder = FALSE;
2999 SILC_LOG_DEBUG(("Start"));
3004 /* Get the client entry */
3005 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3006 client = (SilcClientEntry)sock->user_data;
3008 client = silc_server_get_client_resolve(server, client_id, &resolve);
3014 silc_server_command_send_status_reply(
3015 cmd, SILC_COMMAND_JOIN,
3016 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3020 /* The client info is being resolved. Reprocess this packet after
3021 receiving the reply to the query. */
3022 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3024 silc_server_command_join,
3025 silc_server_command_dup(cmd));
3026 cmd->pending = TRUE;
3030 cmd->pending = FALSE;
3034 * Check founder auth payload if provided. If client can gain founder
3035 * privileges it can override various conditions on joining the channel,
3036 * and can have directly the founder mode set on the channel.
3038 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3039 SilcIDListData idata = (SilcIDListData)client;
3041 if (channel->founder_key && idata->public_key &&
3042 silc_pkcs_public_key_compare(channel->founder_key,
3043 idata->public_key)) {
3044 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3045 (void *)channel->founder_passwd :
3046 (void *)channel->founder_key);
3047 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3048 channel->founder_passwd_len : 0);
3050 /* Check whether the client is to become founder */
3051 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3052 auth_data, auth_data_len,
3053 idata->hash, client->id, SILC_ID_CLIENT)) {
3054 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3061 * Check channel modes
3065 memset(check, 0, sizeof(check));
3066 memset(check2, 0, sizeof(check2));
3067 strncat(check, client->nickname, strlen(client->nickname));
3068 strncat(check, "!", 1);
3069 strncat(check, client->username, strlen(client->username));
3070 if (!strchr(client->username, '@')) {
3071 strncat(check, "@", 1);
3072 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3075 strncat(check2, client->nickname, strlen(client->nickname));
3076 if (!strchr(client->nickname, '@')) {
3077 strncat(check2, "@", 1);
3078 strncat(check2, server->server_name, strlen(server->server_name));
3080 strncat(check2, "!", 1);
3081 strncat(check2, client->username, strlen(client->username));
3082 if (!strchr(client->username, '@')) {
3083 strncat(check2, "@", 1);
3084 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3087 /* Check invite list if channel is invite-only channel */
3088 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3089 if (!channel->invite_list ||
3090 (!silc_string_match(channel->invite_list, check) &&
3091 !silc_string_match(channel->invite_list, check2))) {
3092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3093 SILC_STATUS_ERR_NOT_INVITED);
3098 /* Check ban list if it exists. If the client's nickname, server,
3099 username and/or hostname is in the ban list the access to the
3100 channel is denied. */
3101 if (channel->ban_list) {
3102 if (silc_string_match(channel->ban_list, check) ||
3103 silc_string_match(channel->ban_list, check2)) {
3104 silc_server_command_send_status_reply(
3105 cmd, SILC_COMMAND_JOIN,
3106 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3111 /* Check user count limit if set. */
3112 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3113 if (silc_hash_table_count(channel->user_list) + 1 >
3114 channel->user_limit) {
3115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3116 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3122 /* Check the channel passphrase if set. */
3123 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3124 /* Get passphrase */
3125 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3127 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3128 memcpy(passphrase, tmp, tmp_len);
3131 if (!passphrase || !channel->passphrase ||
3132 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3134 SILC_STATUS_ERR_BAD_PASSWORD);
3140 * Client is allowed to join to the channel. Make it happen.
3143 /* Check whether the client already is on the channel */
3144 if (silc_server_client_on_channel(client, channel)) {
3145 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3146 SILC_STATUS_ERR_USER_ON_CHANNEL);
3150 /* Generate new channel key as protocol dictates */
3152 if (!silc_server_create_channel_key(server, channel, 0))
3155 /* Send the channel key. This is broadcasted to the channel but is not
3156 sent to the client who is joining to the channel. */
3157 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3158 silc_server_send_channel_key(server, NULL, channel,
3159 server->server_type == SILC_ROUTER ?
3160 FALSE : !server->standalone);
3163 /* Join the client to the channel by adding it to channel's user list.
3164 Add also the channel to client entry's channels list for fast cross-
3166 chl = silc_calloc(1, sizeof(*chl));
3168 chl->client = client;
3169 chl->channel = channel;
3170 silc_hash_table_add(channel->user_list, client, chl);
3171 silc_hash_table_add(client->channels, channel, chl);
3173 /* Get users on the channel */
3174 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3177 /* Encode Client ID Payload of the original client who wants to join */
3178 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3180 /* Encode command reply packet */
3181 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3182 SILC_PUT32_MSB(channel->mode, mode);
3183 SILC_PUT32_MSB(created, tmp2);
3184 SILC_PUT32_MSB(user_count, tmp3);
3186 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3187 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3188 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3189 strlen(channel->channel_key->
3191 channel->channel_key->cipher->name,
3192 channel->key_len / 8, channel->key);
3197 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3198 SILC_STATUS_OK, ident, 13,
3199 2, channel->channel_name,
3200 strlen(channel->channel_name),
3201 3, chidp->data, chidp->len,
3202 4, clidp->data, clidp->len,
3205 7, keyp ? keyp->data : NULL,
3206 keyp ? keyp->len : 0,
3207 8, channel->ban_list,
3209 strlen(channel->ban_list) : 0,
3210 9, channel->invite_list,
3211 channel->invite_list ?
3212 strlen(channel->invite_list) : 0,
3215 strlen(channel->topic) : 0,
3216 11, silc_hmac_get_name(channel->hmac),
3217 strlen(silc_hmac_get_name(channel->
3220 13, user_list->data, user_list->len,
3221 14, mode_list->data,
3224 /* Send command reply */
3225 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3226 reply->data, reply->len, FALSE);
3228 /* Send JOIN notify to locally connected clients on the channel. If
3229 we are normal server then router will send or have sent JOIN notify
3230 already. However since we've added the client already to our channel
3231 we'll ignore it (in packet_receive.c) so we must send it here. If
3232 we are router then this will send it to local clients and local
3234 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3235 SILC_NOTIFY_TYPE_JOIN, 2,
3236 clidp->data, clidp->len,
3237 chidp->data, chidp->len);
3239 if (!cmd->pending) {
3240 /* Send JOIN notify packet to our primary router */
3241 if (!server->standalone)
3242 silc_server_send_notify_join(server, server->router->connection,
3243 server->server_type == SILC_ROUTER ?
3244 TRUE : FALSE, channel, client->id);
3247 /* Distribute the channel key to all backup routers. */
3248 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3249 keyp->data, keyp->len, FALSE, TRUE);
3251 /* If client became founder by providing correct founder auth data
3252 notify the mode change to the channel. */
3254 SILC_PUT32_MSB(chl->mode, mode);
3255 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3256 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3257 clidp->data, clidp->len,
3258 mode, 4, clidp->data, clidp->len);
3260 /* Set CUMODE notify type to network */
3261 if (!server->standalone)
3262 silc_server_send_notify_cumode(server, server->router->connection,
3263 server->server_type == SILC_ROUTER ?
3264 TRUE : FALSE, channel,
3265 chl->mode, client->id, SILC_ID_CLIENT,
3270 silc_buffer_free(reply);
3271 silc_buffer_free(clidp);
3272 silc_buffer_free(chidp);
3273 silc_buffer_free(keyp);
3274 silc_buffer_free(user_list);
3275 silc_buffer_free(mode_list);
3278 silc_free(passphrase);
3281 /* Server side of command JOIN. Joins client into requested channel. If
3282 the channel does not exist it will be created. */
3284 SILC_SERVER_CMD_FUNC(join)
3286 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3287 SilcServer server = cmd->server;
3288 unsigned char *auth;
3289 uint32 tmp_len, auth_len;
3290 char *tmp, *channel_name = NULL, *cipher, *hmac;
3291 SilcChannelEntry channel;
3293 bool created = FALSE, create_key = TRUE;
3294 SilcClientID *client_id;
3296 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3298 /* Get channel name */
3299 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3302 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3308 channel_name[255] = '\0';
3310 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3312 SILC_STATUS_ERR_BAD_CHANNEL);
3316 /* Get Client ID of the client who is joining to the channel */
3317 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3320 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3323 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3326 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3330 /* Get cipher, hmac name and auth payload */
3331 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3332 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3333 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3335 /* See if the channel exists */
3336 channel = silc_idlist_find_channel_by_name(server->local_list,
3337 channel_name, NULL);
3339 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3340 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3341 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3343 if (!channel || channel->disabled) {
3344 /* Channel not found */
3346 /* If we are standalone server we don't have a router, we just create
3347 the channel by ourselves. */
3348 if (server->standalone) {
3349 channel = silc_server_create_new_channel(server, server->id, cipher,
3350 hmac, channel_name, TRUE);
3352 silc_server_command_send_status_reply(
3353 cmd, SILC_COMMAND_JOIN,
3354 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3358 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3364 /* The channel does not exist on our server. If we are normal server
3365 we will send JOIN command to our router which will handle the
3366 joining procedure (either creates the channel if it doesn't exist
3367 or joins the client to it). */
3368 if (server->server_type != SILC_ROUTER) {
3372 /* If this is pending command callback then we've resolved
3373 it and it didn't work, return since we've notified the
3374 client already in the command reply callback. */
3378 old_ident = silc_command_get_ident(cmd->payload);
3379 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3380 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3382 /* Send JOIN command to our router */
3383 silc_server_packet_send(server, (SilcSocketConnection)
3384 server->router->connection,
3385 SILC_PACKET_COMMAND, cmd->packet->flags,
3386 tmpbuf->data, tmpbuf->len, TRUE);
3388 /* Reprocess this packet after received reply from router */
3389 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3390 silc_command_get_ident(cmd->payload),
3391 silc_server_command_join,
3392 silc_server_command_dup(cmd));
3393 cmd->pending = TRUE;
3394 silc_command_set_ident(cmd->payload, old_ident);
3398 /* We are router and the channel does not seem exist so we will check
3399 our global list as well for the channel. */
3400 channel = silc_idlist_find_channel_by_name(server->global_list,
3401 channel_name, NULL);
3403 /* Channel really does not exist, create it */
3404 channel = silc_server_create_new_channel(server, server->id, cipher,
3405 hmac, channel_name, TRUE);
3407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3408 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3412 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3420 /* Channel not found */
3422 /* If the command came from router and we are normal server then
3423 something went wrong with the joining as the channel was not found.
3424 We can't do anything else but ignore this. */
3425 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3426 server->server_type != SILC_ROUTER)
3429 /* We are router and the channel does not seem exist so we will check
3430 our global list as well for the channel. */
3431 channel = silc_idlist_find_channel_by_name(server->global_list,
3432 channel_name, NULL);
3434 /* Channel really does not exist, create it */
3435 channel = silc_server_create_new_channel(server, server->id, cipher,
3436 hmac, channel_name, TRUE);
3438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3439 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3443 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3450 /* Check whether the channel was created by our router */
3451 if (cmd->pending && context2) {
3452 SilcServerCommandReplyContext reply =
3453 (SilcServerCommandReplyContext)context2;
3455 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3456 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3457 SILC_GET32_MSB(created, tmp);
3458 create_key = FALSE; /* Router returned the key already */
3461 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3462 !silc_hash_table_count(channel->user_list))
3466 /* If the channel does not have global users and is also empty the client
3467 will be the channel founder and operator. */
3468 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3469 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3471 /* Join to the channel */
3472 silc_server_command_join_channel(server, cmd, channel, client_id,
3473 created, create_key, umode,
3476 silc_free(client_id);
3479 silc_server_command_free(cmd);
3482 /* Server side of command MOTD. Sends server's current "message of the
3483 day" to the client. */
3485 SILC_SERVER_CMD_FUNC(motd)
3487 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3488 SilcServer server = cmd->server;
3489 SilcBuffer packet, idp;
3490 char *motd, *dest_server;
3492 uint16 ident = silc_command_get_ident(cmd->payload);
3494 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3496 /* Get server name */
3497 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3500 SILC_STATUS_ERR_NO_SUCH_SERVER);
3504 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3507 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3509 if (server->config && server->config->motd &&
3510 server->config->motd->motd_file) {
3512 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3517 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3518 SILC_STATUS_OK, ident, 2,
3523 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3524 SILC_STATUS_OK, ident, 1,
3528 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3529 packet->data, packet->len, FALSE);
3530 silc_buffer_free(packet);
3531 silc_buffer_free(idp);
3533 SilcServerEntry entry;
3535 /* Check whether we have this server cached */
3536 entry = silc_idlist_find_server_by_name(server->global_list,
3537 dest_server, TRUE, NULL);
3539 entry = silc_idlist_find_server_by_name(server->local_list,
3540 dest_server, TRUE, NULL);
3543 if (server->server_type != SILC_SERVER && !cmd->pending &&
3544 entry && !entry->motd) {
3545 /* Send to the server */
3549 old_ident = silc_command_get_ident(cmd->payload);
3550 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3551 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3553 silc_server_packet_send(server, entry->connection,
3554 SILC_PACKET_COMMAND, cmd->packet->flags,
3555 tmpbuf->data, tmpbuf->len, TRUE);
3557 /* Reprocess this packet after received reply from router */
3558 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3559 silc_command_get_ident(cmd->payload),
3560 silc_server_command_motd,
3561 silc_server_command_dup(cmd));
3562 cmd->pending = TRUE;
3563 silc_command_set_ident(cmd->payload, old_ident);
3564 silc_buffer_free(tmpbuf);
3568 if (!entry && !cmd->pending && !server->standalone) {
3569 /* Send to the primary router */
3573 old_ident = silc_command_get_ident(cmd->payload);
3574 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3575 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3577 silc_server_packet_send(server, server->router->connection,
3578 SILC_PACKET_COMMAND, cmd->packet->flags,
3579 tmpbuf->data, tmpbuf->len, TRUE);
3581 /* Reprocess this packet after received reply from router */
3582 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3583 silc_command_get_ident(cmd->payload),
3584 silc_server_command_motd,
3585 silc_server_command_dup(cmd));
3586 cmd->pending = TRUE;
3587 silc_command_set_ident(cmd->payload, old_ident);
3588 silc_buffer_free(tmpbuf);
3593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3594 SILC_STATUS_ERR_NO_SUCH_SERVER);
3598 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3599 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3600 SILC_STATUS_OK, ident, 2,
3604 strlen(entry->motd) : 0);
3605 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3606 packet->data, packet->len, FALSE);
3607 silc_buffer_free(packet);
3608 silc_buffer_free(idp);
3612 silc_server_command_free(cmd);
3615 /* Server side of command UMODE. Client can use this command to set/unset
3616 user mode. Client actually cannot set itself to be as server/router
3617 operator so this can be used only to unset the modes. */
3619 SILC_SERVER_CMD_FUNC(umode)
3621 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3622 SilcServer server = cmd->server;
3623 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3625 unsigned char *tmp_mask;
3627 uint16 ident = silc_command_get_ident(cmd->payload);
3629 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3632 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3634 /* Get the client's mode mask */
3635 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3638 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3641 SILC_GET32_MSB(mask, tmp_mask);
3647 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3648 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3649 /* Cannot operator mode */
3650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3651 SILC_STATUS_ERR_PERM_DENIED);
3655 /* Remove the server operator rights */
3656 if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
3657 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3658 if (client->connection)
3659 server->stat.my_server_ops--;
3660 if (server->server_type == SILC_ROUTER)
3661 server->stat.server_ops--;
3665 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3666 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3667 /* Cannot operator mode */
3668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3669 SILC_STATUS_ERR_PERM_DENIED);
3673 /* Remove the router operator rights */
3674 if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
3675 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3676 if (client->connection)
3677 server->stat.my_router_ops--;
3678 if (server->server_type == SILC_ROUTER)
3679 server->stat.router_ops--;
3683 if (mask & SILC_UMODE_GONE) {
3684 client->mode |= SILC_UMODE_GONE;
3686 if (client->mode & SILC_UMODE_GONE)
3687 /* Remove the gone status */
3688 client->mode &= ~SILC_UMODE_GONE;
3691 /* Send UMODE change to primary router */
3692 if (!server->standalone)
3693 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3694 client->id, client->mode);
3696 /* Send command reply to sender */
3697 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3698 SILC_STATUS_OK, ident, 1,
3700 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3701 packet->data, packet->len, FALSE);
3702 silc_buffer_free(packet);
3705 silc_server_command_free(cmd);
3708 /* Checks that client has rights to add or remove channel modes. If any
3709 of the checks fails FALSE is returned. */
3711 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3712 SilcChannelClientEntry client,
3715 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3716 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3718 /* Check whether has rights to change anything */
3719 if (!is_op && !is_fo)
3722 /* Check whether has rights to change everything */
3726 /* We know that client is channel operator, check that they are not
3727 changing anything that requires channel founder rights. Rest of the
3728 modes are available automatically for channel operator. */
3730 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3731 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3732 if (is_op && !is_fo)
3735 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3736 if (is_op && !is_fo)
3741 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3742 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3743 if (is_op && !is_fo)
3746 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3747 if (is_op && !is_fo)
3752 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3753 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3754 if (is_op && !is_fo)
3757 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3758 if (is_op && !is_fo)
3763 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3764 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3765 if (is_op && !is_fo)
3768 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3769 if (is_op && !is_fo)
3777 /* Server side command of CMODE. Changes channel mode */
3779 SILC_SERVER_CMD_FUNC(cmode)
3781 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3782 SilcServer server = cmd->server;
3783 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3784 SilcIDListData idata = (SilcIDListData)client;
3785 SilcChannelID *channel_id;
3786 SilcChannelEntry channel;
3787 SilcChannelClientEntry chl;
3788 SilcBuffer packet, cidp;
3789 unsigned char *tmp, *tmp_id, *tmp_mask;
3790 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3791 uint32 mode_mask, tmp_len, tmp_len2;
3792 uint16 ident = silc_command_get_ident(cmd->payload);
3794 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3796 /* Get Channel ID */
3797 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3800 SILC_STATUS_ERR_NO_CHANNEL_ID);
3803 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3806 SILC_STATUS_ERR_NO_CHANNEL_ID);
3810 /* Get the channel mode mask */
3811 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3814 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3817 SILC_GET32_MSB(mode_mask, tmp_mask);
3819 /* Get channel entry */
3820 channel = silc_idlist_find_channel_by_id(server->local_list,
3823 channel = silc_idlist_find_channel_by_id(server->global_list,
3826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3827 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3832 /* Check whether this client is on the channel */
3833 if (!silc_server_client_on_channel(client, channel)) {
3834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3835 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3839 /* Get entry to the channel user list */
3840 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3842 /* Check that client has rights to change any requested channel modes */
3843 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3845 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3850 * Check the modes. Modes that requires nothing special operation are
3854 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3855 /* Channel uses private keys to protect traffic. Client(s) has set the
3856 key locally they want to use, server does not know that key. */
3857 /* Nothing interesting to do here */
3859 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3860 /* The mode is removed and we need to generate and distribute
3861 new channel key. Clients are not using private channel keys
3862 anymore after this. */
3864 /* Re-generate channel key */
3865 if (!silc_server_create_channel_key(server, channel, 0))
3868 /* Send the channel key. This sends it to our local clients and if
3869 we are normal server to our router as well. */
3870 silc_server_send_channel_key(server, NULL, channel,
3871 server->server_type == SILC_ROUTER ?
3872 FALSE : !server->standalone);
3874 cipher = channel->channel_key->cipher->name;
3875 hmac = (char *)silc_hmac_get_name(channel->hmac);
3879 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3880 /* User limit is set on channel */
3883 /* Get user limit */
3884 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3886 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3887 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3888 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3892 SILC_GET32_MSB(user_limit, tmp);
3893 channel->user_limit = user_limit;
3896 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3897 /* User limit mode is unset. Remove user limit */
3898 channel->user_limit = 0;
3901 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3902 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3903 /* Passphrase has been set to channel */
3905 /* Get the passphrase */
3906 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3909 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3913 /* Save the passphrase */
3914 passphrase = channel->passphrase = strdup(tmp);
3917 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3918 /* Passphrase mode is unset. remove the passphrase */
3919 if (channel->passphrase) {
3920 silc_free(channel->passphrase);
3921 channel->passphrase = NULL;
3926 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3927 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3928 /* Cipher to use protect the traffic */
3929 SilcCipher newkey, oldkey;
3932 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3935 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3939 /* Delete old cipher and allocate the new one */
3940 if (!silc_cipher_alloc(cipher, &newkey)) {
3941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3942 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3946 oldkey = channel->channel_key;
3947 channel->channel_key = newkey;
3949 /* Re-generate channel key */
3950 if (!silc_server_create_channel_key(server, channel, 0)) {
3951 /* We don't have new key, revert to old one */
3952 channel->channel_key = oldkey;
3956 /* Remove old channel key for good */
3957 silc_cipher_free(oldkey);
3959 /* Send the channel key. This sends it to our local clients and if
3960 we are normal server to our router as well. */
3961 silc_server_send_channel_key(server, NULL, channel,
3962 server->server_type == SILC_ROUTER ?
3963 FALSE : !server->standalone);
3966 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3967 /* Cipher mode is unset. Remove the cipher and revert back to
3969 SilcCipher newkey, oldkey;
3970 cipher = channel->cipher;
3972 /* Delete old cipher and allocate default one */
3973 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3975 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3979 oldkey = channel->channel_key;
3980 channel->channel_key = newkey;
3982 /* Re-generate channel key */
3983 if (!silc_server_create_channel_key(server, channel, 0)) {
3984 /* We don't have new key, revert to old one */
3985 channel->channel_key = oldkey;
3989 /* Remove old channel key for good */
3990 silc_cipher_free(oldkey);
3992 /* Send the channel key. This sends it to our local clients and if
3993 we are normal server to our router as well. */
3994 silc_server_send_channel_key(server, NULL, channel,
3995 server->server_type == SILC_ROUTER ?
3996 FALSE : !server->standalone);
4000 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4001 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4002 /* HMAC to use protect the traffic */
4003 unsigned char hash[32];
4007 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4010 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4014 /* Delete old hmac and allocate the new one */
4015 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4017 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4021 silc_hmac_free(channel->hmac);
4022 channel->hmac = newhmac;
4024 /* Set the HMAC key out of current channel key. The client must do
4026 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4027 channel->key_len / 8, hash);
4028 silc_hmac_set_key(channel->hmac, hash,
4029 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4030 memset(hash, 0, sizeof(hash));
4033 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4034 /* Hmac mode is unset. Remove the hmac and revert back to
4037 unsigned char hash[32];
4038 hmac = channel->hmac_name;
4040 /* Delete old hmac and allocate default one */
4041 silc_hmac_free(channel->hmac);
4042 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4044 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4048 silc_hmac_free(channel->hmac);
4049 channel->hmac = newhmac;
4051 /* Set the HMAC key out of current channel key. The client must do
4053 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4054 channel->key_len / 8,
4056 silc_hmac_set_key(channel->hmac, hash,
4057 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4058 memset(hash, 0, sizeof(hash));
4062 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4063 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4064 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4065 /* Set the founder authentication */
4066 SilcAuthPayload auth;
4068 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4071 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4075 auth = silc_auth_payload_parse(tmp, tmp_len);
4077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4078 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4082 /* Save the public key */
4083 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4084 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4087 channel->founder_method = silc_auth_get_method(auth);
4089 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4090 tmp = silc_auth_get_data(auth, &tmp_len);
4091 channel->founder_passwd =
4092 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4093 memcpy(channel->founder_passwd, tmp, tmp_len);
4094 channel->founder_passwd_len = tmp_len;
4096 /* Verify the payload before setting the mode */
4097 if (!silc_auth_verify(auth, channel->founder_method,
4098 channel->founder_key, 0, idata->hash,
4099 client->id, SILC_ID_CLIENT)) {
4100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4101 SILC_STATUS_ERR_AUTH_FAILED);
4106 silc_auth_payload_free(auth);
4110 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4111 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4112 if (channel->founder_key)
4113 silc_pkcs_public_key_free(channel->founder_key);
4114 if (channel->founder_passwd) {
4115 silc_free(channel->founder_passwd);
4116 channel->founder_passwd = NULL;
4122 /* Finally, set the mode */
4123 channel->mode = mode_mask;
4125 /* Send CMODE_CHANGE notify. */
4126 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4127 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4128 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4129 cidp->data, cidp->len,
4131 cipher, cipher ? strlen(cipher) : 0,
4132 hmac, hmac ? strlen(hmac) : 0,
4133 passphrase, passphrase ?
4134 strlen(passphrase) : 0);
4136 /* Set CMODE notify type to network */
4137 if (!server->standalone)
4138 silc_server_send_notify_cmode(server, server->router->connection,
4139 server->server_type == SILC_ROUTER ?
4140 TRUE : FALSE, channel,
4141 mode_mask, client->id, SILC_ID_CLIENT,
4142 cipher, hmac, passphrase);
4144 /* Send command reply to sender */
4145 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4146 SILC_STATUS_OK, ident, 2,
4147 2, tmp_id, tmp_len2,
4149 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4150 packet->data, packet->len, FALSE);
4152 silc_buffer_free(packet);
4153 silc_free(channel_id);
4154 silc_buffer_free(cidp);
4157 silc_server_command_free(cmd);
4160 /* Server side of CUMODE command. Changes client's mode on a channel. */
4162 SILC_SERVER_CMD_FUNC(cumode)
4164 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4165 SilcServer server = cmd->server;
4166 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4167 SilcIDListData idata = (SilcIDListData)client;
4168 SilcChannelID *channel_id;
4169 SilcClientID *client_id;
4170 SilcChannelEntry channel;
4171 SilcClientEntry target_client;
4172 SilcChannelClientEntry chl;
4173 SilcBuffer packet, idp;
4174 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4175 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4177 uint16 ident = silc_command_get_ident(cmd->payload);
4179 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4181 /* Get Channel ID */
4182 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4184 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4185 SILC_STATUS_ERR_NO_CHANNEL_ID);
4188 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4191 SILC_STATUS_ERR_NO_CHANNEL_ID);
4195 /* Get channel entry */
4196 channel = silc_idlist_find_channel_by_id(server->local_list,
4199 channel = silc_idlist_find_channel_by_id(server->global_list,
4202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4203 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4208 /* Check whether sender is on the channel */
4209 if (!silc_server_client_on_channel(client, channel)) {
4210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4211 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4215 /* Check that client has rights to change other's rights */
4216 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4217 sender_mask = chl->mode;
4219 /* Get the target client's channel mode mask */
4220 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4223 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4226 SILC_GET32_MSB(target_mask, tmp_mask);
4228 /* Get target Client ID */
4229 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4232 SILC_STATUS_ERR_NO_CLIENT_ID);
4235 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4238 SILC_STATUS_ERR_NO_CLIENT_ID);
4242 /* Get target client's entry */
4243 target_client = silc_idlist_find_client_by_id(server->local_list,
4244 client_id, TRUE, NULL);
4245 if (!target_client) {
4246 target_client = silc_idlist_find_client_by_id(server->global_list,
4247 client_id, TRUE, NULL);
4250 if (target_client != client &&
4251 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4252 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4253 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4254 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4258 /* Check whether target client is on the channel */
4259 if (target_client != client) {
4260 if (!silc_server_client_on_channel(target_client, channel)) {
4261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4262 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4266 /* Get entry to the channel user list */
4267 silc_hash_table_find(channel->user_list, target_client, NULL,
4275 /* If the target client is founder, no one else can change their mode
4277 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4279 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4283 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4284 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4285 /* The client tries to claim the founder rights. */
4286 unsigned char *tmp_auth;
4287 uint32 tmp_auth_len, auth_len;
4290 if (target_client != client) {
4291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4292 SILC_STATUS_ERR_NOT_YOU);
4296 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4297 !channel->founder_key || !idata->public_key ||
4298 !silc_pkcs_public_key_compare(channel->founder_key,
4299 idata->public_key)) {
4300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4301 SILC_STATUS_ERR_NOT_YOU);
4305 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4308 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4312 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4313 (void *)channel->founder_passwd : (void *)channel->founder_key);
4314 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4315 channel->founder_passwd_len : 0);
4317 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4318 channel->founder_method, auth, auth_len,
4319 idata->hash, client->id, SILC_ID_CLIENT)) {
4320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4321 SILC_STATUS_ERR_AUTH_FAILED);
4325 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4329 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4330 if (target_client == client) {
4331 /* Remove channel founder rights from itself */
4332 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4336 SILC_STATUS_ERR_NOT_YOU);
4342 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4343 /* Promote to operator */
4344 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4345 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4346 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4348 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4352 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4356 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4357 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4358 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4360 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4364 /* Demote to normal user */
4365 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4370 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4371 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4373 /* Send notify to channel, notify only if mode was actually changed. */
4375 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4376 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4377 idp->data, idp->len,
4381 /* Set CUMODE notify type to network */
4382 if (!server->standalone)
4383 silc_server_send_notify_cumode(server, server->router->connection,
4384 server->server_type == SILC_ROUTER ?
4385 TRUE : FALSE, channel,
4386 target_mask, client->id,
4391 /* Send command reply to sender */
4392 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4393 SILC_STATUS_OK, ident, 3,
4395 3, tmp_ch_id, tmp_ch_len,
4396 4, tmp_id, tmp_len);
4397 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4398 packet->data, packet->len, FALSE);
4400 silc_buffer_free(packet);
4401 silc_free(channel_id);
4402 silc_free(client_id);
4403 silc_buffer_free(idp);
4406 silc_server_command_free(cmd);
4409 /* Server side of KICK command. Kicks client out of channel. */
4411 SILC_SERVER_CMD_FUNC(kick)
4413 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4414 SilcServer server = cmd->server;
4415 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4416 SilcClientEntry target_client;
4417 SilcChannelID *channel_id;
4418 SilcClientID *client_id;
4419 SilcChannelEntry channel;
4420 SilcChannelClientEntry chl;
4422 uint32 tmp_len, target_idp_len;
4423 unsigned char *tmp, *comment, *target_idp;
4425 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4427 /* Get Channel ID */
4428 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4431 SILC_STATUS_ERR_NO_CHANNEL_ID);
4434 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4437 SILC_STATUS_ERR_NO_CHANNEL_ID);
4441 /* Get channel entry */
4442 channel = silc_idlist_find_channel_by_id(server->local_list,
4445 channel = silc_idlist_find_channel_by_id(server->local_list,
4448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4449 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4454 /* Check whether sender is on the channel */
4455 if (!silc_server_client_on_channel(client, channel)) {
4456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4457 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4461 /* Check that the kicker is channel operator or channel founder */
4462 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4463 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4465 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4469 /* Get target Client ID */
4470 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4473 SILC_STATUS_ERR_NO_CLIENT_ID);
4476 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4479 SILC_STATUS_ERR_NO_CLIENT_ID);
4483 /* Get target client's entry */
4484 target_client = silc_idlist_find_client_by_id(server->local_list,
4485 client_id, TRUE, NULL);
4486 if (!target_client) {
4487 target_client = silc_idlist_find_client_by_id(server->global_list,
4488 client_id, TRUE, NULL);
4491 /* Check that the target client is not channel founder. Channel founder
4492 cannot be kicked from the channel. */
4493 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4494 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4496 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4500 /* Check whether target client is on the channel */
4501 if (!silc_server_client_on_channel(target_client, channel)) {
4502 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4503 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4509 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4513 /* Send command reply to sender */
4514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4517 /* Send KICKED notify to local clients on the channel */
4518 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4519 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4520 SILC_NOTIFY_TYPE_KICKED, 3,
4521 target_idp, target_idp_len,
4522 comment, comment ? strlen(comment) : 0,
4523 idp->data, idp->len);
4524 silc_buffer_free(idp);
4526 /* Remove the client from the channel. If the channel does not exist
4527 after removing the client then the client kicked itself off the channel
4528 and we don't have to send anything after that. */
4529 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4530 target_client, FALSE))
4533 /* Send KICKED notify to primary route */
4534 if (!server->standalone)
4535 silc_server_send_notify_kicked(server, server->router->connection,
4536 server->server_type == SILC_ROUTER ?
4537 TRUE : FALSE, channel,
4538 target_client->id, client->id, comment);
4540 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4541 /* Re-generate channel key */
4542 if (!silc_server_create_channel_key(server, channel, 0))
4545 /* Send the channel key to the channel. The key of course is not sent
4546 to the client who was kicked off the channel. */
4547 silc_server_send_channel_key(server, target_client->connection, channel,
4548 server->server_type == SILC_ROUTER ?
4549 FALSE : !server->standalone);
4553 silc_server_command_free(cmd);
4556 /* Server side of OPER command. Client uses this comand to obtain server
4557 operator privileges to this server/router. */
4559 SILC_SERVER_CMD_FUNC(oper)
4561 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4562 SilcServer server = cmd->server;
4563 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4564 unsigned char *username, *auth;
4566 SilcServerConfigSectionAdminConnection *admin;
4567 SilcIDListData idata = (SilcIDListData)client;
4569 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4571 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4574 /* Get the username */
4575 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4577 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4578 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4582 /* Get the admin configuration */
4583 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4584 username, client->nickname);
4586 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4587 username, client->nickname);
4589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4590 SILC_STATUS_ERR_AUTH_FAILED);
4595 /* Get the authentication payload */
4596 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4599 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4603 /* Verify the authentication data */
4604 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4605 admin->auth_data, admin->auth_data_len,
4606 idata->hash, client->id, SILC_ID_CLIENT)) {
4607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4608 SILC_STATUS_ERR_AUTH_FAILED);
4612 /* Client is now server operator */
4613 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4615 /* Update statistics */
4616 if (client->connection)
4617 server->stat.my_server_ops++;
4618 if (server->server_type == SILC_ROUTER)
4619 server->stat.server_ops++;
4621 /* Send UMODE change to primary router */
4622 if (!server->standalone)
4623 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4624 client->id, client->mode);
4626 /* Send reply to the sender */
4627 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4631 silc_server_command_free(cmd);
4634 /* Server side of SILCOPER command. Client uses this comand to obtain router
4635 operator privileges to this router. */
4637 SILC_SERVER_CMD_FUNC(silcoper)
4639 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4640 SilcServer server = cmd->server;
4641 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4642 unsigned char *username, *auth;
4644 SilcServerConfigSectionAdminConnection *admin;
4645 SilcIDListData idata = (SilcIDListData)client;
4647 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4649 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4652 if (server->server_type != SILC_ROUTER) {
4653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4654 SILC_STATUS_ERR_AUTH_FAILED);
4658 /* Get the username */
4659 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4662 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4666 /* Get the admin configuration */
4667 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4668 username, client->nickname);
4670 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4671 username, client->nickname);
4673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4674 SILC_STATUS_ERR_AUTH_FAILED);
4679 /* Get the authentication payload */
4680 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4683 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4687 /* Verify the authentication data */
4688 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4689 admin->auth_data, admin->auth_data_len,
4690 idata->hash, client->id, SILC_ID_CLIENT)) {
4691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4692 SILC_STATUS_ERR_AUTH_FAILED);
4696 /* Client is now router operator */
4697 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4699 /* Update statistics */
4700 if (client->connection)
4701 server->stat.my_router_ops++;
4702 if (server->server_type == SILC_ROUTER)
4703 server->stat.router_ops++;
4705 /* Send UMODE change to primary router */
4706 if (!server->standalone)
4707 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4708 client->id, client->mode);
4710 /* Send reply to the sender */
4711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4715 silc_server_command_free(cmd);
4718 /* Server side command of CONNECT. Connects us to the specified remote
4719 server or router. */
4721 SILC_SERVER_CMD_FUNC(connect)
4723 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4724 SilcServer server = cmd->server;
4725 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4726 unsigned char *tmp, *host;
4728 uint32 port = SILC_PORT;
4730 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4732 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4735 /* Check whether client has the permissions. */
4736 if (client->mode == SILC_UMODE_NONE) {
4737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4738 SILC_STATUS_ERR_NO_SERVER_PRIV);
4742 if (server->server_type == SILC_ROUTER &&
4743 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4745 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4749 /* Get the remote server */
4750 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4752 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4753 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4758 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4760 SILC_GET32_MSB(port, tmp);
4762 /* Create the connection. It is done with timeout and is async. */
4763 silc_server_create_connection(server, host, port);
4765 /* Send reply to the sender */
4766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4770 silc_server_command_free(cmd);
4773 /* Server side of command BAN. This is used to manage the ban list of the
4774 channel. To add clients and remove clients from the ban list. */
4776 SILC_SERVER_CMD_FUNC(ban)
4778 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4779 SilcServer server = cmd->server;
4780 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4782 SilcChannelEntry channel;
4783 SilcChannelClientEntry chl;
4784 SilcChannelID *channel_id = NULL;
4785 unsigned char *id, *add, *del;
4786 uint32 id_len, tmp_len;
4787 uint16 ident = silc_command_get_ident(cmd->payload);
4789 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4792 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4794 /* Get Channel ID */
4795 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4797 channel_id = silc_id_payload_parse_id(id, id_len);
4799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4800 SILC_STATUS_ERR_NO_CHANNEL_ID);
4805 /* Get channel entry. The server must know about the channel since the
4806 client is expected to be on the channel. */
4807 channel = silc_idlist_find_channel_by_id(server->local_list,
4810 channel = silc_idlist_find_channel_by_id(server->global_list,
4813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4814 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4819 /* Check whether this client is on the channel */
4820 if (!silc_server_client_on_channel(client, channel)) {
4821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4822 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4826 /* Get entry to the channel user list */
4827 if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
4828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4829 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4833 /* The client must be at least channel operator. */
4834 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4836 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4840 /* Get the new ban and add it to the ban list */
4841 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4843 if (!channel->ban_list)
4844 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4846 channel->ban_list = silc_realloc(channel->ban_list,
4847 sizeof(*channel->ban_list) *
4849 strlen(channel->ban_list) + 2));
4850 if (add[tmp_len - 1] == ',')
4851 add[tmp_len - 1] = '\0';
4853 strncat(channel->ban_list, add, tmp_len);
4854 strncat(channel->ban_list, ",", 1);
4857 /* Get the ban to be removed and remove it from the list */
4858 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4859 if (del && channel->ban_list) {
4860 char *start, *end, *n;
4862 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4863 silc_free(channel->ban_list);
4864 channel->ban_list = NULL;
4866 start = strstr(channel->ban_list, del);
4867 if (start && strlen(start) >= tmp_len) {
4868 end = start + tmp_len;
4869 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4870 strncat(n, channel->ban_list, start - channel->ban_list);
4871 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4873 silc_free(channel->ban_list);
4874 channel->ban_list = n;
4879 /* Send the BAN notify type to our primary router. */
4880 if (!server->standalone && (add || del))
4881 silc_server_send_notify_ban(server, server->router->connection,
4882 server->server_type == SILC_ROUTER ?
4883 TRUE : FALSE, channel, add, del);
4885 /* Send the reply back to the client */
4887 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4888 SILC_STATUS_OK, ident, 2,
4890 3, channel->ban_list,
4892 strlen(channel->ban_list) : 0);
4893 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4894 packet->data, packet->len, FALSE);
4896 silc_buffer_free(packet);
4899 silc_free(channel_id);
4900 silc_server_command_free(cmd);
4903 /* Server side command of CLOSE. Closes connection to a specified server. */
4905 SILC_SERVER_CMD_FUNC(close)
4907 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4908 SilcServer server = cmd->server;
4909 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4910 SilcServerEntry server_entry;
4911 SilcSocketConnection sock;
4914 unsigned char *name;
4915 uint32 port = SILC_PORT;
4917 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4919 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4922 /* Check whether client has the permissions. */
4923 if (client->mode == SILC_UMODE_NONE) {
4924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4925 SILC_STATUS_ERR_NO_SERVER_PRIV);
4929 /* Get the remote server */
4930 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4932 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4933 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4938 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4940 SILC_GET32_MSB(port, tmp);
4942 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4943 name, port, FALSE, NULL);
4945 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4946 name, port, FALSE, NULL);
4947 if (!server_entry) {
4948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4949 SILC_STATUS_ERR_NO_SERVER_ID);
4953 /* Send reply to the sender */
4954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4957 /* Close the connection to the server */
4958 sock = (SilcSocketConnection)server_entry->connection;
4960 /* If we shutdown primary router connection manually then don't trigger
4961 any reconnect or backup router connections, by setting the router
4963 if (server->router == server_entry) {
4964 server->id_entry->router = NULL;
4965 server->router = NULL;
4966 server->standalone = TRUE;
4968 silc_server_free_sock_user_data(server, sock, NULL);
4969 silc_server_close_connection(server, sock);
4972 silc_server_command_free(cmd);
4975 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4976 active connections. */
4978 SILC_SERVER_CMD_FUNC(shutdown)
4980 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4981 SilcServer server = cmd->server;
4982 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4984 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4986 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4989 /* Check whether client has the permission. */
4990 if (client->mode == SILC_UMODE_NONE) {
4991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4992 SILC_STATUS_ERR_NO_SERVER_PRIV);
4996 /* Send reply to the sender */
4997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5000 /* Then, gracefully, or not, bring the server down. */
5001 silc_server_stop(server);
5005 silc_server_command_free(cmd);
5008 /* Server side command of LEAVE. Removes client from a channel. */
5010 SILC_SERVER_CMD_FUNC(leave)
5012 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5013 SilcServer server = cmd->server;
5014 SilcSocketConnection sock = cmd->sock;
5015 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5016 SilcChannelID *id = NULL;
5017 SilcChannelEntry channel;
5021 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5023 /* Get Channel ID */
5024 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5027 SILC_STATUS_ERR_NO_CHANNEL_ID);
5030 id = silc_id_payload_parse_id(tmp, len);
5032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5033 SILC_STATUS_ERR_NO_CHANNEL_ID);
5037 /* Get channel entry */
5038 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5040 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5043 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5048 /* Check whether this client is on the channel */
5049 if (!silc_server_client_on_channel(id_entry, channel)) {
5050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5051 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5055 /* Notify routers that they should remove this client from their list
5056 of clients on the channel. Send LEAVE notify type. */
5057 if (!server->standalone)
5058 silc_server_send_notify_leave(server, server->router->connection,
5059 server->server_type == SILC_ROUTER ?
5060 TRUE : FALSE, channel, id_entry->id);
5062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5065 /* Remove client from channel */
5066 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5068 /* If the channel does not exist anymore we won't send anything */
5071 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5072 /* Re-generate channel key */
5073 if (!silc_server_create_channel_key(server, channel, 0))
5076 /* Send the channel key */
5077 silc_server_send_channel_key(server, NULL, channel,
5078 server->server_type == SILC_ROUTER ?
5079 FALSE : !server->standalone);
5084 silc_server_command_free(cmd);
5087 /* Server side of command USERS. Resolves clients and their USERS currently
5088 joined on the requested channel. The list of Client ID's and their modes
5089 on the channel is sent back. */
5091 SILC_SERVER_CMD_FUNC(users)
5093 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5094 SilcServer server = cmd->server;
5095 SilcChannelEntry channel;
5096 SilcChannelID *id = NULL;
5097 SilcBuffer packet, idp;
5098 unsigned char *channel_id;
5099 uint32 channel_id_len;
5100 SilcBuffer client_id_list;
5101 SilcBuffer client_mode_list;
5102 unsigned char lc[4];
5103 uint32 list_count = 0;
5104 uint16 ident = silc_command_get_ident(cmd->payload);
5107 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5109 /* Get Channel ID */
5110 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5112 /* Get channel name */
5113 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5115 if (!channel_id && !channel_name) {
5116 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5117 SILC_STATUS_ERR_NO_CHANNEL_ID);
5122 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5124 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5125 SILC_STATUS_ERR_NO_CHANNEL_ID);
5130 /* If we are server and we don't know about this channel we will send
5131 the command to our router. If we know about the channel then we also
5132 have the list of users already. */
5134 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5136 channel = silc_idlist_find_channel_by_name(server->local_list,
5137 channel_name, NULL);
5139 if (!channel || channel->disabled) {
5140 if (server->server_type != SILC_ROUTER && !server->standalone &&
5144 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5145 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5147 /* Send USERS command */
5148 silc_server_packet_send(server, server->router->connection,
5149 SILC_PACKET_COMMAND, cmd->packet->flags,
5150 tmpbuf->data, tmpbuf->len, TRUE);
5152 /* Reprocess this packet after received reply */
5153 silc_server_command_pending(server, SILC_COMMAND_USERS,
5154 silc_command_get_ident(cmd->payload),
5155 silc_server_command_users,
5156 silc_server_command_dup(cmd));
5157 cmd->pending = TRUE;
5158 silc_command_set_ident(cmd->payload, ident);
5159 silc_buffer_free(tmpbuf);
5164 /* Check the global list as well. */
5166 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5168 channel = silc_idlist_find_channel_by_name(server->global_list,
5169 channel_name, NULL);
5171 /* Channel really does not exist */
5172 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5173 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5178 /* If the channel is private or secret do not send anything, unless the
5179 user requesting this command is on the channel. */
5180 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5181 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5182 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5184 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5189 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5191 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5196 /* Get the users list */
5197 silc_server_get_users_on_channel(server, channel, &client_id_list,
5198 &client_mode_list, &list_count);
5201 SILC_PUT32_MSB(list_count, lc);
5204 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5205 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5206 SILC_STATUS_OK, ident, 4,
5207 2, idp->data, idp->len,
5209 4, client_id_list->data,
5210 client_id_list->len,
5211 5, client_mode_list->data,
5212 client_mode_list->len);
5213 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5214 packet->data, packet->len, FALSE);
5216 silc_buffer_free(idp);
5217 silc_buffer_free(packet);
5218 silc_buffer_free(client_id_list);
5219 silc_buffer_free(client_mode_list);
5223 silc_server_command_free(cmd);
5226 /* Server side of command GETKEY. This fetches the client's public key
5227 from the server where to the client is connected. */
5229 SILC_SERVER_CMD_FUNC(getkey)
5231 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5232 SilcServer server = cmd->server;
5234 SilcClientEntry client;
5235 SilcServerEntry server_entry;
5236 SilcClientID *client_id = NULL;
5237 SilcServerID *server_id = NULL;
5238 SilcIDPayload idp = NULL;
5239 uint16 ident = silc_command_get_ident(cmd->payload);
5240 unsigned char *tmp, *pkdata;
5241 uint32 tmp_len, pklen;
5242 SilcBuffer pk = NULL;
5244 SilcPublicKey public_key;
5246 SILC_LOG_DEBUG(("Start"));
5248 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5251 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5254 idp = silc_id_payload_parse(tmp, tmp_len);
5256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5257 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5261 id_type = silc_id_payload_get_type(idp);
5262 if (id_type == SILC_ID_CLIENT) {
5263 client_id = silc_id_payload_get_id(idp);
5265 /* If the client is not found from local list there is no chance it
5266 would be locally connected client so send the command further. */
5267 client = silc_idlist_find_client_by_id(server->local_list,
5268 client_id, TRUE, NULL);
5270 client = silc_idlist_find_client_by_id(server->global_list,
5271 client_id, TRUE, NULL);
5273 if ((!client && !cmd->pending && !server->standalone) ||
5274 (client && !client->connection && !cmd->pending) ||
5275 (client && !client->data.public_key && !cmd->pending)) {
5278 SilcSocketConnection dest_sock;
5280 dest_sock = silc_server_get_client_route(server, NULL, 0,
5285 old_ident = silc_command_get_ident(cmd->payload);
5286 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5287 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5289 silc_server_packet_send(server, dest_sock,
5290 SILC_PACKET_COMMAND, cmd->packet->flags,
5291 tmpbuf->data, tmpbuf->len, TRUE);
5293 /* Reprocess this packet after received reply from router */
5294 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5295 silc_command_get_ident(cmd->payload),
5296 silc_server_command_getkey,
5297 silc_server_command_dup(cmd));
5298 cmd->pending = TRUE;
5299 silc_command_set_ident(cmd->payload, old_ident);
5300 silc_buffer_free(tmpbuf);
5305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5306 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5310 /* The client is locally connected, just get the public key and
5311 send it back. If they key does not exist then do not send it,
5312 send just OK reply */
5313 public_key = client->data.public_key;
5318 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5319 pk = silc_buffer_alloc(4 + tmp_len);
5320 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5321 silc_buffer_format(pk,
5322 SILC_STR_UI_SHORT(tmp_len),
5323 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5324 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5330 } else if (id_type == SILC_ID_SERVER) {
5331 server_id = silc_id_payload_get_id(idp);
5333 /* If the server is not found from local list there is no chance it
5334 would be locally connected server so send the command further. */
5335 server_entry = silc_idlist_find_server_by_id(server->local_list,
5336 server_id, TRUE, NULL);
5338 server_entry = silc_idlist_find_server_by_id(server->global_list,
5339 server_id, TRUE, NULL);
5341 if (server_entry != server->id_entry &&
5342 ((!server_entry && !cmd->pending && !server->standalone) ||
5343 (server_entry && !server_entry->connection && !cmd->pending &&
5344 !server->standalone) ||
5345 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5346 !server->standalone))) {
5350 old_ident = silc_command_get_ident(cmd->payload);
5351 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5352 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5354 silc_server_packet_send(server, server->router->connection,
5355 SILC_PACKET_COMMAND, cmd->packet->flags,
5356 tmpbuf->data, tmpbuf->len, TRUE);
5358 /* Reprocess this packet after received reply from router */
5359 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5360 silc_command_get_ident(cmd->payload),
5361 silc_server_command_getkey,
5362 silc_server_command_dup(cmd));
5363 cmd->pending = TRUE;
5364 silc_command_set_ident(cmd->payload, old_ident);
5365 silc_buffer_free(tmpbuf);
5369 if (!server_entry) {
5370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5371 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5375 /* If they key does not exist then do not send it, send just OK reply */
5376 public_key = (!server_entry->data.public_key ?
5377 (server_entry == server->id_entry ? server->public_key :
5378 NULL) : server_entry->data.public_key);
5383 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5384 pk = silc_buffer_alloc(4 + tmp_len);
5385 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5386 silc_buffer_format(pk,
5387 SILC_STR_UI_SHORT(tmp_len),
5388 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5389 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5399 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5400 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5401 SILC_STATUS_OK, ident,
5405 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5406 packet->data, packet->len, FALSE);
5407 silc_buffer_free(packet);
5410 silc_buffer_free(pk);
5414 silc_id_payload_free(idp);
5415 silc_free(client_id);
5416 silc_free(server_id);
5417 silc_server_command_free(cmd);