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 = silc_memdup(tmp, strlen(tmp));
3831 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3832 /* Passphrase mode is unset. remove the passphrase */
3833 silc_free(channel->passphrase);
3834 channel->passphrase = NULL;
3838 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3839 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3840 /* Cipher to use protect the traffic */
3841 SilcCipher newkey, oldkey;
3844 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3847 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3851 /* Delete old cipher and allocate the new one */
3852 if (!silc_cipher_alloc(cipher, &newkey)) {
3853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3854 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3858 oldkey = channel->channel_key;
3859 channel->channel_key = newkey;
3861 /* Re-generate channel key */
3862 if (!silc_server_create_channel_key(server, channel, 0)) {
3863 /* We don't have new key, revert to old one */
3864 channel->channel_key = oldkey;
3868 /* Remove old channel key for good */
3869 silc_cipher_free(oldkey);
3871 /* Send the channel key. This sends it to our local clients and if
3872 we are normal server to our router as well. */
3873 silc_server_send_channel_key(server, NULL, channel,
3874 server->server_type == SILC_ROUTER ?
3875 FALSE : !server->standalone);
3878 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3879 /* Cipher mode is unset. Remove the cipher and revert back to
3881 SilcCipher newkey, oldkey;
3882 cipher = channel->cipher;
3884 /* Delete old cipher and allocate default one */
3885 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3887 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3891 oldkey = channel->channel_key;
3892 channel->channel_key = newkey;
3894 /* Re-generate channel key */
3895 if (!silc_server_create_channel_key(server, channel, 0)) {
3896 /* We don't have new key, revert to old one */
3897 channel->channel_key = oldkey;
3901 /* Remove old channel key for good */
3902 silc_cipher_free(oldkey);
3904 /* Send the channel key. This sends it to our local clients and if
3905 we are normal server to our router as well. */
3906 silc_server_send_channel_key(server, NULL, channel,
3907 server->server_type == SILC_ROUTER ?
3908 FALSE : !server->standalone);
3912 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3913 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3914 /* HMAC to use protect the traffic */
3915 unsigned char hash[32];
3919 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3922 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3926 /* Delete old hmac and allocate the new one */
3927 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3928 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3929 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3933 silc_hmac_free(channel->hmac);
3934 channel->hmac = newhmac;
3936 /* Set the HMAC key out of current channel key. The client must do
3938 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3939 channel->key_len / 8, hash);
3940 silc_hmac_set_key(channel->hmac, hash,
3941 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3942 memset(hash, 0, sizeof(hash));
3945 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3946 /* Hmac mode is unset. Remove the hmac and revert back to
3949 unsigned char hash[32];
3950 hmac = channel->hmac_name;
3952 /* Delete old hmac and allocate default one */
3953 silc_hmac_free(channel->hmac);
3954 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3956 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3960 silc_hmac_free(channel->hmac);
3961 channel->hmac = newhmac;
3963 /* Set the HMAC key out of current channel key. The client must do
3965 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3966 channel->key_len / 8,
3968 silc_hmac_set_key(channel->hmac, hash,
3969 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3970 memset(hash, 0, sizeof(hash));
3974 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3975 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3976 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3977 /* Set the founder authentication */
3978 SilcAuthPayload auth;
3980 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3983 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3987 auth = silc_auth_payload_parse(tmp, tmp_len);
3989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3990 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3994 /* Save the public key */
3995 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3996 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3999 channel->founder_method = silc_auth_get_method(auth);
4001 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4002 tmp = silc_auth_get_data(auth, &tmp_len);
4003 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4004 channel->founder_passwd_len = tmp_len;
4006 /* Verify the payload before setting the mode */
4007 if (!silc_auth_verify(auth, channel->founder_method,
4008 channel->founder_key, 0, idata->hash,
4009 client->id, SILC_ID_CLIENT)) {
4010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4011 SILC_STATUS_ERR_AUTH_FAILED);
4016 silc_auth_payload_free(auth);
4020 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4021 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4022 if (channel->founder_key)
4023 silc_pkcs_public_key_free(channel->founder_key);
4024 if (channel->founder_passwd) {
4025 silc_free(channel->founder_passwd);
4026 channel->founder_passwd = NULL;
4032 /* Finally, set the mode */
4033 channel->mode = mode_mask;
4035 /* Send CMODE_CHANGE notify. */
4036 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4037 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4038 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4039 cidp->data, cidp->len,
4041 cipher, cipher ? strlen(cipher) : 0,
4042 hmac, hmac ? strlen(hmac) : 0,
4043 passphrase, passphrase ?
4044 strlen(passphrase) : 0);
4046 /* Set CMODE notify type to network */
4047 if (!server->standalone)
4048 silc_server_send_notify_cmode(server, server->router->connection,
4049 server->server_type == SILC_ROUTER ?
4050 TRUE : FALSE, channel,
4051 mode_mask, client->id, SILC_ID_CLIENT,
4052 cipher, hmac, passphrase);
4054 /* Send command reply to sender */
4055 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4056 SILC_STATUS_OK, ident, 2,
4057 2, tmp_id, tmp_len2,
4059 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4060 packet->data, packet->len, FALSE);
4062 silc_buffer_free(packet);
4063 silc_free(channel_id);
4064 silc_buffer_free(cidp);
4067 silc_server_command_free(cmd);
4070 /* Server side of CUMODE command. Changes client's mode on a channel. */
4072 SILC_SERVER_CMD_FUNC(cumode)
4074 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4075 SilcServer server = cmd->server;
4076 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4077 SilcIDListData idata = (SilcIDListData)client;
4078 SilcChannelID *channel_id;
4079 SilcClientID *client_id;
4080 SilcChannelEntry channel;
4081 SilcClientEntry target_client;
4082 SilcChannelClientEntry chl;
4083 SilcBuffer packet, idp;
4084 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4085 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4087 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4089 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4091 /* Get Channel ID */
4092 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4095 SILC_STATUS_ERR_NO_CHANNEL_ID);
4098 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4101 SILC_STATUS_ERR_NO_CHANNEL_ID);
4105 /* Get channel entry */
4106 channel = silc_idlist_find_channel_by_id(server->local_list,
4109 channel = silc_idlist_find_channel_by_id(server->global_list,
4112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4113 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4118 /* Check whether sender is on the channel */
4119 if (!silc_server_client_on_channel(client, channel, &chl)) {
4120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4121 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4124 sender_mask = chl->mode;
4126 /* Get the target client's channel mode mask */
4127 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4130 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4133 SILC_GET32_MSB(target_mask, tmp_mask);
4135 /* Get target Client ID */
4136 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4139 SILC_STATUS_ERR_NO_CLIENT_ID);
4142 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4145 SILC_STATUS_ERR_NO_CLIENT_ID);
4149 /* Get target client's entry */
4150 target_client = silc_idlist_find_client_by_id(server->local_list,
4151 client_id, TRUE, NULL);
4152 if (!target_client) {
4153 target_client = silc_idlist_find_client_by_id(server->global_list,
4154 client_id, TRUE, NULL);
4157 if (target_client != client &&
4158 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4159 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4161 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4165 /* Check whether target client is on the channel */
4166 if (target_client != client) {
4167 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4168 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4169 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4178 /* If the target client is founder, no one else can change their mode
4180 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4181 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4182 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4186 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4187 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4188 /* The client tries to claim the founder rights. */
4189 unsigned char *tmp_auth;
4190 SilcUInt32 tmp_auth_len, auth_len;
4193 if (target_client != client) {
4194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4195 SILC_STATUS_ERR_NOT_YOU);
4199 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4200 !channel->founder_key || !idata->public_key ||
4201 !silc_pkcs_public_key_compare(channel->founder_key,
4202 idata->public_key)) {
4203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4204 SILC_STATUS_ERR_NOT_YOU);
4208 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4211 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4215 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4216 (void *)channel->founder_passwd : (void *)channel->founder_key);
4217 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4218 channel->founder_passwd_len : 0);
4220 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4221 channel->founder_method, auth, auth_len,
4222 idata->hash, client->id, SILC_ID_CLIENT)) {
4223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4224 SILC_STATUS_ERR_AUTH_FAILED);
4228 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4232 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4233 if (target_client == client) {
4234 /* Remove channel founder rights from itself */
4235 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4239 SILC_STATUS_ERR_NOT_YOU);
4245 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4246 /* Promote to operator */
4247 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4248 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4249 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4251 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4255 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4259 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4260 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4261 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4263 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4267 /* Demote to normal user */
4268 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4273 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4274 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4276 /* Send notify to channel, notify only if mode was actually changed. */
4278 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4279 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4280 idp->data, idp->len,
4284 /* Set CUMODE notify type to network */
4285 if (!server->standalone)
4286 silc_server_send_notify_cumode(server, server->router->connection,
4287 server->server_type == SILC_ROUTER ?
4288 TRUE : FALSE, channel,
4289 target_mask, client->id,
4294 /* Send command reply to sender */
4295 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4296 SILC_STATUS_OK, ident, 3,
4298 3, tmp_ch_id, tmp_ch_len,
4299 4, tmp_id, tmp_len);
4300 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4301 packet->data, packet->len, FALSE);
4303 silc_buffer_free(packet);
4304 silc_free(channel_id);
4305 silc_free(client_id);
4306 silc_buffer_free(idp);
4309 silc_server_command_free(cmd);
4312 /* Server side of KICK command. Kicks client out of channel. */
4314 SILC_SERVER_CMD_FUNC(kick)
4316 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4317 SilcServer server = cmd->server;
4318 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4319 SilcClientEntry target_client;
4320 SilcChannelID *channel_id;
4321 SilcClientID *client_id;
4322 SilcChannelEntry channel;
4323 SilcChannelClientEntry chl;
4325 SilcUInt32 tmp_len, target_idp_len;
4326 unsigned char *tmp, *comment, *target_idp;
4328 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4330 /* Get Channel ID */
4331 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4334 SILC_STATUS_ERR_NO_CHANNEL_ID);
4337 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4340 SILC_STATUS_ERR_NO_CHANNEL_ID);
4344 /* Get channel entry */
4345 channel = silc_idlist_find_channel_by_id(server->local_list,
4348 channel = silc_idlist_find_channel_by_id(server->local_list,
4351 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4352 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4357 /* Check whether sender is on the channel */
4358 if (!silc_server_client_on_channel(client, channel, &chl)) {
4359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4360 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4364 /* Check that the kicker is channel operator or channel founder */
4365 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4366 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4367 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4371 /* Get target Client ID */
4372 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4375 SILC_STATUS_ERR_NO_CLIENT_ID);
4378 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4381 SILC_STATUS_ERR_NO_CLIENT_ID);
4385 /* Get target client's entry */
4386 target_client = silc_idlist_find_client_by_id(server->local_list,
4387 client_id, TRUE, NULL);
4388 if (!target_client) {
4389 target_client = silc_idlist_find_client_by_id(server->global_list,
4390 client_id, TRUE, NULL);
4393 /* Check whether target client is on the channel */
4394 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4396 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4400 /* Check that the target client is not channel founder. Channel founder
4401 cannot be kicked from the channel. */
4402 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4404 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4410 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4414 /* Send command reply to sender */
4415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4418 /* Send KICKED notify to local clients on the channel */
4419 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4420 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4421 SILC_NOTIFY_TYPE_KICKED, 3,
4422 target_idp, target_idp_len,
4423 comment, comment ? strlen(comment) : 0,
4424 idp->data, idp->len);
4425 silc_buffer_free(idp);
4427 /* Remove the client from the channel. If the channel does not exist
4428 after removing the client then the client kicked itself off the channel
4429 and we don't have to send anything after that. */
4430 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4431 target_client, FALSE))
4434 /* Send KICKED notify to primary route */
4435 if (!server->standalone)
4436 silc_server_send_notify_kicked(server, server->router->connection,
4437 server->server_type == SILC_ROUTER ?
4438 TRUE : FALSE, channel,
4439 target_client->id, client->id, comment);
4441 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4442 /* Re-generate channel key */
4443 if (!silc_server_create_channel_key(server, channel, 0))
4446 /* Send the channel key to the channel. The key of course is not sent
4447 to the client who was kicked off the channel. */
4448 silc_server_send_channel_key(server, target_client->connection, channel,
4449 server->server_type == SILC_ROUTER ?
4450 FALSE : !server->standalone);
4454 silc_server_command_free(cmd);
4457 /* Server side of OPER command. Client uses this comand to obtain server
4458 operator privileges to this server/router. */
4460 SILC_SERVER_CMD_FUNC(oper)
4462 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4463 SilcServer server = cmd->server;
4464 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4465 unsigned char *username, *auth;
4467 SilcServerConfigAdmin *admin;
4468 SilcIDListData idata = (SilcIDListData)client;
4469 bool result = FALSE;
4470 SilcPublicKey cached_key;
4472 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4474 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4477 /* Get the username */
4478 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4480 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4481 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4485 /* Get the admin configuration */
4486 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4487 username, client->nickname);
4489 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4490 username, client->nickname);
4492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4493 SILC_STATUS_ERR_AUTH_FAILED);
4498 /* Get the authentication payload */
4499 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4502 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4506 /* Verify the authentication data. If both passphrase and public key
4507 is set then try both of them. */
4508 if (admin->passphrase)
4509 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4510 admin->passphrase, admin->passphrase_len,
4511 idata->hash, client->id, SILC_ID_CLIENT);
4512 if (!result && admin->publickeys) {
4513 cached_key = silc_server_get_public_key(server, admin->publickeys);
4516 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4517 cached_key, 0, idata->hash,
4518 client->id, SILC_ID_CLIENT);
4521 /* Authentication failed */
4522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4523 SILC_STATUS_ERR_AUTH_FAILED);
4527 /* Client is now server operator */
4528 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4530 /* Update statistics */
4531 if (client->connection)
4532 server->stat.my_server_ops++;
4533 if (server->server_type == SILC_ROUTER)
4534 server->stat.server_ops++;
4536 /* Send UMODE change to primary router */
4537 if (!server->standalone)
4538 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4539 client->id, client->mode);
4541 /* Send reply to the sender */
4542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4546 silc_server_command_free(cmd);
4549 /* Server side of SILCOPER command. Client uses this comand to obtain router
4550 operator privileges to this router. */
4552 SILC_SERVER_CMD_FUNC(silcoper)
4554 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4555 SilcServer server = cmd->server;
4556 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4557 unsigned char *username, *auth;
4559 SilcServerConfigAdmin *admin;
4560 SilcIDListData idata = (SilcIDListData)client;
4561 bool result = FALSE;
4562 SilcPublicKey cached_key;
4564 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4566 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4569 if (server->server_type != SILC_ROUTER) {
4570 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4571 SILC_STATUS_ERR_AUTH_FAILED);
4575 /* Get the username */
4576 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4579 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4583 /* Get the admin configuration */
4584 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4585 username, client->nickname);
4587 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4588 username, client->nickname);
4590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4591 SILC_STATUS_ERR_AUTH_FAILED);
4596 /* Get the authentication payload */
4597 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4600 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4604 /* Verify the authentication data. If both passphrase and public key
4605 is set then try both of them. */
4606 if (admin->passphrase)
4607 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4608 admin->passphrase, admin->passphrase_len,
4609 idata->hash, client->id, SILC_ID_CLIENT);
4610 if (!result && admin->publickeys) {
4611 cached_key = silc_server_get_public_key(server, admin->publickeys);
4614 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4615 cached_key, 0, idata->hash,
4616 client->id, SILC_ID_CLIENT);
4619 /* Authentication failed */
4620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4621 SILC_STATUS_ERR_AUTH_FAILED);
4625 /* Client is now router operator */
4626 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4628 /* Update statistics */
4629 if (client->connection)
4630 server->stat.my_router_ops++;
4631 if (server->server_type == SILC_ROUTER)
4632 server->stat.router_ops++;
4634 /* Send UMODE change to primary router */
4635 if (!server->standalone)
4636 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4637 client->id, client->mode);
4639 /* Send reply to the sender */
4640 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4644 silc_server_command_free(cmd);
4647 /* Server side of command BAN. This is used to manage the ban list of the
4648 channel. To add clients and remove clients from the ban list. */
4650 SILC_SERVER_CMD_FUNC(ban)
4652 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4653 SilcServer server = cmd->server;
4654 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4656 SilcChannelEntry channel;
4657 SilcChannelClientEntry chl;
4658 SilcChannelID *channel_id = NULL;
4659 unsigned char *id, *add, *del;
4660 SilcUInt32 id_len, tmp_len;
4661 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4663 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4666 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4668 /* Get Channel ID */
4669 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4671 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4674 SILC_STATUS_ERR_NO_CHANNEL_ID);
4679 /* Get channel entry. The server must know about the channel since the
4680 client is expected to be on the channel. */
4681 channel = silc_idlist_find_channel_by_id(server->local_list,
4684 channel = silc_idlist_find_channel_by_id(server->global_list,
4687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4688 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4693 /* Check whether this client is on the channel */
4694 if (!silc_server_client_on_channel(client, channel, &chl)) {
4695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4696 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4700 /* The client must be at least channel operator. */
4701 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4703 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4707 /* Get the new ban and add it to the ban list */
4708 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4710 if (!channel->ban_list)
4711 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4713 channel->ban_list = silc_realloc(channel->ban_list,
4714 sizeof(*channel->ban_list) *
4716 strlen(channel->ban_list) + 2));
4717 if (add[tmp_len - 1] == ',')
4718 add[tmp_len - 1] = '\0';
4720 strncat(channel->ban_list, add, tmp_len);
4721 strncat(channel->ban_list, ",", 1);
4724 /* Get the ban to be removed and remove it from the list */
4725 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4726 if (del && channel->ban_list) {
4727 char *start, *end, *n;
4729 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4730 silc_free(channel->ban_list);
4731 channel->ban_list = NULL;
4733 start = strstr(channel->ban_list, del);
4734 if (start && strlen(start) >= tmp_len) {
4735 end = start + tmp_len;
4736 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4737 strncat(n, channel->ban_list, start - channel->ban_list);
4738 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4740 silc_free(channel->ban_list);
4741 channel->ban_list = n;
4746 /* Send the BAN notify type to our primary router. */
4747 if (!server->standalone && (add || del))
4748 silc_server_send_notify_ban(server, server->router->connection,
4749 server->server_type == SILC_ROUTER ?
4750 TRUE : FALSE, channel, add, del);
4752 /* Send the reply back to the client */
4754 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4755 SILC_STATUS_OK, ident, 2,
4757 3, channel->ban_list,
4759 strlen(channel->ban_list) -1 : 0);
4760 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4761 packet->data, packet->len, FALSE);
4763 silc_buffer_free(packet);
4766 silc_free(channel_id);
4767 silc_server_command_free(cmd);
4770 /* Server side command of LEAVE. Removes client from a channel. */
4772 SILC_SERVER_CMD_FUNC(leave)
4774 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4775 SilcServer server = cmd->server;
4776 SilcSocketConnection sock = cmd->sock;
4777 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4778 SilcChannelID *id = NULL;
4779 SilcChannelEntry channel;
4783 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4785 /* Get Channel ID */
4786 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4789 SILC_STATUS_ERR_NO_CHANNEL_ID);
4792 id = silc_id_payload_parse_id(tmp, len, NULL);
4794 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4795 SILC_STATUS_ERR_NO_CHANNEL_ID);
4799 /* Get channel entry */
4800 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4802 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4805 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4810 /* Check whether this client is on the channel */
4811 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4813 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4817 /* Notify routers that they should remove this client from their list
4818 of clients on the channel. Send LEAVE notify type. */
4819 if (!server->standalone)
4820 silc_server_send_notify_leave(server, server->router->connection,
4821 server->server_type == SILC_ROUTER ?
4822 TRUE : FALSE, channel, id_entry->id);
4824 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4825 SILC_STATUS_OK, 2, tmp, len);
4827 /* Remove client from channel */
4828 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4830 /* If the channel does not exist anymore we won't send anything */
4833 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4834 /* Re-generate channel key */
4835 if (!silc_server_create_channel_key(server, channel, 0))
4838 /* Send the channel key */
4839 silc_server_send_channel_key(server, NULL, channel,
4840 server->server_type == SILC_ROUTER ?
4841 FALSE : !server->standalone);
4846 silc_server_command_free(cmd);
4849 /* Server side of command USERS. Resolves clients and their USERS currently
4850 joined on the requested channel. The list of Client ID's and their modes
4851 on the channel is sent back. */
4853 SILC_SERVER_CMD_FUNC(users)
4855 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4856 SilcServer server = cmd->server;
4857 SilcChannelEntry channel;
4858 SilcChannelID *id = NULL;
4859 SilcBuffer packet, idp;
4860 unsigned char *channel_id;
4861 SilcUInt32 channel_id_len;
4862 SilcBuffer client_id_list;
4863 SilcBuffer client_mode_list;
4864 unsigned char lc[4];
4865 SilcUInt32 list_count = 0;
4866 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4869 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4871 /* Get Channel ID */
4872 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4874 /* Get channel name */
4875 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4877 if (!channel_id && !channel_name) {
4878 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4879 SILC_STATUS_ERR_NO_CHANNEL_ID);
4884 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4887 SILC_STATUS_ERR_NO_CHANNEL_ID);
4892 /* If we are server and we don't know about this channel we will send
4893 the command to our router. If we know about the channel then we also
4894 have the list of users already. */
4896 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4898 channel = silc_idlist_find_channel_by_name(server->local_list,
4899 channel_name, NULL);
4901 if (!channel || channel->disabled) {
4902 if (server->server_type != SILC_ROUTER && !server->standalone &&
4906 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4907 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4909 /* Send USERS command */
4910 silc_server_packet_send(server, server->router->connection,
4911 SILC_PACKET_COMMAND, cmd->packet->flags,
4912 tmpbuf->data, tmpbuf->len, TRUE);
4914 /* Reprocess this packet after received reply */
4915 silc_server_command_pending(server, SILC_COMMAND_USERS,
4916 silc_command_get_ident(cmd->payload),
4917 silc_server_command_users,
4918 silc_server_command_dup(cmd));
4919 cmd->pending = TRUE;
4920 silc_command_set_ident(cmd->payload, ident);
4921 silc_buffer_free(tmpbuf);
4926 /* Check the global list as well. */
4928 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4930 channel = silc_idlist_find_channel_by_name(server->global_list,
4931 channel_name, NULL);
4933 /* Channel really does not exist */
4934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4935 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4940 /* If the channel is private or secret do not send anything, unless the
4941 user requesting this command is on the channel. */
4942 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4943 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4944 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4946 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4947 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4952 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
4953 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4954 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4959 /* Get the users list */
4960 silc_server_get_users_on_channel(server, channel, &client_id_list,
4961 &client_mode_list, &list_count);
4964 SILC_PUT32_MSB(list_count, lc);
4967 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4968 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4969 SILC_STATUS_OK, ident, 4,
4970 2, idp->data, idp->len,
4972 4, client_id_list->data,
4973 client_id_list->len,
4974 5, client_mode_list->data,
4975 client_mode_list->len);
4976 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4977 packet->data, packet->len, FALSE);
4979 silc_buffer_free(idp);
4980 silc_buffer_free(packet);
4981 silc_buffer_free(client_id_list);
4982 silc_buffer_free(client_mode_list);
4986 silc_server_command_free(cmd);
4989 /* Server side of command GETKEY. This fetches the client's public key
4990 from the server where to the client is connected. */
4992 SILC_SERVER_CMD_FUNC(getkey)
4994 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4995 SilcServer server = cmd->server;
4997 SilcClientEntry client;
4998 SilcServerEntry server_entry;
4999 SilcClientID *client_id = NULL;
5000 SilcServerID *server_id = NULL;
5001 SilcIDPayload idp = NULL;
5002 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5003 unsigned char *tmp, *pkdata;
5004 SilcUInt32 tmp_len, pklen;
5005 SilcBuffer pk = NULL;
5007 SilcPublicKey public_key;
5009 SILC_LOG_DEBUG(("Start"));
5011 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5014 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5017 idp = silc_id_payload_parse(tmp, tmp_len);
5019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5020 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5024 id_type = silc_id_payload_get_type(idp);
5025 if (id_type == SILC_ID_CLIENT) {
5026 client_id = silc_id_payload_get_id(idp);
5028 /* If the client is not found from local list there is no chance it
5029 would be locally connected client so send the command further. */
5030 client = silc_idlist_find_client_by_id(server->local_list,
5031 client_id, TRUE, NULL);
5033 client = silc_idlist_find_client_by_id(server->global_list,
5034 client_id, TRUE, NULL);
5036 if ((!client && !cmd->pending && !server->standalone) ||
5037 (client && !client->connection && !cmd->pending) ||
5038 (client && !client->data.public_key && !cmd->pending)) {
5040 SilcUInt16 old_ident;
5041 SilcSocketConnection dest_sock;
5043 dest_sock = silc_server_get_client_route(server, NULL, 0,
5048 old_ident = silc_command_get_ident(cmd->payload);
5049 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5050 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5052 silc_server_packet_send(server, dest_sock,
5053 SILC_PACKET_COMMAND, cmd->packet->flags,
5054 tmpbuf->data, tmpbuf->len, TRUE);
5056 /* Reprocess this packet after received reply from router */
5057 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5058 silc_command_get_ident(cmd->payload),
5059 silc_server_command_getkey,
5060 silc_server_command_dup(cmd));
5061 cmd->pending = TRUE;
5062 silc_command_set_ident(cmd->payload, old_ident);
5063 silc_buffer_free(tmpbuf);
5068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5069 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5073 /* The client is locally connected, just get the public key and
5074 send it back. If they key does not exist then do not send it,
5075 send just OK reply */
5076 public_key = client->data.public_key;
5081 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5082 pk = silc_buffer_alloc(4 + tmp_len);
5083 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5084 silc_buffer_format(pk,
5085 SILC_STR_UI_SHORT(tmp_len),
5086 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5087 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5093 } else if (id_type == SILC_ID_SERVER) {
5094 server_id = silc_id_payload_get_id(idp);
5096 /* If the server is not found from local list there is no chance it
5097 would be locally connected server so send the command further. */
5098 server_entry = silc_idlist_find_server_by_id(server->local_list,
5099 server_id, TRUE, NULL);
5101 server_entry = silc_idlist_find_server_by_id(server->global_list,
5102 server_id, TRUE, NULL);
5104 if (server_entry != server->id_entry &&
5105 ((!server_entry && !cmd->pending && !server->standalone) ||
5106 (server_entry && !server_entry->connection && !cmd->pending &&
5107 !server->standalone) ||
5108 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5109 !server->standalone))) {
5111 SilcUInt16 old_ident;
5113 old_ident = silc_command_get_ident(cmd->payload);
5114 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5115 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5117 silc_server_packet_send(server, server->router->connection,
5118 SILC_PACKET_COMMAND, cmd->packet->flags,
5119 tmpbuf->data, tmpbuf->len, TRUE);
5121 /* Reprocess this packet after received reply from router */
5122 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5123 silc_command_get_ident(cmd->payload),
5124 silc_server_command_getkey,
5125 silc_server_command_dup(cmd));
5126 cmd->pending = TRUE;
5127 silc_command_set_ident(cmd->payload, old_ident);
5128 silc_buffer_free(tmpbuf);
5132 if (!server_entry) {
5133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5134 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5138 /* If they key does not exist then do not send it, send just OK reply */
5139 public_key = (!server_entry->data.public_key ?
5140 (server_entry == server->id_entry ? server->public_key :
5141 NULL) : server_entry->data.public_key);
5146 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5147 pk = silc_buffer_alloc(4 + tmp_len);
5148 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5149 silc_buffer_format(pk,
5150 SILC_STR_UI_SHORT(tmp_len),
5151 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5152 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5162 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5163 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5164 SILC_STATUS_OK, ident,
5168 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5169 packet->data, packet->len, FALSE);
5170 silc_buffer_free(packet);
5173 silc_buffer_free(pk);
5177 silc_id_payload_free(idp);
5178 silc_free(client_id);
5179 silc_free(server_id);
5180 silc_server_command_free(cmd);
5184 /* Private range commands, specific to this implementation */
5186 /* Server side command of CONNECT. Connects us to the specified remote
5187 server or router. */
5189 SILC_SERVER_CMD_FUNC(connect)
5191 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5192 SilcServer server = cmd->server;
5193 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5194 unsigned char *tmp, *host;
5196 SilcUInt32 port = SILC_PORT;
5198 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5200 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5203 /* Check whether client has the permissions. */
5204 if (client->mode == SILC_UMODE_NONE) {
5205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5206 SILC_STATUS_ERR_NO_SERVER_PRIV);
5210 if (server->server_type == SILC_ROUTER &&
5211 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5213 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5217 /* Get the remote server */
5218 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5220 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5221 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5226 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5228 SILC_GET32_MSB(port, tmp);
5230 /* Create the connection. It is done with timeout and is async. */
5231 silc_server_create_connection(server, host, port);
5233 /* Send reply to the sender */
5234 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5238 silc_server_command_free(cmd);
5241 /* Server side command of CLOSE. Closes connection to a specified server. */
5243 SILC_SERVER_CMD_FUNC(close)
5245 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5246 SilcServer server = cmd->server;
5247 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5248 SilcServerEntry server_entry;
5249 SilcSocketConnection sock;
5252 unsigned char *name;
5253 SilcUInt32 port = SILC_PORT;
5255 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5257 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5260 /* Check whether client has the permissions. */
5261 if (client->mode == SILC_UMODE_NONE) {
5262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5263 SILC_STATUS_ERR_NO_SERVER_PRIV);
5267 /* Get the remote server */
5268 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5271 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5276 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5278 SILC_GET32_MSB(port, tmp);
5280 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5281 name, port, FALSE, NULL);
5283 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5284 name, port, FALSE, NULL);
5285 if (!server_entry) {
5286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5287 SILC_STATUS_ERR_NO_SERVER_ID);
5291 /* Send reply to the sender */
5292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5295 /* Close the connection to the server */
5296 sock = (SilcSocketConnection)server_entry->connection;
5298 /* If we shutdown primary router connection manually then don't trigger
5299 any reconnect or backup router connections, by setting the router
5301 if (server->router == server_entry) {
5302 server->id_entry->router = NULL;
5303 server->router = NULL;
5304 server->standalone = TRUE;
5306 silc_server_free_sock_user_data(server, sock, NULL);
5307 silc_server_close_connection(server, sock);
5310 silc_server_command_free(cmd);
5313 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5314 active connections. */
5316 SILC_SERVER_CMD_FUNC(shutdown)
5318 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5319 SilcServer server = cmd->server;
5320 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5322 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5324 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5327 /* Check whether client has the permission. */
5328 if (client->mode == SILC_UMODE_NONE) {
5329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5330 SILC_STATUS_ERR_NO_SERVER_PRIV);
5334 /* Send reply to the sender */
5335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5338 /* Then, gracefully, or not, bring the server down. */
5339 silc_server_stop(server);
5343 silc_server_command_free(cmd);