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,
2486 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2487 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2491 memset(invite, 0, sizeof(invite));
2492 strncat(invite, dest->nickname, strlen(dest->nickname));
2493 strncat(invite, "!", 1);
2494 strncat(invite, dest->username, strlen(dest->username));
2495 if (!strchr(dest->username, '@')) {
2496 strncat(invite, "@", 1);
2497 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2500 len = strlen(invite);
2501 if (!channel->invite_list)
2502 channel->invite_list = silc_calloc(len + 2,
2503 sizeof(*channel->invite_list));
2505 channel->invite_list = silc_realloc(channel->invite_list,
2506 sizeof(*channel->invite_list) *
2508 strlen(channel->invite_list) + 2));
2509 strncat(channel->invite_list, invite, len);
2510 strncat(channel->invite_list, ",", 1);
2512 /* Send notify to the client that is invited to the channel */
2513 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2514 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2515 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2517 SILC_NOTIFY_TYPE_INVITE, 3,
2518 idp->data, idp->len,
2519 channel->channel_name,
2520 strlen(channel->channel_name),
2521 idp2->data, idp2->len);
2522 silc_buffer_free(idp);
2523 silc_buffer_free(idp2);
2526 /* Add the client to the invite list of the channel */
2527 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2529 if (!channel->invite_list)
2530 channel->invite_list = silc_calloc(len + 2,
2531 sizeof(*channel->invite_list));
2533 channel->invite_list = silc_realloc(channel->invite_list,
2534 sizeof(*channel->invite_list) *
2536 strlen(channel->invite_list) + 2));
2537 if (add[len - 1] == ',')
2538 add[len - 1] = '\0';
2540 strncat(channel->invite_list, add, len);
2541 strncat(channel->invite_list, ",", 1);
2544 /* Get the invite to be removed and remove it from the list */
2545 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2546 if (del && channel->invite_list) {
2547 char *start, *end, *n;
2549 if (!strncmp(channel->invite_list, del,
2550 strlen(channel->invite_list) - 1)) {
2551 silc_free(channel->invite_list);
2552 channel->invite_list = NULL;
2554 start = strstr(channel->invite_list, del);
2555 if (start && strlen(start) >= len) {
2557 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2558 strncat(n, channel->invite_list, start - channel->invite_list);
2559 strncat(n, end + 1, ((channel->invite_list +
2560 strlen(channel->invite_list)) - end) - 1);
2561 silc_free(channel->invite_list);
2562 channel->invite_list = n;
2567 /* Send notify to the primary router */
2568 if (!server->standalone)
2569 silc_server_send_notify_invite(server, server->router->connection,
2570 server->server_type == SILC_ROUTER ?
2571 TRUE : FALSE, channel,
2572 sender->id, add, del);
2574 /* Send command reply */
2575 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2579 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2580 SILC_STATUS_OK, 0, ident, 2,
2582 3, channel->invite_list,
2583 channel->invite_list ?
2584 strlen(channel->invite_list) : 0);
2587 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2588 SILC_STATUS_OK, 0, ident, 1,
2590 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2591 packet->data, packet->len, FALSE);
2592 silc_buffer_free(packet);
2596 silc_free(channel_id);
2597 silc_server_command_free(cmd);
2602 SilcSocketConnection sock;
2606 /* Quits connection to client. This gets called if client won't
2607 close the connection even when it has issued QUIT command. */
2609 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2611 QuitInternal q = (QuitInternal)context;
2613 /* Free all client specific data, such as client entry and entires
2614 on channels this client may be on. */
2615 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2617 q->sock->user_data = NULL;
2619 /* Close the connection on our side */
2620 silc_server_close_connection(q->server, q->sock);
2622 silc_free(q->signoff);
2626 /* Quits SILC session. This is the normal way to disconnect client. */
2628 SILC_SERVER_CMD_FUNC(quit)
2630 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2631 SilcServer server = cmd->server;
2632 SilcSocketConnection sock = cmd->sock;
2634 unsigned char *tmp = NULL;
2637 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2639 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2642 /* Get destination ID */
2643 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2647 q = silc_calloc(1, sizeof(*q));
2650 q->signoff = tmp ? strdup(tmp) : NULL;
2652 /* We quit the connection with little timeout */
2653 silc_schedule_task_add(server->schedule, sock->sock,
2654 silc_server_command_quit_cb, (void *)q,
2655 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2658 silc_server_command_free(cmd);
2661 /* Server side of command KILL. This command is used by router operator
2662 to remove an client from the SILC Network temporarily. */
2664 SILC_SERVER_CMD_FUNC(kill)
2666 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2667 SilcServer server = cmd->server;
2668 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2669 SilcClientEntry remote_client;
2670 SilcClientID *client_id;
2671 unsigned char *tmp, *comment;
2672 SilcUInt32 tmp_len, tmp_len2;
2676 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2678 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2681 /* KILL command works only on router */
2682 if (server->server_type != SILC_ROUTER) {
2683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2684 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2688 /* Check whether client has the permissions. */
2689 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2691 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2695 /* Get the client ID */
2696 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2699 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2702 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2704 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2705 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2709 /* Get the client entry */
2710 remote_client = silc_idlist_find_client_by_id(server->local_list,
2711 client_id, TRUE, NULL);
2713 if (!remote_client) {
2714 remote_client = silc_idlist_find_client_by_id(server->global_list,
2715 client_id, TRUE, NULL);
2717 if (!remote_client) {
2718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2719 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2725 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2729 /* Send reply to the sender */
2730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2733 /* Send the KILL notify packets. First send it to the channel, then
2734 to our primary router and then directly to the client who is being
2735 killed right now. */
2737 /* Send KILLED notify to the channels. It is not sent to the client
2738 as it will be sent differently destined directly to the client and not
2740 killer = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2741 silc_server_send_notify_on_channels(server, remote_client,
2742 remote_client, SILC_NOTIFY_TYPE_KILLED,
2744 comment, comment ? tmp_len2 : 0,
2745 killer->data, killer->len);
2746 silc_buffer_free(killer);
2748 /* Send KILLED notify to primary route */
2749 if (!server->standalone)
2750 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2751 remote_client->id, comment, client->id);
2753 /* Send KILLED notify to the client directly */
2754 silc_server_send_notify_killed(server, remote_client->connection ?
2755 remote_client->connection :
2756 remote_client->router->connection, FALSE,
2757 remote_client->id, comment, client->id);
2759 /* Remove the client from all channels. This generates new keys to the
2760 channels as well. */
2761 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2764 /* Remove the client entry, If it is locally connected then we will also
2765 disconnect the client here */
2766 if (remote_client->connection) {
2767 /* Remove locally conneted client */
2768 SilcSocketConnection sock = remote_client->connection;
2769 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2770 silc_server_close_connection(server, sock);
2772 /* Update statistics */
2773 if (remote_client->connection)
2774 server->stat.my_clients--;
2775 if (server->stat.cell_clients)
2776 server->stat.cell_clients--;
2777 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2778 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2780 /* Remove remote client */
2781 silc_idlist_del_client(local ? server->local_list :
2782 server->global_list, remote_client);
2786 silc_server_command_free(cmd);
2789 /* Server side of command INFO. This sends information about us to
2790 the client. If client requested specific server we will send the
2791 command to that server. */
2793 SILC_SERVER_CMD_FUNC(info)
2795 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2796 SilcServer server = cmd->server;
2797 SilcBuffer packet, idp;
2800 char *dest_server, *server_info = NULL, *server_name;
2801 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2802 SilcServerEntry entry = NULL;
2803 SilcServerID *server_id = NULL;
2805 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2807 /* Get server name */
2808 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2811 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2813 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2816 SILC_STATUS_ERR_NO_SERVER_ID);
2822 /* Check whether we have this server cached */
2823 entry = silc_idlist_find_server_by_id(server->local_list,
2824 server_id, TRUE, NULL);
2826 entry = silc_idlist_find_server_by_id(server->global_list,
2827 server_id, TRUE, NULL);
2828 if (!entry && server->server_type != SILC_SERVER) {
2829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2830 SILC_STATUS_ERR_NO_SUCH_SERVER);
2836 /* Some buggy servers has sent request to router about themselves. */
2837 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2840 if ((!dest_server && !server_id && !entry) || (entry &&
2841 entry == server->id_entry) ||
2842 (dest_server && !cmd->pending &&
2843 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2844 /* Send our reply */
2845 char info_string[256];
2847 memset(info_string, 0, sizeof(info_string));
2848 snprintf(info_string, sizeof(info_string),
2849 "location: %s server: %s admin: %s <%s>",
2850 server->config->server_info->location,
2851 server->config->server_info->server_type,
2852 server->config->server_info->admin,
2853 server->config->server_info->email);
2855 server_info = info_string;
2856 entry = server->id_entry;
2858 /* Check whether we have this server cached */
2859 if (!entry && dest_server) {
2860 entry = silc_idlist_find_server_by_name(server->global_list,
2861 dest_server, TRUE, NULL);
2863 entry = silc_idlist_find_server_by_name(server->local_list,
2864 dest_server, TRUE, NULL);
2868 if (!cmd->pending &&
2869 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2870 /* Send to the server */
2872 SilcUInt16 old_ident;
2874 old_ident = silc_command_get_ident(cmd->payload);
2875 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2876 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2878 silc_server_packet_send(server, entry->connection,
2879 SILC_PACKET_COMMAND, cmd->packet->flags,
2880 tmpbuf->data, tmpbuf->len, TRUE);
2882 /* Reprocess this packet after received reply from router */
2883 silc_server_command_pending(server, SILC_COMMAND_INFO,
2884 silc_command_get_ident(cmd->payload),
2885 silc_server_command_info,
2886 silc_server_command_dup(cmd));
2887 cmd->pending = TRUE;
2888 silc_command_set_ident(cmd->payload, old_ident);
2889 silc_buffer_free(tmpbuf);
2893 if (!entry && !cmd->pending && !server->standalone) {
2894 /* Send to the primary router */
2896 SilcUInt16 old_ident;
2898 old_ident = silc_command_get_ident(cmd->payload);
2899 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2900 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2902 silc_server_packet_send(server, server->router->connection,
2903 SILC_PACKET_COMMAND, cmd->packet->flags,
2904 tmpbuf->data, tmpbuf->len, TRUE);
2906 /* Reprocess this packet after received reply from router */
2907 silc_server_command_pending(server, SILC_COMMAND_INFO,
2908 silc_command_get_ident(cmd->payload),
2909 silc_server_command_info,
2910 silc_server_command_dup(cmd));
2911 cmd->pending = TRUE;
2912 silc_command_set_ident(cmd->payload, old_ident);
2913 silc_buffer_free(tmpbuf);
2918 silc_free(server_id);
2921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2922 SILC_STATUS_ERR_NO_SUCH_SERVER);
2926 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2928 server_info = entry->server_info;
2929 server_name = entry->server_name;
2931 /* Send the reply */
2932 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2933 SILC_STATUS_OK, 0, ident, 3,
2934 2, idp->data, idp->len,
2936 strlen(server_name),
2939 strlen(server_info) : 0);
2940 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2941 packet->data, packet->len, FALSE);
2943 silc_buffer_free(packet);
2944 silc_buffer_free(idp);
2947 silc_server_command_free(cmd);
2950 /* Server side of command PING. This just replies to the ping. */
2952 SILC_SERVER_CMD_FUNC(ping)
2954 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2955 SilcServer server = cmd->server;
2960 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2963 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2966 SILC_STATUS_ERR_NO_SERVER_ID);
2969 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2973 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2974 /* Send our reply */
2975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2978 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2979 SILC_STATUS_ERR_NO_SUCH_SERVER);
2986 silc_server_command_free(cmd);
2989 /* Server side of command STATS. */
2991 SILC_SERVER_CMD_FUNC(stats)
2993 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2994 SilcServer server = cmd->server;
2995 SilcServerID *server_id;
2998 SilcBuffer packet, stats;
2999 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3002 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3005 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3008 SILC_STATUS_ERR_NO_SERVER_ID);
3011 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3015 /* The ID must be ours */
3016 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3018 SILC_STATUS_ERR_NO_SUCH_SERVER);
3019 silc_free(server_id);
3022 silc_free(server_id);
3024 /* If we are router then just send everything we got. If we are normal
3025 server then we'll send this to our router to get all the latest
3026 statistical information. */
3027 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3028 !server->standalone) {
3029 /* Send request to our router */
3030 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3032 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3033 ++server->cmd_ident, 1,
3034 1, idp->data, idp->len);
3035 silc_server_packet_send(server, server->router->connection,
3036 SILC_PACKET_COMMAND, 0, packet->data,
3037 packet->len, FALSE);
3039 /* Reprocess this packet after received reply from router */
3040 silc_server_command_pending(server, SILC_COMMAND_STATS,
3042 silc_server_command_stats,
3043 silc_server_command_dup(cmd));
3044 cmd->pending = TRUE;
3045 silc_buffer_free(packet);
3046 silc_buffer_free(idp);
3050 /* Send our reply to sender */
3051 uptime = time(NULL) - server->starttime;
3053 stats = silc_buffer_alloc_size(60);
3054 silc_buffer_format(stats,
3055 SILC_STR_UI_INT(server->starttime),
3056 SILC_STR_UI_INT(uptime),
3057 SILC_STR_UI_INT(server->stat.my_clients),
3058 SILC_STR_UI_INT(server->stat.my_channels),
3059 SILC_STR_UI_INT(server->stat.my_server_ops),
3060 SILC_STR_UI_INT(server->stat.my_router_ops),
3061 SILC_STR_UI_INT(server->stat.cell_clients),
3062 SILC_STR_UI_INT(server->stat.cell_channels),
3063 SILC_STR_UI_INT(server->stat.cell_servers),
3064 SILC_STR_UI_INT(server->stat.clients),
3065 SILC_STR_UI_INT(server->stat.channels),
3066 SILC_STR_UI_INT(server->stat.servers),
3067 SILC_STR_UI_INT(server->stat.routers),
3068 SILC_STR_UI_INT(server->stat.server_ops),
3069 SILC_STR_UI_INT(server->stat.router_ops),
3072 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3073 SILC_STATUS_OK, 0, ident, 2,
3075 3, stats->data, stats->len);
3076 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3077 0, packet->data, packet->len, FALSE);
3078 silc_buffer_free(packet);
3079 silc_buffer_free(stats);
3082 silc_server_command_free(cmd);
3085 /* Internal routine to join channel. The channel sent to this function
3086 has been either created or resolved from ID lists. This joins the sent
3087 client to the channel. */
3089 static void silc_server_command_join_channel(SilcServer server,
3090 SilcServerCommandContext cmd,
3091 SilcChannelEntry channel,
3092 SilcClientID *client_id,
3096 const unsigned char *auth,
3097 SilcUInt32 auth_len)
3099 SilcSocketConnection sock = cmd->sock;
3101 SilcUInt32 tmp_len, user_count;
3102 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3103 SilcClientEntry client;
3104 SilcChannelClientEntry chl;
3105 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3106 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3107 char check[512], check2[512];
3108 bool founder = FALSE;
3111 SILC_LOG_DEBUG(("Start"));
3116 /* Get the client entry */
3117 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3118 client = (SilcClientEntry)sock->user_data;
3120 client = silc_server_get_client_resolve(server, client_id, &resolve);
3126 silc_server_command_send_status_reply(
3127 cmd, SILC_COMMAND_JOIN,
3128 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3132 /* The client info is being resolved. Reprocess this packet after
3133 receiving the reply to the query. */
3134 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3136 silc_server_command_join,
3137 silc_server_command_dup(cmd));
3138 cmd->pending = TRUE;
3142 cmd->pending = FALSE;
3146 * Check founder auth payload if provided. If client can gain founder
3147 * privileges it can override various conditions on joining the channel,
3148 * and can have directly the founder mode set on the channel.
3150 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3151 SilcIDListData idata = (SilcIDListData)client;
3153 if (channel->founder_key && idata->public_key &&
3154 silc_pkcs_public_key_compare(channel->founder_key,
3155 idata->public_key)) {
3156 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3157 (void *)channel->founder_passwd :
3158 (void *)channel->founder_key);
3159 SilcUInt32 auth_data_len =
3160 (channel->founder_method == SILC_AUTH_PASSWORD ?
3161 channel->founder_passwd_len : 0);
3163 /* Check whether the client is to become founder */
3164 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3165 auth_data, auth_data_len,
3166 idata->hash, client->id, SILC_ID_CLIENT)) {
3167 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3174 * Check channel modes
3178 memset(check, 0, sizeof(check));
3179 memset(check2, 0, sizeof(check2));
3180 strncat(check, client->nickname, strlen(client->nickname));
3181 strncat(check, "!", 1);
3182 strncat(check, client->username, strlen(client->username));
3183 if (!strchr(client->username, '@')) {
3184 strncat(check, "@", 1);
3185 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3188 strncat(check2, client->nickname, strlen(client->nickname));
3189 if (!strchr(client->nickname, '@')) {
3190 strncat(check2, "@", 1);
3191 strncat(check2, server->server_name, strlen(server->server_name));
3193 strncat(check2, "!", 1);
3194 strncat(check2, client->username, strlen(client->username));
3195 if (!strchr(client->username, '@')) {
3196 strncat(check2, "@", 1);
3197 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3200 /* Check invite list if channel is invite-only channel */
3201 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3202 if (!channel->invite_list ||
3203 (!silc_string_match(channel->invite_list, check) &&
3204 !silc_string_match(channel->invite_list, check2))) {
3205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3206 SILC_STATUS_ERR_NOT_INVITED);
3211 /* Check ban list if it exists. If the client's nickname, server,
3212 username and/or hostname is in the ban list the access to the
3213 channel is denied. */
3214 if (channel->ban_list) {
3215 if (silc_string_match(channel->ban_list, check) ||
3216 silc_string_match(channel->ban_list, check2)) {
3217 silc_server_command_send_status_reply(
3218 cmd, SILC_COMMAND_JOIN,
3219 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3224 /* Check user count limit if set. */
3225 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3226 if (silc_hash_table_count(channel->user_list) + 1 >
3227 channel->user_limit) {
3228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3229 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3235 /* Check the channel passphrase if set. */
3236 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3237 /* Get passphrase */
3238 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3240 passphrase = silc_memdup(tmp, tmp_len);
3242 if (!passphrase || !channel->passphrase ||
3243 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3245 SILC_STATUS_ERR_BAD_PASSWORD);
3251 * Client is allowed to join to the channel. Make it happen.
3254 /* Check whether the client already is on the channel */
3255 if (silc_server_client_on_channel(client, channel, NULL)) {
3256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3257 SILC_STATUS_ERR_USER_ON_CHANNEL);
3261 /* Generate new channel key as protocol dictates */
3263 if (!silc_server_create_channel_key(server, channel, 0))
3266 /* Send the channel key. This is broadcasted to the channel but is not
3267 sent to the client who is joining to the channel. */
3268 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3269 silc_server_send_channel_key(server, NULL, channel,
3270 server->server_type == SILC_ROUTER ?
3271 FALSE : !server->standalone);
3274 /* Join the client to the channel by adding it to channel's user list.
3275 Add also the channel to client entry's channels list for fast cross-
3277 chl = silc_calloc(1, sizeof(*chl));
3279 chl->client = client;
3280 chl->channel = channel;
3281 silc_hash_table_add(channel->user_list, client, chl);
3282 silc_hash_table_add(client->channels, channel, chl);
3283 channel->user_count++;
3285 /* Get users on the channel */
3286 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3289 /* Encode Client ID Payload of the original client who wants to join */
3290 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3292 /* Encode command reply packet */
3293 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3294 SILC_PUT32_MSB(channel->mode, mode);
3295 SILC_PUT32_MSB(created, tmp2);
3296 SILC_PUT32_MSB(user_count, tmp3);
3298 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3299 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3300 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3301 strlen(channel->channel_key->
3303 channel->channel_key->cipher->name,
3304 channel->key_len / 8, channel->key);
3309 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3310 SILC_STATUS_OK, 0, ident, 13,
3311 2, channel->channel_name,
3312 strlen(channel->channel_name),
3313 3, chidp->data, chidp->len,
3314 4, clidp->data, clidp->len,
3317 7, keyp ? keyp->data : NULL,
3318 keyp ? keyp->len : 0,
3319 8, channel->ban_list,
3321 strlen(channel->ban_list) : 0,
3322 9, channel->invite_list,
3323 channel->invite_list ?
3324 strlen(channel->invite_list) : 0,
3327 strlen(channel->topic) : 0,
3328 11, silc_hmac_get_name(channel->hmac),
3329 strlen(silc_hmac_get_name(channel->
3332 13, user_list->data, user_list->len,
3333 14, mode_list->data,
3336 /* Send command reply */
3337 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3338 reply->data, reply->len, FALSE);
3340 /* Send JOIN notify to locally connected clients on the channel. If
3341 we are normal server then router will send or have sent JOIN notify
3342 already. However since we've added the client already to our channel
3343 we'll ignore it (in packet_receive.c) so we must send it here. If
3344 we are router then this will send it to local clients and local
3346 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3347 SILC_NOTIFY_TYPE_JOIN, 2,
3348 clidp->data, clidp->len,
3349 chidp->data, chidp->len);
3351 if (!cmd->pending) {
3352 /* Send JOIN notify packet to our primary router */
3353 if (!server->standalone)
3354 silc_server_send_notify_join(server, server->router->connection,
3355 server->server_type == SILC_ROUTER ?
3356 TRUE : FALSE, channel, client->id);
3359 /* Distribute the channel key to all backup routers. */
3360 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3361 keyp->data, keyp->len, FALSE, TRUE);
3364 /* If client became founder by providing correct founder auth data
3365 notify the mode change to the channel. */
3367 SILC_PUT32_MSB(chl->mode, mode);
3368 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3369 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3370 clidp->data, clidp->len,
3371 mode, 4, clidp->data, clidp->len);
3373 /* Set CUMODE notify type to network */
3374 if (!server->standalone)
3375 silc_server_send_notify_cumode(server, server->router->connection,
3376 server->server_type == SILC_ROUTER ?
3377 TRUE : FALSE, channel,
3378 chl->mode, client->id, SILC_ID_CLIENT,
3382 silc_buffer_free(reply);
3383 silc_buffer_free(clidp);
3384 silc_buffer_free(chidp);
3385 silc_buffer_free(keyp);
3386 silc_buffer_free(user_list);
3387 silc_buffer_free(mode_list);
3390 silc_free(passphrase);
3393 /* Server side of command JOIN. Joins client into requested channel. If
3394 the channel does not exist it will be created. */
3396 SILC_SERVER_CMD_FUNC(join)
3398 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3399 SilcServer server = cmd->server;
3400 unsigned char *auth;
3401 SilcUInt32 tmp_len, auth_len;
3402 char *tmp, *channel_name = NULL, *cipher, *hmac;
3403 SilcChannelEntry channel;
3404 SilcUInt32 umode = 0;
3405 bool created = FALSE, create_key = TRUE;
3406 SilcClientID *client_id;
3408 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3410 /* Get channel name */
3411 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3414 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3420 channel_name[255] = '\0';
3422 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3424 SILC_STATUS_ERR_BAD_CHANNEL);
3428 /* Get Client ID of the client who is joining to the channel */
3429 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3432 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3435 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3438 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3442 /* Get cipher, hmac name and auth payload */
3443 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3444 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3445 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3447 /* See if the channel exists */
3448 channel = silc_idlist_find_channel_by_name(server->local_list,
3449 channel_name, NULL);
3451 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3452 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3453 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3455 if (!channel || channel->disabled) {
3456 /* Channel not found */
3458 /* If we are standalone server we don't have a router, we just create
3459 the channel by ourselves. */
3460 if (server->standalone) {
3461 channel = silc_server_create_new_channel(server, server->id, cipher,
3462 hmac, channel_name, TRUE);
3464 silc_server_command_send_status_reply(
3465 cmd, SILC_COMMAND_JOIN,
3466 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3470 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3476 /* The channel does not exist on our server. If we are normal server
3477 we will send JOIN command to our router which will handle the
3478 joining procedure (either creates the channel if it doesn't exist
3479 or joins the client to it). */
3480 if (server->server_type != SILC_ROUTER) {
3482 SilcUInt16 old_ident;
3484 /* If this is pending command callback then we've resolved
3485 it and it didn't work, return since we've notified the
3486 client already in the command reply callback. */
3490 old_ident = silc_command_get_ident(cmd->payload);
3491 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3492 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3494 /* Send JOIN command to our router */
3495 silc_server_packet_send(server, (SilcSocketConnection)
3496 server->router->connection,
3497 SILC_PACKET_COMMAND, cmd->packet->flags,
3498 tmpbuf->data, tmpbuf->len, TRUE);
3500 /* Reprocess this packet after received reply from router */
3501 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3502 silc_command_get_ident(cmd->payload),
3503 silc_server_command_join,
3504 silc_server_command_dup(cmd));
3505 cmd->pending = TRUE;
3506 silc_command_set_ident(cmd->payload, old_ident);
3507 silc_buffer_free(tmpbuf);
3511 /* We are router and the channel does not seem exist so we will check
3512 our global list as well for the channel. */
3513 channel = silc_idlist_find_channel_by_name(server->global_list,
3514 channel_name, NULL);
3516 /* Channel really does not exist, create it */
3517 channel = silc_server_create_new_channel(server, server->id, cipher,
3518 hmac, channel_name, TRUE);
3520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3521 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3525 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3533 /* Channel not found */
3535 /* If the command came from router and we are normal server then
3536 something went wrong with the joining as the channel was not found.
3537 We can't do anything else but ignore this. */
3538 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3539 server->server_type != SILC_ROUTER)
3542 /* We are router and the channel does not seem exist so we will check
3543 our global list as well for the channel. */
3544 channel = silc_idlist_find_channel_by_name(server->global_list,
3545 channel_name, NULL);
3547 /* Channel really does not exist, create it */
3548 channel = silc_server_create_new_channel(server, server->id, cipher,
3549 hmac, channel_name, TRUE);
3551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3552 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3556 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3563 /* Check whether the channel was created by our router */
3564 if (cmd->pending && context2) {
3565 SilcServerCommandReplyContext reply = context2;
3567 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3568 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3569 SILC_GET32_MSB(created, tmp);
3570 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3571 create_key = FALSE; /* Router returned the key already */
3574 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3575 !silc_hash_table_count(channel->user_list))
3579 /* If the channel does not have global users and is also empty the client
3580 will be the channel founder and operator. */
3581 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3582 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3584 /* Join to the channel */
3585 silc_server_command_join_channel(server, cmd, channel, client_id,
3586 created, create_key, umode,
3589 silc_free(client_id);
3592 silc_server_command_free(cmd);
3595 /* Server side of command MOTD. Sends server's current "message of the
3596 day" to the client. */
3598 SILC_SERVER_CMD_FUNC(motd)
3600 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3601 SilcServer server = cmd->server;
3602 SilcBuffer packet, idp;
3603 char *motd, *dest_server;
3604 SilcUInt32 motd_len;
3605 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3607 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3609 /* Get server name */
3610 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3613 SILC_STATUS_ERR_NO_SUCH_SERVER);
3617 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3620 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3622 if (server->config && server->config->server_info &&
3623 server->config->server_info->motd_file) {
3625 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3630 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3637 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3643 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3644 packet->data, packet->len, FALSE);
3645 silc_buffer_free(packet);
3646 silc_buffer_free(idp);
3648 SilcServerEntry entry;
3650 /* Check whether we have this server cached */
3651 entry = silc_idlist_find_server_by_name(server->global_list,
3652 dest_server, TRUE, NULL);
3654 entry = silc_idlist_find_server_by_name(server->local_list,
3655 dest_server, TRUE, NULL);
3658 if (server->server_type != SILC_SERVER && !cmd->pending &&
3659 entry && !entry->motd) {
3660 /* Send to the server */
3662 SilcUInt16 old_ident;
3664 old_ident = silc_command_get_ident(cmd->payload);
3665 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3666 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3668 silc_server_packet_send(server, entry->connection,
3669 SILC_PACKET_COMMAND, cmd->packet->flags,
3670 tmpbuf->data, tmpbuf->len, TRUE);
3672 /* Reprocess this packet after received reply from router */
3673 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3674 silc_command_get_ident(cmd->payload),
3675 silc_server_command_motd,
3676 silc_server_command_dup(cmd));
3677 cmd->pending = TRUE;
3678 silc_command_set_ident(cmd->payload, old_ident);
3679 silc_buffer_free(tmpbuf);
3683 if (!entry && !cmd->pending && !server->standalone) {
3684 /* Send to the primary router */
3686 SilcUInt16 old_ident;
3688 old_ident = silc_command_get_ident(cmd->payload);
3689 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3690 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3692 silc_server_packet_send(server, server->router->connection,
3693 SILC_PACKET_COMMAND, cmd->packet->flags,
3694 tmpbuf->data, tmpbuf->len, TRUE);
3696 /* Reprocess this packet after received reply from router */
3697 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3698 silc_command_get_ident(cmd->payload),
3699 silc_server_command_motd,
3700 silc_server_command_dup(cmd));
3701 cmd->pending = TRUE;
3702 silc_command_set_ident(cmd->payload, old_ident);
3703 silc_buffer_free(tmpbuf);
3708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3709 SILC_STATUS_ERR_NO_SUCH_SERVER);
3713 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3714 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3715 SILC_STATUS_OK, 0, ident, 2,
3719 strlen(entry->motd) : 0);
3720 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3721 packet->data, packet->len, FALSE);
3722 silc_buffer_free(packet);
3723 silc_buffer_free(idp);
3727 silc_server_command_free(cmd);
3730 /* Server side of command UMODE. Client can use this command to set/unset
3731 user mode. Client actually cannot set itself to be as server/router
3732 operator so this can be used only to unset the modes. */
3734 SILC_SERVER_CMD_FUNC(umode)
3736 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3737 SilcServer server = cmd->server;
3738 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3740 unsigned char *tmp_mask;
3742 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3744 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3747 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3749 /* Get the client's mode mask */
3750 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3752 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3753 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3756 SILC_GET32_MSB(mask, tmp_mask);
3758 /* Check that mode changing is allowed. */
3759 if (!silc_server_check_umode_rights(server, client, mask)) {
3760 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3761 SILC_STATUS_ERR_PERM_DENIED);
3765 /* Anonymous mode cannot be set by client */
3766 if (mask & SILC_UMODE_ANONYMOUS) {
3767 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3769 SILC_STATUS_ERR_PERM_DENIED);
3773 if (client->mode & SILC_UMODE_ANONYMOUS) {
3774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3775 SILC_STATUS_ERR_PERM_DENIED);
3780 /* Change the mode */
3781 client->mode = mask;
3783 /* Send UMODE change to primary router */
3784 if (!server->standalone)
3785 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3786 client->id, client->mode);
3788 /* Send command reply to sender */
3789 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3790 SILC_STATUS_OK, 0, ident, 1,
3792 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3793 packet->data, packet->len, FALSE);
3794 silc_buffer_free(packet);
3797 silc_server_command_free(cmd);
3800 /* Server side command of CMODE. Changes channel mode */
3802 SILC_SERVER_CMD_FUNC(cmode)
3804 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3805 SilcServer server = cmd->server;
3806 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3807 SilcIDListData idata = (SilcIDListData)client;
3808 SilcChannelID *channel_id;
3809 SilcChannelEntry channel;
3810 SilcChannelClientEntry chl;
3811 SilcBuffer packet, cidp;
3812 unsigned char *tmp, *tmp_id, *tmp_mask;
3813 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3814 SilcUInt32 mode_mask, tmp_len, tmp_len2;
3815 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3817 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3819 /* Get Channel ID */
3820 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3823 SILC_STATUS_ERR_NO_CHANNEL_ID);
3826 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3829 SILC_STATUS_ERR_NO_CHANNEL_ID);
3833 /* Get the channel mode mask */
3834 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3837 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3840 SILC_GET32_MSB(mode_mask, tmp_mask);
3842 /* Get channel entry */
3843 channel = silc_idlist_find_channel_by_id(server->local_list,
3846 channel = silc_idlist_find_channel_by_id(server->global_list,
3849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3850 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3855 /* Check whether this client is on the channel */
3856 if (!silc_server_client_on_channel(client, channel, &chl)) {
3857 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3858 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3862 /* Check that client has rights to change any requested channel modes */
3863 if (!silc_server_check_cmode_rights(server, channel, chl, mode_mask)) {
3864 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3866 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3867 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3872 * Check the modes. Modes that requires nothing special operation are
3876 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3877 /* Channel uses private keys to protect traffic. Client(s) has set the
3878 key locally they want to use, server does not know that key. */
3879 /* Nothing interesting to do here */
3881 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3882 /* The mode is removed and we need to generate and distribute
3883 new channel key. Clients are not using private channel keys
3884 anymore after this. */
3886 /* Re-generate channel key */
3887 if (!silc_server_create_channel_key(server, channel, 0))
3890 /* Send the channel key. This sends it to our local clients and if
3891 we are normal server to our router as well. */
3892 silc_server_send_channel_key(server, NULL, channel,
3893 server->server_type == SILC_ROUTER ?
3894 FALSE : !server->standalone);
3896 cipher = channel->channel_key->cipher->name;
3897 hmac = (char *)silc_hmac_get_name(channel->hmac);
3901 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3902 /* User limit is set on channel */
3903 SilcUInt32 user_limit;
3905 /* Get user limit */
3906 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3908 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3910 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3914 SILC_GET32_MSB(user_limit, tmp);
3915 channel->user_limit = user_limit;
3918 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3919 /* User limit mode is unset. Remove user limit */
3920 channel->user_limit = 0;
3923 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3924 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3925 /* Passphrase has been set to channel */
3927 /* Get the passphrase */
3928 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3931 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3935 /* Save the passphrase */
3936 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3939 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3940 /* Passphrase mode is unset. remove the passphrase */
3941 silc_free(channel->passphrase);
3942 channel->passphrase = NULL;
3946 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3947 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3948 /* Cipher to use protect the traffic */
3949 SilcCipher newkey, oldkey;
3952 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3955 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3959 /* Delete old cipher and allocate the new one */
3960 if (!silc_cipher_alloc(cipher, &newkey)) {
3961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3962 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3966 oldkey = channel->channel_key;
3967 channel->channel_key = newkey;
3969 /* Re-generate channel key */
3970 if (!silc_server_create_channel_key(server, channel, 0)) {
3971 /* We don't have new key, revert to old one */
3972 channel->channel_key = oldkey;
3976 /* Remove old channel key for good */
3977 silc_cipher_free(oldkey);
3979 /* Send the channel key. This sends it to our local clients and if
3980 we are normal server to our router as well. */
3981 silc_server_send_channel_key(server, NULL, channel,
3982 server->server_type == SILC_ROUTER ?
3983 FALSE : !server->standalone);
3986 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3987 /* Cipher mode is unset. Remove the cipher and revert back to
3989 SilcCipher newkey, oldkey;
3990 cipher = channel->cipher;
3992 /* Delete old cipher and allocate default one */
3993 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3994 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3995 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3999 oldkey = channel->channel_key;
4000 channel->channel_key = newkey;
4002 /* Re-generate channel key */
4003 if (!silc_server_create_channel_key(server, channel, 0)) {
4004 /* We don't have new key, revert to old one */
4005 channel->channel_key = oldkey;
4009 /* Remove old channel key for good */
4010 silc_cipher_free(oldkey);
4012 /* Send the channel key. This sends it to our local clients and if
4013 we are normal server to our router as well. */
4014 silc_server_send_channel_key(server, NULL, channel,
4015 server->server_type == SILC_ROUTER ?
4016 FALSE : !server->standalone);
4020 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4021 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4022 /* HMAC to use protect the traffic */
4023 unsigned char hash[32];
4027 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4030 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4034 /* Delete old hmac and allocate the new one */
4035 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4037 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4041 silc_hmac_free(channel->hmac);
4042 channel->hmac = newhmac;
4044 /* Set the HMAC key out of current channel key. The client must do
4046 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4047 channel->key_len / 8, hash);
4048 silc_hmac_set_key(channel->hmac, hash,
4049 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4050 memset(hash, 0, sizeof(hash));
4053 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4054 /* Hmac mode is unset. Remove the hmac and revert back to
4057 unsigned char hash[32];
4058 hmac = channel->hmac_name;
4060 /* Delete old hmac and allocate default one */
4061 silc_hmac_free(channel->hmac);
4062 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4064 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4068 silc_hmac_free(channel->hmac);
4069 channel->hmac = newhmac;
4071 /* Set the HMAC key out of current channel key. The client must do
4073 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4074 channel->key_len / 8,
4076 silc_hmac_set_key(channel->hmac, hash,
4077 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4078 memset(hash, 0, sizeof(hash));
4082 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4083 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4084 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4085 /* Set the founder authentication */
4086 SilcAuthPayload auth;
4088 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4091 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4095 auth = silc_auth_payload_parse(tmp, tmp_len);
4097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4098 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4102 /* Save the public key */
4103 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4104 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4107 channel->founder_method = silc_auth_get_method(auth);
4109 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4110 tmp = silc_auth_get_data(auth, &tmp_len);
4111 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4112 channel->founder_passwd_len = tmp_len;
4114 /* Verify the payload before setting the mode */
4115 if (!silc_auth_verify(auth, channel->founder_method,
4116 channel->founder_key, 0, idata->hash,
4117 client->id, SILC_ID_CLIENT)) {
4118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4119 SILC_STATUS_ERR_AUTH_FAILED);
4124 silc_auth_payload_free(auth);
4128 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4129 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4130 if (channel->founder_key)
4131 silc_pkcs_public_key_free(channel->founder_key);
4132 if (channel->founder_passwd) {
4133 silc_free(channel->founder_passwd);
4134 channel->founder_passwd = NULL;
4140 /* Finally, set the mode */
4141 channel->mode = mode_mask;
4143 /* Send CMODE_CHANGE notify. */
4144 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4145 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4146 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4147 cidp->data, cidp->len,
4149 cipher, cipher ? strlen(cipher) : 0,
4150 hmac, hmac ? strlen(hmac) : 0,
4151 passphrase, passphrase ?
4152 strlen(passphrase) : 0);
4154 /* Set CMODE notify type to network */
4155 if (!server->standalone)
4156 silc_server_send_notify_cmode(server, server->router->connection,
4157 server->server_type == SILC_ROUTER ?
4158 TRUE : FALSE, channel,
4159 mode_mask, client->id, SILC_ID_CLIENT,
4160 cipher, hmac, passphrase);
4162 /* Send command reply to sender */
4163 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4164 SILC_STATUS_OK, 0, ident, 2,
4165 2, tmp_id, tmp_len2,
4167 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4168 packet->data, packet->len, FALSE);
4170 silc_buffer_free(packet);
4171 silc_free(channel_id);
4172 silc_buffer_free(cidp);
4175 silc_server_command_free(cmd);
4178 /* Server side of CUMODE command. Changes client's mode on a channel. */
4180 SILC_SERVER_CMD_FUNC(cumode)
4182 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4183 SilcServer server = cmd->server;
4184 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4185 SilcIDListData idata = (SilcIDListData)client;
4186 SilcChannelID *channel_id;
4187 SilcClientID *client_id;
4188 SilcChannelEntry channel;
4189 SilcClientEntry target_client;
4190 SilcChannelClientEntry chl;
4191 SilcBuffer packet, idp;
4192 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4193 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4195 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4197 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4199 /* Get Channel ID */
4200 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4203 SILC_STATUS_ERR_NO_CHANNEL_ID);
4206 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4209 SILC_STATUS_ERR_NO_CHANNEL_ID);
4213 /* Get channel entry */
4214 channel = silc_idlist_find_channel_by_id(server->local_list,
4217 channel = silc_idlist_find_channel_by_id(server->global_list,
4220 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4221 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4226 /* Check whether sender is on the channel */
4227 if (!silc_server_client_on_channel(client, channel, &chl)) {
4228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4229 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4232 sender_mask = chl->mode;
4234 /* Get the target client's channel mode mask */
4235 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4238 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4241 SILC_GET32_MSB(target_mask, tmp_mask);
4243 /* Get target Client ID */
4244 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4247 SILC_STATUS_ERR_NO_CLIENT_ID);
4250 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_NO_CLIENT_ID);
4257 /* Get target client's entry */
4258 target_client = silc_idlist_find_client_by_id(server->local_list,
4259 client_id, TRUE, NULL);
4260 if (!target_client) {
4261 target_client = silc_idlist_find_client_by_id(server->global_list,
4262 client_id, TRUE, NULL);
4265 if (target_client != client &&
4266 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4267 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4269 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4273 /* Check whether target client is on the channel */
4274 if (target_client != client) {
4275 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4277 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4286 /* If the target client is founder, no one else can change their mode
4288 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4290 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4294 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4295 if (target_client != client) {
4296 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4297 SILC_STATUS_ERR_NOT_YOU);
4301 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4302 /* The client tries to claim the founder rights. */
4303 unsigned char *tmp_auth;
4304 SilcUInt32 tmp_auth_len, auth_len;
4307 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4308 !channel->founder_key || !idata->public_key ||
4309 !silc_pkcs_public_key_compare(channel->founder_key,
4310 idata->public_key)) {
4311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4312 SILC_STATUS_ERR_NOT_YOU);
4316 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4319 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4323 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4324 (void *)channel->founder_passwd : (void *)channel->founder_key);
4325 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4326 channel->founder_passwd_len : 0);
4328 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4329 channel->founder_method, auth, auth_len,
4330 idata->hash, client->id, SILC_ID_CLIENT)) {
4331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4332 SILC_STATUS_ERR_AUTH_FAILED);
4336 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4340 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4341 if (target_client == client) {
4342 /* Remove channel founder rights from itself */
4343 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4347 SILC_STATUS_ERR_NOT_YOU);
4353 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4354 /* Promote to operator */
4355 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4356 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4357 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4358 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4359 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4363 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4367 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4368 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4369 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4371 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4375 /* Demote to normal user */
4376 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4381 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4382 if (target_client != client) {
4383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4384 SILC_STATUS_ERR_NOT_YOU);
4388 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4389 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4393 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4394 if (target_client != client) {
4395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4396 SILC_STATUS_ERR_NOT_YOU);
4400 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4406 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4407 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4409 /* Send notify to channel, notify only if mode was actually changed. */
4411 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4412 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4413 idp->data, idp->len,
4417 /* Set CUMODE notify type to network */
4418 if (!server->standalone)
4419 silc_server_send_notify_cumode(server, server->router->connection,
4420 server->server_type == SILC_ROUTER ?
4421 TRUE : FALSE, channel,
4422 target_mask, client->id,
4427 /* Send command reply to sender */
4428 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4429 SILC_STATUS_OK, 0, ident, 3,
4431 3, tmp_ch_id, tmp_ch_len,
4432 4, tmp_id, tmp_len);
4433 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4434 packet->data, packet->len, FALSE);
4436 silc_buffer_free(packet);
4437 silc_free(channel_id);
4438 silc_free(client_id);
4439 silc_buffer_free(idp);
4442 silc_server_command_free(cmd);
4445 /* Server side of KICK command. Kicks client out of channel. */
4447 SILC_SERVER_CMD_FUNC(kick)
4449 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4450 SilcServer server = cmd->server;
4451 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4452 SilcClientEntry target_client;
4453 SilcChannelID *channel_id;
4454 SilcClientID *client_id;
4455 SilcChannelEntry channel;
4456 SilcChannelClientEntry chl;
4458 SilcUInt32 tmp_len, target_idp_len;
4459 unsigned char *tmp, *comment, *target_idp;
4461 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4463 /* Get Channel ID */
4464 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4467 SILC_STATUS_ERR_NO_CHANNEL_ID);
4470 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4473 SILC_STATUS_ERR_NO_CHANNEL_ID);
4477 /* Get channel entry */
4478 channel = silc_idlist_find_channel_by_id(server->local_list,
4481 channel = silc_idlist_find_channel_by_id(server->local_list,
4484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4485 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4490 /* Check whether sender is on the channel */
4491 if (!silc_server_client_on_channel(client, channel, &chl)) {
4492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4493 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4497 /* Check that the kicker is channel operator or channel founder */
4498 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4500 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4504 /* Get target Client ID */
4505 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4508 SILC_STATUS_ERR_NO_CLIENT_ID);
4511 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4514 SILC_STATUS_ERR_NO_CLIENT_ID);
4518 /* Get target client's entry */
4519 target_client = silc_idlist_find_client_by_id(server->local_list,
4520 client_id, TRUE, NULL);
4521 if (!target_client) {
4522 target_client = silc_idlist_find_client_by_id(server->global_list,
4523 client_id, TRUE, NULL);
4526 /* Check whether target client is on the channel */
4527 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4529 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4533 /* Check that the target client is not channel founder. Channel founder
4534 cannot be kicked from the channel. */
4535 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4537 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4543 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4547 /* Send command reply to sender */
4548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4551 /* Send KICKED notify to local clients on the channel */
4552 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4553 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4554 SILC_NOTIFY_TYPE_KICKED, 3,
4555 target_idp, target_idp_len,
4556 comment, comment ? strlen(comment) : 0,
4557 idp->data, idp->len);
4558 silc_buffer_free(idp);
4560 /* Remove the client from the channel. If the channel does not exist
4561 after removing the client then the client kicked itself off the channel
4562 and we don't have to send anything after that. */
4563 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4564 target_client, FALSE))
4567 /* Send KICKED notify to primary route */
4568 if (!server->standalone)
4569 silc_server_send_notify_kicked(server, server->router->connection,
4570 server->server_type == SILC_ROUTER ?
4571 TRUE : FALSE, channel,
4572 target_client->id, client->id, comment);
4574 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4575 /* Re-generate channel key */
4576 if (!silc_server_create_channel_key(server, channel, 0))
4579 /* Send the channel key to the channel. The key of course is not sent
4580 to the client who was kicked off the channel. */
4581 silc_server_send_channel_key(server, target_client->connection, channel,
4582 server->server_type == SILC_ROUTER ?
4583 FALSE : !server->standalone);
4587 silc_server_command_free(cmd);
4590 /* Server side of OPER command. Client uses this comand to obtain server
4591 operator privileges to this server/router. */
4593 SILC_SERVER_CMD_FUNC(oper)
4595 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4596 SilcServer server = cmd->server;
4597 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4598 unsigned char *username, *auth;
4600 SilcServerConfigAdmin *admin;
4601 SilcIDListData idata = (SilcIDListData)client;
4602 bool result = FALSE;
4603 SilcPublicKey cached_key;
4605 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4607 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4610 /* Get the username */
4611 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4613 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4614 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4618 /* Get the admin configuration */
4619 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4620 username, client->nickname);
4622 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4623 username, client->nickname);
4625 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4626 SILC_STATUS_ERR_AUTH_FAILED);
4631 /* Get the authentication payload */
4632 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4635 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4639 /* Verify the authentication data. If both passphrase and public key
4640 is set then try both of them. */
4641 if (admin->passphrase)
4642 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4643 admin->passphrase, admin->passphrase_len,
4644 idata->hash, client->id, SILC_ID_CLIENT);
4645 if (!result && admin->publickeys) {
4646 cached_key = silc_server_get_public_key(server, admin->publickeys);
4649 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4650 cached_key, 0, idata->hash,
4651 client->id, SILC_ID_CLIENT);
4654 /* Authentication failed */
4655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4656 SILC_STATUS_ERR_AUTH_FAILED);
4660 /* Client is now server operator */
4661 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4663 /* Update statistics */
4664 if (client->connection)
4665 server->stat.my_server_ops++;
4666 if (server->server_type == SILC_ROUTER)
4667 server->stat.server_ops++;
4669 /* Send UMODE change to primary router */
4670 if (!server->standalone)
4671 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4672 client->id, client->mode);
4674 /* Send reply to the sender */
4675 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4679 silc_server_command_free(cmd);
4682 /* Server side of SILCOPER command. Client uses this comand to obtain router
4683 operator privileges to this router. */
4685 SILC_SERVER_CMD_FUNC(silcoper)
4687 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4688 SilcServer server = cmd->server;
4689 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4690 unsigned char *username, *auth;
4692 SilcServerConfigAdmin *admin;
4693 SilcIDListData idata = (SilcIDListData)client;
4694 bool result = FALSE;
4695 SilcPublicKey cached_key;
4697 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4699 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4702 if (server->server_type != SILC_ROUTER) {
4703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4704 SILC_STATUS_ERR_AUTH_FAILED);
4708 /* Get the username */
4709 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4712 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4716 /* Get the admin configuration */
4717 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4718 username, client->nickname);
4720 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4721 username, client->nickname);
4723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4724 SILC_STATUS_ERR_AUTH_FAILED);
4729 /* Get the authentication payload */
4730 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4732 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4733 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4737 /* Verify the authentication data. If both passphrase and public key
4738 is set then try both of them. */
4739 if (admin->passphrase)
4740 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4741 admin->passphrase, admin->passphrase_len,
4742 idata->hash, client->id, SILC_ID_CLIENT);
4743 if (!result && admin->publickeys) {
4744 cached_key = silc_server_get_public_key(server, admin->publickeys);
4747 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4748 cached_key, 0, idata->hash,
4749 client->id, SILC_ID_CLIENT);
4752 /* Authentication failed */
4753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4754 SILC_STATUS_ERR_AUTH_FAILED);
4758 /* Client is now router operator */
4759 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4761 /* Update statistics */
4762 if (client->connection)
4763 server->stat.my_router_ops++;
4764 if (server->server_type == SILC_ROUTER)
4765 server->stat.router_ops++;
4767 /* Send UMODE change to primary router */
4768 if (!server->standalone)
4769 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4770 client->id, client->mode);
4772 /* Send reply to the sender */
4773 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4777 silc_server_command_free(cmd);
4780 /* Server side of command BAN. This is used to manage the ban list of the
4781 channel. To add clients and remove clients from the ban list. */
4783 SILC_SERVER_CMD_FUNC(ban)
4785 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4786 SilcServer server = cmd->server;
4787 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4789 SilcChannelEntry channel;
4790 SilcChannelClientEntry chl;
4791 SilcChannelID *channel_id = NULL;
4792 unsigned char *id, *add, *del;
4793 SilcUInt32 id_len, tmp_len;
4794 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4796 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4799 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4801 /* Get Channel ID */
4802 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4804 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4807 SILC_STATUS_ERR_NO_CHANNEL_ID);
4812 /* Get channel entry. The server must know about the channel since the
4813 client is expected to be on the channel. */
4814 channel = silc_idlist_find_channel_by_id(server->local_list,
4817 channel = silc_idlist_find_channel_by_id(server->global_list,
4820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4821 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4826 /* Check whether this client is on the channel */
4827 if (!silc_server_client_on_channel(client, channel, &chl)) {
4828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4829 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4833 /* The client must be at least channel operator. */
4834 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4836 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4840 /* Get the new ban and add it to the ban list */
4841 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4843 if (!channel->ban_list)
4844 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4846 channel->ban_list = silc_realloc(channel->ban_list,
4847 sizeof(*channel->ban_list) *
4849 strlen(channel->ban_list) + 2));
4850 if (add[tmp_len - 1] == ',')
4851 add[tmp_len - 1] = '\0';
4853 strncat(channel->ban_list, add, tmp_len);
4854 strncat(channel->ban_list, ",", 1);
4857 /* Get the ban to be removed and remove it from the list */
4858 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4859 if (del && channel->ban_list) {
4860 char *start, *end, *n;
4862 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4863 silc_free(channel->ban_list);
4864 channel->ban_list = NULL;
4866 start = strstr(channel->ban_list, del);
4867 if (start && strlen(start) >= tmp_len) {
4868 end = start + tmp_len;
4869 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4870 strncat(n, channel->ban_list, start - channel->ban_list);
4871 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4873 silc_free(channel->ban_list);
4874 channel->ban_list = n;
4879 /* Send the BAN notify type to our primary router. */
4880 if (!server->standalone && (add || del))
4881 silc_server_send_notify_ban(server, server->router->connection,
4882 server->server_type == SILC_ROUTER ?
4883 TRUE : FALSE, channel, add, del);
4885 /* Send the reply back to the client */
4887 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4888 SILC_STATUS_OK, 0, ident, 2,
4890 3, channel->ban_list,
4892 strlen(channel->ban_list) -1 : 0);
4893 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4894 packet->data, packet->len, FALSE);
4896 silc_buffer_free(packet);
4899 silc_free(channel_id);
4900 silc_server_command_free(cmd);
4903 /* Server side command of LEAVE. Removes client from a channel. */
4905 SILC_SERVER_CMD_FUNC(leave)
4907 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4908 SilcServer server = cmd->server;
4909 SilcSocketConnection sock = cmd->sock;
4910 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4911 SilcChannelID *id = NULL;
4912 SilcChannelEntry channel;
4916 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4918 /* Get Channel ID */
4919 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4922 SILC_STATUS_ERR_NO_CHANNEL_ID);
4925 id = silc_id_payload_parse_id(tmp, len, NULL);
4927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4928 SILC_STATUS_ERR_NO_CHANNEL_ID);
4932 /* Get channel entry */
4933 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4935 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4938 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4943 /* Check whether this client is on the channel */
4944 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4945 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4946 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4950 /* Notify routers that they should remove this client from their list
4951 of clients on the channel. Send LEAVE notify type. */
4952 if (!server->standalone)
4953 silc_server_send_notify_leave(server, server->router->connection,
4954 server->server_type == SILC_ROUTER ?
4955 TRUE : FALSE, channel, id_entry->id);
4957 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4958 SILC_STATUS_OK, 2, tmp, len);
4960 /* Remove client from channel */
4961 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4963 /* If the channel does not exist anymore we won't send anything */
4966 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4967 /* Re-generate channel key */
4968 if (!silc_server_create_channel_key(server, channel, 0))
4971 /* Send the channel key */
4972 silc_server_send_channel_key(server, NULL, channel,
4973 server->server_type == SILC_ROUTER ?
4974 FALSE : !server->standalone);
4979 silc_server_command_free(cmd);
4982 /* Server side of command USERS. Resolves clients and their USERS currently
4983 joined on the requested channel. The list of Client ID's and their modes
4984 on the channel is sent back. */
4986 SILC_SERVER_CMD_FUNC(users)
4988 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4989 SilcServer server = cmd->server;
4990 SilcChannelEntry channel;
4991 SilcChannelID *id = NULL;
4992 SilcBuffer packet, idp;
4993 unsigned char *channel_id;
4994 SilcUInt32 channel_id_len;
4995 SilcBuffer client_id_list;
4996 SilcBuffer client_mode_list;
4997 unsigned char lc[4];
4998 SilcUInt32 list_count = 0;
4999 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5002 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5004 /* Get Channel ID */
5005 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5007 /* Get channel name */
5008 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5010 if (!channel_id && !channel_name) {
5011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5012 SILC_STATUS_ERR_NO_CHANNEL_ID);
5017 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5020 SILC_STATUS_ERR_NO_CHANNEL_ID);
5025 /* If we are server and we don't know about this channel we will send
5026 the command to our router. If we know about the channel then we also
5027 have the list of users already. */
5029 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5031 channel = silc_idlist_find_channel_by_name(server->local_list,
5032 channel_name, NULL);
5034 if (!channel || channel->disabled) {
5035 if (server->server_type != SILC_ROUTER && !server->standalone &&
5039 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5040 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5042 /* Send USERS command */
5043 silc_server_packet_send(server, server->router->connection,
5044 SILC_PACKET_COMMAND, cmd->packet->flags,
5045 tmpbuf->data, tmpbuf->len, TRUE);
5047 /* Reprocess this packet after received reply */
5048 silc_server_command_pending(server, SILC_COMMAND_USERS,
5049 silc_command_get_ident(cmd->payload),
5050 silc_server_command_users,
5051 silc_server_command_dup(cmd));
5052 cmd->pending = TRUE;
5053 silc_command_set_ident(cmd->payload, ident);
5054 silc_buffer_free(tmpbuf);
5059 /* Check the global list as well. */
5061 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5063 channel = silc_idlist_find_channel_by_name(server->global_list,
5064 channel_name, NULL);
5066 /* Channel really does not exist */
5067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5068 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5073 /* If the channel is private or secret do not send anything, unless the
5074 user requesting this command is on the channel. */
5075 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5076 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5077 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5080 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5085 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5087 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5092 /* Get the users list */
5093 silc_server_get_users_on_channel(server, channel, &client_id_list,
5094 &client_mode_list, &list_count);
5097 SILC_PUT32_MSB(list_count, lc);
5100 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5101 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5102 SILC_STATUS_OK, 0, ident, 4,
5103 2, idp->data, idp->len,
5105 4, client_id_list->data,
5106 client_id_list->len,
5107 5, client_mode_list->data,
5108 client_mode_list->len);
5109 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5110 packet->data, packet->len, FALSE);
5112 silc_buffer_free(idp);
5113 silc_buffer_free(packet);
5114 silc_buffer_free(client_id_list);
5115 silc_buffer_free(client_mode_list);
5119 silc_server_command_free(cmd);
5122 /* Server side of command GETKEY. This fetches the client's public key
5123 from the server where to the client is connected. */
5125 SILC_SERVER_CMD_FUNC(getkey)
5127 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5128 SilcServer server = cmd->server;
5130 SilcClientEntry client;
5131 SilcServerEntry server_entry;
5132 SilcClientID *client_id = NULL;
5133 SilcServerID *server_id = NULL;
5134 SilcIDPayload idp = NULL;
5135 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5136 unsigned char *tmp, *pkdata;
5137 SilcUInt32 tmp_len, pklen;
5138 SilcBuffer pk = NULL;
5140 SilcPublicKey public_key;
5142 SILC_LOG_DEBUG(("Start"));
5144 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5146 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5147 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5150 idp = silc_id_payload_parse(tmp, tmp_len);
5152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5153 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5157 id_type = silc_id_payload_get_type(idp);
5158 if (id_type == SILC_ID_CLIENT) {
5159 client_id = silc_id_payload_get_id(idp);
5161 /* If the client is not found from local list there is no chance it
5162 would be locally connected client so send the command further. */
5163 client = silc_idlist_find_client_by_id(server->local_list,
5164 client_id, TRUE, NULL);
5166 client = silc_idlist_find_client_by_id(server->global_list,
5167 client_id, TRUE, NULL);
5169 if ((!client && !cmd->pending && !server->standalone) ||
5170 (client && !client->connection && !cmd->pending) ||
5171 (client && !client->data.public_key && !cmd->pending)) {
5173 SilcUInt16 old_ident;
5174 SilcSocketConnection dest_sock;
5176 dest_sock = silc_server_get_client_route(server, NULL, 0,
5177 client_id, NULL, NULL);
5181 old_ident = silc_command_get_ident(cmd->payload);
5182 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5183 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5185 silc_server_packet_send(server, dest_sock,
5186 SILC_PACKET_COMMAND, cmd->packet->flags,
5187 tmpbuf->data, tmpbuf->len, TRUE);
5189 /* Reprocess this packet after received reply from router */
5190 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5191 silc_command_get_ident(cmd->payload),
5192 silc_server_command_getkey,
5193 silc_server_command_dup(cmd));
5194 cmd->pending = TRUE;
5195 silc_command_set_ident(cmd->payload, old_ident);
5196 silc_buffer_free(tmpbuf);
5201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5202 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5206 /* The client is locally connected, just get the public key and
5207 send it back. If they key does not exist then do not send it,
5208 send just OK reply */
5209 public_key = client->data.public_key;
5214 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5215 pk = silc_buffer_alloc(4 + tmp_len);
5216 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5217 silc_buffer_format(pk,
5218 SILC_STR_UI_SHORT(tmp_len),
5219 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5220 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5226 } else if (id_type == SILC_ID_SERVER) {
5227 server_id = silc_id_payload_get_id(idp);
5229 /* If the server is not found from local list there is no chance it
5230 would be locally connected server so send the command further. */
5231 server_entry = silc_idlist_find_server_by_id(server->local_list,
5232 server_id, TRUE, NULL);
5234 server_entry = silc_idlist_find_server_by_id(server->global_list,
5235 server_id, TRUE, NULL);
5237 if (server_entry != server->id_entry &&
5238 ((!server_entry && !cmd->pending && !server->standalone) ||
5239 (server_entry && !server_entry->connection && !cmd->pending &&
5240 !server->standalone) ||
5241 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5242 !server->standalone))) {
5244 SilcUInt16 old_ident;
5246 old_ident = silc_command_get_ident(cmd->payload);
5247 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5248 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5250 silc_server_packet_send(server, server->router->connection,
5251 SILC_PACKET_COMMAND, cmd->packet->flags,
5252 tmpbuf->data, tmpbuf->len, TRUE);
5254 /* Reprocess this packet after received reply from router */
5255 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5256 silc_command_get_ident(cmd->payload),
5257 silc_server_command_getkey,
5258 silc_server_command_dup(cmd));
5259 cmd->pending = TRUE;
5260 silc_command_set_ident(cmd->payload, old_ident);
5261 silc_buffer_free(tmpbuf);
5265 if (!server_entry) {
5266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5267 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5271 /* If they key does not exist then do not send it, send just OK reply */
5272 public_key = (!server_entry->data.public_key ?
5273 (server_entry == server->id_entry ? server->public_key :
5274 NULL) : server_entry->data.public_key);
5279 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5280 pk = silc_buffer_alloc(4 + tmp_len);
5281 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5282 silc_buffer_format(pk,
5283 SILC_STR_UI_SHORT(tmp_len),
5284 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5285 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5295 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5296 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5297 SILC_STATUS_OK, 0, ident,
5301 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5302 packet->data, packet->len, FALSE);
5303 silc_buffer_free(packet);
5306 silc_buffer_free(pk);
5310 silc_id_payload_free(idp);
5311 silc_free(client_id);
5312 silc_free(server_id);
5313 silc_server_command_free(cmd);
5317 /* Private range commands, specific to this implementation */
5319 /* Server side command of CONNECT. Connects us to the specified remote
5320 server or router. */
5322 SILC_SERVER_CMD_FUNC(connect)
5324 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5325 SilcServer server = cmd->server;
5326 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5327 unsigned char *tmp, *host;
5329 SilcUInt32 port = SILC_PORT;
5331 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5333 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5336 /* Check whether client has the permissions. */
5337 if (client->mode == SILC_UMODE_NONE) {
5338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5339 SILC_STATUS_ERR_NO_SERVER_PRIV);
5343 if (server->server_type == SILC_ROUTER &&
5344 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5346 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5350 /* Get the remote server */
5351 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5354 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5359 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5361 SILC_GET32_MSB(port, tmp);
5363 /* Create the connection. It is done with timeout and is async. */
5364 silc_server_create_connection(server, host, port);
5366 /* Send reply to the sender */
5367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5371 silc_server_command_free(cmd);
5374 /* Server side command of CLOSE. Closes connection to a specified server. */
5376 SILC_SERVER_CMD_FUNC(close)
5378 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5379 SilcServer server = cmd->server;
5380 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5381 SilcServerEntry server_entry;
5382 SilcSocketConnection sock;
5385 unsigned char *name;
5386 SilcUInt32 port = SILC_PORT;
5388 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5390 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5393 /* Check whether client has the permissions. */
5394 if (client->mode == SILC_UMODE_NONE) {
5395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5396 SILC_STATUS_ERR_NO_SERVER_PRIV);
5400 /* Get the remote server */
5401 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5404 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5409 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5411 SILC_GET32_MSB(port, tmp);
5413 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5414 name, port, FALSE, NULL);
5416 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5417 name, port, FALSE, NULL);
5418 if (!server_entry) {
5419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5420 SILC_STATUS_ERR_NO_SERVER_ID);
5424 /* Send reply to the sender */
5425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5428 /* Close the connection to the server */
5429 sock = (SilcSocketConnection)server_entry->connection;
5431 /* If we shutdown primary router connection manually then don't trigger
5432 any reconnect or backup router connections, by setting the router
5434 if (server->router == server_entry) {
5435 server->id_entry->router = NULL;
5436 server->router = NULL;
5437 server->standalone = TRUE;
5439 silc_server_free_sock_user_data(server, sock, NULL);
5440 silc_server_close_connection(server, sock);
5443 silc_server_command_free(cmd);
5446 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5447 active connections. */
5449 SILC_SERVER_CMD_FUNC(shutdown)
5451 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5452 SilcServer server = cmd->server;
5453 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5455 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5457 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5460 /* Check whether client has the permission. */
5461 if (client->mode == SILC_UMODE_NONE) {
5462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5463 SILC_STATUS_ERR_NO_SERVER_PRIV);
5467 /* Send reply to the sender */
5468 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5471 /* Then, gracefully, or not, bring the server down. */
5472 silc_server_stop(server);
5476 silc_server_command_free(cmd);