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 = NULL;
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 = 0, tmp_len, tmp_len2;
3815 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3816 bool set_mask = FALSE;
3818 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3820 /* Get Channel ID */
3821 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3824 SILC_STATUS_ERR_NO_CHANNEL_ID);
3827 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3830 SILC_STATUS_ERR_NO_CHANNEL_ID);
3834 /* Get the channel mode mask */
3835 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3837 SILC_GET32_MSB(mode_mask, tmp_mask);
3841 /* Get channel entry */
3842 channel = silc_idlist_find_channel_by_id(server->local_list,
3845 channel = silc_idlist_find_channel_by_id(server->global_list,
3848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3849 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3854 /* Check whether this client is on the channel */
3855 if (!silc_server_client_on_channel(client, channel, &chl)) {
3856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3857 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3861 /* Check that client has rights to change any requested channel modes */
3862 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
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));
3871 /* If mode mask was not sent as argument then merely return the current
3872 mode mask to the sender. */
3875 SILC_PUT32_MSB(channel->mode, m);
3876 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3877 SILC_STATUS_OK, 0, ident, 2,
3878 2, tmp_id, tmp_len2,
3880 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3881 packet->data, packet->len, FALSE);
3882 silc_buffer_free(packet);
3887 * Check the modes. Modes that requires nothing special operation are
3891 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3892 /* Channel uses private keys to protect traffic. Client(s) has set the
3893 key locally they want to use, server does not know that key. */
3894 /* Nothing interesting to do here */
3896 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3897 /* The mode is removed and we need to generate and distribute
3898 new channel key. Clients are not using private channel keys
3899 anymore after this. */
3901 /* Re-generate channel key */
3902 if (!silc_server_create_channel_key(server, channel, 0))
3905 /* Send the channel key. This sends it to our local clients and if
3906 we are normal server to our router as well. */
3907 silc_server_send_channel_key(server, NULL, channel,
3908 server->server_type == SILC_ROUTER ?
3909 FALSE : !server->standalone);
3911 cipher = channel->channel_key->cipher->name;
3912 hmac = (char *)silc_hmac_get_name(channel->hmac);
3916 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3917 /* User limit is set on channel */
3918 SilcUInt32 user_limit;
3920 /* Get user limit */
3921 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3923 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3925 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3929 SILC_GET32_MSB(user_limit, tmp);
3930 channel->user_limit = user_limit;
3933 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3934 /* User limit mode is unset. Remove user limit */
3935 channel->user_limit = 0;
3938 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3939 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3940 /* Passphrase has been set to channel */
3942 /* Get the passphrase */
3943 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3945 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3946 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3950 /* Save the passphrase */
3951 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3954 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3955 /* Passphrase mode is unset. remove the passphrase */
3956 silc_free(channel->passphrase);
3957 channel->passphrase = NULL;
3961 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3962 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3963 /* Cipher to use protect the traffic */
3964 SilcCipher newkey, oldkey;
3967 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3970 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3974 /* Delete old cipher and allocate the new one */
3975 if (!silc_cipher_alloc(cipher, &newkey)) {
3976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3977 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3981 oldkey = channel->channel_key;
3982 channel->channel_key = newkey;
3984 /* Re-generate channel key */
3985 if (!silc_server_create_channel_key(server, channel, 0)) {
3986 /* We don't have new key, revert to old one */
3987 channel->channel_key = oldkey;
3991 /* Remove old channel key for good */
3992 silc_cipher_free(oldkey);
3994 /* Send the channel key. This sends it to our local clients and if
3995 we are normal server to our router as well. */
3996 silc_server_send_channel_key(server, NULL, channel,
3997 server->server_type == SILC_ROUTER ?
3998 FALSE : !server->standalone);
4001 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4002 /* Cipher mode is unset. Remove the cipher and revert back to
4004 SilcCipher newkey, oldkey;
4005 cipher = channel->cipher;
4007 /* Delete old cipher and allocate default one */
4008 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4010 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4014 oldkey = channel->channel_key;
4015 channel->channel_key = newkey;
4017 /* Re-generate channel key */
4018 if (!silc_server_create_channel_key(server, channel, 0)) {
4019 /* We don't have new key, revert to old one */
4020 channel->channel_key = oldkey;
4024 /* Remove old channel key for good */
4025 silc_cipher_free(oldkey);
4027 /* Send the channel key. This sends it to our local clients and if
4028 we are normal server to our router as well. */
4029 silc_server_send_channel_key(server, NULL, channel,
4030 server->server_type == SILC_ROUTER ?
4031 FALSE : !server->standalone);
4035 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4036 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4037 /* HMAC to use protect the traffic */
4038 unsigned char hash[32];
4042 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4045 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4049 /* Delete old hmac and allocate the new one */
4050 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4052 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4056 silc_hmac_free(channel->hmac);
4057 channel->hmac = newhmac;
4059 /* Set the HMAC key out of current channel key. The client must do
4061 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4062 channel->key_len / 8, hash);
4063 silc_hmac_set_key(channel->hmac, hash,
4064 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4065 memset(hash, 0, sizeof(hash));
4068 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4069 /* Hmac mode is unset. Remove the hmac and revert back to
4072 unsigned char hash[32];
4073 hmac = channel->hmac_name;
4075 /* Delete old hmac and allocate default one */
4076 silc_hmac_free(channel->hmac);
4077 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4079 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4083 silc_hmac_free(channel->hmac);
4084 channel->hmac = newhmac;
4086 /* Set the HMAC key out of current channel key. The client must do
4088 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4089 channel->key_len / 8,
4091 silc_hmac_set_key(channel->hmac, hash,
4092 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4093 memset(hash, 0, sizeof(hash));
4097 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4098 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4099 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4100 /* Set the founder authentication */
4101 SilcAuthPayload auth;
4103 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4105 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4106 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4110 auth = silc_auth_payload_parse(tmp, tmp_len);
4112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4113 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4117 /* Save the public key */
4118 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4119 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4122 channel->founder_method = silc_auth_get_method(auth);
4124 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4125 tmp = silc_auth_get_data(auth, &tmp_len);
4126 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4127 channel->founder_passwd_len = tmp_len;
4129 /* Verify the payload before setting the mode */
4130 if (!silc_auth_verify(auth, channel->founder_method,
4131 channel->founder_key, 0, idata->hash,
4132 client->id, SILC_ID_CLIENT)) {
4133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4134 SILC_STATUS_ERR_AUTH_FAILED);
4139 silc_auth_payload_free(auth);
4143 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4144 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4145 if (channel->founder_key)
4146 silc_pkcs_public_key_free(channel->founder_key);
4147 if (channel->founder_passwd) {
4148 silc_free(channel->founder_passwd);
4149 channel->founder_passwd = NULL;
4155 /* Finally, set the mode */
4156 channel->mode = mode_mask;
4158 /* Send CMODE_CHANGE notify. */
4159 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4160 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4161 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4162 cidp->data, cidp->len,
4164 cipher, cipher ? strlen(cipher) : 0,
4165 hmac, hmac ? strlen(hmac) : 0,
4166 passphrase, passphrase ?
4167 strlen(passphrase) : 0);
4169 /* Set CMODE notify type to network */
4170 if (!server->standalone)
4171 silc_server_send_notify_cmode(server, server->router->connection,
4172 server->server_type == SILC_ROUTER ?
4173 TRUE : FALSE, channel,
4174 mode_mask, client->id, SILC_ID_CLIENT,
4175 cipher, hmac, passphrase);
4177 /* Send command reply to sender */
4178 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4179 SILC_STATUS_OK, 0, ident, 2,
4180 2, tmp_id, tmp_len2,
4182 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4183 packet->data, packet->len, FALSE);
4185 silc_buffer_free(packet);
4186 silc_buffer_free(cidp);
4189 silc_free(channel_id);
4190 silc_server_command_free(cmd);
4193 /* Server side of CUMODE command. Changes client's mode on a channel. */
4195 SILC_SERVER_CMD_FUNC(cumode)
4197 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4198 SilcServer server = cmd->server;
4199 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4200 SilcIDListData idata = (SilcIDListData)client;
4201 SilcChannelID *channel_id;
4202 SilcClientID *client_id;
4203 SilcChannelEntry channel;
4204 SilcClientEntry target_client;
4205 SilcChannelClientEntry chl;
4206 SilcBuffer packet, idp;
4207 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4208 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4210 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4212 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4214 /* Get Channel ID */
4215 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4218 SILC_STATUS_ERR_NO_CHANNEL_ID);
4221 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4224 SILC_STATUS_ERR_NO_CHANNEL_ID);
4228 /* Get channel entry */
4229 channel = silc_idlist_find_channel_by_id(server->local_list,
4232 channel = silc_idlist_find_channel_by_id(server->global_list,
4235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4236 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4241 /* Check whether sender is on the channel */
4242 if (!silc_server_client_on_channel(client, channel, &chl)) {
4243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4244 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4247 sender_mask = chl->mode;
4249 /* Get the target client's channel mode mask */
4250 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4256 SILC_GET32_MSB(target_mask, tmp_mask);
4258 /* Get target Client ID */
4259 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4262 SILC_STATUS_ERR_NO_CLIENT_ID);
4265 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4268 SILC_STATUS_ERR_NO_CLIENT_ID);
4272 /* Get target client's entry */
4273 target_client = silc_idlist_find_client_by_id(server->local_list,
4274 client_id, TRUE, NULL);
4275 if (!target_client) {
4276 target_client = silc_idlist_find_client_by_id(server->global_list,
4277 client_id, TRUE, NULL);
4280 if (target_client != client &&
4281 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4282 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4284 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4288 /* Check whether target client is on the channel */
4289 if (target_client != client) {
4290 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4292 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4301 /* If the target client is founder, no one else can change their mode
4303 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4305 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4309 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4310 if (target_client != client) {
4311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4312 SILC_STATUS_ERR_NOT_YOU);
4316 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4317 /* The client tries to claim the founder rights. */
4318 unsigned char *tmp_auth;
4319 SilcUInt32 tmp_auth_len, auth_len;
4322 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4323 !channel->founder_key || !idata->public_key ||
4324 !silc_pkcs_public_key_compare(channel->founder_key,
4325 idata->public_key)) {
4326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4327 SILC_STATUS_ERR_NOT_YOU);
4331 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4334 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4338 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4339 (void *)channel->founder_passwd : (void *)channel->founder_key);
4340 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4341 channel->founder_passwd_len : 0);
4343 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4344 channel->founder_method, auth, auth_len,
4345 idata->hash, client->id, SILC_ID_CLIENT)) {
4346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4347 SILC_STATUS_ERR_AUTH_FAILED);
4351 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4355 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4356 if (target_client == client) {
4357 /* Remove channel founder rights from itself */
4358 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4362 SILC_STATUS_ERR_NOT_YOU);
4368 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4369 /* Promote to operator */
4370 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4371 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4372 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4374 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4378 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4382 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4383 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4384 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4386 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4390 /* Demote to normal user */
4391 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4396 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4397 if (target_client != client) {
4398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4399 SILC_STATUS_ERR_NOT_YOU);
4403 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4404 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4408 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4409 if (target_client != client) {
4410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4411 SILC_STATUS_ERR_NOT_YOU);
4415 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4421 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4422 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4424 /* Send notify to channel, notify only if mode was actually changed. */
4426 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4427 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4428 idp->data, idp->len,
4432 /* Set CUMODE notify type to network */
4433 if (!server->standalone)
4434 silc_server_send_notify_cumode(server, server->router->connection,
4435 server->server_type == SILC_ROUTER ?
4436 TRUE : FALSE, channel,
4437 target_mask, client->id,
4442 /* Send command reply to sender */
4443 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4444 SILC_STATUS_OK, 0, ident, 3,
4446 3, tmp_ch_id, tmp_ch_len,
4447 4, tmp_id, tmp_len);
4448 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4449 packet->data, packet->len, FALSE);
4451 silc_buffer_free(packet);
4452 silc_free(channel_id);
4453 silc_free(client_id);
4454 silc_buffer_free(idp);
4457 silc_server_command_free(cmd);
4460 /* Server side of KICK command. Kicks client out of channel. */
4462 SILC_SERVER_CMD_FUNC(kick)
4464 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4465 SilcServer server = cmd->server;
4466 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4467 SilcClientEntry target_client;
4468 SilcChannelID *channel_id;
4469 SilcClientID *client_id;
4470 SilcChannelEntry channel;
4471 SilcChannelClientEntry chl;
4473 SilcUInt32 tmp_len, target_idp_len;
4474 unsigned char *tmp, *comment, *target_idp;
4476 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4478 /* Get Channel ID */
4479 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4482 SILC_STATUS_ERR_NO_CHANNEL_ID);
4485 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4488 SILC_STATUS_ERR_NO_CHANNEL_ID);
4492 /* Get channel entry */
4493 channel = silc_idlist_find_channel_by_id(server->local_list,
4496 channel = silc_idlist_find_channel_by_id(server->local_list,
4499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4500 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4505 /* Check whether sender is on the channel */
4506 if (!silc_server_client_on_channel(client, channel, &chl)) {
4507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4508 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4512 /* Check that the kicker is channel operator or channel founder */
4513 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4515 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4519 /* Get target Client ID */
4520 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4523 SILC_STATUS_ERR_NO_CLIENT_ID);
4526 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4529 SILC_STATUS_ERR_NO_CLIENT_ID);
4533 /* Get target client's entry */
4534 target_client = silc_idlist_find_client_by_id(server->local_list,
4535 client_id, TRUE, NULL);
4536 if (!target_client) {
4537 target_client = silc_idlist_find_client_by_id(server->global_list,
4538 client_id, TRUE, NULL);
4541 /* Check whether target client is on the channel */
4542 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4543 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4544 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4548 /* Check that the target client is not channel founder. Channel founder
4549 cannot be kicked from the channel. */
4550 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4552 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4558 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4562 /* Send command reply to sender */
4563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4566 /* Send KICKED notify to local clients on the channel */
4567 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4568 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4569 SILC_NOTIFY_TYPE_KICKED, 3,
4570 target_idp, target_idp_len,
4571 comment, comment ? strlen(comment) : 0,
4572 idp->data, idp->len);
4573 silc_buffer_free(idp);
4575 /* Remove the client from the channel. If the channel does not exist
4576 after removing the client then the client kicked itself off the channel
4577 and we don't have to send anything after that. */
4578 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4579 target_client, FALSE))
4582 /* Send KICKED notify to primary route */
4583 if (!server->standalone)
4584 silc_server_send_notify_kicked(server, server->router->connection,
4585 server->server_type == SILC_ROUTER ?
4586 TRUE : FALSE, channel,
4587 target_client->id, client->id, comment);
4589 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4590 /* Re-generate channel key */
4591 if (!silc_server_create_channel_key(server, channel, 0))
4594 /* Send the channel key to the channel. The key of course is not sent
4595 to the client who was kicked off the channel. */
4596 silc_server_send_channel_key(server, target_client->connection, channel,
4597 server->server_type == SILC_ROUTER ?
4598 FALSE : !server->standalone);
4602 silc_server_command_free(cmd);
4605 /* Server side of OPER command. Client uses this comand to obtain server
4606 operator privileges to this server/router. */
4608 SILC_SERVER_CMD_FUNC(oper)
4610 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4611 SilcServer server = cmd->server;
4612 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4613 unsigned char *username, *auth;
4615 SilcServerConfigAdmin *admin;
4616 SilcIDListData idata = (SilcIDListData)client;
4617 bool result = FALSE;
4618 SilcPublicKey cached_key;
4620 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4622 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4625 /* Get the username */
4626 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4629 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4633 /* Get the admin configuration */
4634 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4635 username, client->nickname);
4637 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4638 username, client->nickname);
4640 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4641 SILC_STATUS_ERR_AUTH_FAILED);
4646 /* Get the authentication payload */
4647 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4650 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4654 /* Verify the authentication data. If both passphrase and public key
4655 is set then try both of them. */
4656 if (admin->passphrase)
4657 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4658 admin->passphrase, admin->passphrase_len,
4659 idata->hash, client->id, SILC_ID_CLIENT);
4660 if (!result && admin->publickeys) {
4661 cached_key = silc_server_get_public_key(server, admin->publickeys);
4664 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4665 cached_key, 0, idata->hash,
4666 client->id, SILC_ID_CLIENT);
4669 /* Authentication failed */
4670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4671 SILC_STATUS_ERR_AUTH_FAILED);
4675 /* Client is now server operator */
4676 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4678 /* Update statistics */
4679 if (client->connection)
4680 server->stat.my_server_ops++;
4681 if (server->server_type == SILC_ROUTER)
4682 server->stat.server_ops++;
4684 /* Send UMODE change to primary router */
4685 if (!server->standalone)
4686 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4687 client->id, client->mode);
4689 /* Send reply to the sender */
4690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4694 silc_server_command_free(cmd);
4697 /* Server side of SILCOPER command. Client uses this comand to obtain router
4698 operator privileges to this router. */
4700 SILC_SERVER_CMD_FUNC(silcoper)
4702 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4703 SilcServer server = cmd->server;
4704 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4705 unsigned char *username, *auth;
4707 SilcServerConfigAdmin *admin;
4708 SilcIDListData idata = (SilcIDListData)client;
4709 bool result = FALSE;
4710 SilcPublicKey cached_key;
4712 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4714 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4717 if (server->server_type != SILC_ROUTER) {
4718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4719 SILC_STATUS_ERR_AUTH_FAILED);
4723 /* Get the username */
4724 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4727 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4731 /* Get the admin configuration */
4732 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4733 username, client->nickname);
4735 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4736 username, client->nickname);
4738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4739 SILC_STATUS_ERR_AUTH_FAILED);
4744 /* Get the authentication payload */
4745 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4748 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4752 /* Verify the authentication data. If both passphrase and public key
4753 is set then try both of them. */
4754 if (admin->passphrase)
4755 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4756 admin->passphrase, admin->passphrase_len,
4757 idata->hash, client->id, SILC_ID_CLIENT);
4758 if (!result && admin->publickeys) {
4759 cached_key = silc_server_get_public_key(server, admin->publickeys);
4762 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4763 cached_key, 0, idata->hash,
4764 client->id, SILC_ID_CLIENT);
4767 /* Authentication failed */
4768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4769 SILC_STATUS_ERR_AUTH_FAILED);
4773 /* Client is now router operator */
4774 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4776 /* Update statistics */
4777 if (client->connection)
4778 server->stat.my_router_ops++;
4779 if (server->server_type == SILC_ROUTER)
4780 server->stat.router_ops++;
4782 /* Send UMODE change to primary router */
4783 if (!server->standalone)
4784 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4785 client->id, client->mode);
4787 /* Send reply to the sender */
4788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4792 silc_server_command_free(cmd);
4795 /* Server side of command BAN. This is used to manage the ban list of the
4796 channel. To add clients and remove clients from the ban list. */
4798 SILC_SERVER_CMD_FUNC(ban)
4800 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4801 SilcServer server = cmd->server;
4802 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4804 SilcChannelEntry channel;
4805 SilcChannelClientEntry chl;
4806 SilcChannelID *channel_id = NULL;
4807 unsigned char *id, *add, *del;
4808 SilcUInt32 id_len, tmp_len;
4809 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4811 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4814 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4816 /* Get Channel ID */
4817 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4819 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4822 SILC_STATUS_ERR_NO_CHANNEL_ID);
4827 /* Get channel entry. The server must know about the channel since the
4828 client is expected to be on the channel. */
4829 channel = silc_idlist_find_channel_by_id(server->local_list,
4832 channel = silc_idlist_find_channel_by_id(server->global_list,
4835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4836 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4841 /* Check whether this client is on the channel */
4842 if (!silc_server_client_on_channel(client, channel, &chl)) {
4843 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4844 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4848 /* The client must be at least channel operator. */
4849 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4850 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4851 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4855 /* Get the new ban and add it to the ban list */
4856 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4858 if (!channel->ban_list)
4859 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4861 channel->ban_list = silc_realloc(channel->ban_list,
4862 sizeof(*channel->ban_list) *
4864 strlen(channel->ban_list) + 2));
4865 if (add[tmp_len - 1] == ',')
4866 add[tmp_len - 1] = '\0';
4868 strncat(channel->ban_list, add, tmp_len);
4869 strncat(channel->ban_list, ",", 1);
4872 /* Get the ban to be removed and remove it from the list */
4873 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4874 if (del && channel->ban_list) {
4875 char *start, *end, *n;
4877 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4878 silc_free(channel->ban_list);
4879 channel->ban_list = NULL;
4881 start = strstr(channel->ban_list, del);
4882 if (start && strlen(start) >= tmp_len) {
4883 end = start + tmp_len;
4884 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4885 strncat(n, channel->ban_list, start - channel->ban_list);
4886 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4888 silc_free(channel->ban_list);
4889 channel->ban_list = n;
4894 /* Send the BAN notify type to our primary router. */
4895 if (!server->standalone && (add || del))
4896 silc_server_send_notify_ban(server, server->router->connection,
4897 server->server_type == SILC_ROUTER ?
4898 TRUE : FALSE, channel, add, del);
4900 /* Send the reply back to the client */
4902 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4903 SILC_STATUS_OK, 0, ident, 2,
4905 3, channel->ban_list,
4907 strlen(channel->ban_list) -1 : 0);
4908 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4909 packet->data, packet->len, FALSE);
4911 silc_buffer_free(packet);
4914 silc_free(channel_id);
4915 silc_server_command_free(cmd);
4918 /* Server side command of LEAVE. Removes client from a channel. */
4920 SILC_SERVER_CMD_FUNC(leave)
4922 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4923 SilcServer server = cmd->server;
4924 SilcSocketConnection sock = cmd->sock;
4925 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4926 SilcChannelID *id = NULL;
4927 SilcChannelEntry channel;
4931 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4933 /* Get Channel ID */
4934 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4937 SILC_STATUS_ERR_NO_CHANNEL_ID);
4940 id = silc_id_payload_parse_id(tmp, len, NULL);
4942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4943 SILC_STATUS_ERR_NO_CHANNEL_ID);
4947 /* Get channel entry */
4948 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4950 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4953 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4958 /* Check whether this client is on the channel */
4959 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4961 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4965 /* Notify routers that they should remove this client from their list
4966 of clients on the channel. Send LEAVE notify type. */
4967 if (!server->standalone)
4968 silc_server_send_notify_leave(server, server->router->connection,
4969 server->server_type == SILC_ROUTER ?
4970 TRUE : FALSE, channel, id_entry->id);
4972 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4973 SILC_STATUS_OK, 2, tmp, len);
4975 /* Remove client from channel */
4976 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4978 /* If the channel does not exist anymore we won't send anything */
4981 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4982 /* Re-generate channel key */
4983 if (!silc_server_create_channel_key(server, channel, 0))
4986 /* Send the channel key */
4987 silc_server_send_channel_key(server, NULL, channel,
4988 server->server_type == SILC_ROUTER ?
4989 FALSE : !server->standalone);
4994 silc_server_command_free(cmd);
4997 /* Server side of command USERS. Resolves clients and their USERS currently
4998 joined on the requested channel. The list of Client ID's and their modes
4999 on the channel is sent back. */
5001 SILC_SERVER_CMD_FUNC(users)
5003 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5004 SilcServer server = cmd->server;
5005 SilcChannelEntry channel;
5006 SilcChannelID *id = NULL;
5007 SilcBuffer packet, idp;
5008 unsigned char *channel_id;
5009 SilcUInt32 channel_id_len;
5010 SilcBuffer client_id_list;
5011 SilcBuffer client_mode_list;
5012 unsigned char lc[4];
5013 SilcUInt32 list_count = 0;
5014 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5017 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5019 /* Get Channel ID */
5020 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5022 /* Get channel name */
5023 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5025 if (!channel_id && !channel_name) {
5026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5027 SILC_STATUS_ERR_NO_CHANNEL_ID);
5032 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5035 SILC_STATUS_ERR_NO_CHANNEL_ID);
5040 /* If we are server and we don't know about this channel we will send
5041 the command to our router. If we know about the channel then we also
5042 have the list of users already. */
5044 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5046 channel = silc_idlist_find_channel_by_name(server->local_list,
5047 channel_name, NULL);
5049 if (!channel || channel->disabled) {
5050 if (server->server_type != SILC_ROUTER && !server->standalone &&
5054 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5055 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5057 /* Send USERS command */
5058 silc_server_packet_send(server, server->router->connection,
5059 SILC_PACKET_COMMAND, cmd->packet->flags,
5060 tmpbuf->data, tmpbuf->len, TRUE);
5062 /* Reprocess this packet after received reply */
5063 silc_server_command_pending(server, SILC_COMMAND_USERS,
5064 silc_command_get_ident(cmd->payload),
5065 silc_server_command_users,
5066 silc_server_command_dup(cmd));
5067 cmd->pending = TRUE;
5068 silc_command_set_ident(cmd->payload, ident);
5069 silc_buffer_free(tmpbuf);
5074 /* Check the global list as well. */
5076 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5078 channel = silc_idlist_find_channel_by_name(server->global_list,
5079 channel_name, NULL);
5081 /* Channel really does not exist */
5082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5083 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5088 /* If the channel is private or secret do not send anything, unless the
5089 user requesting this command is on the channel. */
5090 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5091 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5092 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5095 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5100 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5102 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5107 /* Get the users list */
5108 silc_server_get_users_on_channel(server, channel, &client_id_list,
5109 &client_mode_list, &list_count);
5112 SILC_PUT32_MSB(list_count, lc);
5115 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5116 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5117 SILC_STATUS_OK, 0, ident, 4,
5118 2, idp->data, idp->len,
5120 4, client_id_list->data,
5121 client_id_list->len,
5122 5, client_mode_list->data,
5123 client_mode_list->len);
5124 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5125 packet->data, packet->len, FALSE);
5127 silc_buffer_free(idp);
5128 silc_buffer_free(packet);
5129 silc_buffer_free(client_id_list);
5130 silc_buffer_free(client_mode_list);
5134 silc_server_command_free(cmd);
5137 /* Server side of command GETKEY. This fetches the client's public key
5138 from the server where to the client is connected. */
5140 SILC_SERVER_CMD_FUNC(getkey)
5142 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5143 SilcServer server = cmd->server;
5145 SilcClientEntry client;
5146 SilcServerEntry server_entry;
5147 SilcClientID *client_id = NULL;
5148 SilcServerID *server_id = NULL;
5149 SilcIDPayload idp = NULL;
5150 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5151 unsigned char *tmp, *pkdata;
5152 SilcUInt32 tmp_len, pklen;
5153 SilcBuffer pk = NULL;
5155 SilcPublicKey public_key;
5157 SILC_LOG_DEBUG(("Start"));
5159 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5162 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5165 idp = silc_id_payload_parse(tmp, tmp_len);
5167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5168 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5172 id_type = silc_id_payload_get_type(idp);
5173 if (id_type == SILC_ID_CLIENT) {
5174 client_id = silc_id_payload_get_id(idp);
5176 /* If the client is not found from local list there is no chance it
5177 would be locally connected client so send the command further. */
5178 client = silc_idlist_find_client_by_id(server->local_list,
5179 client_id, TRUE, NULL);
5181 client = silc_idlist_find_client_by_id(server->global_list,
5182 client_id, TRUE, NULL);
5184 if ((!client && !cmd->pending && !server->standalone) ||
5185 (client && !client->connection && !cmd->pending) ||
5186 (client && !client->data.public_key && !cmd->pending)) {
5188 SilcUInt16 old_ident;
5189 SilcSocketConnection dest_sock;
5191 dest_sock = silc_server_get_client_route(server, NULL, 0,
5192 client_id, NULL, NULL);
5196 old_ident = silc_command_get_ident(cmd->payload);
5197 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5198 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5200 silc_server_packet_send(server, dest_sock,
5201 SILC_PACKET_COMMAND, cmd->packet->flags,
5202 tmpbuf->data, tmpbuf->len, TRUE);
5204 /* Reprocess this packet after received reply from router */
5205 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5206 silc_command_get_ident(cmd->payload),
5207 silc_server_command_getkey,
5208 silc_server_command_dup(cmd));
5209 cmd->pending = TRUE;
5210 silc_command_set_ident(cmd->payload, old_ident);
5211 silc_buffer_free(tmpbuf);
5216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5217 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5221 /* The client is locally connected, just get the public key and
5222 send it back. If they key does not exist then do not send it,
5223 send just OK reply */
5224 public_key = client->data.public_key;
5229 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5230 pk = silc_buffer_alloc(4 + tmp_len);
5231 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5232 silc_buffer_format(pk,
5233 SILC_STR_UI_SHORT(tmp_len),
5234 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5235 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5241 } else if (id_type == SILC_ID_SERVER) {
5242 server_id = silc_id_payload_get_id(idp);
5244 /* If the server is not found from local list there is no chance it
5245 would be locally connected server so send the command further. */
5246 server_entry = silc_idlist_find_server_by_id(server->local_list,
5247 server_id, TRUE, NULL);
5249 server_entry = silc_idlist_find_server_by_id(server->global_list,
5250 server_id, TRUE, NULL);
5252 if (server_entry != server->id_entry &&
5253 ((!server_entry && !cmd->pending && !server->standalone) ||
5254 (server_entry && !server_entry->connection && !cmd->pending &&
5255 !server->standalone) ||
5256 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5257 !server->standalone))) {
5259 SilcUInt16 old_ident;
5261 old_ident = silc_command_get_ident(cmd->payload);
5262 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5263 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5265 silc_server_packet_send(server, server->router->connection,
5266 SILC_PACKET_COMMAND, cmd->packet->flags,
5267 tmpbuf->data, tmpbuf->len, TRUE);
5269 /* Reprocess this packet after received reply from router */
5270 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5271 silc_command_get_ident(cmd->payload),
5272 silc_server_command_getkey,
5273 silc_server_command_dup(cmd));
5274 cmd->pending = TRUE;
5275 silc_command_set_ident(cmd->payload, old_ident);
5276 silc_buffer_free(tmpbuf);
5280 if (!server_entry) {
5281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5282 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5286 /* If they key does not exist then do not send it, send just OK reply */
5287 public_key = (!server_entry->data.public_key ?
5288 (server_entry == server->id_entry ? server->public_key :
5289 NULL) : server_entry->data.public_key);
5294 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5295 pk = silc_buffer_alloc(4 + tmp_len);
5296 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5297 silc_buffer_format(pk,
5298 SILC_STR_UI_SHORT(tmp_len),
5299 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5300 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5310 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5311 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5312 SILC_STATUS_OK, 0, ident,
5316 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5317 packet->data, packet->len, FALSE);
5318 silc_buffer_free(packet);
5321 silc_buffer_free(pk);
5325 silc_id_payload_free(idp);
5326 silc_free(client_id);
5327 silc_free(server_id);
5328 silc_server_command_free(cmd);
5332 /* Private range commands, specific to this implementation */
5334 /* Server side command of CONNECT. Connects us to the specified remote
5335 server or router. */
5337 SILC_SERVER_CMD_FUNC(connect)
5339 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5340 SilcServer server = cmd->server;
5341 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5342 unsigned char *tmp, *host;
5344 SilcUInt32 port = SILC_PORT;
5346 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5348 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5351 /* Check whether client has the permissions. */
5352 if (client->mode == SILC_UMODE_NONE) {
5353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5354 SILC_STATUS_ERR_NO_SERVER_PRIV);
5358 if (server->server_type == SILC_ROUTER &&
5359 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5361 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5365 /* Get the remote server */
5366 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5369 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5374 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5376 SILC_GET32_MSB(port, tmp);
5378 /* Create the connection. It is done with timeout and is async. */
5379 silc_server_create_connection(server, host, port);
5381 /* Send reply to the sender */
5382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5386 silc_server_command_free(cmd);
5389 /* Server side command of CLOSE. Closes connection to a specified server. */
5391 SILC_SERVER_CMD_FUNC(close)
5393 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5394 SilcServer server = cmd->server;
5395 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5396 SilcServerEntry server_entry;
5397 SilcSocketConnection sock;
5400 unsigned char *name;
5401 SilcUInt32 port = SILC_PORT;
5403 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5405 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5408 /* Check whether client has the permissions. */
5409 if (client->mode == SILC_UMODE_NONE) {
5410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5411 SILC_STATUS_ERR_NO_SERVER_PRIV);
5415 /* Get the remote server */
5416 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5419 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5424 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5426 SILC_GET32_MSB(port, tmp);
5428 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5429 name, port, FALSE, NULL);
5431 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5432 name, port, FALSE, NULL);
5433 if (!server_entry) {
5434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5435 SILC_STATUS_ERR_NO_SERVER_ID);
5439 /* Send reply to the sender */
5440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5443 /* Close the connection to the server */
5444 sock = (SilcSocketConnection)server_entry->connection;
5446 /* If we shutdown primary router connection manually then don't trigger
5447 any reconnect or backup router connections, by setting the router
5449 if (server->router == server_entry) {
5450 server->id_entry->router = NULL;
5451 server->router = NULL;
5452 server->standalone = TRUE;
5454 silc_server_free_sock_user_data(server, sock, NULL);
5455 silc_server_close_connection(server, sock);
5458 silc_server_command_free(cmd);
5461 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5462 active connections. */
5464 SILC_SERVER_CMD_FUNC(shutdown)
5466 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5467 SilcServer server = cmd->server;
5468 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5470 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5472 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5475 /* Check whether client has the permission. */
5476 if (client->mode == SILC_UMODE_NONE) {
5477 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5478 SILC_STATUS_ERR_NO_SERVER_PRIV);
5482 /* Send reply to the sender */
5483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5486 /* Then, gracefully, or not, bring the server down. */
5487 silc_server_stop(server);
5491 silc_server_command_free(cmd);