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, umode_list = NULL;
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 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
786 channels = silc_server_get_client_channel_list(server, entry, FALSE,
789 channels = silc_server_get_client_channel_list(server, entry, TRUE,
792 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
793 fingerprint = entry->data.fingerprint;
797 SILC_PUT32_MSB(entry->mode, mode);
799 if (entry->connection) {
800 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
804 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
806 2, idp->data, idp->len,
810 strlen(entry->userinfo),
811 6, channels ? channels->data : NULL,
812 channels ? channels->len : 0,
816 fingerprint ? 20 : 0,
817 10, umode_list ? umode_list->data :
818 NULL, umode_list ? umode_list->len :
821 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
822 0, packet->data, packet->len, FALSE);
824 silc_buffer_free(packet);
825 silc_buffer_free(idp);
827 silc_buffer_free(channels);
829 silc_buffer_free(umode_list);
838 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
840 SilcServer server = cmd->server;
842 SilcUInt16 old_ident;
844 old_ident = silc_command_get_ident(cmd->payload);
845 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
846 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
848 /* Send WHOIS command to our router */
849 silc_server_packet_send(server, (SilcSocketConnection)
850 server->router->connection,
851 SILC_PACKET_COMMAND, cmd->packet->flags,
852 tmpbuf->data, tmpbuf->len, TRUE);
854 /* Reprocess this packet after received reply from router */
855 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
856 silc_command_get_ident(cmd->payload),
857 silc_server_command_whois,
858 silc_server_command_dup(cmd));
860 silc_command_set_ident(cmd->payload, old_ident);
861 silc_buffer_free(tmpbuf);
865 silc_server_command_whois_process(SilcServerCommandContext cmd)
867 SilcServer server = cmd->server;
868 char *nick = NULL, *server_name = NULL;
870 SilcClientEntry *clients = NULL, entry;
871 SilcClientID **client_id = NULL;
872 SilcUInt32 client_id_count = 0, clients_count = 0;
874 bool check_global = FALSE;
876 /* Parse the whois request */
877 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
878 &nick, &server_name, &count,
882 /* Send the WHOIS request to the router only if it included nickname.
883 Since nicknames can be expanded into many clients we need to send it
884 to router. If the WHOIS included only client ID's we will check them
885 first locally since we just might have them. */
886 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
887 server->server_type == SILC_SERVER && !cmd->pending &&
888 !server->standalone) {
889 silc_server_command_whois_send_router(cmd);
894 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
896 else if (server->server_type != SILC_SERVER)
899 /* Get all clients matching that ID or nickname from local list */
900 if (client_id_count) {
901 /* Check all Client ID's received in the command packet */
902 for (i = 0; i < client_id_count; i++) {
903 entry = silc_idlist_find_client_by_id(server->local_list,
904 client_id[i], TRUE, NULL);
905 if (!entry && check_global)
906 entry = silc_idlist_find_client_by_id(server->global_list,
907 client_id[i], TRUE, NULL);
909 clients = silc_realloc(clients, sizeof(*clients) *
910 (clients_count + 1));
911 clients[clients_count++] = entry;
913 /* If we are normal server and did not send the request first to router
914 do it now, since we do not have the Client ID information. */
915 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
916 server->server_type == SILC_SERVER && !cmd->pending &&
917 !server->standalone) {
918 silc_server_command_whois_send_router(cmd);
925 /* Find by nickname */
926 if (!silc_idlist_get_clients_by_hash(server->local_list,
927 nick, server->md5hash,
928 &clients, &clients_count))
929 silc_idlist_get_clients_by_nickname(server->local_list,
931 &clients, &clients_count);
933 if (!silc_idlist_get_clients_by_hash(server->global_list,
934 nick, server->md5hash,
935 &clients, &clients_count))
936 silc_idlist_get_clients_by_nickname(server->global_list,
938 &clients, &clients_count);
943 /* If we are normal server and did not send the request first to router
944 do it now, since we do not have the information. */
945 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
946 server->server_type == SILC_SERVER && !cmd->pending &&
947 !server->standalone) {
948 silc_server_command_whois_send_router(cmd);
953 /* Such client(s) really does not exist in the SILC network. */
954 if (!client_id_count) {
955 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
956 SILC_STATUS_ERR_NO_SUCH_NICK,
957 3, nick, strlen(nick));
959 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
960 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
961 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
962 2, idp->data, idp->len);
963 silc_buffer_free(idp);
968 /* Router always finds the client entry if it exists in the SILC network.
969 However, it might be incomplete entry and does not include all the
970 mandatory fields that WHOIS command reply requires. Check for these and
971 make query from the server who owns the client if some fields are
973 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
978 /* Send the command reply */
979 silc_server_command_whois_send_reply(cmd, clients, clients_count,
980 count, nick, client_id);
983 if (client_id_count) {
984 for (i = 0; i < client_id_count; i++)
985 silc_free(client_id[i]);
986 silc_free(client_id);
990 silc_free(server_name);
995 /* Server side of command WHOIS. Processes user's query and sends found
996 results as command replies back to the client. */
998 SILC_SERVER_CMD_FUNC(whois)
1000 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1003 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1005 ret = silc_server_command_whois_process(cmd);
1006 silc_server_command_free(cmd);
1009 /******************************************************************************
1013 ******************************************************************************/
1016 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1024 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1027 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1031 /* Get the nickname@server string and parse it. */
1032 silc_parse_userfqdn(tmp, nickname, server_name);
1034 /* Get the max count of reply messages allowed */
1035 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1045 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1046 SilcClientEntry *clients,
1047 SilcUInt32 clients_count)
1049 SilcServer server = cmd->server;
1051 SilcClientEntry entry;
1053 for (i = 0; i < clients_count; i++) {
1056 if (!entry->nickname || !entry->username) {
1058 SilcUInt16 old_ident;
1063 old_ident = silc_command_get_ident(cmd->payload);
1064 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1065 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1067 /* Send WHOWAS command */
1068 silc_server_packet_send(server, entry->router->connection,
1069 SILC_PACKET_COMMAND, cmd->packet->flags,
1070 tmpbuf->data, tmpbuf->len, TRUE);
1072 /* Reprocess this packet after received reply */
1073 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1074 silc_command_get_ident(cmd->payload),
1075 silc_server_command_whowas,
1076 silc_server_command_dup(cmd));
1077 cmd->pending = TRUE;
1078 silc_command_set_ident(cmd->payload, old_ident);
1080 silc_buffer_free(tmpbuf);
1089 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1090 SilcClientEntry *clients,
1091 SilcUInt32 clients_count)
1093 SilcServer server = cmd->server;
1095 int i, k, count = 0, len;
1096 SilcBuffer packet, idp;
1097 SilcClientEntry entry = NULL;
1098 SilcCommandStatus status;
1099 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1100 char nh[256], uh[256];
1103 status = SILC_STATUS_OK;
1105 /* Process only entries that are not registered anymore. */
1107 for (i = 0; i < clients_count; i++) {
1108 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1115 /* No valid entries found at all, just send error */
1118 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1120 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1121 SILC_STATUS_ERR_NO_SUCH_NICK,
1122 3, tmp, strlen(tmp));
1126 if (valid_count > 1)
1127 status = SILC_STATUS_LIST_START;
1129 for (i = 0, k = 0; i < clients_count; i++) {
1135 status = SILC_STATUS_LIST_ITEM;
1136 if (valid_count > 1 && k == valid_count - 1)
1137 status = SILC_STATUS_LIST_END;
1138 if (count && k - 1 == count)
1139 status = SILC_STATUS_LIST_END;
1140 if (count && k - 1 > count)
1143 /* Send WHOWAS reply */
1144 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1145 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1146 memset(uh, 0, sizeof(uh));
1147 memset(nh, 0, sizeof(nh));
1149 strncat(nh, entry->nickname, strlen(entry->nickname));
1150 if (!strchr(entry->nickname, '@')) {
1151 strncat(nh, "@", 1);
1152 if (entry->servername) {
1153 strncat(nh, entry->servername, strlen(entry->servername));
1155 len = entry->router ? strlen(entry->router->server_name) :
1156 strlen(server->server_name);
1157 strncat(nh, entry->router ? entry->router->server_name :
1158 server->server_name, len);
1162 strncat(uh, entry->username, strlen(entry->username));
1163 if (!strchr(entry->username, '@')) {
1164 strncat(uh, "@", 1);
1165 strcat(uh, "*private*");
1169 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1170 status, 0, ident, 4,
1171 2, idp->data, idp->len,
1176 strlen(entry->userinfo) : 0);
1177 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1178 0, packet->data, packet->len, FALSE);
1180 silc_buffer_free(packet);
1181 silc_buffer_free(idp);
1188 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1190 SilcServer server = cmd->server;
1191 char *nick = NULL, *server_name = NULL;
1193 SilcClientEntry *clients = NULL;
1194 SilcUInt32 clients_count = 0;
1196 bool check_global = FALSE;
1198 /* Protocol dictates that we must always send the received WHOWAS request
1199 to our router if we are normal server, so let's do it now unless we
1200 are standalone. We will not send any replies to the client until we
1201 have received reply from the router. */
1202 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1203 server->server_type == SILC_SERVER && !cmd->pending &&
1204 !server->standalone) {
1206 SilcUInt16 old_ident;
1208 old_ident = silc_command_get_ident(cmd->payload);
1209 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1210 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1212 /* Send WHOWAS command to our router */
1213 silc_server_packet_send(server, (SilcSocketConnection)
1214 server->router->connection,
1215 SILC_PACKET_COMMAND, cmd->packet->flags,
1216 tmpbuf->data, tmpbuf->len, TRUE);
1218 /* Reprocess this packet after received reply from router */
1219 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1220 silc_command_get_ident(cmd->payload),
1221 silc_server_command_whowas,
1222 silc_server_command_dup(cmd));
1223 cmd->pending = TRUE;
1224 silc_command_set_ident(cmd->payload, old_ident);
1226 silc_buffer_free(tmpbuf);
1231 /* We are ready to process the command request. Let's search for the
1232 requested client and send reply to the requesting client. */
1234 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1235 check_global = TRUE;
1236 else if (server->server_type != SILC_SERVER)
1237 check_global = TRUE;
1239 /* Parse the whowas request */
1240 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1243 /* Get all clients matching that nickname from local list */
1244 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1246 &clients, &clients_count))
1247 silc_idlist_get_clients_by_hash(server->local_list,
1248 nick, server->md5hash,
1249 &clients, &clients_count);
1251 /* Check global list as well */
1253 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1255 &clients, &clients_count))
1256 silc_idlist_get_clients_by_hash(server->global_list,
1257 nick, server->md5hash,
1258 &clients, &clients_count);
1262 /* Such a client really does not exist in the SILC network. */
1263 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1264 SILC_STATUS_ERR_NO_SUCH_NICK,
1265 3, nick, strlen(nick));
1269 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1274 /* Send the command reply to the client */
1275 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1280 silc_free(server_name);
1284 /* Server side of command WHOWAS. */
1286 SILC_SERVER_CMD_FUNC(whowas)
1288 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1291 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1293 ret = silc_server_command_whowas_process(cmd);
1294 silc_server_command_free(cmd);
1297 /******************************************************************************
1301 ******************************************************************************/
1304 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1306 SilcServer server = cmd->server;
1308 SilcUInt16 old_ident;
1310 old_ident = silc_command_get_ident(cmd->payload);
1311 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1312 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1314 /* Send IDENTIFY command to our router */
1315 silc_server_packet_send(server, (SilcSocketConnection)
1316 server->router->connection,
1317 SILC_PACKET_COMMAND, cmd->packet->flags,
1318 tmpbuf->data, tmpbuf->len, TRUE);
1320 /* Reprocess this packet after received reply from router */
1321 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1322 silc_command_get_ident(cmd->payload),
1323 silc_server_command_identify,
1324 silc_server_command_dup(cmd));
1325 cmd->pending = TRUE;
1326 silc_command_set_ident(cmd->payload, old_ident);
1327 silc_buffer_free(tmpbuf);
1331 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1332 SilcClientEntry **clients,
1333 SilcUInt32 *clients_count,
1334 SilcServerEntry **servers,
1335 SilcUInt32 *servers_count,
1336 SilcChannelEntry **channels,
1337 SilcUInt32 *channels_count,
1340 SilcServer server = cmd->server;
1343 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1345 bool check_global = FALSE;
1350 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1351 check_global = TRUE;
1352 else if (server->server_type != SILC_SERVER)
1353 check_global = TRUE;
1355 /* If ID Payload is in the command it must be used instead of names */
1356 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1358 /* No ID, get the names. */
1360 /* If we are normal server and have not resolved information from
1361 router yet, do so now. */
1362 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1363 server->server_type == SILC_SERVER && !cmd->pending &&
1364 !server->standalone) {
1365 silc_server_command_identify_send_router(cmd);
1369 /* Try to get nickname@server. */
1370 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1373 char *nick_server = NULL;
1375 silc_parse_userfqdn(tmp, &nick, &nick_server);
1377 if (!silc_idlist_get_clients_by_hash(server->local_list,
1378 nick, server->md5hash,
1379 clients, clients_count))
1380 silc_idlist_get_clients_by_nickname(server->local_list,
1382 clients, clients_count);
1384 if (!silc_idlist_get_clients_by_hash(server->global_list,
1385 nick, server->md5hash,
1386 clients, clients_count))
1387 silc_idlist_get_clients_by_nickname(server->global_list,
1389 clients, clients_count);
1393 silc_free(nick_server);
1396 /* the nickname does not exist, send error reply */
1397 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1398 SILC_STATUS_ERR_NO_SUCH_NICK,
1399 3, tmp, strlen(tmp));
1404 /* Try to get server name */
1405 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1407 entry = silc_idlist_find_server_by_name(server->local_list,
1409 if (!entry && check_global)
1410 entry = silc_idlist_find_server_by_name(server->global_list,
1413 *servers = silc_realloc(*servers, sizeof(**servers) *
1414 (*servers_count + 1));
1415 (*servers)[(*servers_count)++] = entry;
1419 /* the server does not exist, send error reply */
1420 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1421 SILC_STATUS_ERR_NO_SUCH_SERVER,
1422 3, tmp, strlen(tmp));
1427 /* Try to get channel name */
1428 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1430 entry = silc_idlist_find_channel_by_name(server->local_list,
1432 if (!entry && check_global)
1433 entry = silc_idlist_find_channel_by_name(server->global_list,
1436 *channels = silc_realloc(*channels, sizeof(**channels) *
1437 (*channels_count + 1));
1438 (*channels)[(*channels_count)++] = entry;
1442 /* The channel does not exist, send error reply */
1443 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1444 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1445 3, tmp, strlen(tmp));
1450 if (!(*clients) && !(*servers) && !(*channels)) {
1451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1452 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1456 /* Command includes ID, we must use that. Also check whether the command
1457 has more than one ID set - take them all. */
1459 /* Take all ID's from the command packet */
1460 for (i = 0; i < argc; i++) {
1463 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1467 idp = silc_id_payload_parse(tmp, len);
1469 silc_free(*clients);
1470 silc_free(*servers);
1471 silc_free(*channels);
1472 silc_server_command_send_status_reply(
1473 cmd, SILC_COMMAND_IDENTIFY,
1474 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1478 id = silc_id_payload_get_id(idp);
1480 switch (silc_id_payload_get_type(idp)) {
1482 case SILC_ID_CLIENT:
1483 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1485 if (!entry && check_global)
1486 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1489 *clients = silc_realloc(*clients, sizeof(**clients) *
1490 (*clients_count + 1));
1491 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1493 /* If we are normal server and have not resolved information from
1494 router yet, do so now. */
1495 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1496 server->server_type == SILC_SERVER && !cmd->pending &&
1497 !server->standalone) {
1498 silc_server_command_identify_send_router(cmd);
1499 silc_free(*clients);
1500 silc_free(*servers);
1501 silc_free(*channels);
1504 silc_server_command_send_status_data(
1505 cmd, SILC_COMMAND_IDENTIFY,
1506 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1514 case SILC_ID_SERVER:
1515 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1517 if (!entry && check_global)
1518 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1521 *servers = silc_realloc(*servers, sizeof(**servers) *
1522 (*servers_count + 1));
1523 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1525 /* If we are normal server and have not resolved information from
1526 router yet, do so now. */
1527 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1528 server->server_type == SILC_SERVER && !cmd->pending &&
1529 !server->standalone) {
1530 silc_server_command_identify_send_router(cmd);
1531 silc_free(*clients);
1532 silc_free(*servers);
1533 silc_free(*channels);
1536 silc_server_command_send_status_data(
1537 cmd, SILC_COMMAND_IDENTIFY,
1538 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1545 case SILC_ID_CHANNEL:
1546 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1548 if (!entry && check_global)
1549 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1552 *channels = silc_realloc(*channels, sizeof(**channels) *
1553 (*channels_count + 1));
1554 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1556 /* If we are normal server and have not resolved information from
1557 router yet, do so now. */
1558 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1559 server->server_type == SILC_SERVER && !cmd->pending &&
1560 !server->standalone) {
1561 silc_server_command_identify_send_router(cmd);
1562 silc_free(*clients);
1563 silc_free(*servers);
1564 silc_free(*channels);
1567 silc_server_command_send_status_data(
1568 cmd, SILC_COMMAND_IDENTIFY,
1569 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1582 silc_free(*clients);
1583 silc_free(*servers);
1584 silc_free(*channels);
1588 /* Get the max count of reply messages allowed */
1589 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1598 /* Checks that all mandatory fields in client entry are present. If not
1599 then send WHOIS request to the server who owns the client. We use
1600 WHOIS because we want to get as much information as possible at once. */
1603 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1604 SilcClientEntry *clients,
1605 SilcUInt32 clients_count)
1607 SilcServer server = cmd->server;
1608 SilcClientEntry entry;
1609 SilcServerResolveContext resolve = NULL, r = NULL;
1610 SilcUInt32 resolve_count = 0;
1614 for (i = 0; i < clients_count; i++) {
1619 if (entry->nickname ||
1620 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1624 /* If we are normal server, and we've not resolved this client from
1625 router and it is global client, we'll check whether it is on some
1626 channel. If not then we cannot be sure about its validity, and
1627 we'll resolve it from router. */
1628 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1629 entry->connection || silc_hash_table_count(entry->channels))
1633 /* We need to resolve this entry since it is not complete */
1635 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1636 /* The entry is being resolved (and we are not the resolver) so attach
1637 to the command reply and we're done with this one. */
1638 silc_server_command_pending(server, SILC_COMMAND_NONE,
1639 entry->resolve_cmd_ident,
1640 silc_server_command_identify,
1641 silc_server_command_dup(cmd));
1644 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1645 /* We've resolved this and it still is not ready. We'll return
1646 and are that this will be handled again after it is resolved. */
1647 for (i = 0; i < resolve_count; i++) {
1648 for (k = 0; k < r->res_argc; k++)
1649 silc_free(r->res_argv[k]);
1650 silc_free(r->res_argv);
1651 silc_free(r->res_argv_lens);
1652 silc_free(r->res_argv_types);
1657 /* We'll resolve this client */
1661 for (k = 0; k < resolve_count; k++) {
1662 if (resolve[k].router == entry->router) {
1669 resolve = silc_realloc(resolve, sizeof(*resolve) *
1670 (resolve_count + 1));
1671 r = &resolve[resolve_count];
1672 memset(r, 0, sizeof(*r));
1673 r->router = entry->router;
1674 r->ident = ++server->cmd_ident;
1678 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1680 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1681 sizeof(*r->res_argv_lens) *
1683 r->res_argv_types = silc_realloc(r->res_argv_types,
1684 sizeof(*r->res_argv_types) *
1686 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1687 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1688 sizeof(**r->res_argv));
1689 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1690 r->res_argv_lens[r->res_argc] = idp->len;
1691 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1693 silc_buffer_free(idp);
1695 entry->resolve_cmd_ident = r->ident;
1696 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1697 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1702 /* Do the resolving */
1703 for (i = 0; i < resolve_count; i++) {
1708 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1709 now anyway so make it a good one. */
1710 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1711 r->res_argc, r->res_argv,
1715 silc_server_packet_send(server, r->router->connection,
1716 SILC_PACKET_COMMAND, cmd->packet->flags,
1717 res_cmd->data, res_cmd->len, FALSE);
1719 /* Reprocess this packet after received reply */
1720 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1722 silc_server_command_identify,
1723 silc_server_command_dup(cmd));
1724 cmd->pending = TRUE;
1726 silc_buffer_free(res_cmd);
1727 for (k = 0; k < r->res_argc; k++)
1728 silc_free(r->res_argv[k]);
1729 silc_free(r->res_argv);
1730 silc_free(r->res_argv_lens);
1731 silc_free(r->res_argv_types);
1740 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1741 SilcClientEntry *clients,
1742 SilcUInt32 clients_count,
1743 SilcServerEntry *servers,
1744 SilcUInt32 servers_count,
1745 SilcChannelEntry *channels,
1746 SilcUInt32 channels_count,
1749 SilcServer server = cmd->server;
1750 int i, k, len, valid_count;
1751 SilcBuffer packet, idp;
1752 SilcCommandStatus status;
1753 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1754 char nh[256], uh[256];
1755 SilcSocketConnection hsock;
1757 status = SILC_STATUS_OK;
1760 SilcClientEntry entry;
1762 /* Process only valid entries. */
1764 for (i = 0; i < clients_count; i++) {
1765 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1772 /* No valid entries found at all, just send error */
1775 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1777 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1778 SILC_STATUS_ERR_NO_SUCH_NICK,
1779 3, tmp, strlen(tmp));
1781 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1782 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1783 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1789 /* Process all valid client entries and send command replies */
1791 if (valid_count > 1)
1792 status = SILC_STATUS_LIST_START;
1794 for (i = 0, k = 0; i < clients_count; i++) {
1800 status = SILC_STATUS_LIST_ITEM;
1801 if (valid_count > 1 && k == valid_count - 1
1802 && !servers_count && !channels_count)
1803 status = SILC_STATUS_LIST_END;
1804 if (count && k - 1 == count)
1805 status = SILC_STATUS_LIST_END;
1806 if (count && k - 1 > count)
1809 /* Send IDENTIFY reply */
1811 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1812 memset(uh, 0, sizeof(uh));
1813 memset(nh, 0, sizeof(nh));
1814 strncat(nh, entry->nickname, strlen(entry->nickname));
1815 if (!strchr(entry->nickname, '@')) {
1816 strncat(nh, "@", 1);
1817 if (entry->servername) {
1818 strncat(nh, entry->servername, strlen(entry->servername));
1820 len = entry->router ? strlen(entry->router->server_name) :
1821 strlen(server->server_name);
1822 strncat(nh, entry->router ? entry->router->server_name :
1823 server->server_name, len);
1827 if (!entry->username) {
1828 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1829 status, 0, ident, 2,
1830 2, idp->data, idp->len,
1833 strncat(uh, entry->username, strlen(entry->username));
1834 if (!strchr(entry->username, '@')) {
1835 strncat(uh, "@", 1);
1836 hsock = (SilcSocketConnection)entry->connection;
1837 len = strlen(hsock->hostname);
1838 strncat(uh, hsock->hostname, len);
1841 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1842 status, 0, ident, 3,
1843 2, idp->data, idp->len,
1848 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1849 0, packet->data, packet->len, FALSE);
1851 silc_buffer_free(packet);
1852 silc_buffer_free(idp);
1859 SilcServerEntry entry;
1861 if (status == SILC_STATUS_OK && servers_count > 1)
1862 status = SILC_STATUS_LIST_START;
1864 for (i = 0, k = 0; i < servers_count; i++) {
1868 status = SILC_STATUS_LIST_ITEM;
1869 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1870 status = SILC_STATUS_LIST_END;
1871 if (count && k - 1 == count)
1872 status = SILC_STATUS_LIST_END;
1873 if (count && k - 1 > count)
1876 /* Send IDENTIFY reply */
1877 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1879 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1880 status, 0, ident, 2,
1881 2, idp->data, idp->len,
1882 3, entry->server_name,
1883 entry->server_name ?
1884 strlen(entry->server_name) : 0);
1885 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1886 0, packet->data, packet->len, FALSE);
1888 silc_buffer_free(packet);
1889 silc_buffer_free(idp);
1896 SilcChannelEntry entry;
1898 if (status == SILC_STATUS_OK && channels_count > 1)
1899 status = SILC_STATUS_LIST_START;
1901 for (i = 0, k = 0; i < channels_count; i++) {
1902 entry = channels[i];
1905 status = SILC_STATUS_LIST_ITEM;
1906 if (channels_count > 1 && k == channels_count - 1)
1907 status = SILC_STATUS_LIST_END;
1908 if (count && k - 1 == count)
1909 status = SILC_STATUS_LIST_END;
1910 if (count && k - 1 > count)
1913 /* Send IDENTIFY reply */
1914 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1916 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1917 status, 0, ident, 2,
1918 2, idp->data, idp->len,
1919 3, entry->channel_name,
1920 entry->channel_name ?
1921 strlen(entry->channel_name): 0);
1922 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1923 0, packet->data, packet->len, FALSE);
1925 silc_buffer_free(packet);
1926 silc_buffer_free(idp);
1934 silc_server_command_identify_process(SilcServerCommandContext cmd)
1936 SilcUInt32 count = 0;
1938 SilcClientEntry *clients = NULL;
1939 SilcServerEntry *servers = NULL;
1940 SilcChannelEntry *channels = NULL;
1941 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1943 /* Parse the IDENTIFY request */
1944 ret = silc_server_command_identify_parse(cmd,
1945 &clients, &clients_count,
1946 &servers, &servers_count,
1947 &channels, &channels_count,
1953 /* Check that all mandatory fields are present and request those data
1954 from the server who owns the client if necessary. */
1955 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1961 /* Send the command reply to the client */
1962 silc_server_command_identify_send_reply(cmd,
1963 clients, clients_count,
1964 servers, servers_count,
1965 channels, channels_count,
1971 silc_free(channels);
1975 SILC_SERVER_CMD_FUNC(identify)
1977 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1980 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1982 ret = silc_server_command_identify_process(cmd);
1983 silc_server_command_free(cmd);
1986 /* Server side of command NICK. Sets nickname for user. Setting
1987 nickname causes generation of a new client ID for the client. The
1988 new client ID is sent to the client after changing the nickname. */
1990 SILC_SERVER_CMD_FUNC(nick)
1992 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1993 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1994 SilcServer server = cmd->server;
1995 SilcBuffer packet, nidp, oidp = NULL;
1996 SilcClientID *new_id;
1997 SilcUInt32 nick_len;
1999 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2002 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2005 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2007 /* Check nickname */
2008 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2011 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2013 SILC_STATUS_ERR_BAD_NICKNAME);
2017 /* Check for same nickname */
2018 if (!strcmp(client->nickname, nick)) {
2019 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2023 /* Create new Client ID */
2024 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2026 cmd->server->md5hash, nick,
2030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2031 SILC_STATUS_ERR_BAD_NICKNAME);
2034 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2037 /* Send notify about nickname change to our router. We send the new
2038 ID and ask to replace it with the old one. If we are router the
2039 packet is broadcasted. Send NICK_CHANGE notify. */
2040 if (!server->standalone)
2041 silc_server_send_notify_nick_change(server, server->router->connection,
2042 server->server_type == SILC_SERVER ?
2043 FALSE : TRUE, client->id,
2046 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2048 /* Remove old cache entry */
2049 silc_idcache_del_by_context(server->local_list->clients, client);
2052 silc_free(client->id);
2054 /* Save the nickname as this client is our local client */
2055 silc_free(client->nickname);
2057 client->nickname = strdup(nick);
2058 client->id = new_id;
2060 /* Update client cache */
2061 silc_idcache_add(server->local_list->clients, client->nickname,
2062 client->id, (void *)client, 0, NULL);
2064 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2066 /* Send NICK_CHANGE notify to the client's channels */
2067 silc_server_send_notify_on_channels(server, NULL, client,
2068 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2069 oidp->data, oidp->len,
2070 nidp->data, nidp->len,
2072 strlen(client->nickname));
2075 /* Send the new Client ID as reply command back to client */
2076 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2077 SILC_STATUS_OK, 0, ident, 1,
2078 2, nidp->data, nidp->len);
2079 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2080 0, packet->data, packet->len, FALSE);
2082 silc_buffer_free(packet);
2083 silc_buffer_free(nidp);
2085 silc_buffer_free(oidp);
2088 silc_server_command_free(cmd);
2091 /* Sends the LIST command reply */
2094 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2095 SilcChannelEntry *lch,
2096 SilcUInt32 lch_count,
2097 SilcChannelEntry *gch,
2098 SilcUInt32 gch_count)
2101 SilcBuffer packet, idp;
2102 SilcChannelEntry entry;
2103 SilcCommandStatus status;
2104 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2106 unsigned char usercount[4];
2108 int valid_lcount = 0, valid_rcount = 0;
2110 for (i = 0; i < lch_count; i++) {
2111 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2116 for (i = 0; i < gch_count; i++) {
2117 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2123 status = SILC_STATUS_OK;
2124 if ((lch_count + gch_count) > 1)
2125 status = SILC_STATUS_LIST_START;
2128 for (i = 0, k = 0; i < lch_count; i++) {
2134 status = SILC_STATUS_LIST_ITEM;
2135 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2136 status = SILC_STATUS_LIST_END;
2138 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2140 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2141 topic = "*private*";
2142 memset(usercount, 0, sizeof(usercount));
2144 topic = entry->topic;
2145 users = silc_hash_table_count(entry->user_list);
2146 SILC_PUT32_MSB(users, usercount);
2149 /* Send the reply */
2151 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2152 status, 0, ident, 4,
2153 2, idp->data, idp->len,
2154 3, entry->channel_name,
2155 strlen(entry->channel_name),
2156 4, topic, topic ? strlen(topic) : 0,
2158 silc_server_packet_send(cmd->server, cmd->sock,
2159 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2160 packet->len, FALSE);
2161 silc_buffer_free(packet);
2162 silc_buffer_free(idp);
2167 for (i = 0, k = 0; i < gch_count; i++) {
2173 status = SILC_STATUS_LIST_ITEM;
2174 if (valid_rcount > 1 && k == valid_rcount - 1)
2175 status = SILC_STATUS_LIST_END;
2177 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2179 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2180 topic = "*private*";
2181 memset(usercount, 0, sizeof(usercount));
2183 topic = entry->topic;
2184 users = entry->user_count;
2185 SILC_PUT32_MSB(users, usercount);
2188 /* Send the reply */
2190 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2191 status, 0, ident, 4,
2192 2, idp->data, idp->len,
2193 3, entry->channel_name,
2194 strlen(entry->channel_name),
2195 4, topic, topic ? strlen(topic) : 0,
2197 silc_server_packet_send(cmd->server, cmd->sock,
2198 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2199 packet->len, FALSE);
2200 silc_buffer_free(packet);
2201 silc_buffer_free(idp);
2206 /* Server side of LIST command. This lists the channel of the requested
2207 server. Secret channels are not listed. */
2209 SILC_SERVER_CMD_FUNC(list)
2211 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2212 SilcServer server = cmd->server;
2213 SilcChannelID *channel_id = NULL;
2216 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2217 SilcUInt32 lch_count = 0, gch_count = 0;
2219 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2221 /* If we are normal server, send the command to router, since we
2222 want to know all channels in the network. */
2223 if (!cmd->pending && server->server_type == SILC_SERVER &&
2224 !server->standalone) {
2226 SilcUInt16 old_ident;
2228 old_ident = silc_command_get_ident(cmd->payload);
2229 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2230 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2231 silc_server_packet_send(server, server->router->connection,
2232 SILC_PACKET_COMMAND, cmd->packet->flags,
2233 tmpbuf->data, tmpbuf->len, TRUE);
2235 /* Reprocess this packet after received reply from router */
2236 silc_server_command_pending(server, SILC_COMMAND_LIST,
2237 silc_command_get_ident(cmd->payload),
2238 silc_server_command_list,
2239 silc_server_command_dup(cmd));
2240 cmd->pending = TRUE;
2241 silc_command_set_ident(cmd->payload, old_ident);
2242 silc_buffer_free(tmpbuf);
2246 /* Get Channel ID */
2247 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2249 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2252 SILC_STATUS_ERR_NO_CHANNEL_ID);
2257 /* Get the channels from local list */
2258 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2261 /* Get the channels from global list */
2262 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2265 /* Send the reply */
2266 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2267 gchannels, gch_count);
2269 silc_free(lchannels);
2270 silc_free(gchannels);
2273 silc_server_command_free(cmd);
2276 /* Server side of TOPIC command. Sets topic for channel and/or returns
2277 current topic to client. */
2279 SILC_SERVER_CMD_FUNC(topic)
2281 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2282 SilcServer server = cmd->server;
2283 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2284 SilcChannelID *channel_id;
2285 SilcChannelEntry channel;
2286 SilcChannelClientEntry chl;
2287 SilcBuffer packet, idp;
2289 SilcUInt32 argc, tmp_len;
2290 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2292 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2294 argc = silc_argument_get_arg_num(cmd->args);
2296 /* Get Channel ID */
2297 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2300 SILC_STATUS_ERR_NO_CHANNEL_ID);
2303 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2306 SILC_STATUS_ERR_NO_CHANNEL_ID);
2310 /* Check whether the channel exists */
2311 channel = silc_idlist_find_channel_by_id(server->local_list,
2314 channel = silc_idlist_find_channel_by_id(server->global_list,
2317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2318 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2325 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2328 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2332 if (strlen(tmp) > 256) {
2333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2334 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2338 /* See whether the client is on channel and has rights to change topic */
2339 if (!silc_server_client_on_channel(client, channel, &chl)) {
2340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2341 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2345 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2346 channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2348 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2352 /* Set the topic for channel */
2353 silc_free(channel->topic);
2354 channel->topic = strdup(tmp);
2356 /* Send TOPIC_SET notify type to the network */
2357 if (!server->standalone)
2358 silc_server_send_notify_topic_set(server, server->router->connection,
2359 server->server_type == SILC_ROUTER ?
2360 TRUE : FALSE, channel,
2361 client->id, SILC_ID_CLIENT,
2364 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2366 /* Send notify about topic change to all clients on the channel */
2367 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2368 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2369 idp->data, idp->len,
2370 channel->topic, strlen(channel->topic));
2371 silc_buffer_free(idp);
2374 /* Send the topic to client as reply packet */
2375 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2376 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2377 SILC_STATUS_OK, 0, ident, 2,
2378 2, idp->data, idp->len,
2381 strlen(channel->topic) : 0);
2382 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2383 0, packet->data, packet->len, FALSE);
2385 silc_buffer_free(packet);
2386 silc_buffer_free(idp);
2387 silc_free(channel_id);
2390 silc_server_command_free(cmd);
2393 /* Server side of INVITE command. Invites some client to join some channel.
2394 This command is also used to manage the invite list of the channel. */
2396 SILC_SERVER_CMD_FUNC(invite)
2398 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2399 SilcServer server = cmd->server;
2400 SilcSocketConnection sock = cmd->sock, dest_sock;
2401 SilcChannelClientEntry chl;
2402 SilcClientEntry sender, dest;
2403 SilcClientID *dest_id = NULL;
2404 SilcChannelEntry channel;
2405 SilcChannelID *channel_id = NULL;
2406 SilcIDListData idata;
2407 SilcBuffer idp, idp2, packet;
2408 unsigned char *tmp, *add, *del;
2410 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2412 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2414 /* Get Channel ID */
2415 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2418 SILC_STATUS_ERR_NO_CHANNEL_ID);
2421 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2424 SILC_STATUS_ERR_NO_CHANNEL_ID);
2428 /* Get the channel entry */
2429 channel = silc_idlist_find_channel_by_id(server->local_list,
2432 channel = silc_idlist_find_channel_by_id(server->global_list,
2435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2436 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2441 /* Check whether the sender of this command is on the channel. */
2442 sender = (SilcClientEntry)sock->user_data;
2443 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2445 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2449 /* Check whether the channel is invite-only channel. If yes then the
2450 sender of this command must be at least channel operator. */
2451 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2452 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2454 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2458 /* Get destination client ID */
2459 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2464 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2467 SILC_STATUS_ERR_NO_CLIENT_ID);
2471 /* Get the client entry */
2472 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2474 if (server->server_type != SILC_SERVER || !resolve) {
2475 silc_server_command_send_status_reply(
2476 cmd, SILC_COMMAND_INVITE,
2477 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2481 /* The client info is being resolved. Reprocess this packet after
2482 receiving the reply to the query. */
2483 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2485 silc_server_command_invite,
2486 silc_server_command_dup(cmd));
2487 cmd->pending = TRUE;
2488 silc_free(channel_id);
2493 /* Check whether the requested client is already on the channel. */
2494 if (silc_server_client_on_channel(dest, channel, NULL)) {
2495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2496 SILC_STATUS_ERR_USER_ON_CHANNEL);
2500 /* Get route to the client */
2501 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2505 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2509 memset(invite, 0, sizeof(invite));
2510 strncat(invite, dest->nickname, strlen(dest->nickname));
2511 strncat(invite, "!", 1);
2512 strncat(invite, dest->username, strlen(dest->username));
2513 if (!strchr(dest->username, '@')) {
2514 strncat(invite, "@", 1);
2515 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2518 len = strlen(invite);
2519 if (!channel->invite_list)
2520 channel->invite_list = silc_calloc(len + 2,
2521 sizeof(*channel->invite_list));
2523 channel->invite_list = silc_realloc(channel->invite_list,
2524 sizeof(*channel->invite_list) *
2526 strlen(channel->invite_list) + 2));
2527 strncat(channel->invite_list, invite, len);
2528 strncat(channel->invite_list, ",", 1);
2530 /* Send notify to the client that is invited to the channel */
2531 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2532 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2533 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2535 SILC_NOTIFY_TYPE_INVITE, 3,
2536 idp->data, idp->len,
2537 channel->channel_name,
2538 strlen(channel->channel_name),
2539 idp2->data, idp2->len);
2540 silc_buffer_free(idp);
2541 silc_buffer_free(idp2);
2544 /* Add the client to the invite list of the channel */
2545 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2547 if (!channel->invite_list)
2548 channel->invite_list = silc_calloc(len + 2,
2549 sizeof(*channel->invite_list));
2551 channel->invite_list = silc_realloc(channel->invite_list,
2552 sizeof(*channel->invite_list) *
2554 strlen(channel->invite_list) + 2));
2555 if (add[len - 1] == ',')
2556 add[len - 1] = '\0';
2558 strncat(channel->invite_list, add, len);
2559 strncat(channel->invite_list, ",", 1);
2562 /* Get the invite to be removed and remove it from the list */
2563 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2564 if (del && channel->invite_list) {
2565 char *start, *end, *n;
2567 if (!strncmp(channel->invite_list, del,
2568 strlen(channel->invite_list) - 1)) {
2569 silc_free(channel->invite_list);
2570 channel->invite_list = NULL;
2572 start = strstr(channel->invite_list, del);
2573 if (start && strlen(start) >= len) {
2575 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2576 strncat(n, channel->invite_list, start - channel->invite_list);
2577 strncat(n, end + 1, ((channel->invite_list +
2578 strlen(channel->invite_list)) - end) - 1);
2579 silc_free(channel->invite_list);
2580 channel->invite_list = n;
2585 /* Send notify to the primary router */
2586 if (!server->standalone)
2587 silc_server_send_notify_invite(server, server->router->connection,
2588 server->server_type == SILC_ROUTER ?
2589 TRUE : FALSE, channel,
2590 sender->id, add, del);
2592 /* Send command reply */
2593 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2597 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2598 SILC_STATUS_OK, 0, ident, 2,
2600 3, channel->invite_list,
2601 channel->invite_list ?
2602 strlen(channel->invite_list) : 0);
2605 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2606 SILC_STATUS_OK, 0, ident, 1,
2608 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2609 packet->data, packet->len, FALSE);
2610 silc_buffer_free(packet);
2614 silc_free(channel_id);
2615 silc_server_command_free(cmd);
2620 SilcSocketConnection sock;
2624 /* Quits connection to client. This gets called if client won't
2625 close the connection even when it has issued QUIT command. */
2627 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2629 QuitInternal q = (QuitInternal)context;
2631 /* Free all client specific data, such as client entry and entires
2632 on channels this client may be on. */
2633 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2635 q->sock->user_data = NULL;
2637 /* Close the connection on our side */
2638 silc_server_close_connection(q->server, q->sock);
2640 silc_free(q->signoff);
2644 /* Quits SILC session. This is the normal way to disconnect client. */
2646 SILC_SERVER_CMD_FUNC(quit)
2648 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2649 SilcServer server = cmd->server;
2650 SilcSocketConnection sock = cmd->sock;
2652 unsigned char *tmp = NULL;
2655 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2657 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2661 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2665 q = silc_calloc(1, sizeof(*q));
2668 q->signoff = tmp ? strdup(tmp) : NULL;
2670 /* We quit the connection with little timeout */
2671 silc_schedule_task_add(server->schedule, sock->sock,
2672 silc_server_command_quit_cb, (void *)q,
2673 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2676 silc_server_command_free(cmd);
2679 /* Server side of command KILL. This command is used by router operator
2680 to remove an client from the SILC Network temporarily. */
2682 SILC_SERVER_CMD_FUNC(kill)
2684 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2685 SilcServer server = cmd->server;
2686 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2687 SilcClientEntry remote_client;
2688 SilcClientID *client_id;
2689 unsigned char *tmp, *comment;
2690 SilcUInt32 tmp_len, tmp_len2;
2693 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2695 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2698 /* KILL command works only on router */
2699 if (server->server_type != SILC_ROUTER) {
2700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2701 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2705 /* Check whether client has the permissions. */
2706 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2707 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2708 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2712 /* Get the client ID */
2713 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2716 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2719 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2722 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2726 /* Get the client entry */
2727 remote_client = silc_idlist_find_client_by_id(server->local_list,
2728 client_id, TRUE, NULL);
2730 if (!remote_client) {
2731 remote_client = silc_idlist_find_client_by_id(server->global_list,
2732 client_id, TRUE, NULL);
2734 if (!remote_client) {
2735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2736 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2742 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2746 /* Send reply to the sender */
2747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2750 /* Now do the killing */
2751 silc_server_kill_client(server, remote_client, comment, client->id,
2755 silc_server_command_free(cmd);
2758 /* Server side of command INFO. This sends information about us to
2759 the client. If client requested specific server we will send the
2760 command to that server. */
2762 SILC_SERVER_CMD_FUNC(info)
2764 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2765 SilcServer server = cmd->server;
2766 SilcBuffer packet, idp;
2769 char *dest_server, *server_info = NULL, *server_name;
2770 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2771 SilcServerEntry entry = NULL;
2772 SilcServerID *server_id = NULL;
2774 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2776 /* Get server name */
2777 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2780 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2782 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2785 SILC_STATUS_ERR_NO_SERVER_ID);
2791 /* Check whether we have this server cached */
2792 entry = silc_idlist_find_server_by_id(server->local_list,
2793 server_id, TRUE, NULL);
2795 entry = silc_idlist_find_server_by_id(server->global_list,
2796 server_id, TRUE, NULL);
2797 if (!entry && server->server_type != SILC_SERVER) {
2798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2799 SILC_STATUS_ERR_NO_SUCH_SERVER);
2805 /* Some buggy servers has sent request to router about themselves. */
2806 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2809 if ((!dest_server && !server_id && !entry) || (entry &&
2810 entry == server->id_entry) ||
2811 (dest_server && !cmd->pending &&
2812 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2813 /* Send our reply */
2814 char info_string[256];
2816 memset(info_string, 0, sizeof(info_string));
2817 snprintf(info_string, sizeof(info_string),
2818 "location: %s server: %s admin: %s <%s>",
2819 server->config->server_info->location,
2820 server->config->server_info->server_type,
2821 server->config->server_info->admin,
2822 server->config->server_info->email);
2824 server_info = info_string;
2825 entry = server->id_entry;
2827 /* Check whether we have this server cached */
2828 if (!entry && dest_server) {
2829 entry = silc_idlist_find_server_by_name(server->global_list,
2830 dest_server, TRUE, NULL);
2832 entry = silc_idlist_find_server_by_name(server->local_list,
2833 dest_server, TRUE, NULL);
2837 if (!cmd->pending &&
2838 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2839 /* Send to the server */
2841 SilcUInt16 old_ident;
2843 old_ident = silc_command_get_ident(cmd->payload);
2844 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2845 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2847 silc_server_packet_send(server, entry->connection,
2848 SILC_PACKET_COMMAND, cmd->packet->flags,
2849 tmpbuf->data, tmpbuf->len, TRUE);
2851 /* Reprocess this packet after received reply from router */
2852 silc_server_command_pending(server, SILC_COMMAND_INFO,
2853 silc_command_get_ident(cmd->payload),
2854 silc_server_command_info,
2855 silc_server_command_dup(cmd));
2856 cmd->pending = TRUE;
2857 silc_command_set_ident(cmd->payload, old_ident);
2858 silc_buffer_free(tmpbuf);
2862 if (!entry && !cmd->pending && !server->standalone) {
2863 /* Send to the primary router */
2865 SilcUInt16 old_ident;
2867 old_ident = silc_command_get_ident(cmd->payload);
2868 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2869 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2871 silc_server_packet_send(server, server->router->connection,
2872 SILC_PACKET_COMMAND, cmd->packet->flags,
2873 tmpbuf->data, tmpbuf->len, TRUE);
2875 /* Reprocess this packet after received reply from router */
2876 silc_server_command_pending(server, SILC_COMMAND_INFO,
2877 silc_command_get_ident(cmd->payload),
2878 silc_server_command_info,
2879 silc_server_command_dup(cmd));
2880 cmd->pending = TRUE;
2881 silc_command_set_ident(cmd->payload, old_ident);
2882 silc_buffer_free(tmpbuf);
2887 silc_free(server_id);
2890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2891 SILC_STATUS_ERR_NO_SUCH_SERVER);
2895 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2897 server_info = entry->server_info;
2898 server_name = entry->server_name;
2900 /* Send the reply */
2901 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2902 SILC_STATUS_OK, 0, ident, 3,
2903 2, idp->data, idp->len,
2905 strlen(server_name),
2908 strlen(server_info) : 0);
2909 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2910 packet->data, packet->len, FALSE);
2912 silc_buffer_free(packet);
2913 silc_buffer_free(idp);
2916 silc_server_command_free(cmd);
2919 /* Server side of command PING. This just replies to the ping. */
2921 SILC_SERVER_CMD_FUNC(ping)
2923 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2924 SilcServer server = cmd->server;
2929 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2932 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2935 SILC_STATUS_ERR_NO_SERVER_ID);
2938 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2942 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2943 /* Send our reply */
2944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2948 SILC_STATUS_ERR_NO_SUCH_SERVER);
2955 silc_server_command_free(cmd);
2958 /* Server side of command STATS. */
2960 SILC_SERVER_CMD_FUNC(stats)
2962 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2963 SilcServer server = cmd->server;
2964 SilcServerID *server_id;
2967 SilcBuffer packet, stats;
2968 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2971 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
2974 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2977 SILC_STATUS_ERR_NO_SERVER_ID);
2980 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2984 /* The ID must be ours */
2985 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
2986 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2987 SILC_STATUS_ERR_NO_SUCH_SERVER);
2988 silc_free(server_id);
2991 silc_free(server_id);
2993 /* If we are router then just send everything we got. If we are normal
2994 server then we'll send this to our router to get all the latest
2995 statistical information. */
2996 if (!cmd->pending && server->server_type != SILC_ROUTER &&
2997 !server->standalone) {
2998 /* Send request to our router */
2999 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3001 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3002 ++server->cmd_ident, 1,
3003 1, idp->data, idp->len);
3004 silc_server_packet_send(server, server->router->connection,
3005 SILC_PACKET_COMMAND, 0, packet->data,
3006 packet->len, FALSE);
3008 /* Reprocess this packet after received reply from router */
3009 silc_server_command_pending(server, SILC_COMMAND_STATS,
3011 silc_server_command_stats,
3012 silc_server_command_dup(cmd));
3013 cmd->pending = TRUE;
3014 silc_buffer_free(packet);
3015 silc_buffer_free(idp);
3019 /* Send our reply to sender */
3020 uptime = time(NULL) - server->starttime;
3022 stats = silc_buffer_alloc_size(60);
3023 silc_buffer_format(stats,
3024 SILC_STR_UI_INT(server->starttime),
3025 SILC_STR_UI_INT(uptime),
3026 SILC_STR_UI_INT(server->stat.my_clients),
3027 SILC_STR_UI_INT(server->stat.my_channels),
3028 SILC_STR_UI_INT(server->stat.my_server_ops),
3029 SILC_STR_UI_INT(server->stat.my_router_ops),
3030 SILC_STR_UI_INT(server->stat.cell_clients),
3031 SILC_STR_UI_INT(server->stat.cell_channels),
3032 SILC_STR_UI_INT(server->stat.cell_servers),
3033 SILC_STR_UI_INT(server->stat.clients),
3034 SILC_STR_UI_INT(server->stat.channels),
3035 SILC_STR_UI_INT(server->stat.servers),
3036 SILC_STR_UI_INT(server->stat.routers),
3037 SILC_STR_UI_INT(server->stat.server_ops),
3038 SILC_STR_UI_INT(server->stat.router_ops),
3041 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3042 SILC_STATUS_OK, 0, ident, 2,
3044 3, stats->data, stats->len);
3045 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3046 0, packet->data, packet->len, FALSE);
3047 silc_buffer_free(packet);
3048 silc_buffer_free(stats);
3051 silc_server_command_free(cmd);
3054 /* Internal routine to join channel. The channel sent to this function
3055 has been either created or resolved from ID lists. This joins the sent
3056 client to the channel. */
3058 static void silc_server_command_join_channel(SilcServer server,
3059 SilcServerCommandContext cmd,
3060 SilcChannelEntry channel,
3061 SilcClientID *client_id,
3065 const unsigned char *auth,
3066 SilcUInt32 auth_len)
3068 SilcSocketConnection sock = cmd->sock;
3070 SilcUInt32 tmp_len, user_count;
3071 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3072 SilcClientEntry client;
3073 SilcChannelClientEntry chl;
3074 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3075 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3076 char check[512], check2[512];
3077 bool founder = FALSE;
3080 SILC_LOG_DEBUG(("Start"));
3085 /* Get the client entry */
3086 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3087 client = (SilcClientEntry)sock->user_data;
3089 client = silc_server_get_client_resolve(server, client_id, FALSE,
3096 silc_server_command_send_status_reply(
3097 cmd, SILC_COMMAND_JOIN,
3098 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3102 /* The client info is being resolved. Reprocess this packet after
3103 receiving the reply to the query. */
3104 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3106 silc_server_command_join,
3107 silc_server_command_dup(cmd));
3108 cmd->pending = TRUE;
3112 cmd->pending = FALSE;
3116 * Check founder auth payload if provided. If client can gain founder
3117 * privileges it can override various conditions on joining the channel,
3118 * and can have directly the founder mode set on the channel.
3120 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3121 SilcIDListData idata = (SilcIDListData)client;
3123 if (channel->founder_key && idata->public_key &&
3124 silc_pkcs_public_key_compare(channel->founder_key,
3125 idata->public_key)) {
3126 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3127 (void *)channel->founder_passwd :
3128 (void *)channel->founder_key);
3129 SilcUInt32 auth_data_len =
3130 (channel->founder_method == SILC_AUTH_PASSWORD ?
3131 channel->founder_passwd_len : 0);
3133 /* Check whether the client is to become founder */
3134 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3135 auth_data, auth_data_len,
3136 idata->hash, client->id, SILC_ID_CLIENT)) {
3137 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3144 * Check channel modes
3148 memset(check, 0, sizeof(check));
3149 memset(check2, 0, sizeof(check2));
3150 strncat(check, client->nickname, strlen(client->nickname));
3151 strncat(check, "!", 1);
3152 strncat(check, client->username, strlen(client->username));
3153 if (!strchr(client->username, '@')) {
3154 strncat(check, "@", 1);
3155 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3158 strncat(check2, client->nickname, strlen(client->nickname));
3159 if (!strchr(client->nickname, '@')) {
3160 strncat(check2, "@", 1);
3161 strncat(check2, server->server_name, strlen(server->server_name));
3163 strncat(check2, "!", 1);
3164 strncat(check2, client->username, strlen(client->username));
3165 if (!strchr(client->username, '@')) {
3166 strncat(check2, "@", 1);
3167 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3170 /* Check invite list if channel is invite-only channel */
3171 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3172 if (!channel->invite_list ||
3173 (!silc_string_match(channel->invite_list, check) &&
3174 !silc_string_match(channel->invite_list, check2))) {
3175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3176 SILC_STATUS_ERR_NOT_INVITED);
3181 /* Check ban list if it exists. If the client's nickname, server,
3182 username and/or hostname is in the ban list the access to the
3183 channel is denied. */
3184 if (channel->ban_list) {
3185 if (silc_string_match(channel->ban_list, check) ||
3186 silc_string_match(channel->ban_list, check2)) {
3187 silc_server_command_send_status_reply(
3188 cmd, SILC_COMMAND_JOIN,
3189 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3194 /* Check user count limit if set. */
3195 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3196 if (silc_hash_table_count(channel->user_list) + 1 >
3197 channel->user_limit) {
3198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3199 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3205 /* Check the channel passphrase if set. */
3206 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3207 /* Get passphrase */
3208 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3210 passphrase = silc_memdup(tmp, tmp_len);
3212 if (!passphrase || !channel->passphrase ||
3213 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3214 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3215 SILC_STATUS_ERR_BAD_PASSWORD);
3221 * Client is allowed to join to the channel. Make it happen.
3224 /* Check whether the client already is on the channel */
3225 if (silc_server_client_on_channel(client, channel, NULL)) {
3226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3227 SILC_STATUS_ERR_USER_ON_CHANNEL);
3231 /* Generate new channel key as protocol dictates */
3233 if (!silc_server_create_channel_key(server, channel, 0))
3236 /* Send the channel key. This is broadcasted to the channel but is not
3237 sent to the client who is joining to the channel. */
3238 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3239 silc_server_send_channel_key(server, NULL, channel,
3240 server->server_type == SILC_ROUTER ?
3241 FALSE : !server->standalone);
3244 /* Join the client to the channel by adding it to channel's user list.
3245 Add also the channel to client entry's channels list for fast cross-
3247 chl = silc_calloc(1, sizeof(*chl));
3249 chl->client = client;
3250 chl->channel = channel;
3251 silc_hash_table_add(channel->user_list, client, chl);
3252 silc_hash_table_add(client->channels, channel, chl);
3253 channel->user_count++;
3255 /* Get users on the channel */
3256 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3259 /* Encode Client ID Payload of the original client who wants to join */
3260 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3262 /* Encode command reply packet */
3263 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3264 SILC_PUT32_MSB(channel->mode, mode);
3265 SILC_PUT32_MSB(created, tmp2);
3266 SILC_PUT32_MSB(user_count, tmp3);
3268 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3269 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3270 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3273 strlen(channel->channel_key->
3275 channel->channel_key->cipher->name,
3276 channel->key_len / 8, channel->key);
3281 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3282 SILC_STATUS_OK, 0, ident, 13,
3283 2, channel->channel_name,
3284 strlen(channel->channel_name),
3285 3, chidp->data, chidp->len,
3286 4, clidp->data, clidp->len,
3289 7, keyp ? keyp->data : NULL,
3290 keyp ? keyp->len : 0,
3291 8, channel->ban_list,
3293 strlen(channel->ban_list) : 0,
3294 9, channel->invite_list,
3295 channel->invite_list ?
3296 strlen(channel->invite_list) : 0,
3299 strlen(channel->topic) : 0,
3300 11, silc_hmac_get_name(channel->hmac),
3301 strlen(silc_hmac_get_name(channel->
3304 13, user_list->data, user_list->len,
3305 14, mode_list->data,
3308 /* Send command reply */
3309 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3310 reply->data, reply->len, FALSE);
3312 /* Send JOIN notify to locally connected clients on the channel. If
3313 we are normal server then router will send or have sent JOIN notify
3314 already. However since we've added the client already to our channel
3315 we'll ignore it (in packet_receive.c) so we must send it here. If
3316 we are router then this will send it to local clients and local
3318 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3319 SILC_NOTIFY_TYPE_JOIN, 2,
3320 clidp->data, clidp->len,
3321 chidp->data, chidp->len);
3323 if (!cmd->pending) {
3324 /* Send JOIN notify packet to our primary router */
3325 if (!server->standalone)
3326 silc_server_send_notify_join(server, server->router->connection,
3327 server->server_type == SILC_ROUTER ?
3328 TRUE : FALSE, channel, client->id);
3331 /* Distribute the channel key to all backup routers. */
3332 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3333 keyp->data, keyp->len, FALSE, TRUE);
3336 /* If client became founder by providing correct founder auth data
3337 notify the mode change to the channel. */
3339 SILC_PUT32_MSB(chl->mode, mode);
3340 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3341 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3342 clidp->data, clidp->len,
3343 mode, 4, clidp->data, clidp->len);
3345 /* Set CUMODE notify type to network */
3346 if (!server->standalone)
3347 silc_server_send_notify_cumode(server, server->router->connection,
3348 server->server_type == SILC_ROUTER ?
3349 TRUE : FALSE, channel,
3350 chl->mode, client->id, SILC_ID_CLIENT,
3354 silc_buffer_free(reply);
3355 silc_buffer_free(clidp);
3356 silc_buffer_free(chidp);
3357 silc_buffer_free(keyp);
3358 silc_buffer_free(user_list);
3359 silc_buffer_free(mode_list);
3362 silc_free(passphrase);
3365 /* Server side of command JOIN. Joins client into requested channel. If
3366 the channel does not exist it will be created. */
3368 SILC_SERVER_CMD_FUNC(join)
3370 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3371 SilcServer server = cmd->server;
3372 unsigned char *auth;
3373 SilcUInt32 tmp_len, auth_len;
3374 char *tmp, *channel_name = NULL, *cipher, *hmac;
3375 SilcChannelEntry channel;
3376 SilcUInt32 umode = 0;
3377 bool created = FALSE, create_key = TRUE;
3378 SilcClientID *client_id;
3380 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3382 /* Get channel name */
3383 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3386 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3392 channel_name[255] = '\0';
3394 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3396 SILC_STATUS_ERR_BAD_CHANNEL);
3400 /* Get Client ID of the client who is joining to the channel */
3401 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3404 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3407 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3410 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3414 /* Get cipher, hmac name and auth payload */
3415 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3416 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3417 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3419 /* See if the channel exists */
3420 channel = silc_idlist_find_channel_by_name(server->local_list,
3421 channel_name, NULL);
3423 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3424 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3425 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3427 if (!channel || channel->disabled) {
3428 /* Channel not found */
3430 /* If we are standalone server we don't have a router, we just create
3431 the channel by ourselves. */
3432 if (server->standalone) {
3433 channel = silc_server_create_new_channel(server, server->id, cipher,
3434 hmac, channel_name, TRUE);
3436 silc_server_command_send_status_reply(
3437 cmd, SILC_COMMAND_JOIN,
3438 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3442 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3448 /* The channel does not exist on our server. If we are normal server
3449 we will send JOIN command to our router which will handle the
3450 joining procedure (either creates the channel if it doesn't exist
3451 or joins the client to it). */
3452 if (server->server_type != SILC_ROUTER) {
3454 SilcUInt16 old_ident;
3456 /* If this is pending command callback then we've resolved
3457 it and it didn't work, return since we've notified the
3458 client already in the command reply callback. */
3462 old_ident = silc_command_get_ident(cmd->payload);
3463 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3464 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3466 /* Send JOIN command to our router */
3467 silc_server_packet_send(server, (SilcSocketConnection)
3468 server->router->connection,
3469 SILC_PACKET_COMMAND, cmd->packet->flags,
3470 tmpbuf->data, tmpbuf->len, TRUE);
3472 /* Reprocess this packet after received reply from router */
3473 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3474 silc_command_get_ident(cmd->payload),
3475 silc_server_command_join,
3476 silc_server_command_dup(cmd));
3477 cmd->pending = TRUE;
3478 silc_command_set_ident(cmd->payload, old_ident);
3479 silc_buffer_free(tmpbuf);
3483 /* We are router and the channel does not seem exist so we will check
3484 our global list as well for the channel. */
3485 channel = silc_idlist_find_channel_by_name(server->global_list,
3486 channel_name, NULL);
3488 /* Channel really does not exist, create it */
3489 channel = silc_server_create_new_channel(server, server->id, cipher,
3490 hmac, channel_name, TRUE);
3492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3493 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3497 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3505 /* Channel not found */
3507 /* If the command came from router and we are normal server then
3508 something went wrong with the joining as the channel was not found.
3509 We can't do anything else but ignore this. */
3510 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3511 server->server_type != SILC_ROUTER)
3514 /* We are router and the channel does not seem exist so we will check
3515 our global list as well for the channel. */
3516 channel = silc_idlist_find_channel_by_name(server->global_list,
3517 channel_name, NULL);
3519 /* Channel really does not exist, create it */
3520 channel = silc_server_create_new_channel(server, server->id, cipher,
3521 hmac, channel_name, TRUE);
3523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3524 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3528 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3535 /* Check whether the channel was created by our router */
3536 if (cmd->pending && context2) {
3537 SilcServerCommandReplyContext reply = context2;
3539 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3540 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3541 SILC_GET32_MSB(created, tmp);
3542 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3543 create_key = FALSE; /* Router returned the key already */
3546 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3547 !silc_hash_table_count(channel->user_list))
3551 /* If the channel does not have global users and is also empty the client
3552 will be the channel founder and operator. */
3553 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3554 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3556 /* Join to the channel */
3557 silc_server_command_join_channel(server, cmd, channel, client_id,
3558 created, create_key, umode,
3561 silc_free(client_id);
3564 silc_server_command_free(cmd);
3567 /* Server side of command MOTD. Sends server's current "message of the
3568 day" to the client. */
3570 SILC_SERVER_CMD_FUNC(motd)
3572 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3573 SilcServer server = cmd->server;
3574 SilcBuffer packet, idp;
3575 char *motd, *dest_server;
3576 SilcUInt32 motd_len;
3577 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3579 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3581 /* Get server name */
3582 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3585 SILC_STATUS_ERR_NO_SUCH_SERVER);
3589 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3592 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3594 if (server->config && server->config->server_info &&
3595 server->config->server_info->motd_file) {
3597 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3602 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3609 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3615 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3616 packet->data, packet->len, FALSE);
3617 silc_buffer_free(packet);
3618 silc_buffer_free(idp);
3620 SilcServerEntry entry;
3622 /* Check whether we have this server cached */
3623 entry = silc_idlist_find_server_by_name(server->global_list,
3624 dest_server, TRUE, NULL);
3626 entry = silc_idlist_find_server_by_name(server->local_list,
3627 dest_server, TRUE, NULL);
3630 if (server->server_type != SILC_SERVER && !cmd->pending &&
3631 entry && !entry->motd) {
3632 /* Send to the server */
3634 SilcUInt16 old_ident;
3636 old_ident = silc_command_get_ident(cmd->payload);
3637 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3638 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3640 silc_server_packet_send(server, entry->connection,
3641 SILC_PACKET_COMMAND, cmd->packet->flags,
3642 tmpbuf->data, tmpbuf->len, TRUE);
3644 /* Reprocess this packet after received reply from router */
3645 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3646 silc_command_get_ident(cmd->payload),
3647 silc_server_command_motd,
3648 silc_server_command_dup(cmd));
3649 cmd->pending = TRUE;
3650 silc_command_set_ident(cmd->payload, old_ident);
3651 silc_buffer_free(tmpbuf);
3655 if (!entry && !cmd->pending && !server->standalone) {
3656 /* Send to the primary router */
3658 SilcUInt16 old_ident;
3660 old_ident = silc_command_get_ident(cmd->payload);
3661 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3662 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3664 silc_server_packet_send(server, server->router->connection,
3665 SILC_PACKET_COMMAND, cmd->packet->flags,
3666 tmpbuf->data, tmpbuf->len, TRUE);
3668 /* Reprocess this packet after received reply from router */
3669 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3670 silc_command_get_ident(cmd->payload),
3671 silc_server_command_motd,
3672 silc_server_command_dup(cmd));
3673 cmd->pending = TRUE;
3674 silc_command_set_ident(cmd->payload, old_ident);
3675 silc_buffer_free(tmpbuf);
3680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3681 SILC_STATUS_ERR_NO_SUCH_SERVER);
3685 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3686 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3687 SILC_STATUS_OK, 0, ident, 2,
3691 strlen(entry->motd) : 0);
3692 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3693 packet->data, packet->len, FALSE);
3694 silc_buffer_free(packet);
3695 silc_buffer_free(idp);
3699 silc_server_command_free(cmd);
3702 /* Server side of command UMODE. Client can use this command to set/unset
3703 user mode. Client actually cannot set itself to be as server/router
3704 operator so this can be used only to unset the modes. */
3706 SILC_SERVER_CMD_FUNC(umode)
3708 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3709 SilcServer server = cmd->server;
3710 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3712 unsigned char *tmp_mask, m[4];
3713 SilcUInt32 mask = 0;
3714 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3715 bool set_mask = FALSE;
3717 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3720 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3722 /* Get the client's mode mask */
3723 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3725 SILC_GET32_MSB(mask, tmp_mask);
3730 /* Check that mode changing is allowed. */
3731 if (!silc_server_check_umode_rights(server, client, mask)) {
3732 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3733 SILC_STATUS_ERR_PERM_DENIED);
3737 /* Anonymous mode cannot be set by client */
3738 if (mask & SILC_UMODE_ANONYMOUS) {
3739 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3740 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3741 SILC_STATUS_ERR_PERM_DENIED);
3745 if (client->mode & SILC_UMODE_ANONYMOUS) {
3746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3747 SILC_STATUS_ERR_PERM_DENIED);
3752 /* Change the mode */
3753 client->mode = mask;
3755 /* Send UMODE change to primary router */
3756 if (!server->standalone)
3757 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3758 client->id, client->mode);
3761 /* Send command reply to sender */
3762 SILC_PUT32_MSB(client->mode, m);
3763 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3764 SILC_STATUS_OK, 0, ident, 1,
3766 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3767 packet->data, packet->len, FALSE);
3768 silc_buffer_free(packet);
3771 silc_server_command_free(cmd);
3774 /* Server side command of CMODE. Changes channel mode */
3776 SILC_SERVER_CMD_FUNC(cmode)
3778 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3779 SilcServer server = cmd->server;
3780 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3781 SilcIDListData idata = (SilcIDListData)client;
3782 SilcChannelID *channel_id = NULL;
3783 SilcChannelEntry channel;
3784 SilcChannelClientEntry chl;
3785 SilcBuffer packet, cidp;
3786 unsigned char *tmp, *tmp_id, *tmp_mask;
3787 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3788 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3789 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3790 bool set_mask = FALSE;
3792 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3794 /* Get Channel ID */
3795 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3798 SILC_STATUS_ERR_NO_CHANNEL_ID);
3801 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3804 SILC_STATUS_ERR_NO_CHANNEL_ID);
3808 /* Get the channel mode mask */
3809 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3811 SILC_GET32_MSB(mode_mask, tmp_mask);
3815 /* Get channel entry */
3816 channel = silc_idlist_find_channel_by_id(server->local_list,
3819 channel = silc_idlist_find_channel_by_id(server->global_list,
3822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3823 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3828 /* Check whether this client is on the channel */
3829 if (!silc_server_client_on_channel(client, channel, &chl)) {
3830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3831 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3835 /* Check that client has rights to change any requested channel modes */
3836 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3840 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3841 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3845 /* If mode mask was not sent as argument then merely return the current
3846 mode mask to the sender. */
3849 SILC_PUT32_MSB(channel->mode, m);
3850 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3851 SILC_STATUS_OK, 0, ident, 2,
3852 2, tmp_id, tmp_len2,
3854 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3855 packet->data, packet->len, FALSE);
3856 silc_buffer_free(packet);
3861 * Check the modes. Modes that requires nothing special operation are
3865 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3866 /* Channel uses private keys to protect traffic. Client(s) has set the
3867 key locally they want to use, server does not know that key. */
3868 /* Nothing interesting to do here */
3870 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3871 /* The mode is removed and we need to generate and distribute
3872 new channel key. Clients are not using private channel keys
3873 anymore after this. */
3875 /* Re-generate channel key */
3876 if (!silc_server_create_channel_key(server, channel, 0))
3879 /* Send the channel key. This sends it to our local clients and if
3880 we are normal server to our router as well. */
3881 silc_server_send_channel_key(server, NULL, channel,
3882 server->server_type == SILC_ROUTER ?
3883 FALSE : !server->standalone);
3885 cipher = channel->channel_key->cipher->name;
3886 hmac = (char *)silc_hmac_get_name(channel->hmac);
3890 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3891 /* User limit is set on channel */
3892 SilcUInt32 user_limit;
3894 /* Get user limit */
3895 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3897 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3898 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3899 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3903 SILC_GET32_MSB(user_limit, tmp);
3904 channel->user_limit = user_limit;
3907 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3908 /* User limit mode is unset. Remove user limit */
3909 channel->user_limit = 0;
3912 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3913 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3914 /* Passphrase has been set to channel */
3916 /* Get the passphrase */
3917 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3919 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3920 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3924 /* Save the passphrase */
3925 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3928 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3929 /* Passphrase mode is unset. remove the passphrase */
3930 silc_free(channel->passphrase);
3931 channel->passphrase = NULL;
3935 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3936 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3937 /* Cipher to use protect the traffic */
3938 SilcCipher newkey, oldkey;
3941 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3944 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3948 /* Delete old cipher and allocate the new one */
3949 if (!silc_cipher_alloc(cipher, &newkey)) {
3950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3951 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3955 oldkey = channel->channel_key;
3956 channel->channel_key = newkey;
3958 /* Re-generate channel key */
3959 if (!silc_server_create_channel_key(server, channel, 0)) {
3960 /* We don't have new key, revert to old one */
3961 channel->channel_key = oldkey;
3965 /* Remove old channel key for good */
3966 silc_cipher_free(oldkey);
3968 /* Send the channel key. This sends it to our local clients and if
3969 we are normal server to our router as well. */
3970 silc_server_send_channel_key(server, NULL, channel,
3971 server->server_type == SILC_ROUTER ?
3972 FALSE : !server->standalone);
3975 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3976 /* Cipher mode is unset. Remove the cipher and revert back to
3978 SilcCipher newkey, oldkey;
3979 cipher = channel->cipher;
3981 /* Delete old cipher and allocate default one */
3982 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3984 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3988 oldkey = channel->channel_key;
3989 channel->channel_key = newkey;
3991 /* Re-generate channel key */
3992 if (!silc_server_create_channel_key(server, channel, 0)) {
3993 /* We don't have new key, revert to old one */
3994 channel->channel_key = oldkey;
3998 /* Remove old channel key for good */
3999 silc_cipher_free(oldkey);
4001 /* Send the channel key. This sends it to our local clients and if
4002 we are normal server to our router as well. */
4003 silc_server_send_channel_key(server, NULL, channel,
4004 server->server_type == SILC_ROUTER ?
4005 FALSE : !server->standalone);
4009 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4010 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4011 /* HMAC to use protect the traffic */
4012 unsigned char hash[32];
4016 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4019 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4023 /* Delete old hmac and allocate the new one */
4024 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4026 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4030 silc_hmac_free(channel->hmac);
4031 channel->hmac = newhmac;
4033 /* Set the HMAC key out of current channel key. The client must do
4035 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4036 channel->key_len / 8, hash);
4037 silc_hmac_set_key(channel->hmac, hash,
4038 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4039 memset(hash, 0, sizeof(hash));
4042 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4043 /* Hmac mode is unset. Remove the hmac and revert back to
4046 unsigned char hash[32];
4047 hmac = channel->hmac_name;
4049 /* Delete old hmac and allocate default one */
4050 silc_hmac_free(channel->hmac);
4051 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4053 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4057 silc_hmac_free(channel->hmac);
4058 channel->hmac = newhmac;
4060 /* Set the HMAC key out of current channel key. The client must do
4062 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4063 channel->key_len / 8,
4065 silc_hmac_set_key(channel->hmac, hash,
4066 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4067 memset(hash, 0, sizeof(hash));
4071 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4072 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4073 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4074 /* Set the founder authentication */
4075 SilcAuthPayload auth;
4077 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4080 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4084 auth = silc_auth_payload_parse(tmp, tmp_len);
4086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4087 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4091 /* Save the public key */
4092 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4093 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4096 channel->founder_method = silc_auth_get_method(auth);
4098 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4099 tmp = silc_auth_get_data(auth, &tmp_len);
4100 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4101 channel->founder_passwd_len = tmp_len;
4103 /* Verify the payload before setting the mode */
4104 if (!silc_auth_verify(auth, channel->founder_method,
4105 channel->founder_key, 0, idata->hash,
4106 client->id, SILC_ID_CLIENT)) {
4107 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4108 SILC_STATUS_ERR_AUTH_FAILED);
4113 silc_auth_payload_free(auth);
4117 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4118 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4119 if (channel->founder_key)
4120 silc_pkcs_public_key_free(channel->founder_key);
4121 if (channel->founder_passwd) {
4122 silc_free(channel->founder_passwd);
4123 channel->founder_passwd = NULL;
4129 /* Finally, set the mode */
4130 channel->mode = mode_mask;
4132 /* Send CMODE_CHANGE notify. */
4133 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4134 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4135 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4136 cidp->data, cidp->len,
4138 cipher, cipher ? strlen(cipher) : 0,
4139 hmac, hmac ? strlen(hmac) : 0,
4140 passphrase, passphrase ?
4141 strlen(passphrase) : 0);
4143 /* Set CMODE notify type to network */
4144 if (!server->standalone)
4145 silc_server_send_notify_cmode(server, server->router->connection,
4146 server->server_type == SILC_ROUTER ?
4147 TRUE : FALSE, channel,
4148 mode_mask, client->id, SILC_ID_CLIENT,
4149 cipher, hmac, passphrase);
4151 /* Send command reply to sender */
4152 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4153 SILC_STATUS_OK, 0, ident, 2,
4154 2, tmp_id, tmp_len2,
4156 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4157 packet->data, packet->len, FALSE);
4159 silc_buffer_free(packet);
4160 silc_buffer_free(cidp);
4163 silc_free(channel_id);
4164 silc_server_command_free(cmd);
4167 /* Server side of CUMODE command. Changes client's mode on a channel. */
4169 SILC_SERVER_CMD_FUNC(cumode)
4171 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4172 SilcServer server = cmd->server;
4173 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4174 SilcIDListData idata = (SilcIDListData)client;
4175 SilcChannelID *channel_id;
4176 SilcClientID *client_id;
4177 SilcChannelEntry channel;
4178 SilcClientEntry target_client;
4179 SilcChannelClientEntry chl;
4180 SilcBuffer packet, idp;
4181 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4182 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4184 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4186 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4188 /* Get Channel ID */
4189 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4192 SILC_STATUS_ERR_NO_CHANNEL_ID);
4195 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4198 SILC_STATUS_ERR_NO_CHANNEL_ID);
4202 /* Get channel entry */
4203 channel = silc_idlist_find_channel_by_id(server->local_list,
4206 channel = silc_idlist_find_channel_by_id(server->global_list,
4209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4210 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4215 /* Check whether sender is on the channel */
4216 if (!silc_server_client_on_channel(client, channel, &chl)) {
4217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4218 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4221 sender_mask = chl->mode;
4223 /* Get the target client's channel mode mask */
4224 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4227 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4230 SILC_GET32_MSB(target_mask, tmp_mask);
4232 /* Get target Client ID */
4233 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4236 SILC_STATUS_ERR_NO_CLIENT_ID);
4239 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4242 SILC_STATUS_ERR_NO_CLIENT_ID);
4246 /* Get target client's entry */
4247 target_client = silc_idlist_find_client_by_id(server->local_list,
4248 client_id, TRUE, NULL);
4249 if (!target_client) {
4250 target_client = silc_idlist_find_client_by_id(server->global_list,
4251 client_id, TRUE, NULL);
4254 if (target_client != client &&
4255 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4256 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4258 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4262 /* Check whether target client is on the channel */
4263 if (target_client != client) {
4264 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4266 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4275 /* If the target client is founder, no one else can change their mode
4277 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4279 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4283 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4284 if (target_client != client) {
4285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4286 SILC_STATUS_ERR_NOT_YOU);
4290 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4291 /* The client tries to claim the founder rights. */
4292 unsigned char *tmp_auth;
4293 SilcUInt32 tmp_auth_len, auth_len;
4296 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4297 !channel->founder_key || !idata->public_key ||
4298 !silc_pkcs_public_key_compare(channel->founder_key,
4299 idata->public_key)) {
4300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4301 SILC_STATUS_ERR_NOT_YOU);
4305 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4308 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4312 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4313 (void *)channel->founder_passwd : (void *)channel->founder_key);
4314 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4315 channel->founder_passwd_len : 0);
4317 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4318 channel->founder_method, auth, auth_len,
4319 idata->hash, client->id, SILC_ID_CLIENT)) {
4320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4321 SILC_STATUS_ERR_AUTH_FAILED);
4325 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4329 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4330 if (target_client == client) {
4331 /* Remove channel founder rights from itself */
4332 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4336 SILC_STATUS_ERR_NOT_YOU);
4342 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4343 /* Promote to operator */
4344 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4345 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4346 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4348 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4352 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4356 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4357 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4358 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4360 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4364 /* Demote to normal user */
4365 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4370 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4371 if (target_client != client) {
4372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4373 SILC_STATUS_ERR_NOT_YOU);
4377 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4378 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4382 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4383 if (target_client != client) {
4384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4385 SILC_STATUS_ERR_NOT_YOU);
4389 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4395 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4396 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4398 /* Send notify to channel, notify only if mode was actually changed. */
4400 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4401 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4402 idp->data, idp->len,
4406 /* Set CUMODE notify type to network */
4407 if (!server->standalone)
4408 silc_server_send_notify_cumode(server, server->router->connection,
4409 server->server_type == SILC_ROUTER ?
4410 TRUE : FALSE, channel,
4411 target_mask, client->id,
4416 /* Send command reply to sender */
4417 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4418 SILC_STATUS_OK, 0, ident, 3,
4420 3, tmp_ch_id, tmp_ch_len,
4421 4, tmp_id, tmp_len);
4422 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4423 packet->data, packet->len, FALSE);
4425 silc_buffer_free(packet);
4426 silc_free(channel_id);
4427 silc_free(client_id);
4428 silc_buffer_free(idp);
4431 silc_server_command_free(cmd);
4434 /* Server side of KICK command. Kicks client out of channel. */
4436 SILC_SERVER_CMD_FUNC(kick)
4438 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4439 SilcServer server = cmd->server;
4440 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4441 SilcClientEntry target_client;
4442 SilcChannelID *channel_id;
4443 SilcClientID *client_id;
4444 SilcChannelEntry channel;
4445 SilcChannelClientEntry chl;
4447 SilcUInt32 tmp_len, target_idp_len;
4448 unsigned char *tmp, *comment, *target_idp;
4450 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4452 /* Get Channel ID */
4453 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4456 SILC_STATUS_ERR_NO_CHANNEL_ID);
4459 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4462 SILC_STATUS_ERR_NO_CHANNEL_ID);
4466 /* Get channel entry */
4467 channel = silc_idlist_find_channel_by_id(server->local_list,
4470 channel = silc_idlist_find_channel_by_id(server->local_list,
4473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4474 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4479 /* Check whether sender is on the channel */
4480 if (!silc_server_client_on_channel(client, channel, &chl)) {
4481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4482 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4486 /* Check that the kicker is channel operator or channel founder */
4487 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4489 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4493 /* Get target Client ID */
4494 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4497 SILC_STATUS_ERR_NO_CLIENT_ID);
4500 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4502 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4503 SILC_STATUS_ERR_NO_CLIENT_ID);
4507 /* Get target client's entry */
4508 target_client = silc_idlist_find_client_by_id(server->local_list,
4509 client_id, TRUE, NULL);
4510 if (!target_client) {
4511 target_client = silc_idlist_find_client_by_id(server->global_list,
4512 client_id, TRUE, NULL);
4515 /* Check whether target client is on the channel */
4516 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4518 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4522 /* Check that the target client is not channel founder. Channel founder
4523 cannot be kicked from the channel. */
4524 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4526 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4532 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4536 /* Send command reply to sender */
4537 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4540 /* Send KICKED notify to local clients on the channel */
4541 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4542 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4543 SILC_NOTIFY_TYPE_KICKED, 3,
4544 target_idp, target_idp_len,
4545 comment, comment ? strlen(comment) : 0,
4546 idp->data, idp->len);
4547 silc_buffer_free(idp);
4549 /* Remove the client from the channel. If the channel does not exist
4550 after removing the client then the client kicked itself off the channel
4551 and we don't have to send anything after that. */
4552 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4553 target_client, FALSE))
4556 /* Send KICKED notify to primary route */
4557 if (!server->standalone)
4558 silc_server_send_notify_kicked(server, server->router->connection,
4559 server->server_type == SILC_ROUTER ?
4560 TRUE : FALSE, channel,
4561 target_client->id, client->id, comment);
4563 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4564 /* Re-generate channel key */
4565 if (!silc_server_create_channel_key(server, channel, 0))
4568 /* Send the channel key to the channel. The key of course is not sent
4569 to the client who was kicked off the channel. */
4570 silc_server_send_channel_key(server, target_client->connection, channel,
4571 server->server_type == SILC_ROUTER ?
4572 FALSE : !server->standalone);
4576 silc_server_command_free(cmd);
4579 /* Server side of OPER command. Client uses this comand to obtain server
4580 operator privileges to this server/router. */
4582 SILC_SERVER_CMD_FUNC(oper)
4584 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4585 SilcServer server = cmd->server;
4586 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4587 unsigned char *username, *auth;
4589 SilcServerConfigAdmin *admin;
4590 SilcIDListData idata = (SilcIDListData)client;
4591 bool result = FALSE;
4592 SilcPublicKey cached_key;
4594 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4596 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4599 /* Get the username */
4600 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4603 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4607 /* Get the admin configuration */
4608 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4609 username, client->nickname);
4611 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4612 username, client->nickname);
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4615 SILC_STATUS_ERR_AUTH_FAILED);
4620 /* Get the authentication payload */
4621 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4624 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4628 /* Verify the authentication data. If both passphrase and public key
4629 is set then try both of them. */
4630 if (admin->passphrase)
4631 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4632 admin->passphrase, admin->passphrase_len,
4633 idata->hash, client->id, SILC_ID_CLIENT);
4634 if (!result && admin->publickeys) {
4635 cached_key = silc_server_get_public_key(server, admin->publickeys);
4638 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4639 cached_key, 0, idata->hash,
4640 client->id, SILC_ID_CLIENT);
4643 /* Authentication failed */
4644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4645 SILC_STATUS_ERR_AUTH_FAILED);
4649 /* Client is now server operator */
4650 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4652 /* Update statistics */
4653 if (client->connection)
4654 server->stat.my_server_ops++;
4655 if (server->server_type == SILC_ROUTER)
4656 server->stat.server_ops++;
4658 /* Send UMODE change to primary router */
4659 if (!server->standalone)
4660 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4661 client->id, client->mode);
4663 /* Send reply to the sender */
4664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4668 silc_server_command_free(cmd);
4671 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4673 QuitInternal q = (QuitInternal)context;
4674 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4676 /* If there is pending outgoing data for the client then purge it
4677 to the network before closing connection. */
4678 silc_server_packet_queue_purge(q->server, q->sock);
4680 /* Close the connection on our side */
4681 client->router = NULL;
4682 client->connection = NULL;
4683 q->sock->user_data = NULL;
4684 silc_server_close_connection(q->server, q->sock);
4689 /* Server side of DETACH command. Detached the client from the network
4690 by closing the connection but preserving the session. */
4692 SILC_SERVER_CMD_FUNC(detach)
4694 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4695 SilcServer server = cmd->server;
4696 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4699 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4702 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4704 /* Send the user mode notify to notify that client is detached */
4705 client->mode |= SILC_UMODE_DETACHED;
4706 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4707 if (!server->standalone)
4708 silc_server_send_notify_umode(server, server->router->connection,
4709 server->server_type == SILC_SERVER ?
4710 FALSE : TRUE, client->id, client->mode);
4712 q = silc_calloc(1, sizeof(*q));
4714 q->sock = cmd->sock;
4715 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4716 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4718 /* Send reply to the sender */
4719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4723 silc_server_command_free(cmd);
4726 /* Server side of SILCOPER command. Client uses this comand to obtain router
4727 operator privileges to this router. */
4729 SILC_SERVER_CMD_FUNC(silcoper)
4731 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4732 SilcServer server = cmd->server;
4733 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4734 unsigned char *username, *auth;
4736 SilcServerConfigAdmin *admin;
4737 SilcIDListData idata = (SilcIDListData)client;
4738 bool result = FALSE;
4739 SilcPublicKey cached_key;
4741 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4743 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4746 if (server->server_type != SILC_ROUTER) {
4747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4748 SILC_STATUS_ERR_AUTH_FAILED);
4752 /* Get the username */
4753 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4756 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4760 /* Get the admin configuration */
4761 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4762 username, client->nickname);
4764 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4765 username, client->nickname);
4767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4768 SILC_STATUS_ERR_AUTH_FAILED);
4773 /* Get the authentication payload */
4774 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4777 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4781 /* Verify the authentication data. If both passphrase and public key
4782 is set then try both of them. */
4783 if (admin->passphrase)
4784 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4785 admin->passphrase, admin->passphrase_len,
4786 idata->hash, client->id, SILC_ID_CLIENT);
4787 if (!result && admin->publickeys) {
4788 cached_key = silc_server_get_public_key(server, admin->publickeys);
4791 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4792 cached_key, 0, idata->hash,
4793 client->id, SILC_ID_CLIENT);
4796 /* Authentication failed */
4797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4798 SILC_STATUS_ERR_AUTH_FAILED);
4802 /* Client is now router operator */
4803 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4805 /* Update statistics */
4806 if (client->connection)
4807 server->stat.my_router_ops++;
4808 if (server->server_type == SILC_ROUTER)
4809 server->stat.router_ops++;
4811 /* Send UMODE change to primary router */
4812 if (!server->standalone)
4813 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4814 client->id, client->mode);
4816 /* Send reply to the sender */
4817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4821 silc_server_command_free(cmd);
4824 /* Server side of command BAN. This is used to manage the ban list of the
4825 channel. To add clients and remove clients from the ban list. */
4827 SILC_SERVER_CMD_FUNC(ban)
4829 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4830 SilcServer server = cmd->server;
4831 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4833 SilcChannelEntry channel;
4834 SilcChannelClientEntry chl;
4835 SilcChannelID *channel_id = NULL;
4836 unsigned char *id, *add, *del;
4837 SilcUInt32 id_len, tmp_len;
4838 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4840 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4843 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4845 /* Get Channel ID */
4846 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4848 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4850 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4851 SILC_STATUS_ERR_NO_CHANNEL_ID);
4856 /* Get channel entry. The server must know about the channel since the
4857 client is expected to be on the channel. */
4858 channel = silc_idlist_find_channel_by_id(server->local_list,
4861 channel = silc_idlist_find_channel_by_id(server->global_list,
4864 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4865 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4870 /* Check whether this client is on the channel */
4871 if (!silc_server_client_on_channel(client, channel, &chl)) {
4872 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4873 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4877 /* The client must be at least channel operator. */
4878 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4880 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4884 /* Get the new ban and add it to the ban list */
4885 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4887 if (!channel->ban_list)
4888 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4890 channel->ban_list = silc_realloc(channel->ban_list,
4891 sizeof(*channel->ban_list) *
4893 strlen(channel->ban_list) + 2));
4894 if (add[tmp_len - 1] == ',')
4895 add[tmp_len - 1] = '\0';
4897 strncat(channel->ban_list, add, tmp_len);
4898 strncat(channel->ban_list, ",", 1);
4901 /* Get the ban to be removed and remove it from the list */
4902 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4903 if (del && channel->ban_list) {
4904 char *start, *end, *n;
4906 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4907 silc_free(channel->ban_list);
4908 channel->ban_list = NULL;
4910 start = strstr(channel->ban_list, del);
4911 if (start && strlen(start) >= tmp_len) {
4912 end = start + tmp_len;
4913 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4914 strncat(n, channel->ban_list, start - channel->ban_list);
4915 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4917 silc_free(channel->ban_list);
4918 channel->ban_list = n;
4923 /* Send the BAN notify type to our primary router. */
4924 if (!server->standalone && (add || del))
4925 silc_server_send_notify_ban(server, server->router->connection,
4926 server->server_type == SILC_ROUTER ?
4927 TRUE : FALSE, channel, add, del);
4929 /* Send the reply back to the client */
4931 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4932 SILC_STATUS_OK, 0, ident, 2,
4934 3, channel->ban_list,
4936 strlen(channel->ban_list) -1 : 0);
4937 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4938 packet->data, packet->len, FALSE);
4940 silc_buffer_free(packet);
4943 silc_free(channel_id);
4944 silc_server_command_free(cmd);
4947 /* Server side command of LEAVE. Removes client from a channel. */
4949 SILC_SERVER_CMD_FUNC(leave)
4951 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4952 SilcServer server = cmd->server;
4953 SilcSocketConnection sock = cmd->sock;
4954 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4955 SilcChannelID *id = NULL;
4956 SilcChannelEntry channel;
4960 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4962 /* Get Channel ID */
4963 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4966 SILC_STATUS_ERR_NO_CHANNEL_ID);
4969 id = silc_id_payload_parse_id(tmp, len, NULL);
4971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4972 SILC_STATUS_ERR_NO_CHANNEL_ID);
4976 /* Get channel entry */
4977 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4979 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4982 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4987 /* Check whether this client is on the channel */
4988 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4990 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4994 /* Notify routers that they should remove this client from their list
4995 of clients on the channel. Send LEAVE notify type. */
4996 if (!server->standalone)
4997 silc_server_send_notify_leave(server, server->router->connection,
4998 server->server_type == SILC_ROUTER ?
4999 TRUE : FALSE, channel, id_entry->id);
5001 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5002 SILC_STATUS_OK, 2, tmp, len);
5004 /* Remove client from channel */
5005 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5007 /* If the channel does not exist anymore we won't send anything */
5010 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5011 /* Re-generate channel key */
5012 if (!silc_server_create_channel_key(server, channel, 0))
5015 /* Send the channel key */
5016 silc_server_send_channel_key(server, NULL, channel,
5017 server->server_type == SILC_ROUTER ?
5018 FALSE : !server->standalone);
5023 silc_server_command_free(cmd);
5026 /* Server side of command USERS. Resolves clients and their USERS currently
5027 joined on the requested channel. The list of Client ID's and their modes
5028 on the channel is sent back. */
5030 SILC_SERVER_CMD_FUNC(users)
5032 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5033 SilcServer server = cmd->server;
5034 SilcChannelEntry channel;
5035 SilcChannelID *id = NULL;
5036 SilcBuffer packet, idp;
5037 unsigned char *channel_id;
5038 SilcUInt32 channel_id_len;
5039 SilcBuffer client_id_list;
5040 SilcBuffer client_mode_list;
5041 unsigned char lc[4];
5042 SilcUInt32 list_count = 0;
5043 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5046 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5048 /* Get Channel ID */
5049 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5051 /* Get channel name */
5052 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5054 if (!channel_id && !channel_name) {
5055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5056 SILC_STATUS_ERR_NO_CHANNEL_ID);
5061 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5064 SILC_STATUS_ERR_NO_CHANNEL_ID);
5069 /* If we are server and we don't know about this channel we will send
5070 the command to our router. If we know about the channel then we also
5071 have the list of users already. */
5073 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5075 channel = silc_idlist_find_channel_by_name(server->local_list,
5076 channel_name, NULL);
5078 if (!channel || channel->disabled || !channel->users_resolved) {
5079 if (server->server_type != SILC_ROUTER && !server->standalone &&
5083 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5084 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5086 /* Send USERS command */
5087 silc_server_packet_send(server, server->router->connection,
5088 SILC_PACKET_COMMAND, cmd->packet->flags,
5089 tmpbuf->data, tmpbuf->len, TRUE);
5091 /* Reprocess this packet after received reply */
5092 silc_server_command_pending(server, SILC_COMMAND_USERS,
5093 silc_command_get_ident(cmd->payload),
5094 silc_server_command_users,
5095 silc_server_command_dup(cmd));
5096 cmd->pending = TRUE;
5097 silc_command_set_ident(cmd->payload, ident);
5098 silc_buffer_free(tmpbuf);
5103 /* Check the global list as well. */
5105 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5107 channel = silc_idlist_find_channel_by_name(server->global_list,
5108 channel_name, NULL);
5110 /* Channel really does not exist */
5111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5112 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5117 /* If the channel is private or secret do not send anything, unless the
5118 user requesting this command is on the channel or is server */
5119 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5120 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5121 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5124 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5129 /* Get the users list */
5130 silc_server_get_users_on_channel(server, channel, &client_id_list,
5131 &client_mode_list, &list_count);
5134 SILC_PUT32_MSB(list_count, lc);
5137 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5138 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5139 SILC_STATUS_OK, 0, ident, 4,
5140 2, idp->data, idp->len,
5142 4, client_id_list->data,
5143 client_id_list->len,
5144 5, client_mode_list->data,
5145 client_mode_list->len);
5146 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5147 packet->data, packet->len, FALSE);
5149 silc_buffer_free(idp);
5150 silc_buffer_free(packet);
5151 silc_buffer_free(client_id_list);
5152 silc_buffer_free(client_mode_list);
5156 silc_server_command_free(cmd);
5159 /* Server side of command GETKEY. This fetches the client's public key
5160 from the server where to the client is connected. */
5162 SILC_SERVER_CMD_FUNC(getkey)
5164 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5165 SilcServer server = cmd->server;
5167 SilcClientEntry client;
5168 SilcServerEntry server_entry;
5169 SilcClientID *client_id = NULL;
5170 SilcServerID *server_id = NULL;
5171 SilcIDPayload idp = NULL;
5172 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5173 unsigned char *tmp, *pkdata;
5174 SilcUInt32 tmp_len, pklen;
5175 SilcBuffer pk = NULL;
5177 SilcPublicKey public_key;
5179 SILC_LOG_DEBUG(("Start"));
5181 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5184 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5187 idp = silc_id_payload_parse(tmp, tmp_len);
5189 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5190 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5194 id_type = silc_id_payload_get_type(idp);
5195 if (id_type == SILC_ID_CLIENT) {
5196 client_id = silc_id_payload_get_id(idp);
5198 /* If the client is not found from local list there is no chance it
5199 would be locally connected client so send the command further. */
5200 client = silc_idlist_find_client_by_id(server->local_list,
5201 client_id, TRUE, NULL);
5203 client = silc_idlist_find_client_by_id(server->global_list,
5204 client_id, TRUE, NULL);
5206 if ((!client && !cmd->pending && !server->standalone) ||
5207 (client && !client->connection && !cmd->pending &&
5208 !(client->mode & SILC_UMODE_DETACHED)) ||
5209 (client && !client->data.public_key && !cmd->pending)) {
5211 SilcUInt16 old_ident;
5212 SilcSocketConnection dest_sock;
5214 dest_sock = silc_server_get_client_route(server, NULL, 0,
5215 client_id, NULL, NULL);
5219 old_ident = silc_command_get_ident(cmd->payload);
5220 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5221 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5223 silc_server_packet_send(server, dest_sock,
5224 SILC_PACKET_COMMAND, cmd->packet->flags,
5225 tmpbuf->data, tmpbuf->len, TRUE);
5227 /* Reprocess this packet after received reply from router */
5228 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5229 silc_command_get_ident(cmd->payload),
5230 silc_server_command_getkey,
5231 silc_server_command_dup(cmd));
5232 cmd->pending = TRUE;
5233 silc_command_set_ident(cmd->payload, old_ident);
5234 silc_buffer_free(tmpbuf);
5239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5240 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5244 /* The client is locally connected, just get the public key and
5245 send it back. If they key does not exist then do not send it,
5246 send just OK reply */
5247 public_key = client->data.public_key;
5252 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5253 pk = silc_buffer_alloc(4 + tmp_len);
5254 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5255 silc_buffer_format(pk,
5256 SILC_STR_UI_SHORT(tmp_len),
5257 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5258 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5264 } else if (id_type == SILC_ID_SERVER) {
5265 server_id = silc_id_payload_get_id(idp);
5267 /* If the server is not found from local list there is no chance it
5268 would be locally connected server so send the command further. */
5269 server_entry = silc_idlist_find_server_by_id(server->local_list,
5270 server_id, TRUE, NULL);
5272 server_entry = silc_idlist_find_server_by_id(server->global_list,
5273 server_id, TRUE, NULL);
5275 if (server_entry != server->id_entry &&
5276 ((!server_entry && !cmd->pending && !server->standalone) ||
5277 (server_entry && !server_entry->connection && !cmd->pending &&
5278 !server->standalone) ||
5279 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5280 !server->standalone))) {
5282 SilcUInt16 old_ident;
5284 old_ident = silc_command_get_ident(cmd->payload);
5285 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5286 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5288 silc_server_packet_send(server, server->router->connection,
5289 SILC_PACKET_COMMAND, cmd->packet->flags,
5290 tmpbuf->data, tmpbuf->len, TRUE);
5292 /* Reprocess this packet after received reply from router */
5293 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5294 silc_command_get_ident(cmd->payload),
5295 silc_server_command_getkey,
5296 silc_server_command_dup(cmd));
5297 cmd->pending = TRUE;
5298 silc_command_set_ident(cmd->payload, old_ident);
5299 silc_buffer_free(tmpbuf);
5303 if (!server_entry) {
5304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5305 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5309 /* If they key does not exist then do not send it, send just OK reply */
5310 public_key = (!server_entry->data.public_key ?
5311 (server_entry == server->id_entry ? server->public_key :
5312 NULL) : server_entry->data.public_key);
5317 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5318 pk = silc_buffer_alloc(4 + tmp_len);
5319 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5320 silc_buffer_format(pk,
5321 SILC_STR_UI_SHORT(tmp_len),
5322 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5323 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5333 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5334 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5335 SILC_STATUS_OK, 0, ident,
5339 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5340 packet->data, packet->len, FALSE);
5341 silc_buffer_free(packet);
5344 silc_buffer_free(pk);
5348 silc_id_payload_free(idp);
5349 silc_free(client_id);
5350 silc_free(server_id);
5351 silc_server_command_free(cmd);
5355 /* Private range commands, specific to this implementation */
5357 /* Server side command of CONNECT. Connects us to the specified remote
5358 server or router. */
5360 SILC_SERVER_CMD_FUNC(connect)
5362 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5363 SilcServer server = cmd->server;
5364 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5365 unsigned char *tmp, *host;
5367 SilcUInt32 port = SILC_PORT;
5369 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5371 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5374 /* Check whether client has the permissions. */
5375 if (client->mode == SILC_UMODE_NONE) {
5376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5377 SILC_STATUS_ERR_NO_SERVER_PRIV);
5381 if (server->server_type == SILC_ROUTER &&
5382 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5384 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5388 /* Get the remote server */
5389 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5392 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5397 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5399 SILC_GET32_MSB(port, tmp);
5401 /* Create the connection. It is done with timeout and is async. */
5402 silc_server_create_connection(server, host, port);
5404 /* Send reply to the sender */
5405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5409 silc_server_command_free(cmd);
5412 /* Server side command of CLOSE. Closes connection to a specified server. */
5414 SILC_SERVER_CMD_FUNC(close)
5416 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5417 SilcServer server = cmd->server;
5418 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5419 SilcServerEntry server_entry;
5420 SilcSocketConnection sock;
5423 unsigned char *name;
5424 SilcUInt32 port = SILC_PORT;
5426 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5428 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5431 /* Check whether client has the permissions. */
5432 if (client->mode == SILC_UMODE_NONE) {
5433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5434 SILC_STATUS_ERR_NO_SERVER_PRIV);
5438 /* Get the remote server */
5439 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5442 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5447 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5449 SILC_GET32_MSB(port, tmp);
5451 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5452 name, port, FALSE, NULL);
5454 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5455 name, port, FALSE, NULL);
5456 if (!server_entry) {
5457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5458 SILC_STATUS_ERR_NO_SERVER_ID);
5462 /* Send reply to the sender */
5463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5466 /* Close the connection to the server */
5467 sock = (SilcSocketConnection)server_entry->connection;
5469 /* If we shutdown primary router connection manually then don't trigger
5470 any reconnect or backup router connections, by setting the router
5472 if (server->router == server_entry) {
5473 server->id_entry->router = NULL;
5474 server->router = NULL;
5475 server->standalone = TRUE;
5477 silc_server_free_sock_user_data(server, sock, NULL);
5478 silc_server_close_connection(server, sock);
5481 silc_server_command_free(cmd);
5484 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5485 active connections. */
5487 SILC_SERVER_CMD_FUNC(shutdown)
5489 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5490 SilcServer server = cmd->server;
5491 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5493 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5495 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5498 /* Check whether client has the permission. */
5499 if (client->mode == SILC_UMODE_NONE) {
5500 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5501 SILC_STATUS_ERR_NO_SERVER_PRIV);
5505 /* Send reply to the sender */
5506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5509 /* Then, gracefully, or not, bring the server down. */
5510 silc_server_stop(server);
5514 silc_server_command_free(cmd);