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);
163 silc_server_command_free(timeout->ctx);
168 /* Processes received command packet. */
170 void silc_server_command_process(SilcServer server,
171 SilcSocketConnection sock,
172 SilcPacketContext *packet)
174 SilcServerCommandContext ctx;
175 SilcServerCommand *cmd;
178 /* Allocate command context. This must be free'd by the
179 command routine receiving it. */
180 ctx = silc_server_command_alloc();
181 ctx->server = server;
182 ctx->sock = silc_socket_dup(sock);
183 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
185 /* Parse the command payload in the packet */
186 ctx->payload = silc_command_payload_parse(packet->buffer->data,
187 packet->buffer->len);
189 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
190 silc_buffer_free(packet->buffer);
191 silc_packet_context_free(packet);
192 silc_socket_free(ctx->sock);
196 ctx->args = silc_command_get_args(ctx->payload);
198 /* Get the command */
199 command = silc_command_get(ctx->payload);
200 for (cmd = silc_command_list; cmd->cb; cmd++)
201 if (cmd->cmd == command)
205 silc_server_command_send_status_reply(ctx, command,
206 SILC_STATUS_ERR_UNKNOWN_COMMAND);
207 silc_server_command_free(ctx);
211 /* Execute client's commands always with timeout. Normally they are
212 executed with zero (0) timeout but if client is sending command more
213 frequently than once in 2 seconds, then the timeout may be 0 to 2
215 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
216 SilcClientEntry client = (SilcClientEntry)sock->user_data;
217 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
223 if (client->last_command && (time(NULL) - client->last_command) < 2) {
224 client->fast_command++;
227 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
228 client->fast_command--);
232 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
233 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
234 silc_schedule_task_add(server->schedule, sock->sock,
235 silc_server_command_process_timeout,
237 2 - (time(NULL) - client->last_command), 0,
238 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
240 silc_schedule_task_add(server->schedule, sock->sock,
241 silc_server_command_process_timeout,
242 (void *)timeout, 0, 1,
243 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
247 /* Execute for server */
249 if (!(cmd->flags & SILC_CF_REG))
251 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
254 silc_server_command_free(ctx);
257 /* Allocate Command Context */
259 SilcServerCommandContext silc_server_command_alloc()
261 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
266 /* Free's the command context allocated before executing the command */
268 void silc_server_command_free(SilcServerCommandContext ctx)
271 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
273 if (ctx->users < 1) {
275 silc_command_payload_free(ctx->payload);
277 silc_packet_context_free(ctx->packet);
279 silc_socket_free(ctx->sock); /* Decrease reference counter */
284 /* Duplicate Command Context by adding reference counter. The context won't
285 be free'd untill it hits zero. */
287 SilcServerCommandContext
288 silc_server_command_dup(SilcServerCommandContext ctx)
291 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
296 /* Add new pending command to be executed when reply to a command has been
297 received. The `reply_cmd' is the command that will call the `callback'
298 with `context' when reply has been received. It can be SILC_COMMAND_NONE
299 to match any command with the `ident'. If `ident' is non-zero
300 the `callback' will be executed when received reply with command
301 identifier `ident'. If there already exists pending command for the
302 specified command, ident, callback and context this function has no
305 bool silc_server_command_pending(SilcServer server,
306 SilcCommand reply_cmd,
308 SilcCommandCb callback,
311 SilcServerCommandPending *reply;
313 /* Check whether identical pending already exists for same command,
314 ident, callback and callback context. If it does then it would be
315 error to register it again. */
316 silc_dlist_start(server->pending_commands);
317 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
318 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
319 reply->callback == callback && reply->context == context)
323 reply = silc_calloc(1, sizeof(*reply));
324 reply->reply_cmd = reply_cmd;
325 reply->ident = ident;
326 reply->context = context;
327 reply->callback = callback;
328 silc_dlist_add(server->pending_commands, reply);
333 /* Deletes pending command by reply command type. */
335 void silc_server_command_pending_del(SilcServer server,
336 SilcCommand reply_cmd,
339 SilcServerCommandPending *r;
341 silc_dlist_start(server->pending_commands);
342 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
343 if (r->reply_cmd == reply_cmd && r->ident == ident) {
344 silc_dlist_del(server->pending_commands, r);
350 /* Checks for pending commands and marks callbacks to be called from
351 the command reply function. Returns TRUE if there were pending command. */
353 SilcServerCommandPendingCallbacks
354 silc_server_command_pending_check(SilcServer server,
355 SilcServerCommandReplyContext ctx,
358 uint32 *callbacks_count)
360 SilcServerCommandPending *r;
361 SilcServerCommandPendingCallbacks callbacks = NULL;
364 silc_dlist_start(server->pending_commands);
365 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
366 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
367 && r->ident == ident) {
368 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
369 callbacks[i].context = r->context;
370 callbacks[i].callback = r->callback;
376 *callbacks_count = i;
380 /* Sends simple status message as command reply packet */
383 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
385 SilcCommandStatus status)
389 SILC_LOG_DEBUG(("Sending command status %d", status));
392 silc_command_reply_payload_encode_va(command, status,
393 silc_command_get_ident(cmd->payload),
395 silc_server_packet_send(cmd->server, cmd->sock,
396 SILC_PACKET_COMMAND_REPLY, 0,
397 buffer->data, buffer->len, FALSE);
398 silc_buffer_free(buffer);
401 /* Sends command status reply with one extra argument. The argument
402 type must be sent as argument. */
405 silc_server_command_send_status_data(SilcServerCommandContext cmd,
407 SilcCommandStatus status,
409 const unsigned char *arg,
414 SILC_LOG_DEBUG(("Sending command status %d", status));
417 silc_command_reply_payload_encode_va(command, status,
418 silc_command_get_ident(cmd->payload),
419 1, arg_type, arg, arg_len);
420 silc_server_packet_send(cmd->server, cmd->sock,
421 SILC_PACKET_COMMAND_REPLY, 0,
422 buffer->data, buffer->len, FALSE);
423 silc_buffer_free(buffer);
426 /* This function can be called to check whether in the command reply
427 an error occurred. This function has no effect if this is called
428 when the command function was not called as pending command callback.
429 This returns TRUE if error had occurred. */
432 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
433 SilcServerCommandReplyContext cmdr,
436 SilcCommandStatus status;
438 if (!cmd->pending || !cmdr)
441 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
442 if (status != SILC_STATUS_OK &&
443 status != SILC_STATUS_LIST_START &&
444 status != SILC_STATUS_LIST_ITEM &&
445 status != SILC_STATUS_LIST_END) {
448 /* Send the same command reply payload */
449 silc_command_set_ident(cmdr->payload,
450 silc_command_get_ident(cmd->payload));
451 buffer = silc_command_payload_encode_payload(cmdr->payload);
452 silc_server_packet_send(cmd->server, cmd->sock,
453 SILC_PACKET_COMMAND_REPLY, 0,
454 buffer->data, buffer->len, FALSE);
455 silc_buffer_free(buffer);
462 /******************************************************************************
466 ******************************************************************************/
469 silc_server_command_whois_parse(SilcServerCommandContext cmd,
470 SilcClientID ***client_id,
471 uint32 *client_id_count,
479 uint32 argc = silc_argument_get_arg_num(cmd->args);
482 /* If client ID is in the command it must be used instead of nickname */
483 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
485 /* No ID, get the nickname@server string and parse it. */
486 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
488 silc_parse_userfqdn(tmp, nickname, server_name);
490 silc_server_command_send_status_reply(cmd, command,
491 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
495 /* Command includes ID, we must use that. Also check whether the command
496 has more than one ID set - take them all. */
498 *client_id = silc_calloc(1, sizeof(**client_id));
499 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
500 if ((*client_id)[0] == NULL) {
501 silc_free(*client_id);
502 silc_server_command_send_status_reply(cmd, command,
503 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
506 *client_id_count = 1;
508 /* Take all ID's from the command packet */
510 for (k = 1, i = 1; i < argc; i++) {
511 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
513 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
514 (*client_id_count + 1));
515 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
516 if ((*client_id)[k] == NULL) {
517 /* Cleanup all and fail */
518 for (i = 0; i < *client_id_count; i++)
519 silc_free((*client_id)[i]);
520 silc_free(*client_id);
521 silc_server_command_send_status_reply(
523 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
526 (*client_id_count)++;
533 /* Get the max count of reply messages allowed */
534 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
543 /* Resolve context used by both WHOIS and IDENTIFY commands */
545 SilcServerEntry router;
547 unsigned char **res_argv;
548 uint32 *res_argv_lens;
549 uint32 *res_argv_types;
551 } *SilcServerResolveContext;
554 silc_server_command_whois_check(SilcServerCommandContext cmd,
555 SilcClientEntry *clients,
556 uint32 clients_count)
558 SilcServer server = cmd->server;
559 SilcClientEntry entry;
560 SilcServerResolveContext resolve = NULL, r = NULL;
561 uint32 resolve_count = 0;
565 SILC_LOG_DEBUG(("Start"));
567 for (i = 0; i < clients_count; i++) {
572 if ((entry->nickname && entry->username && entry->userinfo) ||
573 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
577 /* If we are normal server, and we've not resolved this client from
578 router and it is global client, we'll check whether it is on some
579 channel. If not then we cannot be sure about its validity, and
580 we'll resolve it from router. */
581 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
582 entry->connection || silc_hash_table_count(entry->channels))
586 /* We need to resolve this entry since it is not complete */
588 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
589 /* The entry is being resolved (and we are not the resolver) so attach
590 to the command reply and we're done with this one. */
591 silc_server_command_pending(server, SILC_COMMAND_NONE,
592 entry->resolve_cmd_ident,
593 silc_server_command_whois,
594 silc_server_command_dup(cmd));
597 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
598 /* We've resolved this and it still is not ready. We'll return
599 and are that this will be handled again after it is resolved. */
600 for (i = 0; i < resolve_count; i++) {
601 for (k = 0; k < r->res_argc; k++)
602 silc_free(r->res_argv[k]);
603 silc_free(r->res_argv);
604 silc_free(r->res_argv_lens);
605 silc_free(r->res_argv_types);
610 /* We'll resolve this client */
614 for (k = 0; k < resolve_count; k++) {
615 if (resolve[k].router == entry->router) {
622 resolve = silc_realloc(resolve, sizeof(*resolve) *
623 (resolve_count + 1));
624 r = &resolve[resolve_count];
625 memset(r, 0, sizeof(*r));
626 r->router = entry->router;
627 r->ident = ++server->cmd_ident;
631 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
633 r->res_argv_lens = silc_realloc(r->res_argv_lens,
634 sizeof(*r->res_argv_lens) *
636 r->res_argv_types = silc_realloc(r->res_argv_types,
637 sizeof(*r->res_argv_types) *
639 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
640 r->res_argv[r->res_argc] = silc_calloc(idp->len,
641 sizeof(**r->res_argv));
642 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
643 r->res_argv_lens[r->res_argc] = idp->len;
644 r->res_argv_types[r->res_argc] = r->res_argc + 3;
646 silc_buffer_free(idp);
648 entry->resolve_cmd_ident = r->ident;
649 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
650 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
655 /* Do the resolving */
656 for (i = 0; i < resolve_count; i++) {
661 /* Send WHOIS request. We send WHOIS since we're doing the requesting
662 now anyway so make it a good one. */
663 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
664 r->res_argc, r->res_argv,
668 silc_server_packet_send(server, r->router->connection,
669 SILC_PACKET_COMMAND, cmd->packet->flags,
670 res_cmd->data, res_cmd->len, FALSE);
672 /* Reprocess this packet after received reply */
673 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
675 silc_server_command_whois,
676 silc_server_command_dup(cmd));
679 silc_buffer_free(res_cmd);
680 for (k = 0; k < r->res_argc; k++)
681 silc_free(r->res_argv[k]);
682 silc_free(r->res_argv);
683 silc_free(r->res_argv_lens);
684 silc_free(r->res_argv_types);
693 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
694 SilcClientEntry *clients,
695 uint32 clients_count,
697 const char *nickname,
698 SilcClientID **client_ids)
700 SilcServer server = cmd->server;
702 int i, k, len, valid_count;
703 SilcBuffer packet, idp, channels;
704 SilcClientEntry entry;
705 SilcCommandStatus status;
706 uint16 ident = silc_command_get_ident(cmd->payload);
707 char nh[256], uh[256];
708 unsigned char idle[4], mode[4];
709 unsigned char *fingerprint;
710 SilcSocketConnection hsock;
712 /* Process only valid clients and ignore those that are not registered. */
714 for (i = 0; i < clients_count; i++) {
715 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
722 /* No valid clients found, send error reply */
724 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
725 SILC_STATUS_ERR_NO_SUCH_NICK,
726 3, nickname, strlen(nickname));
727 } else if (client_ids && client_ids[0]) {
728 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
729 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
730 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
731 2, idp->data, idp->len);
732 silc_buffer_free(idp);
737 /* Start processing found clients. */
739 status = SILC_STATUS_LIST_START;
741 status = SILC_STATUS_OK;
743 for (i = 0, k = 0; i < clients_count; i++) {
749 status = SILC_STATUS_LIST_ITEM;
750 if (valid_count > 1 && k == valid_count - 1)
751 status = SILC_STATUS_LIST_END;
752 if (count && k - 1 == count)
753 status = SILC_STATUS_LIST_END;
755 /* Send WHOIS reply */
756 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
757 tmp = silc_argument_get_first_arg(cmd->args, NULL);
759 memset(uh, 0, sizeof(uh));
760 memset(nh, 0, sizeof(nh));
761 memset(idle, 0, sizeof(idle));
763 strncat(nh, entry->nickname, strlen(entry->nickname));
764 if (!strchr(entry->nickname, '@')) {
766 if (entry->servername) {
767 strncat(nh, entry->servername, strlen(entry->servername));
769 len = entry->router ? strlen(entry->router->server_name) :
770 strlen(server->server_name);
771 strncat(nh, entry->router ? entry->router->server_name :
772 server->server_name, len);
776 strncat(uh, entry->username, strlen(entry->username));
777 if (!strchr(entry->username, '@')) {
779 hsock = (SilcSocketConnection)entry->connection;
780 len = strlen(hsock->hostname);
781 strncat(uh, hsock->hostname, len);
784 channels = silc_server_get_client_channel_list(server, entry);
786 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
787 fingerprint = entry->data.fingerprint;
791 SILC_PUT32_MSB(entry->mode, mode);
793 if (entry->connection) {
794 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
798 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
800 2, idp->data, idp->len,
804 strlen(entry->userinfo),
805 6, channels ? channels->data : NULL,
806 channels ? channels->len : 0,
810 fingerprint ? 20 : 0);
812 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
813 0, packet->data, packet->len, FALSE);
815 silc_buffer_free(packet);
816 silc_buffer_free(idp);
818 silc_buffer_free(channels);
825 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
827 SilcServer server = cmd->server;
831 old_ident = silc_command_get_ident(cmd->payload);
832 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
833 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
835 /* Send WHOIS command to our router */
836 silc_server_packet_send(server, (SilcSocketConnection)
837 server->router->connection,
838 SILC_PACKET_COMMAND, cmd->packet->flags,
839 tmpbuf->data, tmpbuf->len, TRUE);
841 /* Reprocess this packet after received reply from router */
842 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
843 silc_command_get_ident(cmd->payload),
844 silc_server_command_whois,
845 silc_server_command_dup(cmd));
847 silc_command_set_ident(cmd->payload, old_ident);
848 silc_buffer_free(tmpbuf);
852 silc_server_command_whois_process(SilcServerCommandContext cmd)
854 SilcServer server = cmd->server;
855 char *nick = NULL, *server_name = NULL;
857 SilcClientEntry *clients = NULL, entry;
858 SilcClientID **client_id = NULL;
859 uint32 client_id_count = 0, clients_count = 0;
861 bool check_global = FALSE;
863 /* Parse the whois request */
864 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
865 &nick, &server_name, &count,
869 /* Send the WHOIS request to the router only if it included nickname.
870 Since nicknames can be expanded into many clients we need to send it
871 to router. If the WHOIS included only client ID's we will check them
872 first locally since we just might have them. */
873 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
874 server->server_type == SILC_SERVER && !cmd->pending &&
875 !server->standalone) {
876 silc_server_command_whois_send_router(cmd);
881 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
883 else if (server->server_type != SILC_SERVER)
886 /* Get all clients matching that ID or nickname from local list */
887 if (client_id_count) {
888 /* Check all Client ID's received in the command packet */
889 for (i = 0; i < client_id_count; i++) {
890 entry = silc_idlist_find_client_by_id(server->local_list,
891 client_id[i], TRUE, NULL);
892 if (!entry && check_global)
893 entry = silc_idlist_find_client_by_id(server->global_list,
894 client_id[i], TRUE, NULL);
896 clients = silc_realloc(clients, sizeof(*clients) *
897 (clients_count + 1));
898 clients[clients_count++] = entry;
900 /* If we are normal server and did not send the request first to router
901 do it now, since we do not have the Client ID information. */
902 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
903 server->server_type == SILC_SERVER && !cmd->pending &&
904 !server->standalone) {
905 silc_server_command_whois_send_router(cmd);
912 /* Find by nickname */
913 if (!silc_idlist_get_clients_by_hash(server->local_list,
914 nick, server->md5hash,
915 &clients, &clients_count))
916 silc_idlist_get_clients_by_nickname(server->local_list,
918 &clients, &clients_count);
920 if (!silc_idlist_get_clients_by_hash(server->global_list,
921 nick, server->md5hash,
922 &clients, &clients_count))
923 silc_idlist_get_clients_by_nickname(server->global_list,
925 &clients, &clients_count);
930 /* If we are normal server and did not send the request first to router
931 do it now, since we do not have the information. */
932 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
933 server->server_type == SILC_SERVER && !cmd->pending &&
934 !server->standalone) {
935 silc_server_command_whois_send_router(cmd);
940 /* Such client(s) really does not exist in the SILC network. */
941 if (!client_id_count) {
942 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
943 SILC_STATUS_ERR_NO_SUCH_NICK,
944 3, nick, strlen(nick));
946 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
947 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
948 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
949 2, idp->data, idp->len);
950 silc_buffer_free(idp);
955 /* Router always finds the client entry if it exists in the SILC network.
956 However, it might be incomplete entry and does not include all the
957 mandatory fields that WHOIS command reply requires. Check for these and
958 make query from the server who owns the client if some fields are
960 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
965 /* Send the command reply */
966 silc_server_command_whois_send_reply(cmd, clients, clients_count,
967 count, nick, client_id);
970 if (client_id_count) {
971 for (i = 0; i < client_id_count; i++)
972 silc_free(client_id[i]);
973 silc_free(client_id);
977 silc_free(server_name);
982 /* Server side of command WHOIS. Processes user's query and sends found
983 results as command replies back to the client. */
985 SILC_SERVER_CMD_FUNC(whois)
987 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
990 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
992 ret = silc_server_command_whois_process(cmd);
993 silc_server_command_free(cmd);
996 /******************************************************************************
1000 ******************************************************************************/
1003 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1011 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1014 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1018 /* Get the nickname@server string and parse it. */
1019 silc_parse_userfqdn(tmp, nickname, server_name);
1021 /* Get the max count of reply messages allowed */
1022 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1032 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1033 SilcClientEntry *clients,
1034 uint32 clients_count)
1036 SilcServer server = cmd->server;
1038 SilcClientEntry entry;
1040 for (i = 0; i < clients_count; i++) {
1043 if (!entry->nickname || !entry->username) {
1050 old_ident = silc_command_get_ident(cmd->payload);
1051 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1052 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1054 /* Send WHOWAS command */
1055 silc_server_packet_send(server, entry->router->connection,
1056 SILC_PACKET_COMMAND, cmd->packet->flags,
1057 tmpbuf->data, tmpbuf->len, TRUE);
1059 /* Reprocess this packet after received reply */
1060 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1061 silc_command_get_ident(cmd->payload),
1062 silc_server_command_whowas,
1063 silc_server_command_dup(cmd));
1064 cmd->pending = TRUE;
1065 silc_command_set_ident(cmd->payload, old_ident);
1067 silc_buffer_free(tmpbuf);
1076 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1077 SilcClientEntry *clients,
1078 uint32 clients_count)
1080 SilcServer server = cmd->server;
1082 int i, count = 0, len;
1083 SilcBuffer packet, idp;
1084 SilcClientEntry entry = NULL;
1085 SilcCommandStatus status;
1086 uint16 ident = silc_command_get_ident(cmd->payload);
1088 char nh[256], uh[256];
1090 status = SILC_STATUS_OK;
1091 if (clients_count > 1)
1092 status = SILC_STATUS_LIST_START;
1094 for (i = 0; i < clients_count; i++) {
1097 /* We will take only clients that are not valid anymore. They are the
1098 ones that are not registered anymore but still have a ID. They
1099 have disconnected us, and thus valid for WHOWAS. */
1100 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1103 if (count && i - 1 == count)
1108 if (clients_count > 2)
1109 status = SILC_STATUS_LIST_ITEM;
1110 if (clients_count > 1 && i == clients_count - 1)
1111 status = SILC_STATUS_LIST_END;
1113 /* Send WHOWAS reply */
1114 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1115 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1116 memset(uh, 0, sizeof(uh));
1117 memset(nh, 0, sizeof(nh));
1119 strncat(nh, entry->nickname, strlen(entry->nickname));
1120 if (!strchr(entry->nickname, '@')) {
1121 strncat(nh, "@", 1);
1122 if (entry->servername) {
1123 strncat(nh, entry->servername, strlen(entry->servername));
1125 len = entry->router ? strlen(entry->router->server_name) :
1126 strlen(server->server_name);
1127 strncat(nh, entry->router ? entry->router->server_name :
1128 server->server_name, len);
1132 strncat(uh, entry->username, strlen(entry->username));
1133 if (!strchr(entry->username, '@')) {
1134 strncat(uh, "@", 1);
1135 strcat(uh, "*private*");
1139 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1141 2, idp->data, idp->len,
1146 strlen(entry->userinfo) : 0);
1147 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1148 0, packet->data, packet->len, FALSE);
1150 silc_buffer_free(packet);
1151 silc_buffer_free(idp);
1154 if (found == FALSE && entry)
1155 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1156 SILC_STATUS_ERR_NO_SUCH_NICK,
1158 strlen(entry->nickname));
1162 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1164 SilcServer server = cmd->server;
1165 char *nick = NULL, *server_name = NULL;
1167 SilcClientEntry *clients = NULL;
1168 uint32 clients_count = 0;
1170 bool check_global = FALSE;
1172 /* Protocol dictates that we must always send the received WHOWAS request
1173 to our router if we are normal server, so let's do it now unless we
1174 are standalone. We will not send any replies to the client until we
1175 have received reply from the router. */
1176 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1177 server->server_type == SILC_SERVER && !cmd->pending &&
1178 !server->standalone) {
1182 old_ident = silc_command_get_ident(cmd->payload);
1183 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1184 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1186 /* Send WHOWAS command to our router */
1187 silc_server_packet_send(server, (SilcSocketConnection)
1188 server->router->connection,
1189 SILC_PACKET_COMMAND, cmd->packet->flags,
1190 tmpbuf->data, tmpbuf->len, TRUE);
1192 /* Reprocess this packet after received reply from router */
1193 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1194 silc_command_get_ident(cmd->payload),
1195 silc_server_command_whowas,
1196 silc_server_command_dup(cmd));
1197 cmd->pending = TRUE;
1198 silc_command_set_ident(cmd->payload, old_ident);
1200 silc_buffer_free(tmpbuf);
1205 /* We are ready to process the command request. Let's search for the
1206 requested client and send reply to the requesting client. */
1208 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1209 check_global = TRUE;
1210 else if (server->server_type != SILC_SERVER)
1211 check_global = TRUE;
1213 /* Parse the whowas request */
1214 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1217 /* Get all clients matching that nickname from local list */
1218 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1220 &clients, &clients_count))
1221 silc_idlist_get_clients_by_hash(server->local_list,
1222 nick, server->md5hash,
1223 &clients, &clients_count);
1225 /* Check global list as well */
1227 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1229 &clients, &clients_count))
1230 silc_idlist_get_clients_by_hash(server->global_list,
1231 nick, server->md5hash,
1232 &clients, &clients_count);
1236 /* Such a client really does not exist in the SILC network. */
1237 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1238 SILC_STATUS_ERR_NO_SUCH_NICK,
1239 3, nick, strlen(nick));
1243 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1248 /* Send the command reply to the client */
1249 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1254 silc_free(server_name);
1258 /* Server side of command WHOWAS. */
1260 SILC_SERVER_CMD_FUNC(whowas)
1262 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1265 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1267 ret = silc_server_command_whowas_process(cmd);
1268 silc_server_command_free(cmd);
1271 /******************************************************************************
1275 ******************************************************************************/
1278 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1280 SilcServer server = cmd->server;
1284 old_ident = silc_command_get_ident(cmd->payload);
1285 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1286 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1288 /* Send IDENTIFY command to our router */
1289 silc_server_packet_send(server, (SilcSocketConnection)
1290 server->router->connection,
1291 SILC_PACKET_COMMAND, cmd->packet->flags,
1292 tmpbuf->data, tmpbuf->len, TRUE);
1294 /* Reprocess this packet after received reply from router */
1295 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1296 silc_command_get_ident(cmd->payload),
1297 silc_server_command_identify,
1298 silc_server_command_dup(cmd));
1299 cmd->pending = TRUE;
1300 silc_command_set_ident(cmd->payload, old_ident);
1301 silc_buffer_free(tmpbuf);
1305 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1306 SilcClientEntry **clients,
1307 uint32 *clients_count,
1308 SilcServerEntry **servers,
1309 uint32 *servers_count,
1310 SilcChannelEntry **channels,
1311 uint32 *channels_count,
1314 SilcServer server = cmd->server;
1317 uint32 argc = silc_argument_get_arg_num(cmd->args);
1319 bool check_global = FALSE;
1324 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1325 check_global = TRUE;
1326 else if (server->server_type != SILC_SERVER)
1327 check_global = TRUE;
1329 /* If ID Payload is in the command it must be used instead of names */
1330 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1332 /* No ID, get the names. */
1334 /* If we are normal server and have not resolved information from
1335 router yet, do so now. */
1336 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1337 server->server_type == SILC_SERVER && !cmd->pending &&
1338 !server->standalone) {
1339 silc_server_command_identify_send_router(cmd);
1343 /* Try to get nickname@server. */
1344 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1347 char *nick_server = NULL;
1349 silc_parse_userfqdn(tmp, &nick, &nick_server);
1351 if (!silc_idlist_get_clients_by_hash(server->local_list,
1352 nick, server->md5hash,
1353 clients, clients_count))
1354 silc_idlist_get_clients_by_nickname(server->local_list,
1356 clients, clients_count);
1358 if (!silc_idlist_get_clients_by_hash(server->global_list,
1359 nick, server->md5hash,
1360 clients, clients_count))
1361 silc_idlist_get_clients_by_nickname(server->global_list,
1363 clients, clients_count);
1367 silc_free(nick_server);
1370 /* the nickname does not exist, send error reply */
1371 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1372 SILC_STATUS_ERR_NO_SUCH_NICK,
1373 3, tmp, strlen(tmp));
1378 /* Try to get server name */
1379 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1381 entry = silc_idlist_find_server_by_name(server->local_list,
1383 if (!entry && check_global)
1384 entry = silc_idlist_find_server_by_name(server->global_list,
1387 *servers = silc_realloc(*servers, sizeof(**servers) *
1388 (*servers_count + 1));
1389 (*servers)[(*servers_count)++] = entry;
1393 /* the server does not exist, send error reply */
1394 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1395 SILC_STATUS_ERR_NO_SUCH_SERVER,
1396 3, tmp, strlen(tmp));
1401 /* Try to get channel name */
1402 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1404 entry = silc_idlist_find_channel_by_name(server->local_list,
1406 if (!entry && check_global)
1407 entry = silc_idlist_find_channel_by_name(server->global_list,
1410 *channels = silc_realloc(*channels, sizeof(**channels) *
1411 (*channels_count + 1));
1412 (*channels)[(*channels_count)++] = entry;
1416 /* The channel does not exist, send error reply */
1417 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1418 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1419 3, tmp, strlen(tmp));
1424 if (!(*clients) && !(*servers) && !(*channels)) {
1425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1426 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1430 /* Command includes ID, we must use that. Also check whether the command
1431 has more than one ID set - take them all. */
1433 /* Take all ID's from the command packet */
1434 for (i = 0; i < argc; i++) {
1437 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1441 idp = silc_id_payload_parse(tmp, len);
1443 silc_free(*clients);
1444 silc_free(*servers);
1445 silc_free(*channels);
1446 silc_server_command_send_status_reply(
1447 cmd, SILC_COMMAND_IDENTIFY,
1448 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1452 id = silc_id_payload_get_id(idp);
1454 switch (silc_id_payload_get_type(idp)) {
1456 case SILC_ID_CLIENT:
1457 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1459 if (!entry && check_global)
1460 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1463 *clients = silc_realloc(*clients, sizeof(**clients) *
1464 (*clients_count + 1));
1465 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1467 /* If we are normal server and have not resolved information from
1468 router yet, do so now. */
1469 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1470 server->server_type == SILC_SERVER && !cmd->pending &&
1471 !server->standalone) {
1472 silc_server_command_identify_send_router(cmd);
1473 silc_free(*clients);
1474 silc_free(*servers);
1475 silc_free(*channels);
1478 silc_server_command_send_status_data(
1479 cmd, SILC_COMMAND_IDENTIFY,
1480 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1488 case SILC_ID_SERVER:
1489 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1491 if (!entry && check_global)
1492 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1495 *servers = silc_realloc(*servers, sizeof(**servers) *
1496 (*servers_count + 1));
1497 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1499 /* If we are normal server and have not resolved information from
1500 router yet, do so now. */
1501 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1502 server->server_type == SILC_SERVER && !cmd->pending &&
1503 !server->standalone) {
1504 silc_server_command_identify_send_router(cmd);
1505 silc_free(*clients);
1506 silc_free(*servers);
1507 silc_free(*channels);
1510 silc_server_command_send_status_data(
1511 cmd, SILC_COMMAND_IDENTIFY,
1512 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1519 case SILC_ID_CHANNEL:
1520 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1522 if (!entry && check_global)
1523 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1526 *channels = silc_realloc(*channels, sizeof(**channels) *
1527 (*channels_count + 1));
1528 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1530 /* If we are normal server and have not resolved information from
1531 router yet, do so now. */
1532 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1533 server->server_type == SILC_SERVER && !cmd->pending &&
1534 !server->standalone) {
1535 silc_server_command_identify_send_router(cmd);
1536 silc_free(*clients);
1537 silc_free(*servers);
1538 silc_free(*channels);
1541 silc_server_command_send_status_data(
1542 cmd, SILC_COMMAND_IDENTIFY,
1543 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1556 silc_free(*clients);
1557 silc_free(*servers);
1558 silc_free(*channels);
1562 /* Get the max count of reply messages allowed */
1563 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1572 /* Checks that all mandatory fields in client entry are present. If not
1573 then send WHOIS request to the server who owns the client. We use
1574 WHOIS because we want to get as much information as possible at once. */
1577 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1578 SilcClientEntry *clients,
1579 uint32 clients_count)
1581 SilcServer server = cmd->server;
1582 SilcClientEntry entry;
1583 SilcServerResolveContext resolve = NULL, r = NULL;
1584 uint32 resolve_count = 0;
1588 for (i = 0; i < clients_count; i++) {
1593 if (entry->nickname ||
1594 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1598 /* If we are normal server, and we've not resolved this client from
1599 router and it is global client, we'll check whether it is on some
1600 channel. If not then we cannot be sure about its validity, and
1601 we'll resolve it from router. */
1602 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1603 entry->connection || silc_hash_table_count(entry->channels))
1607 /* We need to resolve this entry since it is not complete */
1609 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1610 /* The entry is being resolved (and we are not the resolver) so attach
1611 to the command reply and we're done with this one. */
1612 silc_server_command_pending(server, SILC_COMMAND_NONE,
1613 entry->resolve_cmd_ident,
1614 silc_server_command_identify,
1615 silc_server_command_dup(cmd));
1618 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1619 /* We've resolved this and it still is not ready. We'll return
1620 and are that this will be handled again after it is resolved. */
1621 for (i = 0; i < resolve_count; i++) {
1622 for (k = 0; k < r->res_argc; k++)
1623 silc_free(r->res_argv[k]);
1624 silc_free(r->res_argv);
1625 silc_free(r->res_argv_lens);
1626 silc_free(r->res_argv_types);
1631 /* We'll resolve this client */
1635 for (k = 0; k < resolve_count; k++) {
1636 if (resolve[k].router == entry->router) {
1643 resolve = silc_realloc(resolve, sizeof(*resolve) *
1644 (resolve_count + 1));
1645 r = &resolve[resolve_count];
1646 memset(r, 0, sizeof(*r));
1647 r->router = entry->router;
1648 r->ident = ++server->cmd_ident;
1652 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1654 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1655 sizeof(*r->res_argv_lens) *
1657 r->res_argv_types = silc_realloc(r->res_argv_types,
1658 sizeof(*r->res_argv_types) *
1660 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1661 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1662 sizeof(**r->res_argv));
1663 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1664 r->res_argv_lens[r->res_argc] = idp->len;
1665 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1667 silc_buffer_free(idp);
1669 entry->resolve_cmd_ident = r->ident;
1670 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1671 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1676 /* Do the resolving */
1677 for (i = 0; i < resolve_count; i++) {
1682 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1683 now anyway so make it a good one. */
1684 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1685 r->res_argc, r->res_argv,
1689 silc_server_packet_send(server, r->router->connection,
1690 SILC_PACKET_COMMAND, cmd->packet->flags,
1691 res_cmd->data, res_cmd->len, FALSE);
1693 /* Reprocess this packet after received reply */
1694 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1696 silc_server_command_identify,
1697 silc_server_command_dup(cmd));
1698 cmd->pending = TRUE;
1700 silc_buffer_free(res_cmd);
1701 for (k = 0; k < r->res_argc; k++)
1702 silc_free(r->res_argv[k]);
1703 silc_free(r->res_argv);
1704 silc_free(r->res_argv_lens);
1705 silc_free(r->res_argv_types);
1714 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1715 SilcClientEntry *clients,
1716 uint32 clients_count,
1717 SilcServerEntry *servers,
1718 uint32 servers_count,
1719 SilcChannelEntry *channels,
1720 uint32 channels_count,
1723 SilcServer server = cmd->server;
1724 int i, k, len, valid_count;
1725 SilcBuffer packet, idp;
1726 SilcCommandStatus status;
1727 uint16 ident = silc_command_get_ident(cmd->payload);
1728 char nh[256], uh[256];
1729 SilcSocketConnection hsock;
1731 status = SILC_STATUS_OK;
1734 SilcClientEntry entry;
1736 /* Process only valid entries. */
1738 for (i = 0; i < clients_count; i++) {
1739 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1746 /* No valid entries found at all, just send error */
1749 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1751 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1752 SILC_STATUS_ERR_NO_SUCH_NICK,
1753 3, tmp, strlen(tmp));
1755 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1756 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1757 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1763 /* Process all valid client entries and send command replies */
1765 if (valid_count > 1)
1766 status = SILC_STATUS_LIST_START;
1768 for (i = 0, k = 0; i < clients_count; i++) {
1774 status = SILC_STATUS_LIST_ITEM;
1775 if (valid_count > 1 && k == valid_count - 1
1776 && !servers_count && !channels_count)
1777 status = SILC_STATUS_LIST_END;
1778 if (count && k - 1 == count)
1779 status = SILC_STATUS_LIST_END;
1780 if (count && k - 1 > count)
1783 /* Send IDENTIFY reply */
1785 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1786 memset(uh, 0, sizeof(uh));
1787 memset(nh, 0, sizeof(nh));
1788 strncat(nh, entry->nickname, strlen(entry->nickname));
1789 if (!strchr(entry->nickname, '@')) {
1790 strncat(nh, "@", 1);
1791 if (entry->servername) {
1792 strncat(nh, entry->servername, strlen(entry->servername));
1794 len = entry->router ? strlen(entry->router->server_name) :
1795 strlen(server->server_name);
1796 strncat(nh, entry->router ? entry->router->server_name :
1797 server->server_name, len);
1801 if (!entry->username) {
1802 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1804 2, idp->data, idp->len,
1807 strncat(uh, entry->username, strlen(entry->username));
1808 if (!strchr(entry->username, '@')) {
1809 strncat(uh, "@", 1);
1810 hsock = (SilcSocketConnection)entry->connection;
1811 len = strlen(hsock->hostname);
1812 strncat(uh, hsock->hostname, len);
1815 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1817 2, idp->data, idp->len,
1822 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1823 0, packet->data, packet->len, FALSE);
1825 silc_buffer_free(packet);
1826 silc_buffer_free(idp);
1833 SilcServerEntry entry;
1835 if (status == SILC_STATUS_OK && servers_count > 1)
1836 status = SILC_STATUS_LIST_START;
1838 for (i = 0, k = 0; i < servers_count; i++) {
1842 status = SILC_STATUS_LIST_ITEM;
1843 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1844 status = SILC_STATUS_LIST_END;
1845 if (count && k - 1 == count)
1846 status = SILC_STATUS_LIST_END;
1847 if (count && k - 1 > count)
1850 /* Send IDENTIFY reply */
1851 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1853 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1855 2, idp->data, idp->len,
1856 3, entry->server_name,
1857 entry->server_name ?
1858 strlen(entry->server_name) : 0);
1859 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1860 0, packet->data, packet->len, FALSE);
1862 silc_buffer_free(packet);
1863 silc_buffer_free(idp);
1870 SilcChannelEntry entry;
1872 if (status == SILC_STATUS_OK && channels_count > 1)
1873 status = SILC_STATUS_LIST_START;
1875 for (i = 0, k = 0; i < channels_count; i++) {
1876 entry = channels[i];
1879 status = SILC_STATUS_LIST_ITEM;
1880 if (channels_count > 1 && k == channels_count - 1)
1881 status = SILC_STATUS_LIST_END;
1882 if (count && k - 1 == count)
1883 status = SILC_STATUS_LIST_END;
1884 if (count && k - 1 > count)
1887 /* Send IDENTIFY reply */
1888 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1890 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1892 2, idp->data, idp->len,
1893 3, entry->channel_name,
1894 entry->channel_name ?
1895 strlen(entry->channel_name): 0);
1896 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1897 0, packet->data, packet->len, FALSE);
1899 silc_buffer_free(packet);
1900 silc_buffer_free(idp);
1908 silc_server_command_identify_process(SilcServerCommandContext cmd)
1912 SilcClientEntry *clients = NULL;
1913 SilcServerEntry *servers = NULL;
1914 SilcChannelEntry *channels = NULL;
1915 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1917 /* Parse the IDENTIFY request */
1918 ret = silc_server_command_identify_parse(cmd,
1919 &clients, &clients_count,
1920 &servers, &servers_count,
1921 &channels, &channels_count,
1927 /* Check that all mandatory fields are present and request those data
1928 from the server who owns the client if necessary. */
1929 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1935 /* Send the command reply to the client */
1936 silc_server_command_identify_send_reply(cmd,
1937 clients, clients_count,
1938 servers, servers_count,
1939 channels, channels_count,
1945 silc_free(channels);
1949 SILC_SERVER_CMD_FUNC(identify)
1951 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1954 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1956 ret = silc_server_command_identify_process(cmd);
1957 silc_server_command_free(cmd);
1960 /* Server side of command NICK. Sets nickname for user. Setting
1961 nickname causes generation of a new client ID for the client. The
1962 new client ID is sent to the client after changing the nickname. */
1964 SILC_SERVER_CMD_FUNC(nick)
1966 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1967 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1968 SilcServer server = cmd->server;
1969 SilcBuffer packet, nidp, oidp = NULL;
1970 SilcClientID *new_id;
1973 uint16 ident = silc_command_get_ident(cmd->payload);
1976 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1979 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1981 /* Check nickname */
1982 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
1985 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
1986 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1987 SILC_STATUS_ERR_BAD_NICKNAME);
1991 /* Check for same nickname */
1992 if (!strcmp(client->nickname, nick)) {
1993 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1997 /* Create new Client ID */
1998 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2000 cmd->server->md5hash, nick,
2003 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2006 /* Send notify about nickname change to our router. We send the new
2007 ID and ask to replace it with the old one. If we are router the
2008 packet is broadcasted. Send NICK_CHANGE notify. */
2009 if (!server->standalone)
2010 silc_server_send_notify_nick_change(server, server->router->connection,
2011 server->server_type == SILC_SERVER ?
2012 FALSE : TRUE, client->id,
2015 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2017 /* Remove old cache entry */
2018 silc_idcache_del_by_context(server->local_list->clients, client);
2021 silc_free(client->id);
2023 /* Save the nickname as this client is our local client */
2024 silc_free(client->nickname);
2026 client->nickname = strdup(nick);
2027 client->id = new_id;
2029 /* Update client cache */
2030 silc_idcache_add(server->local_list->clients, client->nickname,
2031 client->id, (void *)client, 0, NULL);
2033 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2035 /* Send NICK_CHANGE notify to the client's channels */
2036 silc_server_send_notify_on_channels(server, NULL, client,
2037 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2038 oidp->data, oidp->len,
2039 nidp->data, nidp->len);
2042 /* Send the new Client ID as reply command back to client */
2043 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2044 SILC_STATUS_OK, ident, 1,
2045 2, nidp->data, nidp->len);
2046 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2047 0, packet->data, packet->len, FALSE);
2049 silc_buffer_free(packet);
2050 silc_buffer_free(nidp);
2052 silc_buffer_free(oidp);
2055 silc_server_command_free(cmd);
2058 /* Sends the LIST command reply */
2061 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2062 SilcChannelEntry *lch,
2064 SilcChannelEntry *gch,
2068 SilcBuffer packet, idp;
2069 SilcChannelEntry entry;
2070 SilcCommandStatus status;
2071 uint16 ident = silc_command_get_ident(cmd->payload);
2073 unsigned char usercount[4];
2075 int valid_lcount = 0, valid_rcount = 0;
2077 for (i = 0; i < lch_count; i++) {
2078 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2083 for (i = 0; i < gch_count; i++) {
2084 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2090 status = SILC_STATUS_OK;
2091 if ((lch_count + gch_count) > 1)
2092 status = SILC_STATUS_LIST_START;
2095 for (i = 0, k = 0; i < lch_count; i++) {
2101 status = SILC_STATUS_LIST_ITEM;
2102 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2103 status = SILC_STATUS_LIST_END;
2105 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2107 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2108 topic = "*private*";
2109 memset(usercount, 0, sizeof(usercount));
2111 topic = entry->topic;
2112 users = silc_hash_table_count(entry->user_list);
2113 SILC_PUT32_MSB(users, usercount);
2116 /* Send the reply */
2118 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2120 2, idp->data, idp->len,
2121 3, entry->channel_name,
2122 strlen(entry->channel_name),
2123 4, topic, topic ? strlen(topic) : 0,
2125 silc_server_packet_send(cmd->server, cmd->sock,
2126 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2127 packet->len, FALSE);
2128 silc_buffer_free(packet);
2129 silc_buffer_free(idp);
2134 for (i = 0, k = 0; i < gch_count; i++) {
2140 status = SILC_STATUS_LIST_ITEM;
2141 if (valid_rcount > 1 && k == valid_rcount - 1)
2142 status = SILC_STATUS_LIST_END;
2144 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2146 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2147 topic = "*private*";
2148 memset(usercount, 0, sizeof(usercount));
2150 topic = entry->topic;
2151 users = silc_hash_table_count(entry->user_list);
2152 SILC_PUT32_MSB(users, usercount);
2155 /* Send the reply */
2157 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2159 2, idp->data, idp->len,
2160 3, entry->channel_name,
2161 strlen(entry->channel_name),
2162 4, topic, topic ? strlen(topic) : 0,
2164 silc_server_packet_send(cmd->server, cmd->sock,
2165 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2166 packet->len, FALSE);
2167 silc_buffer_free(packet);
2168 silc_buffer_free(idp);
2173 /* Server side of LIST command. This lists the channel of the requested
2174 server. Secret channels are not listed. */
2176 SILC_SERVER_CMD_FUNC(list)
2178 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2179 SilcServer server = cmd->server;
2180 SilcChannelID *channel_id = NULL;
2183 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2184 uint32 lch_count = 0, gch_count = 0;
2186 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2188 /* If we are normal server, send the command to router, since we
2189 want to know all channels in the network. */
2190 if (!cmd->pending && server->server_type == SILC_SERVER &&
2191 !server->standalone) {
2195 old_ident = silc_command_get_ident(cmd->payload);
2196 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2197 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2198 silc_server_packet_send(server, server->router->connection,
2199 SILC_PACKET_COMMAND, cmd->packet->flags,
2200 tmpbuf->data, tmpbuf->len, TRUE);
2202 /* Reprocess this packet after received reply from router */
2203 silc_server_command_pending(server, SILC_COMMAND_LIST,
2204 silc_command_get_ident(cmd->payload),
2205 silc_server_command_list,
2206 silc_server_command_dup(cmd));
2207 cmd->pending = TRUE;
2208 silc_command_set_ident(cmd->payload, old_ident);
2209 silc_buffer_free(tmpbuf);
2213 /* Get Channel ID */
2214 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2216 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2219 SILC_STATUS_ERR_NO_CHANNEL_ID);
2224 /* Get the channels from local list */
2225 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2228 /* Get the channels from global list */
2229 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2232 /* Send the reply */
2233 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2234 gchannels, gch_count);
2236 silc_free(lchannels);
2237 silc_free(gchannels);
2240 silc_server_command_free(cmd);
2243 /* Server side of TOPIC command. Sets topic for channel and/or returns
2244 current topic to client. */
2246 SILC_SERVER_CMD_FUNC(topic)
2248 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2249 SilcServer server = cmd->server;
2250 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2251 SilcChannelID *channel_id;
2252 SilcChannelEntry channel;
2253 SilcChannelClientEntry chl;
2254 SilcBuffer packet, idp;
2256 uint32 argc, tmp_len;
2257 uint16 ident = silc_command_get_ident(cmd->payload);
2259 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2261 argc = silc_argument_get_arg_num(cmd->args);
2263 /* Get Channel ID */
2264 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2267 SILC_STATUS_ERR_NO_CHANNEL_ID);
2270 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2273 SILC_STATUS_ERR_NO_CHANNEL_ID);
2277 /* Check whether the channel exists */
2278 channel = silc_idlist_find_channel_by_id(server->local_list,
2281 channel = silc_idlist_find_channel_by_id(server->global_list,
2284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2285 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2292 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2295 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2299 if (strlen(tmp) > 256) {
2300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2301 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2305 /* See whether the client is on channel and has rights to change topic */
2306 if (!silc_hash_table_find(channel->user_list, client, NULL,
2308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2309 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2313 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2314 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2316 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2321 /* Set the topic for channel */
2322 silc_free(channel->topic);
2323 channel->topic = strdup(tmp);
2325 /* Send TOPIC_SET notify type to the network */
2326 if (!server->standalone)
2327 silc_server_send_notify_topic_set(server, server->router->connection,
2328 server->server_type == SILC_ROUTER ?
2329 TRUE : FALSE, channel,
2330 client->id, SILC_ID_CLIENT,
2333 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2335 /* Send notify about topic change to all clients on the channel */
2336 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2337 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2338 idp->data, idp->len,
2339 channel->topic, strlen(channel->topic));
2340 silc_buffer_free(idp);
2343 /* Send the topic to client as reply packet */
2344 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2345 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2346 SILC_STATUS_OK, ident, 2,
2347 2, idp->data, idp->len,
2350 strlen(channel->topic) : 0);
2351 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2352 0, packet->data, packet->len, FALSE);
2354 silc_buffer_free(packet);
2355 silc_buffer_free(idp);
2356 silc_free(channel_id);
2359 silc_server_command_free(cmd);
2362 /* Server side of INVITE command. Invites some client to join some channel.
2363 This command is also used to manage the invite list of the channel. */
2365 SILC_SERVER_CMD_FUNC(invite)
2367 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2368 SilcServer server = cmd->server;
2369 SilcSocketConnection sock = cmd->sock, dest_sock;
2370 SilcChannelClientEntry chl;
2371 SilcClientEntry sender, dest;
2372 SilcClientID *dest_id = NULL;
2373 SilcChannelEntry channel;
2374 SilcChannelID *channel_id = NULL;
2375 SilcIDListData idata;
2376 SilcBuffer idp, idp2, packet;
2377 unsigned char *tmp, *add, *del;
2379 uint16 ident = silc_command_get_ident(cmd->payload);
2381 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2383 /* Get Channel ID */
2384 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2387 SILC_STATUS_ERR_NO_CHANNEL_ID);
2390 channel_id = silc_id_payload_parse_id(tmp, len);
2392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2393 SILC_STATUS_ERR_NO_CHANNEL_ID);
2397 /* Get the channel entry */
2398 channel = silc_idlist_find_channel_by_id(server->local_list,
2401 channel = silc_idlist_find_channel_by_id(server->global_list,
2404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2405 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2410 /* Check whether the sender of this command is on the channel. */
2411 sender = (SilcClientEntry)sock->user_data;
2412 if (!silc_server_client_on_channel(sender, channel)) {
2413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2414 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2418 /* Check whether the channel is invite-only channel. If yes then the
2419 sender of this command must be at least channel operator. */
2420 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2421 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2422 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2424 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2429 /* Get destination client ID */
2430 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2435 dest_id = silc_id_payload_parse_id(tmp, len);
2437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2438 SILC_STATUS_ERR_NO_CLIENT_ID);
2442 /* Get the client entry */
2443 dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2445 if (server->server_type != SILC_SERVER || !resolve) {
2446 silc_server_command_send_status_reply(
2447 cmd, SILC_COMMAND_INVITE,
2448 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2452 /* The client info is being resolved. Reprocess this packet after
2453 receiving the reply to the query. */
2454 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2456 silc_server_command_invite,
2457 silc_server_command_dup(cmd));
2458 cmd->pending = TRUE;
2459 silc_free(channel_id);
2464 /* Check whether the requested client is already on the channel. */
2465 if (silc_server_client_on_channel(dest, channel)) {
2466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2467 SILC_STATUS_ERR_USER_ON_CHANNEL);
2471 /* Get route to the client */
2472 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2475 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2479 memset(invite, 0, sizeof(invite));
2480 strncat(invite, dest->nickname, strlen(dest->nickname));
2481 strncat(invite, "!", 1);
2482 strncat(invite, dest->username, strlen(dest->username));
2483 if (!strchr(dest->username, '@')) {
2484 strncat(invite, "@", 1);
2485 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2488 len = strlen(invite);
2489 if (!channel->invite_list)
2490 channel->invite_list = silc_calloc(len + 2,
2491 sizeof(*channel->invite_list));
2493 channel->invite_list = silc_realloc(channel->invite_list,
2494 sizeof(*channel->invite_list) *
2496 strlen(channel->invite_list) + 2));
2497 strncat(channel->invite_list, invite, len);
2498 strncat(channel->invite_list, ",", 1);
2500 /* Send notify to the client that is invited to the channel */
2501 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2502 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2503 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2505 SILC_NOTIFY_TYPE_INVITE, 3,
2506 idp->data, idp->len,
2507 channel->channel_name,
2508 strlen(channel->channel_name),
2509 idp2->data, idp2->len);
2510 silc_buffer_free(idp);
2511 silc_buffer_free(idp2);
2514 /* Add the client to the invite list of the channel */
2515 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2517 if (!channel->invite_list)
2518 channel->invite_list = silc_calloc(len + 2,
2519 sizeof(*channel->invite_list));
2521 channel->invite_list = silc_realloc(channel->invite_list,
2522 sizeof(*channel->invite_list) *
2524 strlen(channel->invite_list) + 2));
2525 if (add[len - 1] == ',')
2526 add[len - 1] = '\0';
2528 strncat(channel->invite_list, add, len);
2529 strncat(channel->invite_list, ",", 1);
2532 /* Get the invite to be removed and remove it from the list */
2533 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2534 if (del && channel->invite_list) {
2535 char *start, *end, *n;
2537 if (!strncmp(channel->invite_list, del,
2538 strlen(channel->invite_list) - 1)) {
2539 silc_free(channel->invite_list);
2540 channel->invite_list = NULL;
2542 start = strstr(channel->invite_list, del);
2543 if (start && strlen(start) >= len) {
2545 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2546 strncat(n, channel->invite_list, start - channel->invite_list);
2547 strncat(n, end + 1, ((channel->invite_list +
2548 strlen(channel->invite_list)) - end) - 1);
2549 silc_free(channel->invite_list);
2550 channel->invite_list = n;
2555 /* Send notify to the primary router */
2556 if (!server->standalone)
2557 silc_server_send_notify_invite(server, server->router->connection,
2558 server->server_type == SILC_ROUTER ?
2559 TRUE : FALSE, channel,
2560 sender->id, add, del);
2562 /* Send command reply */
2563 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2567 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2568 SILC_STATUS_OK, ident, 2,
2570 3, channel->invite_list,
2571 channel->invite_list ?
2572 strlen(channel->invite_list) : 0);
2575 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2576 SILC_STATUS_OK, ident, 1,
2578 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2579 packet->data, packet->len, FALSE);
2580 silc_buffer_free(packet);
2584 silc_free(channel_id);
2585 silc_server_command_free(cmd);
2590 SilcSocketConnection sock;
2594 /* Quits connection to client. This gets called if client won't
2595 close the connection even when it has issued QUIT command. */
2597 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2599 QuitInternal q = (QuitInternal)context;
2601 /* Free all client specific data, such as client entry and entires
2602 on channels this client may be on. */
2603 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2605 q->sock->user_data = NULL;
2607 /* Close the connection on our side */
2608 silc_server_close_connection(q->server, q->sock);
2610 silc_free(q->signoff);
2614 /* Quits SILC session. This is the normal way to disconnect client. */
2616 SILC_SERVER_CMD_FUNC(quit)
2618 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2619 SilcServer server = cmd->server;
2620 SilcSocketConnection sock = cmd->sock;
2622 unsigned char *tmp = NULL;
2625 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2627 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2630 /* Get destination ID */
2631 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2635 q = silc_calloc(1, sizeof(*q));
2638 q->signoff = tmp ? strdup(tmp) : NULL;
2640 /* We quit the connection with little timeout */
2641 silc_schedule_task_add(server->schedule, sock->sock,
2642 silc_server_command_quit_cb, (void *)q,
2643 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2646 silc_server_command_free(cmd);
2649 /* Server side of command KILL. This command is used by router operator
2650 to remove an client from the SILC Network temporarily. */
2652 SILC_SERVER_CMD_FUNC(kill)
2654 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2655 SilcServer server = cmd->server;
2656 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2657 SilcClientEntry remote_client;
2658 SilcClientID *client_id;
2659 unsigned char *tmp, *comment;
2660 uint32 tmp_len, tmp_len2;
2663 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2665 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2668 /* KILL command works only on router */
2669 if (server->server_type != SILC_ROUTER) {
2670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2671 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2675 /* Check whether client has the permissions. */
2676 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2677 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2678 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2682 /* Get the client ID */
2683 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2686 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2689 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2692 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2696 /* Get the client entry */
2697 remote_client = silc_idlist_find_client_by_id(server->local_list,
2698 client_id, TRUE, NULL);
2700 if (!remote_client) {
2701 remote_client = silc_idlist_find_client_by_id(server->global_list,
2702 client_id, TRUE, NULL);
2704 if (!remote_client) {
2705 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2706 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2712 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2716 /* Send reply to the sender */
2717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2720 /* Send the KILL notify packets. First send it to the channel, then
2721 to our primary router and then directly to the client who is being
2722 killed right now. */
2724 /* Send KILLED notify to the channels. It is not sent to the client
2725 as it will be sent differently destined directly to the client and not
2727 silc_server_send_notify_on_channels(server, remote_client,
2728 remote_client, SILC_NOTIFY_TYPE_KILLED,
2731 comment, comment ? tmp_len2 : 0);
2733 /* Send KILLED notify to primary route */
2734 if (!server->standalone)
2735 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2736 remote_client->id, comment);
2738 /* Send KILLED notify to the client directly */
2739 silc_server_send_notify_killed(server, remote_client->connection ?
2740 remote_client->connection :
2741 remote_client->router->connection, FALSE,
2742 remote_client->id, comment);
2744 /* Remove the client from all channels. This generates new keys to the
2745 channels as well. */
2746 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2749 /* Remove the client entry, If it is locally connected then we will also
2750 disconnect the client here */
2751 if (remote_client->connection) {
2752 /* Remove locally conneted client */
2753 SilcSocketConnection sock = remote_client->connection;
2754 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2755 silc_server_close_connection(server, sock);
2757 /* Update statistics */
2758 if (remote_client->connection)
2759 server->stat.my_clients--;
2760 if (server->server_type == SILC_ROUTER)
2761 server->stat.cell_clients--;
2762 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2763 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2765 /* Remove remote client */
2766 silc_idlist_del_client(local ? server->local_list :
2767 server->global_list, remote_client);
2771 silc_server_command_free(cmd);
2774 /* Server side of command INFO. This sends information about us to
2775 the client. If client requested specific server we will send the
2776 command to that server. */
2778 SILC_SERVER_CMD_FUNC(info)
2780 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2781 SilcServer server = cmd->server;
2782 SilcBuffer packet, idp;
2785 char *dest_server, *server_info = NULL, *server_name;
2786 uint16 ident = silc_command_get_ident(cmd->payload);
2787 SilcServerEntry entry = NULL;
2788 SilcServerID *server_id = NULL;
2790 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2792 /* Get server name */
2793 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2796 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2798 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2801 SILC_STATUS_ERR_NO_SERVER_ID);
2807 /* Check whether we have this server cached */
2808 entry = silc_idlist_find_server_by_id(server->local_list,
2809 server_id, TRUE, NULL);
2811 entry = silc_idlist_find_server_by_id(server->global_list,
2812 server_id, TRUE, NULL);
2813 if (!entry && server->server_type != SILC_SERVER) {
2814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2815 SILC_STATUS_ERR_NO_SUCH_SERVER);
2821 /* Some buggy servers has sent request to router about themselves. */
2822 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2825 if ((!dest_server && !server_id && !entry) || (entry &&
2826 entry == server->id_entry) ||
2827 (dest_server && !cmd->pending &&
2828 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2829 /* Send our reply */
2830 char info_string[256];
2832 memset(info_string, 0, sizeof(info_string));
2833 snprintf(info_string, sizeof(info_string),
2834 "location: %s server: %s admin: %s <%s>",
2835 server->config->admin_info->location,
2836 server->config->admin_info->server_type,
2837 server->config->admin_info->admin_name,
2838 server->config->admin_info->admin_email);
2840 server_info = info_string;
2841 entry = server->id_entry;
2843 /* Check whether we have this server cached */
2844 if (!entry && dest_server) {
2845 entry = silc_idlist_find_server_by_name(server->global_list,
2846 dest_server, TRUE, NULL);
2848 entry = silc_idlist_find_server_by_name(server->local_list,
2849 dest_server, TRUE, NULL);
2853 if (!cmd->pending &&
2854 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2855 /* Send to the server */
2859 old_ident = silc_command_get_ident(cmd->payload);
2860 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2861 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2863 silc_server_packet_send(server, entry->connection,
2864 SILC_PACKET_COMMAND, cmd->packet->flags,
2865 tmpbuf->data, tmpbuf->len, TRUE);
2867 /* Reprocess this packet after received reply from router */
2868 silc_server_command_pending(server, SILC_COMMAND_INFO,
2869 silc_command_get_ident(cmd->payload),
2870 silc_server_command_info,
2871 silc_server_command_dup(cmd));
2872 cmd->pending = TRUE;
2873 silc_command_set_ident(cmd->payload, old_ident);
2874 silc_buffer_free(tmpbuf);
2878 if (!entry && !cmd->pending && !server->standalone) {
2879 /* Send to the primary router */
2883 old_ident = silc_command_get_ident(cmd->payload);
2884 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2885 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2887 silc_server_packet_send(server, server->router->connection,
2888 SILC_PACKET_COMMAND, cmd->packet->flags,
2889 tmpbuf->data, tmpbuf->len, TRUE);
2891 /* Reprocess this packet after received reply from router */
2892 silc_server_command_pending(server, SILC_COMMAND_INFO,
2893 silc_command_get_ident(cmd->payload),
2894 silc_server_command_info,
2895 silc_server_command_dup(cmd));
2896 cmd->pending = TRUE;
2897 silc_command_set_ident(cmd->payload, old_ident);
2898 silc_buffer_free(tmpbuf);
2903 silc_free(server_id);
2906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2907 SILC_STATUS_ERR_NO_SUCH_SERVER);
2911 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2913 server_info = entry->server_info;
2914 server_name = entry->server_name;
2916 /* Send the reply */
2917 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2918 SILC_STATUS_OK, ident, 3,
2919 2, idp->data, idp->len,
2921 strlen(server_name),
2924 strlen(server_info) : 0);
2925 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2926 packet->data, packet->len, FALSE);
2928 silc_buffer_free(packet);
2929 silc_buffer_free(idp);
2932 silc_server_command_free(cmd);
2935 /* Server side of command PING. This just replies to the ping. */
2937 SILC_SERVER_CMD_FUNC(ping)
2939 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2940 SilcServer server = cmd->server;
2945 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2948 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2951 SILC_STATUS_ERR_NO_SERVER_ID);
2954 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2958 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2959 /* Send our reply */
2960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2964 SILC_STATUS_ERR_NO_SUCH_SERVER);
2971 silc_server_command_free(cmd);
2974 /* Internal routine to join channel. The channel sent to this function
2975 has been either created or resolved from ID lists. This joins the sent
2976 client to the channel. */
2978 static void silc_server_command_join_channel(SilcServer server,
2979 SilcServerCommandContext cmd,
2980 SilcChannelEntry channel,
2981 SilcClientID *client_id,
2985 const unsigned char *auth,
2988 SilcSocketConnection sock = cmd->sock;
2990 uint32 tmp_len, user_count;
2991 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2992 SilcClientEntry client;
2993 SilcChannelClientEntry chl;
2994 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2995 uint16 ident = silc_command_get_ident(cmd->payload);
2996 char check[512], check2[512];
2997 bool founder = FALSE;
3000 SILC_LOG_DEBUG(("Start"));
3005 /* Get the client entry */
3006 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3007 client = (SilcClientEntry)sock->user_data;
3009 client = silc_server_get_client_resolve(server, client_id, &resolve);
3015 silc_server_command_send_status_reply(
3016 cmd, SILC_COMMAND_JOIN,
3017 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3021 /* The client info is being resolved. Reprocess this packet after
3022 receiving the reply to the query. */
3023 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3025 silc_server_command_join,
3026 silc_server_command_dup(cmd));
3027 cmd->pending = TRUE;
3031 cmd->pending = FALSE;
3035 * Check founder auth payload if provided. If client can gain founder
3036 * privileges it can override various conditions on joining the channel,
3037 * and can have directly the founder mode set on the channel.
3039 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3040 SilcIDListData idata = (SilcIDListData)client;
3042 if (channel->founder_key && idata->public_key &&
3043 silc_pkcs_public_key_compare(channel->founder_key,
3044 idata->public_key)) {
3045 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3046 (void *)channel->founder_passwd :
3047 (void *)channel->founder_key);
3048 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3049 channel->founder_passwd_len : 0);
3051 /* Check whether the client is to become founder */
3052 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3053 auth_data, auth_data_len,
3054 idata->hash, client->id, SILC_ID_CLIENT)) {
3055 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3062 * Check channel modes
3066 memset(check, 0, sizeof(check));
3067 memset(check2, 0, sizeof(check2));
3068 strncat(check, client->nickname, strlen(client->nickname));
3069 strncat(check, "!", 1);
3070 strncat(check, client->username, strlen(client->username));
3071 if (!strchr(client->username, '@')) {
3072 strncat(check, "@", 1);
3073 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3076 strncat(check2, client->nickname, strlen(client->nickname));
3077 if (!strchr(client->nickname, '@')) {
3078 strncat(check2, "@", 1);
3079 strncat(check2, server->server_name, strlen(server->server_name));
3081 strncat(check2, "!", 1);
3082 strncat(check2, client->username, strlen(client->username));
3083 if (!strchr(client->username, '@')) {
3084 strncat(check2, "@", 1);
3085 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3088 /* Check invite list if channel is invite-only channel */
3089 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3090 if (!channel->invite_list ||
3091 (!silc_string_match(channel->invite_list, check) &&
3092 !silc_string_match(channel->invite_list, check2))) {
3093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3094 SILC_STATUS_ERR_NOT_INVITED);
3099 /* Check ban list if it exists. If the client's nickname, server,
3100 username and/or hostname is in the ban list the access to the
3101 channel is denied. */
3102 if (channel->ban_list) {
3103 if (silc_string_match(channel->ban_list, check) ||
3104 silc_string_match(channel->ban_list, check2)) {
3105 silc_server_command_send_status_reply(
3106 cmd, SILC_COMMAND_JOIN,
3107 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3112 /* Check user count limit if set. */
3113 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3114 if (silc_hash_table_count(channel->user_list) + 1 >
3115 channel->user_limit) {
3116 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3117 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3123 /* Check the channel passphrase if set. */
3124 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3125 /* Get passphrase */
3126 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3128 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3129 memcpy(passphrase, tmp, tmp_len);
3132 if (!passphrase || !channel->passphrase ||
3133 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3134 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3135 SILC_STATUS_ERR_BAD_PASSWORD);
3141 * Client is allowed to join to the channel. Make it happen.
3144 /* Check whether the client already is on the channel */
3145 if (silc_server_client_on_channel(client, channel)) {
3146 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3147 SILC_STATUS_ERR_USER_ON_CHANNEL);
3151 /* Generate new channel key as protocol dictates */
3153 if (!silc_server_create_channel_key(server, channel, 0))
3156 /* Send the channel key. This is broadcasted to the channel but is not
3157 sent to the client who is joining to the channel. */
3158 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3159 silc_server_send_channel_key(server, NULL, channel,
3160 server->server_type == SILC_ROUTER ?
3161 FALSE : !server->standalone);
3164 /* Join the client to the channel by adding it to channel's user list.
3165 Add also the channel to client entry's channels list for fast cross-
3167 chl = silc_calloc(1, sizeof(*chl));
3169 chl->client = client;
3170 chl->channel = channel;
3171 silc_hash_table_add(channel->user_list, client, chl);
3172 silc_hash_table_add(client->channels, channel, chl);
3174 /* Get users on the channel */
3175 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3178 /* Encode Client ID Payload of the original client who wants to join */
3179 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3181 /* Encode command reply packet */
3182 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3183 SILC_PUT32_MSB(channel->mode, mode);
3184 SILC_PUT32_MSB(created, tmp2);
3185 SILC_PUT32_MSB(user_count, tmp3);
3187 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3188 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3189 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3190 strlen(channel->channel_key->
3192 channel->channel_key->cipher->name,
3193 channel->key_len / 8, channel->key);
3198 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3199 SILC_STATUS_OK, ident, 13,
3200 2, channel->channel_name,
3201 strlen(channel->channel_name),
3202 3, chidp->data, chidp->len,
3203 4, clidp->data, clidp->len,
3206 7, keyp ? keyp->data : NULL,
3207 keyp ? keyp->len : 0,
3208 8, channel->ban_list,
3210 strlen(channel->ban_list) : 0,
3211 9, channel->invite_list,
3212 channel->invite_list ?
3213 strlen(channel->invite_list) : 0,
3216 strlen(channel->topic) : 0,
3217 11, silc_hmac_get_name(channel->hmac),
3218 strlen(silc_hmac_get_name(channel->
3221 13, user_list->data, user_list->len,
3222 14, mode_list->data,
3225 /* Send command reply */
3226 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3227 reply->data, reply->len, FALSE);
3229 /* Send JOIN notify to locally connected clients on the channel. If
3230 we are normal server then router will send or have sent JOIN notify
3231 already. However since we've added the client already to our channel
3232 we'll ignore it (in packet_receive.c) so we must send it here. If
3233 we are router then this will send it to local clients and local
3235 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3236 SILC_NOTIFY_TYPE_JOIN, 2,
3237 clidp->data, clidp->len,
3238 chidp->data, chidp->len);
3240 if (!cmd->pending) {
3241 /* Send JOIN notify packet to our primary router */
3242 if (!server->standalone)
3243 silc_server_send_notify_join(server, server->router->connection,
3244 server->server_type == SILC_ROUTER ?
3245 TRUE : FALSE, channel, client->id);
3248 /* Distribute the channel key to all backup routers. */
3249 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3250 keyp->data, keyp->len, FALSE, TRUE);
3252 /* If client became founder by providing correct founder auth data
3253 notify the mode change to the channel. */
3255 SILC_PUT32_MSB(chl->mode, mode);
3256 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3257 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3258 clidp->data, clidp->len,
3259 mode, 4, clidp->data, clidp->len);
3261 /* Set CUMODE notify type to network */
3262 if (!server->standalone)
3263 silc_server_send_notify_cumode(server, server->router->connection,
3264 server->server_type == SILC_ROUTER ?
3265 TRUE : FALSE, channel,
3266 chl->mode, client->id, SILC_ID_CLIENT,
3271 silc_buffer_free(reply);
3272 silc_buffer_free(clidp);
3273 silc_buffer_free(chidp);
3274 silc_buffer_free(keyp);
3275 silc_buffer_free(user_list);
3276 silc_buffer_free(mode_list);
3279 silc_free(passphrase);
3282 /* Server side of command JOIN. Joins client into requested channel. If
3283 the channel does not exist it will be created. */
3285 SILC_SERVER_CMD_FUNC(join)
3287 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3288 SilcServer server = cmd->server;
3289 unsigned char *auth;
3290 uint32 tmp_len, auth_len;
3291 char *tmp, *channel_name = NULL, *cipher, *hmac;
3292 SilcChannelEntry channel;
3294 bool created = FALSE, create_key = TRUE;
3295 SilcClientID *client_id;
3297 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3299 /* Get channel name */
3300 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3303 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3309 channel_name[255] = '\0';
3311 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3313 SILC_STATUS_ERR_BAD_CHANNEL);
3317 /* Get Client ID of the client who is joining to the channel */
3318 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3321 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3324 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3327 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3331 /* Get cipher, hmac name and auth payload */
3332 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3333 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3334 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3336 /* See if the channel exists */
3337 channel = silc_idlist_find_channel_by_name(server->local_list,
3338 channel_name, NULL);
3340 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3341 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3342 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3344 if (!channel || channel->disabled) {
3345 /* Channel not found */
3347 /* If we are standalone server we don't have a router, we just create
3348 the channel by ourselves. */
3349 if (server->standalone) {
3350 channel = silc_server_create_new_channel(server, server->id, cipher,
3351 hmac, channel_name, TRUE);
3353 silc_server_command_send_status_reply(
3354 cmd, SILC_COMMAND_JOIN,
3355 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3359 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3365 /* The channel does not exist on our server. If we are normal server
3366 we will send JOIN command to our router which will handle the
3367 joining procedure (either creates the channel if it doesn't exist
3368 or joins the client to it). */
3369 if (server->server_type != SILC_ROUTER) {
3373 /* If this is pending command callback then we've resolved
3374 it and it didn't work, return since we've notified the
3375 client already in the command reply callback. */
3379 old_ident = silc_command_get_ident(cmd->payload);
3380 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3381 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3383 /* Send JOIN command to our router */
3384 silc_server_packet_send(server, (SilcSocketConnection)
3385 server->router->connection,
3386 SILC_PACKET_COMMAND, cmd->packet->flags,
3387 tmpbuf->data, tmpbuf->len, TRUE);
3389 /* Reprocess this packet after received reply from router */
3390 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3391 silc_command_get_ident(cmd->payload),
3392 silc_server_command_join,
3393 silc_server_command_dup(cmd));
3394 cmd->pending = TRUE;
3395 silc_command_set_ident(cmd->payload, old_ident);
3399 /* We are router and the channel does not seem exist so we will check
3400 our global list as well for the channel. */
3401 channel = silc_idlist_find_channel_by_name(server->global_list,
3402 channel_name, NULL);
3404 /* Channel really does not exist, create it */
3405 channel = silc_server_create_new_channel(server, server->id, cipher,
3406 hmac, channel_name, TRUE);
3408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3409 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3413 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3421 /* Channel not found */
3423 /* If the command came from router and we are normal server then
3424 something went wrong with the joining as the channel was not found.
3425 We can't do anything else but ignore this. */
3426 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3427 server->server_type != SILC_ROUTER)
3430 /* We are router and the channel does not seem exist so we will check
3431 our global list as well for the channel. */
3432 channel = silc_idlist_find_channel_by_name(server->global_list,
3433 channel_name, NULL);
3435 /* Channel really does not exist, create it */
3436 channel = silc_server_create_new_channel(server, server->id, cipher,
3437 hmac, channel_name, TRUE);
3439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3440 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3444 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3451 /* Check whether the channel was created by our router */
3452 if (cmd->pending && context2) {
3453 SilcServerCommandReplyContext reply =
3454 (SilcServerCommandReplyContext)context2;
3456 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3457 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3458 SILC_GET32_MSB(created, tmp);
3459 if (silc_argument_get_arg_type(reply->args, 7, NULL)
3460 create_key = FALSE; /* Router returned the key already */
3463 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3464 !silc_hash_table_count(channel->user_list))
3468 /* If the channel does not have global users and is also empty the client
3469 will be the channel founder and operator. */
3470 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3471 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3473 /* Join to the channel */
3474 silc_server_command_join_channel(server, cmd, channel, client_id,
3475 created, create_key, umode,
3478 silc_free(client_id);
3481 silc_server_command_free(cmd);
3484 /* Server side of command MOTD. Sends server's current "message of the
3485 day" to the client. */
3487 SILC_SERVER_CMD_FUNC(motd)
3489 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3490 SilcServer server = cmd->server;
3491 SilcBuffer packet, idp;
3492 char *motd, *dest_server;
3494 uint16 ident = silc_command_get_ident(cmd->payload);
3496 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3498 /* Get server name */
3499 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3502 SILC_STATUS_ERR_NO_SUCH_SERVER);
3506 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3509 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3511 if (server->config && server->config->motd &&
3512 server->config->motd->motd_file) {
3514 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3519 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3520 SILC_STATUS_OK, ident, 2,
3525 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3526 SILC_STATUS_OK, ident, 1,
3530 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3531 packet->data, packet->len, FALSE);
3532 silc_buffer_free(packet);
3533 silc_buffer_free(idp);
3535 SilcServerEntry entry;
3537 /* Check whether we have this server cached */
3538 entry = silc_idlist_find_server_by_name(server->global_list,
3539 dest_server, TRUE, NULL);
3541 entry = silc_idlist_find_server_by_name(server->local_list,
3542 dest_server, TRUE, NULL);
3545 if (server->server_type != SILC_SERVER && !cmd->pending &&
3546 entry && !entry->motd) {
3547 /* Send to the server */
3551 old_ident = silc_command_get_ident(cmd->payload);
3552 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3553 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3555 silc_server_packet_send(server, entry->connection,
3556 SILC_PACKET_COMMAND, cmd->packet->flags,
3557 tmpbuf->data, tmpbuf->len, TRUE);
3559 /* Reprocess this packet after received reply from router */
3560 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3561 silc_command_get_ident(cmd->payload),
3562 silc_server_command_motd,
3563 silc_server_command_dup(cmd));
3564 cmd->pending = TRUE;
3565 silc_command_set_ident(cmd->payload, old_ident);
3566 silc_buffer_free(tmpbuf);
3570 if (!entry && !cmd->pending && !server->standalone) {
3571 /* Send to the primary router */
3575 old_ident = silc_command_get_ident(cmd->payload);
3576 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3577 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3579 silc_server_packet_send(server, server->router->connection,
3580 SILC_PACKET_COMMAND, cmd->packet->flags,
3581 tmpbuf->data, tmpbuf->len, TRUE);
3583 /* Reprocess this packet after received reply from router */
3584 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3585 silc_command_get_ident(cmd->payload),
3586 silc_server_command_motd,
3587 silc_server_command_dup(cmd));
3588 cmd->pending = TRUE;
3589 silc_command_set_ident(cmd->payload, old_ident);
3590 silc_buffer_free(tmpbuf);
3595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3596 SILC_STATUS_ERR_NO_SUCH_SERVER);
3600 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3601 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3602 SILC_STATUS_OK, ident, 2,
3606 strlen(entry->motd) : 0);
3607 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3608 packet->data, packet->len, FALSE);
3609 silc_buffer_free(packet);
3610 silc_buffer_free(idp);
3614 silc_server_command_free(cmd);
3617 /* Server side of command UMODE. Client can use this command to set/unset
3618 user mode. Client actually cannot set itself to be as server/router
3619 operator so this can be used only to unset the modes. */
3621 SILC_SERVER_CMD_FUNC(umode)
3623 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3624 SilcServer server = cmd->server;
3625 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3627 unsigned char *tmp_mask;
3629 uint16 ident = silc_command_get_ident(cmd->payload);
3631 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3634 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3636 /* Get the client's mode mask */
3637 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3640 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3643 SILC_GET32_MSB(mask, tmp_mask);
3649 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3650 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3651 /* Cannot operator mode */
3652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3653 SILC_STATUS_ERR_PERM_DENIED);
3657 /* Remove the server operator rights */
3658 if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
3659 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3660 if (client->connection)
3661 server->stat.my_server_ops--;
3662 if (server->server_type == SILC_ROUTER)
3663 server->stat.server_ops--;
3667 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3668 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3669 /* Cannot operator mode */
3670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3671 SILC_STATUS_ERR_PERM_DENIED);
3675 /* Remove the router operator rights */
3676 if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
3677 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3678 if (client->connection)
3679 server->stat.my_router_ops--;
3680 if (server->server_type == SILC_ROUTER)
3681 server->stat.router_ops--;
3685 if (mask & SILC_UMODE_GONE) {
3686 client->mode |= SILC_UMODE_GONE;
3688 if (client->mode & SILC_UMODE_GONE)
3689 /* Remove the gone status */
3690 client->mode &= ~SILC_UMODE_GONE;
3693 /* Send UMODE change to primary router */
3694 if (!server->standalone)
3695 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3696 client->id, client->mode);
3698 /* Send command reply to sender */
3699 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3700 SILC_STATUS_OK, ident, 1,
3702 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3703 packet->data, packet->len, FALSE);
3704 silc_buffer_free(packet);
3707 silc_server_command_free(cmd);
3710 /* Checks that client has rights to add or remove channel modes. If any
3711 of the checks fails FALSE is returned. */
3713 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3714 SilcChannelClientEntry client,
3717 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3718 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3720 /* Check whether has rights to change anything */
3721 if (!is_op && !is_fo)
3724 /* Check whether has rights to change everything */
3728 /* We know that client is channel operator, check that they are not
3729 changing anything that requires channel founder rights. Rest of the
3730 modes are available automatically for channel operator. */
3732 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3733 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3734 if (is_op && !is_fo)
3737 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3738 if (is_op && !is_fo)
3743 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3744 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3745 if (is_op && !is_fo)
3748 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3749 if (is_op && !is_fo)
3754 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3755 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3756 if (is_op && !is_fo)
3759 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3760 if (is_op && !is_fo)
3765 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3766 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3767 if (is_op && !is_fo)
3770 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3771 if (is_op && !is_fo)
3779 /* Server side command of CMODE. Changes channel mode */
3781 SILC_SERVER_CMD_FUNC(cmode)
3783 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3784 SilcServer server = cmd->server;
3785 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3786 SilcIDListData idata = (SilcIDListData)client;
3787 SilcChannelID *channel_id;
3788 SilcChannelEntry channel;
3789 SilcChannelClientEntry chl;
3790 SilcBuffer packet, cidp;
3791 unsigned char *tmp, *tmp_id, *tmp_mask;
3792 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3793 uint32 mode_mask, tmp_len, tmp_len2;
3794 uint16 ident = silc_command_get_ident(cmd->payload);
3796 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3798 /* Get Channel ID */
3799 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3802 SILC_STATUS_ERR_NO_CHANNEL_ID);
3805 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3808 SILC_STATUS_ERR_NO_CHANNEL_ID);
3812 /* Get the channel mode mask */
3813 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3816 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3819 SILC_GET32_MSB(mode_mask, tmp_mask);
3821 /* Get channel entry */
3822 channel = silc_idlist_find_channel_by_id(server->local_list,
3825 channel = silc_idlist_find_channel_by_id(server->global_list,
3828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3829 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3834 /* Check whether this client is on the channel */
3835 if (!silc_server_client_on_channel(client, channel)) {
3836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3837 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3841 /* Get entry to the channel user list */
3842 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3844 /* Check that client has rights to change any requested channel modes */
3845 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3847 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3852 * Check the modes. Modes that requires nothing special operation are
3856 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3857 /* Channel uses private keys to protect traffic. Client(s) has set the
3858 key locally they want to use, server does not know that key. */
3859 /* Nothing interesting to do here */
3861 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3862 /* The mode is removed and we need to generate and distribute
3863 new channel key. Clients are not using private channel keys
3864 anymore after this. */
3866 /* Re-generate channel key */
3867 if (!silc_server_create_channel_key(server, channel, 0))
3870 /* Send the channel key. This sends it to our local clients and if
3871 we are normal server to our router as well. */
3872 silc_server_send_channel_key(server, NULL, channel,
3873 server->server_type == SILC_ROUTER ?
3874 FALSE : !server->standalone);
3876 cipher = channel->channel_key->cipher->name;
3877 hmac = (char *)silc_hmac_get_name(channel->hmac);
3881 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3882 /* User limit is set on channel */
3885 /* Get user limit */
3886 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3888 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3890 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3894 SILC_GET32_MSB(user_limit, tmp);
3895 channel->user_limit = user_limit;
3898 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3899 /* User limit mode is unset. Remove user limit */
3900 channel->user_limit = 0;
3903 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3904 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3905 /* Passphrase has been set to channel */
3907 /* Get the passphrase */
3908 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3911 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3915 /* Save the passphrase */
3916 passphrase = channel->passphrase = strdup(tmp);
3919 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3920 /* Passphrase mode is unset. remove the passphrase */
3921 if (channel->passphrase) {
3922 silc_free(channel->passphrase);
3923 channel->passphrase = NULL;
3928 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3929 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3930 /* Cipher to use protect the traffic */
3931 SilcCipher newkey, oldkey;
3934 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3937 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3941 /* Delete old cipher and allocate the new one */
3942 if (!silc_cipher_alloc(cipher, &newkey)) {
3943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3944 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3948 oldkey = channel->channel_key;
3949 channel->channel_key = newkey;
3951 /* Re-generate channel key */
3952 if (!silc_server_create_channel_key(server, channel, 0)) {
3953 /* We don't have new key, revert to old one */
3954 channel->channel_key = oldkey;
3958 /* Remove old channel key for good */
3959 silc_cipher_free(oldkey);
3961 /* Send the channel key. This sends it to our local clients and if
3962 we are normal server to our router as well. */
3963 silc_server_send_channel_key(server, NULL, channel,
3964 server->server_type == SILC_ROUTER ?
3965 FALSE : !server->standalone);
3968 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3969 /* Cipher mode is unset. Remove the cipher and revert back to
3971 SilcCipher newkey, oldkey;
3972 cipher = channel->cipher;
3974 /* Delete old cipher and allocate default one */
3975 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3977 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3981 oldkey = channel->channel_key;
3982 channel->channel_key = newkey;
3984 /* Re-generate channel key */
3985 if (!silc_server_create_channel_key(server, channel, 0)) {
3986 /* We don't have new key, revert to old one */
3987 channel->channel_key = oldkey;
3991 /* Remove old channel key for good */
3992 silc_cipher_free(oldkey);
3994 /* Send the channel key. This sends it to our local clients and if
3995 we are normal server to our router as well. */
3996 silc_server_send_channel_key(server, NULL, channel,
3997 server->server_type == SILC_ROUTER ?
3998 FALSE : !server->standalone);
4002 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4003 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4004 /* HMAC to use protect the traffic */
4005 unsigned char hash[32];
4009 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4012 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4016 /* Delete old hmac and allocate the new one */
4017 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4019 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4023 silc_hmac_free(channel->hmac);
4024 channel->hmac = newhmac;
4026 /* Set the HMAC key out of current channel key. The client must do
4028 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4029 channel->key_len / 8, hash);
4030 silc_hmac_set_key(channel->hmac, hash,
4031 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4032 memset(hash, 0, sizeof(hash));
4035 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4036 /* Hmac mode is unset. Remove the hmac and revert back to
4039 unsigned char hash[32];
4040 hmac = channel->hmac_name;
4042 /* Delete old hmac and allocate default one */
4043 silc_hmac_free(channel->hmac);
4044 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4046 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4050 silc_hmac_free(channel->hmac);
4051 channel->hmac = newhmac;
4053 /* Set the HMAC key out of current channel key. The client must do
4055 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4056 channel->key_len / 8,
4058 silc_hmac_set_key(channel->hmac, hash,
4059 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4060 memset(hash, 0, sizeof(hash));
4064 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4065 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4066 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4067 /* Set the founder authentication */
4068 SilcAuthPayload auth;
4070 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4072 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4073 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4077 auth = silc_auth_payload_parse(tmp, tmp_len);
4079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4080 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4084 /* Save the public key */
4085 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4086 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4089 channel->founder_method = silc_auth_get_method(auth);
4091 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4092 tmp = silc_auth_get_data(auth, &tmp_len);
4093 channel->founder_passwd =
4094 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4095 memcpy(channel->founder_passwd, tmp, tmp_len);
4096 channel->founder_passwd_len = tmp_len;
4098 /* Verify the payload before setting the mode */
4099 if (!silc_auth_verify(auth, channel->founder_method,
4100 channel->founder_key, 0, idata->hash,
4101 client->id, SILC_ID_CLIENT)) {
4102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4103 SILC_STATUS_ERR_AUTH_FAILED);
4108 silc_auth_payload_free(auth);
4112 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4113 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4114 if (channel->founder_key)
4115 silc_pkcs_public_key_free(channel->founder_key);
4116 if (channel->founder_passwd) {
4117 silc_free(channel->founder_passwd);
4118 channel->founder_passwd = NULL;
4124 /* Finally, set the mode */
4125 channel->mode = mode_mask;
4127 /* Send CMODE_CHANGE notify. */
4128 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4129 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4130 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4131 cidp->data, cidp->len,
4133 cipher, cipher ? strlen(cipher) : 0,
4134 hmac, hmac ? strlen(hmac) : 0,
4135 passphrase, passphrase ?
4136 strlen(passphrase) : 0);
4138 /* Set CMODE notify type to network */
4139 if (!server->standalone)
4140 silc_server_send_notify_cmode(server, server->router->connection,
4141 server->server_type == SILC_ROUTER ?
4142 TRUE : FALSE, channel,
4143 mode_mask, client->id, SILC_ID_CLIENT,
4144 cipher, hmac, passphrase);
4146 /* Send command reply to sender */
4147 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4148 SILC_STATUS_OK, ident, 2,
4149 2, tmp_id, tmp_len2,
4151 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4152 packet->data, packet->len, FALSE);
4154 silc_buffer_free(packet);
4155 silc_free(channel_id);
4156 silc_buffer_free(cidp);
4159 silc_server_command_free(cmd);
4162 /* Server side of CUMODE command. Changes client's mode on a channel. */
4164 SILC_SERVER_CMD_FUNC(cumode)
4166 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4167 SilcServer server = cmd->server;
4168 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4169 SilcIDListData idata = (SilcIDListData)client;
4170 SilcChannelID *channel_id;
4171 SilcClientID *client_id;
4172 SilcChannelEntry channel;
4173 SilcClientEntry target_client;
4174 SilcChannelClientEntry chl;
4175 SilcBuffer packet, idp;
4176 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4177 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4179 uint16 ident = silc_command_get_ident(cmd->payload);
4181 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4183 /* Get Channel ID */
4184 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4187 SILC_STATUS_ERR_NO_CHANNEL_ID);
4190 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4193 SILC_STATUS_ERR_NO_CHANNEL_ID);
4197 /* Get channel entry */
4198 channel = silc_idlist_find_channel_by_id(server->local_list,
4201 channel = silc_idlist_find_channel_by_id(server->global_list,
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4205 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4210 /* Check whether sender is on the channel */
4211 if (!silc_server_client_on_channel(client, channel)) {
4212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4213 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4217 /* Check that client has rights to change other's rights */
4218 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4219 sender_mask = chl->mode;
4221 /* Get the target client's channel mode mask */
4222 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4225 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4228 SILC_GET32_MSB(target_mask, tmp_mask);
4230 /* Get target Client ID */
4231 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4234 SILC_STATUS_ERR_NO_CLIENT_ID);
4237 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4240 SILC_STATUS_ERR_NO_CLIENT_ID);
4244 /* Get target client's entry */
4245 target_client = silc_idlist_find_client_by_id(server->local_list,
4246 client_id, TRUE, NULL);
4247 if (!target_client) {
4248 target_client = silc_idlist_find_client_by_id(server->global_list,
4249 client_id, TRUE, NULL);
4252 if (target_client != client &&
4253 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4254 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4256 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4260 /* Check whether target client is on the channel */
4261 if (target_client != client) {
4262 if (!silc_server_client_on_channel(target_client, channel)) {
4263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4264 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4268 /* Get entry to the channel user list */
4269 silc_hash_table_find(channel->user_list, target_client, NULL,
4277 /* If the target client is founder, no one else can change their mode
4279 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4281 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4285 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4286 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4287 /* The client tries to claim the founder rights. */
4288 unsigned char *tmp_auth;
4289 uint32 tmp_auth_len, auth_len;
4292 if (target_client != client) {
4293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4294 SILC_STATUS_ERR_NOT_YOU);
4298 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4299 !channel->founder_key || !idata->public_key ||
4300 !silc_pkcs_public_key_compare(channel->founder_key,
4301 idata->public_key)) {
4302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4303 SILC_STATUS_ERR_NOT_YOU);
4307 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4310 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4314 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4315 (void *)channel->founder_passwd : (void *)channel->founder_key);
4316 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4317 channel->founder_passwd_len : 0);
4319 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4320 channel->founder_method, auth, auth_len,
4321 idata->hash, client->id, SILC_ID_CLIENT)) {
4322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4323 SILC_STATUS_ERR_AUTH_FAILED);
4327 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4331 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4332 if (target_client == client) {
4333 /* Remove channel founder rights from itself */
4334 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4338 SILC_STATUS_ERR_NOT_YOU);
4344 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4345 /* Promote to operator */
4346 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4347 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4348 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4349 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4350 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4354 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4358 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4359 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4360 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4362 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4366 /* Demote to normal user */
4367 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4372 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4373 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4375 /* Send notify to channel, notify only if mode was actually changed. */
4377 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4378 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4379 idp->data, idp->len,
4383 /* Set CUMODE notify type to network */
4384 if (!server->standalone)
4385 silc_server_send_notify_cumode(server, server->router->connection,
4386 server->server_type == SILC_ROUTER ?
4387 TRUE : FALSE, channel,
4388 target_mask, client->id,
4393 /* Send command reply to sender */
4394 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4395 SILC_STATUS_OK, ident, 3,
4397 3, tmp_ch_id, tmp_ch_len,
4398 4, tmp_id, tmp_len);
4399 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4400 packet->data, packet->len, FALSE);
4402 silc_buffer_free(packet);
4403 silc_free(channel_id);
4404 silc_free(client_id);
4405 silc_buffer_free(idp);
4408 silc_server_command_free(cmd);
4411 /* Server side of KICK command. Kicks client out of channel. */
4413 SILC_SERVER_CMD_FUNC(kick)
4415 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4416 SilcServer server = cmd->server;
4417 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4418 SilcClientEntry target_client;
4419 SilcChannelID *channel_id;
4420 SilcClientID *client_id;
4421 SilcChannelEntry channel;
4422 SilcChannelClientEntry chl;
4424 uint32 tmp_len, target_idp_len;
4425 unsigned char *tmp, *comment, *target_idp;
4427 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4429 /* Get Channel ID */
4430 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4433 SILC_STATUS_ERR_NO_CHANNEL_ID);
4436 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4439 SILC_STATUS_ERR_NO_CHANNEL_ID);
4443 /* Get channel entry */
4444 channel = silc_idlist_find_channel_by_id(server->local_list,
4447 channel = silc_idlist_find_channel_by_id(server->local_list,
4450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4451 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4456 /* Check whether sender is on the channel */
4457 if (!silc_server_client_on_channel(client, channel)) {
4458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4459 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4463 /* Check that the kicker is channel operator or channel founder */
4464 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4465 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4467 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4471 /* Get target Client ID */
4472 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4475 SILC_STATUS_ERR_NO_CLIENT_ID);
4478 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4480 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4481 SILC_STATUS_ERR_NO_CLIENT_ID);
4485 /* Get target client's entry */
4486 target_client = silc_idlist_find_client_by_id(server->local_list,
4487 client_id, TRUE, NULL);
4488 if (!target_client) {
4489 target_client = silc_idlist_find_client_by_id(server->global_list,
4490 client_id, TRUE, NULL);
4493 /* Check that the target client is not channel founder. Channel founder
4494 cannot be kicked from the channel. */
4495 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4496 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4497 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4498 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4502 /* Check whether target client is on the channel */
4503 if (!silc_server_client_on_channel(target_client, channel)) {
4504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4505 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4511 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4515 /* Send command reply to sender */
4516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4519 /* Send KICKED notify to local clients on the channel */
4520 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4521 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4522 SILC_NOTIFY_TYPE_KICKED, 3,
4523 target_idp, target_idp_len,
4524 comment, comment ? strlen(comment) : 0,
4525 idp->data, idp->len);
4526 silc_buffer_free(idp);
4528 /* Remove the client from the channel. If the channel does not exist
4529 after removing the client then the client kicked itself off the channel
4530 and we don't have to send anything after that. */
4531 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4532 target_client, FALSE))
4535 /* Send KICKED notify to primary route */
4536 if (!server->standalone)
4537 silc_server_send_notify_kicked(server, server->router->connection,
4538 server->server_type == SILC_ROUTER ?
4539 TRUE : FALSE, channel,
4540 target_client->id, client->id, comment);
4542 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4543 /* Re-generate channel key */
4544 if (!silc_server_create_channel_key(server, channel, 0))
4547 /* Send the channel key to the channel. The key of course is not sent
4548 to the client who was kicked off the channel. */
4549 silc_server_send_channel_key(server, target_client->connection, channel,
4550 server->server_type == SILC_ROUTER ?
4551 FALSE : !server->standalone);
4555 silc_server_command_free(cmd);
4558 /* Server side of OPER command. Client uses this comand to obtain server
4559 operator privileges to this server/router. */
4561 SILC_SERVER_CMD_FUNC(oper)
4563 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4564 SilcServer server = cmd->server;
4565 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4566 unsigned char *username, *auth;
4568 SilcServerConfigSectionAdminConnection *admin;
4569 SilcIDListData idata = (SilcIDListData)client;
4571 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4573 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4576 /* Get the username */
4577 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4579 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4580 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4584 /* Get the admin configuration */
4585 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4586 username, client->nickname);
4588 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4589 username, client->nickname);
4591 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4592 SILC_STATUS_ERR_AUTH_FAILED);
4597 /* Get the authentication payload */
4598 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4600 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4601 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4605 /* Verify the authentication data */
4606 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4607 admin->auth_data, admin->auth_data_len,
4608 idata->hash, client->id, SILC_ID_CLIENT)) {
4609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4610 SILC_STATUS_ERR_AUTH_FAILED);
4614 /* Client is now server operator */
4615 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4617 /* Update statistics */
4618 if (client->connection)
4619 server->stat.my_server_ops++;
4620 if (server->server_type == SILC_ROUTER)
4621 server->stat.server_ops++;
4623 /* Send UMODE change to primary router */
4624 if (!server->standalone)
4625 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4626 client->id, client->mode);
4628 /* Send reply to the sender */
4629 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4633 silc_server_command_free(cmd);
4636 /* Server side of SILCOPER command. Client uses this comand to obtain router
4637 operator privileges to this router. */
4639 SILC_SERVER_CMD_FUNC(silcoper)
4641 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4642 SilcServer server = cmd->server;
4643 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4644 unsigned char *username, *auth;
4646 SilcServerConfigSectionAdminConnection *admin;
4647 SilcIDListData idata = (SilcIDListData)client;
4649 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4651 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4654 if (server->server_type != SILC_ROUTER) {
4655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4656 SILC_STATUS_ERR_AUTH_FAILED);
4660 /* Get the username */
4661 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4664 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4668 /* Get the admin configuration */
4669 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4670 username, client->nickname);
4672 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4673 username, client->nickname);
4675 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4676 SILC_STATUS_ERR_AUTH_FAILED);
4681 /* Get the authentication payload */
4682 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4685 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4689 /* Verify the authentication data */
4690 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4691 admin->auth_data, admin->auth_data_len,
4692 idata->hash, client->id, SILC_ID_CLIENT)) {
4693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4694 SILC_STATUS_ERR_AUTH_FAILED);
4698 /* Client is now router operator */
4699 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4701 /* Update statistics */
4702 if (client->connection)
4703 server->stat.my_router_ops++;
4704 if (server->server_type == SILC_ROUTER)
4705 server->stat.router_ops++;
4707 /* Send UMODE change to primary router */
4708 if (!server->standalone)
4709 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4710 client->id, client->mode);
4712 /* Send reply to the sender */
4713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4717 silc_server_command_free(cmd);
4720 /* Server side command of CONNECT. Connects us to the specified remote
4721 server or router. */
4723 SILC_SERVER_CMD_FUNC(connect)
4725 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4726 SilcServer server = cmd->server;
4727 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4728 unsigned char *tmp, *host;
4730 uint32 port = SILC_PORT;
4732 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4734 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4737 /* Check whether client has the permissions. */
4738 if (client->mode == SILC_UMODE_NONE) {
4739 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4740 SILC_STATUS_ERR_NO_SERVER_PRIV);
4744 if (server->server_type == SILC_ROUTER &&
4745 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4747 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4751 /* Get the remote server */
4752 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4755 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4760 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4762 SILC_GET32_MSB(port, tmp);
4764 /* Create the connection. It is done with timeout and is async. */
4765 silc_server_create_connection(server, host, port);
4767 /* Send reply to the sender */
4768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4772 silc_server_command_free(cmd);
4775 /* Server side of command BAN. This is used to manage the ban list of the
4776 channel. To add clients and remove clients from the ban list. */
4778 SILC_SERVER_CMD_FUNC(ban)
4780 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4781 SilcServer server = cmd->server;
4782 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4784 SilcChannelEntry channel;
4785 SilcChannelClientEntry chl;
4786 SilcChannelID *channel_id = NULL;
4787 unsigned char *id, *add, *del;
4788 uint32 id_len, tmp_len;
4789 uint16 ident = silc_command_get_ident(cmd->payload);
4791 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4794 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4796 /* Get Channel ID */
4797 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4799 channel_id = silc_id_payload_parse_id(id, id_len);
4801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4802 SILC_STATUS_ERR_NO_CHANNEL_ID);
4807 /* Get channel entry. The server must know about the channel since the
4808 client is expected to be on the channel. */
4809 channel = silc_idlist_find_channel_by_id(server->local_list,
4812 channel = silc_idlist_find_channel_by_id(server->global_list,
4815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4816 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4821 /* Check whether this client is on the channel */
4822 if (!silc_server_client_on_channel(client, channel)) {
4823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4824 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4828 /* Get entry to the channel user list */
4829 if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
4830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4831 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4835 /* The client must be at least channel operator. */
4836 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4838 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4842 /* Get the new ban and add it to the ban list */
4843 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4845 if (!channel->ban_list)
4846 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4848 channel->ban_list = silc_realloc(channel->ban_list,
4849 sizeof(*channel->ban_list) *
4851 strlen(channel->ban_list) + 2));
4852 if (add[tmp_len - 1] == ',')
4853 add[tmp_len - 1] = '\0';
4855 strncat(channel->ban_list, add, tmp_len);
4856 strncat(channel->ban_list, ",", 1);
4859 /* Get the ban to be removed and remove it from the list */
4860 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4861 if (del && channel->ban_list) {
4862 char *start, *end, *n;
4864 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4865 silc_free(channel->ban_list);
4866 channel->ban_list = NULL;
4868 start = strstr(channel->ban_list, del);
4869 if (start && strlen(start) >= tmp_len) {
4870 end = start + tmp_len;
4871 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4872 strncat(n, channel->ban_list, start - channel->ban_list);
4873 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4875 silc_free(channel->ban_list);
4876 channel->ban_list = n;
4881 /* Send the BAN notify type to our primary router. */
4882 if (!server->standalone && (add || del))
4883 silc_server_send_notify_ban(server, server->router->connection,
4884 server->server_type == SILC_ROUTER ?
4885 TRUE : FALSE, channel, add, del);
4887 /* Send the reply back to the client */
4889 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4890 SILC_STATUS_OK, ident, 2,
4892 3, channel->ban_list,
4894 strlen(channel->ban_list) : 0);
4895 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4896 packet->data, packet->len, FALSE);
4898 silc_buffer_free(packet);
4901 silc_free(channel_id);
4902 silc_server_command_free(cmd);
4905 /* Server side command of CLOSE. Closes connection to a specified server. */
4907 SILC_SERVER_CMD_FUNC(close)
4909 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4910 SilcServer server = cmd->server;
4911 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4912 SilcServerEntry server_entry;
4913 SilcSocketConnection sock;
4916 unsigned char *name;
4917 uint32 port = SILC_PORT;
4919 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4921 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4924 /* Check whether client has the permissions. */
4925 if (client->mode == SILC_UMODE_NONE) {
4926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4927 SILC_STATUS_ERR_NO_SERVER_PRIV);
4931 /* Get the remote server */
4932 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4935 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4940 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4942 SILC_GET32_MSB(port, tmp);
4944 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4945 name, port, FALSE, NULL);
4947 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4948 name, port, FALSE, NULL);
4949 if (!server_entry) {
4950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4951 SILC_STATUS_ERR_NO_SERVER_ID);
4955 /* Send reply to the sender */
4956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4959 /* Close the connection to the server */
4960 sock = (SilcSocketConnection)server_entry->connection;
4962 /* If we shutdown primary router connection manually then don't trigger
4963 any reconnect or backup router connections, by setting the router
4965 if (server->router == server_entry) {
4966 server->id_entry->router = NULL;
4967 server->router = NULL;
4968 server->standalone = TRUE;
4970 silc_server_free_sock_user_data(server, sock, NULL);
4971 silc_server_close_connection(server, sock);
4974 silc_server_command_free(cmd);
4977 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4978 active connections. */
4980 SILC_SERVER_CMD_FUNC(shutdown)
4982 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4983 SilcServer server = cmd->server;
4984 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4986 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4988 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4991 /* Check whether client has the permission. */
4992 if (client->mode == SILC_UMODE_NONE) {
4993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4994 SILC_STATUS_ERR_NO_SERVER_PRIV);
4998 /* Send reply to the sender */
4999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5002 /* Then, gracefully, or not, bring the server down. */
5003 silc_server_stop(server);
5007 silc_server_command_free(cmd);
5010 /* Server side command of LEAVE. Removes client from a channel. */
5012 SILC_SERVER_CMD_FUNC(leave)
5014 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5015 SilcServer server = cmd->server;
5016 SilcSocketConnection sock = cmd->sock;
5017 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5018 SilcChannelID *id = NULL;
5019 SilcChannelEntry channel;
5023 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5025 /* Get Channel ID */
5026 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5029 SILC_STATUS_ERR_NO_CHANNEL_ID);
5032 id = silc_id_payload_parse_id(tmp, len);
5034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5035 SILC_STATUS_ERR_NO_CHANNEL_ID);
5039 /* Get channel entry */
5040 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5042 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5045 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5050 /* Check whether this client is on the channel */
5051 if (!silc_server_client_on_channel(id_entry, channel)) {
5052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5053 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5057 /* Notify routers that they should remove this client from their list
5058 of clients on the channel. Send LEAVE notify type. */
5059 if (!server->standalone)
5060 silc_server_send_notify_leave(server, server->router->connection,
5061 server->server_type == SILC_ROUTER ?
5062 TRUE : FALSE, channel, id_entry->id);
5064 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5067 /* Remove client from channel */
5068 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5070 /* If the channel does not exist anymore we won't send anything */
5073 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5074 /* Re-generate channel key */
5075 if (!silc_server_create_channel_key(server, channel, 0))
5078 /* Send the channel key */
5079 silc_server_send_channel_key(server, NULL, channel,
5080 server->server_type == SILC_ROUTER ?
5081 FALSE : !server->standalone);
5086 silc_server_command_free(cmd);
5089 /* Server side of command USERS. Resolves clients and their USERS currently
5090 joined on the requested channel. The list of Client ID's and their modes
5091 on the channel is sent back. */
5093 SILC_SERVER_CMD_FUNC(users)
5095 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5096 SilcServer server = cmd->server;
5097 SilcChannelEntry channel;
5098 SilcChannelID *id = NULL;
5099 SilcBuffer packet, idp;
5100 unsigned char *channel_id;
5101 uint32 channel_id_len;
5102 SilcBuffer client_id_list;
5103 SilcBuffer client_mode_list;
5104 unsigned char lc[4];
5105 uint32 list_count = 0;
5106 uint16 ident = silc_command_get_ident(cmd->payload);
5109 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5111 /* Get Channel ID */
5112 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5114 /* Get channel name */
5115 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5117 if (!channel_id && !channel_name) {
5118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5119 SILC_STATUS_ERR_NO_CHANNEL_ID);
5124 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5127 SILC_STATUS_ERR_NO_CHANNEL_ID);
5132 /* If we are server and we don't know about this channel we will send
5133 the command to our router. If we know about the channel then we also
5134 have the list of users already. */
5136 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5138 channel = silc_idlist_find_channel_by_name(server->local_list,
5139 channel_name, NULL);
5141 if (!channel || channel->disabled) {
5142 if (server->server_type != SILC_ROUTER && !server->standalone &&
5146 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5147 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5149 /* Send USERS command */
5150 silc_server_packet_send(server, server->router->connection,
5151 SILC_PACKET_COMMAND, cmd->packet->flags,
5152 tmpbuf->data, tmpbuf->len, TRUE);
5154 /* Reprocess this packet after received reply */
5155 silc_server_command_pending(server, SILC_COMMAND_USERS,
5156 silc_command_get_ident(cmd->payload),
5157 silc_server_command_users,
5158 silc_server_command_dup(cmd));
5159 cmd->pending = TRUE;
5160 silc_command_set_ident(cmd->payload, ident);
5161 silc_buffer_free(tmpbuf);
5166 /* Check the global list as well. */
5168 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5170 channel = silc_idlist_find_channel_by_name(server->global_list,
5171 channel_name, NULL);
5173 /* Channel really does not exist */
5174 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5175 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5180 /* If the channel is private or secret do not send anything, unless the
5181 user requesting this command is on the channel. */
5182 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5183 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5184 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5186 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5191 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5193 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5198 /* Get the users list */
5199 silc_server_get_users_on_channel(server, channel, &client_id_list,
5200 &client_mode_list, &list_count);
5203 SILC_PUT32_MSB(list_count, lc);
5206 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5207 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5208 SILC_STATUS_OK, ident, 4,
5209 2, idp->data, idp->len,
5211 4, client_id_list->data,
5212 client_id_list->len,
5213 5, client_mode_list->data,
5214 client_mode_list->len);
5215 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5216 packet->data, packet->len, FALSE);
5218 silc_buffer_free(idp);
5219 silc_buffer_free(packet);
5220 silc_buffer_free(client_id_list);
5221 silc_buffer_free(client_mode_list);
5225 silc_server_command_free(cmd);
5228 /* Server side of command GETKEY. This fetches the client's public key
5229 from the server where to the client is connected. */
5231 SILC_SERVER_CMD_FUNC(getkey)
5233 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5234 SilcServer server = cmd->server;
5236 SilcClientEntry client;
5237 SilcServerEntry server_entry;
5238 SilcClientID *client_id = NULL;
5239 SilcServerID *server_id = NULL;
5240 SilcIDPayload idp = NULL;
5241 uint16 ident = silc_command_get_ident(cmd->payload);
5242 unsigned char *tmp, *pkdata;
5243 uint32 tmp_len, pklen;
5244 SilcBuffer pk = NULL;
5246 SilcPublicKey public_key;
5248 SILC_LOG_DEBUG(("Start"));
5250 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5253 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5256 idp = silc_id_payload_parse(tmp, tmp_len);
5258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5259 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5263 id_type = silc_id_payload_get_type(idp);
5264 if (id_type == SILC_ID_CLIENT) {
5265 client_id = silc_id_payload_get_id(idp);
5267 /* If the client is not found from local list there is no chance it
5268 would be locally connected client so send the command further. */
5269 client = silc_idlist_find_client_by_id(server->local_list,
5270 client_id, TRUE, NULL);
5272 client = silc_idlist_find_client_by_id(server->global_list,
5273 client_id, TRUE, NULL);
5275 if ((!client && !cmd->pending && !server->standalone) ||
5276 (client && !client->connection && !cmd->pending) ||
5277 (client && !client->data.public_key && !cmd->pending)) {
5280 SilcSocketConnection dest_sock;
5282 dest_sock = silc_server_get_client_route(server, NULL, 0,
5287 old_ident = silc_command_get_ident(cmd->payload);
5288 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5289 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5291 silc_server_packet_send(server, dest_sock,
5292 SILC_PACKET_COMMAND, cmd->packet->flags,
5293 tmpbuf->data, tmpbuf->len, TRUE);
5295 /* Reprocess this packet after received reply from router */
5296 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5297 silc_command_get_ident(cmd->payload),
5298 silc_server_command_getkey,
5299 silc_server_command_dup(cmd));
5300 cmd->pending = TRUE;
5301 silc_command_set_ident(cmd->payload, old_ident);
5302 silc_buffer_free(tmpbuf);
5307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5308 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5312 /* The client is locally connected, just get the public key and
5313 send it back. If they key does not exist then do not send it,
5314 send just OK reply */
5315 public_key = client->data.public_key;
5320 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5321 pk = silc_buffer_alloc(4 + tmp_len);
5322 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5323 silc_buffer_format(pk,
5324 SILC_STR_UI_SHORT(tmp_len),
5325 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5326 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5332 } else if (id_type == SILC_ID_SERVER) {
5333 server_id = silc_id_payload_get_id(idp);
5335 /* If the server is not found from local list there is no chance it
5336 would be locally connected server so send the command further. */
5337 server_entry = silc_idlist_find_server_by_id(server->local_list,
5338 server_id, TRUE, NULL);
5340 server_entry = silc_idlist_find_server_by_id(server->global_list,
5341 server_id, TRUE, NULL);
5343 if (server_entry != server->id_entry &&
5344 ((!server_entry && !cmd->pending && !server->standalone) ||
5345 (server_entry && !server_entry->connection && !cmd->pending &&
5346 !server->standalone) ||
5347 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5348 !server->standalone))) {
5352 old_ident = silc_command_get_ident(cmd->payload);
5353 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5354 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5356 silc_server_packet_send(server, server->router->connection,
5357 SILC_PACKET_COMMAND, cmd->packet->flags,
5358 tmpbuf->data, tmpbuf->len, TRUE);
5360 /* Reprocess this packet after received reply from router */
5361 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5362 silc_command_get_ident(cmd->payload),
5363 silc_server_command_getkey,
5364 silc_server_command_dup(cmd));
5365 cmd->pending = TRUE;
5366 silc_command_set_ident(cmd->payload, old_ident);
5367 silc_buffer_free(tmpbuf);
5371 if (!server_entry) {
5372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5373 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5377 /* If they key does not exist then do not send it, send just OK reply */
5378 public_key = (!server_entry->data.public_key ?
5379 (server_entry == server->id_entry ? server->public_key :
5380 NULL) : server_entry->data.public_key);
5385 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5386 pk = silc_buffer_alloc(4 + tmp_len);
5387 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5388 silc_buffer_format(pk,
5389 SILC_STR_UI_SHORT(tmp_len),
5390 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5391 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5401 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5402 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5403 SILC_STATUS_OK, ident,
5407 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5408 packet->data, packet->len, FALSE);
5409 silc_buffer_free(packet);
5412 silc_buffer_free(pk);
5416 silc_id_payload_free(idp);
5417 silc_free(client_id);
5418 silc_free(server_id);
5419 silc_server_command_free(cmd);