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(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(silcoper, SILCOPER,
70 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
71 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
72 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
73 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
75 SILC_SERVER_CMD(connect, PRIV_CONNECT,
76 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
77 SILC_SERVER_CMD(close, PRIV_CLOSE,
78 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
79 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
85 /* Performs several checks to the command. It first checks whether this
86 command was called as pending command callback. If it was then it checks
87 whether error occurred in the command reply where the pending command
90 It also checks that the requested command includes correct amount
92 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
96 SILC_LOG_DEBUG(("Start")); \
98 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
99 silc_server_command_free(cmd); \
103 _argc = silc_argument_get_arg_num(cmd->args); \
105 silc_server_command_send_status_reply(cmd, command, \
106 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
107 silc_server_command_free(cmd); \
111 silc_server_command_send_status_reply(cmd, command, \
112 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
113 silc_server_command_free(cmd); \
118 /* Returns TRUE if the connection is registered. Unregistered connections
119 usually cannot send commands hence the check. */
121 static int silc_server_is_registered(SilcServer server,
122 SilcSocketConnection sock,
123 SilcServerCommandContext cmd,
126 SilcIDListData idata = (SilcIDListData)sock->user_data;
131 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
134 silc_server_command_send_status_reply(cmd, command,
135 SILC_STATUS_ERR_NOT_REGISTERED);
139 /* Internal context to hold data when executed command with timeout. */
141 SilcServerCommandContext ctx;
142 SilcServerCommand *cmd;
143 } *SilcServerCommandTimeout;
145 /* Timeout callback to process commands with timeout for client. Client's
146 commands are always executed with timeout. */
148 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
150 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
151 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
154 silc_server_command_free(timeout->ctx);
158 /* Update access time */
159 client->last_command = time(NULL);
161 if (!(timeout->cmd->flags & SILC_CF_REG))
162 timeout->cmd->cb(timeout->ctx, NULL);
163 else if (silc_server_is_registered(timeout->ctx->server,
167 timeout->cmd->cb(timeout->ctx, NULL);
169 silc_server_command_free(timeout->ctx);
174 /* Processes received command packet. */
176 void silc_server_command_process(SilcServer server,
177 SilcSocketConnection sock,
178 SilcPacketContext *packet)
180 SilcServerCommandContext ctx;
181 SilcServerCommand *cmd;
184 /* Allocate command context. This must be free'd by the
185 command routine receiving it. */
186 ctx = silc_server_command_alloc();
187 ctx->server = server;
188 ctx->sock = silc_socket_dup(sock);
189 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
191 /* Parse the command payload in the packet */
192 ctx->payload = silc_command_payload_parse(packet->buffer->data,
193 packet->buffer->len);
195 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
196 silc_buffer_free(packet->buffer);
197 silc_packet_context_free(packet);
198 silc_socket_free(ctx->sock);
202 ctx->args = silc_command_get_args(ctx->payload);
204 /* Get the command */
205 command = silc_command_get(ctx->payload);
206 for (cmd = silc_command_list; cmd->cb; cmd++)
207 if (cmd->cmd == command)
210 if (!cmd || !cmd->cb) {
211 silc_server_command_send_status_reply(ctx, command,
212 SILC_STATUS_ERR_UNKNOWN_COMMAND);
213 silc_server_command_free(ctx);
217 /* Execute client's commands always with timeout. Normally they are
218 executed with zero (0) timeout but if client is sending command more
219 frequently than once in 2 seconds, then the timeout may be 0 to 2
221 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
222 SilcClientEntry client = (SilcClientEntry)sock->user_data;
223 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
229 if (client->last_command && (time(NULL) - client->last_command) < 2) {
230 client->fast_command++;
233 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
234 client->fast_command--);
238 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
239 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
240 silc_schedule_task_add(server->schedule, sock->sock,
241 silc_server_command_process_timeout,
243 2 - (time(NULL) - client->last_command), 0,
244 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
246 silc_schedule_task_add(server->schedule, sock->sock,
247 silc_server_command_process_timeout,
248 (void *)timeout, 0, 1,
249 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
253 /* Execute for server */
255 if (!(cmd->flags & SILC_CF_REG))
257 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
260 silc_server_command_free(ctx);
263 /* Allocate Command Context */
265 SilcServerCommandContext silc_server_command_alloc()
267 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
272 /* Free's the command context allocated before executing the command */
274 void silc_server_command_free(SilcServerCommandContext ctx)
277 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
279 if (ctx->users < 1) {
281 silc_command_payload_free(ctx->payload);
283 silc_packet_context_free(ctx->packet);
285 silc_socket_free(ctx->sock); /* Decrease reference counter */
290 /* Duplicate Command Context by adding reference counter. The context won't
291 be free'd untill it hits zero. */
293 SilcServerCommandContext
294 silc_server_command_dup(SilcServerCommandContext ctx)
297 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
302 /* Add new pending command to be executed when reply to a command has been
303 received. The `reply_cmd' is the command that will call the `callback'
304 with `context' when reply has been received. It can be SILC_COMMAND_NONE
305 to match any command with the `ident'. If `ident' is non-zero
306 the `callback' will be executed when received reply with command
307 identifier `ident'. If there already exists pending command for the
308 specified command, ident, callback and context this function has no
311 bool silc_server_command_pending(SilcServer server,
312 SilcCommand reply_cmd,
314 SilcCommandCb callback,
317 SilcServerCommandPending *reply;
319 /* Check whether identical pending already exists for same command,
320 ident, callback and callback context. If it does then it would be
321 error to register it again. */
322 silc_dlist_start(server->pending_commands);
323 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
324 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
325 reply->callback == callback && reply->context == context)
329 reply = silc_calloc(1, sizeof(*reply));
330 reply->reply_cmd = reply_cmd;
331 reply->ident = ident;
332 reply->context = context;
333 reply->callback = callback;
334 silc_dlist_add(server->pending_commands, reply);
339 /* Deletes pending command by reply command type. */
341 void silc_server_command_pending_del(SilcServer server,
342 SilcCommand reply_cmd,
345 SilcServerCommandPending *r;
347 silc_dlist_start(server->pending_commands);
348 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
349 if (r->reply_cmd == reply_cmd && r->ident == ident) {
350 silc_dlist_del(server->pending_commands, r);
356 /* Checks for pending commands and marks callbacks to be called from
357 the command reply function. Returns TRUE if there were pending command. */
359 SilcServerCommandPendingCallbacks
360 silc_server_command_pending_check(SilcServer server,
361 SilcServerCommandReplyContext ctx,
364 SilcUInt32 *callbacks_count)
366 SilcServerCommandPending *r;
367 SilcServerCommandPendingCallbacks callbacks = NULL;
370 silc_dlist_start(server->pending_commands);
371 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
372 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
373 && r->ident == ident) {
374 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
375 callbacks[i].context = r->context;
376 callbacks[i].callback = r->callback;
382 *callbacks_count = i;
386 /* Sends simple status message as command reply packet */
389 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
391 SilcCommandStatus status)
395 SILC_LOG_DEBUG(("Sending command status %d", status));
398 silc_command_reply_payload_encode_va(command, status, 0,
399 silc_command_get_ident(cmd->payload),
401 silc_server_packet_send(cmd->server, cmd->sock,
402 SILC_PACKET_COMMAND_REPLY, 0,
403 buffer->data, buffer->len, FALSE);
404 silc_buffer_free(buffer);
407 /* Sends command status reply with one extra argument. The argument
408 type must be sent as argument. */
411 silc_server_command_send_status_data(SilcServerCommandContext cmd,
413 SilcCommandStatus status,
415 const unsigned char *arg,
420 SILC_LOG_DEBUG(("Sending command status %d", status));
423 silc_command_reply_payload_encode_va(command, status, 0,
424 silc_command_get_ident(cmd->payload),
425 1, arg_type, arg, arg_len);
426 silc_server_packet_send(cmd->server, cmd->sock,
427 SILC_PACKET_COMMAND_REPLY, 0,
428 buffer->data, buffer->len, FALSE);
429 silc_buffer_free(buffer);
432 /* This function can be called to check whether in the command reply
433 an error occurred. This function has no effect if this is called
434 when the command function was not called as pending command callback.
435 This returns TRUE if error had occurred. */
438 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
439 SilcServerCommandReplyContext cmdr,
442 if (!cmd->pending || !cmdr)
445 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
448 /* Send the same command reply payload */
449 silc_command_set_ident(cmdr->payload,
450 silc_command_get_ident(cmd->payload));
451 buffer = silc_command_payload_encode_payload(cmdr->payload);
452 silc_server_packet_send(cmd->server, cmd->sock,
453 SILC_PACKET_COMMAND_REPLY, 0,
454 buffer->data, buffer->len, FALSE);
455 silc_buffer_free(buffer);
462 /******************************************************************************
466 ******************************************************************************/
469 silc_server_command_whois_parse(SilcServerCommandContext cmd,
470 SilcClientID ***client_id,
471 SilcUInt32 *client_id_count,
479 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
482 /* If client ID is in the command it must be used instead of nickname */
483 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
485 /* No ID, get the nickname@server string and parse it. */
486 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
488 silc_parse_userfqdn(tmp, nickname, server_name);
490 silc_server_command_send_status_reply(cmd, command,
491 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
495 /* Command includes ID, we must use that. Also check whether the command
496 has more than one ID set - take them all. */
498 *client_id = silc_calloc(1, sizeof(**client_id));
499 (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
500 if ((*client_id)[0] == NULL) {
501 silc_free(*client_id);
502 silc_server_command_send_status_reply(cmd, command,
503 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
506 *client_id_count = 1;
508 /* Take all ID's from the command packet */
510 for (k = 1, i = 1; i < argc; i++) {
511 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
513 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
514 (*client_id_count + 1));
515 (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
516 if ((*client_id)[k] == NULL) {
517 /* Cleanup all and fail */
518 for (i = 0; i < *client_id_count; i++)
519 silc_free((*client_id)[i]);
520 silc_free(*client_id);
521 silc_server_command_send_status_reply(
523 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
526 (*client_id_count)++;
533 /* Get the max count of reply messages allowed */
534 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
543 /* Resolve context used by both WHOIS and IDENTIFY commands */
545 SilcServerEntry router;
547 unsigned char **res_argv;
548 SilcUInt32 *res_argv_lens;
549 SilcUInt32 *res_argv_types;
551 } *SilcServerResolveContext;
554 silc_server_command_whois_check(SilcServerCommandContext cmd,
555 SilcClientEntry *clients,
556 SilcUInt32 clients_count)
558 SilcServer server = cmd->server;
559 SilcClientEntry entry;
560 SilcServerResolveContext resolve = NULL, r = NULL;
561 SilcUInt32 resolve_count = 0;
565 SILC_LOG_DEBUG(("Start"));
567 for (i = 0; i < clients_count; i++) {
572 if ((entry->nickname && entry->username && entry->userinfo) ||
573 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
577 /* If we are normal server, and we've not resolved this client from
578 router and it is global client, we'll check whether it is on some
579 channel. If not then we cannot be sure about its validity, and
580 we'll resolve it from router. */
581 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
582 entry->connection || silc_hash_table_count(entry->channels))
586 /* We need to resolve this entry since it is not complete */
588 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
589 /* The entry is being resolved (and we are not the resolver) so attach
590 to the command reply and we're done with this one. */
591 silc_server_command_pending(server, SILC_COMMAND_NONE,
592 entry->resolve_cmd_ident,
593 silc_server_command_whois,
594 silc_server_command_dup(cmd));
597 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
598 /* We've resolved this and it still is not ready. We'll return
599 and are that this will be handled again after it is resolved. */
600 for (i = 0; i < resolve_count; i++) {
601 for (k = 0; k < r->res_argc; k++)
602 silc_free(r->res_argv[k]);
603 silc_free(r->res_argv);
604 silc_free(r->res_argv_lens);
605 silc_free(r->res_argv_types);
610 /* We'll resolve this client */
614 for (k = 0; k < resolve_count; k++) {
615 if (resolve[k].router == entry->router) {
622 resolve = silc_realloc(resolve, sizeof(*resolve) *
623 (resolve_count + 1));
624 r = &resolve[resolve_count];
625 memset(r, 0, sizeof(*r));
626 r->router = entry->router;
627 r->ident = ++server->cmd_ident;
631 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
633 r->res_argv_lens = silc_realloc(r->res_argv_lens,
634 sizeof(*r->res_argv_lens) *
636 r->res_argv_types = silc_realloc(r->res_argv_types,
637 sizeof(*r->res_argv_types) *
639 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
640 r->res_argv[r->res_argc] = silc_calloc(idp->len,
641 sizeof(**r->res_argv));
642 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
643 r->res_argv_lens[r->res_argc] = idp->len;
644 r->res_argv_types[r->res_argc] = r->res_argc + 3;
646 silc_buffer_free(idp);
648 entry->resolve_cmd_ident = r->ident;
649 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
650 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
655 /* Do the resolving */
656 for (i = 0; i < resolve_count; i++) {
661 /* Send WHOIS request. We send WHOIS since we're doing the requesting
662 now anyway so make it a good one. */
663 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
664 r->res_argc, r->res_argv,
668 silc_server_packet_send(server, r->router->connection,
669 SILC_PACKET_COMMAND, cmd->packet->flags,
670 res_cmd->data, res_cmd->len, FALSE);
672 /* Reprocess this packet after received reply */
673 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
675 silc_server_command_whois,
676 silc_server_command_dup(cmd));
679 silc_buffer_free(res_cmd);
680 for (k = 0; k < r->res_argc; k++)
681 silc_free(r->res_argv[k]);
682 silc_free(r->res_argv);
683 silc_free(r->res_argv_lens);
684 silc_free(r->res_argv_types);
693 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
694 SilcClientEntry *clients,
695 SilcUInt32 clients_count,
697 const char *nickname,
698 SilcClientID **client_ids)
700 SilcServer server = cmd->server;
702 int i, k, len, valid_count;
703 SilcBuffer packet, idp, channels;
704 SilcClientEntry entry;
705 SilcCommandStatus status;
706 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
707 char nh[256], uh[256];
708 unsigned char idle[4], mode[4];
709 unsigned char *fingerprint;
710 SilcSocketConnection hsock;
712 /* Process only valid clients and ignore those that are not registered. */
714 for (i = 0; i < clients_count; i++) {
715 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
722 /* No valid clients found, send error reply */
724 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
725 SILC_STATUS_ERR_NO_SUCH_NICK,
726 3, nickname, strlen(nickname));
727 } else if (client_ids && client_ids[0]) {
728 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
729 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
730 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
731 2, idp->data, idp->len);
732 silc_buffer_free(idp);
737 /* Start processing found clients. */
739 status = SILC_STATUS_LIST_START;
741 status = SILC_STATUS_OK;
743 for (i = 0, k = 0; i < clients_count; i++) {
749 status = SILC_STATUS_LIST_ITEM;
750 if (valid_count > 1 && k == valid_count - 1)
751 status = SILC_STATUS_LIST_END;
752 if (count && k - 1 == count)
753 status = SILC_STATUS_LIST_END;
755 /* Send WHOIS reply */
756 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
757 tmp = silc_argument_get_first_arg(cmd->args, NULL);
759 memset(uh, 0, sizeof(uh));
760 memset(nh, 0, sizeof(nh));
761 memset(idle, 0, sizeof(idle));
763 strncat(nh, entry->nickname, strlen(entry->nickname));
764 if (!strchr(entry->nickname, '@')) {
766 if (entry->servername) {
767 strncat(nh, entry->servername, strlen(entry->servername));
769 len = entry->router ? strlen(entry->router->server_name) :
770 strlen(server->server_name);
771 strncat(nh, entry->router ? entry->router->server_name :
772 server->server_name, len);
776 strncat(uh, entry->username, strlen(entry->username));
777 if (!strchr(entry->username, '@')) {
779 hsock = (SilcSocketConnection)entry->connection;
780 len = strlen(hsock->hostname);
781 strncat(uh, hsock->hostname, len);
784 channels = silc_server_get_client_channel_list(server, entry);
786 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
787 fingerprint = entry->data.fingerprint;
791 SILC_PUT32_MSB(entry->mode, mode);
793 if (entry->connection) {
794 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
798 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
800 2, idp->data, idp->len,
804 strlen(entry->userinfo),
805 6, channels ? channels->data : NULL,
806 channels ? channels->len : 0,
810 fingerprint ? 20 : 0);
812 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
813 0, packet->data, packet->len, FALSE);
815 silc_buffer_free(packet);
816 silc_buffer_free(idp);
818 silc_buffer_free(channels);
825 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
827 SilcServer server = cmd->server;
829 SilcUInt16 old_ident;
831 old_ident = silc_command_get_ident(cmd->payload);
832 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
833 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
835 /* Send WHOIS command to our router */
836 silc_server_packet_send(server, (SilcSocketConnection)
837 server->router->connection,
838 SILC_PACKET_COMMAND, cmd->packet->flags,
839 tmpbuf->data, tmpbuf->len, TRUE);
841 /* Reprocess this packet after received reply from router */
842 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
843 silc_command_get_ident(cmd->payload),
844 silc_server_command_whois,
845 silc_server_command_dup(cmd));
847 silc_command_set_ident(cmd->payload, old_ident);
848 silc_buffer_free(tmpbuf);
852 silc_server_command_whois_process(SilcServerCommandContext cmd)
854 SilcServer server = cmd->server;
855 char *nick = NULL, *server_name = NULL;
857 SilcClientEntry *clients = NULL, entry;
858 SilcClientID **client_id = NULL;
859 SilcUInt32 client_id_count = 0, clients_count = 0;
861 bool check_global = FALSE;
863 /* Parse the whois request */
864 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
865 &nick, &server_name, &count,
869 /* Send the WHOIS request to the router only if it included nickname.
870 Since nicknames can be expanded into many clients we need to send it
871 to router. If the WHOIS included only client ID's we will check them
872 first locally since we just might have them. */
873 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
874 server->server_type == SILC_SERVER && !cmd->pending &&
875 !server->standalone) {
876 silc_server_command_whois_send_router(cmd);
881 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
883 else if (server->server_type != SILC_SERVER)
886 /* Get all clients matching that ID or nickname from local list */
887 if (client_id_count) {
888 /* Check all Client ID's received in the command packet */
889 for (i = 0; i < client_id_count; i++) {
890 entry = silc_idlist_find_client_by_id(server->local_list,
891 client_id[i], TRUE, NULL);
892 if (!entry && check_global)
893 entry = silc_idlist_find_client_by_id(server->global_list,
894 client_id[i], TRUE, NULL);
896 clients = silc_realloc(clients, sizeof(*clients) *
897 (clients_count + 1));
898 clients[clients_count++] = entry;
900 /* If we are normal server and did not send the request first to router
901 do it now, since we do not have the Client ID information. */
902 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
903 server->server_type == SILC_SERVER && !cmd->pending &&
904 !server->standalone) {
905 silc_server_command_whois_send_router(cmd);
912 /* Find by nickname */
913 if (!silc_idlist_get_clients_by_hash(server->local_list,
914 nick, server->md5hash,
915 &clients, &clients_count))
916 silc_idlist_get_clients_by_nickname(server->local_list,
918 &clients, &clients_count);
920 if (!silc_idlist_get_clients_by_hash(server->global_list,
921 nick, server->md5hash,
922 &clients, &clients_count))
923 silc_idlist_get_clients_by_nickname(server->global_list,
925 &clients, &clients_count);
930 /* If we are normal server and did not send the request first to router
931 do it now, since we do not have the information. */
932 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
933 server->server_type == SILC_SERVER && !cmd->pending &&
934 !server->standalone) {
935 silc_server_command_whois_send_router(cmd);
940 /* Such client(s) really does not exist in the SILC network. */
941 if (!client_id_count) {
942 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
943 SILC_STATUS_ERR_NO_SUCH_NICK,
944 3, nick, strlen(nick));
946 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
947 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
948 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
949 2, idp->data, idp->len);
950 silc_buffer_free(idp);
955 /* Router always finds the client entry if it exists in the SILC network.
956 However, it might be incomplete entry and does not include all the
957 mandatory fields that WHOIS command reply requires. Check for these and
958 make query from the server who owns the client if some fields are
960 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
965 /* Send the command reply */
966 silc_server_command_whois_send_reply(cmd, clients, clients_count,
967 count, nick, client_id);
970 if (client_id_count) {
971 for (i = 0; i < client_id_count; i++)
972 silc_free(client_id[i]);
973 silc_free(client_id);
977 silc_free(server_name);
982 /* Server side of command WHOIS. Processes user's query and sends found
983 results as command replies back to the client. */
985 SILC_SERVER_CMD_FUNC(whois)
987 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
990 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
992 ret = silc_server_command_whois_process(cmd);
993 silc_server_command_free(cmd);
996 /******************************************************************************
1000 ******************************************************************************/
1003 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1011 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1014 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1018 /* Get the nickname@server string and parse it. */
1019 silc_parse_userfqdn(tmp, nickname, server_name);
1021 /* Get the max count of reply messages allowed */
1022 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1032 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1033 SilcClientEntry *clients,
1034 SilcUInt32 clients_count)
1036 SilcServer server = cmd->server;
1038 SilcClientEntry entry;
1040 for (i = 0; i < clients_count; i++) {
1043 if (!entry->nickname || !entry->username) {
1045 SilcUInt16 old_ident;
1050 old_ident = silc_command_get_ident(cmd->payload);
1051 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1052 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1054 /* Send WHOWAS command */
1055 silc_server_packet_send(server, entry->router->connection,
1056 SILC_PACKET_COMMAND, cmd->packet->flags,
1057 tmpbuf->data, tmpbuf->len, TRUE);
1059 /* Reprocess this packet after received reply */
1060 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1061 silc_command_get_ident(cmd->payload),
1062 silc_server_command_whowas,
1063 silc_server_command_dup(cmd));
1064 cmd->pending = TRUE;
1065 silc_command_set_ident(cmd->payload, old_ident);
1067 silc_buffer_free(tmpbuf);
1076 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1077 SilcClientEntry *clients,
1078 SilcUInt32 clients_count)
1080 SilcServer server = cmd->server;
1082 int i, k, count = 0, len;
1083 SilcBuffer packet, idp;
1084 SilcClientEntry entry = NULL;
1085 SilcCommandStatus status;
1086 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1087 char nh[256], uh[256];
1090 status = SILC_STATUS_OK;
1092 /* Process only entries that are not registered anymore. */
1094 for (i = 0; i < clients_count; i++) {
1095 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1102 /* No valid entries found at all, just send error */
1105 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1107 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1108 SILC_STATUS_ERR_NO_SUCH_NICK,
1109 3, tmp, strlen(tmp));
1113 if (valid_count > 1)
1114 status = SILC_STATUS_LIST_START;
1116 for (i = 0, k = 0; i < clients_count; i++) {
1122 status = SILC_STATUS_LIST_ITEM;
1123 if (valid_count > 1 && k == valid_count - 1)
1124 status = SILC_STATUS_LIST_END;
1125 if (count && k - 1 == count)
1126 status = SILC_STATUS_LIST_END;
1127 if (count && k - 1 > count)
1130 /* Send WHOWAS reply */
1131 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1132 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1133 memset(uh, 0, sizeof(uh));
1134 memset(nh, 0, sizeof(nh));
1136 strncat(nh, entry->nickname, strlen(entry->nickname));
1137 if (!strchr(entry->nickname, '@')) {
1138 strncat(nh, "@", 1);
1139 if (entry->servername) {
1140 strncat(nh, entry->servername, strlen(entry->servername));
1142 len = entry->router ? strlen(entry->router->server_name) :
1143 strlen(server->server_name);
1144 strncat(nh, entry->router ? entry->router->server_name :
1145 server->server_name, len);
1149 strncat(uh, entry->username, strlen(entry->username));
1150 if (!strchr(entry->username, '@')) {
1151 strncat(uh, "@", 1);
1152 strcat(uh, "*private*");
1156 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1157 status, 0, ident, 4,
1158 2, idp->data, idp->len,
1163 strlen(entry->userinfo) : 0);
1164 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1165 0, packet->data, packet->len, FALSE);
1167 silc_buffer_free(packet);
1168 silc_buffer_free(idp);
1175 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1177 SilcServer server = cmd->server;
1178 char *nick = NULL, *server_name = NULL;
1180 SilcClientEntry *clients = NULL;
1181 SilcUInt32 clients_count = 0;
1183 bool check_global = FALSE;
1185 /* Protocol dictates that we must always send the received WHOWAS request
1186 to our router if we are normal server, so let's do it now unless we
1187 are standalone. We will not send any replies to the client until we
1188 have received reply from the router. */
1189 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1190 server->server_type == SILC_SERVER && !cmd->pending &&
1191 !server->standalone) {
1193 SilcUInt16 old_ident;
1195 old_ident = silc_command_get_ident(cmd->payload);
1196 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1197 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1199 /* Send WHOWAS command to our router */
1200 silc_server_packet_send(server, (SilcSocketConnection)
1201 server->router->connection,
1202 SILC_PACKET_COMMAND, cmd->packet->flags,
1203 tmpbuf->data, tmpbuf->len, TRUE);
1205 /* Reprocess this packet after received reply from router */
1206 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1207 silc_command_get_ident(cmd->payload),
1208 silc_server_command_whowas,
1209 silc_server_command_dup(cmd));
1210 cmd->pending = TRUE;
1211 silc_command_set_ident(cmd->payload, old_ident);
1213 silc_buffer_free(tmpbuf);
1218 /* We are ready to process the command request. Let's search for the
1219 requested client and send reply to the requesting client. */
1221 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1222 check_global = TRUE;
1223 else if (server->server_type != SILC_SERVER)
1224 check_global = TRUE;
1226 /* Parse the whowas request */
1227 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1230 /* Get all clients matching that nickname from local list */
1231 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1233 &clients, &clients_count))
1234 silc_idlist_get_clients_by_hash(server->local_list,
1235 nick, server->md5hash,
1236 &clients, &clients_count);
1238 /* Check global list as well */
1240 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1242 &clients, &clients_count))
1243 silc_idlist_get_clients_by_hash(server->global_list,
1244 nick, server->md5hash,
1245 &clients, &clients_count);
1249 /* Such a client really does not exist in the SILC network. */
1250 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1251 SILC_STATUS_ERR_NO_SUCH_NICK,
1252 3, nick, strlen(nick));
1256 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1261 /* Send the command reply to the client */
1262 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1267 silc_free(server_name);
1271 /* Server side of command WHOWAS. */
1273 SILC_SERVER_CMD_FUNC(whowas)
1275 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1278 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1280 ret = silc_server_command_whowas_process(cmd);
1281 silc_server_command_free(cmd);
1284 /******************************************************************************
1288 ******************************************************************************/
1291 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1293 SilcServer server = cmd->server;
1295 SilcUInt16 old_ident;
1297 old_ident = silc_command_get_ident(cmd->payload);
1298 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1299 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1301 /* Send IDENTIFY command to our router */
1302 silc_server_packet_send(server, (SilcSocketConnection)
1303 server->router->connection,
1304 SILC_PACKET_COMMAND, cmd->packet->flags,
1305 tmpbuf->data, tmpbuf->len, TRUE);
1307 /* Reprocess this packet after received reply from router */
1308 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1309 silc_command_get_ident(cmd->payload),
1310 silc_server_command_identify,
1311 silc_server_command_dup(cmd));
1312 cmd->pending = TRUE;
1313 silc_command_set_ident(cmd->payload, old_ident);
1314 silc_buffer_free(tmpbuf);
1318 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1319 SilcClientEntry **clients,
1320 SilcUInt32 *clients_count,
1321 SilcServerEntry **servers,
1322 SilcUInt32 *servers_count,
1323 SilcChannelEntry **channels,
1324 SilcUInt32 *channels_count,
1327 SilcServer server = cmd->server;
1330 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1332 bool check_global = FALSE;
1337 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1338 check_global = TRUE;
1339 else if (server->server_type != SILC_SERVER)
1340 check_global = TRUE;
1342 /* If ID Payload is in the command it must be used instead of names */
1343 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1345 /* No ID, get the names. */
1347 /* If we are normal server and have not resolved information from
1348 router yet, do so now. */
1349 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1350 server->server_type == SILC_SERVER && !cmd->pending &&
1351 !server->standalone) {
1352 silc_server_command_identify_send_router(cmd);
1356 /* Try to get nickname@server. */
1357 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1360 char *nick_server = NULL;
1362 silc_parse_userfqdn(tmp, &nick, &nick_server);
1364 if (!silc_idlist_get_clients_by_hash(server->local_list,
1365 nick, server->md5hash,
1366 clients, clients_count))
1367 silc_idlist_get_clients_by_nickname(server->local_list,
1369 clients, clients_count);
1371 if (!silc_idlist_get_clients_by_hash(server->global_list,
1372 nick, server->md5hash,
1373 clients, clients_count))
1374 silc_idlist_get_clients_by_nickname(server->global_list,
1376 clients, clients_count);
1380 silc_free(nick_server);
1383 /* the nickname does not exist, send error reply */
1384 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1385 SILC_STATUS_ERR_NO_SUCH_NICK,
1386 3, tmp, strlen(tmp));
1391 /* Try to get server name */
1392 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1394 entry = silc_idlist_find_server_by_name(server->local_list,
1396 if (!entry && check_global)
1397 entry = silc_idlist_find_server_by_name(server->global_list,
1400 *servers = silc_realloc(*servers, sizeof(**servers) *
1401 (*servers_count + 1));
1402 (*servers)[(*servers_count)++] = entry;
1406 /* the server does not exist, send error reply */
1407 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1408 SILC_STATUS_ERR_NO_SUCH_SERVER,
1409 3, tmp, strlen(tmp));
1414 /* Try to get channel name */
1415 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1417 entry = silc_idlist_find_channel_by_name(server->local_list,
1419 if (!entry && check_global)
1420 entry = silc_idlist_find_channel_by_name(server->global_list,
1423 *channels = silc_realloc(*channels, sizeof(**channels) *
1424 (*channels_count + 1));
1425 (*channels)[(*channels_count)++] = entry;
1429 /* The channel does not exist, send error reply */
1430 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1431 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1432 3, tmp, strlen(tmp));
1437 if (!(*clients) && !(*servers) && !(*channels)) {
1438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1439 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1443 /* Command includes ID, we must use that. Also check whether the command
1444 has more than one ID set - take them all. */
1446 /* Take all ID's from the command packet */
1447 for (i = 0; i < argc; i++) {
1450 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1454 idp = silc_id_payload_parse(tmp, len);
1456 silc_free(*clients);
1457 silc_free(*servers);
1458 silc_free(*channels);
1459 silc_server_command_send_status_reply(
1460 cmd, SILC_COMMAND_IDENTIFY,
1461 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1465 id = silc_id_payload_get_id(idp);
1467 switch (silc_id_payload_get_type(idp)) {
1469 case SILC_ID_CLIENT:
1470 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1472 if (!entry && check_global)
1473 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1476 *clients = silc_realloc(*clients, sizeof(**clients) *
1477 (*clients_count + 1));
1478 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1480 /* If we are normal server and have not resolved information from
1481 router yet, do so now. */
1482 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1483 server->server_type == SILC_SERVER && !cmd->pending &&
1484 !server->standalone) {
1485 silc_server_command_identify_send_router(cmd);
1486 silc_free(*clients);
1487 silc_free(*servers);
1488 silc_free(*channels);
1491 silc_server_command_send_status_data(
1492 cmd, SILC_COMMAND_IDENTIFY,
1493 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1501 case SILC_ID_SERVER:
1502 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1504 if (!entry && check_global)
1505 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1508 *servers = silc_realloc(*servers, sizeof(**servers) *
1509 (*servers_count + 1));
1510 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1512 /* If we are normal server and have not resolved information from
1513 router yet, do so now. */
1514 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1515 server->server_type == SILC_SERVER && !cmd->pending &&
1516 !server->standalone) {
1517 silc_server_command_identify_send_router(cmd);
1518 silc_free(*clients);
1519 silc_free(*servers);
1520 silc_free(*channels);
1523 silc_server_command_send_status_data(
1524 cmd, SILC_COMMAND_IDENTIFY,
1525 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1532 case SILC_ID_CHANNEL:
1533 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1535 if (!entry && check_global)
1536 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1539 *channels = silc_realloc(*channels, sizeof(**channels) *
1540 (*channels_count + 1));
1541 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1543 /* If we are normal server and have not resolved information from
1544 router yet, do so now. */
1545 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1546 server->server_type == SILC_SERVER && !cmd->pending &&
1547 !server->standalone) {
1548 silc_server_command_identify_send_router(cmd);
1549 silc_free(*clients);
1550 silc_free(*servers);
1551 silc_free(*channels);
1554 silc_server_command_send_status_data(
1555 cmd, SILC_COMMAND_IDENTIFY,
1556 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1569 silc_free(*clients);
1570 silc_free(*servers);
1571 silc_free(*channels);
1575 /* Get the max count of reply messages allowed */
1576 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1585 /* Checks that all mandatory fields in client entry are present. If not
1586 then send WHOIS request to the server who owns the client. We use
1587 WHOIS because we want to get as much information as possible at once. */
1590 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1591 SilcClientEntry *clients,
1592 SilcUInt32 clients_count)
1594 SilcServer server = cmd->server;
1595 SilcClientEntry entry;
1596 SilcServerResolveContext resolve = NULL, r = NULL;
1597 SilcUInt32 resolve_count = 0;
1601 for (i = 0; i < clients_count; i++) {
1606 if (entry->nickname ||
1607 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1611 /* If we are normal server, and we've not resolved this client from
1612 router and it is global client, we'll check whether it is on some
1613 channel. If not then we cannot be sure about its validity, and
1614 we'll resolve it from router. */
1615 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1616 entry->connection || silc_hash_table_count(entry->channels))
1620 /* We need to resolve this entry since it is not complete */
1622 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1623 /* The entry is being resolved (and we are not the resolver) so attach
1624 to the command reply and we're done with this one. */
1625 silc_server_command_pending(server, SILC_COMMAND_NONE,
1626 entry->resolve_cmd_ident,
1627 silc_server_command_identify,
1628 silc_server_command_dup(cmd));
1631 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1632 /* We've resolved this and it still is not ready. We'll return
1633 and are that this will be handled again after it is resolved. */
1634 for (i = 0; i < resolve_count; i++) {
1635 for (k = 0; k < r->res_argc; k++)
1636 silc_free(r->res_argv[k]);
1637 silc_free(r->res_argv);
1638 silc_free(r->res_argv_lens);
1639 silc_free(r->res_argv_types);
1644 /* We'll resolve this client */
1648 for (k = 0; k < resolve_count; k++) {
1649 if (resolve[k].router == entry->router) {
1656 resolve = silc_realloc(resolve, sizeof(*resolve) *
1657 (resolve_count + 1));
1658 r = &resolve[resolve_count];
1659 memset(r, 0, sizeof(*r));
1660 r->router = entry->router;
1661 r->ident = ++server->cmd_ident;
1665 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1667 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1668 sizeof(*r->res_argv_lens) *
1670 r->res_argv_types = silc_realloc(r->res_argv_types,
1671 sizeof(*r->res_argv_types) *
1673 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1674 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1675 sizeof(**r->res_argv));
1676 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1677 r->res_argv_lens[r->res_argc] = idp->len;
1678 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1680 silc_buffer_free(idp);
1682 entry->resolve_cmd_ident = r->ident;
1683 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1684 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1689 /* Do the resolving */
1690 for (i = 0; i < resolve_count; i++) {
1695 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1696 now anyway so make it a good one. */
1697 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1698 r->res_argc, r->res_argv,
1702 silc_server_packet_send(server, r->router->connection,
1703 SILC_PACKET_COMMAND, cmd->packet->flags,
1704 res_cmd->data, res_cmd->len, FALSE);
1706 /* Reprocess this packet after received reply */
1707 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1709 silc_server_command_identify,
1710 silc_server_command_dup(cmd));
1711 cmd->pending = TRUE;
1713 silc_buffer_free(res_cmd);
1714 for (k = 0; k < r->res_argc; k++)
1715 silc_free(r->res_argv[k]);
1716 silc_free(r->res_argv);
1717 silc_free(r->res_argv_lens);
1718 silc_free(r->res_argv_types);
1727 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1728 SilcClientEntry *clients,
1729 SilcUInt32 clients_count,
1730 SilcServerEntry *servers,
1731 SilcUInt32 servers_count,
1732 SilcChannelEntry *channels,
1733 SilcUInt32 channels_count,
1736 SilcServer server = cmd->server;
1737 int i, k, len, valid_count;
1738 SilcBuffer packet, idp;
1739 SilcCommandStatus status;
1740 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1741 char nh[256], uh[256];
1742 SilcSocketConnection hsock;
1744 status = SILC_STATUS_OK;
1747 SilcClientEntry entry;
1749 /* Process only valid entries. */
1751 for (i = 0; i < clients_count; i++) {
1752 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1759 /* No valid entries found at all, just send error */
1762 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1764 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1765 SILC_STATUS_ERR_NO_SUCH_NICK,
1766 3, tmp, strlen(tmp));
1768 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1769 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1770 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1776 /* Process all valid client entries and send command replies */
1778 if (valid_count > 1)
1779 status = SILC_STATUS_LIST_START;
1781 for (i = 0, k = 0; i < clients_count; i++) {
1787 status = SILC_STATUS_LIST_ITEM;
1788 if (valid_count > 1 && k == valid_count - 1
1789 && !servers_count && !channels_count)
1790 status = SILC_STATUS_LIST_END;
1791 if (count && k - 1 == count)
1792 status = SILC_STATUS_LIST_END;
1793 if (count && k - 1 > count)
1796 /* Send IDENTIFY reply */
1798 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1799 memset(uh, 0, sizeof(uh));
1800 memset(nh, 0, sizeof(nh));
1801 strncat(nh, entry->nickname, strlen(entry->nickname));
1802 if (!strchr(entry->nickname, '@')) {
1803 strncat(nh, "@", 1);
1804 if (entry->servername) {
1805 strncat(nh, entry->servername, strlen(entry->servername));
1807 len = entry->router ? strlen(entry->router->server_name) :
1808 strlen(server->server_name);
1809 strncat(nh, entry->router ? entry->router->server_name :
1810 server->server_name, len);
1814 if (!entry->username) {
1815 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1816 status, 0, ident, 2,
1817 2, idp->data, idp->len,
1820 strncat(uh, entry->username, strlen(entry->username));
1821 if (!strchr(entry->username, '@')) {
1822 strncat(uh, "@", 1);
1823 hsock = (SilcSocketConnection)entry->connection;
1824 len = strlen(hsock->hostname);
1825 strncat(uh, hsock->hostname, len);
1828 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1829 status, 0, ident, 3,
1830 2, idp->data, idp->len,
1835 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1836 0, packet->data, packet->len, FALSE);
1838 silc_buffer_free(packet);
1839 silc_buffer_free(idp);
1846 SilcServerEntry entry;
1848 if (status == SILC_STATUS_OK && servers_count > 1)
1849 status = SILC_STATUS_LIST_START;
1851 for (i = 0, k = 0; i < servers_count; i++) {
1855 status = SILC_STATUS_LIST_ITEM;
1856 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1857 status = SILC_STATUS_LIST_END;
1858 if (count && k - 1 == count)
1859 status = SILC_STATUS_LIST_END;
1860 if (count && k - 1 > count)
1863 /* Send IDENTIFY reply */
1864 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1866 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1867 status, 0, ident, 2,
1868 2, idp->data, idp->len,
1869 3, entry->server_name,
1870 entry->server_name ?
1871 strlen(entry->server_name) : 0);
1872 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1873 0, packet->data, packet->len, FALSE);
1875 silc_buffer_free(packet);
1876 silc_buffer_free(idp);
1883 SilcChannelEntry entry;
1885 if (status == SILC_STATUS_OK && channels_count > 1)
1886 status = SILC_STATUS_LIST_START;
1888 for (i = 0, k = 0; i < channels_count; i++) {
1889 entry = channels[i];
1892 status = SILC_STATUS_LIST_ITEM;
1893 if (channels_count > 1 && k == channels_count - 1)
1894 status = SILC_STATUS_LIST_END;
1895 if (count && k - 1 == count)
1896 status = SILC_STATUS_LIST_END;
1897 if (count && k - 1 > count)
1900 /* Send IDENTIFY reply */
1901 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1903 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1904 status, 0, ident, 2,
1905 2, idp->data, idp->len,
1906 3, entry->channel_name,
1907 entry->channel_name ?
1908 strlen(entry->channel_name): 0);
1909 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1910 0, packet->data, packet->len, FALSE);
1912 silc_buffer_free(packet);
1913 silc_buffer_free(idp);
1921 silc_server_command_identify_process(SilcServerCommandContext cmd)
1923 SilcUInt32 count = 0;
1925 SilcClientEntry *clients = NULL;
1926 SilcServerEntry *servers = NULL;
1927 SilcChannelEntry *channels = NULL;
1928 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1930 /* Parse the IDENTIFY request */
1931 ret = silc_server_command_identify_parse(cmd,
1932 &clients, &clients_count,
1933 &servers, &servers_count,
1934 &channels, &channels_count,
1940 /* Check that all mandatory fields are present and request those data
1941 from the server who owns the client if necessary. */
1942 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1948 /* Send the command reply to the client */
1949 silc_server_command_identify_send_reply(cmd,
1950 clients, clients_count,
1951 servers, servers_count,
1952 channels, channels_count,
1958 silc_free(channels);
1962 SILC_SERVER_CMD_FUNC(identify)
1964 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1967 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1969 ret = silc_server_command_identify_process(cmd);
1970 silc_server_command_free(cmd);
1973 /* Server side of command NICK. Sets nickname for user. Setting
1974 nickname causes generation of a new client ID for the client. The
1975 new client ID is sent to the client after changing the nickname. */
1977 SILC_SERVER_CMD_FUNC(nick)
1979 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1980 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1981 SilcServer server = cmd->server;
1982 SilcBuffer packet, nidp, oidp = NULL;
1983 SilcClientID *new_id;
1984 SilcUInt32 nick_len;
1986 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1989 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1992 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1994 /* Check nickname */
1995 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
1998 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
1999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2000 SILC_STATUS_ERR_BAD_NICKNAME);
2004 /* Check for same nickname */
2005 if (!strcmp(client->nickname, nick)) {
2006 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2010 /* Create new Client ID */
2011 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2013 cmd->server->md5hash, nick,
2016 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2019 /* Send notify about nickname change to our router. We send the new
2020 ID and ask to replace it with the old one. If we are router the
2021 packet is broadcasted. Send NICK_CHANGE notify. */
2022 if (!server->standalone)
2023 silc_server_send_notify_nick_change(server, server->router->connection,
2024 server->server_type == SILC_SERVER ?
2025 FALSE : TRUE, client->id,
2028 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2030 /* Remove old cache entry */
2031 silc_idcache_del_by_context(server->local_list->clients, client);
2034 silc_free(client->id);
2036 /* Save the nickname as this client is our local client */
2037 silc_free(client->nickname);
2039 client->nickname = strdup(nick);
2040 client->id = new_id;
2042 /* Update client cache */
2043 silc_idcache_add(server->local_list->clients, client->nickname,
2044 client->id, (void *)client, 0, NULL);
2046 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2048 /* Send NICK_CHANGE notify to the client's channels */
2049 silc_server_send_notify_on_channels(server, NULL, client,
2050 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2051 oidp->data, oidp->len,
2052 nidp->data, nidp->len,
2054 strlen(client->nickname));
2057 /* Send the new Client ID as reply command back to client */
2058 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2059 SILC_STATUS_OK, 0, ident, 1,
2060 2, nidp->data, nidp->len);
2061 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2062 0, packet->data, packet->len, FALSE);
2064 silc_buffer_free(packet);
2065 silc_buffer_free(nidp);
2067 silc_buffer_free(oidp);
2070 silc_server_command_free(cmd);
2073 /* Sends the LIST command reply */
2076 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2077 SilcChannelEntry *lch,
2078 SilcUInt32 lch_count,
2079 SilcChannelEntry *gch,
2080 SilcUInt32 gch_count)
2083 SilcBuffer packet, idp;
2084 SilcChannelEntry entry;
2085 SilcCommandStatus status;
2086 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2088 unsigned char usercount[4];
2090 int valid_lcount = 0, valid_rcount = 0;
2092 for (i = 0; i < lch_count; i++) {
2093 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2098 for (i = 0; i < gch_count; i++) {
2099 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2105 status = SILC_STATUS_OK;
2106 if ((lch_count + gch_count) > 1)
2107 status = SILC_STATUS_LIST_START;
2110 for (i = 0, k = 0; i < lch_count; i++) {
2116 status = SILC_STATUS_LIST_ITEM;
2117 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2118 status = SILC_STATUS_LIST_END;
2120 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2122 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2123 topic = "*private*";
2124 memset(usercount, 0, sizeof(usercount));
2126 topic = entry->topic;
2127 users = silc_hash_table_count(entry->user_list);
2128 SILC_PUT32_MSB(users, usercount);
2131 /* Send the reply */
2133 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2134 status, 0, ident, 4,
2135 2, idp->data, idp->len,
2136 3, entry->channel_name,
2137 strlen(entry->channel_name),
2138 4, topic, topic ? strlen(topic) : 0,
2140 silc_server_packet_send(cmd->server, cmd->sock,
2141 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2142 packet->len, FALSE);
2143 silc_buffer_free(packet);
2144 silc_buffer_free(idp);
2149 for (i = 0, k = 0; i < gch_count; i++) {
2155 status = SILC_STATUS_LIST_ITEM;
2156 if (valid_rcount > 1 && k == valid_rcount - 1)
2157 status = SILC_STATUS_LIST_END;
2159 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2161 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2162 topic = "*private*";
2163 memset(usercount, 0, sizeof(usercount));
2165 topic = entry->topic;
2166 users = entry->user_count;
2167 SILC_PUT32_MSB(users, usercount);
2170 /* Send the reply */
2172 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2173 status, 0, ident, 4,
2174 2, idp->data, idp->len,
2175 3, entry->channel_name,
2176 strlen(entry->channel_name),
2177 4, topic, topic ? strlen(topic) : 0,
2179 silc_server_packet_send(cmd->server, cmd->sock,
2180 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2181 packet->len, FALSE);
2182 silc_buffer_free(packet);
2183 silc_buffer_free(idp);
2188 /* Server side of LIST command. This lists the channel of the requested
2189 server. Secret channels are not listed. */
2191 SILC_SERVER_CMD_FUNC(list)
2193 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2194 SilcServer server = cmd->server;
2195 SilcChannelID *channel_id = NULL;
2198 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2199 SilcUInt32 lch_count = 0, gch_count = 0;
2201 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2203 /* If we are normal server, send the command to router, since we
2204 want to know all channels in the network. */
2205 if (!cmd->pending && server->server_type == SILC_SERVER &&
2206 !server->standalone) {
2208 SilcUInt16 old_ident;
2210 old_ident = silc_command_get_ident(cmd->payload);
2211 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2212 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2213 silc_server_packet_send(server, server->router->connection,
2214 SILC_PACKET_COMMAND, cmd->packet->flags,
2215 tmpbuf->data, tmpbuf->len, TRUE);
2217 /* Reprocess this packet after received reply from router */
2218 silc_server_command_pending(server, SILC_COMMAND_LIST,
2219 silc_command_get_ident(cmd->payload),
2220 silc_server_command_list,
2221 silc_server_command_dup(cmd));
2222 cmd->pending = TRUE;
2223 silc_command_set_ident(cmd->payload, old_ident);
2224 silc_buffer_free(tmpbuf);
2228 /* Get Channel ID */
2229 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2231 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2234 SILC_STATUS_ERR_NO_CHANNEL_ID);
2239 /* Get the channels from local list */
2240 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2243 /* Get the channels from global list */
2244 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2247 /* Send the reply */
2248 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2249 gchannels, gch_count);
2251 silc_free(lchannels);
2252 silc_free(gchannels);
2255 silc_server_command_free(cmd);
2258 /* Server side of TOPIC command. Sets topic for channel and/or returns
2259 current topic to client. */
2261 SILC_SERVER_CMD_FUNC(topic)
2263 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2264 SilcServer server = cmd->server;
2265 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2266 SilcChannelID *channel_id;
2267 SilcChannelEntry channel;
2268 SilcChannelClientEntry chl;
2269 SilcBuffer packet, idp;
2271 SilcUInt32 argc, tmp_len;
2272 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2274 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2276 argc = silc_argument_get_arg_num(cmd->args);
2278 /* Get Channel ID */
2279 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2282 SILC_STATUS_ERR_NO_CHANNEL_ID);
2285 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2288 SILC_STATUS_ERR_NO_CHANNEL_ID);
2292 /* Check whether the channel exists */
2293 channel = silc_idlist_find_channel_by_id(server->local_list,
2296 channel = silc_idlist_find_channel_by_id(server->global_list,
2299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2300 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2307 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2310 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2314 if (strlen(tmp) > 256) {
2315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2316 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2320 /* See whether the client is on channel and has rights to change topic */
2321 if (!silc_server_client_on_channel(client, channel, &chl)) {
2322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2323 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2327 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2328 channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2330 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2334 /* Set the topic for channel */
2335 silc_free(channel->topic);
2336 channel->topic = strdup(tmp);
2338 /* Send TOPIC_SET notify type to the network */
2339 if (!server->standalone)
2340 silc_server_send_notify_topic_set(server, server->router->connection,
2341 server->server_type == SILC_ROUTER ?
2342 TRUE : FALSE, channel,
2343 client->id, SILC_ID_CLIENT,
2346 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2348 /* Send notify about topic change to all clients on the channel */
2349 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2350 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2351 idp->data, idp->len,
2352 channel->topic, strlen(channel->topic));
2353 silc_buffer_free(idp);
2356 /* Send the topic to client as reply packet */
2357 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2358 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2359 SILC_STATUS_OK, 0, ident, 2,
2360 2, idp->data, idp->len,
2363 strlen(channel->topic) : 0);
2364 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2365 0, packet->data, packet->len, FALSE);
2367 silc_buffer_free(packet);
2368 silc_buffer_free(idp);
2369 silc_free(channel_id);
2372 silc_server_command_free(cmd);
2375 /* Server side of INVITE command. Invites some client to join some channel.
2376 This command is also used to manage the invite list of the channel. */
2378 SILC_SERVER_CMD_FUNC(invite)
2380 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2381 SilcServer server = cmd->server;
2382 SilcSocketConnection sock = cmd->sock, dest_sock;
2383 SilcChannelClientEntry chl;
2384 SilcClientEntry sender, dest;
2385 SilcClientID *dest_id = NULL;
2386 SilcChannelEntry channel;
2387 SilcChannelID *channel_id = NULL;
2388 SilcIDListData idata;
2389 SilcBuffer idp, idp2, packet;
2390 unsigned char *tmp, *add, *del;
2392 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2394 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2396 /* Get Channel ID */
2397 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2400 SILC_STATUS_ERR_NO_CHANNEL_ID);
2403 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406 SILC_STATUS_ERR_NO_CHANNEL_ID);
2410 /* Get the channel entry */
2411 channel = silc_idlist_find_channel_by_id(server->local_list,
2414 channel = silc_idlist_find_channel_by_id(server->global_list,
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2418 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2423 /* Check whether the sender of this command is on the channel. */
2424 sender = (SilcClientEntry)sock->user_data;
2425 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2427 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2431 /* Check whether the channel is invite-only channel. If yes then the
2432 sender of this command must be at least channel operator. */
2433 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2434 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2436 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2440 /* Get destination client ID */
2441 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2446 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2449 SILC_STATUS_ERR_NO_CLIENT_ID);
2453 /* Get the client entry */
2454 dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2456 if (server->server_type != SILC_SERVER || !resolve) {
2457 silc_server_command_send_status_reply(
2458 cmd, SILC_COMMAND_INVITE,
2459 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2463 /* The client info is being resolved. Reprocess this packet after
2464 receiving the reply to the query. */
2465 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2467 silc_server_command_invite,
2468 silc_server_command_dup(cmd));
2469 cmd->pending = TRUE;
2470 silc_free(channel_id);
2475 /* Check whether the requested client is already on the channel. */
2476 if (silc_server_client_on_channel(dest, channel, NULL)) {
2477 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2478 SILC_STATUS_ERR_USER_ON_CHANNEL);
2482 /* Get route to the client */
2483 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2486 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2490 memset(invite, 0, sizeof(invite));
2491 strncat(invite, dest->nickname, strlen(dest->nickname));
2492 strncat(invite, "!", 1);
2493 strncat(invite, dest->username, strlen(dest->username));
2494 if (!strchr(dest->username, '@')) {
2495 strncat(invite, "@", 1);
2496 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2499 len = strlen(invite);
2500 if (!channel->invite_list)
2501 channel->invite_list = silc_calloc(len + 2,
2502 sizeof(*channel->invite_list));
2504 channel->invite_list = silc_realloc(channel->invite_list,
2505 sizeof(*channel->invite_list) *
2507 strlen(channel->invite_list) + 2));
2508 strncat(channel->invite_list, invite, len);
2509 strncat(channel->invite_list, ",", 1);
2511 /* Send notify to the client that is invited to the channel */
2512 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2513 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2514 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2516 SILC_NOTIFY_TYPE_INVITE, 3,
2517 idp->data, idp->len,
2518 channel->channel_name,
2519 strlen(channel->channel_name),
2520 idp2->data, idp2->len);
2521 silc_buffer_free(idp);
2522 silc_buffer_free(idp2);
2525 /* Add the client to the invite list of the channel */
2526 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2528 if (!channel->invite_list)
2529 channel->invite_list = silc_calloc(len + 2,
2530 sizeof(*channel->invite_list));
2532 channel->invite_list = silc_realloc(channel->invite_list,
2533 sizeof(*channel->invite_list) *
2535 strlen(channel->invite_list) + 2));
2536 if (add[len - 1] == ',')
2537 add[len - 1] = '\0';
2539 strncat(channel->invite_list, add, len);
2540 strncat(channel->invite_list, ",", 1);
2543 /* Get the invite to be removed and remove it from the list */
2544 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2545 if (del && channel->invite_list) {
2546 char *start, *end, *n;
2548 if (!strncmp(channel->invite_list, del,
2549 strlen(channel->invite_list) - 1)) {
2550 silc_free(channel->invite_list);
2551 channel->invite_list = NULL;
2553 start = strstr(channel->invite_list, del);
2554 if (start && strlen(start) >= len) {
2556 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2557 strncat(n, channel->invite_list, start - channel->invite_list);
2558 strncat(n, end + 1, ((channel->invite_list +
2559 strlen(channel->invite_list)) - end) - 1);
2560 silc_free(channel->invite_list);
2561 channel->invite_list = n;
2566 /* Send notify to the primary router */
2567 if (!server->standalone)
2568 silc_server_send_notify_invite(server, server->router->connection,
2569 server->server_type == SILC_ROUTER ?
2570 TRUE : FALSE, channel,
2571 sender->id, add, del);
2573 /* Send command reply */
2574 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2578 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2579 SILC_STATUS_OK, 0, ident, 2,
2581 3, channel->invite_list,
2582 channel->invite_list ?
2583 strlen(channel->invite_list) : 0);
2586 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2587 SILC_STATUS_OK, 0, ident, 1,
2589 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2590 packet->data, packet->len, FALSE);
2591 silc_buffer_free(packet);
2595 silc_free(channel_id);
2596 silc_server_command_free(cmd);
2601 SilcSocketConnection sock;
2605 /* Quits connection to client. This gets called if client won't
2606 close the connection even when it has issued QUIT command. */
2608 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2610 QuitInternal q = (QuitInternal)context;
2612 /* Free all client specific data, such as client entry and entires
2613 on channels this client may be on. */
2614 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2616 q->sock->user_data = NULL;
2618 /* Close the connection on our side */
2619 silc_server_close_connection(q->server, q->sock);
2621 silc_free(q->signoff);
2625 /* Quits SILC session. This is the normal way to disconnect client. */
2627 SILC_SERVER_CMD_FUNC(quit)
2629 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2630 SilcServer server = cmd->server;
2631 SilcSocketConnection sock = cmd->sock;
2633 unsigned char *tmp = NULL;
2636 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2638 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2641 /* Get destination ID */
2642 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2646 q = silc_calloc(1, sizeof(*q));
2649 q->signoff = tmp ? strdup(tmp) : NULL;
2651 /* We quit the connection with little timeout */
2652 silc_schedule_task_add(server->schedule, sock->sock,
2653 silc_server_command_quit_cb, (void *)q,
2654 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2657 silc_server_command_free(cmd);
2660 /* Server side of command KILL. This command is used by router operator
2661 to remove an client from the SILC Network temporarily. */
2663 SILC_SERVER_CMD_FUNC(kill)
2665 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2666 SilcServer server = cmd->server;
2667 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2668 SilcClientEntry remote_client;
2669 SilcClientID *client_id;
2670 unsigned char *tmp, *comment;
2671 SilcUInt32 tmp_len, tmp_len2;
2675 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2677 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2680 /* KILL command works only on router */
2681 if (server->server_type != SILC_ROUTER) {
2682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2683 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2687 /* Check whether client has the permissions. */
2688 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2690 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2694 /* Get the client ID */
2695 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2698 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2701 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2704 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2708 /* Get the client entry */
2709 remote_client = silc_idlist_find_client_by_id(server->local_list,
2710 client_id, TRUE, NULL);
2712 if (!remote_client) {
2713 remote_client = silc_idlist_find_client_by_id(server->global_list,
2714 client_id, TRUE, NULL);
2716 if (!remote_client) {
2717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2718 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2724 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2728 /* Send reply to the sender */
2729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2732 /* Send the KILL notify packets. First send it to the channel, then
2733 to our primary router and then directly to the client who is being
2734 killed right now. */
2736 /* Send KILLED notify to the channels. It is not sent to the client
2737 as it will be sent differently destined directly to the client and not
2739 killer = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2740 silc_server_send_notify_on_channels(server, remote_client,
2741 remote_client, SILC_NOTIFY_TYPE_KILLED,
2743 comment, comment ? tmp_len2 : 0,
2744 killer->data, killer->len);
2745 silc_buffer_free(killer);
2747 /* Send KILLED notify to primary route */
2748 if (!server->standalone)
2749 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2750 remote_client->id, comment, client->id);
2752 /* Send KILLED notify to the client directly */
2753 silc_server_send_notify_killed(server, remote_client->connection ?
2754 remote_client->connection :
2755 remote_client->router->connection, FALSE,
2756 remote_client->id, comment, client->id);
2758 /* Remove the client from all channels. This generates new keys to the
2759 channels as well. */
2760 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2763 /* Remove the client entry, If it is locally connected then we will also
2764 disconnect the client here */
2765 if (remote_client->connection) {
2766 /* Remove locally conneted client */
2767 SilcSocketConnection sock = remote_client->connection;
2768 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2769 silc_server_close_connection(server, sock);
2771 /* Update statistics */
2772 if (remote_client->connection)
2773 server->stat.my_clients--;
2774 if (server->stat.cell_clients)
2775 server->stat.cell_clients--;
2776 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2777 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2779 /* Remove remote client */
2780 silc_idlist_del_client(local ? server->local_list :
2781 server->global_list, remote_client);
2785 silc_server_command_free(cmd);
2788 /* Server side of command INFO. This sends information about us to
2789 the client. If client requested specific server we will send the
2790 command to that server. */
2792 SILC_SERVER_CMD_FUNC(info)
2794 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2795 SilcServer server = cmd->server;
2796 SilcBuffer packet, idp;
2799 char *dest_server, *server_info = NULL, *server_name;
2800 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2801 SilcServerEntry entry = NULL;
2802 SilcServerID *server_id = NULL;
2804 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2806 /* Get server name */
2807 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2810 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2812 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2815 SILC_STATUS_ERR_NO_SERVER_ID);
2821 /* Check whether we have this server cached */
2822 entry = silc_idlist_find_server_by_id(server->local_list,
2823 server_id, TRUE, NULL);
2825 entry = silc_idlist_find_server_by_id(server->global_list,
2826 server_id, TRUE, NULL);
2827 if (!entry && server->server_type != SILC_SERVER) {
2828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2829 SILC_STATUS_ERR_NO_SUCH_SERVER);
2835 /* Some buggy servers has sent request to router about themselves. */
2836 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2839 if ((!dest_server && !server_id && !entry) || (entry &&
2840 entry == server->id_entry) ||
2841 (dest_server && !cmd->pending &&
2842 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2843 /* Send our reply */
2844 char info_string[256];
2846 memset(info_string, 0, sizeof(info_string));
2847 snprintf(info_string, sizeof(info_string),
2848 "location: %s server: %s admin: %s <%s>",
2849 server->config->server_info->location,
2850 server->config->server_info->server_type,
2851 server->config->server_info->admin,
2852 server->config->server_info->email);
2854 server_info = info_string;
2855 entry = server->id_entry;
2857 /* Check whether we have this server cached */
2858 if (!entry && dest_server) {
2859 entry = silc_idlist_find_server_by_name(server->global_list,
2860 dest_server, TRUE, NULL);
2862 entry = silc_idlist_find_server_by_name(server->local_list,
2863 dest_server, TRUE, NULL);
2867 if (!cmd->pending &&
2868 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2869 /* Send to the server */
2871 SilcUInt16 old_ident;
2873 old_ident = silc_command_get_ident(cmd->payload);
2874 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2875 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2877 silc_server_packet_send(server, entry->connection,
2878 SILC_PACKET_COMMAND, cmd->packet->flags,
2879 tmpbuf->data, tmpbuf->len, TRUE);
2881 /* Reprocess this packet after received reply from router */
2882 silc_server_command_pending(server, SILC_COMMAND_INFO,
2883 silc_command_get_ident(cmd->payload),
2884 silc_server_command_info,
2885 silc_server_command_dup(cmd));
2886 cmd->pending = TRUE;
2887 silc_command_set_ident(cmd->payload, old_ident);
2888 silc_buffer_free(tmpbuf);
2892 if (!entry && !cmd->pending && !server->standalone) {
2893 /* Send to the primary router */
2895 SilcUInt16 old_ident;
2897 old_ident = silc_command_get_ident(cmd->payload);
2898 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2899 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2901 silc_server_packet_send(server, server->router->connection,
2902 SILC_PACKET_COMMAND, cmd->packet->flags,
2903 tmpbuf->data, tmpbuf->len, TRUE);
2905 /* Reprocess this packet after received reply from router */
2906 silc_server_command_pending(server, SILC_COMMAND_INFO,
2907 silc_command_get_ident(cmd->payload),
2908 silc_server_command_info,
2909 silc_server_command_dup(cmd));
2910 cmd->pending = TRUE;
2911 silc_command_set_ident(cmd->payload, old_ident);
2912 silc_buffer_free(tmpbuf);
2917 silc_free(server_id);
2920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2921 SILC_STATUS_ERR_NO_SUCH_SERVER);
2925 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2927 server_info = entry->server_info;
2928 server_name = entry->server_name;
2930 /* Send the reply */
2931 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2932 SILC_STATUS_OK, 0, ident, 3,
2933 2, idp->data, idp->len,
2935 strlen(server_name),
2938 strlen(server_info) : 0);
2939 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2940 packet->data, packet->len, FALSE);
2942 silc_buffer_free(packet);
2943 silc_buffer_free(idp);
2946 silc_server_command_free(cmd);
2949 /* Server side of command PING. This just replies to the ping. */
2951 SILC_SERVER_CMD_FUNC(ping)
2953 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2954 SilcServer server = cmd->server;
2959 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2962 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2965 SILC_STATUS_ERR_NO_SERVER_ID);
2968 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2972 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2973 /* Send our reply */
2974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2978 SILC_STATUS_ERR_NO_SUCH_SERVER);
2985 silc_server_command_free(cmd);
2988 /* Server side of command STATS. */
2990 SILC_SERVER_CMD_FUNC(stats)
2992 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2993 SilcServer server = cmd->server;
2994 SilcServerID *server_id;
2997 SilcBuffer packet, stats;
2998 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3001 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3004 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3006 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3007 SILC_STATUS_ERR_NO_SERVER_ID);
3010 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3014 /* The ID must be ours */
3015 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3017 SILC_STATUS_ERR_NO_SUCH_SERVER);
3018 silc_free(server_id);
3021 silc_free(server_id);
3023 /* If we are router then just send everything we got. If we are normal
3024 server then we'll send this to our router to get all the latest
3025 statistical information. */
3026 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3027 !server->standalone) {
3028 /* Send request to our router */
3029 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3031 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3032 ++server->cmd_ident, 1,
3033 1, idp->data, idp->len);
3034 silc_server_packet_send(server, server->router->connection,
3035 SILC_PACKET_COMMAND, 0, packet->data,
3036 packet->len, FALSE);
3038 /* Reprocess this packet after received reply from router */
3039 silc_server_command_pending(server, SILC_COMMAND_STATS,
3041 silc_server_command_stats,
3042 silc_server_command_dup(cmd));
3043 cmd->pending = TRUE;
3044 silc_buffer_free(packet);
3045 silc_buffer_free(idp);
3049 /* Send our reply to sender */
3050 uptime = time(NULL) - server->starttime;
3052 stats = silc_buffer_alloc_size(60);
3053 silc_buffer_format(stats,
3054 SILC_STR_UI_INT(server->starttime),
3055 SILC_STR_UI_INT(uptime),
3056 SILC_STR_UI_INT(server->stat.my_clients),
3057 SILC_STR_UI_INT(server->stat.my_channels),
3058 SILC_STR_UI_INT(server->stat.my_server_ops),
3059 SILC_STR_UI_INT(server->stat.my_router_ops),
3060 SILC_STR_UI_INT(server->stat.cell_clients),
3061 SILC_STR_UI_INT(server->stat.cell_channels),
3062 SILC_STR_UI_INT(server->stat.cell_servers),
3063 SILC_STR_UI_INT(server->stat.clients),
3064 SILC_STR_UI_INT(server->stat.channels),
3065 SILC_STR_UI_INT(server->stat.servers),
3066 SILC_STR_UI_INT(server->stat.routers),
3067 SILC_STR_UI_INT(server->stat.server_ops),
3068 SILC_STR_UI_INT(server->stat.router_ops),
3071 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3072 SILC_STATUS_OK, 0, ident, 2,
3074 3, stats->data, stats->len);
3075 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3076 0, packet->data, packet->len, FALSE);
3077 silc_buffer_free(packet);
3078 silc_buffer_free(stats);
3081 silc_server_command_free(cmd);
3084 /* Internal routine to join channel. The channel sent to this function
3085 has been either created or resolved from ID lists. This joins the sent
3086 client to the channel. */
3088 static void silc_server_command_join_channel(SilcServer server,
3089 SilcServerCommandContext cmd,
3090 SilcChannelEntry channel,
3091 SilcClientID *client_id,
3095 const unsigned char *auth,
3096 SilcUInt32 auth_len)
3098 SilcSocketConnection sock = cmd->sock;
3100 SilcUInt32 tmp_len, user_count;
3101 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3102 SilcClientEntry client;
3103 SilcChannelClientEntry chl;
3104 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3105 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3106 char check[512], check2[512];
3107 bool founder = FALSE;
3110 SILC_LOG_DEBUG(("Start"));
3115 /* Get the client entry */
3116 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3117 client = (SilcClientEntry)sock->user_data;
3119 client = silc_server_get_client_resolve(server, client_id, &resolve);
3125 silc_server_command_send_status_reply(
3126 cmd, SILC_COMMAND_JOIN,
3127 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3131 /* The client info is being resolved. Reprocess this packet after
3132 receiving the reply to the query. */
3133 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3135 silc_server_command_join,
3136 silc_server_command_dup(cmd));
3137 cmd->pending = TRUE;
3141 cmd->pending = FALSE;
3145 * Check founder auth payload if provided. If client can gain founder
3146 * privileges it can override various conditions on joining the channel,
3147 * and can have directly the founder mode set on the channel.
3149 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3150 SilcIDListData idata = (SilcIDListData)client;
3152 if (channel->founder_key && idata->public_key &&
3153 silc_pkcs_public_key_compare(channel->founder_key,
3154 idata->public_key)) {
3155 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3156 (void *)channel->founder_passwd :
3157 (void *)channel->founder_key);
3158 SilcUInt32 auth_data_len =
3159 (channel->founder_method == SILC_AUTH_PASSWORD ?
3160 channel->founder_passwd_len : 0);
3162 /* Check whether the client is to become founder */
3163 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3164 auth_data, auth_data_len,
3165 idata->hash, client->id, SILC_ID_CLIENT)) {
3166 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3173 * Check channel modes
3177 memset(check, 0, sizeof(check));
3178 memset(check2, 0, sizeof(check2));
3179 strncat(check, client->nickname, strlen(client->nickname));
3180 strncat(check, "!", 1);
3181 strncat(check, client->username, strlen(client->username));
3182 if (!strchr(client->username, '@')) {
3183 strncat(check, "@", 1);
3184 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3187 strncat(check2, client->nickname, strlen(client->nickname));
3188 if (!strchr(client->nickname, '@')) {
3189 strncat(check2, "@", 1);
3190 strncat(check2, server->server_name, strlen(server->server_name));
3192 strncat(check2, "!", 1);
3193 strncat(check2, client->username, strlen(client->username));
3194 if (!strchr(client->username, '@')) {
3195 strncat(check2, "@", 1);
3196 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3199 /* Check invite list if channel is invite-only channel */
3200 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3201 if (!channel->invite_list ||
3202 (!silc_string_match(channel->invite_list, check) &&
3203 !silc_string_match(channel->invite_list, check2))) {
3204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3205 SILC_STATUS_ERR_NOT_INVITED);
3210 /* Check ban list if it exists. If the client's nickname, server,
3211 username and/or hostname is in the ban list the access to the
3212 channel is denied. */
3213 if (channel->ban_list) {
3214 if (silc_string_match(channel->ban_list, check) ||
3215 silc_string_match(channel->ban_list, check2)) {
3216 silc_server_command_send_status_reply(
3217 cmd, SILC_COMMAND_JOIN,
3218 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3223 /* Check user count limit if set. */
3224 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3225 if (silc_hash_table_count(channel->user_list) + 1 >
3226 channel->user_limit) {
3227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3228 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3234 /* Check the channel passphrase if set. */
3235 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3236 /* Get passphrase */
3237 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3239 passphrase = silc_memdup(tmp, tmp_len);
3241 if (!passphrase || !channel->passphrase ||
3242 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3244 SILC_STATUS_ERR_BAD_PASSWORD);
3250 * Client is allowed to join to the channel. Make it happen.
3253 /* Check whether the client already is on the channel */
3254 if (silc_server_client_on_channel(client, channel, NULL)) {
3255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3256 SILC_STATUS_ERR_USER_ON_CHANNEL);
3260 /* Generate new channel key as protocol dictates */
3262 if (!silc_server_create_channel_key(server, channel, 0))
3265 /* Send the channel key. This is broadcasted to the channel but is not
3266 sent to the client who is joining to the channel. */
3267 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3268 silc_server_send_channel_key(server, NULL, channel,
3269 server->server_type == SILC_ROUTER ?
3270 FALSE : !server->standalone);
3273 /* Join the client to the channel by adding it to channel's user list.
3274 Add also the channel to client entry's channels list for fast cross-
3276 chl = silc_calloc(1, sizeof(*chl));
3278 chl->client = client;
3279 chl->channel = channel;
3280 silc_hash_table_add(channel->user_list, client, chl);
3281 silc_hash_table_add(client->channels, channel, chl);
3282 channel->user_count++;
3284 /* Get users on the channel */
3285 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3288 /* Encode Client ID Payload of the original client who wants to join */
3289 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3291 /* Encode command reply packet */
3292 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3293 SILC_PUT32_MSB(channel->mode, mode);
3294 SILC_PUT32_MSB(created, tmp2);
3295 SILC_PUT32_MSB(user_count, tmp3);
3297 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3298 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3299 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3300 strlen(channel->channel_key->
3302 channel->channel_key->cipher->name,
3303 channel->key_len / 8, channel->key);
3308 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3309 SILC_STATUS_OK, 0, ident, 13,
3310 2, channel->channel_name,
3311 strlen(channel->channel_name),
3312 3, chidp->data, chidp->len,
3313 4, clidp->data, clidp->len,
3316 7, keyp ? keyp->data : NULL,
3317 keyp ? keyp->len : 0,
3318 8, channel->ban_list,
3320 strlen(channel->ban_list) : 0,
3321 9, channel->invite_list,
3322 channel->invite_list ?
3323 strlen(channel->invite_list) : 0,
3326 strlen(channel->topic) : 0,
3327 11, silc_hmac_get_name(channel->hmac),
3328 strlen(silc_hmac_get_name(channel->
3331 13, user_list->data, user_list->len,
3332 14, mode_list->data,
3335 /* Send command reply */
3336 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3337 reply->data, reply->len, FALSE);
3339 /* Send JOIN notify to locally connected clients on the channel. If
3340 we are normal server then router will send or have sent JOIN notify
3341 already. However since we've added the client already to our channel
3342 we'll ignore it (in packet_receive.c) so we must send it here. If
3343 we are router then this will send it to local clients and local
3345 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3346 SILC_NOTIFY_TYPE_JOIN, 2,
3347 clidp->data, clidp->len,
3348 chidp->data, chidp->len);
3350 if (!cmd->pending) {
3351 /* Send JOIN notify packet to our primary router */
3352 if (!server->standalone)
3353 silc_server_send_notify_join(server, server->router->connection,
3354 server->server_type == SILC_ROUTER ?
3355 TRUE : FALSE, channel, client->id);
3358 /* Distribute the channel key to all backup routers. */
3359 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3360 keyp->data, keyp->len, FALSE, TRUE);
3363 /* If client became founder by providing correct founder auth data
3364 notify the mode change to the channel. */
3366 SILC_PUT32_MSB(chl->mode, mode);
3367 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3368 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3369 clidp->data, clidp->len,
3370 mode, 4, clidp->data, clidp->len);
3372 /* Set CUMODE notify type to network */
3373 if (!server->standalone)
3374 silc_server_send_notify_cumode(server, server->router->connection,
3375 server->server_type == SILC_ROUTER ?
3376 TRUE : FALSE, channel,
3377 chl->mode, client->id, SILC_ID_CLIENT,
3381 silc_buffer_free(reply);
3382 silc_buffer_free(clidp);
3383 silc_buffer_free(chidp);
3384 silc_buffer_free(keyp);
3385 silc_buffer_free(user_list);
3386 silc_buffer_free(mode_list);
3389 silc_free(passphrase);
3392 /* Server side of command JOIN. Joins client into requested channel. If
3393 the channel does not exist it will be created. */
3395 SILC_SERVER_CMD_FUNC(join)
3397 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3398 SilcServer server = cmd->server;
3399 unsigned char *auth;
3400 SilcUInt32 tmp_len, auth_len;
3401 char *tmp, *channel_name = NULL, *cipher, *hmac;
3402 SilcChannelEntry channel;
3403 SilcUInt32 umode = 0;
3404 bool created = FALSE, create_key = TRUE;
3405 SilcClientID *client_id;
3407 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3409 /* Get channel name */
3410 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3413 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3419 channel_name[255] = '\0';
3421 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3423 SILC_STATUS_ERR_BAD_CHANNEL);
3427 /* Get Client ID of the client who is joining to the channel */
3428 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3431 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3434 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3437 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3441 /* Get cipher, hmac name and auth payload */
3442 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3443 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3444 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3446 /* See if the channel exists */
3447 channel = silc_idlist_find_channel_by_name(server->local_list,
3448 channel_name, NULL);
3450 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3451 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3452 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3454 if (!channel || channel->disabled) {
3455 /* Channel not found */
3457 /* If we are standalone server we don't have a router, we just create
3458 the channel by ourselves. */
3459 if (server->standalone) {
3460 channel = silc_server_create_new_channel(server, server->id, cipher,
3461 hmac, channel_name, TRUE);
3463 silc_server_command_send_status_reply(
3464 cmd, SILC_COMMAND_JOIN,
3465 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3469 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3475 /* The channel does not exist on our server. If we are normal server
3476 we will send JOIN command to our router which will handle the
3477 joining procedure (either creates the channel if it doesn't exist
3478 or joins the client to it). */
3479 if (server->server_type != SILC_ROUTER) {
3481 SilcUInt16 old_ident;
3483 /* If this is pending command callback then we've resolved
3484 it and it didn't work, return since we've notified the
3485 client already in the command reply callback. */
3489 old_ident = silc_command_get_ident(cmd->payload);
3490 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3491 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3493 /* Send JOIN command to our router */
3494 silc_server_packet_send(server, (SilcSocketConnection)
3495 server->router->connection,
3496 SILC_PACKET_COMMAND, cmd->packet->flags,
3497 tmpbuf->data, tmpbuf->len, TRUE);
3499 /* Reprocess this packet after received reply from router */
3500 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3501 silc_command_get_ident(cmd->payload),
3502 silc_server_command_join,
3503 silc_server_command_dup(cmd));
3504 cmd->pending = TRUE;
3505 silc_command_set_ident(cmd->payload, old_ident);
3506 silc_buffer_free(tmpbuf);
3510 /* We are router and the channel does not seem exist so we will check
3511 our global list as well for the channel. */
3512 channel = silc_idlist_find_channel_by_name(server->global_list,
3513 channel_name, NULL);
3515 /* Channel really does not exist, create it */
3516 channel = silc_server_create_new_channel(server, server->id, cipher,
3517 hmac, channel_name, TRUE);
3519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3520 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3524 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3532 /* Channel not found */
3534 /* If the command came from router and we are normal server then
3535 something went wrong with the joining as the channel was not found.
3536 We can't do anything else but ignore this. */
3537 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3538 server->server_type != SILC_ROUTER)
3541 /* We are router and the channel does not seem exist so we will check
3542 our global list as well for the channel. */
3543 channel = silc_idlist_find_channel_by_name(server->global_list,
3544 channel_name, NULL);
3546 /* Channel really does not exist, create it */
3547 channel = silc_server_create_new_channel(server, server->id, cipher,
3548 hmac, channel_name, TRUE);
3550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3551 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3555 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3562 /* Check whether the channel was created by our router */
3563 if (cmd->pending && context2) {
3564 SilcServerCommandReplyContext reply = context2;
3566 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3567 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3568 SILC_GET32_MSB(created, tmp);
3569 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3570 create_key = FALSE; /* Router returned the key already */
3573 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3574 !silc_hash_table_count(channel->user_list))
3578 /* If the channel does not have global users and is also empty the client
3579 will be the channel founder and operator. */
3580 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3581 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3583 /* Join to the channel */
3584 silc_server_command_join_channel(server, cmd, channel, client_id,
3585 created, create_key, umode,
3588 silc_free(client_id);
3591 silc_server_command_free(cmd);
3594 /* Server side of command MOTD. Sends server's current "message of the
3595 day" to the client. */
3597 SILC_SERVER_CMD_FUNC(motd)
3599 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3600 SilcServer server = cmd->server;
3601 SilcBuffer packet, idp;
3602 char *motd, *dest_server;
3603 SilcUInt32 motd_len;
3604 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3606 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3608 /* Get server name */
3609 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3612 SILC_STATUS_ERR_NO_SUCH_SERVER);
3616 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3619 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3621 if (server->config && server->config->server_info &&
3622 server->config->server_info->motd_file) {
3624 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3629 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3636 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3642 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3643 packet->data, packet->len, FALSE);
3644 silc_buffer_free(packet);
3645 silc_buffer_free(idp);
3647 SilcServerEntry entry;
3649 /* Check whether we have this server cached */
3650 entry = silc_idlist_find_server_by_name(server->global_list,
3651 dest_server, TRUE, NULL);
3653 entry = silc_idlist_find_server_by_name(server->local_list,
3654 dest_server, TRUE, NULL);
3657 if (server->server_type != SILC_SERVER && !cmd->pending &&
3658 entry && !entry->motd) {
3659 /* Send to the server */
3661 SilcUInt16 old_ident;
3663 old_ident = silc_command_get_ident(cmd->payload);
3664 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3665 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3667 silc_server_packet_send(server, entry->connection,
3668 SILC_PACKET_COMMAND, cmd->packet->flags,
3669 tmpbuf->data, tmpbuf->len, TRUE);
3671 /* Reprocess this packet after received reply from router */
3672 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3673 silc_command_get_ident(cmd->payload),
3674 silc_server_command_motd,
3675 silc_server_command_dup(cmd));
3676 cmd->pending = TRUE;
3677 silc_command_set_ident(cmd->payload, old_ident);
3678 silc_buffer_free(tmpbuf);
3682 if (!entry && !cmd->pending && !server->standalone) {
3683 /* Send to the primary router */
3685 SilcUInt16 old_ident;
3687 old_ident = silc_command_get_ident(cmd->payload);
3688 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3689 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3691 silc_server_packet_send(server, server->router->connection,
3692 SILC_PACKET_COMMAND, cmd->packet->flags,
3693 tmpbuf->data, tmpbuf->len, TRUE);
3695 /* Reprocess this packet after received reply from router */
3696 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3697 silc_command_get_ident(cmd->payload),
3698 silc_server_command_motd,
3699 silc_server_command_dup(cmd));
3700 cmd->pending = TRUE;
3701 silc_command_set_ident(cmd->payload, old_ident);
3702 silc_buffer_free(tmpbuf);
3707 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3708 SILC_STATUS_ERR_NO_SUCH_SERVER);
3712 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3713 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3714 SILC_STATUS_OK, 0, ident, 2,
3718 strlen(entry->motd) : 0);
3719 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3720 packet->data, packet->len, FALSE);
3721 silc_buffer_free(packet);
3722 silc_buffer_free(idp);
3726 silc_server_command_free(cmd);
3729 /* Server side of command UMODE. Client can use this command to set/unset
3730 user mode. Client actually cannot set itself to be as server/router
3731 operator so this can be used only to unset the modes. */
3733 SILC_SERVER_CMD_FUNC(umode)
3735 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3736 SilcServer server = cmd->server;
3737 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3739 unsigned char *tmp_mask;
3741 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3743 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3746 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3748 /* Get the client's mode mask */
3749 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3752 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3755 SILC_GET32_MSB(mask, tmp_mask);
3757 /* Check that mode changing is allowed. */
3758 if (!silc_server_check_umode_rights(server, client, mask)) {
3759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3760 SILC_STATUS_ERR_PERM_DENIED);
3764 /* Change the mode */
3765 client->mode = mask;
3767 /* Send UMODE change to primary router */
3768 if (!server->standalone)
3769 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3770 client->id, client->mode);
3772 /* Send command reply to sender */
3773 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3774 SILC_STATUS_OK, 0, ident, 1,
3776 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3777 packet->data, packet->len, FALSE);
3778 silc_buffer_free(packet);
3781 silc_server_command_free(cmd);
3784 /* Server side command of CMODE. Changes channel mode */
3786 SILC_SERVER_CMD_FUNC(cmode)
3788 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3789 SilcServer server = cmd->server;
3790 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3791 SilcIDListData idata = (SilcIDListData)client;
3792 SilcChannelID *channel_id;
3793 SilcChannelEntry channel;
3794 SilcChannelClientEntry chl;
3795 SilcBuffer packet, cidp;
3796 unsigned char *tmp, *tmp_id, *tmp_mask;
3797 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3798 SilcUInt32 mode_mask, tmp_len, tmp_len2;
3799 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3801 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3803 /* Get Channel ID */
3804 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3807 SILC_STATUS_ERR_NO_CHANNEL_ID);
3810 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3813 SILC_STATUS_ERR_NO_CHANNEL_ID);
3817 /* Get the channel mode mask */
3818 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3821 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3824 SILC_GET32_MSB(mode_mask, tmp_mask);
3826 /* Get channel entry */
3827 channel = silc_idlist_find_channel_by_id(server->local_list,
3830 channel = silc_idlist_find_channel_by_id(server->global_list,
3833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3834 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3839 /* Check whether this client is on the channel */
3840 if (!silc_server_client_on_channel(client, channel, &chl)) {
3841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3842 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3846 /* Check that client has rights to change any requested channel modes */
3847 if (!silc_server_check_cmode_rights(server, channel, chl, mode_mask)) {
3848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3850 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3851 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3856 * Check the modes. Modes that requires nothing special operation are
3860 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3861 /* Channel uses private keys to protect traffic. Client(s) has set the
3862 key locally they want to use, server does not know that key. */
3863 /* Nothing interesting to do here */
3865 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3866 /* The mode is removed and we need to generate and distribute
3867 new channel key. Clients are not using private channel keys
3868 anymore after this. */
3870 /* Re-generate channel key */
3871 if (!silc_server_create_channel_key(server, channel, 0))
3874 /* Send the channel key. This sends it to our local clients and if
3875 we are normal server to our router as well. */
3876 silc_server_send_channel_key(server, NULL, channel,
3877 server->server_type == SILC_ROUTER ?
3878 FALSE : !server->standalone);
3880 cipher = channel->channel_key->cipher->name;
3881 hmac = (char *)silc_hmac_get_name(channel->hmac);
3885 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3886 /* User limit is set on channel */
3887 SilcUInt32 user_limit;
3889 /* Get user limit */
3890 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3892 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3894 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3898 SILC_GET32_MSB(user_limit, tmp);
3899 channel->user_limit = user_limit;
3902 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3903 /* User limit mode is unset. Remove user limit */
3904 channel->user_limit = 0;
3907 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3908 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3909 /* Passphrase has been set to channel */
3911 /* Get the passphrase */
3912 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3915 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3919 /* Save the passphrase */
3920 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3923 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3924 /* Passphrase mode is unset. remove the passphrase */
3925 silc_free(channel->passphrase);
3926 channel->passphrase = NULL;
3930 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3931 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3932 /* Cipher to use protect the traffic */
3933 SilcCipher newkey, oldkey;
3936 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3939 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3943 /* Delete old cipher and allocate the new one */
3944 if (!silc_cipher_alloc(cipher, &newkey)) {
3945 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3946 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3950 oldkey = channel->channel_key;
3951 channel->channel_key = newkey;
3953 /* Re-generate channel key */
3954 if (!silc_server_create_channel_key(server, channel, 0)) {
3955 /* We don't have new key, revert to old one */
3956 channel->channel_key = oldkey;
3960 /* Remove old channel key for good */
3961 silc_cipher_free(oldkey);
3963 /* Send the channel key. This sends it to our local clients and if
3964 we are normal server to our router as well. */
3965 silc_server_send_channel_key(server, NULL, channel,
3966 server->server_type == SILC_ROUTER ?
3967 FALSE : !server->standalone);
3970 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3971 /* Cipher mode is unset. Remove the cipher and revert back to
3973 SilcCipher newkey, oldkey;
3974 cipher = channel->cipher;
3976 /* Delete old cipher and allocate default one */
3977 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3978 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3979 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3983 oldkey = channel->channel_key;
3984 channel->channel_key = newkey;
3986 /* Re-generate channel key */
3987 if (!silc_server_create_channel_key(server, channel, 0)) {
3988 /* We don't have new key, revert to old one */
3989 channel->channel_key = oldkey;
3993 /* Remove old channel key for good */
3994 silc_cipher_free(oldkey);
3996 /* Send the channel key. This sends it to our local clients and if
3997 we are normal server to our router as well. */
3998 silc_server_send_channel_key(server, NULL, channel,
3999 server->server_type == SILC_ROUTER ?
4000 FALSE : !server->standalone);
4004 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4005 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4006 /* HMAC to use protect the traffic */
4007 unsigned char hash[32];
4011 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4014 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4018 /* Delete old hmac and allocate the new one */
4019 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4021 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4025 silc_hmac_free(channel->hmac);
4026 channel->hmac = newhmac;
4028 /* Set the HMAC key out of current channel key. The client must do
4030 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4031 channel->key_len / 8, hash);
4032 silc_hmac_set_key(channel->hmac, hash,
4033 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4034 memset(hash, 0, sizeof(hash));
4037 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4038 /* Hmac mode is unset. Remove the hmac and revert back to
4041 unsigned char hash[32];
4042 hmac = channel->hmac_name;
4044 /* Delete old hmac and allocate default one */
4045 silc_hmac_free(channel->hmac);
4046 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4048 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4052 silc_hmac_free(channel->hmac);
4053 channel->hmac = newhmac;
4055 /* Set the HMAC key out of current channel key. The client must do
4057 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4058 channel->key_len / 8,
4060 silc_hmac_set_key(channel->hmac, hash,
4061 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4062 memset(hash, 0, sizeof(hash));
4066 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4067 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4068 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4069 /* Set the founder authentication */
4070 SilcAuthPayload auth;
4072 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4075 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4079 auth = silc_auth_payload_parse(tmp, tmp_len);
4081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4082 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4086 /* Save the public key */
4087 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4088 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4091 channel->founder_method = silc_auth_get_method(auth);
4093 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4094 tmp = silc_auth_get_data(auth, &tmp_len);
4095 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4096 channel->founder_passwd_len = tmp_len;
4098 /* Verify the payload before setting the mode */
4099 if (!silc_auth_verify(auth, channel->founder_method,
4100 channel->founder_key, 0, idata->hash,
4101 client->id, SILC_ID_CLIENT)) {
4102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4103 SILC_STATUS_ERR_AUTH_FAILED);
4108 silc_auth_payload_free(auth);
4112 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4113 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4114 if (channel->founder_key)
4115 silc_pkcs_public_key_free(channel->founder_key);
4116 if (channel->founder_passwd) {
4117 silc_free(channel->founder_passwd);
4118 channel->founder_passwd = NULL;
4124 /* Finally, set the mode */
4125 channel->mode = mode_mask;
4127 /* Send CMODE_CHANGE notify. */
4128 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4129 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4130 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4131 cidp->data, cidp->len,
4133 cipher, cipher ? strlen(cipher) : 0,
4134 hmac, hmac ? strlen(hmac) : 0,
4135 passphrase, passphrase ?
4136 strlen(passphrase) : 0);
4138 /* Set CMODE notify type to network */
4139 if (!server->standalone)
4140 silc_server_send_notify_cmode(server, server->router->connection,
4141 server->server_type == SILC_ROUTER ?
4142 TRUE : FALSE, channel,
4143 mode_mask, client->id, SILC_ID_CLIENT,
4144 cipher, hmac, passphrase);
4146 /* Send command reply to sender */
4147 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4148 SILC_STATUS_OK, 0, ident, 2,
4149 2, tmp_id, tmp_len2,
4151 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4152 packet->data, packet->len, FALSE);
4154 silc_buffer_free(packet);
4155 silc_free(channel_id);
4156 silc_buffer_free(cidp);
4159 silc_server_command_free(cmd);
4162 /* Server side of CUMODE command. Changes client's mode on a channel. */
4164 SILC_SERVER_CMD_FUNC(cumode)
4166 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4167 SilcServer server = cmd->server;
4168 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4169 SilcIDListData idata = (SilcIDListData)client;
4170 SilcChannelID *channel_id;
4171 SilcClientID *client_id;
4172 SilcChannelEntry channel;
4173 SilcClientEntry target_client;
4174 SilcChannelClientEntry chl;
4175 SilcBuffer packet, idp;
4176 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4177 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4179 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4181 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4183 /* Get Channel ID */
4184 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4187 SILC_STATUS_ERR_NO_CHANNEL_ID);
4190 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4193 SILC_STATUS_ERR_NO_CHANNEL_ID);
4197 /* Get channel entry */
4198 channel = silc_idlist_find_channel_by_id(server->local_list,
4201 channel = silc_idlist_find_channel_by_id(server->global_list,
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4205 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4210 /* Check whether sender is on the channel */
4211 if (!silc_server_client_on_channel(client, channel, &chl)) {
4212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4213 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4216 sender_mask = chl->mode;
4218 /* Get the target client's channel mode mask */
4219 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4222 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4225 SILC_GET32_MSB(target_mask, tmp_mask);
4227 /* Get target Client ID */
4228 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4231 SILC_STATUS_ERR_NO_CLIENT_ID);
4234 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4237 SILC_STATUS_ERR_NO_CLIENT_ID);
4241 /* Get target client's entry */
4242 target_client = silc_idlist_find_client_by_id(server->local_list,
4243 client_id, TRUE, NULL);
4244 if (!target_client) {
4245 target_client = silc_idlist_find_client_by_id(server->global_list,
4246 client_id, TRUE, NULL);
4249 if (target_client != client &&
4250 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4251 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4257 /* Check whether target client is on the channel */
4258 if (target_client != client) {
4259 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4261 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4270 /* If the target client is founder, no one else can change their mode
4272 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4274 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4278 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4279 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4280 /* The client tries to claim the founder rights. */
4281 unsigned char *tmp_auth;
4282 SilcUInt32 tmp_auth_len, auth_len;
4285 if (target_client != client) {
4286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4287 SILC_STATUS_ERR_NOT_YOU);
4291 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4292 !channel->founder_key || !idata->public_key ||
4293 !silc_pkcs_public_key_compare(channel->founder_key,
4294 idata->public_key)) {
4295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4296 SILC_STATUS_ERR_NOT_YOU);
4300 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4303 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4307 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4308 (void *)channel->founder_passwd : (void *)channel->founder_key);
4309 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4310 channel->founder_passwd_len : 0);
4312 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4313 channel->founder_method, auth, auth_len,
4314 idata->hash, client->id, SILC_ID_CLIENT)) {
4315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4316 SILC_STATUS_ERR_AUTH_FAILED);
4320 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4324 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4325 if (target_client == client) {
4326 /* Remove channel founder rights from itself */
4327 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4331 SILC_STATUS_ERR_NOT_YOU);
4337 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4338 /* Promote to operator */
4339 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4340 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4341 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4343 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4347 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4351 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4352 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4353 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4355 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4359 /* Demote to normal user */
4360 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4365 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4366 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4368 /* Send notify to channel, notify only if mode was actually changed. */
4370 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4371 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4372 idp->data, idp->len,
4376 /* Set CUMODE notify type to network */
4377 if (!server->standalone)
4378 silc_server_send_notify_cumode(server, server->router->connection,
4379 server->server_type == SILC_ROUTER ?
4380 TRUE : FALSE, channel,
4381 target_mask, client->id,
4386 /* Send command reply to sender */
4387 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4388 SILC_STATUS_OK, 0, ident, 3,
4390 3, tmp_ch_id, tmp_ch_len,
4391 4, tmp_id, tmp_len);
4392 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4393 packet->data, packet->len, FALSE);
4395 silc_buffer_free(packet);
4396 silc_free(channel_id);
4397 silc_free(client_id);
4398 silc_buffer_free(idp);
4401 silc_server_command_free(cmd);
4404 /* Server side of KICK command. Kicks client out of channel. */
4406 SILC_SERVER_CMD_FUNC(kick)
4408 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4409 SilcServer server = cmd->server;
4410 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4411 SilcClientEntry target_client;
4412 SilcChannelID *channel_id;
4413 SilcClientID *client_id;
4414 SilcChannelEntry channel;
4415 SilcChannelClientEntry chl;
4417 SilcUInt32 tmp_len, target_idp_len;
4418 unsigned char *tmp, *comment, *target_idp;
4420 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4422 /* Get Channel ID */
4423 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4426 SILC_STATUS_ERR_NO_CHANNEL_ID);
4429 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4432 SILC_STATUS_ERR_NO_CHANNEL_ID);
4436 /* Get channel entry */
4437 channel = silc_idlist_find_channel_by_id(server->local_list,
4440 channel = silc_idlist_find_channel_by_id(server->local_list,
4443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4444 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4449 /* Check whether sender is on the channel */
4450 if (!silc_server_client_on_channel(client, channel, &chl)) {
4451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4452 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4456 /* Check that the kicker is channel operator or channel founder */
4457 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4459 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4463 /* Get target Client ID */
4464 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4467 SILC_STATUS_ERR_NO_CLIENT_ID);
4470 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4473 SILC_STATUS_ERR_NO_CLIENT_ID);
4477 /* Get target client's entry */
4478 target_client = silc_idlist_find_client_by_id(server->local_list,
4479 client_id, TRUE, NULL);
4480 if (!target_client) {
4481 target_client = silc_idlist_find_client_by_id(server->global_list,
4482 client_id, TRUE, NULL);
4485 /* Check whether target client is on the channel */
4486 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4488 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4492 /* Check that the target client is not channel founder. Channel founder
4493 cannot be kicked from the channel. */
4494 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4496 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4502 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4506 /* Send command reply to sender */
4507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4510 /* Send KICKED notify to local clients on the channel */
4511 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4512 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4513 SILC_NOTIFY_TYPE_KICKED, 3,
4514 target_idp, target_idp_len,
4515 comment, comment ? strlen(comment) : 0,
4516 idp->data, idp->len);
4517 silc_buffer_free(idp);
4519 /* Remove the client from the channel. If the channel does not exist
4520 after removing the client then the client kicked itself off the channel
4521 and we don't have to send anything after that. */
4522 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4523 target_client, FALSE))
4526 /* Send KICKED notify to primary route */
4527 if (!server->standalone)
4528 silc_server_send_notify_kicked(server, server->router->connection,
4529 server->server_type == SILC_ROUTER ?
4530 TRUE : FALSE, channel,
4531 target_client->id, client->id, comment);
4533 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4534 /* Re-generate channel key */
4535 if (!silc_server_create_channel_key(server, channel, 0))
4538 /* Send the channel key to the channel. The key of course is not sent
4539 to the client who was kicked off the channel. */
4540 silc_server_send_channel_key(server, target_client->connection, channel,
4541 server->server_type == SILC_ROUTER ?
4542 FALSE : !server->standalone);
4546 silc_server_command_free(cmd);
4549 /* Server side of OPER command. Client uses this comand to obtain server
4550 operator privileges to this server/router. */
4552 SILC_SERVER_CMD_FUNC(oper)
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_OPER, cmd, 1, 2);
4566 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4569 /* Get the username */
4570 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4573 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4577 /* Get the admin configuration */
4578 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4579 username, client->nickname);
4581 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4582 username, client->nickname);
4584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4585 SILC_STATUS_ERR_AUTH_FAILED);
4590 /* Get the authentication payload */
4591 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4594 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4598 /* Verify the authentication data. If both passphrase and public key
4599 is set then try both of them. */
4600 if (admin->passphrase)
4601 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4602 admin->passphrase, admin->passphrase_len,
4603 idata->hash, client->id, SILC_ID_CLIENT);
4604 if (!result && admin->publickeys) {
4605 cached_key = silc_server_get_public_key(server, admin->publickeys);
4608 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4609 cached_key, 0, idata->hash,
4610 client->id, SILC_ID_CLIENT);
4613 /* Authentication failed */
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4615 SILC_STATUS_ERR_AUTH_FAILED);
4619 /* Client is now server operator */
4620 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4622 /* Update statistics */
4623 if (client->connection)
4624 server->stat.my_server_ops++;
4625 if (server->server_type == SILC_ROUTER)
4626 server->stat.server_ops++;
4628 /* Send UMODE change to primary router */
4629 if (!server->standalone)
4630 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4631 client->id, client->mode);
4633 /* Send reply to the sender */
4634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4638 silc_server_command_free(cmd);
4641 /* Server side of SILCOPER command. Client uses this comand to obtain router
4642 operator privileges to this router. */
4644 SILC_SERVER_CMD_FUNC(silcoper)
4646 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4647 SilcServer server = cmd->server;
4648 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4649 unsigned char *username, *auth;
4651 SilcServerConfigAdmin *admin;
4652 SilcIDListData idata = (SilcIDListData)client;
4653 bool result = FALSE;
4654 SilcPublicKey cached_key;
4656 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4658 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4661 if (server->server_type != SILC_ROUTER) {
4662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4663 SILC_STATUS_ERR_AUTH_FAILED);
4667 /* Get the username */
4668 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4671 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4675 /* Get the admin configuration */
4676 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4677 username, client->nickname);
4679 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4680 username, client->nickname);
4682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4683 SILC_STATUS_ERR_AUTH_FAILED);
4688 /* Get the authentication payload */
4689 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4692 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4696 /* Verify the authentication data. If both passphrase and public key
4697 is set then try both of them. */
4698 if (admin->passphrase)
4699 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4700 admin->passphrase, admin->passphrase_len,
4701 idata->hash, client->id, SILC_ID_CLIENT);
4702 if (!result && admin->publickeys) {
4703 cached_key = silc_server_get_public_key(server, admin->publickeys);
4706 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4707 cached_key, 0, idata->hash,
4708 client->id, SILC_ID_CLIENT);
4711 /* Authentication failed */
4712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4713 SILC_STATUS_ERR_AUTH_FAILED);
4717 /* Client is now router operator */
4718 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4720 /* Update statistics */
4721 if (client->connection)
4722 server->stat.my_router_ops++;
4723 if (server->server_type == SILC_ROUTER)
4724 server->stat.router_ops++;
4726 /* Send UMODE change to primary router */
4727 if (!server->standalone)
4728 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4729 client->id, client->mode);
4731 /* Send reply to the sender */
4732 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4736 silc_server_command_free(cmd);
4739 /* Server side of command BAN. This is used to manage the ban list of the
4740 channel. To add clients and remove clients from the ban list. */
4742 SILC_SERVER_CMD_FUNC(ban)
4744 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4745 SilcServer server = cmd->server;
4746 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4748 SilcChannelEntry channel;
4749 SilcChannelClientEntry chl;
4750 SilcChannelID *channel_id = NULL;
4751 unsigned char *id, *add, *del;
4752 SilcUInt32 id_len, tmp_len;
4753 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4755 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4758 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4760 /* Get Channel ID */
4761 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4763 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4766 SILC_STATUS_ERR_NO_CHANNEL_ID);
4771 /* Get channel entry. The server must know about the channel since the
4772 client is expected to be on the channel. */
4773 channel = silc_idlist_find_channel_by_id(server->local_list,
4776 channel = silc_idlist_find_channel_by_id(server->global_list,
4779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4780 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4785 /* Check whether this client is on the channel */
4786 if (!silc_server_client_on_channel(client, channel, &chl)) {
4787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4788 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4792 /* The client must be at least channel operator. */
4793 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4794 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4795 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4799 /* Get the new ban and add it to the ban list */
4800 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4802 if (!channel->ban_list)
4803 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4805 channel->ban_list = silc_realloc(channel->ban_list,
4806 sizeof(*channel->ban_list) *
4808 strlen(channel->ban_list) + 2));
4809 if (add[tmp_len - 1] == ',')
4810 add[tmp_len - 1] = '\0';
4812 strncat(channel->ban_list, add, tmp_len);
4813 strncat(channel->ban_list, ",", 1);
4816 /* Get the ban to be removed and remove it from the list */
4817 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4818 if (del && channel->ban_list) {
4819 char *start, *end, *n;
4821 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4822 silc_free(channel->ban_list);
4823 channel->ban_list = NULL;
4825 start = strstr(channel->ban_list, del);
4826 if (start && strlen(start) >= tmp_len) {
4827 end = start + tmp_len;
4828 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4829 strncat(n, channel->ban_list, start - channel->ban_list);
4830 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4832 silc_free(channel->ban_list);
4833 channel->ban_list = n;
4838 /* Send the BAN notify type to our primary router. */
4839 if (!server->standalone && (add || del))
4840 silc_server_send_notify_ban(server, server->router->connection,
4841 server->server_type == SILC_ROUTER ?
4842 TRUE : FALSE, channel, add, del);
4844 /* Send the reply back to the client */
4846 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4847 SILC_STATUS_OK, 0, ident, 2,
4849 3, channel->ban_list,
4851 strlen(channel->ban_list) -1 : 0);
4852 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4853 packet->data, packet->len, FALSE);
4855 silc_buffer_free(packet);
4858 silc_free(channel_id);
4859 silc_server_command_free(cmd);
4862 /* Server side command of LEAVE. Removes client from a channel. */
4864 SILC_SERVER_CMD_FUNC(leave)
4866 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4867 SilcServer server = cmd->server;
4868 SilcSocketConnection sock = cmd->sock;
4869 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4870 SilcChannelID *id = NULL;
4871 SilcChannelEntry channel;
4875 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4877 /* Get Channel ID */
4878 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4880 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4881 SILC_STATUS_ERR_NO_CHANNEL_ID);
4884 id = silc_id_payload_parse_id(tmp, len, NULL);
4886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4887 SILC_STATUS_ERR_NO_CHANNEL_ID);
4891 /* Get channel entry */
4892 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4894 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4897 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4902 /* Check whether this client is on the channel */
4903 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4905 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4909 /* Notify routers that they should remove this client from their list
4910 of clients on the channel. Send LEAVE notify type. */
4911 if (!server->standalone)
4912 silc_server_send_notify_leave(server, server->router->connection,
4913 server->server_type == SILC_ROUTER ?
4914 TRUE : FALSE, channel, id_entry->id);
4916 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4917 SILC_STATUS_OK, 2, tmp, len);
4919 /* Remove client from channel */
4920 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4922 /* If the channel does not exist anymore we won't send anything */
4925 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4926 /* Re-generate channel key */
4927 if (!silc_server_create_channel_key(server, channel, 0))
4930 /* Send the channel key */
4931 silc_server_send_channel_key(server, NULL, channel,
4932 server->server_type == SILC_ROUTER ?
4933 FALSE : !server->standalone);
4938 silc_server_command_free(cmd);
4941 /* Server side of command USERS. Resolves clients and their USERS currently
4942 joined on the requested channel. The list of Client ID's and their modes
4943 on the channel is sent back. */
4945 SILC_SERVER_CMD_FUNC(users)
4947 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4948 SilcServer server = cmd->server;
4949 SilcChannelEntry channel;
4950 SilcChannelID *id = NULL;
4951 SilcBuffer packet, idp;
4952 unsigned char *channel_id;
4953 SilcUInt32 channel_id_len;
4954 SilcBuffer client_id_list;
4955 SilcBuffer client_mode_list;
4956 unsigned char lc[4];
4957 SilcUInt32 list_count = 0;
4958 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4961 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4963 /* Get Channel ID */
4964 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4966 /* Get channel name */
4967 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4969 if (!channel_id && !channel_name) {
4970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4971 SILC_STATUS_ERR_NO_CHANNEL_ID);
4976 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4978 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4979 SILC_STATUS_ERR_NO_CHANNEL_ID);
4984 /* If we are server and we don't know about this channel we will send
4985 the command to our router. If we know about the channel then we also
4986 have the list of users already. */
4988 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4990 channel = silc_idlist_find_channel_by_name(server->local_list,
4991 channel_name, NULL);
4993 if (!channel || channel->disabled) {
4994 if (server->server_type != SILC_ROUTER && !server->standalone &&
4998 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4999 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5001 /* Send USERS command */
5002 silc_server_packet_send(server, server->router->connection,
5003 SILC_PACKET_COMMAND, cmd->packet->flags,
5004 tmpbuf->data, tmpbuf->len, TRUE);
5006 /* Reprocess this packet after received reply */
5007 silc_server_command_pending(server, SILC_COMMAND_USERS,
5008 silc_command_get_ident(cmd->payload),
5009 silc_server_command_users,
5010 silc_server_command_dup(cmd));
5011 cmd->pending = TRUE;
5012 silc_command_set_ident(cmd->payload, ident);
5013 silc_buffer_free(tmpbuf);
5018 /* Check the global list as well. */
5020 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5022 channel = silc_idlist_find_channel_by_name(server->global_list,
5023 channel_name, NULL);
5025 /* Channel really does not exist */
5026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5027 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5032 /* If the channel is private or secret do not send anything, unless the
5033 user requesting this command is on the channel. */
5034 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5035 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5036 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5039 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5044 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5046 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5051 /* Get the users list */
5052 silc_server_get_users_on_channel(server, channel, &client_id_list,
5053 &client_mode_list, &list_count);
5056 SILC_PUT32_MSB(list_count, lc);
5059 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5060 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5061 SILC_STATUS_OK, 0, ident, 4,
5062 2, idp->data, idp->len,
5064 4, client_id_list->data,
5065 client_id_list->len,
5066 5, client_mode_list->data,
5067 client_mode_list->len);
5068 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5069 packet->data, packet->len, FALSE);
5071 silc_buffer_free(idp);
5072 silc_buffer_free(packet);
5073 silc_buffer_free(client_id_list);
5074 silc_buffer_free(client_mode_list);
5078 silc_server_command_free(cmd);
5081 /* Server side of command GETKEY. This fetches the client's public key
5082 from the server where to the client is connected. */
5084 SILC_SERVER_CMD_FUNC(getkey)
5086 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5087 SilcServer server = cmd->server;
5089 SilcClientEntry client;
5090 SilcServerEntry server_entry;
5091 SilcClientID *client_id = NULL;
5092 SilcServerID *server_id = NULL;
5093 SilcIDPayload idp = NULL;
5094 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5095 unsigned char *tmp, *pkdata;
5096 SilcUInt32 tmp_len, pklen;
5097 SilcBuffer pk = NULL;
5099 SilcPublicKey public_key;
5101 SILC_LOG_DEBUG(("Start"));
5103 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5105 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5106 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5109 idp = silc_id_payload_parse(tmp, tmp_len);
5111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5112 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5116 id_type = silc_id_payload_get_type(idp);
5117 if (id_type == SILC_ID_CLIENT) {
5118 client_id = silc_id_payload_get_id(idp);
5120 /* If the client is not found from local list there is no chance it
5121 would be locally connected client so send the command further. */
5122 client = silc_idlist_find_client_by_id(server->local_list,
5123 client_id, TRUE, NULL);
5125 client = silc_idlist_find_client_by_id(server->global_list,
5126 client_id, TRUE, NULL);
5128 if ((!client && !cmd->pending && !server->standalone) ||
5129 (client && !client->connection && !cmd->pending) ||
5130 (client && !client->data.public_key && !cmd->pending)) {
5132 SilcUInt16 old_ident;
5133 SilcSocketConnection dest_sock;
5135 dest_sock = silc_server_get_client_route(server, NULL, 0,
5140 old_ident = silc_command_get_ident(cmd->payload);
5141 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5142 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5144 silc_server_packet_send(server, dest_sock,
5145 SILC_PACKET_COMMAND, cmd->packet->flags,
5146 tmpbuf->data, tmpbuf->len, TRUE);
5148 /* Reprocess this packet after received reply from router */
5149 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5150 silc_command_get_ident(cmd->payload),
5151 silc_server_command_getkey,
5152 silc_server_command_dup(cmd));
5153 cmd->pending = TRUE;
5154 silc_command_set_ident(cmd->payload, old_ident);
5155 silc_buffer_free(tmpbuf);
5160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5161 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5165 /* The client is locally connected, just get the public key and
5166 send it back. If they key does not exist then do not send it,
5167 send just OK reply */
5168 public_key = client->data.public_key;
5173 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5174 pk = silc_buffer_alloc(4 + tmp_len);
5175 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5176 silc_buffer_format(pk,
5177 SILC_STR_UI_SHORT(tmp_len),
5178 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5179 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5185 } else if (id_type == SILC_ID_SERVER) {
5186 server_id = silc_id_payload_get_id(idp);
5188 /* If the server is not found from local list there is no chance it
5189 would be locally connected server so send the command further. */
5190 server_entry = silc_idlist_find_server_by_id(server->local_list,
5191 server_id, TRUE, NULL);
5193 server_entry = silc_idlist_find_server_by_id(server->global_list,
5194 server_id, TRUE, NULL);
5196 if (server_entry != server->id_entry &&
5197 ((!server_entry && !cmd->pending && !server->standalone) ||
5198 (server_entry && !server_entry->connection && !cmd->pending &&
5199 !server->standalone) ||
5200 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5201 !server->standalone))) {
5203 SilcUInt16 old_ident;
5205 old_ident = silc_command_get_ident(cmd->payload);
5206 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5207 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5209 silc_server_packet_send(server, server->router->connection,
5210 SILC_PACKET_COMMAND, cmd->packet->flags,
5211 tmpbuf->data, tmpbuf->len, TRUE);
5213 /* Reprocess this packet after received reply from router */
5214 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5215 silc_command_get_ident(cmd->payload),
5216 silc_server_command_getkey,
5217 silc_server_command_dup(cmd));
5218 cmd->pending = TRUE;
5219 silc_command_set_ident(cmd->payload, old_ident);
5220 silc_buffer_free(tmpbuf);
5224 if (!server_entry) {
5225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5226 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5230 /* If they key does not exist then do not send it, send just OK reply */
5231 public_key = (!server_entry->data.public_key ?
5232 (server_entry == server->id_entry ? server->public_key :
5233 NULL) : server_entry->data.public_key);
5238 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5239 pk = silc_buffer_alloc(4 + tmp_len);
5240 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5241 silc_buffer_format(pk,
5242 SILC_STR_UI_SHORT(tmp_len),
5243 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5244 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5254 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5255 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5256 SILC_STATUS_OK, 0, ident,
5260 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5261 packet->data, packet->len, FALSE);
5262 silc_buffer_free(packet);
5265 silc_buffer_free(pk);
5269 silc_id_payload_free(idp);
5270 silc_free(client_id);
5271 silc_free(server_id);
5272 silc_server_command_free(cmd);
5276 /* Private range commands, specific to this implementation */
5278 /* Server side command of CONNECT. Connects us to the specified remote
5279 server or router. */
5281 SILC_SERVER_CMD_FUNC(connect)
5283 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5284 SilcServer server = cmd->server;
5285 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5286 unsigned char *tmp, *host;
5288 SilcUInt32 port = SILC_PORT;
5290 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5292 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5295 /* Check whether client has the permissions. */
5296 if (client->mode == SILC_UMODE_NONE) {
5297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5298 SILC_STATUS_ERR_NO_SERVER_PRIV);
5302 if (server->server_type == SILC_ROUTER &&
5303 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5305 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5309 /* Get the remote server */
5310 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5313 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5318 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5320 SILC_GET32_MSB(port, tmp);
5322 /* Create the connection. It is done with timeout and is async. */
5323 silc_server_create_connection(server, host, port);
5325 /* Send reply to the sender */
5326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5330 silc_server_command_free(cmd);
5333 /* Server side command of CLOSE. Closes connection to a specified server. */
5335 SILC_SERVER_CMD_FUNC(close)
5337 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5338 SilcServer server = cmd->server;
5339 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5340 SilcServerEntry server_entry;
5341 SilcSocketConnection sock;
5344 unsigned char *name;
5345 SilcUInt32 port = SILC_PORT;
5347 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5349 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5352 /* Check whether client has the permissions. */
5353 if (client->mode == SILC_UMODE_NONE) {
5354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5355 SILC_STATUS_ERR_NO_SERVER_PRIV);
5359 /* Get the remote server */
5360 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5362 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5363 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5368 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5370 SILC_GET32_MSB(port, tmp);
5372 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5373 name, port, FALSE, NULL);
5375 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5376 name, port, FALSE, NULL);
5377 if (!server_entry) {
5378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5379 SILC_STATUS_ERR_NO_SERVER_ID);
5383 /* Send reply to the sender */
5384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5387 /* Close the connection to the server */
5388 sock = (SilcSocketConnection)server_entry->connection;
5390 /* If we shutdown primary router connection manually then don't trigger
5391 any reconnect or backup router connections, by setting the router
5393 if (server->router == server_entry) {
5394 server->id_entry->router = NULL;
5395 server->router = NULL;
5396 server->standalone = TRUE;
5398 silc_server_free_sock_user_data(server, sock, NULL);
5399 silc_server_close_connection(server, sock);
5402 silc_server_command_free(cmd);
5405 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5406 active connections. */
5408 SILC_SERVER_CMD_FUNC(shutdown)
5410 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5411 SilcServer server = cmd->server;
5412 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5414 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5416 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5419 /* Check whether client has the permission. */
5420 if (client->mode == SILC_UMODE_NONE) {
5421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5422 SILC_STATUS_ERR_NO_SERVER_PRIV);
5426 /* Send reply to the sender */
5427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5430 /* Then, gracefully, or not, bring the server down. */
5431 silc_server_stop(server);
5435 silc_server_command_free(cmd);