5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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(ping, PING, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
62 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(silcoper, SILCOPER,
69 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
70 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
71 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
72 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
74 SILC_SERVER_CMD(connect, PRIV_CONNECT,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
76 SILC_SERVER_CMD(close, PRIV_CLOSE,
77 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
78 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
84 /* Performs several checks to the command. It first checks whether this
85 command was called as pending command callback. If it was then it checks
86 whether error occurred in the command reply where the pending command
89 It also checks that the requested command includes correct amount
91 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
95 SILC_LOG_DEBUG(("Start")); \
97 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
98 silc_server_command_free(cmd); \
102 _argc = silc_argument_get_arg_num(cmd->args); \
104 silc_server_command_send_status_reply(cmd, command, \
105 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
106 silc_server_command_free(cmd); \
110 silc_server_command_send_status_reply(cmd, command, \
111 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
112 silc_server_command_free(cmd); \
117 /* Returns TRUE if the connection is registered. Unregistered connections
118 usually cannot send commands hence the check. */
120 static int silc_server_is_registered(SilcServer server,
121 SilcSocketConnection sock,
122 SilcServerCommandContext cmd,
125 SilcIDListData idata = (SilcIDListData)sock->user_data;
130 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
133 silc_server_command_send_status_reply(cmd, command,
134 SILC_STATUS_ERR_NOT_REGISTERED);
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;
153 silc_server_command_free(timeout->ctx);
157 /* Update access time */
158 client->last_command = time(NULL);
160 if (!(timeout->cmd->flags & SILC_CF_REG))
161 timeout->cmd->cb(timeout->ctx, NULL);
162 else if (silc_server_is_registered(timeout->ctx->server,
166 timeout->cmd->cb(timeout->ctx, NULL);
168 silc_server_command_free(timeout->ctx);
173 /* Processes received command packet. */
175 void silc_server_command_process(SilcServer server,
176 SilcSocketConnection sock,
177 SilcPacketContext *packet)
179 SilcServerCommandContext ctx;
180 SilcServerCommand *cmd;
183 /* Allocate command context. This must be free'd by the
184 command routine receiving it. */
185 ctx = silc_server_command_alloc();
186 ctx->server = server;
187 ctx->sock = silc_socket_dup(sock);
188 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
190 /* Parse the command payload in the packet */
191 ctx->payload = silc_command_payload_parse(packet->buffer->data,
192 packet->buffer->len);
194 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
195 silc_buffer_free(packet->buffer);
196 silc_packet_context_free(packet);
197 silc_socket_free(ctx->sock);
201 ctx->args = silc_command_get_args(ctx->payload);
203 /* Get the command */
204 command = silc_command_get(ctx->payload);
205 for (cmd = silc_command_list; cmd->cb; cmd++)
206 if (cmd->cmd == command)
209 if (!cmd || !cmd->cb) {
210 silc_server_command_send_status_reply(ctx, command,
211 SILC_STATUS_ERR_UNKNOWN_COMMAND);
212 silc_server_command_free(ctx);
216 /* Execute client's commands always with timeout. Normally they are
217 executed with zero (0) timeout but if client is sending command more
218 frequently than once in 2 seconds, then the timeout may be 0 to 2
220 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
221 SilcClientEntry client = (SilcClientEntry)sock->user_data;
222 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
228 if (client->last_command && (time(NULL) - client->last_command) < 2) {
229 client->fast_command++;
232 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
233 client->fast_command--);
237 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
238 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
239 silc_schedule_task_add(server->schedule, sock->sock,
240 silc_server_command_process_timeout,
242 2 - (time(NULL) - client->last_command), 0,
243 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
245 silc_schedule_task_add(server->schedule, sock->sock,
246 silc_server_command_process_timeout,
247 (void *)timeout, 0, 1,
248 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
252 /* Execute for server */
254 if (!(cmd->flags & SILC_CF_REG))
256 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
259 silc_server_command_free(ctx);
262 /* Allocate Command Context */
264 SilcServerCommandContext silc_server_command_alloc()
266 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
271 /* Free's the command context allocated before executing the command */
273 void silc_server_command_free(SilcServerCommandContext ctx)
276 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
278 if (ctx->users < 1) {
280 silc_command_payload_free(ctx->payload);
282 silc_packet_context_free(ctx->packet);
284 silc_socket_free(ctx->sock); /* Decrease reference counter */
289 /* Duplicate Command Context by adding reference counter. The context won't
290 be free'd untill it hits zero. */
292 SilcServerCommandContext
293 silc_server_command_dup(SilcServerCommandContext ctx)
296 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
301 /* Add new pending command to be executed when reply to a command has been
302 received. The `reply_cmd' is the command that will call the `callback'
303 with `context' when reply has been received. It can be SILC_COMMAND_NONE
304 to match any command with the `ident'. If `ident' is non-zero
305 the `callback' will be executed when received reply with command
306 identifier `ident'. If there already exists pending command for the
307 specified command, ident, callback and context this function has no
310 bool silc_server_command_pending(SilcServer server,
311 SilcCommand reply_cmd,
313 SilcCommandCb callback,
316 SilcServerCommandPending *reply;
318 /* Check whether identical pending already exists for same command,
319 ident, callback and callback context. If it does then it would be
320 error to register it again. */
321 silc_dlist_start(server->pending_commands);
322 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
323 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
324 reply->callback == callback && reply->context == context)
328 reply = silc_calloc(1, sizeof(*reply));
329 reply->reply_cmd = reply_cmd;
330 reply->ident = ident;
331 reply->context = context;
332 reply->callback = callback;
333 silc_dlist_add(server->pending_commands, reply);
338 /* Deletes pending command by reply command type. */
340 void silc_server_command_pending_del(SilcServer server,
341 SilcCommand reply_cmd,
344 SilcServerCommandPending *r;
346 silc_dlist_start(server->pending_commands);
347 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
348 if (r->reply_cmd == reply_cmd && r->ident == ident) {
349 silc_dlist_del(server->pending_commands, r);
355 /* Checks for pending commands and marks callbacks to be called from
356 the command reply function. Returns TRUE if there were pending command. */
358 SilcServerCommandPendingCallbacks
359 silc_server_command_pending_check(SilcServer server,
360 SilcServerCommandReplyContext ctx,
363 SilcUInt32 *callbacks_count)
365 SilcServerCommandPending *r;
366 SilcServerCommandPendingCallbacks callbacks = NULL;
369 silc_dlist_start(server->pending_commands);
370 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
371 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
372 && r->ident == ident) {
373 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
374 callbacks[i].context = r->context;
375 callbacks[i].callback = r->callback;
381 *callbacks_count = i;
385 /* Sends simple status message as command reply packet */
388 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
390 SilcCommandStatus status)
394 SILC_LOG_DEBUG(("Sending command status %d", status));
397 silc_command_reply_payload_encode_va(command, status,
398 silc_command_get_ident(cmd->payload),
400 silc_server_packet_send(cmd->server, cmd->sock,
401 SILC_PACKET_COMMAND_REPLY, 0,
402 buffer->data, buffer->len, FALSE);
403 silc_buffer_free(buffer);
406 /* Sends command status reply with one extra argument. The argument
407 type must be sent as argument. */
410 silc_server_command_send_status_data(SilcServerCommandContext cmd,
412 SilcCommandStatus status,
414 const unsigned char *arg,
419 SILC_LOG_DEBUG(("Sending command status %d", status));
422 silc_command_reply_payload_encode_va(command, status,
423 silc_command_get_ident(cmd->payload),
424 1, arg_type, arg, arg_len);
425 silc_server_packet_send(cmd->server, cmd->sock,
426 SILC_PACKET_COMMAND_REPLY, 0,
427 buffer->data, buffer->len, FALSE);
428 silc_buffer_free(buffer);
431 /* This function can be called to check whether in the command reply
432 an error occurred. This function has no effect if this is called
433 when the command function was not called as pending command callback.
434 This returns TRUE if error had occurred. */
437 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
438 SilcServerCommandReplyContext cmdr,
441 SilcCommandStatus status;
443 if (!cmd->pending || !cmdr)
446 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
447 if (status != SILC_STATUS_OK &&
448 status != SILC_STATUS_LIST_START &&
449 status != SILC_STATUS_LIST_ITEM &&
450 status != SILC_STATUS_LIST_END) {
453 /* Send the same command reply payload */
454 silc_command_set_ident(cmdr->payload,
455 silc_command_get_ident(cmd->payload));
456 buffer = silc_command_payload_encode_payload(cmdr->payload);
457 silc_server_packet_send(cmd->server, cmd->sock,
458 SILC_PACKET_COMMAND_REPLY, 0,
459 buffer->data, buffer->len, FALSE);
460 silc_buffer_free(buffer);
467 /******************************************************************************
471 ******************************************************************************/
474 silc_server_command_whois_parse(SilcServerCommandContext cmd,
475 SilcClientID ***client_id,
476 SilcUInt32 *client_id_count,
484 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
487 /* If client ID is in the command it must be used instead of nickname */
488 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
490 /* No ID, get the nickname@server string and parse it. */
491 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
493 silc_parse_userfqdn(tmp, nickname, server_name);
495 silc_server_command_send_status_reply(cmd, command,
496 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
500 /* Command includes ID, we must use that. Also check whether the command
501 has more than one ID set - take them all. */
503 *client_id = silc_calloc(1, sizeof(**client_id));
504 (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
505 if ((*client_id)[0] == NULL) {
506 silc_free(*client_id);
507 silc_server_command_send_status_reply(cmd, command,
508 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
511 *client_id_count = 1;
513 /* Take all ID's from the command packet */
515 for (k = 1, i = 1; i < argc; i++) {
516 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
518 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
519 (*client_id_count + 1));
520 (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
521 if ((*client_id)[k] == NULL) {
522 /* Cleanup all and fail */
523 for (i = 0; i < *client_id_count; i++)
524 silc_free((*client_id)[i]);
525 silc_free(*client_id);
526 silc_server_command_send_status_reply(
528 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
531 (*client_id_count)++;
538 /* Get the max count of reply messages allowed */
539 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
548 /* Resolve context used by both WHOIS and IDENTIFY commands */
550 SilcServerEntry router;
552 unsigned char **res_argv;
553 SilcUInt32 *res_argv_lens;
554 SilcUInt32 *res_argv_types;
556 } *SilcServerResolveContext;
559 silc_server_command_whois_check(SilcServerCommandContext cmd,
560 SilcClientEntry *clients,
561 SilcUInt32 clients_count)
563 SilcServer server = cmd->server;
564 SilcClientEntry entry;
565 SilcServerResolveContext resolve = NULL, r = NULL;
566 SilcUInt32 resolve_count = 0;
570 SILC_LOG_DEBUG(("Start"));
572 for (i = 0; i < clients_count; i++) {
577 if ((entry->nickname && entry->username && entry->userinfo) ||
578 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
582 /* If we are normal server, and we've not resolved this client from
583 router and it is global client, we'll check whether it is on some
584 channel. If not then we cannot be sure about its validity, and
585 we'll resolve it from router. */
586 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
587 entry->connection || silc_hash_table_count(entry->channels))
591 /* We need to resolve this entry since it is not complete */
593 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
594 /* The entry is being resolved (and we are not the resolver) so attach
595 to the command reply and we're done with this one. */
596 silc_server_command_pending(server, SILC_COMMAND_NONE,
597 entry->resolve_cmd_ident,
598 silc_server_command_whois,
599 silc_server_command_dup(cmd));
602 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
603 /* We've resolved this and it still is not ready. We'll return
604 and are that this will be handled again after it is resolved. */
605 for (i = 0; i < resolve_count; i++) {
606 for (k = 0; k < r->res_argc; k++)
607 silc_free(r->res_argv[k]);
608 silc_free(r->res_argv);
609 silc_free(r->res_argv_lens);
610 silc_free(r->res_argv_types);
615 /* We'll resolve this client */
619 for (k = 0; k < resolve_count; k++) {
620 if (resolve[k].router == entry->router) {
627 resolve = silc_realloc(resolve, sizeof(*resolve) *
628 (resolve_count + 1));
629 r = &resolve[resolve_count];
630 memset(r, 0, sizeof(*r));
631 r->router = entry->router;
632 r->ident = ++server->cmd_ident;
636 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
638 r->res_argv_lens = silc_realloc(r->res_argv_lens,
639 sizeof(*r->res_argv_lens) *
641 r->res_argv_types = silc_realloc(r->res_argv_types,
642 sizeof(*r->res_argv_types) *
644 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
645 r->res_argv[r->res_argc] = silc_calloc(idp->len,
646 sizeof(**r->res_argv));
647 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
648 r->res_argv_lens[r->res_argc] = idp->len;
649 r->res_argv_types[r->res_argc] = r->res_argc + 3;
651 silc_buffer_free(idp);
653 entry->resolve_cmd_ident = r->ident;
654 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
655 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
660 /* Do the resolving */
661 for (i = 0; i < resolve_count; i++) {
666 /* Send WHOIS request. We send WHOIS since we're doing the requesting
667 now anyway so make it a good one. */
668 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
669 r->res_argc, r->res_argv,
673 silc_server_packet_send(server, r->router->connection,
674 SILC_PACKET_COMMAND, cmd->packet->flags,
675 res_cmd->data, res_cmd->len, FALSE);
677 /* Reprocess this packet after received reply */
678 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
680 silc_server_command_whois,
681 silc_server_command_dup(cmd));
684 silc_buffer_free(res_cmd);
685 for (k = 0; k < r->res_argc; k++)
686 silc_free(r->res_argv[k]);
687 silc_free(r->res_argv);
688 silc_free(r->res_argv_lens);
689 silc_free(r->res_argv_types);
698 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
699 SilcClientEntry *clients,
700 SilcUInt32 clients_count,
702 const char *nickname,
703 SilcClientID **client_ids)
705 SilcServer server = cmd->server;
707 int i, k, len, valid_count;
708 SilcBuffer packet, idp, channels;
709 SilcClientEntry entry;
710 SilcCommandStatus status;
711 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
712 char nh[256], uh[256];
713 unsigned char idle[4], mode[4];
714 unsigned char *fingerprint;
715 SilcSocketConnection hsock;
717 /* Process only valid clients and ignore those that are not registered. */
719 for (i = 0; i < clients_count; i++) {
720 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
727 /* No valid clients found, send error reply */
729 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
730 SILC_STATUS_ERR_NO_SUCH_NICK,
731 3, nickname, strlen(nickname));
732 } else if (client_ids && client_ids[0]) {
733 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
734 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
735 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
736 2, idp->data, idp->len);
737 silc_buffer_free(idp);
742 /* Start processing found clients. */
744 status = SILC_STATUS_LIST_START;
746 status = SILC_STATUS_OK;
748 for (i = 0, k = 0; i < clients_count; i++) {
754 status = SILC_STATUS_LIST_ITEM;
755 if (valid_count > 1 && k == valid_count - 1)
756 status = SILC_STATUS_LIST_END;
757 if (count && k - 1 == count)
758 status = SILC_STATUS_LIST_END;
760 /* Send WHOIS reply */
761 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
762 tmp = silc_argument_get_first_arg(cmd->args, NULL);
764 memset(uh, 0, sizeof(uh));
765 memset(nh, 0, sizeof(nh));
766 memset(idle, 0, sizeof(idle));
768 strncat(nh, entry->nickname, strlen(entry->nickname));
769 if (!strchr(entry->nickname, '@')) {
771 if (entry->servername) {
772 strncat(nh, entry->servername, strlen(entry->servername));
774 len = entry->router ? strlen(entry->router->server_name) :
775 strlen(server->server_name);
776 strncat(nh, entry->router ? entry->router->server_name :
777 server->server_name, len);
781 strncat(uh, entry->username, strlen(entry->username));
782 if (!strchr(entry->username, '@')) {
784 hsock = (SilcSocketConnection)entry->connection;
785 len = strlen(hsock->hostname);
786 strncat(uh, hsock->hostname, len);
789 channels = silc_server_get_client_channel_list(server, entry);
791 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
792 fingerprint = entry->data.fingerprint;
796 SILC_PUT32_MSB(entry->mode, mode);
798 if (entry->connection) {
799 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
803 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
805 2, idp->data, idp->len,
809 strlen(entry->userinfo),
810 6, channels ? channels->data : NULL,
811 channels ? channels->len : 0,
815 fingerprint ? 20 : 0);
817 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
818 0, packet->data, packet->len, FALSE);
820 silc_buffer_free(packet);
821 silc_buffer_free(idp);
823 silc_buffer_free(channels);
830 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
832 SilcServer server = cmd->server;
834 SilcUInt16 old_ident;
836 old_ident = silc_command_get_ident(cmd->payload);
837 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
838 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
840 /* Send WHOIS command to our router */
841 silc_server_packet_send(server, (SilcSocketConnection)
842 server->router->connection,
843 SILC_PACKET_COMMAND, cmd->packet->flags,
844 tmpbuf->data, tmpbuf->len, TRUE);
846 /* Reprocess this packet after received reply from router */
847 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
848 silc_command_get_ident(cmd->payload),
849 silc_server_command_whois,
850 silc_server_command_dup(cmd));
852 silc_command_set_ident(cmd->payload, old_ident);
853 silc_buffer_free(tmpbuf);
857 silc_server_command_whois_process(SilcServerCommandContext cmd)
859 SilcServer server = cmd->server;
860 char *nick = NULL, *server_name = NULL;
862 SilcClientEntry *clients = NULL, entry;
863 SilcClientID **client_id = NULL;
864 SilcUInt32 client_id_count = 0, clients_count = 0;
866 bool check_global = FALSE;
868 /* Parse the whois request */
869 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
870 &nick, &server_name, &count,
874 /* Send the WHOIS request to the router only if it included nickname.
875 Since nicknames can be expanded into many clients we need to send it
876 to router. If the WHOIS included only client ID's we will check them
877 first locally since we just might have them. */
878 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
879 server->server_type == SILC_SERVER && !cmd->pending &&
880 !server->standalone) {
881 silc_server_command_whois_send_router(cmd);
886 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
888 else if (server->server_type != SILC_SERVER)
891 /* Get all clients matching that ID or nickname from local list */
892 if (client_id_count) {
893 /* Check all Client ID's received in the command packet */
894 for (i = 0; i < client_id_count; i++) {
895 entry = silc_idlist_find_client_by_id(server->local_list,
896 client_id[i], TRUE, NULL);
897 if (!entry && check_global)
898 entry = silc_idlist_find_client_by_id(server->global_list,
899 client_id[i], TRUE, NULL);
901 clients = silc_realloc(clients, sizeof(*clients) *
902 (clients_count + 1));
903 clients[clients_count++] = entry;
905 /* If we are normal server and did not send the request first to router
906 do it now, since we do not have the Client ID information. */
907 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
908 server->server_type == SILC_SERVER && !cmd->pending &&
909 !server->standalone) {
910 silc_server_command_whois_send_router(cmd);
917 /* Find by nickname */
918 if (!silc_idlist_get_clients_by_hash(server->local_list,
919 nick, server->md5hash,
920 &clients, &clients_count))
921 silc_idlist_get_clients_by_nickname(server->local_list,
923 &clients, &clients_count);
925 if (!silc_idlist_get_clients_by_hash(server->global_list,
926 nick, server->md5hash,
927 &clients, &clients_count))
928 silc_idlist_get_clients_by_nickname(server->global_list,
930 &clients, &clients_count);
935 /* If we are normal server and did not send the request first to router
936 do it now, since we do not have the information. */
937 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
938 server->server_type == SILC_SERVER && !cmd->pending &&
939 !server->standalone) {
940 silc_server_command_whois_send_router(cmd);
945 /* Such client(s) really does not exist in the SILC network. */
946 if (!client_id_count) {
947 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
948 SILC_STATUS_ERR_NO_SUCH_NICK,
949 3, nick, strlen(nick));
951 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
952 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
953 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
954 2, idp->data, idp->len);
955 silc_buffer_free(idp);
960 /* Router always finds the client entry if it exists in the SILC network.
961 However, it might be incomplete entry and does not include all the
962 mandatory fields that WHOIS command reply requires. Check for these and
963 make query from the server who owns the client if some fields are
965 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
970 /* Send the command reply */
971 silc_server_command_whois_send_reply(cmd, clients, clients_count,
972 count, nick, client_id);
975 if (client_id_count) {
976 for (i = 0; i < client_id_count; i++)
977 silc_free(client_id[i]);
978 silc_free(client_id);
982 silc_free(server_name);
987 /* Server side of command WHOIS. Processes user's query and sends found
988 results as command replies back to the client. */
990 SILC_SERVER_CMD_FUNC(whois)
992 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
995 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
997 ret = silc_server_command_whois_process(cmd);
998 silc_server_command_free(cmd);
1001 /******************************************************************************
1005 ******************************************************************************/
1008 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1016 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1019 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1023 /* Get the nickname@server string and parse it. */
1024 silc_parse_userfqdn(tmp, nickname, server_name);
1026 /* Get the max count of reply messages allowed */
1027 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1037 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1038 SilcClientEntry *clients,
1039 SilcUInt32 clients_count)
1041 SilcServer server = cmd->server;
1043 SilcClientEntry entry;
1045 for (i = 0; i < clients_count; i++) {
1048 if (!entry->nickname || !entry->username) {
1050 SilcUInt16 old_ident;
1055 old_ident = silc_command_get_ident(cmd->payload);
1056 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1057 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1059 /* Send WHOWAS command */
1060 silc_server_packet_send(server, entry->router->connection,
1061 SILC_PACKET_COMMAND, cmd->packet->flags,
1062 tmpbuf->data, tmpbuf->len, TRUE);
1064 /* Reprocess this packet after received reply */
1065 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1066 silc_command_get_ident(cmd->payload),
1067 silc_server_command_whowas,
1068 silc_server_command_dup(cmd));
1069 cmd->pending = TRUE;
1070 silc_command_set_ident(cmd->payload, old_ident);
1072 silc_buffer_free(tmpbuf);
1081 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1082 SilcClientEntry *clients,
1083 SilcUInt32 clients_count)
1085 SilcServer server = cmd->server;
1087 int i, k, count = 0, len;
1088 SilcBuffer packet, idp;
1089 SilcClientEntry entry = NULL;
1090 SilcCommandStatus status;
1091 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1092 char nh[256], uh[256];
1095 status = SILC_STATUS_OK;
1097 /* Process only entries that are not registered anymore. */
1099 for (i = 0; i < clients_count; i++) {
1100 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1107 /* No valid entries found at all, just send error */
1110 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1112 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1113 SILC_STATUS_ERR_NO_SUCH_NICK,
1114 3, tmp, strlen(tmp));
1118 if (valid_count > 1)
1119 status = SILC_STATUS_LIST_START;
1121 for (i = 0, k = 0; i < clients_count; i++) {
1127 status = SILC_STATUS_LIST_ITEM;
1128 if (valid_count > 1 && k == valid_count - 1)
1129 status = SILC_STATUS_LIST_END;
1130 if (count && k - 1 == count)
1131 status = SILC_STATUS_LIST_END;
1132 if (count && k - 1 > count)
1135 /* Send WHOWAS reply */
1136 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1137 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1138 memset(uh, 0, sizeof(uh));
1139 memset(nh, 0, sizeof(nh));
1141 strncat(nh, entry->nickname, strlen(entry->nickname));
1142 if (!strchr(entry->nickname, '@')) {
1143 strncat(nh, "@", 1);
1144 if (entry->servername) {
1145 strncat(nh, entry->servername, strlen(entry->servername));
1147 len = entry->router ? strlen(entry->router->server_name) :
1148 strlen(server->server_name);
1149 strncat(nh, entry->router ? entry->router->server_name :
1150 server->server_name, len);
1154 strncat(uh, entry->username, strlen(entry->username));
1155 if (!strchr(entry->username, '@')) {
1156 strncat(uh, "@", 1);
1157 strcat(uh, "*private*");
1161 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1163 2, idp->data, idp->len,
1168 strlen(entry->userinfo) : 0);
1169 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1170 0, packet->data, packet->len, FALSE);
1172 silc_buffer_free(packet);
1173 silc_buffer_free(idp);
1180 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1182 SilcServer server = cmd->server;
1183 char *nick = NULL, *server_name = NULL;
1185 SilcClientEntry *clients = NULL;
1186 SilcUInt32 clients_count = 0;
1188 bool check_global = FALSE;
1190 /* Protocol dictates that we must always send the received WHOWAS request
1191 to our router if we are normal server, so let's do it now unless we
1192 are standalone. We will not send any replies to the client until we
1193 have received reply from the router. */
1194 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1195 server->server_type == SILC_SERVER && !cmd->pending &&
1196 !server->standalone) {
1198 SilcUInt16 old_ident;
1200 old_ident = silc_command_get_ident(cmd->payload);
1201 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1202 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1204 /* Send WHOWAS command to our router */
1205 silc_server_packet_send(server, (SilcSocketConnection)
1206 server->router->connection,
1207 SILC_PACKET_COMMAND, cmd->packet->flags,
1208 tmpbuf->data, tmpbuf->len, TRUE);
1210 /* Reprocess this packet after received reply from router */
1211 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1212 silc_command_get_ident(cmd->payload),
1213 silc_server_command_whowas,
1214 silc_server_command_dup(cmd));
1215 cmd->pending = TRUE;
1216 silc_command_set_ident(cmd->payload, old_ident);
1218 silc_buffer_free(tmpbuf);
1223 /* We are ready to process the command request. Let's search for the
1224 requested client and send reply to the requesting client. */
1226 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1227 check_global = TRUE;
1228 else if (server->server_type != SILC_SERVER)
1229 check_global = TRUE;
1231 /* Parse the whowas request */
1232 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1235 /* Get all clients matching that nickname from local list */
1236 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1238 &clients, &clients_count))
1239 silc_idlist_get_clients_by_hash(server->local_list,
1240 nick, server->md5hash,
1241 &clients, &clients_count);
1243 /* Check global list as well */
1245 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1247 &clients, &clients_count))
1248 silc_idlist_get_clients_by_hash(server->global_list,
1249 nick, server->md5hash,
1250 &clients, &clients_count);
1254 /* Such a client really does not exist in the SILC network. */
1255 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1256 SILC_STATUS_ERR_NO_SUCH_NICK,
1257 3, nick, strlen(nick));
1261 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1266 /* Send the command reply to the client */
1267 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1272 silc_free(server_name);
1276 /* Server side of command WHOWAS. */
1278 SILC_SERVER_CMD_FUNC(whowas)
1280 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1283 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1285 ret = silc_server_command_whowas_process(cmd);
1286 silc_server_command_free(cmd);
1289 /******************************************************************************
1293 ******************************************************************************/
1296 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1298 SilcServer server = cmd->server;
1300 SilcUInt16 old_ident;
1302 old_ident = silc_command_get_ident(cmd->payload);
1303 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1304 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1306 /* Send IDENTIFY command to our router */
1307 silc_server_packet_send(server, (SilcSocketConnection)
1308 server->router->connection,
1309 SILC_PACKET_COMMAND, cmd->packet->flags,
1310 tmpbuf->data, tmpbuf->len, TRUE);
1312 /* Reprocess this packet after received reply from router */
1313 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1314 silc_command_get_ident(cmd->payload),
1315 silc_server_command_identify,
1316 silc_server_command_dup(cmd));
1317 cmd->pending = TRUE;
1318 silc_command_set_ident(cmd->payload, old_ident);
1319 silc_buffer_free(tmpbuf);
1323 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1324 SilcClientEntry **clients,
1325 SilcUInt32 *clients_count,
1326 SilcServerEntry **servers,
1327 SilcUInt32 *servers_count,
1328 SilcChannelEntry **channels,
1329 SilcUInt32 *channels_count,
1332 SilcServer server = cmd->server;
1335 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1337 bool check_global = FALSE;
1342 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1343 check_global = TRUE;
1344 else if (server->server_type != SILC_SERVER)
1345 check_global = TRUE;
1347 /* If ID Payload is in the command it must be used instead of names */
1348 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1350 /* No ID, get the names. */
1352 /* If we are normal server and have not resolved information from
1353 router yet, do so now. */
1354 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1355 server->server_type == SILC_SERVER && !cmd->pending &&
1356 !server->standalone) {
1357 silc_server_command_identify_send_router(cmd);
1361 /* Try to get nickname@server. */
1362 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1365 char *nick_server = NULL;
1367 silc_parse_userfqdn(tmp, &nick, &nick_server);
1369 if (!silc_idlist_get_clients_by_hash(server->local_list,
1370 nick, server->md5hash,
1371 clients, clients_count))
1372 silc_idlist_get_clients_by_nickname(server->local_list,
1374 clients, clients_count);
1376 if (!silc_idlist_get_clients_by_hash(server->global_list,
1377 nick, server->md5hash,
1378 clients, clients_count))
1379 silc_idlist_get_clients_by_nickname(server->global_list,
1381 clients, clients_count);
1385 silc_free(nick_server);
1388 /* the nickname does not exist, send error reply */
1389 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1390 SILC_STATUS_ERR_NO_SUCH_NICK,
1391 3, tmp, strlen(tmp));
1396 /* Try to get server name */
1397 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1399 entry = silc_idlist_find_server_by_name(server->local_list,
1401 if (!entry && check_global)
1402 entry = silc_idlist_find_server_by_name(server->global_list,
1405 *servers = silc_realloc(*servers, sizeof(**servers) *
1406 (*servers_count + 1));
1407 (*servers)[(*servers_count)++] = entry;
1411 /* the server does not exist, send error reply */
1412 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1413 SILC_STATUS_ERR_NO_SUCH_SERVER,
1414 3, tmp, strlen(tmp));
1419 /* Try to get channel name */
1420 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1422 entry = silc_idlist_find_channel_by_name(server->local_list,
1424 if (!entry && check_global)
1425 entry = silc_idlist_find_channel_by_name(server->global_list,
1428 *channels = silc_realloc(*channels, sizeof(**channels) *
1429 (*channels_count + 1));
1430 (*channels)[(*channels_count)++] = entry;
1434 /* The channel does not exist, send error reply */
1435 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1436 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1437 3, tmp, strlen(tmp));
1442 if (!(*clients) && !(*servers) && !(*channels)) {
1443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1444 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1448 /* Command includes ID, we must use that. Also check whether the command
1449 has more than one ID set - take them all. */
1451 /* Take all ID's from the command packet */
1452 for (i = 0; i < argc; i++) {
1455 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1459 idp = silc_id_payload_parse(tmp, len);
1461 silc_free(*clients);
1462 silc_free(*servers);
1463 silc_free(*channels);
1464 silc_server_command_send_status_reply(
1465 cmd, SILC_COMMAND_IDENTIFY,
1466 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1470 id = silc_id_payload_get_id(idp);
1472 switch (silc_id_payload_get_type(idp)) {
1474 case SILC_ID_CLIENT:
1475 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1477 if (!entry && check_global)
1478 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1481 *clients = silc_realloc(*clients, sizeof(**clients) *
1482 (*clients_count + 1));
1483 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1485 /* If we are normal server and have not resolved information from
1486 router yet, do so now. */
1487 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1488 server->server_type == SILC_SERVER && !cmd->pending &&
1489 !server->standalone) {
1490 silc_server_command_identify_send_router(cmd);
1491 silc_free(*clients);
1492 silc_free(*servers);
1493 silc_free(*channels);
1496 silc_server_command_send_status_data(
1497 cmd, SILC_COMMAND_IDENTIFY,
1498 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1506 case SILC_ID_SERVER:
1507 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1509 if (!entry && check_global)
1510 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1513 *servers = silc_realloc(*servers, sizeof(**servers) *
1514 (*servers_count + 1));
1515 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1517 /* If we are normal server and have not resolved information from
1518 router yet, do so now. */
1519 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1520 server->server_type == SILC_SERVER && !cmd->pending &&
1521 !server->standalone) {
1522 silc_server_command_identify_send_router(cmd);
1523 silc_free(*clients);
1524 silc_free(*servers);
1525 silc_free(*channels);
1528 silc_server_command_send_status_data(
1529 cmd, SILC_COMMAND_IDENTIFY,
1530 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1537 case SILC_ID_CHANNEL:
1538 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1540 if (!entry && check_global)
1541 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1544 *channels = silc_realloc(*channels, sizeof(**channels) *
1545 (*channels_count + 1));
1546 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1548 /* If we are normal server and have not resolved information from
1549 router yet, do so now. */
1550 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1551 server->server_type == SILC_SERVER && !cmd->pending &&
1552 !server->standalone) {
1553 silc_server_command_identify_send_router(cmd);
1554 silc_free(*clients);
1555 silc_free(*servers);
1556 silc_free(*channels);
1559 silc_server_command_send_status_data(
1560 cmd, SILC_COMMAND_IDENTIFY,
1561 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1574 silc_free(*clients);
1575 silc_free(*servers);
1576 silc_free(*channels);
1580 /* Get the max count of reply messages allowed */
1581 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1590 /* Checks that all mandatory fields in client entry are present. If not
1591 then send WHOIS request to the server who owns the client. We use
1592 WHOIS because we want to get as much information as possible at once. */
1595 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1596 SilcClientEntry *clients,
1597 SilcUInt32 clients_count)
1599 SilcServer server = cmd->server;
1600 SilcClientEntry entry;
1601 SilcServerResolveContext resolve = NULL, r = NULL;
1602 SilcUInt32 resolve_count = 0;
1606 for (i = 0; i < clients_count; i++) {
1611 if (entry->nickname ||
1612 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1616 /* If we are normal server, and we've not resolved this client from
1617 router and it is global client, we'll check whether it is on some
1618 channel. If not then we cannot be sure about its validity, and
1619 we'll resolve it from router. */
1620 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1621 entry->connection || silc_hash_table_count(entry->channels))
1625 /* We need to resolve this entry since it is not complete */
1627 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1628 /* The entry is being resolved (and we are not the resolver) so attach
1629 to the command reply and we're done with this one. */
1630 silc_server_command_pending(server, SILC_COMMAND_NONE,
1631 entry->resolve_cmd_ident,
1632 silc_server_command_identify,
1633 silc_server_command_dup(cmd));
1636 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1637 /* We've resolved this and it still is not ready. We'll return
1638 and are that this will be handled again after it is resolved. */
1639 for (i = 0; i < resolve_count; i++) {
1640 for (k = 0; k < r->res_argc; k++)
1641 silc_free(r->res_argv[k]);
1642 silc_free(r->res_argv);
1643 silc_free(r->res_argv_lens);
1644 silc_free(r->res_argv_types);
1649 /* We'll resolve this client */
1653 for (k = 0; k < resolve_count; k++) {
1654 if (resolve[k].router == entry->router) {
1661 resolve = silc_realloc(resolve, sizeof(*resolve) *
1662 (resolve_count + 1));
1663 r = &resolve[resolve_count];
1664 memset(r, 0, sizeof(*r));
1665 r->router = entry->router;
1666 r->ident = ++server->cmd_ident;
1670 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1672 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1673 sizeof(*r->res_argv_lens) *
1675 r->res_argv_types = silc_realloc(r->res_argv_types,
1676 sizeof(*r->res_argv_types) *
1678 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1679 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1680 sizeof(**r->res_argv));
1681 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1682 r->res_argv_lens[r->res_argc] = idp->len;
1683 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1685 silc_buffer_free(idp);
1687 entry->resolve_cmd_ident = r->ident;
1688 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1689 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1694 /* Do the resolving */
1695 for (i = 0; i < resolve_count; i++) {
1700 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1701 now anyway so make it a good one. */
1702 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1703 r->res_argc, r->res_argv,
1707 silc_server_packet_send(server, r->router->connection,
1708 SILC_PACKET_COMMAND, cmd->packet->flags,
1709 res_cmd->data, res_cmd->len, FALSE);
1711 /* Reprocess this packet after received reply */
1712 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1714 silc_server_command_identify,
1715 silc_server_command_dup(cmd));
1716 cmd->pending = TRUE;
1718 silc_buffer_free(res_cmd);
1719 for (k = 0; k < r->res_argc; k++)
1720 silc_free(r->res_argv[k]);
1721 silc_free(r->res_argv);
1722 silc_free(r->res_argv_lens);
1723 silc_free(r->res_argv_types);
1732 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1733 SilcClientEntry *clients,
1734 SilcUInt32 clients_count,
1735 SilcServerEntry *servers,
1736 SilcUInt32 servers_count,
1737 SilcChannelEntry *channels,
1738 SilcUInt32 channels_count,
1741 SilcServer server = cmd->server;
1742 int i, k, len, valid_count;
1743 SilcBuffer packet, idp;
1744 SilcCommandStatus status;
1745 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1746 char nh[256], uh[256];
1747 SilcSocketConnection hsock;
1749 status = SILC_STATUS_OK;
1752 SilcClientEntry entry;
1754 /* Process only valid entries. */
1756 for (i = 0; i < clients_count; i++) {
1757 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1764 /* No valid entries found at all, just send error */
1767 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1769 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1770 SILC_STATUS_ERR_NO_SUCH_NICK,
1771 3, tmp, strlen(tmp));
1773 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1774 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1775 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1781 /* Process all valid client entries and send command replies */
1783 if (valid_count > 1)
1784 status = SILC_STATUS_LIST_START;
1786 for (i = 0, k = 0; i < clients_count; i++) {
1792 status = SILC_STATUS_LIST_ITEM;
1793 if (valid_count > 1 && k == valid_count - 1
1794 && !servers_count && !channels_count)
1795 status = SILC_STATUS_LIST_END;
1796 if (count && k - 1 == count)
1797 status = SILC_STATUS_LIST_END;
1798 if (count && k - 1 > count)
1801 /* Send IDENTIFY reply */
1803 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1804 memset(uh, 0, sizeof(uh));
1805 memset(nh, 0, sizeof(nh));
1806 strncat(nh, entry->nickname, strlen(entry->nickname));
1807 if (!strchr(entry->nickname, '@')) {
1808 strncat(nh, "@", 1);
1809 if (entry->servername) {
1810 strncat(nh, entry->servername, strlen(entry->servername));
1812 len = entry->router ? strlen(entry->router->server_name) :
1813 strlen(server->server_name);
1814 strncat(nh, entry->router ? entry->router->server_name :
1815 server->server_name, len);
1819 if (!entry->username) {
1820 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1822 2, idp->data, idp->len,
1825 strncat(uh, entry->username, strlen(entry->username));
1826 if (!strchr(entry->username, '@')) {
1827 strncat(uh, "@", 1);
1828 hsock = (SilcSocketConnection)entry->connection;
1829 len = strlen(hsock->hostname);
1830 strncat(uh, hsock->hostname, len);
1833 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1835 2, idp->data, idp->len,
1840 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1841 0, packet->data, packet->len, FALSE);
1843 silc_buffer_free(packet);
1844 silc_buffer_free(idp);
1851 SilcServerEntry entry;
1853 if (status == SILC_STATUS_OK && servers_count > 1)
1854 status = SILC_STATUS_LIST_START;
1856 for (i = 0, k = 0; i < servers_count; i++) {
1860 status = SILC_STATUS_LIST_ITEM;
1861 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1862 status = SILC_STATUS_LIST_END;
1863 if (count && k - 1 == count)
1864 status = SILC_STATUS_LIST_END;
1865 if (count && k - 1 > count)
1868 /* Send IDENTIFY reply */
1869 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1871 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1873 2, idp->data, idp->len,
1874 3, entry->server_name,
1875 entry->server_name ?
1876 strlen(entry->server_name) : 0);
1877 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1878 0, packet->data, packet->len, FALSE);
1880 silc_buffer_free(packet);
1881 silc_buffer_free(idp);
1888 SilcChannelEntry entry;
1890 if (status == SILC_STATUS_OK && channels_count > 1)
1891 status = SILC_STATUS_LIST_START;
1893 for (i = 0, k = 0; i < channels_count; i++) {
1894 entry = channels[i];
1897 status = SILC_STATUS_LIST_ITEM;
1898 if (channels_count > 1 && k == channels_count - 1)
1899 status = SILC_STATUS_LIST_END;
1900 if (count && k - 1 == count)
1901 status = SILC_STATUS_LIST_END;
1902 if (count && k - 1 > count)
1905 /* Send IDENTIFY reply */
1906 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1908 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1910 2, idp->data, idp->len,
1911 3, entry->channel_name,
1912 entry->channel_name ?
1913 strlen(entry->channel_name): 0);
1914 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1915 0, packet->data, packet->len, FALSE);
1917 silc_buffer_free(packet);
1918 silc_buffer_free(idp);
1926 silc_server_command_identify_process(SilcServerCommandContext cmd)
1928 SilcUInt32 count = 0;
1930 SilcClientEntry *clients = NULL;
1931 SilcServerEntry *servers = NULL;
1932 SilcChannelEntry *channels = NULL;
1933 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1935 /* Parse the IDENTIFY request */
1936 ret = silc_server_command_identify_parse(cmd,
1937 &clients, &clients_count,
1938 &servers, &servers_count,
1939 &channels, &channels_count,
1945 /* Check that all mandatory fields are present and request those data
1946 from the server who owns the client if necessary. */
1947 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1953 /* Send the command reply to the client */
1954 silc_server_command_identify_send_reply(cmd,
1955 clients, clients_count,
1956 servers, servers_count,
1957 channels, channels_count,
1963 silc_free(channels);
1967 SILC_SERVER_CMD_FUNC(identify)
1969 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1972 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1974 ret = silc_server_command_identify_process(cmd);
1975 silc_server_command_free(cmd);
1978 /* Server side of command NICK. Sets nickname for user. Setting
1979 nickname causes generation of a new client ID for the client. The
1980 new client ID is sent to the client after changing the nickname. */
1982 SILC_SERVER_CMD_FUNC(nick)
1984 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1985 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1986 SilcServer server = cmd->server;
1987 SilcBuffer packet, nidp, oidp = NULL;
1988 SilcClientID *new_id;
1989 SilcUInt32 nick_len;
1991 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1994 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1997 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1999 /* Check nickname */
2000 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2003 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2005 SILC_STATUS_ERR_BAD_NICKNAME);
2009 /* Check for same nickname */
2010 if (!strcmp(client->nickname, nick)) {
2011 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2015 /* Create new Client ID */
2016 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2018 cmd->server->md5hash, nick,
2021 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2024 /* Send notify about nickname change to our router. We send the new
2025 ID and ask to replace it with the old one. If we are router the
2026 packet is broadcasted. Send NICK_CHANGE notify. */
2027 if (!server->standalone)
2028 silc_server_send_notify_nick_change(server, server->router->connection,
2029 server->server_type == SILC_SERVER ?
2030 FALSE : TRUE, client->id,
2033 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2035 /* Remove old cache entry */
2036 silc_idcache_del_by_context(server->local_list->clients, client);
2039 silc_free(client->id);
2041 /* Save the nickname as this client is our local client */
2042 silc_free(client->nickname);
2044 client->nickname = strdup(nick);
2045 client->id = new_id;
2047 /* Update client cache */
2048 silc_idcache_add(server->local_list->clients, client->nickname,
2049 client->id, (void *)client, 0, NULL);
2051 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2053 /* Send NICK_CHANGE notify to the client's channels */
2054 silc_server_send_notify_on_channels(server, NULL, client,
2055 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2056 oidp->data, oidp->len,
2057 nidp->data, nidp->len,
2059 strlen(client->nickname));
2062 /* Send the new Client ID as reply command back to client */
2063 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2064 SILC_STATUS_OK, ident, 1,
2065 2, nidp->data, nidp->len);
2066 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2067 0, packet->data, packet->len, FALSE);
2069 silc_buffer_free(packet);
2070 silc_buffer_free(nidp);
2072 silc_buffer_free(oidp);
2075 silc_server_command_free(cmd);
2078 /* Sends the LIST command reply */
2081 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2082 SilcChannelEntry *lch,
2083 SilcUInt32 lch_count,
2084 SilcChannelEntry *gch,
2085 SilcUInt32 gch_count)
2088 SilcBuffer packet, idp;
2089 SilcChannelEntry entry;
2090 SilcCommandStatus status;
2091 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2093 unsigned char usercount[4];
2095 int valid_lcount = 0, valid_rcount = 0;
2097 for (i = 0; i < lch_count; i++) {
2098 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2103 for (i = 0; i < gch_count; i++) {
2104 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2110 status = SILC_STATUS_OK;
2111 if ((lch_count + gch_count) > 1)
2112 status = SILC_STATUS_LIST_START;
2115 for (i = 0, k = 0; i < lch_count; i++) {
2121 status = SILC_STATUS_LIST_ITEM;
2122 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2123 status = SILC_STATUS_LIST_END;
2125 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2127 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2128 topic = "*private*";
2129 memset(usercount, 0, sizeof(usercount));
2131 topic = entry->topic;
2132 users = silc_hash_table_count(entry->user_list);
2133 SILC_PUT32_MSB(users, usercount);
2136 /* Send the reply */
2138 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2140 2, idp->data, idp->len,
2141 3, entry->channel_name,
2142 strlen(entry->channel_name),
2143 4, topic, topic ? strlen(topic) : 0,
2145 silc_server_packet_send(cmd->server, cmd->sock,
2146 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2147 packet->len, FALSE);
2148 silc_buffer_free(packet);
2149 silc_buffer_free(idp);
2154 for (i = 0, k = 0; i < gch_count; i++) {
2160 status = SILC_STATUS_LIST_ITEM;
2161 if (valid_rcount > 1 && k == valid_rcount - 1)
2162 status = SILC_STATUS_LIST_END;
2164 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2166 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2167 topic = "*private*";
2168 memset(usercount, 0, sizeof(usercount));
2170 topic = entry->topic;
2171 users = entry->user_count;
2172 SILC_PUT32_MSB(users, usercount);
2175 /* Send the reply */
2177 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2179 2, idp->data, idp->len,
2180 3, entry->channel_name,
2181 strlen(entry->channel_name),
2182 4, topic, topic ? strlen(topic) : 0,
2184 silc_server_packet_send(cmd->server, cmd->sock,
2185 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2186 packet->len, FALSE);
2187 silc_buffer_free(packet);
2188 silc_buffer_free(idp);
2193 /* Server side of LIST command. This lists the channel of the requested
2194 server. Secret channels are not listed. */
2196 SILC_SERVER_CMD_FUNC(list)
2198 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2199 SilcServer server = cmd->server;
2200 SilcChannelID *channel_id = NULL;
2203 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2204 SilcUInt32 lch_count = 0, gch_count = 0;
2206 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2208 /* If we are normal server, send the command to router, since we
2209 want to know all channels in the network. */
2210 if (!cmd->pending && server->server_type == SILC_SERVER &&
2211 !server->standalone) {
2213 SilcUInt16 old_ident;
2215 old_ident = silc_command_get_ident(cmd->payload);
2216 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2217 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2218 silc_server_packet_send(server, server->router->connection,
2219 SILC_PACKET_COMMAND, cmd->packet->flags,
2220 tmpbuf->data, tmpbuf->len, TRUE);
2222 /* Reprocess this packet after received reply from router */
2223 silc_server_command_pending(server, SILC_COMMAND_LIST,
2224 silc_command_get_ident(cmd->payload),
2225 silc_server_command_list,
2226 silc_server_command_dup(cmd));
2227 cmd->pending = TRUE;
2228 silc_command_set_ident(cmd->payload, old_ident);
2229 silc_buffer_free(tmpbuf);
2233 /* Get Channel ID */
2234 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2236 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2239 SILC_STATUS_ERR_NO_CHANNEL_ID);
2244 /* Get the channels from local list */
2245 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2248 /* Get the channels from global list */
2249 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2252 /* Send the reply */
2253 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2254 gchannels, gch_count);
2256 silc_free(lchannels);
2257 silc_free(gchannels);
2260 silc_server_command_free(cmd);
2263 /* Server side of TOPIC command. Sets topic for channel and/or returns
2264 current topic to client. */
2266 SILC_SERVER_CMD_FUNC(topic)
2268 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2269 SilcServer server = cmd->server;
2270 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2271 SilcChannelID *channel_id;
2272 SilcChannelEntry channel;
2273 SilcChannelClientEntry chl;
2274 SilcBuffer packet, idp;
2276 SilcUInt32 argc, tmp_len;
2277 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2279 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2281 argc = silc_argument_get_arg_num(cmd->args);
2283 /* Get Channel ID */
2284 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2287 SILC_STATUS_ERR_NO_CHANNEL_ID);
2290 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2293 SILC_STATUS_ERR_NO_CHANNEL_ID);
2297 /* Check whether the channel exists */
2298 channel = silc_idlist_find_channel_by_id(server->local_list,
2301 channel = silc_idlist_find_channel_by_id(server->global_list,
2304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2305 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2312 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2315 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2319 if (strlen(tmp) > 256) {
2320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2321 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2325 /* See whether the client is on channel and has rights to change topic */
2326 if (!silc_server_client_on_channel(client, channel, &chl)) {
2327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2328 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2332 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2333 channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2335 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2339 /* Set the topic for channel */
2340 silc_free(channel->topic);
2341 channel->topic = strdup(tmp);
2343 /* Send TOPIC_SET notify type to the network */
2344 if (!server->standalone)
2345 silc_server_send_notify_topic_set(server, server->router->connection,
2346 server->server_type == SILC_ROUTER ?
2347 TRUE : FALSE, channel,
2348 client->id, SILC_ID_CLIENT,
2351 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2353 /* Send notify about topic change to all clients on the channel */
2354 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2355 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2356 idp->data, idp->len,
2357 channel->topic, strlen(channel->topic));
2358 silc_buffer_free(idp);
2361 /* Send the topic to client as reply packet */
2362 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2363 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2364 SILC_STATUS_OK, ident, 2,
2365 2, idp->data, idp->len,
2368 strlen(channel->topic) : 0);
2369 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2370 0, packet->data, packet->len, FALSE);
2372 silc_buffer_free(packet);
2373 silc_buffer_free(idp);
2374 silc_free(channel_id);
2377 silc_server_command_free(cmd);
2380 /* Server side of INVITE command. Invites some client to join some channel.
2381 This command is also used to manage the invite list of the channel. */
2383 SILC_SERVER_CMD_FUNC(invite)
2385 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2386 SilcServer server = cmd->server;
2387 SilcSocketConnection sock = cmd->sock, dest_sock;
2388 SilcChannelClientEntry chl;
2389 SilcClientEntry sender, dest;
2390 SilcClientID *dest_id = NULL;
2391 SilcChannelEntry channel;
2392 SilcChannelID *channel_id = NULL;
2393 SilcIDListData idata;
2394 SilcBuffer idp, idp2, packet;
2395 unsigned char *tmp, *add, *del;
2397 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2399 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2401 /* Get Channel ID */
2402 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2405 SILC_STATUS_ERR_NO_CHANNEL_ID);
2408 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2411 SILC_STATUS_ERR_NO_CHANNEL_ID);
2415 /* Get the channel entry */
2416 channel = silc_idlist_find_channel_by_id(server->local_list,
2419 channel = silc_idlist_find_channel_by_id(server->global_list,
2422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2423 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2428 /* Check whether the sender of this command is on the channel. */
2429 sender = (SilcClientEntry)sock->user_data;
2430 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2432 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2436 /* Check whether the channel is invite-only channel. If yes then the
2437 sender of this command must be at least channel operator. */
2438 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2439 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2441 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2445 /* Get destination client ID */
2446 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2451 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2454 SILC_STATUS_ERR_NO_CLIENT_ID);
2458 /* Get the client entry */
2459 dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2461 if (server->server_type != SILC_SERVER || !resolve) {
2462 silc_server_command_send_status_reply(
2463 cmd, SILC_COMMAND_INVITE,
2464 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2468 /* The client info is being resolved. Reprocess this packet after
2469 receiving the reply to the query. */
2470 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2472 silc_server_command_invite,
2473 silc_server_command_dup(cmd));
2474 cmd->pending = TRUE;
2475 silc_free(channel_id);
2480 /* Check whether the requested client is already on the channel. */
2481 if (silc_server_client_on_channel(dest, channel, NULL)) {
2482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2483 SILC_STATUS_ERR_USER_ON_CHANNEL);
2487 /* Get route to the client */
2488 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2491 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2495 memset(invite, 0, sizeof(invite));
2496 strncat(invite, dest->nickname, strlen(dest->nickname));
2497 strncat(invite, "!", 1);
2498 strncat(invite, dest->username, strlen(dest->username));
2499 if (!strchr(dest->username, '@')) {
2500 strncat(invite, "@", 1);
2501 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2504 len = strlen(invite);
2505 if (!channel->invite_list)
2506 channel->invite_list = silc_calloc(len + 2,
2507 sizeof(*channel->invite_list));
2509 channel->invite_list = silc_realloc(channel->invite_list,
2510 sizeof(*channel->invite_list) *
2512 strlen(channel->invite_list) + 2));
2513 strncat(channel->invite_list, invite, len);
2514 strncat(channel->invite_list, ",", 1);
2516 /* Send notify to the client that is invited to the channel */
2517 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2518 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2519 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2521 SILC_NOTIFY_TYPE_INVITE, 3,
2522 idp->data, idp->len,
2523 channel->channel_name,
2524 strlen(channel->channel_name),
2525 idp2->data, idp2->len);
2526 silc_buffer_free(idp);
2527 silc_buffer_free(idp2);
2530 /* Add the client to the invite list of the channel */
2531 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2533 if (!channel->invite_list)
2534 channel->invite_list = silc_calloc(len + 2,
2535 sizeof(*channel->invite_list));
2537 channel->invite_list = silc_realloc(channel->invite_list,
2538 sizeof(*channel->invite_list) *
2540 strlen(channel->invite_list) + 2));
2541 if (add[len - 1] == ',')
2542 add[len - 1] = '\0';
2544 strncat(channel->invite_list, add, len);
2545 strncat(channel->invite_list, ",", 1);
2548 /* Get the invite to be removed and remove it from the list */
2549 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2550 if (del && channel->invite_list) {
2551 char *start, *end, *n;
2553 if (!strncmp(channel->invite_list, del,
2554 strlen(channel->invite_list) - 1)) {
2555 silc_free(channel->invite_list);
2556 channel->invite_list = NULL;
2558 start = strstr(channel->invite_list, del);
2559 if (start && strlen(start) >= len) {
2561 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2562 strncat(n, channel->invite_list, start - channel->invite_list);
2563 strncat(n, end + 1, ((channel->invite_list +
2564 strlen(channel->invite_list)) - end) - 1);
2565 silc_free(channel->invite_list);
2566 channel->invite_list = n;
2571 /* Send notify to the primary router */
2572 if (!server->standalone)
2573 silc_server_send_notify_invite(server, server->router->connection,
2574 server->server_type == SILC_ROUTER ?
2575 TRUE : FALSE, channel,
2576 sender->id, add, del);
2578 /* Send command reply */
2579 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2583 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2584 SILC_STATUS_OK, ident, 2,
2586 3, channel->invite_list,
2587 channel->invite_list ?
2588 strlen(channel->invite_list) : 0);
2591 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2592 SILC_STATUS_OK, ident, 1,
2594 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2595 packet->data, packet->len, FALSE);
2596 silc_buffer_free(packet);
2600 silc_free(channel_id);
2601 silc_server_command_free(cmd);
2606 SilcSocketConnection sock;
2610 /* Quits connection to client. This gets called if client won't
2611 close the connection even when it has issued QUIT command. */
2613 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2615 QuitInternal q = (QuitInternal)context;
2617 /* Free all client specific data, such as client entry and entires
2618 on channels this client may be on. */
2619 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2621 q->sock->user_data = NULL;
2623 /* Close the connection on our side */
2624 silc_server_close_connection(q->server, q->sock);
2626 silc_free(q->signoff);
2630 /* Quits SILC session. This is the normal way to disconnect client. */
2632 SILC_SERVER_CMD_FUNC(quit)
2634 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2635 SilcServer server = cmd->server;
2636 SilcSocketConnection sock = cmd->sock;
2638 unsigned char *tmp = NULL;
2641 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2643 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2646 /* Get destination ID */
2647 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2651 q = silc_calloc(1, sizeof(*q));
2654 q->signoff = tmp ? strdup(tmp) : NULL;
2656 /* We quit the connection with little timeout */
2657 silc_schedule_task_add(server->schedule, sock->sock,
2658 silc_server_command_quit_cb, (void *)q,
2659 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2662 silc_server_command_free(cmd);
2665 /* Server side of command KILL. This command is used by router operator
2666 to remove an client from the SILC Network temporarily. */
2668 SILC_SERVER_CMD_FUNC(kill)
2670 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2671 SilcServer server = cmd->server;
2672 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2673 SilcClientEntry remote_client;
2674 SilcClientID *client_id;
2675 unsigned char *tmp, *comment;
2676 SilcUInt32 tmp_len, tmp_len2;
2680 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2682 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2685 /* KILL command works only on router */
2686 if (server->server_type != SILC_ROUTER) {
2687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2688 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2692 /* Check whether client has the permissions. */
2693 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2695 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2699 /* Get the client ID */
2700 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2703 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2706 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2709 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2713 /* Get the client entry */
2714 remote_client = silc_idlist_find_client_by_id(server->local_list,
2715 client_id, TRUE, NULL);
2717 if (!remote_client) {
2718 remote_client = silc_idlist_find_client_by_id(server->global_list,
2719 client_id, TRUE, NULL);
2721 if (!remote_client) {
2722 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2723 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2729 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2733 /* Send reply to the sender */
2734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2737 /* Send the KILL notify packets. First send it to the channel, then
2738 to our primary router and then directly to the client who is being
2739 killed right now. */
2741 /* Send KILLED notify to the channels. It is not sent to the client
2742 as it will be sent differently destined directly to the client and not
2744 killer = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2745 silc_server_send_notify_on_channels(server, remote_client,
2746 remote_client, SILC_NOTIFY_TYPE_KILLED,
2748 comment, comment ? tmp_len2 : 0,
2749 killer->data, killer->len);
2750 silc_buffer_free(killer);
2752 /* Send KILLED notify to primary route */
2753 if (!server->standalone)
2754 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2755 remote_client->id, comment, client->id);
2757 /* Send KILLED notify to the client directly */
2758 silc_server_send_notify_killed(server, remote_client->connection ?
2759 remote_client->connection :
2760 remote_client->router->connection, FALSE,
2761 remote_client->id, comment, client->id);
2763 /* Remove the client from all channels. This generates new keys to the
2764 channels as well. */
2765 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2768 /* Remove the client entry, If it is locally connected then we will also
2769 disconnect the client here */
2770 if (remote_client->connection) {
2771 /* Remove locally conneted client */
2772 SilcSocketConnection sock = remote_client->connection;
2773 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2774 silc_server_close_connection(server, sock);
2776 /* Update statistics */
2777 if (remote_client->connection)
2778 server->stat.my_clients--;
2779 if (server->server_type == SILC_ROUTER)
2780 server->stat.cell_clients--;
2781 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2782 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2784 /* Remove remote client */
2785 silc_idlist_del_client(local ? server->local_list :
2786 server->global_list, remote_client);
2790 silc_server_command_free(cmd);
2793 /* Server side of command INFO. This sends information about us to
2794 the client. If client requested specific server we will send the
2795 command to that server. */
2797 SILC_SERVER_CMD_FUNC(info)
2799 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2800 SilcServer server = cmd->server;
2801 SilcBuffer packet, idp;
2804 char *dest_server, *server_info = NULL, *server_name;
2805 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2806 SilcServerEntry entry = NULL;
2807 SilcServerID *server_id = NULL;
2809 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2811 /* Get server name */
2812 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2815 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2817 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2820 SILC_STATUS_ERR_NO_SERVER_ID);
2826 /* Check whether we have this server cached */
2827 entry = silc_idlist_find_server_by_id(server->local_list,
2828 server_id, TRUE, NULL);
2830 entry = silc_idlist_find_server_by_id(server->global_list,
2831 server_id, TRUE, NULL);
2832 if (!entry && server->server_type != SILC_SERVER) {
2833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2834 SILC_STATUS_ERR_NO_SUCH_SERVER);
2840 /* Some buggy servers has sent request to router about themselves. */
2841 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2844 if ((!dest_server && !server_id && !entry) || (entry &&
2845 entry == server->id_entry) ||
2846 (dest_server && !cmd->pending &&
2847 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2848 /* Send our reply */
2849 char info_string[256];
2851 memset(info_string, 0, sizeof(info_string));
2852 snprintf(info_string, sizeof(info_string),
2853 "location: %s server: %s admin: %s <%s>",
2854 server->config->server_info->location,
2855 server->config->server_info->server_type,
2856 server->config->server_info->admin,
2857 server->config->server_info->email);
2859 server_info = info_string;
2860 entry = server->id_entry;
2862 /* Check whether we have this server cached */
2863 if (!entry && dest_server) {
2864 entry = silc_idlist_find_server_by_name(server->global_list,
2865 dest_server, TRUE, NULL);
2867 entry = silc_idlist_find_server_by_name(server->local_list,
2868 dest_server, TRUE, NULL);
2872 if (!cmd->pending &&
2873 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2874 /* Send to the server */
2876 SilcUInt16 old_ident;
2878 old_ident = silc_command_get_ident(cmd->payload);
2879 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2880 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2882 silc_server_packet_send(server, entry->connection,
2883 SILC_PACKET_COMMAND, cmd->packet->flags,
2884 tmpbuf->data, tmpbuf->len, TRUE);
2886 /* Reprocess this packet after received reply from router */
2887 silc_server_command_pending(server, SILC_COMMAND_INFO,
2888 silc_command_get_ident(cmd->payload),
2889 silc_server_command_info,
2890 silc_server_command_dup(cmd));
2891 cmd->pending = TRUE;
2892 silc_command_set_ident(cmd->payload, old_ident);
2893 silc_buffer_free(tmpbuf);
2897 if (!entry && !cmd->pending && !server->standalone) {
2898 /* Send to the primary router */
2900 SilcUInt16 old_ident;
2902 old_ident = silc_command_get_ident(cmd->payload);
2903 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2904 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2906 silc_server_packet_send(server, server->router->connection,
2907 SILC_PACKET_COMMAND, cmd->packet->flags,
2908 tmpbuf->data, tmpbuf->len, TRUE);
2910 /* Reprocess this packet after received reply from router */
2911 silc_server_command_pending(server, SILC_COMMAND_INFO,
2912 silc_command_get_ident(cmd->payload),
2913 silc_server_command_info,
2914 silc_server_command_dup(cmd));
2915 cmd->pending = TRUE;
2916 silc_command_set_ident(cmd->payload, old_ident);
2917 silc_buffer_free(tmpbuf);
2922 silc_free(server_id);
2925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2926 SILC_STATUS_ERR_NO_SUCH_SERVER);
2930 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2932 server_info = entry->server_info;
2933 server_name = entry->server_name;
2935 /* Send the reply */
2936 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2937 SILC_STATUS_OK, ident, 3,
2938 2, idp->data, idp->len,
2940 strlen(server_name),
2943 strlen(server_info) : 0);
2944 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2945 packet->data, packet->len, FALSE);
2947 silc_buffer_free(packet);
2948 silc_buffer_free(idp);
2951 silc_server_command_free(cmd);
2954 /* Server side of command PING. This just replies to the ping. */
2956 SILC_SERVER_CMD_FUNC(ping)
2958 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2959 SilcServer server = cmd->server;
2964 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2967 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2970 SILC_STATUS_ERR_NO_SERVER_ID);
2973 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2977 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2978 /* Send our reply */
2979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2983 SILC_STATUS_ERR_NO_SUCH_SERVER);
2990 silc_server_command_free(cmd);
2993 /* Internal routine to join channel. The channel sent to this function
2994 has been either created or resolved from ID lists. This joins the sent
2995 client to the channel. */
2997 static void silc_server_command_join_channel(SilcServer server,
2998 SilcServerCommandContext cmd,
2999 SilcChannelEntry channel,
3000 SilcClientID *client_id,
3004 const unsigned char *auth,
3005 SilcUInt32 auth_len)
3007 SilcSocketConnection sock = cmd->sock;
3009 SilcUInt32 tmp_len, user_count;
3010 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3011 SilcClientEntry client;
3012 SilcChannelClientEntry chl;
3013 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3014 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3015 char check[512], check2[512];
3016 bool founder = FALSE;
3019 SILC_LOG_DEBUG(("Start"));
3024 /* Get the client entry */
3025 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3026 client = (SilcClientEntry)sock->user_data;
3028 client = silc_server_get_client_resolve(server, client_id, &resolve);
3034 silc_server_command_send_status_reply(
3035 cmd, SILC_COMMAND_JOIN,
3036 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3040 /* The client info is being resolved. Reprocess this packet after
3041 receiving the reply to the query. */
3042 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3044 silc_server_command_join,
3045 silc_server_command_dup(cmd));
3046 cmd->pending = TRUE;
3050 cmd->pending = FALSE;
3054 * Check founder auth payload if provided. If client can gain founder
3055 * privileges it can override various conditions on joining the channel,
3056 * and can have directly the founder mode set on the channel.
3058 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3059 SilcIDListData idata = (SilcIDListData)client;
3061 if (channel->founder_key && idata->public_key &&
3062 silc_pkcs_public_key_compare(channel->founder_key,
3063 idata->public_key)) {
3064 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3065 (void *)channel->founder_passwd :
3066 (void *)channel->founder_key);
3067 SilcUInt32 auth_data_len =
3068 (channel->founder_method == SILC_AUTH_PASSWORD ?
3069 channel->founder_passwd_len : 0);
3071 /* Check whether the client is to become founder */
3072 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3073 auth_data, auth_data_len,
3074 idata->hash, client->id, SILC_ID_CLIENT)) {
3075 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3082 * Check channel modes
3086 memset(check, 0, sizeof(check));
3087 memset(check2, 0, sizeof(check2));
3088 strncat(check, client->nickname, strlen(client->nickname));
3089 strncat(check, "!", 1);
3090 strncat(check, client->username, strlen(client->username));
3091 if (!strchr(client->username, '@')) {
3092 strncat(check, "@", 1);
3093 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3096 strncat(check2, client->nickname, strlen(client->nickname));
3097 if (!strchr(client->nickname, '@')) {
3098 strncat(check2, "@", 1);
3099 strncat(check2, server->server_name, strlen(server->server_name));
3101 strncat(check2, "!", 1);
3102 strncat(check2, client->username, strlen(client->username));
3103 if (!strchr(client->username, '@')) {
3104 strncat(check2, "@", 1);
3105 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3108 /* Check invite list if channel is invite-only channel */
3109 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3110 if (!channel->invite_list ||
3111 (!silc_string_match(channel->invite_list, check) &&
3112 !silc_string_match(channel->invite_list, check2))) {
3113 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3114 SILC_STATUS_ERR_NOT_INVITED);
3119 /* Check ban list if it exists. If the client's nickname, server,
3120 username and/or hostname is in the ban list the access to the
3121 channel is denied. */
3122 if (channel->ban_list) {
3123 if (silc_string_match(channel->ban_list, check) ||
3124 silc_string_match(channel->ban_list, check2)) {
3125 silc_server_command_send_status_reply(
3126 cmd, SILC_COMMAND_JOIN,
3127 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3132 /* Check user count limit if set. */
3133 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3134 if (silc_hash_table_count(channel->user_list) + 1 >
3135 channel->user_limit) {
3136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3137 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3143 /* Check the channel passphrase if set. */
3144 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3145 /* Get passphrase */
3146 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3148 passphrase = silc_memdup(tmp, tmp_len);
3150 if (!passphrase || !channel->passphrase ||
3151 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3153 SILC_STATUS_ERR_BAD_PASSWORD);
3159 * Client is allowed to join to the channel. Make it happen.
3162 /* Check whether the client already is on the channel */
3163 if (silc_server_client_on_channel(client, channel, NULL)) {
3164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3165 SILC_STATUS_ERR_USER_ON_CHANNEL);
3169 /* Generate new channel key as protocol dictates */
3171 if (!silc_server_create_channel_key(server, channel, 0))
3174 /* Send the channel key. This is broadcasted to the channel but is not
3175 sent to the client who is joining to the channel. */
3176 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3177 silc_server_send_channel_key(server, NULL, channel,
3178 server->server_type == SILC_ROUTER ?
3179 FALSE : !server->standalone);
3182 /* Join the client to the channel by adding it to channel's user list.
3183 Add also the channel to client entry's channels list for fast cross-
3185 chl = silc_calloc(1, sizeof(*chl));
3187 chl->client = client;
3188 chl->channel = channel;
3189 silc_hash_table_add(channel->user_list, client, chl);
3190 silc_hash_table_add(client->channels, channel, chl);
3191 channel->user_count++;
3193 /* Get users on the channel */
3194 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3197 /* Encode Client ID Payload of the original client who wants to join */
3198 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3200 /* Encode command reply packet */
3201 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3202 SILC_PUT32_MSB(channel->mode, mode);
3203 SILC_PUT32_MSB(created, tmp2);
3204 SILC_PUT32_MSB(user_count, tmp3);
3206 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3207 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3208 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3209 strlen(channel->channel_key->
3211 channel->channel_key->cipher->name,
3212 channel->key_len / 8, channel->key);
3217 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3218 SILC_STATUS_OK, ident, 13,
3219 2, channel->channel_name,
3220 strlen(channel->channel_name),
3221 3, chidp->data, chidp->len,
3222 4, clidp->data, clidp->len,
3225 7, keyp ? keyp->data : NULL,
3226 keyp ? keyp->len : 0,
3227 8, channel->ban_list,
3229 strlen(channel->ban_list) : 0,
3230 9, channel->invite_list,
3231 channel->invite_list ?
3232 strlen(channel->invite_list) : 0,
3235 strlen(channel->topic) : 0,
3236 11, silc_hmac_get_name(channel->hmac),
3237 strlen(silc_hmac_get_name(channel->
3240 13, user_list->data, user_list->len,
3241 14, mode_list->data,
3244 /* Send command reply */
3245 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3246 reply->data, reply->len, FALSE);
3248 /* Send JOIN notify to locally connected clients on the channel. If
3249 we are normal server then router will send or have sent JOIN notify
3250 already. However since we've added the client already to our channel
3251 we'll ignore it (in packet_receive.c) so we must send it here. If
3252 we are router then this will send it to local clients and local
3254 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3255 SILC_NOTIFY_TYPE_JOIN, 2,
3256 clidp->data, clidp->len,
3257 chidp->data, chidp->len);
3259 if (!cmd->pending) {
3260 /* Send JOIN notify packet to our primary router */
3261 if (!server->standalone)
3262 silc_server_send_notify_join(server, server->router->connection,
3263 server->server_type == SILC_ROUTER ?
3264 TRUE : FALSE, channel, client->id);
3267 /* Distribute the channel key to all backup routers. */
3268 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3269 keyp->data, keyp->len, FALSE, TRUE);
3272 /* If client became founder by providing correct founder auth data
3273 notify the mode change to the channel. */
3275 SILC_PUT32_MSB(chl->mode, mode);
3276 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3277 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3278 clidp->data, clidp->len,
3279 mode, 4, clidp->data, clidp->len);
3281 /* Set CUMODE notify type to network */
3282 if (!server->standalone)
3283 silc_server_send_notify_cumode(server, server->router->connection,
3284 server->server_type == SILC_ROUTER ?
3285 TRUE : FALSE, channel,
3286 chl->mode, client->id, SILC_ID_CLIENT,
3290 silc_buffer_free(reply);
3291 silc_buffer_free(clidp);
3292 silc_buffer_free(chidp);
3293 silc_buffer_free(keyp);
3294 silc_buffer_free(user_list);
3295 silc_buffer_free(mode_list);
3298 silc_free(passphrase);
3301 /* Server side of command JOIN. Joins client into requested channel. If
3302 the channel does not exist it will be created. */
3304 SILC_SERVER_CMD_FUNC(join)
3306 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3307 SilcServer server = cmd->server;
3308 unsigned char *auth;
3309 SilcUInt32 tmp_len, auth_len;
3310 char *tmp, *channel_name = NULL, *cipher, *hmac;
3311 SilcChannelEntry channel;
3312 SilcUInt32 umode = 0;
3313 bool created = FALSE, create_key = TRUE;
3314 SilcClientID *client_id;
3316 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3318 /* Get channel name */
3319 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3322 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3328 channel_name[255] = '\0';
3330 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3332 SILC_STATUS_ERR_BAD_CHANNEL);
3336 /* Get Client ID of the client who is joining to the channel */
3337 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3340 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3343 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3346 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3350 /* Get cipher, hmac name and auth payload */
3351 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3352 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3353 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3355 /* See if the channel exists */
3356 channel = silc_idlist_find_channel_by_name(server->local_list,
3357 channel_name, NULL);
3359 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3360 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3361 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3363 if (!channel || channel->disabled) {
3364 /* Channel not found */
3366 /* If we are standalone server we don't have a router, we just create
3367 the channel by ourselves. */
3368 if (server->standalone) {
3369 channel = silc_server_create_new_channel(server, server->id, cipher,
3370 hmac, channel_name, TRUE);
3372 silc_server_command_send_status_reply(
3373 cmd, SILC_COMMAND_JOIN,
3374 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3378 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3384 /* The channel does not exist on our server. If we are normal server
3385 we will send JOIN command to our router which will handle the
3386 joining procedure (either creates the channel if it doesn't exist
3387 or joins the client to it). */
3388 if (server->server_type != SILC_ROUTER) {
3390 SilcUInt16 old_ident;
3392 /* If this is pending command callback then we've resolved
3393 it and it didn't work, return since we've notified the
3394 client already in the command reply callback. */
3398 old_ident = silc_command_get_ident(cmd->payload);
3399 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3400 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3402 /* Send JOIN command to our router */
3403 silc_server_packet_send(server, (SilcSocketConnection)
3404 server->router->connection,
3405 SILC_PACKET_COMMAND, cmd->packet->flags,
3406 tmpbuf->data, tmpbuf->len, TRUE);
3408 /* Reprocess this packet after received reply from router */
3409 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3410 silc_command_get_ident(cmd->payload),
3411 silc_server_command_join,
3412 silc_server_command_dup(cmd));
3413 cmd->pending = TRUE;
3414 silc_command_set_ident(cmd->payload, old_ident);
3415 silc_buffer_free(tmpbuf);
3419 /* We are router and the channel does not seem exist so we will check
3420 our global list as well for the channel. */
3421 channel = silc_idlist_find_channel_by_name(server->global_list,
3422 channel_name, NULL);
3424 /* Channel really does not exist, create it */
3425 channel = silc_server_create_new_channel(server, server->id, cipher,
3426 hmac, channel_name, TRUE);
3428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3429 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3433 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3441 /* Channel not found */
3443 /* If the command came from router and we are normal server then
3444 something went wrong with the joining as the channel was not found.
3445 We can't do anything else but ignore this. */
3446 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3447 server->server_type != SILC_ROUTER)
3450 /* We are router and the channel does not seem exist so we will check
3451 our global list as well for the channel. */
3452 channel = silc_idlist_find_channel_by_name(server->global_list,
3453 channel_name, NULL);
3455 /* Channel really does not exist, create it */
3456 channel = silc_server_create_new_channel(server, server->id, cipher,
3457 hmac, channel_name, TRUE);
3459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3460 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3464 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3471 /* Check whether the channel was created by our router */
3472 if (cmd->pending && context2) {
3473 SilcServerCommandReplyContext reply =
3474 (SilcServerCommandReplyContext)context2;
3476 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3477 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3478 SILC_GET32_MSB(created, tmp);
3479 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3480 create_key = FALSE; /* Router returned the key already */
3483 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3484 !silc_hash_table_count(channel->user_list))
3488 /* If the channel does not have global users and is also empty the client
3489 will be the channel founder and operator. */
3490 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3491 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3493 /* Join to the channel */
3494 silc_server_command_join_channel(server, cmd, channel, client_id,
3495 created, create_key, umode,
3498 silc_free(client_id);
3501 silc_server_command_free(cmd);
3504 /* Server side of command MOTD. Sends server's current "message of the
3505 day" to the client. */
3507 SILC_SERVER_CMD_FUNC(motd)
3509 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3510 SilcServer server = cmd->server;
3511 SilcBuffer packet, idp;
3512 char *motd, *dest_server;
3513 SilcUInt32 motd_len;
3514 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3516 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3518 /* Get server name */
3519 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3521 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3522 SILC_STATUS_ERR_NO_SUCH_SERVER);
3526 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3529 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3531 if (server->config && server->config->server_info &&
3532 server->config->server_info->motd_file) {
3534 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3539 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3540 SILC_STATUS_OK, ident, 2,
3545 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3546 SILC_STATUS_OK, ident, 1,
3550 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3551 packet->data, packet->len, FALSE);
3552 silc_buffer_free(packet);
3553 silc_buffer_free(idp);
3555 SilcServerEntry entry;
3557 /* Check whether we have this server cached */
3558 entry = silc_idlist_find_server_by_name(server->global_list,
3559 dest_server, TRUE, NULL);
3561 entry = silc_idlist_find_server_by_name(server->local_list,
3562 dest_server, TRUE, NULL);
3565 if (server->server_type != SILC_SERVER && !cmd->pending &&
3566 entry && !entry->motd) {
3567 /* Send to the server */
3569 SilcUInt16 old_ident;
3571 old_ident = silc_command_get_ident(cmd->payload);
3572 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3573 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3575 silc_server_packet_send(server, entry->connection,
3576 SILC_PACKET_COMMAND, cmd->packet->flags,
3577 tmpbuf->data, tmpbuf->len, TRUE);
3579 /* Reprocess this packet after received reply from router */
3580 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3581 silc_command_get_ident(cmd->payload),
3582 silc_server_command_motd,
3583 silc_server_command_dup(cmd));
3584 cmd->pending = TRUE;
3585 silc_command_set_ident(cmd->payload, old_ident);
3586 silc_buffer_free(tmpbuf);
3590 if (!entry && !cmd->pending && !server->standalone) {
3591 /* Send to the primary router */
3593 SilcUInt16 old_ident;
3595 old_ident = silc_command_get_ident(cmd->payload);
3596 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3597 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3599 silc_server_packet_send(server, server->router->connection,
3600 SILC_PACKET_COMMAND, cmd->packet->flags,
3601 tmpbuf->data, tmpbuf->len, TRUE);
3603 /* Reprocess this packet after received reply from router */
3604 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3605 silc_command_get_ident(cmd->payload),
3606 silc_server_command_motd,
3607 silc_server_command_dup(cmd));
3608 cmd->pending = TRUE;
3609 silc_command_set_ident(cmd->payload, old_ident);
3610 silc_buffer_free(tmpbuf);
3615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3616 SILC_STATUS_ERR_NO_SUCH_SERVER);
3620 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3621 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3622 SILC_STATUS_OK, ident, 2,
3626 strlen(entry->motd) : 0);
3627 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3628 packet->data, packet->len, FALSE);
3629 silc_buffer_free(packet);
3630 silc_buffer_free(idp);
3634 silc_server_command_free(cmd);
3637 /* Server side of command UMODE. Client can use this command to set/unset
3638 user mode. Client actually cannot set itself to be as server/router
3639 operator so this can be used only to unset the modes. */
3641 SILC_SERVER_CMD_FUNC(umode)
3643 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3644 SilcServer server = cmd->server;
3645 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3647 unsigned char *tmp_mask;
3649 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3651 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3654 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3656 /* Get the client's mode mask */
3657 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3660 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3663 SILC_GET32_MSB(mask, tmp_mask);
3665 /* Check that mode changing is allowed. */
3666 if (!silc_server_check_umode_rights(server, client, mask)) {
3667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3668 SILC_STATUS_ERR_PERM_DENIED);
3672 /* Change the mode */
3673 client->mode = mask;
3675 /* Send UMODE change to primary router */
3676 if (!server->standalone)
3677 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3678 client->id, client->mode);
3680 /* Send command reply to sender */
3681 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3682 SILC_STATUS_OK, ident, 1,
3684 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3685 packet->data, packet->len, FALSE);
3686 silc_buffer_free(packet);
3689 silc_server_command_free(cmd);
3692 /* Server side command of CMODE. Changes channel mode */
3694 SILC_SERVER_CMD_FUNC(cmode)
3696 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3697 SilcServer server = cmd->server;
3698 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3699 SilcIDListData idata = (SilcIDListData)client;
3700 SilcChannelID *channel_id;
3701 SilcChannelEntry channel;
3702 SilcChannelClientEntry chl;
3703 SilcBuffer packet, cidp;
3704 unsigned char *tmp, *tmp_id, *tmp_mask;
3705 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3706 SilcUInt32 mode_mask, tmp_len, tmp_len2;
3707 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3709 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3711 /* Get Channel ID */
3712 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3714 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3715 SILC_STATUS_ERR_NO_CHANNEL_ID);
3718 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3721 SILC_STATUS_ERR_NO_CHANNEL_ID);
3725 /* Get the channel mode mask */
3726 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3729 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3732 SILC_GET32_MSB(mode_mask, tmp_mask);
3734 /* Get channel entry */
3735 channel = silc_idlist_find_channel_by_id(server->local_list,
3738 channel = silc_idlist_find_channel_by_id(server->global_list,
3741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3742 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3747 /* Check whether this client is on the channel */
3748 if (!silc_server_client_on_channel(client, channel, &chl)) {
3749 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3750 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3754 /* Check that client has rights to change any requested channel modes */
3755 if (!silc_server_check_cmode_rights(server, channel, chl, mode_mask)) {
3756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3758 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3759 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3764 * Check the modes. Modes that requires nothing special operation are
3768 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3769 /* Channel uses private keys to protect traffic. Client(s) has set the
3770 key locally they want to use, server does not know that key. */
3771 /* Nothing interesting to do here */
3773 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3774 /* The mode is removed and we need to generate and distribute
3775 new channel key. Clients are not using private channel keys
3776 anymore after this. */
3778 /* Re-generate channel key */
3779 if (!silc_server_create_channel_key(server, channel, 0))
3782 /* Send the channel key. This sends it to our local clients and if
3783 we are normal server to our router as well. */
3784 silc_server_send_channel_key(server, NULL, channel,
3785 server->server_type == SILC_ROUTER ?
3786 FALSE : !server->standalone);
3788 cipher = channel->channel_key->cipher->name;
3789 hmac = (char *)silc_hmac_get_name(channel->hmac);
3793 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3794 /* User limit is set on channel */
3795 SilcUInt32 user_limit;
3797 /* Get user limit */
3798 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3800 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3802 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3806 SILC_GET32_MSB(user_limit, tmp);
3807 channel->user_limit = user_limit;
3810 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3811 /* User limit mode is unset. Remove user limit */
3812 channel->user_limit = 0;
3815 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3816 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3817 /* Passphrase has been set to channel */
3819 /* Get the passphrase */
3820 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3823 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3827 /* Save the passphrase */
3828 passphrase = channel->passphrase = strdup(tmp);
3831 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3832 /* Passphrase mode is unset. remove the passphrase */
3833 if (channel->passphrase) {
3834 silc_free(channel->passphrase);
3835 channel->passphrase = NULL;
3840 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3841 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3842 /* Cipher to use protect the traffic */
3843 SilcCipher newkey, oldkey;
3846 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3849 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3853 /* Delete old cipher and allocate the new one */
3854 if (!silc_cipher_alloc(cipher, &newkey)) {
3855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3856 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3860 oldkey = channel->channel_key;
3861 channel->channel_key = newkey;
3863 /* Re-generate channel key */
3864 if (!silc_server_create_channel_key(server, channel, 0)) {
3865 /* We don't have new key, revert to old one */
3866 channel->channel_key = oldkey;
3870 /* Remove old channel key for good */
3871 silc_cipher_free(oldkey);
3873 /* Send the channel key. This sends it to our local clients and if
3874 we are normal server to our router as well. */
3875 silc_server_send_channel_key(server, NULL, channel,
3876 server->server_type == SILC_ROUTER ?
3877 FALSE : !server->standalone);
3880 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3881 /* Cipher mode is unset. Remove the cipher and revert back to
3883 SilcCipher newkey, oldkey;
3884 cipher = channel->cipher;
3886 /* Delete old cipher and allocate default one */
3887 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3888 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3889 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3893 oldkey = channel->channel_key;
3894 channel->channel_key = newkey;
3896 /* Re-generate channel key */
3897 if (!silc_server_create_channel_key(server, channel, 0)) {
3898 /* We don't have new key, revert to old one */
3899 channel->channel_key = oldkey;
3903 /* Remove old channel key for good */
3904 silc_cipher_free(oldkey);
3906 /* Send the channel key. This sends it to our local clients and if
3907 we are normal server to our router as well. */
3908 silc_server_send_channel_key(server, NULL, channel,
3909 server->server_type == SILC_ROUTER ?
3910 FALSE : !server->standalone);
3914 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3915 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3916 /* HMAC to use protect the traffic */
3917 unsigned char hash[32];
3921 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3924 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3928 /* Delete old hmac and allocate the new one */
3929 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3931 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3935 silc_hmac_free(channel->hmac);
3936 channel->hmac = newhmac;
3938 /* Set the HMAC key out of current channel key. The client must do
3940 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3941 channel->key_len / 8, hash);
3942 silc_hmac_set_key(channel->hmac, hash,
3943 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3944 memset(hash, 0, sizeof(hash));
3947 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3948 /* Hmac mode is unset. Remove the hmac and revert back to
3951 unsigned char hash[32];
3952 hmac = channel->hmac_name;
3954 /* Delete old hmac and allocate default one */
3955 silc_hmac_free(channel->hmac);
3956 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3957 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3958 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3962 silc_hmac_free(channel->hmac);
3963 channel->hmac = newhmac;
3965 /* Set the HMAC key out of current channel key. The client must do
3967 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3968 channel->key_len / 8,
3970 silc_hmac_set_key(channel->hmac, hash,
3971 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3972 memset(hash, 0, sizeof(hash));
3976 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3977 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3978 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3979 /* Set the founder authentication */
3980 SilcAuthPayload auth;
3982 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3985 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3989 auth = silc_auth_payload_parse(tmp, tmp_len);
3991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3992 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3996 /* Save the public key */
3997 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3998 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4001 channel->founder_method = silc_auth_get_method(auth);
4003 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4004 tmp = silc_auth_get_data(auth, &tmp_len);
4005 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4006 channel->founder_passwd_len = tmp_len;
4008 /* Verify the payload before setting the mode */
4009 if (!silc_auth_verify(auth, channel->founder_method,
4010 channel->founder_key, 0, idata->hash,
4011 client->id, SILC_ID_CLIENT)) {
4012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4013 SILC_STATUS_ERR_AUTH_FAILED);
4018 silc_auth_payload_free(auth);
4022 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4023 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4024 if (channel->founder_key)
4025 silc_pkcs_public_key_free(channel->founder_key);
4026 if (channel->founder_passwd) {
4027 silc_free(channel->founder_passwd);
4028 channel->founder_passwd = NULL;
4034 /* Finally, set the mode */
4035 channel->mode = mode_mask;
4037 /* Send CMODE_CHANGE notify. */
4038 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4039 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4040 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4041 cidp->data, cidp->len,
4043 cipher, cipher ? strlen(cipher) : 0,
4044 hmac, hmac ? strlen(hmac) : 0,
4045 passphrase, passphrase ?
4046 strlen(passphrase) : 0);
4048 /* Set CMODE notify type to network */
4049 if (!server->standalone)
4050 silc_server_send_notify_cmode(server, server->router->connection,
4051 server->server_type == SILC_ROUTER ?
4052 TRUE : FALSE, channel,
4053 mode_mask, client->id, SILC_ID_CLIENT,
4054 cipher, hmac, passphrase);
4056 /* Send command reply to sender */
4057 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4058 SILC_STATUS_OK, ident, 2,
4059 2, tmp_id, tmp_len2,
4061 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4062 packet->data, packet->len, FALSE);
4064 silc_buffer_free(packet);
4065 silc_free(channel_id);
4066 silc_buffer_free(cidp);
4069 silc_server_command_free(cmd);
4072 /* Server side of CUMODE command. Changes client's mode on a channel. */
4074 SILC_SERVER_CMD_FUNC(cumode)
4076 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4077 SilcServer server = cmd->server;
4078 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4079 SilcIDListData idata = (SilcIDListData)client;
4080 SilcChannelID *channel_id;
4081 SilcClientID *client_id;
4082 SilcChannelEntry channel;
4083 SilcClientEntry target_client;
4084 SilcChannelClientEntry chl;
4085 SilcBuffer packet, idp;
4086 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4087 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4089 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4091 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4093 /* Get Channel ID */
4094 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4097 SILC_STATUS_ERR_NO_CHANNEL_ID);
4100 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4103 SILC_STATUS_ERR_NO_CHANNEL_ID);
4107 /* Get channel entry */
4108 channel = silc_idlist_find_channel_by_id(server->local_list,
4111 channel = silc_idlist_find_channel_by_id(server->global_list,
4114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4115 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4120 /* Check whether sender is on the channel */
4121 if (!silc_server_client_on_channel(client, channel, &chl)) {
4122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4123 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4126 sender_mask = chl->mode;
4128 /* Get the target client's channel mode mask */
4129 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4132 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4135 SILC_GET32_MSB(target_mask, tmp_mask);
4137 /* Get target Client ID */
4138 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4140 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4141 SILC_STATUS_ERR_NO_CLIENT_ID);
4144 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4146 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4147 SILC_STATUS_ERR_NO_CLIENT_ID);
4151 /* Get target client's entry */
4152 target_client = silc_idlist_find_client_by_id(server->local_list,
4153 client_id, TRUE, NULL);
4154 if (!target_client) {
4155 target_client = silc_idlist_find_client_by_id(server->global_list,
4156 client_id, TRUE, NULL);
4159 if (target_client != client &&
4160 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4161 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4163 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4167 /* Check whether target client is on the channel */
4168 if (target_client != client) {
4169 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4170 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4171 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4180 /* If the target client is founder, no one else can change their mode
4182 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4184 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4188 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4189 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4190 /* The client tries to claim the founder rights. */
4191 unsigned char *tmp_auth;
4192 SilcUInt32 tmp_auth_len, auth_len;
4195 if (target_client != client) {
4196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4197 SILC_STATUS_ERR_NOT_YOU);
4201 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4202 !channel->founder_key || !idata->public_key ||
4203 !silc_pkcs_public_key_compare(channel->founder_key,
4204 idata->public_key)) {
4205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4206 SILC_STATUS_ERR_NOT_YOU);
4210 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4213 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4217 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4218 (void *)channel->founder_passwd : (void *)channel->founder_key);
4219 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4220 channel->founder_passwd_len : 0);
4222 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4223 channel->founder_method, auth, auth_len,
4224 idata->hash, client->id, SILC_ID_CLIENT)) {
4225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4226 SILC_STATUS_ERR_AUTH_FAILED);
4230 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4234 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4235 if (target_client == client) {
4236 /* Remove channel founder rights from itself */
4237 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4241 SILC_STATUS_ERR_NOT_YOU);
4247 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4248 /* Promote to operator */
4249 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4250 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4251 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4257 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4261 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4262 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4263 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4265 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4269 /* Demote to normal user */
4270 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4275 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4276 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4278 /* Send notify to channel, notify only if mode was actually changed. */
4280 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4281 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4282 idp->data, idp->len,
4286 /* Set CUMODE notify type to network */
4287 if (!server->standalone)
4288 silc_server_send_notify_cumode(server, server->router->connection,
4289 server->server_type == SILC_ROUTER ?
4290 TRUE : FALSE, channel,
4291 target_mask, client->id,
4296 /* Send command reply to sender */
4297 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4298 SILC_STATUS_OK, ident, 3,
4300 3, tmp_ch_id, tmp_ch_len,
4301 4, tmp_id, tmp_len);
4302 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4303 packet->data, packet->len, FALSE);
4305 silc_buffer_free(packet);
4306 silc_free(channel_id);
4307 silc_free(client_id);
4308 silc_buffer_free(idp);
4311 silc_server_command_free(cmd);
4314 /* Server side of KICK command. Kicks client out of channel. */
4316 SILC_SERVER_CMD_FUNC(kick)
4318 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4319 SilcServer server = cmd->server;
4320 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4321 SilcClientEntry target_client;
4322 SilcChannelID *channel_id;
4323 SilcClientID *client_id;
4324 SilcChannelEntry channel;
4325 SilcChannelClientEntry chl;
4327 SilcUInt32 tmp_len, target_idp_len;
4328 unsigned char *tmp, *comment, *target_idp;
4330 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4332 /* Get Channel ID */
4333 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4336 SILC_STATUS_ERR_NO_CHANNEL_ID);
4339 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4342 SILC_STATUS_ERR_NO_CHANNEL_ID);
4346 /* Get channel entry */
4347 channel = silc_idlist_find_channel_by_id(server->local_list,
4350 channel = silc_idlist_find_channel_by_id(server->local_list,
4353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4354 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4359 /* Check whether sender is on the channel */
4360 if (!silc_server_client_on_channel(client, channel, &chl)) {
4361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4362 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4366 /* Check that the kicker is channel operator or channel founder */
4367 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4369 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4373 /* Get target Client ID */
4374 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4377 SILC_STATUS_ERR_NO_CLIENT_ID);
4380 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4383 SILC_STATUS_ERR_NO_CLIENT_ID);
4387 /* Get target client's entry */
4388 target_client = silc_idlist_find_client_by_id(server->local_list,
4389 client_id, TRUE, NULL);
4390 if (!target_client) {
4391 target_client = silc_idlist_find_client_by_id(server->global_list,
4392 client_id, TRUE, NULL);
4395 /* Check whether target client is on the channel */
4396 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4398 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4402 /* Check that the target client is not channel founder. Channel founder
4403 cannot be kicked from the channel. */
4404 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4406 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4412 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4416 /* Send command reply to sender */
4417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4420 /* Send KICKED notify to local clients on the channel */
4421 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4422 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4423 SILC_NOTIFY_TYPE_KICKED, 3,
4424 target_idp, target_idp_len,
4425 comment, comment ? strlen(comment) : 0,
4426 idp->data, idp->len);
4427 silc_buffer_free(idp);
4429 /* Remove the client from the channel. If the channel does not exist
4430 after removing the client then the client kicked itself off the channel
4431 and we don't have to send anything after that. */
4432 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4433 target_client, FALSE))
4436 /* Send KICKED notify to primary route */
4437 if (!server->standalone)
4438 silc_server_send_notify_kicked(server, server->router->connection,
4439 server->server_type == SILC_ROUTER ?
4440 TRUE : FALSE, channel,
4441 target_client->id, client->id, comment);
4443 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4444 /* Re-generate channel key */
4445 if (!silc_server_create_channel_key(server, channel, 0))
4448 /* Send the channel key to the channel. The key of course is not sent
4449 to the client who was kicked off the channel. */
4450 silc_server_send_channel_key(server, target_client->connection, channel,
4451 server->server_type == SILC_ROUTER ?
4452 FALSE : !server->standalone);
4456 silc_server_command_free(cmd);
4459 /* Server side of OPER command. Client uses this comand to obtain server
4460 operator privileges to this server/router. */
4462 SILC_SERVER_CMD_FUNC(oper)
4464 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4465 SilcServer server = cmd->server;
4466 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4467 unsigned char *username, *auth;
4469 SilcServerConfigAdmin *admin;
4470 SilcIDListData idata = (SilcIDListData)client;
4471 bool result = FALSE;
4472 SilcPublicKey cached_key;
4474 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4476 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4479 /* Get the username */
4480 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4483 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4487 /* Get the admin configuration */
4488 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4489 username, client->nickname);
4491 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4492 username, client->nickname);
4494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4495 SILC_STATUS_ERR_AUTH_FAILED);
4500 /* Get the authentication payload */
4501 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4504 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4508 /* Verify the authentication data. If both passphrase and public key
4509 is set then try both of them. */
4510 if (admin->passphrase)
4511 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4512 admin->passphrase, admin->passphrase_len,
4513 idata->hash, client->id, SILC_ID_CLIENT);
4514 if (!result && admin->publickeys) {
4515 cached_key = silc_server_get_public_key(server, admin->publickeys);
4518 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4519 cached_key, 0, idata->hash,
4520 client->id, SILC_ID_CLIENT);
4523 /* Authentication failed */
4524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4525 SILC_STATUS_ERR_AUTH_FAILED);
4529 /* Client is now server operator */
4530 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4532 /* Update statistics */
4533 if (client->connection)
4534 server->stat.my_server_ops++;
4535 if (server->server_type == SILC_ROUTER)
4536 server->stat.server_ops++;
4538 /* Send UMODE change to primary router */
4539 if (!server->standalone)
4540 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4541 client->id, client->mode);
4543 /* Send reply to the sender */
4544 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4548 silc_server_command_free(cmd);
4551 /* Server side of SILCOPER command. Client uses this comand to obtain router
4552 operator privileges to this router. */
4554 SILC_SERVER_CMD_FUNC(silcoper)
4556 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4557 SilcServer server = cmd->server;
4558 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4559 unsigned char *username, *auth;
4561 SilcServerConfigAdmin *admin;
4562 SilcIDListData idata = (SilcIDListData)client;
4563 bool result = FALSE;
4564 SilcPublicKey cached_key;
4566 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4568 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4571 if (server->server_type != SILC_ROUTER) {
4572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4573 SILC_STATUS_ERR_AUTH_FAILED);
4577 /* Get the username */
4578 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4580 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4581 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4585 /* Get the admin configuration */
4586 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4587 username, client->nickname);
4589 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4590 username, client->nickname);
4592 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4593 SILC_STATUS_ERR_AUTH_FAILED);
4598 /* Get the authentication payload */
4599 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4602 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4606 /* Verify the authentication data. If both passphrase and public key
4607 is set then try both of them. */
4608 if (admin->passphrase)
4609 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4610 admin->passphrase, admin->passphrase_len,
4611 idata->hash, client->id, SILC_ID_CLIENT);
4612 if (!result && admin->publickeys) {
4613 cached_key = silc_server_get_public_key(server, admin->publickeys);
4616 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4617 cached_key, 0, idata->hash,
4618 client->id, SILC_ID_CLIENT);
4621 /* Authentication failed */
4622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4623 SILC_STATUS_ERR_AUTH_FAILED);
4627 /* Client is now router operator */
4628 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4630 /* Update statistics */
4631 if (client->connection)
4632 server->stat.my_router_ops++;
4633 if (server->server_type == SILC_ROUTER)
4634 server->stat.router_ops++;
4636 /* Send UMODE change to primary router */
4637 if (!server->standalone)
4638 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4639 client->id, client->mode);
4641 /* Send reply to the sender */
4642 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4646 silc_server_command_free(cmd);
4649 /* Server side of command BAN. This is used to manage the ban list of the
4650 channel. To add clients and remove clients from the ban list. */
4652 SILC_SERVER_CMD_FUNC(ban)
4654 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4655 SilcServer server = cmd->server;
4656 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4658 SilcChannelEntry channel;
4659 SilcChannelClientEntry chl;
4660 SilcChannelID *channel_id = NULL;
4661 unsigned char *id, *add, *del;
4662 SilcUInt32 id_len, tmp_len;
4663 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4665 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4668 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4670 /* Get Channel ID */
4671 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4673 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4675 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4676 SILC_STATUS_ERR_NO_CHANNEL_ID);
4681 /* Get channel entry. The server must know about the channel since the
4682 client is expected to be on the channel. */
4683 channel = silc_idlist_find_channel_by_id(server->local_list,
4686 channel = silc_idlist_find_channel_by_id(server->global_list,
4689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4690 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4695 /* Check whether this client is on the channel */
4696 if (!silc_server_client_on_channel(client, channel, &chl)) {
4697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4698 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4702 /* The client must be at least channel operator. */
4703 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4704 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4705 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4709 /* Get the new ban and add it to the ban list */
4710 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4712 if (!channel->ban_list)
4713 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4715 channel->ban_list = silc_realloc(channel->ban_list,
4716 sizeof(*channel->ban_list) *
4718 strlen(channel->ban_list) + 2));
4719 if (add[tmp_len - 1] == ',')
4720 add[tmp_len - 1] = '\0';
4722 strncat(channel->ban_list, add, tmp_len);
4723 strncat(channel->ban_list, ",", 1);
4726 /* Get the ban to be removed and remove it from the list */
4727 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4728 if (del && channel->ban_list) {
4729 char *start, *end, *n;
4731 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4732 silc_free(channel->ban_list);
4733 channel->ban_list = NULL;
4735 start = strstr(channel->ban_list, del);
4736 if (start && strlen(start) >= tmp_len) {
4737 end = start + tmp_len;
4738 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4739 strncat(n, channel->ban_list, start - channel->ban_list);
4740 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4742 silc_free(channel->ban_list);
4743 channel->ban_list = n;
4748 /* Send the BAN notify type to our primary router. */
4749 if (!server->standalone && (add || del))
4750 silc_server_send_notify_ban(server, server->router->connection,
4751 server->server_type == SILC_ROUTER ?
4752 TRUE : FALSE, channel, add, del);
4754 /* Send the reply back to the client */
4756 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4757 SILC_STATUS_OK, ident, 2,
4759 3, channel->ban_list,
4761 strlen(channel->ban_list) -1 : 0);
4762 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4763 packet->data, packet->len, FALSE);
4765 silc_buffer_free(packet);
4768 silc_free(channel_id);
4769 silc_server_command_free(cmd);
4772 /* Server side command of LEAVE. Removes client from a channel. */
4774 SILC_SERVER_CMD_FUNC(leave)
4776 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4777 SilcServer server = cmd->server;
4778 SilcSocketConnection sock = cmd->sock;
4779 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4780 SilcChannelID *id = NULL;
4781 SilcChannelEntry channel;
4785 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4787 /* Get Channel ID */
4788 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4791 SILC_STATUS_ERR_NO_CHANNEL_ID);
4794 id = silc_id_payload_parse_id(tmp, len, NULL);
4796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4797 SILC_STATUS_ERR_NO_CHANNEL_ID);
4801 /* Get channel entry */
4802 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4804 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4807 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4812 /* Check whether this client is on the channel */
4813 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4815 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4819 /* Notify routers that they should remove this client from their list
4820 of clients on the channel. Send LEAVE notify type. */
4821 if (!server->standalone)
4822 silc_server_send_notify_leave(server, server->router->connection,
4823 server->server_type == SILC_ROUTER ?
4824 TRUE : FALSE, channel, id_entry->id);
4826 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4827 SILC_STATUS_OK, 2, tmp, len);
4829 /* Remove client from channel */
4830 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4832 /* If the channel does not exist anymore we won't send anything */
4835 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4836 /* Re-generate channel key */
4837 if (!silc_server_create_channel_key(server, channel, 0))
4840 /* Send the channel key */
4841 silc_server_send_channel_key(server, NULL, channel,
4842 server->server_type == SILC_ROUTER ?
4843 FALSE : !server->standalone);
4848 silc_server_command_free(cmd);
4851 /* Server side of command USERS. Resolves clients and their USERS currently
4852 joined on the requested channel. The list of Client ID's and their modes
4853 on the channel is sent back. */
4855 SILC_SERVER_CMD_FUNC(users)
4857 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4858 SilcServer server = cmd->server;
4859 SilcChannelEntry channel;
4860 SilcChannelID *id = NULL;
4861 SilcBuffer packet, idp;
4862 unsigned char *channel_id;
4863 SilcUInt32 channel_id_len;
4864 SilcBuffer client_id_list;
4865 SilcBuffer client_mode_list;
4866 unsigned char lc[4];
4867 SilcUInt32 list_count = 0;
4868 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4871 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4873 /* Get Channel ID */
4874 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4876 /* Get channel name */
4877 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4879 if (!channel_id && !channel_name) {
4880 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4881 SILC_STATUS_ERR_NO_CHANNEL_ID);
4886 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4888 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4889 SILC_STATUS_ERR_NO_CHANNEL_ID);
4894 /* If we are server and we don't know about this channel we will send
4895 the command to our router. If we know about the channel then we also
4896 have the list of users already. */
4898 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4900 channel = silc_idlist_find_channel_by_name(server->local_list,
4901 channel_name, NULL);
4903 if (!channel || channel->disabled) {
4904 if (server->server_type != SILC_ROUTER && !server->standalone &&
4908 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4909 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4911 /* Send USERS command */
4912 silc_server_packet_send(server, server->router->connection,
4913 SILC_PACKET_COMMAND, cmd->packet->flags,
4914 tmpbuf->data, tmpbuf->len, TRUE);
4916 /* Reprocess this packet after received reply */
4917 silc_server_command_pending(server, SILC_COMMAND_USERS,
4918 silc_command_get_ident(cmd->payload),
4919 silc_server_command_users,
4920 silc_server_command_dup(cmd));
4921 cmd->pending = TRUE;
4922 silc_command_set_ident(cmd->payload, ident);
4923 silc_buffer_free(tmpbuf);
4928 /* Check the global list as well. */
4930 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4932 channel = silc_idlist_find_channel_by_name(server->global_list,
4933 channel_name, NULL);
4935 /* Channel really does not exist */
4936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4937 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4942 /* If the channel is private or secret do not send anything, unless the
4943 user requesting this command is on the channel. */
4944 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4945 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4946 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4949 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4954 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
4955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4956 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4961 /* Get the users list */
4962 silc_server_get_users_on_channel(server, channel, &client_id_list,
4963 &client_mode_list, &list_count);
4966 SILC_PUT32_MSB(list_count, lc);
4969 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4970 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4971 SILC_STATUS_OK, ident, 4,
4972 2, idp->data, idp->len,
4974 4, client_id_list->data,
4975 client_id_list->len,
4976 5, client_mode_list->data,
4977 client_mode_list->len);
4978 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4979 packet->data, packet->len, FALSE);
4981 silc_buffer_free(idp);
4982 silc_buffer_free(packet);
4983 silc_buffer_free(client_id_list);
4984 silc_buffer_free(client_mode_list);
4988 silc_server_command_free(cmd);
4991 /* Server side of command GETKEY. This fetches the client's public key
4992 from the server where to the client is connected. */
4994 SILC_SERVER_CMD_FUNC(getkey)
4996 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4997 SilcServer server = cmd->server;
4999 SilcClientEntry client;
5000 SilcServerEntry server_entry;
5001 SilcClientID *client_id = NULL;
5002 SilcServerID *server_id = NULL;
5003 SilcIDPayload idp = NULL;
5004 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5005 unsigned char *tmp, *pkdata;
5006 SilcUInt32 tmp_len, pklen;
5007 SilcBuffer pk = NULL;
5009 SilcPublicKey public_key;
5011 SILC_LOG_DEBUG(("Start"));
5013 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5016 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5019 idp = silc_id_payload_parse(tmp, tmp_len);
5021 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5022 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5026 id_type = silc_id_payload_get_type(idp);
5027 if (id_type == SILC_ID_CLIENT) {
5028 client_id = silc_id_payload_get_id(idp);
5030 /* If the client is not found from local list there is no chance it
5031 would be locally connected client so send the command further. */
5032 client = silc_idlist_find_client_by_id(server->local_list,
5033 client_id, TRUE, NULL);
5035 client = silc_idlist_find_client_by_id(server->global_list,
5036 client_id, TRUE, NULL);
5038 if ((!client && !cmd->pending && !server->standalone) ||
5039 (client && !client->connection && !cmd->pending) ||
5040 (client && !client->data.public_key && !cmd->pending)) {
5042 SilcUInt16 old_ident;
5043 SilcSocketConnection dest_sock;
5045 dest_sock = silc_server_get_client_route(server, NULL, 0,
5050 old_ident = silc_command_get_ident(cmd->payload);
5051 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5052 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5054 silc_server_packet_send(server, dest_sock,
5055 SILC_PACKET_COMMAND, cmd->packet->flags,
5056 tmpbuf->data, tmpbuf->len, TRUE);
5058 /* Reprocess this packet after received reply from router */
5059 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5060 silc_command_get_ident(cmd->payload),
5061 silc_server_command_getkey,
5062 silc_server_command_dup(cmd));
5063 cmd->pending = TRUE;
5064 silc_command_set_ident(cmd->payload, old_ident);
5065 silc_buffer_free(tmpbuf);
5070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5071 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5075 /* The client is locally connected, just get the public key and
5076 send it back. If they key does not exist then do not send it,
5077 send just OK reply */
5078 public_key = client->data.public_key;
5083 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5084 pk = silc_buffer_alloc(4 + tmp_len);
5085 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5086 silc_buffer_format(pk,
5087 SILC_STR_UI_SHORT(tmp_len),
5088 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5089 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5095 } else if (id_type == SILC_ID_SERVER) {
5096 server_id = silc_id_payload_get_id(idp);
5098 /* If the server is not found from local list there is no chance it
5099 would be locally connected server so send the command further. */
5100 server_entry = silc_idlist_find_server_by_id(server->local_list,
5101 server_id, TRUE, NULL);
5103 server_entry = silc_idlist_find_server_by_id(server->global_list,
5104 server_id, TRUE, NULL);
5106 if (server_entry != server->id_entry &&
5107 ((!server_entry && !cmd->pending && !server->standalone) ||
5108 (server_entry && !server_entry->connection && !cmd->pending &&
5109 !server->standalone) ||
5110 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5111 !server->standalone))) {
5113 SilcUInt16 old_ident;
5115 old_ident = silc_command_get_ident(cmd->payload);
5116 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5117 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5119 silc_server_packet_send(server, server->router->connection,
5120 SILC_PACKET_COMMAND, cmd->packet->flags,
5121 tmpbuf->data, tmpbuf->len, TRUE);
5123 /* Reprocess this packet after received reply from router */
5124 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5125 silc_command_get_ident(cmd->payload),
5126 silc_server_command_getkey,
5127 silc_server_command_dup(cmd));
5128 cmd->pending = TRUE;
5129 silc_command_set_ident(cmd->payload, old_ident);
5130 silc_buffer_free(tmpbuf);
5134 if (!server_entry) {
5135 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5136 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5140 /* If they key does not exist then do not send it, send just OK reply */
5141 public_key = (!server_entry->data.public_key ?
5142 (server_entry == server->id_entry ? server->public_key :
5143 NULL) : server_entry->data.public_key);
5148 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5149 pk = silc_buffer_alloc(4 + tmp_len);
5150 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5151 silc_buffer_format(pk,
5152 SILC_STR_UI_SHORT(tmp_len),
5153 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5154 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5164 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5165 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5166 SILC_STATUS_OK, ident,
5170 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5171 packet->data, packet->len, FALSE);
5172 silc_buffer_free(packet);
5175 silc_buffer_free(pk);
5179 silc_id_payload_free(idp);
5180 silc_free(client_id);
5181 silc_free(server_id);
5182 silc_server_command_free(cmd);
5186 /* Private range commands, specific to this implementation */
5188 /* Server side command of CONNECT. Connects us to the specified remote
5189 server or router. */
5191 SILC_SERVER_CMD_FUNC(connect)
5193 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5194 SilcServer server = cmd->server;
5195 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5196 unsigned char *tmp, *host;
5198 SilcUInt32 port = SILC_PORT;
5200 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5202 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5205 /* Check whether client has the permissions. */
5206 if (client->mode == SILC_UMODE_NONE) {
5207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5208 SILC_STATUS_ERR_NO_SERVER_PRIV);
5212 if (server->server_type == SILC_ROUTER &&
5213 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5214 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5215 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5219 /* Get the remote server */
5220 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5223 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5228 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5230 SILC_GET32_MSB(port, tmp);
5232 /* Create the connection. It is done with timeout and is async. */
5233 silc_server_create_connection(server, host, port);
5235 /* Send reply to the sender */
5236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5240 silc_server_command_free(cmd);
5243 /* Server side command of CLOSE. Closes connection to a specified server. */
5245 SILC_SERVER_CMD_FUNC(close)
5247 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5248 SilcServer server = cmd->server;
5249 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5250 SilcServerEntry server_entry;
5251 SilcSocketConnection sock;
5254 unsigned char *name;
5255 SilcUInt32 port = SILC_PORT;
5257 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5259 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5262 /* Check whether client has the permissions. */
5263 if (client->mode == SILC_UMODE_NONE) {
5264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5265 SILC_STATUS_ERR_NO_SERVER_PRIV);
5269 /* Get the remote server */
5270 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5273 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5278 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5280 SILC_GET32_MSB(port, tmp);
5282 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5283 name, port, FALSE, NULL);
5285 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5286 name, port, FALSE, NULL);
5287 if (!server_entry) {
5288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5289 SILC_STATUS_ERR_NO_SERVER_ID);
5293 /* Send reply to the sender */
5294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5297 /* Close the connection to the server */
5298 sock = (SilcSocketConnection)server_entry->connection;
5300 /* If we shutdown primary router connection manually then don't trigger
5301 any reconnect or backup router connections, by setting the router
5303 if (server->router == server_entry) {
5304 server->id_entry->router = NULL;
5305 server->router = NULL;
5306 server->standalone = TRUE;
5308 silc_server_free_sock_user_data(server, sock, NULL);
5309 silc_server_close_connection(server, sock);
5312 silc_server_command_free(cmd);
5315 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5316 active connections. */
5318 SILC_SERVER_CMD_FUNC(shutdown)
5320 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5321 SilcServer server = cmd->server;
5322 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5324 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5326 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5329 /* Check whether client has the permission. */
5330 if (client->mode == SILC_UMODE_NONE) {
5331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5332 SILC_STATUS_ERR_NO_SERVER_PRIV);
5336 /* Send reply to the sender */
5337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5340 /* Then, gracefully, or not, bring the server down. */
5341 silc_server_stop(server);
5345 silc_server_command_free(cmd);