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(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(silcoper, SILCOPER,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
72 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
73 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
74 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(connect, PRIV_CONNECT,
77 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
78 SILC_SERVER_CMD(close, PRIV_CLOSE,
79 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
80 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
86 /* Performs several checks to the command. It first checks whether this
87 command was called as pending command callback. If it was then it checks
88 whether error occurred in the command reply where the pending command
91 It also checks that the requested command includes correct amount
93 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
97 SILC_LOG_DEBUG(("Start")); \
99 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
100 silc_server_command_free(cmd); \
104 _argc = silc_argument_get_arg_num(cmd->args); \
106 silc_server_command_send_status_reply(cmd, command, \
107 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
108 silc_server_command_free(cmd); \
112 silc_server_command_send_status_reply(cmd, command, \
113 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
114 silc_server_command_free(cmd); \
119 /* Returns TRUE if the connection is registered. Unregistered connections
120 usually cannot send commands hence the check. */
122 static int silc_server_is_registered(SilcServer server,
123 SilcSocketConnection sock,
124 SilcServerCommandContext cmd,
127 SilcIDListData idata = (SilcIDListData)sock->user_data;
132 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
135 silc_server_command_send_status_reply(cmd, command,
136 SILC_STATUS_ERR_NOT_REGISTERED);
140 /* Internal context to hold data when executed command with timeout. */
142 SilcServerCommandContext ctx;
143 SilcServerCommand *cmd;
144 } *SilcServerCommandTimeout;
146 /* Timeout callback to process commands with timeout for client. Client's
147 commands are always executed with timeout. */
149 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
151 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
152 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
155 silc_server_command_free(timeout->ctx);
159 /* Update access time */
160 client->last_command = time(NULL);
162 if (!(timeout->cmd->flags & SILC_CF_REG))
163 timeout->cmd->cb(timeout->ctx, NULL);
164 else if (silc_server_is_registered(timeout->ctx->server,
168 timeout->cmd->cb(timeout->ctx, NULL);
170 silc_server_command_free(timeout->ctx);
175 /* Processes received command packet. */
177 void silc_server_command_process(SilcServer server,
178 SilcSocketConnection sock,
179 SilcPacketContext *packet)
181 SilcServerCommandContext ctx;
182 SilcServerCommand *cmd;
185 /* Allocate command context. This must be free'd by the
186 command routine receiving it. */
187 ctx = silc_server_command_alloc();
188 ctx->server = server;
189 ctx->sock = silc_socket_dup(sock);
190 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
192 /* Parse the command payload in the packet */
193 ctx->payload = silc_command_payload_parse(packet->buffer->data,
194 packet->buffer->len);
196 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
197 silc_buffer_free(packet->buffer);
198 silc_packet_context_free(packet);
199 silc_socket_free(ctx->sock);
203 ctx->args = silc_command_get_args(ctx->payload);
205 /* Get the command */
206 command = silc_command_get(ctx->payload);
207 for (cmd = silc_command_list; cmd->cb; cmd++)
208 if (cmd->cmd == command)
211 if (!cmd || !cmd->cb) {
212 silc_server_command_send_status_reply(ctx, command,
213 SILC_STATUS_ERR_UNKNOWN_COMMAND);
214 silc_server_command_free(ctx);
218 /* Execute client's commands always with timeout. Normally they are
219 executed with zero (0) timeout but if client is sending command more
220 frequently than once in 2 seconds, then the timeout may be 0 to 2
222 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
223 SilcClientEntry client = (SilcClientEntry)sock->user_data;
224 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
230 if (client->last_command && (time(NULL) - client->last_command) < 2) {
231 client->fast_command++;
234 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
235 client->fast_command--);
239 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
240 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
241 silc_schedule_task_add(server->schedule, sock->sock,
242 silc_server_command_process_timeout,
244 2 - (time(NULL) - client->last_command), 0,
245 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
247 silc_schedule_task_add(server->schedule, sock->sock,
248 silc_server_command_process_timeout,
249 (void *)timeout, 0, 1,
250 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
254 /* Execute for server */
256 if (!(cmd->flags & SILC_CF_REG))
258 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
261 silc_server_command_free(ctx);
264 /* Allocate Command Context */
266 SilcServerCommandContext silc_server_command_alloc()
268 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
273 /* Free's the command context allocated before executing the command */
275 void silc_server_command_free(SilcServerCommandContext ctx)
278 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
280 if (ctx->users < 1) {
282 silc_command_payload_free(ctx->payload);
284 silc_packet_context_free(ctx->packet);
286 silc_socket_free(ctx->sock); /* Decrease reference counter */
291 /* Duplicate Command Context by adding reference counter. The context won't
292 be free'd untill it hits zero. */
294 SilcServerCommandContext
295 silc_server_command_dup(SilcServerCommandContext ctx)
298 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
303 /* Add new pending command to be executed when reply to a command has been
304 received. The `reply_cmd' is the command that will call the `callback'
305 with `context' when reply has been received. It can be SILC_COMMAND_NONE
306 to match any command with the `ident'. If `ident' is non-zero
307 the `callback' will be executed when received reply with command
308 identifier `ident'. If there already exists pending command for the
309 specified command, ident, callback and context this function has no
312 bool silc_server_command_pending(SilcServer server,
313 SilcCommand reply_cmd,
315 SilcCommandCb callback,
318 SilcServerCommandPending *reply;
320 /* Check whether identical pending already exists for same command,
321 ident, callback and callback context. If it does then it would be
322 error to register it again. */
323 silc_dlist_start(server->pending_commands);
324 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
325 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
326 reply->callback == callback && reply->context == context)
330 reply = silc_calloc(1, sizeof(*reply));
331 reply->reply_cmd = reply_cmd;
332 reply->ident = ident;
333 reply->context = context;
334 reply->callback = callback;
335 silc_dlist_add(server->pending_commands, reply);
340 /* Deletes pending command by reply command type. */
342 void silc_server_command_pending_del(SilcServer server,
343 SilcCommand reply_cmd,
346 SilcServerCommandPending *r;
348 silc_dlist_start(server->pending_commands);
349 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
350 if (r->reply_cmd == reply_cmd && r->ident == ident) {
351 silc_dlist_del(server->pending_commands, r);
357 /* Checks for pending commands and marks callbacks to be called from
358 the command reply function. Returns TRUE if there were pending command. */
360 SilcServerCommandPendingCallbacks
361 silc_server_command_pending_check(SilcServer server,
362 SilcServerCommandReplyContext ctx,
365 SilcUInt32 *callbacks_count)
367 SilcServerCommandPending *r;
368 SilcServerCommandPendingCallbacks callbacks = NULL;
371 silc_dlist_start(server->pending_commands);
372 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
373 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
374 && r->ident == ident) {
375 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
376 callbacks[i].context = r->context;
377 callbacks[i].callback = r->callback;
383 *callbacks_count = i;
387 /* Sends simple status message as command reply packet */
390 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
392 SilcCommandStatus status)
396 SILC_LOG_DEBUG(("Sending command status %d", status));
399 silc_command_reply_payload_encode_va(command, status, 0,
400 silc_command_get_ident(cmd->payload),
402 silc_server_packet_send(cmd->server, cmd->sock,
403 SILC_PACKET_COMMAND_REPLY, 0,
404 buffer->data, buffer->len, FALSE);
405 silc_buffer_free(buffer);
408 /* Sends command status reply with one extra argument. The argument
409 type must be sent as argument. */
412 silc_server_command_send_status_data(SilcServerCommandContext cmd,
414 SilcCommandStatus status,
416 const unsigned char *arg,
421 SILC_LOG_DEBUG(("Sending command status %d", status));
424 silc_command_reply_payload_encode_va(command, status, 0,
425 silc_command_get_ident(cmd->payload),
426 1, arg_type, arg, arg_len);
427 silc_server_packet_send(cmd->server, cmd->sock,
428 SILC_PACKET_COMMAND_REPLY, 0,
429 buffer->data, buffer->len, FALSE);
430 silc_buffer_free(buffer);
433 /* This function can be called to check whether in the command reply
434 an error occurred. This function has no effect if this is called
435 when the command function was not called as pending command callback.
436 This returns TRUE if error had occurred. */
439 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
440 SilcServerCommandReplyContext cmdr,
443 if (!cmd->pending || !cmdr)
446 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
449 /* Send the same command reply payload */
450 silc_command_set_ident(cmdr->payload,
451 silc_command_get_ident(cmd->payload));
452 buffer = silc_command_payload_encode_payload(cmdr->payload);
453 silc_server_packet_send(cmd->server, cmd->sock,
454 SILC_PACKET_COMMAND_REPLY, 0,
455 buffer->data, buffer->len, FALSE);
456 silc_buffer_free(buffer);
463 /******************************************************************************
467 ******************************************************************************/
470 silc_server_command_whois_parse(SilcServerCommandContext cmd,
471 SilcClientID ***client_id,
472 SilcUInt32 *client_id_count,
480 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
483 /* If client ID is in the command it must be used instead of nickname */
484 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
486 /* No ID, get the nickname@server string and parse it. */
487 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
489 silc_parse_userfqdn(tmp, nickname, server_name);
491 silc_server_command_send_status_reply(cmd, command,
492 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
496 /* Command includes ID, we must use that. Also check whether the command
497 has more than one ID set - take them all. */
499 *client_id = silc_calloc(1, sizeof(**client_id));
500 (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
501 if ((*client_id)[0] == NULL) {
502 silc_free(*client_id);
503 silc_server_command_send_status_reply(cmd, command,
504 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
507 *client_id_count = 1;
509 /* Take all ID's from the command packet */
511 for (k = 1, i = 1; i < argc; i++) {
512 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
514 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
515 (*client_id_count + 1));
516 (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
517 if ((*client_id)[k] == NULL) {
518 /* Cleanup all and fail */
519 for (i = 0; i < *client_id_count; i++)
520 silc_free((*client_id)[i]);
521 silc_free(*client_id);
522 silc_server_command_send_status_reply(
524 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
527 (*client_id_count)++;
534 /* Get the max count of reply messages allowed */
535 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
544 /* Resolve context used by both WHOIS and IDENTIFY commands */
546 SilcServerEntry router;
548 unsigned char **res_argv;
549 SilcUInt32 *res_argv_lens;
550 SilcUInt32 *res_argv_types;
552 } *SilcServerResolveContext;
555 silc_server_command_whois_check(SilcServerCommandContext cmd,
556 SilcClientEntry *clients,
557 SilcUInt32 clients_count)
559 SilcServer server = cmd->server;
560 SilcClientEntry entry;
561 SilcServerResolveContext resolve = NULL, r = NULL;
562 SilcUInt32 resolve_count = 0;
566 SILC_LOG_DEBUG(("Start"));
568 for (i = 0; i < clients_count; i++) {
573 if ((entry->nickname && entry->username && entry->userinfo) ||
574 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
578 /* If we are normal server, and we've not resolved this client from
579 router and it is global client, we'll check whether it is on some
580 channel. If not then we cannot be sure about its validity, and
581 we'll resolve it from router. */
582 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
583 entry->connection || silc_hash_table_count(entry->channels))
587 /* We need to resolve this entry since it is not complete */
589 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
590 /* The entry is being resolved (and we are not the resolver) so attach
591 to the command reply and we're done with this one. */
592 silc_server_command_pending(server, SILC_COMMAND_NONE,
593 entry->resolve_cmd_ident,
594 silc_server_command_whois,
595 silc_server_command_dup(cmd));
598 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
599 /* We've resolved this and it still is not ready. We'll return
600 and are that this will be handled again after it is resolved. */
601 for (i = 0; i < resolve_count; i++) {
602 for (k = 0; k < r->res_argc; k++)
603 silc_free(r->res_argv[k]);
604 silc_free(r->res_argv);
605 silc_free(r->res_argv_lens);
606 silc_free(r->res_argv_types);
611 /* We'll resolve this client */
615 for (k = 0; k < resolve_count; k++) {
616 if (resolve[k].router == entry->router) {
623 resolve = silc_realloc(resolve, sizeof(*resolve) *
624 (resolve_count + 1));
625 r = &resolve[resolve_count];
626 memset(r, 0, sizeof(*r));
627 r->router = entry->router;
628 r->ident = ++server->cmd_ident;
632 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
634 r->res_argv_lens = silc_realloc(r->res_argv_lens,
635 sizeof(*r->res_argv_lens) *
637 r->res_argv_types = silc_realloc(r->res_argv_types,
638 sizeof(*r->res_argv_types) *
640 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
641 r->res_argv[r->res_argc] = silc_calloc(idp->len,
642 sizeof(**r->res_argv));
643 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
644 r->res_argv_lens[r->res_argc] = idp->len;
645 r->res_argv_types[r->res_argc] = r->res_argc + 3;
647 silc_buffer_free(idp);
649 entry->resolve_cmd_ident = r->ident;
650 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
651 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
656 /* Do the resolving */
657 for (i = 0; i < resolve_count; i++) {
662 /* Send WHOIS request. We send WHOIS since we're doing the requesting
663 now anyway so make it a good one. */
664 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
665 r->res_argc, r->res_argv,
669 silc_server_packet_send(server, r->router->connection,
670 SILC_PACKET_COMMAND, cmd->packet->flags,
671 res_cmd->data, res_cmd->len, FALSE);
673 /* Reprocess this packet after received reply */
674 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
676 silc_server_command_whois,
677 silc_server_command_dup(cmd));
680 silc_buffer_free(res_cmd);
681 for (k = 0; k < r->res_argc; k++)
682 silc_free(r->res_argv[k]);
683 silc_free(r->res_argv);
684 silc_free(r->res_argv_lens);
685 silc_free(r->res_argv_types);
694 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
695 SilcClientEntry *clients,
696 SilcUInt32 clients_count,
698 const char *nickname,
699 SilcClientID **client_ids)
701 SilcServer server = cmd->server;
703 int i, k, len, valid_count;
704 SilcBuffer packet, idp, channels;
705 SilcClientEntry entry;
706 SilcCommandStatus status;
707 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
708 char nh[256], uh[256];
709 unsigned char idle[4], mode[4];
710 unsigned char *fingerprint;
711 SilcSocketConnection hsock;
713 /* Process only valid clients and ignore those that are not registered. */
715 for (i = 0; i < clients_count; i++) {
716 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
723 /* No valid clients found, send error reply */
725 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
726 SILC_STATUS_ERR_NO_SUCH_NICK,
727 3, nickname, strlen(nickname));
728 } else if (client_ids && client_ids[0]) {
729 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
730 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
731 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
732 2, idp->data, idp->len);
733 silc_buffer_free(idp);
738 /* Start processing found clients. */
740 status = SILC_STATUS_LIST_START;
742 status = SILC_STATUS_OK;
744 for (i = 0, k = 0; i < clients_count; i++) {
750 status = SILC_STATUS_LIST_ITEM;
751 if (valid_count > 1 && k == valid_count - 1)
752 status = SILC_STATUS_LIST_END;
753 if (count && k - 1 == count)
754 status = SILC_STATUS_LIST_END;
756 /* Send WHOIS reply */
757 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
758 tmp = silc_argument_get_first_arg(cmd->args, NULL);
760 memset(uh, 0, sizeof(uh));
761 memset(nh, 0, sizeof(nh));
762 memset(idle, 0, sizeof(idle));
764 strncat(nh, entry->nickname, strlen(entry->nickname));
765 if (!strchr(entry->nickname, '@')) {
767 if (entry->servername) {
768 strncat(nh, entry->servername, strlen(entry->servername));
770 len = entry->router ? strlen(entry->router->server_name) :
771 strlen(server->server_name);
772 strncat(nh, entry->router ? entry->router->server_name :
773 server->server_name, len);
777 strncat(uh, entry->username, strlen(entry->username));
778 if (!strchr(entry->username, '@')) {
780 hsock = (SilcSocketConnection)entry->connection;
781 len = strlen(hsock->hostname);
782 strncat(uh, hsock->hostname, len);
785 channels = silc_server_get_client_channel_list(server, entry);
787 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
788 fingerprint = entry->data.fingerprint;
792 SILC_PUT32_MSB(entry->mode, mode);
794 if (entry->connection)
795 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,
2017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2018 SILC_STATUS_ERR_BAD_NICKNAME);
2021 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2024 /* Send notify about nickname change to our router. We send the new
2025 ID and ask to replace it with the old one. If we are router the
2026 packet is broadcasted. Send NICK_CHANGE notify. */
2027 if (!server->standalone)
2028 silc_server_send_notify_nick_change(server, server->router->connection,
2029 server->server_type == SILC_SERVER ?
2030 FALSE : TRUE, client->id,
2033 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2035 /* Remove old cache entry */
2036 silc_idcache_del_by_context(server->local_list->clients, client);
2039 silc_free(client->id);
2041 /* Save the nickname as this client is our local client */
2042 silc_free(client->nickname);
2044 client->nickname = strdup(nick);
2045 client->id = new_id;
2047 /* Update client cache */
2048 silc_idcache_add(server->local_list->clients, client->nickname,
2049 client->id, (void *)client, 0, NULL);
2051 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2053 /* Send NICK_CHANGE notify to the client's channels */
2054 silc_server_send_notify_on_channels(server, NULL, client,
2055 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2056 oidp->data, oidp->len,
2057 nidp->data, nidp->len,
2059 strlen(client->nickname));
2062 /* Send the new Client ID as reply command back to client */
2063 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2064 SILC_STATUS_OK, 0, ident, 1,
2065 2, nidp->data, nidp->len);
2066 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2067 0, packet->data, packet->len, FALSE);
2069 silc_buffer_free(packet);
2070 silc_buffer_free(nidp);
2072 silc_buffer_free(oidp);
2075 silc_server_command_free(cmd);
2078 /* Sends the LIST command reply */
2081 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2082 SilcChannelEntry *lch,
2083 SilcUInt32 lch_count,
2084 SilcChannelEntry *gch,
2085 SilcUInt32 gch_count)
2088 SilcBuffer packet, idp;
2089 SilcChannelEntry entry;
2090 SilcCommandStatus status;
2091 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2093 unsigned char usercount[4];
2095 int valid_lcount = 0, valid_rcount = 0;
2097 for (i = 0; i < lch_count; i++) {
2098 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2103 for (i = 0; i < gch_count; i++) {
2104 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2110 status = SILC_STATUS_OK;
2111 if ((lch_count + gch_count) > 1)
2112 status = SILC_STATUS_LIST_START;
2115 for (i = 0, k = 0; i < lch_count; i++) {
2121 status = SILC_STATUS_LIST_ITEM;
2122 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2123 status = SILC_STATUS_LIST_END;
2125 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2127 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2128 topic = "*private*";
2129 memset(usercount, 0, sizeof(usercount));
2131 topic = entry->topic;
2132 users = silc_hash_table_count(entry->user_list);
2133 SILC_PUT32_MSB(users, usercount);
2136 /* Send the reply */
2138 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2139 status, 0, ident, 4,
2140 2, idp->data, idp->len,
2141 3, entry->channel_name,
2142 strlen(entry->channel_name),
2143 4, topic, topic ? strlen(topic) : 0,
2145 silc_server_packet_send(cmd->server, cmd->sock,
2146 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2147 packet->len, FALSE);
2148 silc_buffer_free(packet);
2149 silc_buffer_free(idp);
2154 for (i = 0, k = 0; i < gch_count; i++) {
2160 status = SILC_STATUS_LIST_ITEM;
2161 if (valid_rcount > 1 && k == valid_rcount - 1)
2162 status = SILC_STATUS_LIST_END;
2164 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2166 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2167 topic = "*private*";
2168 memset(usercount, 0, sizeof(usercount));
2170 topic = entry->topic;
2171 users = entry->user_count;
2172 SILC_PUT32_MSB(users, usercount);
2175 /* Send the reply */
2177 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2178 status, 0, ident, 4,
2179 2, idp->data, idp->len,
2180 3, entry->channel_name,
2181 strlen(entry->channel_name),
2182 4, topic, topic ? strlen(topic) : 0,
2184 silc_server_packet_send(cmd->server, cmd->sock,
2185 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2186 packet->len, FALSE);
2187 silc_buffer_free(packet);
2188 silc_buffer_free(idp);
2193 /* Server side of LIST command. This lists the channel of the requested
2194 server. Secret channels are not listed. */
2196 SILC_SERVER_CMD_FUNC(list)
2198 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2199 SilcServer server = cmd->server;
2200 SilcChannelID *channel_id = NULL;
2203 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2204 SilcUInt32 lch_count = 0, gch_count = 0;
2206 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2208 /* If we are normal server, send the command to router, since we
2209 want to know all channels in the network. */
2210 if (!cmd->pending && server->server_type == SILC_SERVER &&
2211 !server->standalone) {
2213 SilcUInt16 old_ident;
2215 old_ident = silc_command_get_ident(cmd->payload);
2216 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2217 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2218 silc_server_packet_send(server, server->router->connection,
2219 SILC_PACKET_COMMAND, cmd->packet->flags,
2220 tmpbuf->data, tmpbuf->len, TRUE);
2222 /* Reprocess this packet after received reply from router */
2223 silc_server_command_pending(server, SILC_COMMAND_LIST,
2224 silc_command_get_ident(cmd->payload),
2225 silc_server_command_list,
2226 silc_server_command_dup(cmd));
2227 cmd->pending = TRUE;
2228 silc_command_set_ident(cmd->payload, old_ident);
2229 silc_buffer_free(tmpbuf);
2233 /* Get Channel ID */
2234 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2236 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2239 SILC_STATUS_ERR_NO_CHANNEL_ID);
2244 /* Get the channels from local list */
2245 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2248 /* Get the channels from global list */
2249 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2252 /* Send the reply */
2253 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2254 gchannels, gch_count);
2256 silc_free(lchannels);
2257 silc_free(gchannels);
2260 silc_server_command_free(cmd);
2263 /* Server side of TOPIC command. Sets topic for channel and/or returns
2264 current topic to client. */
2266 SILC_SERVER_CMD_FUNC(topic)
2268 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2269 SilcServer server = cmd->server;
2270 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2271 SilcChannelID *channel_id;
2272 SilcChannelEntry channel;
2273 SilcChannelClientEntry chl;
2274 SilcBuffer packet, idp;
2276 SilcUInt32 argc, tmp_len;
2277 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2279 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2281 argc = silc_argument_get_arg_num(cmd->args);
2283 /* Get Channel ID */
2284 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2287 SILC_STATUS_ERR_NO_CHANNEL_ID);
2290 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2293 SILC_STATUS_ERR_NO_CHANNEL_ID);
2297 /* Check whether the channel exists */
2298 channel = silc_idlist_find_channel_by_id(server->local_list,
2301 channel = silc_idlist_find_channel_by_id(server->global_list,
2304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2305 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2312 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2315 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2319 if (strlen(tmp) > 256) {
2320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2321 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2325 /* See whether the client is on channel and has rights to change topic */
2326 if (!silc_server_client_on_channel(client, channel, &chl)) {
2327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2328 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2332 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2333 channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2335 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2339 /* Set the topic for channel */
2340 silc_free(channel->topic);
2341 channel->topic = strdup(tmp);
2343 /* Send TOPIC_SET notify type to the network */
2344 if (!server->standalone)
2345 silc_server_send_notify_topic_set(server, server->router->connection,
2346 server->server_type == SILC_ROUTER ?
2347 TRUE : FALSE, channel,
2348 client->id, SILC_ID_CLIENT,
2351 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2353 /* Send notify about topic change to all clients on the channel */
2354 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2355 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2356 idp->data, idp->len,
2357 channel->topic, strlen(channel->topic));
2358 silc_buffer_free(idp);
2361 /* Send the topic to client as reply packet */
2362 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2363 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2364 SILC_STATUS_OK, 0, ident, 2,
2365 2, idp->data, idp->len,
2368 strlen(channel->topic) : 0);
2369 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2370 0, packet->data, packet->len, FALSE);
2372 silc_buffer_free(packet);
2373 silc_buffer_free(idp);
2374 silc_free(channel_id);
2377 silc_server_command_free(cmd);
2380 /* Server side of INVITE command. Invites some client to join some channel.
2381 This command is also used to manage the invite list of the channel. */
2383 SILC_SERVER_CMD_FUNC(invite)
2385 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2386 SilcServer server = cmd->server;
2387 SilcSocketConnection sock = cmd->sock, dest_sock;
2388 SilcChannelClientEntry chl;
2389 SilcClientEntry sender, dest;
2390 SilcClientID *dest_id = NULL;
2391 SilcChannelEntry channel;
2392 SilcChannelID *channel_id = NULL;
2393 SilcIDListData idata;
2394 SilcBuffer idp, idp2, packet;
2395 unsigned char *tmp, *add, *del;
2397 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2399 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2401 /* Get Channel ID */
2402 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2405 SILC_STATUS_ERR_NO_CHANNEL_ID);
2408 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2411 SILC_STATUS_ERR_NO_CHANNEL_ID);
2415 /* Get the channel entry */
2416 channel = silc_idlist_find_channel_by_id(server->local_list,
2419 channel = silc_idlist_find_channel_by_id(server->global_list,
2422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2423 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2428 /* Check whether the sender of this command is on the channel. */
2429 sender = (SilcClientEntry)sock->user_data;
2430 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2432 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2436 /* Check whether the channel is invite-only channel. If yes then the
2437 sender of this command must be at least channel operator. */
2438 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2439 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2441 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2445 /* Get destination client ID */
2446 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2451 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2454 SILC_STATUS_ERR_NO_CLIENT_ID);
2458 /* Get the client entry */
2459 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2461 if (server->server_type != SILC_SERVER || !resolve) {
2462 silc_server_command_send_status_reply(
2463 cmd, SILC_COMMAND_INVITE,
2464 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2468 /* The client info is being resolved. Reprocess this packet after
2469 receiving the reply to the query. */
2470 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2472 silc_server_command_invite,
2473 silc_server_command_dup(cmd));
2474 cmd->pending = TRUE;
2475 silc_free(channel_id);
2480 /* Check whether the requested client is already on the channel. */
2481 if (silc_server_client_on_channel(dest, channel, NULL)) {
2482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2483 SILC_STATUS_ERR_USER_ON_CHANNEL);
2487 /* Get route to the client */
2488 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2492 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2496 memset(invite, 0, sizeof(invite));
2497 strncat(invite, dest->nickname, strlen(dest->nickname));
2498 strncat(invite, "!", 1);
2499 strncat(invite, dest->username, strlen(dest->username));
2500 if (!strchr(dest->username, '@')) {
2501 strncat(invite, "@", 1);
2502 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2505 len = strlen(invite);
2506 if (!channel->invite_list)
2507 channel->invite_list = silc_calloc(len + 2,
2508 sizeof(*channel->invite_list));
2510 channel->invite_list = silc_realloc(channel->invite_list,
2511 sizeof(*channel->invite_list) *
2513 strlen(channel->invite_list) + 2));
2514 strncat(channel->invite_list, invite, len);
2515 strncat(channel->invite_list, ",", 1);
2517 /* Send notify to the client that is invited to the channel */
2518 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2519 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2520 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2522 SILC_NOTIFY_TYPE_INVITE, 3,
2523 idp->data, idp->len,
2524 channel->channel_name,
2525 strlen(channel->channel_name),
2526 idp2->data, idp2->len);
2527 silc_buffer_free(idp);
2528 silc_buffer_free(idp2);
2531 /* Add the client to the invite list of the channel */
2532 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2534 if (!channel->invite_list)
2535 channel->invite_list = silc_calloc(len + 2,
2536 sizeof(*channel->invite_list));
2538 channel->invite_list = silc_realloc(channel->invite_list,
2539 sizeof(*channel->invite_list) *
2541 strlen(channel->invite_list) + 2));
2542 if (add[len - 1] == ',')
2543 add[len - 1] = '\0';
2545 strncat(channel->invite_list, add, len);
2546 strncat(channel->invite_list, ",", 1);
2549 /* Get the invite to be removed and remove it from the list */
2550 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2551 if (del && channel->invite_list) {
2552 char *start, *end, *n;
2554 if (!strncmp(channel->invite_list, del,
2555 strlen(channel->invite_list) - 1)) {
2556 silc_free(channel->invite_list);
2557 channel->invite_list = NULL;
2559 start = strstr(channel->invite_list, del);
2560 if (start && strlen(start) >= len) {
2562 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2563 strncat(n, channel->invite_list, start - channel->invite_list);
2564 strncat(n, end + 1, ((channel->invite_list +
2565 strlen(channel->invite_list)) - end) - 1);
2566 silc_free(channel->invite_list);
2567 channel->invite_list = n;
2572 /* Send notify to the primary router */
2573 if (!server->standalone)
2574 silc_server_send_notify_invite(server, server->router->connection,
2575 server->server_type == SILC_ROUTER ?
2576 TRUE : FALSE, channel,
2577 sender->id, add, del);
2579 /* Send command reply */
2580 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2584 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2585 SILC_STATUS_OK, 0, ident, 2,
2587 3, channel->invite_list,
2588 channel->invite_list ?
2589 strlen(channel->invite_list) : 0);
2592 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2593 SILC_STATUS_OK, 0, ident, 1,
2595 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2596 packet->data, packet->len, FALSE);
2597 silc_buffer_free(packet);
2601 silc_free(channel_id);
2602 silc_server_command_free(cmd);
2607 SilcSocketConnection sock;
2611 /* Quits connection to client. This gets called if client won't
2612 close the connection even when it has issued QUIT command. */
2614 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2616 QuitInternal q = (QuitInternal)context;
2618 /* Free all client specific data, such as client entry and entires
2619 on channels this client may be on. */
2620 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2622 q->sock->user_data = NULL;
2624 /* Close the connection on our side */
2625 silc_server_close_connection(q->server, q->sock);
2627 silc_free(q->signoff);
2631 /* Quits SILC session. This is the normal way to disconnect client. */
2633 SILC_SERVER_CMD_FUNC(quit)
2635 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2636 SilcServer server = cmd->server;
2637 SilcSocketConnection sock = cmd->sock;
2639 unsigned char *tmp = NULL;
2642 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2644 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2648 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2652 q = silc_calloc(1, sizeof(*q));
2655 q->signoff = tmp ? strdup(tmp) : NULL;
2657 /* We quit the connection with little timeout */
2658 silc_schedule_task_add(server->schedule, sock->sock,
2659 silc_server_command_quit_cb, (void *)q,
2660 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2663 silc_server_command_free(cmd);
2666 /* Server side of command KILL. This command is used by router operator
2667 to remove an client from the SILC Network temporarily. */
2669 SILC_SERVER_CMD_FUNC(kill)
2671 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2672 SilcServer server = cmd->server;
2673 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2674 SilcClientEntry remote_client;
2675 SilcClientID *client_id;
2676 unsigned char *tmp, *comment;
2677 SilcUInt32 tmp_len, tmp_len2;
2680 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2682 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2685 /* KILL command works only on router */
2686 if (server->server_type != SILC_ROUTER) {
2687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2688 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2692 /* Check whether client has the permissions. */
2693 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2695 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2699 /* Get the client ID */
2700 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2703 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2706 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2709 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2713 /* Get the client entry */
2714 remote_client = silc_idlist_find_client_by_id(server->local_list,
2715 client_id, TRUE, NULL);
2717 if (!remote_client) {
2718 remote_client = silc_idlist_find_client_by_id(server->global_list,
2719 client_id, TRUE, NULL);
2721 if (!remote_client) {
2722 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2723 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2729 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2733 /* Send reply to the sender */
2734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2737 /* Now do the killing */
2738 silc_server_kill_client(server, remote_client, comment, client->id,
2742 silc_server_command_free(cmd);
2745 /* Server side of command INFO. This sends information about us to
2746 the client. If client requested specific server we will send the
2747 command to that server. */
2749 SILC_SERVER_CMD_FUNC(info)
2751 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2752 SilcServer server = cmd->server;
2753 SilcBuffer packet, idp;
2756 char *dest_server, *server_info = NULL, *server_name;
2757 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2758 SilcServerEntry entry = NULL;
2759 SilcServerID *server_id = NULL;
2761 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2763 /* Get server name */
2764 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2767 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2769 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2772 SILC_STATUS_ERR_NO_SERVER_ID);
2778 /* Check whether we have this server cached */
2779 entry = silc_idlist_find_server_by_id(server->local_list,
2780 server_id, TRUE, NULL);
2782 entry = silc_idlist_find_server_by_id(server->global_list,
2783 server_id, TRUE, NULL);
2784 if (!entry && server->server_type != SILC_SERVER) {
2785 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2786 SILC_STATUS_ERR_NO_SUCH_SERVER);
2792 /* Some buggy servers has sent request to router about themselves. */
2793 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2796 if ((!dest_server && !server_id && !entry) || (entry &&
2797 entry == server->id_entry) ||
2798 (dest_server && !cmd->pending &&
2799 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2800 /* Send our reply */
2801 char info_string[256];
2803 memset(info_string, 0, sizeof(info_string));
2804 snprintf(info_string, sizeof(info_string),
2805 "location: %s server: %s admin: %s <%s>",
2806 server->config->server_info->location,
2807 server->config->server_info->server_type,
2808 server->config->server_info->admin,
2809 server->config->server_info->email);
2811 server_info = info_string;
2812 entry = server->id_entry;
2814 /* Check whether we have this server cached */
2815 if (!entry && dest_server) {
2816 entry = silc_idlist_find_server_by_name(server->global_list,
2817 dest_server, TRUE, NULL);
2819 entry = silc_idlist_find_server_by_name(server->local_list,
2820 dest_server, TRUE, NULL);
2824 if (!cmd->pending &&
2825 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2826 /* Send to the server */
2828 SilcUInt16 old_ident;
2830 old_ident = silc_command_get_ident(cmd->payload);
2831 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2832 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2834 silc_server_packet_send(server, entry->connection,
2835 SILC_PACKET_COMMAND, cmd->packet->flags,
2836 tmpbuf->data, tmpbuf->len, TRUE);
2838 /* Reprocess this packet after received reply from router */
2839 silc_server_command_pending(server, SILC_COMMAND_INFO,
2840 silc_command_get_ident(cmd->payload),
2841 silc_server_command_info,
2842 silc_server_command_dup(cmd));
2843 cmd->pending = TRUE;
2844 silc_command_set_ident(cmd->payload, old_ident);
2845 silc_buffer_free(tmpbuf);
2849 if (!entry && !cmd->pending && !server->standalone) {
2850 /* Send to the primary router */
2852 SilcUInt16 old_ident;
2854 old_ident = silc_command_get_ident(cmd->payload);
2855 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2856 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2858 silc_server_packet_send(server, server->router->connection,
2859 SILC_PACKET_COMMAND, cmd->packet->flags,
2860 tmpbuf->data, tmpbuf->len, TRUE);
2862 /* Reprocess this packet after received reply from router */
2863 silc_server_command_pending(server, SILC_COMMAND_INFO,
2864 silc_command_get_ident(cmd->payload),
2865 silc_server_command_info,
2866 silc_server_command_dup(cmd));
2867 cmd->pending = TRUE;
2868 silc_command_set_ident(cmd->payload, old_ident);
2869 silc_buffer_free(tmpbuf);
2874 silc_free(server_id);
2877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2878 SILC_STATUS_ERR_NO_SUCH_SERVER);
2882 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2884 server_info = entry->server_info;
2885 server_name = entry->server_name;
2887 /* Send the reply */
2888 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2889 SILC_STATUS_OK, 0, ident, 3,
2890 2, idp->data, idp->len,
2892 strlen(server_name),
2895 strlen(server_info) : 0);
2896 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2897 packet->data, packet->len, FALSE);
2899 silc_buffer_free(packet);
2900 silc_buffer_free(idp);
2903 silc_server_command_free(cmd);
2906 /* Server side of command PING. This just replies to the ping. */
2908 SILC_SERVER_CMD_FUNC(ping)
2910 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2911 SilcServer server = cmd->server;
2916 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2919 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2922 SILC_STATUS_ERR_NO_SERVER_ID);
2925 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2929 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2930 /* Send our reply */
2931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2935 SILC_STATUS_ERR_NO_SUCH_SERVER);
2942 silc_server_command_free(cmd);
2945 /* Server side of command STATS. */
2947 SILC_SERVER_CMD_FUNC(stats)
2949 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2950 SilcServer server = cmd->server;
2951 SilcServerID *server_id;
2954 SilcBuffer packet, stats;
2955 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2958 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
2961 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2964 SILC_STATUS_ERR_NO_SERVER_ID);
2967 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2971 /* The ID must be ours */
2972 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
2973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2974 SILC_STATUS_ERR_NO_SUCH_SERVER);
2975 silc_free(server_id);
2978 silc_free(server_id);
2980 /* If we are router then just send everything we got. If we are normal
2981 server then we'll send this to our router to get all the latest
2982 statistical information. */
2983 if (!cmd->pending && server->server_type != SILC_ROUTER &&
2984 !server->standalone) {
2985 /* Send request to our router */
2986 SilcBuffer idp = silc_id_payload_encode(server->router->id,
2988 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
2989 ++server->cmd_ident, 1,
2990 1, idp->data, idp->len);
2991 silc_server_packet_send(server, server->router->connection,
2992 SILC_PACKET_COMMAND, 0, packet->data,
2993 packet->len, FALSE);
2995 /* Reprocess this packet after received reply from router */
2996 silc_server_command_pending(server, SILC_COMMAND_STATS,
2998 silc_server_command_stats,
2999 silc_server_command_dup(cmd));
3000 cmd->pending = TRUE;
3001 silc_buffer_free(packet);
3002 silc_buffer_free(idp);
3006 /* Send our reply to sender */
3007 uptime = time(NULL) - server->starttime;
3009 stats = silc_buffer_alloc_size(60);
3010 silc_buffer_format(stats,
3011 SILC_STR_UI_INT(server->starttime),
3012 SILC_STR_UI_INT(uptime),
3013 SILC_STR_UI_INT(server->stat.my_clients),
3014 SILC_STR_UI_INT(server->stat.my_channels),
3015 SILC_STR_UI_INT(server->stat.my_server_ops),
3016 SILC_STR_UI_INT(server->stat.my_router_ops),
3017 SILC_STR_UI_INT(server->stat.cell_clients),
3018 SILC_STR_UI_INT(server->stat.cell_channels),
3019 SILC_STR_UI_INT(server->stat.cell_servers),
3020 SILC_STR_UI_INT(server->stat.clients),
3021 SILC_STR_UI_INT(server->stat.channels),
3022 SILC_STR_UI_INT(server->stat.servers),
3023 SILC_STR_UI_INT(server->stat.routers),
3024 SILC_STR_UI_INT(server->stat.server_ops),
3025 SILC_STR_UI_INT(server->stat.router_ops),
3028 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3029 SILC_STATUS_OK, 0, ident, 2,
3031 3, stats->data, stats->len);
3032 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3033 0, packet->data, packet->len, FALSE);
3034 silc_buffer_free(packet);
3035 silc_buffer_free(stats);
3038 silc_server_command_free(cmd);
3041 /* Internal routine to join channel. The channel sent to this function
3042 has been either created or resolved from ID lists. This joins the sent
3043 client to the channel. */
3045 static void silc_server_command_join_channel(SilcServer server,
3046 SilcServerCommandContext cmd,
3047 SilcChannelEntry channel,
3048 SilcClientID *client_id,
3052 const unsigned char *auth,
3053 SilcUInt32 auth_len)
3055 SilcSocketConnection sock = cmd->sock;
3057 SilcUInt32 tmp_len, user_count;
3058 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3059 SilcClientEntry client;
3060 SilcChannelClientEntry chl;
3061 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3062 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3063 char check[512], check2[512];
3064 bool founder = FALSE;
3067 SILC_LOG_DEBUG(("Start"));
3072 /* Get the client entry */
3073 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3074 client = (SilcClientEntry)sock->user_data;
3076 client = silc_server_get_client_resolve(server, client_id, FALSE,
3083 silc_server_command_send_status_reply(
3084 cmd, SILC_COMMAND_JOIN,
3085 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3089 /* The client info is being resolved. Reprocess this packet after
3090 receiving the reply to the query. */
3091 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3093 silc_server_command_join,
3094 silc_server_command_dup(cmd));
3095 cmd->pending = TRUE;
3099 cmd->pending = FALSE;
3103 * Check founder auth payload if provided. If client can gain founder
3104 * privileges it can override various conditions on joining the channel,
3105 * and can have directly the founder mode set on the channel.
3107 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3108 SilcIDListData idata = (SilcIDListData)client;
3110 if (channel->founder_key && idata->public_key &&
3111 silc_pkcs_public_key_compare(channel->founder_key,
3112 idata->public_key)) {
3113 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3114 (void *)channel->founder_passwd :
3115 (void *)channel->founder_key);
3116 SilcUInt32 auth_data_len =
3117 (channel->founder_method == SILC_AUTH_PASSWORD ?
3118 channel->founder_passwd_len : 0);
3120 /* Check whether the client is to become founder */
3121 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3122 auth_data, auth_data_len,
3123 idata->hash, client->id, SILC_ID_CLIENT)) {
3124 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3131 * Check channel modes
3135 memset(check, 0, sizeof(check));
3136 memset(check2, 0, sizeof(check2));
3137 strncat(check, client->nickname, strlen(client->nickname));
3138 strncat(check, "!", 1);
3139 strncat(check, client->username, strlen(client->username));
3140 if (!strchr(client->username, '@')) {
3141 strncat(check, "@", 1);
3142 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3145 strncat(check2, client->nickname, strlen(client->nickname));
3146 if (!strchr(client->nickname, '@')) {
3147 strncat(check2, "@", 1);
3148 strncat(check2, server->server_name, strlen(server->server_name));
3150 strncat(check2, "!", 1);
3151 strncat(check2, client->username, strlen(client->username));
3152 if (!strchr(client->username, '@')) {
3153 strncat(check2, "@", 1);
3154 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3157 /* Check invite list if channel is invite-only channel */
3158 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3159 if (!channel->invite_list ||
3160 (!silc_string_match(channel->invite_list, check) &&
3161 !silc_string_match(channel->invite_list, check2))) {
3162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3163 SILC_STATUS_ERR_NOT_INVITED);
3168 /* Check ban list if it exists. If the client's nickname, server,
3169 username and/or hostname is in the ban list the access to the
3170 channel is denied. */
3171 if (channel->ban_list) {
3172 if (silc_string_match(channel->ban_list, check) ||
3173 silc_string_match(channel->ban_list, check2)) {
3174 silc_server_command_send_status_reply(
3175 cmd, SILC_COMMAND_JOIN,
3176 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3181 /* Check user count limit if set. */
3182 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3183 if (silc_hash_table_count(channel->user_list) + 1 >
3184 channel->user_limit) {
3185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3186 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3192 /* Check the channel passphrase if set. */
3193 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3194 /* Get passphrase */
3195 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3197 passphrase = silc_memdup(tmp, tmp_len);
3199 if (!passphrase || !channel->passphrase ||
3200 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3202 SILC_STATUS_ERR_BAD_PASSWORD);
3208 * Client is allowed to join to the channel. Make it happen.
3211 /* Check whether the client already is on the channel */
3212 if (silc_server_client_on_channel(client, channel, NULL)) {
3213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3214 SILC_STATUS_ERR_USER_ON_CHANNEL);
3218 /* Generate new channel key as protocol dictates */
3220 if (!silc_server_create_channel_key(server, channel, 0))
3223 /* Send the channel key. This is broadcasted to the channel but is not
3224 sent to the client who is joining to the channel. */
3225 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3226 silc_server_send_channel_key(server, NULL, channel,
3227 server->server_type == SILC_ROUTER ?
3228 FALSE : !server->standalone);
3231 /* Join the client to the channel by adding it to channel's user list.
3232 Add also the channel to client entry's channels list for fast cross-
3234 chl = silc_calloc(1, sizeof(*chl));
3236 chl->client = client;
3237 chl->channel = channel;
3238 silc_hash_table_add(channel->user_list, client, chl);
3239 silc_hash_table_add(client->channels, channel, chl);
3240 channel->user_count++;
3242 /* Get users on the channel */
3243 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3246 /* Encode Client ID Payload of the original client who wants to join */
3247 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3249 /* Encode command reply packet */
3250 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3251 SILC_PUT32_MSB(channel->mode, mode);
3252 SILC_PUT32_MSB(created, tmp2);
3253 SILC_PUT32_MSB(user_count, tmp3);
3255 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3256 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3257 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3260 strlen(channel->channel_key->
3262 channel->channel_key->cipher->name,
3263 channel->key_len / 8, channel->key);
3268 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3269 SILC_STATUS_OK, 0, ident, 13,
3270 2, channel->channel_name,
3271 strlen(channel->channel_name),
3272 3, chidp->data, chidp->len,
3273 4, clidp->data, clidp->len,
3276 7, keyp ? keyp->data : NULL,
3277 keyp ? keyp->len : 0,
3278 8, channel->ban_list,
3280 strlen(channel->ban_list) : 0,
3281 9, channel->invite_list,
3282 channel->invite_list ?
3283 strlen(channel->invite_list) : 0,
3286 strlen(channel->topic) : 0,
3287 11, silc_hmac_get_name(channel->hmac),
3288 strlen(silc_hmac_get_name(channel->
3291 13, user_list->data, user_list->len,
3292 14, mode_list->data,
3295 /* Send command reply */
3296 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3297 reply->data, reply->len, FALSE);
3299 /* Send JOIN notify to locally connected clients on the channel. If
3300 we are normal server then router will send or have sent JOIN notify
3301 already. However since we've added the client already to our channel
3302 we'll ignore it (in packet_receive.c) so we must send it here. If
3303 we are router then this will send it to local clients and local
3305 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3306 SILC_NOTIFY_TYPE_JOIN, 2,
3307 clidp->data, clidp->len,
3308 chidp->data, chidp->len);
3310 if (!cmd->pending) {
3311 /* Send JOIN notify packet to our primary router */
3312 if (!server->standalone)
3313 silc_server_send_notify_join(server, server->router->connection,
3314 server->server_type == SILC_ROUTER ?
3315 TRUE : FALSE, channel, client->id);
3318 /* Distribute the channel key to all backup routers. */
3319 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3320 keyp->data, keyp->len, FALSE, TRUE);
3323 /* If client became founder by providing correct founder auth data
3324 notify the mode change to the channel. */
3326 SILC_PUT32_MSB(chl->mode, mode);
3327 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3328 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3329 clidp->data, clidp->len,
3330 mode, 4, clidp->data, clidp->len);
3332 /* Set CUMODE notify type to network */
3333 if (!server->standalone)
3334 silc_server_send_notify_cumode(server, server->router->connection,
3335 server->server_type == SILC_ROUTER ?
3336 TRUE : FALSE, channel,
3337 chl->mode, client->id, SILC_ID_CLIENT,
3341 silc_buffer_free(reply);
3342 silc_buffer_free(clidp);
3343 silc_buffer_free(chidp);
3344 silc_buffer_free(keyp);
3345 silc_buffer_free(user_list);
3346 silc_buffer_free(mode_list);
3349 silc_free(passphrase);
3352 /* Server side of command JOIN. Joins client into requested channel. If
3353 the channel does not exist it will be created. */
3355 SILC_SERVER_CMD_FUNC(join)
3357 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3358 SilcServer server = cmd->server;
3359 unsigned char *auth;
3360 SilcUInt32 tmp_len, auth_len;
3361 char *tmp, *channel_name = NULL, *cipher, *hmac;
3362 SilcChannelEntry channel;
3363 SilcUInt32 umode = 0;
3364 bool created = FALSE, create_key = TRUE;
3365 SilcClientID *client_id;
3367 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3369 /* Get channel name */
3370 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3373 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3379 channel_name[255] = '\0';
3381 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3383 SILC_STATUS_ERR_BAD_CHANNEL);
3387 /* Get Client ID of the client who is joining to the channel */
3388 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3391 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3394 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3397 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3401 /* Get cipher, hmac name and auth payload */
3402 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3403 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3404 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3406 /* See if the channel exists */
3407 channel = silc_idlist_find_channel_by_name(server->local_list,
3408 channel_name, NULL);
3410 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3411 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3412 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3414 if (!channel || channel->disabled) {
3415 /* Channel not found */
3417 /* If we are standalone server we don't have a router, we just create
3418 the channel by ourselves. */
3419 if (server->standalone) {
3420 channel = silc_server_create_new_channel(server, server->id, cipher,
3421 hmac, channel_name, TRUE);
3423 silc_server_command_send_status_reply(
3424 cmd, SILC_COMMAND_JOIN,
3425 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3429 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3435 /* The channel does not exist on our server. If we are normal server
3436 we will send JOIN command to our router which will handle the
3437 joining procedure (either creates the channel if it doesn't exist
3438 or joins the client to it). */
3439 if (server->server_type != SILC_ROUTER) {
3441 SilcUInt16 old_ident;
3443 /* If this is pending command callback then we've resolved
3444 it and it didn't work, return since we've notified the
3445 client already in the command reply callback. */
3449 old_ident = silc_command_get_ident(cmd->payload);
3450 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3451 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3453 /* Send JOIN command to our router */
3454 silc_server_packet_send(server, (SilcSocketConnection)
3455 server->router->connection,
3456 SILC_PACKET_COMMAND, cmd->packet->flags,
3457 tmpbuf->data, tmpbuf->len, TRUE);
3459 /* Reprocess this packet after received reply from router */
3460 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3461 silc_command_get_ident(cmd->payload),
3462 silc_server_command_join,
3463 silc_server_command_dup(cmd));
3464 cmd->pending = TRUE;
3465 silc_command_set_ident(cmd->payload, old_ident);
3466 silc_buffer_free(tmpbuf);
3470 /* We are router and the channel does not seem exist so we will check
3471 our global list as well for the channel. */
3472 channel = silc_idlist_find_channel_by_name(server->global_list,
3473 channel_name, NULL);
3475 /* Channel really does not exist, create it */
3476 channel = silc_server_create_new_channel(server, server->id, cipher,
3477 hmac, channel_name, TRUE);
3479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3480 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3484 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3492 /* Channel not found */
3494 /* If the command came from router and we are normal server then
3495 something went wrong with the joining as the channel was not found.
3496 We can't do anything else but ignore this. */
3497 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3498 server->server_type != SILC_ROUTER)
3501 /* We are router and the channel does not seem exist so we will check
3502 our global list as well for the channel. */
3503 channel = silc_idlist_find_channel_by_name(server->global_list,
3504 channel_name, NULL);
3506 /* Channel really does not exist, create it */
3507 channel = silc_server_create_new_channel(server, server->id, cipher,
3508 hmac, channel_name, TRUE);
3510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3511 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3515 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3522 /* Check whether the channel was created by our router */
3523 if (cmd->pending && context2) {
3524 SilcServerCommandReplyContext reply = context2;
3526 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3527 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3528 SILC_GET32_MSB(created, tmp);
3529 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3530 create_key = FALSE; /* Router returned the key already */
3533 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3534 !silc_hash_table_count(channel->user_list))
3538 /* If the channel does not have global users and is also empty the client
3539 will be the channel founder and operator. */
3540 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3541 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3543 /* Join to the channel */
3544 silc_server_command_join_channel(server, cmd, channel, client_id,
3545 created, create_key, umode,
3548 silc_free(client_id);
3551 silc_server_command_free(cmd);
3554 /* Server side of command MOTD. Sends server's current "message of the
3555 day" to the client. */
3557 SILC_SERVER_CMD_FUNC(motd)
3559 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3560 SilcServer server = cmd->server;
3561 SilcBuffer packet, idp;
3562 char *motd, *dest_server;
3563 SilcUInt32 motd_len;
3564 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3566 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3568 /* Get server name */
3569 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3571 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3572 SILC_STATUS_ERR_NO_SUCH_SERVER);
3576 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3579 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3581 if (server->config && server->config->server_info &&
3582 server->config->server_info->motd_file) {
3584 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3589 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3596 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3602 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3603 packet->data, packet->len, FALSE);
3604 silc_buffer_free(packet);
3605 silc_buffer_free(idp);
3607 SilcServerEntry entry;
3609 /* Check whether we have this server cached */
3610 entry = silc_idlist_find_server_by_name(server->global_list,
3611 dest_server, TRUE, NULL);
3613 entry = silc_idlist_find_server_by_name(server->local_list,
3614 dest_server, TRUE, NULL);
3617 if (server->server_type != SILC_SERVER && !cmd->pending &&
3618 entry && !entry->motd) {
3619 /* Send to the server */
3621 SilcUInt16 old_ident;
3623 old_ident = silc_command_get_ident(cmd->payload);
3624 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3625 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3627 silc_server_packet_send(server, entry->connection,
3628 SILC_PACKET_COMMAND, cmd->packet->flags,
3629 tmpbuf->data, tmpbuf->len, TRUE);
3631 /* Reprocess this packet after received reply from router */
3632 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3633 silc_command_get_ident(cmd->payload),
3634 silc_server_command_motd,
3635 silc_server_command_dup(cmd));
3636 cmd->pending = TRUE;
3637 silc_command_set_ident(cmd->payload, old_ident);
3638 silc_buffer_free(tmpbuf);
3642 if (!entry && !cmd->pending && !server->standalone) {
3643 /* Send to the primary router */
3645 SilcUInt16 old_ident;
3647 old_ident = silc_command_get_ident(cmd->payload);
3648 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3649 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3651 silc_server_packet_send(server, server->router->connection,
3652 SILC_PACKET_COMMAND, cmd->packet->flags,
3653 tmpbuf->data, tmpbuf->len, TRUE);
3655 /* Reprocess this packet after received reply from router */
3656 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3657 silc_command_get_ident(cmd->payload),
3658 silc_server_command_motd,
3659 silc_server_command_dup(cmd));
3660 cmd->pending = TRUE;
3661 silc_command_set_ident(cmd->payload, old_ident);
3662 silc_buffer_free(tmpbuf);
3667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3668 SILC_STATUS_ERR_NO_SUCH_SERVER);
3672 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3673 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3674 SILC_STATUS_OK, 0, ident, 2,
3678 strlen(entry->motd) : 0);
3679 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3680 packet->data, packet->len, FALSE);
3681 silc_buffer_free(packet);
3682 silc_buffer_free(idp);
3686 silc_server_command_free(cmd);
3689 /* Server side of command UMODE. Client can use this command to set/unset
3690 user mode. Client actually cannot set itself to be as server/router
3691 operator so this can be used only to unset the modes. */
3693 SILC_SERVER_CMD_FUNC(umode)
3695 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3696 SilcServer server = cmd->server;
3697 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3699 unsigned char *tmp_mask, m[4];
3700 SilcUInt32 mask = 0;
3701 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3702 bool set_mask = FALSE;
3704 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3707 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3709 /* Get the client's mode mask */
3710 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3712 SILC_GET32_MSB(mask, tmp_mask);
3717 /* Check that mode changing is allowed. */
3718 if (!silc_server_check_umode_rights(server, client, mask)) {
3719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3720 SILC_STATUS_ERR_PERM_DENIED);
3724 /* Anonymous mode cannot be set by client */
3725 if (mask & SILC_UMODE_ANONYMOUS) {
3726 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3728 SILC_STATUS_ERR_PERM_DENIED);
3732 if (client->mode & SILC_UMODE_ANONYMOUS) {
3733 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3734 SILC_STATUS_ERR_PERM_DENIED);
3739 /* Change the mode */
3740 client->mode = mask;
3742 /* Send UMODE change to primary router */
3743 if (!server->standalone)
3744 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3745 client->id, client->mode);
3748 /* Send command reply to sender */
3749 SILC_PUT32_MSB(client->mode, m);
3750 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3751 SILC_STATUS_OK, 0, ident, 1,
3753 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3754 packet->data, packet->len, FALSE);
3755 silc_buffer_free(packet);
3758 silc_server_command_free(cmd);
3761 /* Server side command of CMODE. Changes channel mode */
3763 SILC_SERVER_CMD_FUNC(cmode)
3765 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3766 SilcServer server = cmd->server;
3767 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3768 SilcIDListData idata = (SilcIDListData)client;
3769 SilcChannelID *channel_id = NULL;
3770 SilcChannelEntry channel;
3771 SilcChannelClientEntry chl;
3772 SilcBuffer packet, cidp;
3773 unsigned char *tmp, *tmp_id, *tmp_mask;
3774 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3775 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3776 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3777 bool set_mask = FALSE;
3779 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3781 /* Get Channel ID */
3782 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3785 SILC_STATUS_ERR_NO_CHANNEL_ID);
3788 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3791 SILC_STATUS_ERR_NO_CHANNEL_ID);
3795 /* Get the channel mode mask */
3796 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3798 SILC_GET32_MSB(mode_mask, tmp_mask);
3802 /* Get channel entry */
3803 channel = silc_idlist_find_channel_by_id(server->local_list,
3806 channel = silc_idlist_find_channel_by_id(server->global_list,
3809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3810 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3815 /* Check whether this client is on the channel */
3816 if (!silc_server_client_on_channel(client, channel, &chl)) {
3817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3818 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3822 /* Check that client has rights to change any requested channel modes */
3823 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3827 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3828 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3832 /* If mode mask was not sent as argument then merely return the current
3833 mode mask to the sender. */
3836 SILC_PUT32_MSB(channel->mode, m);
3837 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3838 SILC_STATUS_OK, 0, ident, 2,
3839 2, tmp_id, tmp_len2,
3841 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3842 packet->data, packet->len, FALSE);
3843 silc_buffer_free(packet);
3848 * Check the modes. Modes that requires nothing special operation are
3852 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3853 /* Channel uses private keys to protect traffic. Client(s) has set the
3854 key locally they want to use, server does not know that key. */
3855 /* Nothing interesting to do here */
3857 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3858 /* The mode is removed and we need to generate and distribute
3859 new channel key. Clients are not using private channel keys
3860 anymore after this. */
3862 /* Re-generate channel key */
3863 if (!silc_server_create_channel_key(server, channel, 0))
3866 /* Send the channel key. This sends it to our local clients and if
3867 we are normal server to our router as well. */
3868 silc_server_send_channel_key(server, NULL, channel,
3869 server->server_type == SILC_ROUTER ?
3870 FALSE : !server->standalone);
3872 cipher = channel->channel_key->cipher->name;
3873 hmac = (char *)silc_hmac_get_name(channel->hmac);
3877 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3878 /* User limit is set on channel */
3879 SilcUInt32 user_limit;
3881 /* Get user limit */
3882 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3884 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3886 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3890 SILC_GET32_MSB(user_limit, tmp);
3891 channel->user_limit = user_limit;
3894 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3895 /* User limit mode is unset. Remove user limit */
3896 channel->user_limit = 0;
3899 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3900 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3901 /* Passphrase has been set to channel */
3903 /* Get the passphrase */
3904 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3907 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3911 /* Save the passphrase */
3912 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3915 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3916 /* Passphrase mode is unset. remove the passphrase */
3917 silc_free(channel->passphrase);
3918 channel->passphrase = NULL;
3922 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3923 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3924 /* Cipher to use protect the traffic */
3925 SilcCipher newkey, oldkey;
3928 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3931 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3935 /* Delete old cipher and allocate the new one */
3936 if (!silc_cipher_alloc(cipher, &newkey)) {
3937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3938 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3942 oldkey = channel->channel_key;
3943 channel->channel_key = newkey;
3945 /* Re-generate channel key */
3946 if (!silc_server_create_channel_key(server, channel, 0)) {
3947 /* We don't have new key, revert to old one */
3948 channel->channel_key = oldkey;
3952 /* Remove old channel key for good */
3953 silc_cipher_free(oldkey);
3955 /* Send the channel key. This sends it to our local clients and if
3956 we are normal server to our router as well. */
3957 silc_server_send_channel_key(server, NULL, channel,
3958 server->server_type == SILC_ROUTER ?
3959 FALSE : !server->standalone);
3962 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3963 /* Cipher mode is unset. Remove the cipher and revert back to
3965 SilcCipher newkey, oldkey;
3966 cipher = channel->cipher;
3968 /* Delete old cipher and allocate default one */
3969 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3971 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3975 oldkey = channel->channel_key;
3976 channel->channel_key = newkey;
3978 /* Re-generate channel key */
3979 if (!silc_server_create_channel_key(server, channel, 0)) {
3980 /* We don't have new key, revert to old one */
3981 channel->channel_key = oldkey;
3985 /* Remove old channel key for good */
3986 silc_cipher_free(oldkey);
3988 /* Send the channel key. This sends it to our local clients and if
3989 we are normal server to our router as well. */
3990 silc_server_send_channel_key(server, NULL, channel,
3991 server->server_type == SILC_ROUTER ?
3992 FALSE : !server->standalone);
3996 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3997 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3998 /* HMAC to use protect the traffic */
3999 unsigned char hash[32];
4003 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4006 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4010 /* Delete old hmac and allocate the new one */
4011 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4013 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4017 silc_hmac_free(channel->hmac);
4018 channel->hmac = newhmac;
4020 /* Set the HMAC key out of current channel key. The client must do
4022 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4023 channel->key_len / 8, hash);
4024 silc_hmac_set_key(channel->hmac, hash,
4025 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4026 memset(hash, 0, sizeof(hash));
4029 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4030 /* Hmac mode is unset. Remove the hmac and revert back to
4033 unsigned char hash[32];
4034 hmac = channel->hmac_name;
4036 /* Delete old hmac and allocate default one */
4037 silc_hmac_free(channel->hmac);
4038 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4040 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4044 silc_hmac_free(channel->hmac);
4045 channel->hmac = newhmac;
4047 /* Set the HMAC key out of current channel key. The client must do
4049 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4050 channel->key_len / 8,
4052 silc_hmac_set_key(channel->hmac, hash,
4053 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4054 memset(hash, 0, sizeof(hash));
4058 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4059 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4060 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4061 /* Set the founder authentication */
4062 SilcAuthPayload auth;
4064 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4067 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4071 auth = silc_auth_payload_parse(tmp, tmp_len);
4073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4074 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4078 /* Save the public key */
4079 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4080 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4083 channel->founder_method = silc_auth_get_method(auth);
4085 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4086 tmp = silc_auth_get_data(auth, &tmp_len);
4087 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4088 channel->founder_passwd_len = tmp_len;
4090 /* Verify the payload before setting the mode */
4091 if (!silc_auth_verify(auth, channel->founder_method,
4092 channel->founder_key, 0, idata->hash,
4093 client->id, SILC_ID_CLIENT)) {
4094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4095 SILC_STATUS_ERR_AUTH_FAILED);
4100 silc_auth_payload_free(auth);
4104 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4105 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4106 if (channel->founder_key)
4107 silc_pkcs_public_key_free(channel->founder_key);
4108 if (channel->founder_passwd) {
4109 silc_free(channel->founder_passwd);
4110 channel->founder_passwd = NULL;
4116 /* Finally, set the mode */
4117 channel->mode = mode_mask;
4119 /* Send CMODE_CHANGE notify. */
4120 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4121 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4122 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4123 cidp->data, cidp->len,
4125 cipher, cipher ? strlen(cipher) : 0,
4126 hmac, hmac ? strlen(hmac) : 0,
4127 passphrase, passphrase ?
4128 strlen(passphrase) : 0);
4130 /* Set CMODE notify type to network */
4131 if (!server->standalone)
4132 silc_server_send_notify_cmode(server, server->router->connection,
4133 server->server_type == SILC_ROUTER ?
4134 TRUE : FALSE, channel,
4135 mode_mask, client->id, SILC_ID_CLIENT,
4136 cipher, hmac, passphrase);
4138 /* Send command reply to sender */
4139 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4140 SILC_STATUS_OK, 0, ident, 2,
4141 2, tmp_id, tmp_len2,
4143 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4144 packet->data, packet->len, FALSE);
4146 silc_buffer_free(packet);
4147 silc_buffer_free(cidp);
4150 silc_free(channel_id);
4151 silc_server_command_free(cmd);
4154 /* Server side of CUMODE command. Changes client's mode on a channel. */
4156 SILC_SERVER_CMD_FUNC(cumode)
4158 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4159 SilcServer server = cmd->server;
4160 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4161 SilcIDListData idata = (SilcIDListData)client;
4162 SilcChannelID *channel_id;
4163 SilcClientID *client_id;
4164 SilcChannelEntry channel;
4165 SilcClientEntry target_client;
4166 SilcChannelClientEntry chl;
4167 SilcBuffer packet, idp;
4168 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4169 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4171 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4173 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4175 /* Get Channel ID */
4176 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4179 SILC_STATUS_ERR_NO_CHANNEL_ID);
4182 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4184 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4185 SILC_STATUS_ERR_NO_CHANNEL_ID);
4189 /* Get channel entry */
4190 channel = silc_idlist_find_channel_by_id(server->local_list,
4193 channel = silc_idlist_find_channel_by_id(server->global_list,
4196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4197 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4202 /* Check whether sender is on the channel */
4203 if (!silc_server_client_on_channel(client, channel, &chl)) {
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4205 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4208 sender_mask = chl->mode;
4210 /* Get the target client's channel mode mask */
4211 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4214 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4217 SILC_GET32_MSB(target_mask, tmp_mask);
4219 /* Get target Client ID */
4220 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4223 SILC_STATUS_ERR_NO_CLIENT_ID);
4226 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4229 SILC_STATUS_ERR_NO_CLIENT_ID);
4233 /* Get target client's entry */
4234 target_client = silc_idlist_find_client_by_id(server->local_list,
4235 client_id, TRUE, NULL);
4236 if (!target_client) {
4237 target_client = silc_idlist_find_client_by_id(server->global_list,
4238 client_id, TRUE, NULL);
4241 if (target_client != client &&
4242 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4243 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4245 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4249 /* Check whether target client is on the channel */
4250 if (target_client != client) {
4251 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4262 /* If the target client is founder, no one else can change their mode
4264 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4266 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4270 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4271 if (target_client != client) {
4272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4273 SILC_STATUS_ERR_NOT_YOU);
4277 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4278 /* The client tries to claim the founder rights. */
4279 unsigned char *tmp_auth;
4280 SilcUInt32 tmp_auth_len, auth_len;
4283 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4284 !channel->founder_key || !idata->public_key ||
4285 !silc_pkcs_public_key_compare(channel->founder_key,
4286 idata->public_key)) {
4287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4288 SILC_STATUS_ERR_NOT_YOU);
4292 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4295 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4299 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4300 (void *)channel->founder_passwd : (void *)channel->founder_key);
4301 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4302 channel->founder_passwd_len : 0);
4304 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4305 channel->founder_method, auth, auth_len,
4306 idata->hash, client->id, SILC_ID_CLIENT)) {
4307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4308 SILC_STATUS_ERR_AUTH_FAILED);
4312 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4316 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4317 if (target_client == client) {
4318 /* Remove channel founder rights from itself */
4319 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4323 SILC_STATUS_ERR_NOT_YOU);
4329 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4330 /* Promote to operator */
4331 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4332 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4333 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4335 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4339 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4343 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4344 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4345 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4347 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4351 /* Demote to normal user */
4352 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4357 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4358 if (target_client != client) {
4359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4360 SILC_STATUS_ERR_NOT_YOU);
4364 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4365 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4369 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4370 if (target_client != client) {
4371 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4372 SILC_STATUS_ERR_NOT_YOU);
4376 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4382 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4383 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4385 /* Send notify to channel, notify only if mode was actually changed. */
4387 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4388 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4389 idp->data, idp->len,
4393 /* Set CUMODE notify type to network */
4394 if (!server->standalone)
4395 silc_server_send_notify_cumode(server, server->router->connection,
4396 server->server_type == SILC_ROUTER ?
4397 TRUE : FALSE, channel,
4398 target_mask, client->id,
4403 /* Send command reply to sender */
4404 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4405 SILC_STATUS_OK, 0, ident, 3,
4407 3, tmp_ch_id, tmp_ch_len,
4408 4, tmp_id, tmp_len);
4409 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4410 packet->data, packet->len, FALSE);
4412 silc_buffer_free(packet);
4413 silc_free(channel_id);
4414 silc_free(client_id);
4415 silc_buffer_free(idp);
4418 silc_server_command_free(cmd);
4421 /* Server side of KICK command. Kicks client out of channel. */
4423 SILC_SERVER_CMD_FUNC(kick)
4425 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4426 SilcServer server = cmd->server;
4427 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4428 SilcClientEntry target_client;
4429 SilcChannelID *channel_id;
4430 SilcClientID *client_id;
4431 SilcChannelEntry channel;
4432 SilcChannelClientEntry chl;
4434 SilcUInt32 tmp_len, target_idp_len;
4435 unsigned char *tmp, *comment, *target_idp;
4437 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4439 /* Get Channel ID */
4440 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4443 SILC_STATUS_ERR_NO_CHANNEL_ID);
4446 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4449 SILC_STATUS_ERR_NO_CHANNEL_ID);
4453 /* Get channel entry */
4454 channel = silc_idlist_find_channel_by_id(server->local_list,
4457 channel = silc_idlist_find_channel_by_id(server->local_list,
4460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4461 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4466 /* Check whether sender is on the channel */
4467 if (!silc_server_client_on_channel(client, channel, &chl)) {
4468 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4469 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4473 /* Check that the kicker is channel operator or channel founder */
4474 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4476 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4480 /* Get target Client ID */
4481 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4484 SILC_STATUS_ERR_NO_CLIENT_ID);
4487 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4490 SILC_STATUS_ERR_NO_CLIENT_ID);
4494 /* Get target client's entry */
4495 target_client = silc_idlist_find_client_by_id(server->local_list,
4496 client_id, TRUE, NULL);
4497 if (!target_client) {
4498 target_client = silc_idlist_find_client_by_id(server->global_list,
4499 client_id, TRUE, NULL);
4502 /* Check whether target client is on the channel */
4503 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4505 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4509 /* Check that the target client is not channel founder. Channel founder
4510 cannot be kicked from the channel. */
4511 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4513 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4519 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4523 /* Send command reply to sender */
4524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4527 /* Send KICKED notify to local clients on the channel */
4528 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4529 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4530 SILC_NOTIFY_TYPE_KICKED, 3,
4531 target_idp, target_idp_len,
4532 comment, comment ? strlen(comment) : 0,
4533 idp->data, idp->len);
4534 silc_buffer_free(idp);
4536 /* Remove the client from the channel. If the channel does not exist
4537 after removing the client then the client kicked itself off the channel
4538 and we don't have to send anything after that. */
4539 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4540 target_client, FALSE))
4543 /* Send KICKED notify to primary route */
4544 if (!server->standalone)
4545 silc_server_send_notify_kicked(server, server->router->connection,
4546 server->server_type == SILC_ROUTER ?
4547 TRUE : FALSE, channel,
4548 target_client->id, client->id, comment);
4550 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4551 /* Re-generate channel key */
4552 if (!silc_server_create_channel_key(server, channel, 0))
4555 /* Send the channel key to the channel. The key of course is not sent
4556 to the client who was kicked off the channel. */
4557 silc_server_send_channel_key(server, target_client->connection, channel,
4558 server->server_type == SILC_ROUTER ?
4559 FALSE : !server->standalone);
4563 silc_server_command_free(cmd);
4566 /* Server side of OPER command. Client uses this comand to obtain server
4567 operator privileges to this server/router. */
4569 SILC_SERVER_CMD_FUNC(oper)
4571 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4572 SilcServer server = cmd->server;
4573 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4574 unsigned char *username, *auth;
4576 SilcServerConfigAdmin *admin;
4577 SilcIDListData idata = (SilcIDListData)client;
4578 bool result = FALSE;
4579 SilcPublicKey cached_key;
4581 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4583 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4586 /* Get the username */
4587 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4590 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4594 /* Get the admin configuration */
4595 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4596 username, client->nickname);
4598 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4599 username, client->nickname);
4601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4602 SILC_STATUS_ERR_AUTH_FAILED);
4607 /* Get the authentication payload */
4608 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4610 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4611 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4615 /* Verify the authentication data. If both passphrase and public key
4616 is set then try both of them. */
4617 if (admin->passphrase)
4618 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4619 admin->passphrase, admin->passphrase_len,
4620 idata->hash, client->id, SILC_ID_CLIENT);
4621 if (!result && admin->publickeys) {
4622 cached_key = silc_server_get_public_key(server, admin->publickeys);
4625 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4626 cached_key, 0, idata->hash,
4627 client->id, SILC_ID_CLIENT);
4630 /* Authentication failed */
4631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4632 SILC_STATUS_ERR_AUTH_FAILED);
4636 /* Client is now server operator */
4637 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4639 /* Update statistics */
4640 if (client->connection)
4641 server->stat.my_server_ops++;
4642 if (server->server_type == SILC_ROUTER)
4643 server->stat.server_ops++;
4645 /* Send UMODE change to primary router */
4646 if (!server->standalone)
4647 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4648 client->id, client->mode);
4650 /* Send reply to the sender */
4651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4655 silc_server_command_free(cmd);
4658 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4660 QuitInternal q = (QuitInternal)context;
4661 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4663 /* If there is pending outgoing data for the client then purge it
4664 to the network before closing connection. */
4665 silc_server_packet_queue_purge(q->server, q->sock);
4667 /* Close the connection on our side */
4668 client->router = NULL;
4669 client->connection = NULL;
4670 q->sock->user_data = NULL;
4671 silc_server_close_connection(q->server, q->sock);
4676 /* Server side of DETACH command. Detached the client from the network
4677 by closing the connection but preserving the session. */
4679 SILC_SERVER_CMD_FUNC(detach)
4681 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4682 SilcServer server = cmd->server;
4683 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4686 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4689 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4691 /* Send the user mode notify to notify that client is detached */
4692 client->mode |= SILC_UMODE_DETACHED;
4693 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4694 if (!server->standalone)
4695 silc_server_send_notify_umode(server, server->router->connection,
4696 server->server_type == SILC_SERVER ?
4697 FALSE : TRUE, client->id, client->mode);
4699 q = silc_calloc(1, sizeof(*q));
4701 q->sock = cmd->sock;
4702 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4703 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4705 /* Send reply to the sender */
4706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4710 silc_server_command_free(cmd);
4713 /* Server side of SILCOPER command. Client uses this comand to obtain router
4714 operator privileges to this router. */
4716 SILC_SERVER_CMD_FUNC(silcoper)
4718 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4719 SilcServer server = cmd->server;
4720 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4721 unsigned char *username, *auth;
4723 SilcServerConfigAdmin *admin;
4724 SilcIDListData idata = (SilcIDListData)client;
4725 bool result = FALSE;
4726 SilcPublicKey cached_key;
4728 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4730 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4733 if (server->server_type != SILC_ROUTER) {
4734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4735 SILC_STATUS_ERR_AUTH_FAILED);
4739 /* Get the username */
4740 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4742 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4743 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4747 /* Get the admin configuration */
4748 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4749 username, client->nickname);
4751 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4752 username, client->nickname);
4754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4755 SILC_STATUS_ERR_AUTH_FAILED);
4760 /* Get the authentication payload */
4761 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4764 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4768 /* Verify the authentication data. If both passphrase and public key
4769 is set then try both of them. */
4770 if (admin->passphrase)
4771 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4772 admin->passphrase, admin->passphrase_len,
4773 idata->hash, client->id, SILC_ID_CLIENT);
4774 if (!result && admin->publickeys) {
4775 cached_key = silc_server_get_public_key(server, admin->publickeys);
4778 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4779 cached_key, 0, idata->hash,
4780 client->id, SILC_ID_CLIENT);
4783 /* Authentication failed */
4784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4785 SILC_STATUS_ERR_AUTH_FAILED);
4789 /* Client is now router operator */
4790 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4792 /* Update statistics */
4793 if (client->connection)
4794 server->stat.my_router_ops++;
4795 if (server->server_type == SILC_ROUTER)
4796 server->stat.router_ops++;
4798 /* Send UMODE change to primary router */
4799 if (!server->standalone)
4800 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4801 client->id, client->mode);
4803 /* Send reply to the sender */
4804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4808 silc_server_command_free(cmd);
4811 /* Server side of command BAN. This is used to manage the ban list of the
4812 channel. To add clients and remove clients from the ban list. */
4814 SILC_SERVER_CMD_FUNC(ban)
4816 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4817 SilcServer server = cmd->server;
4818 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4820 SilcChannelEntry channel;
4821 SilcChannelClientEntry chl;
4822 SilcChannelID *channel_id = NULL;
4823 unsigned char *id, *add, *del;
4824 SilcUInt32 id_len, tmp_len;
4825 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4827 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4830 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4832 /* Get Channel ID */
4833 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4835 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4838 SILC_STATUS_ERR_NO_CHANNEL_ID);
4843 /* Get channel entry. The server must know about the channel since the
4844 client is expected to be on the channel. */
4845 channel = silc_idlist_find_channel_by_id(server->local_list,
4848 channel = silc_idlist_find_channel_by_id(server->global_list,
4851 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4852 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4857 /* Check whether this client is on the channel */
4858 if (!silc_server_client_on_channel(client, channel, &chl)) {
4859 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4860 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4864 /* The client must be at least channel operator. */
4865 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4866 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4867 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4871 /* Get the new ban and add it to the ban list */
4872 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4874 if (!channel->ban_list)
4875 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4877 channel->ban_list = silc_realloc(channel->ban_list,
4878 sizeof(*channel->ban_list) *
4880 strlen(channel->ban_list) + 2));
4881 if (add[tmp_len - 1] == ',')
4882 add[tmp_len - 1] = '\0';
4884 strncat(channel->ban_list, add, tmp_len);
4885 strncat(channel->ban_list, ",", 1);
4888 /* Get the ban to be removed and remove it from the list */
4889 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4890 if (del && channel->ban_list) {
4891 char *start, *end, *n;
4893 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4894 silc_free(channel->ban_list);
4895 channel->ban_list = NULL;
4897 start = strstr(channel->ban_list, del);
4898 if (start && strlen(start) >= tmp_len) {
4899 end = start + tmp_len;
4900 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4901 strncat(n, channel->ban_list, start - channel->ban_list);
4902 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4904 silc_free(channel->ban_list);
4905 channel->ban_list = n;
4910 /* Send the BAN notify type to our primary router. */
4911 if (!server->standalone && (add || del))
4912 silc_server_send_notify_ban(server, server->router->connection,
4913 server->server_type == SILC_ROUTER ?
4914 TRUE : FALSE, channel, add, del);
4916 /* Send the reply back to the client */
4918 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4919 SILC_STATUS_OK, 0, ident, 2,
4921 3, channel->ban_list,
4923 strlen(channel->ban_list) -1 : 0);
4924 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4925 packet->data, packet->len, FALSE);
4927 silc_buffer_free(packet);
4930 silc_free(channel_id);
4931 silc_server_command_free(cmd);
4934 /* Server side command of LEAVE. Removes client from a channel. */
4936 SILC_SERVER_CMD_FUNC(leave)
4938 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4939 SilcServer server = cmd->server;
4940 SilcSocketConnection sock = cmd->sock;
4941 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4942 SilcChannelID *id = NULL;
4943 SilcChannelEntry channel;
4947 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4949 /* Get Channel ID */
4950 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4953 SILC_STATUS_ERR_NO_CHANNEL_ID);
4956 id = silc_id_payload_parse_id(tmp, len, NULL);
4958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4959 SILC_STATUS_ERR_NO_CHANNEL_ID);
4963 /* Get channel entry */
4964 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4966 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4968 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4969 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4974 /* Check whether this client is on the channel */
4975 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4977 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4981 /* Notify routers that they should remove this client from their list
4982 of clients on the channel. Send LEAVE notify type. */
4983 if (!server->standalone)
4984 silc_server_send_notify_leave(server, server->router->connection,
4985 server->server_type == SILC_ROUTER ?
4986 TRUE : FALSE, channel, id_entry->id);
4988 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4989 SILC_STATUS_OK, 2, tmp, len);
4991 /* Remove client from channel */
4992 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4994 /* If the channel does not exist anymore we won't send anything */
4997 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4998 /* Re-generate channel key */
4999 if (!silc_server_create_channel_key(server, channel, 0))
5002 /* Send the channel key */
5003 silc_server_send_channel_key(server, NULL, channel,
5004 server->server_type == SILC_ROUTER ?
5005 FALSE : !server->standalone);
5010 silc_server_command_free(cmd);
5013 /* Server side of command USERS. Resolves clients and their USERS currently
5014 joined on the requested channel. The list of Client ID's and their modes
5015 on the channel is sent back. */
5017 SILC_SERVER_CMD_FUNC(users)
5019 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5020 SilcServer server = cmd->server;
5021 SilcChannelEntry channel;
5022 SilcChannelID *id = NULL;
5023 SilcBuffer packet, idp;
5024 unsigned char *channel_id;
5025 SilcUInt32 channel_id_len;
5026 SilcBuffer client_id_list;
5027 SilcBuffer client_mode_list;
5028 unsigned char lc[4];
5029 SilcUInt32 list_count = 0;
5030 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5033 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5035 /* Get Channel ID */
5036 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5038 /* Get channel name */
5039 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5041 if (!channel_id && !channel_name) {
5042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5043 SILC_STATUS_ERR_NO_CHANNEL_ID);
5048 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5051 SILC_STATUS_ERR_NO_CHANNEL_ID);
5056 /* If we are server and we don't know about this channel we will send
5057 the command to our router. If we know about the channel then we also
5058 have the list of users already. */
5060 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5062 channel = silc_idlist_find_channel_by_name(server->local_list,
5063 channel_name, NULL);
5065 if (!channel || channel->disabled) {
5066 if (server->server_type != SILC_ROUTER && !server->standalone &&
5070 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5071 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5073 /* Send USERS command */
5074 silc_server_packet_send(server, server->router->connection,
5075 SILC_PACKET_COMMAND, cmd->packet->flags,
5076 tmpbuf->data, tmpbuf->len, TRUE);
5078 /* Reprocess this packet after received reply */
5079 silc_server_command_pending(server, SILC_COMMAND_USERS,
5080 silc_command_get_ident(cmd->payload),
5081 silc_server_command_users,
5082 silc_server_command_dup(cmd));
5083 cmd->pending = TRUE;
5084 silc_command_set_ident(cmd->payload, ident);
5085 silc_buffer_free(tmpbuf);
5090 /* Check the global list as well. */
5092 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5094 channel = silc_idlist_find_channel_by_name(server->global_list,
5095 channel_name, NULL);
5097 /* Channel really does not exist */
5098 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5099 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5104 /* If the channel is private or secret do not send anything, unless the
5105 user requesting this command is on the channel or is server */
5106 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5107 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5108 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5111 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5116 /* Get the users list */
5117 silc_server_get_users_on_channel(server, channel, &client_id_list,
5118 &client_mode_list, &list_count);
5121 SILC_PUT32_MSB(list_count, lc);
5124 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5125 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5126 SILC_STATUS_OK, 0, ident, 4,
5127 2, idp->data, idp->len,
5129 4, client_id_list->data,
5130 client_id_list->len,
5131 5, client_mode_list->data,
5132 client_mode_list->len);
5133 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5134 packet->data, packet->len, FALSE);
5136 silc_buffer_free(idp);
5137 silc_buffer_free(packet);
5138 silc_buffer_free(client_id_list);
5139 silc_buffer_free(client_mode_list);
5143 silc_server_command_free(cmd);
5146 /* Server side of command GETKEY. This fetches the client's public key
5147 from the server where to the client is connected. */
5149 SILC_SERVER_CMD_FUNC(getkey)
5151 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5152 SilcServer server = cmd->server;
5154 SilcClientEntry client;
5155 SilcServerEntry server_entry;
5156 SilcClientID *client_id = NULL;
5157 SilcServerID *server_id = NULL;
5158 SilcIDPayload idp = NULL;
5159 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5160 unsigned char *tmp, *pkdata;
5161 SilcUInt32 tmp_len, pklen;
5162 SilcBuffer pk = NULL;
5164 SilcPublicKey public_key;
5166 SILC_LOG_DEBUG(("Start"));
5168 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5170 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5171 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5174 idp = silc_id_payload_parse(tmp, tmp_len);
5176 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5177 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5181 id_type = silc_id_payload_get_type(idp);
5182 if (id_type == SILC_ID_CLIENT) {
5183 client_id = silc_id_payload_get_id(idp);
5185 /* If the client is not found from local list there is no chance it
5186 would be locally connected client so send the command further. */
5187 client = silc_idlist_find_client_by_id(server->local_list,
5188 client_id, TRUE, NULL);
5190 client = silc_idlist_find_client_by_id(server->global_list,
5191 client_id, TRUE, NULL);
5193 if ((!client && !cmd->pending && !server->standalone) ||
5194 (client && !client->connection && !cmd->pending &&
5195 !(client->mode & SILC_UMODE_DETACHED)) ||
5196 (client && !client->data.public_key && !cmd->pending)) {
5198 SilcUInt16 old_ident;
5199 SilcSocketConnection dest_sock;
5201 dest_sock = silc_server_get_client_route(server, NULL, 0,
5202 client_id, NULL, NULL);
5206 old_ident = silc_command_get_ident(cmd->payload);
5207 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5208 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5210 silc_server_packet_send(server, dest_sock,
5211 SILC_PACKET_COMMAND, cmd->packet->flags,
5212 tmpbuf->data, tmpbuf->len, TRUE);
5214 /* Reprocess this packet after received reply from router */
5215 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5216 silc_command_get_ident(cmd->payload),
5217 silc_server_command_getkey,
5218 silc_server_command_dup(cmd));
5219 cmd->pending = TRUE;
5220 silc_command_set_ident(cmd->payload, old_ident);
5221 silc_buffer_free(tmpbuf);
5226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5227 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5231 /* The client is locally connected, just get the public key and
5232 send it back. If they key does not exist then do not send it,
5233 send just OK reply */
5234 public_key = client->data.public_key;
5239 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5240 pk = silc_buffer_alloc(4 + tmp_len);
5241 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5242 silc_buffer_format(pk,
5243 SILC_STR_UI_SHORT(tmp_len),
5244 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5245 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5251 } else if (id_type == SILC_ID_SERVER) {
5252 server_id = silc_id_payload_get_id(idp);
5254 /* If the server is not found from local list there is no chance it
5255 would be locally connected server so send the command further. */
5256 server_entry = silc_idlist_find_server_by_id(server->local_list,
5257 server_id, TRUE, NULL);
5259 server_entry = silc_idlist_find_server_by_id(server->global_list,
5260 server_id, TRUE, NULL);
5262 if (server_entry != server->id_entry &&
5263 ((!server_entry && !cmd->pending && !server->standalone) ||
5264 (server_entry && !server_entry->connection && !cmd->pending &&
5265 !server->standalone) ||
5266 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5267 !server->standalone))) {
5269 SilcUInt16 old_ident;
5271 old_ident = silc_command_get_ident(cmd->payload);
5272 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5273 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5275 silc_server_packet_send(server, server->router->connection,
5276 SILC_PACKET_COMMAND, cmd->packet->flags,
5277 tmpbuf->data, tmpbuf->len, TRUE);
5279 /* Reprocess this packet after received reply from router */
5280 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5281 silc_command_get_ident(cmd->payload),
5282 silc_server_command_getkey,
5283 silc_server_command_dup(cmd));
5284 cmd->pending = TRUE;
5285 silc_command_set_ident(cmd->payload, old_ident);
5286 silc_buffer_free(tmpbuf);
5290 if (!server_entry) {
5291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5292 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5296 /* If they key does not exist then do not send it, send just OK reply */
5297 public_key = (!server_entry->data.public_key ?
5298 (server_entry == server->id_entry ? server->public_key :
5299 NULL) : server_entry->data.public_key);
5304 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5305 pk = silc_buffer_alloc(4 + tmp_len);
5306 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5307 silc_buffer_format(pk,
5308 SILC_STR_UI_SHORT(tmp_len),
5309 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5310 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5320 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5321 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5322 SILC_STATUS_OK, 0, ident,
5326 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5327 packet->data, packet->len, FALSE);
5328 silc_buffer_free(packet);
5331 silc_buffer_free(pk);
5335 silc_id_payload_free(idp);
5336 silc_free(client_id);
5337 silc_free(server_id);
5338 silc_server_command_free(cmd);
5342 /* Private range commands, specific to this implementation */
5344 /* Server side command of CONNECT. Connects us to the specified remote
5345 server or router. */
5347 SILC_SERVER_CMD_FUNC(connect)
5349 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5350 SilcServer server = cmd->server;
5351 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5352 unsigned char *tmp, *host;
5354 SilcUInt32 port = SILC_PORT;
5356 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5358 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5361 /* Check whether client has the permissions. */
5362 if (client->mode == SILC_UMODE_NONE) {
5363 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5364 SILC_STATUS_ERR_NO_SERVER_PRIV);
5368 if (server->server_type == SILC_ROUTER &&
5369 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5371 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5375 /* Get the remote server */
5376 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5379 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5384 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5386 SILC_GET32_MSB(port, tmp);
5388 /* Create the connection. It is done with timeout and is async. */
5389 silc_server_create_connection(server, host, port);
5391 /* Send reply to the sender */
5392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5396 silc_server_command_free(cmd);
5399 /* Server side command of CLOSE. Closes connection to a specified server. */
5401 SILC_SERVER_CMD_FUNC(close)
5403 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5404 SilcServer server = cmd->server;
5405 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5406 SilcServerEntry server_entry;
5407 SilcSocketConnection sock;
5410 unsigned char *name;
5411 SilcUInt32 port = SILC_PORT;
5413 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5415 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5418 /* Check whether client has the permissions. */
5419 if (client->mode == SILC_UMODE_NONE) {
5420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5421 SILC_STATUS_ERR_NO_SERVER_PRIV);
5425 /* Get the remote server */
5426 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5429 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5434 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5436 SILC_GET32_MSB(port, tmp);
5438 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5439 name, port, FALSE, NULL);
5441 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5442 name, port, FALSE, NULL);
5443 if (!server_entry) {
5444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5445 SILC_STATUS_ERR_NO_SERVER_ID);
5449 /* Send reply to the sender */
5450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5453 /* Close the connection to the server */
5454 sock = (SilcSocketConnection)server_entry->connection;
5456 /* If we shutdown primary router connection manually then don't trigger
5457 any reconnect or backup router connections, by setting the router
5459 if (server->router == server_entry) {
5460 server->id_entry->router = NULL;
5461 server->router = NULL;
5462 server->standalone = TRUE;
5464 silc_server_free_sock_user_data(server, sock, NULL);
5465 silc_server_close_connection(server, sock);
5468 silc_server_command_free(cmd);
5471 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5472 active connections. */
5474 SILC_SERVER_CMD_FUNC(shutdown)
5476 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5477 SilcServer server = cmd->server;
5478 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5480 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5482 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5485 /* Check whether client has the permission. */
5486 if (client->mode == SILC_UMODE_NONE) {
5487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5488 SILC_STATUS_ERR_NO_SERVER_PRIV);
5492 /* Send reply to the sender */
5493 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5496 /* Then, gracefully, or not, bring the server down. */
5497 silc_server_stop(server);
5501 silc_server_command_free(cmd);