5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
38 const unsigned char *arg,
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42 SilcServerCommandReplyContext cmdr,
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(silcoper, SILCOPER,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
72 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
73 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
74 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(connect, PRIV_CONNECT,
77 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
78 SILC_SERVER_CMD(close, PRIV_CLOSE,
79 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
80 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
86 /* Performs several checks to the command. It first checks whether this
87 command was called as pending command callback. If it was then it checks
88 whether error occurred in the command reply where the pending command
91 It also checks that the requested command includes correct amount
93 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
97 SILC_LOG_DEBUG(("Start")); \
99 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
100 silc_server_command_free(cmd); \
104 _argc = silc_argument_get_arg_num(cmd->args); \
106 silc_server_command_send_status_reply(cmd, command, \
107 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
108 silc_server_command_free(cmd); \
112 silc_server_command_send_status_reply(cmd, command, \
113 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
114 silc_server_command_free(cmd); \
119 /* Returns TRUE if the connection is registered. Unregistered connections
120 usually cannot send commands hence the check. */
122 static int silc_server_is_registered(SilcServer server,
123 SilcSocketConnection sock,
124 SilcServerCommandContext cmd,
127 SilcIDListData idata = (SilcIDListData)sock->user_data;
132 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
135 silc_server_command_send_status_reply(cmd, command,
136 SILC_STATUS_ERR_NOT_REGISTERED);
140 /* Internal context to hold data when executed command with timeout. */
142 SilcServerCommandContext ctx;
143 SilcServerCommand *cmd;
144 } *SilcServerCommandTimeout;
146 /* Timeout callback to process commands with timeout for client. Client's
147 commands are always executed with timeout. */
149 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
151 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
152 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
155 silc_server_command_free(timeout->ctx);
159 /* Update access time */
160 client->last_command = time(NULL);
162 if (!(timeout->cmd->flags & SILC_CF_REG))
163 timeout->cmd->cb(timeout->ctx, NULL);
164 else if (silc_server_is_registered(timeout->ctx->server,
168 timeout->cmd->cb(timeout->ctx, NULL);
170 silc_server_command_free(timeout->ctx);
175 /* Processes received command packet. */
177 void silc_server_command_process(SilcServer server,
178 SilcSocketConnection sock,
179 SilcPacketContext *packet)
181 SilcServerCommandContext ctx;
182 SilcServerCommand *cmd;
185 /* Allocate command context. This must be free'd by the
186 command routine receiving it. */
187 ctx = silc_server_command_alloc();
188 ctx->server = server;
189 ctx->sock = silc_socket_dup(sock);
190 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
192 /* Parse the command payload in the packet */
193 ctx->payload = silc_command_payload_parse(packet->buffer->data,
194 packet->buffer->len);
196 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
197 silc_buffer_free(packet->buffer);
198 silc_packet_context_free(packet);
199 silc_socket_free(ctx->sock);
203 ctx->args = silc_command_get_args(ctx->payload);
205 /* Get the command */
206 command = silc_command_get(ctx->payload);
207 for (cmd = silc_command_list; cmd->cb; cmd++)
208 if (cmd->cmd == command)
211 if (!cmd || !cmd->cb) {
212 silc_server_command_send_status_reply(ctx, command,
213 SILC_STATUS_ERR_UNKNOWN_COMMAND);
214 silc_server_command_free(ctx);
218 /* Execute client's commands always with timeout. Normally they are
219 executed with zero (0) timeout but if client is sending command more
220 frequently than once in 2 seconds, then the timeout may be 0 to 2
222 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
223 SilcClientEntry client = (SilcClientEntry)sock->user_data;
224 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
230 if (client->last_command && (time(NULL) - client->last_command) < 2) {
231 client->fast_command++;
234 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
235 client->fast_command--);
239 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
240 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
241 silc_schedule_task_add(server->schedule, sock->sock,
242 silc_server_command_process_timeout,
244 2 - (time(NULL) - client->last_command), 0,
245 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
247 silc_schedule_task_add(server->schedule, sock->sock,
248 silc_server_command_process_timeout,
249 (void *)timeout, 0, 1,
250 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
254 /* Execute for server */
256 if (!(cmd->flags & SILC_CF_REG))
258 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
261 silc_server_command_free(ctx);
264 /* Allocate Command Context */
266 SilcServerCommandContext silc_server_command_alloc()
268 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
273 /* Free's the command context allocated before executing the command */
275 void silc_server_command_free(SilcServerCommandContext ctx)
278 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
280 if (ctx->users < 1) {
282 silc_command_payload_free(ctx->payload);
284 silc_packet_context_free(ctx->packet);
286 silc_socket_free(ctx->sock); /* Decrease reference counter */
291 /* Duplicate Command Context by adding reference counter. The context won't
292 be free'd untill it hits zero. */
294 SilcServerCommandContext
295 silc_server_command_dup(SilcServerCommandContext ctx)
298 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
303 /* Add new pending command to be executed when reply to a command has been
304 received. The `reply_cmd' is the command that will call the `callback'
305 with `context' when reply has been received. It can be SILC_COMMAND_NONE
306 to match any command with the `ident'. If `ident' is non-zero
307 the `callback' will be executed when received reply with command
308 identifier `ident'. If there already exists pending command for the
309 specified command, ident, callback and context this function has no
312 bool silc_server_command_pending(SilcServer server,
313 SilcCommand reply_cmd,
315 SilcCommandCb callback,
318 SilcServerCommandPending *reply;
320 /* Check whether identical pending already exists for same command,
321 ident, callback and callback context. If it does then it would be
322 error to register it again. */
323 silc_dlist_start(server->pending_commands);
324 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
325 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
326 reply->callback == callback && reply->context == context)
330 reply = silc_calloc(1, sizeof(*reply));
331 reply->reply_cmd = reply_cmd;
332 reply->ident = ident;
333 reply->context = context;
334 reply->callback = callback;
335 silc_dlist_add(server->pending_commands, reply);
340 /* Deletes pending command by reply command type. */
342 void silc_server_command_pending_del(SilcServer server,
343 SilcCommand reply_cmd,
346 SilcServerCommandPending *r;
348 silc_dlist_start(server->pending_commands);
349 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
350 if (r->reply_cmd == reply_cmd && r->ident == ident) {
351 silc_dlist_del(server->pending_commands, r);
357 /* Checks for pending commands and marks callbacks to be called from
358 the command reply function. Returns TRUE if there were pending command. */
360 SilcServerCommandPendingCallbacks
361 silc_server_command_pending_check(SilcServer server,
362 SilcServerCommandReplyContext ctx,
365 SilcUInt32 *callbacks_count)
367 SilcServerCommandPending *r;
368 SilcServerCommandPendingCallbacks callbacks = NULL;
371 silc_dlist_start(server->pending_commands);
372 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
373 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
374 && r->ident == ident) {
375 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
376 callbacks[i].context = r->context;
377 callbacks[i].callback = r->callback;
383 *callbacks_count = i;
387 /* Sends simple status message as command reply packet */
390 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
392 SilcCommandStatus status)
396 SILC_LOG_DEBUG(("Sending command status %d", status));
399 silc_command_reply_payload_encode_va(command, status, 0,
400 silc_command_get_ident(cmd->payload),
402 silc_server_packet_send(cmd->server, cmd->sock,
403 SILC_PACKET_COMMAND_REPLY, 0,
404 buffer->data, buffer->len, FALSE);
405 silc_buffer_free(buffer);
408 /* Sends command status reply with one extra argument. The argument
409 type must be sent as argument. */
412 silc_server_command_send_status_data(SilcServerCommandContext cmd,
414 SilcCommandStatus status,
416 const unsigned char *arg,
421 SILC_LOG_DEBUG(("Sending command status %d", status));
424 silc_command_reply_payload_encode_va(command, status, 0,
425 silc_command_get_ident(cmd->payload),
426 1, arg_type, arg, arg_len);
427 silc_server_packet_send(cmd->server, cmd->sock,
428 SILC_PACKET_COMMAND_REPLY, 0,
429 buffer->data, buffer->len, FALSE);
430 silc_buffer_free(buffer);
433 /* This function can be called to check whether in the command reply
434 an error occurred. This function has no effect if this is called
435 when the command function was not called as pending command callback.
436 This returns TRUE if error had occurred. */
439 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
440 SilcServerCommandReplyContext cmdr,
443 if (!cmd->pending || !cmdr)
446 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
449 /* Send the same command reply payload */
450 silc_command_set_ident(cmdr->payload,
451 silc_command_get_ident(cmd->payload));
452 buffer = silc_command_payload_encode_payload(cmdr->payload);
453 silc_server_packet_send(cmd->server, cmd->sock,
454 SILC_PACKET_COMMAND_REPLY, 0,
455 buffer->data, buffer->len, FALSE);
456 silc_buffer_free(buffer);
463 /******************************************************************************
467 ******************************************************************************/
470 silc_server_command_whois_parse(SilcServerCommandContext cmd,
471 SilcClientID ***client_id,
472 SilcUInt32 *client_id_count,
480 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
483 /* If client ID is in the command it must be used instead of nickname */
484 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
486 /* No ID, get the nickname@server string and parse it. */
487 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
489 silc_parse_userfqdn(tmp, nickname, server_name);
491 silc_server_command_send_status_reply(cmd, command,
492 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
496 /* Command includes ID, we must use that. Also check whether the command
497 has more than one ID set - take them all. */
499 *client_id = silc_calloc(1, sizeof(**client_id));
500 (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
501 if ((*client_id)[0] == NULL) {
502 silc_free(*client_id);
503 silc_server_command_send_status_reply(cmd, command,
504 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
507 *client_id_count = 1;
509 /* Take all ID's from the command packet */
511 for (k = 1, i = 1; i < argc; i++) {
512 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
514 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
515 (*client_id_count + 1));
516 (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
517 if ((*client_id)[k] == NULL) {
518 /* Cleanup all and fail */
519 for (i = 0; i < *client_id_count; i++)
520 silc_free((*client_id)[i]);
521 silc_free(*client_id);
522 silc_server_command_send_status_reply(
524 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
527 (*client_id_count)++;
534 /* Get the max count of reply messages allowed */
535 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
544 /* Resolve context used by both WHOIS and IDENTIFY commands */
546 SilcServerEntry router;
548 unsigned char **res_argv;
549 SilcUInt32 *res_argv_lens;
550 SilcUInt32 *res_argv_types;
552 } *SilcServerResolveContext;
555 silc_server_command_whois_check(SilcServerCommandContext cmd,
556 SilcClientEntry *clients,
557 SilcUInt32 clients_count)
559 SilcServer server = cmd->server;
560 SilcClientEntry entry;
561 SilcServerResolveContext resolve = NULL, r = NULL;
562 SilcUInt32 resolve_count = 0;
566 SILC_LOG_DEBUG(("Start"));
568 for (i = 0; i < clients_count; i++) {
573 if ((entry->nickname && entry->username && entry->userinfo) ||
574 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
578 /* If we are normal server, and we've not resolved this client from
579 router and it is global client, we'll check whether it is on some
580 channel. If not then we cannot be sure about its validity, and
581 we'll resolve it from router. */
582 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
583 entry->connection || silc_hash_table_count(entry->channels))
587 /* We need to resolve this entry since it is not complete */
589 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
590 /* The entry is being resolved (and we are not the resolver) so attach
591 to the command reply and we're done with this one. */
592 silc_server_command_pending(server, SILC_COMMAND_NONE,
593 entry->resolve_cmd_ident,
594 silc_server_command_whois,
595 silc_server_command_dup(cmd));
598 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
599 /* We've resolved this and it still is not ready. We'll return
600 and are that this will be handled again after it is resolved. */
601 for (i = 0; i < resolve_count; i++) {
602 for (k = 0; k < r->res_argc; k++)
603 silc_free(r->res_argv[k]);
604 silc_free(r->res_argv);
605 silc_free(r->res_argv_lens);
606 silc_free(r->res_argv_types);
611 /* We'll resolve this client */
615 for (k = 0; k < resolve_count; k++) {
616 if (resolve[k].router == entry->router) {
623 resolve = silc_realloc(resolve, sizeof(*resolve) *
624 (resolve_count + 1));
625 r = &resolve[resolve_count];
626 memset(r, 0, sizeof(*r));
627 r->router = entry->router;
628 r->ident = ++server->cmd_ident;
632 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
634 r->res_argv_lens = silc_realloc(r->res_argv_lens,
635 sizeof(*r->res_argv_lens) *
637 r->res_argv_types = silc_realloc(r->res_argv_types,
638 sizeof(*r->res_argv_types) *
640 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
641 r->res_argv[r->res_argc] = silc_calloc(idp->len,
642 sizeof(**r->res_argv));
643 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
644 r->res_argv_lens[r->res_argc] = idp->len;
645 r->res_argv_types[r->res_argc] = r->res_argc + 3;
647 silc_buffer_free(idp);
649 entry->resolve_cmd_ident = r->ident;
650 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
651 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
656 /* Do the resolving */
657 for (i = 0; i < resolve_count; i++) {
662 /* Send WHOIS request. We send WHOIS since we're doing the requesting
663 now anyway so make it a good one. */
664 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
665 r->res_argc, r->res_argv,
669 silc_server_packet_send(server, r->router->connection,
670 SILC_PACKET_COMMAND, cmd->packet->flags,
671 res_cmd->data, res_cmd->len, FALSE);
673 /* Reprocess this packet after received reply */
674 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
676 silc_server_command_whois,
677 silc_server_command_dup(cmd));
680 silc_buffer_free(res_cmd);
681 for (k = 0; k < r->res_argc; k++)
682 silc_free(r->res_argv[k]);
683 silc_free(r->res_argv);
684 silc_free(r->res_argv_lens);
685 silc_free(r->res_argv_types);
694 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
695 SilcClientEntry *clients,
696 SilcUInt32 clients_count,
698 const char *nickname,
699 SilcClientID **client_ids)
701 SilcServer server = cmd->server;
703 int i, k, len, valid_count;
704 SilcBuffer packet, idp, channels;
705 SilcClientEntry entry;
706 SilcCommandStatus status;
707 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
708 char nh[256], uh[256];
709 unsigned char idle[4], mode[4];
710 unsigned char *fingerprint;
711 SilcSocketConnection hsock;
713 /* Process only valid clients and ignore those that are not registered. */
715 for (i = 0; i < clients_count; i++) {
716 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
723 /* No valid clients found, send error reply */
725 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
726 SILC_STATUS_ERR_NO_SUCH_NICK,
727 3, nickname, strlen(nickname));
728 } else if (client_ids && client_ids[0]) {
729 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
730 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
731 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
732 2, idp->data, idp->len);
733 silc_buffer_free(idp);
738 /* Start processing found clients. */
740 status = SILC_STATUS_LIST_START;
742 status = SILC_STATUS_OK;
744 for (i = 0, k = 0; i < clients_count; i++) {
750 status = SILC_STATUS_LIST_ITEM;
751 if (valid_count > 1 && k == valid_count - 1)
752 status = SILC_STATUS_LIST_END;
753 if (count && k - 1 == count)
754 status = SILC_STATUS_LIST_END;
756 /* Send WHOIS reply */
757 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
758 tmp = silc_argument_get_first_arg(cmd->args, NULL);
760 memset(uh, 0, sizeof(uh));
761 memset(nh, 0, sizeof(nh));
762 memset(idle, 0, sizeof(idle));
764 strncat(nh, entry->nickname, strlen(entry->nickname));
765 if (!strchr(entry->nickname, '@')) {
767 if (entry->servername) {
768 strncat(nh, entry->servername, strlen(entry->servername));
770 len = entry->router ? strlen(entry->router->server_name) :
771 strlen(server->server_name);
772 strncat(nh, entry->router ? entry->router->server_name :
773 server->server_name, len);
777 strncat(uh, entry->username, strlen(entry->username));
778 if (!strchr(entry->username, '@')) {
780 hsock = (SilcSocketConnection)entry->connection;
781 len = strlen(hsock->hostname);
782 strncat(uh, hsock->hostname, len);
785 channels = silc_server_get_client_channel_list(server, entry);
787 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
788 fingerprint = entry->data.fingerprint;
792 SILC_PUT32_MSB(entry->mode, mode);
794 if (entry->connection) {
795 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
799 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
801 2, idp->data, idp->len,
805 strlen(entry->userinfo),
806 6, channels ? channels->data : NULL,
807 channels ? channels->len : 0,
811 fingerprint ? 20 : 0);
813 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
814 0, packet->data, packet->len, FALSE);
816 silc_buffer_free(packet);
817 silc_buffer_free(idp);
819 silc_buffer_free(channels);
826 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
828 SilcServer server = cmd->server;
830 SilcUInt16 old_ident;
832 old_ident = silc_command_get_ident(cmd->payload);
833 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
834 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
836 /* Send WHOIS command to our router */
837 silc_server_packet_send(server, (SilcSocketConnection)
838 server->router->connection,
839 SILC_PACKET_COMMAND, cmd->packet->flags,
840 tmpbuf->data, tmpbuf->len, TRUE);
842 /* Reprocess this packet after received reply from router */
843 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
844 silc_command_get_ident(cmd->payload),
845 silc_server_command_whois,
846 silc_server_command_dup(cmd));
848 silc_command_set_ident(cmd->payload, old_ident);
849 silc_buffer_free(tmpbuf);
853 silc_server_command_whois_process(SilcServerCommandContext cmd)
855 SilcServer server = cmd->server;
856 char *nick = NULL, *server_name = NULL;
858 SilcClientEntry *clients = NULL, entry;
859 SilcClientID **client_id = NULL;
860 SilcUInt32 client_id_count = 0, clients_count = 0;
862 bool check_global = FALSE;
864 /* Parse the whois request */
865 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
866 &nick, &server_name, &count,
870 /* Send the WHOIS request to the router only if it included nickname.
871 Since nicknames can be expanded into many clients we need to send it
872 to router. If the WHOIS included only client ID's we will check them
873 first locally since we just might have them. */
874 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
875 server->server_type == SILC_SERVER && !cmd->pending &&
876 !server->standalone) {
877 silc_server_command_whois_send_router(cmd);
882 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
884 else if (server->server_type != SILC_SERVER)
887 /* Get all clients matching that ID or nickname from local list */
888 if (client_id_count) {
889 /* Check all Client ID's received in the command packet */
890 for (i = 0; i < client_id_count; i++) {
891 entry = silc_idlist_find_client_by_id(server->local_list,
892 client_id[i], TRUE, NULL);
893 if (!entry && check_global)
894 entry = silc_idlist_find_client_by_id(server->global_list,
895 client_id[i], TRUE, NULL);
897 clients = silc_realloc(clients, sizeof(*clients) *
898 (clients_count + 1));
899 clients[clients_count++] = entry;
901 /* If we are normal server and did not send the request first to router
902 do it now, since we do not have the Client ID information. */
903 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
904 server->server_type == SILC_SERVER && !cmd->pending &&
905 !server->standalone) {
906 silc_server_command_whois_send_router(cmd);
913 /* Find by nickname */
914 if (!silc_idlist_get_clients_by_hash(server->local_list,
915 nick, server->md5hash,
916 &clients, &clients_count))
917 silc_idlist_get_clients_by_nickname(server->local_list,
919 &clients, &clients_count);
921 if (!silc_idlist_get_clients_by_hash(server->global_list,
922 nick, server->md5hash,
923 &clients, &clients_count))
924 silc_idlist_get_clients_by_nickname(server->global_list,
926 &clients, &clients_count);
931 /* If we are normal server and did not send the request first to router
932 do it now, since we do not have the information. */
933 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
934 server->server_type == SILC_SERVER && !cmd->pending &&
935 !server->standalone) {
936 silc_server_command_whois_send_router(cmd);
941 /* Such client(s) really does not exist in the SILC network. */
942 if (!client_id_count) {
943 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
944 SILC_STATUS_ERR_NO_SUCH_NICK,
945 3, nick, strlen(nick));
947 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
948 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
949 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
950 2, idp->data, idp->len);
951 silc_buffer_free(idp);
956 /* Router always finds the client entry if it exists in the SILC network.
957 However, it might be incomplete entry and does not include all the
958 mandatory fields that WHOIS command reply requires. Check for these and
959 make query from the server who owns the client if some fields are
961 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
966 /* Send the command reply */
967 silc_server_command_whois_send_reply(cmd, clients, clients_count,
968 count, nick, client_id);
971 if (client_id_count) {
972 for (i = 0; i < client_id_count; i++)
973 silc_free(client_id[i]);
974 silc_free(client_id);
978 silc_free(server_name);
983 /* Server side of command WHOIS. Processes user's query and sends found
984 results as command replies back to the client. */
986 SILC_SERVER_CMD_FUNC(whois)
988 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
991 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
993 ret = silc_server_command_whois_process(cmd);
994 silc_server_command_free(cmd);
997 /******************************************************************************
1001 ******************************************************************************/
1004 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1012 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1015 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1019 /* Get the nickname@server string and parse it. */
1020 silc_parse_userfqdn(tmp, nickname, server_name);
1022 /* Get the max count of reply messages allowed */
1023 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1033 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1034 SilcClientEntry *clients,
1035 SilcUInt32 clients_count)
1037 SilcServer server = cmd->server;
1039 SilcClientEntry entry;
1041 for (i = 0; i < clients_count; i++) {
1044 if (!entry->nickname || !entry->username) {
1046 SilcUInt16 old_ident;
1051 old_ident = silc_command_get_ident(cmd->payload);
1052 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1053 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1055 /* Send WHOWAS command */
1056 silc_server_packet_send(server, entry->router->connection,
1057 SILC_PACKET_COMMAND, cmd->packet->flags,
1058 tmpbuf->data, tmpbuf->len, TRUE);
1060 /* Reprocess this packet after received reply */
1061 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1062 silc_command_get_ident(cmd->payload),
1063 silc_server_command_whowas,
1064 silc_server_command_dup(cmd));
1065 cmd->pending = TRUE;
1066 silc_command_set_ident(cmd->payload, old_ident);
1068 silc_buffer_free(tmpbuf);
1077 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1078 SilcClientEntry *clients,
1079 SilcUInt32 clients_count)
1081 SilcServer server = cmd->server;
1083 int i, k, count = 0, len;
1084 SilcBuffer packet, idp;
1085 SilcClientEntry entry = NULL;
1086 SilcCommandStatus status;
1087 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1088 char nh[256], uh[256];
1091 status = SILC_STATUS_OK;
1093 /* Process only entries that are not registered anymore. */
1095 for (i = 0; i < clients_count; i++) {
1096 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1103 /* No valid entries found at all, just send error */
1106 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1108 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1109 SILC_STATUS_ERR_NO_SUCH_NICK,
1110 3, tmp, strlen(tmp));
1114 if (valid_count > 1)
1115 status = SILC_STATUS_LIST_START;
1117 for (i = 0, k = 0; i < clients_count; i++) {
1123 status = SILC_STATUS_LIST_ITEM;
1124 if (valid_count > 1 && k == valid_count - 1)
1125 status = SILC_STATUS_LIST_END;
1126 if (count && k - 1 == count)
1127 status = SILC_STATUS_LIST_END;
1128 if (count && k - 1 > count)
1131 /* Send WHOWAS reply */
1132 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1133 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1134 memset(uh, 0, sizeof(uh));
1135 memset(nh, 0, sizeof(nh));
1137 strncat(nh, entry->nickname, strlen(entry->nickname));
1138 if (!strchr(entry->nickname, '@')) {
1139 strncat(nh, "@", 1);
1140 if (entry->servername) {
1141 strncat(nh, entry->servername, strlen(entry->servername));
1143 len = entry->router ? strlen(entry->router->server_name) :
1144 strlen(server->server_name);
1145 strncat(nh, entry->router ? entry->router->server_name :
1146 server->server_name, len);
1150 strncat(uh, entry->username, strlen(entry->username));
1151 if (!strchr(entry->username, '@')) {
1152 strncat(uh, "@", 1);
1153 strcat(uh, "*private*");
1157 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1158 status, 0, ident, 4,
1159 2, idp->data, idp->len,
1164 strlen(entry->userinfo) : 0);
1165 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1166 0, packet->data, packet->len, FALSE);
1168 silc_buffer_free(packet);
1169 silc_buffer_free(idp);
1176 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1178 SilcServer server = cmd->server;
1179 char *nick = NULL, *server_name = NULL;
1181 SilcClientEntry *clients = NULL;
1182 SilcUInt32 clients_count = 0;
1184 bool check_global = FALSE;
1186 /* Protocol dictates that we must always send the received WHOWAS request
1187 to our router if we are normal server, so let's do it now unless we
1188 are standalone. We will not send any replies to the client until we
1189 have received reply from the router. */
1190 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1191 server->server_type == SILC_SERVER && !cmd->pending &&
1192 !server->standalone) {
1194 SilcUInt16 old_ident;
1196 old_ident = silc_command_get_ident(cmd->payload);
1197 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1198 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1200 /* Send WHOWAS command to our router */
1201 silc_server_packet_send(server, (SilcSocketConnection)
1202 server->router->connection,
1203 SILC_PACKET_COMMAND, cmd->packet->flags,
1204 tmpbuf->data, tmpbuf->len, TRUE);
1206 /* Reprocess this packet after received reply from router */
1207 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1208 silc_command_get_ident(cmd->payload),
1209 silc_server_command_whowas,
1210 silc_server_command_dup(cmd));
1211 cmd->pending = TRUE;
1212 silc_command_set_ident(cmd->payload, old_ident);
1214 silc_buffer_free(tmpbuf);
1219 /* We are ready to process the command request. Let's search for the
1220 requested client and send reply to the requesting client. */
1222 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1223 check_global = TRUE;
1224 else if (server->server_type != SILC_SERVER)
1225 check_global = TRUE;
1227 /* Parse the whowas request */
1228 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1231 /* Get all clients matching that nickname from local list */
1232 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1234 &clients, &clients_count))
1235 silc_idlist_get_clients_by_hash(server->local_list,
1236 nick, server->md5hash,
1237 &clients, &clients_count);
1239 /* Check global list as well */
1241 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1243 &clients, &clients_count))
1244 silc_idlist_get_clients_by_hash(server->global_list,
1245 nick, server->md5hash,
1246 &clients, &clients_count);
1250 /* Such a client really does not exist in the SILC network. */
1251 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1252 SILC_STATUS_ERR_NO_SUCH_NICK,
1253 3, nick, strlen(nick));
1257 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1262 /* Send the command reply to the client */
1263 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1268 silc_free(server_name);
1272 /* Server side of command WHOWAS. */
1274 SILC_SERVER_CMD_FUNC(whowas)
1276 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1279 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1281 ret = silc_server_command_whowas_process(cmd);
1282 silc_server_command_free(cmd);
1285 /******************************************************************************
1289 ******************************************************************************/
1292 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1294 SilcServer server = cmd->server;
1296 SilcUInt16 old_ident;
1298 old_ident = silc_command_get_ident(cmd->payload);
1299 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1300 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1302 /* Send IDENTIFY command to our router */
1303 silc_server_packet_send(server, (SilcSocketConnection)
1304 server->router->connection,
1305 SILC_PACKET_COMMAND, cmd->packet->flags,
1306 tmpbuf->data, tmpbuf->len, TRUE);
1308 /* Reprocess this packet after received reply from router */
1309 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1310 silc_command_get_ident(cmd->payload),
1311 silc_server_command_identify,
1312 silc_server_command_dup(cmd));
1313 cmd->pending = TRUE;
1314 silc_command_set_ident(cmd->payload, old_ident);
1315 silc_buffer_free(tmpbuf);
1319 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1320 SilcClientEntry **clients,
1321 SilcUInt32 *clients_count,
1322 SilcServerEntry **servers,
1323 SilcUInt32 *servers_count,
1324 SilcChannelEntry **channels,
1325 SilcUInt32 *channels_count,
1328 SilcServer server = cmd->server;
1331 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1333 bool check_global = FALSE;
1338 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1339 check_global = TRUE;
1340 else if (server->server_type != SILC_SERVER)
1341 check_global = TRUE;
1343 /* If ID Payload is in the command it must be used instead of names */
1344 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1346 /* No ID, get the names. */
1348 /* If we are normal server and have not resolved information from
1349 router yet, do so now. */
1350 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1351 server->server_type == SILC_SERVER && !cmd->pending &&
1352 !server->standalone) {
1353 silc_server_command_identify_send_router(cmd);
1357 /* Try to get nickname@server. */
1358 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1361 char *nick_server = NULL;
1363 silc_parse_userfqdn(tmp, &nick, &nick_server);
1365 if (!silc_idlist_get_clients_by_hash(server->local_list,
1366 nick, server->md5hash,
1367 clients, clients_count))
1368 silc_idlist_get_clients_by_nickname(server->local_list,
1370 clients, clients_count);
1372 if (!silc_idlist_get_clients_by_hash(server->global_list,
1373 nick, server->md5hash,
1374 clients, clients_count))
1375 silc_idlist_get_clients_by_nickname(server->global_list,
1377 clients, clients_count);
1381 silc_free(nick_server);
1384 /* the nickname does not exist, send error reply */
1385 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1386 SILC_STATUS_ERR_NO_SUCH_NICK,
1387 3, tmp, strlen(tmp));
1392 /* Try to get server name */
1393 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1395 entry = silc_idlist_find_server_by_name(server->local_list,
1397 if (!entry && check_global)
1398 entry = silc_idlist_find_server_by_name(server->global_list,
1401 *servers = silc_realloc(*servers, sizeof(**servers) *
1402 (*servers_count + 1));
1403 (*servers)[(*servers_count)++] = entry;
1407 /* the server does not exist, send error reply */
1408 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1409 SILC_STATUS_ERR_NO_SUCH_SERVER,
1410 3, tmp, strlen(tmp));
1415 /* Try to get channel name */
1416 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1418 entry = silc_idlist_find_channel_by_name(server->local_list,
1420 if (!entry && check_global)
1421 entry = silc_idlist_find_channel_by_name(server->global_list,
1424 *channels = silc_realloc(*channels, sizeof(**channels) *
1425 (*channels_count + 1));
1426 (*channels)[(*channels_count)++] = entry;
1430 /* The channel does not exist, send error reply */
1431 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1432 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1433 3, tmp, strlen(tmp));
1438 if (!(*clients) && !(*servers) && !(*channels)) {
1439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1440 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1444 /* Command includes ID, we must use that. Also check whether the command
1445 has more than one ID set - take them all. */
1447 /* Take all ID's from the command packet */
1448 for (i = 0; i < argc; i++) {
1451 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1455 idp = silc_id_payload_parse(tmp, len);
1457 silc_free(*clients);
1458 silc_free(*servers);
1459 silc_free(*channels);
1460 silc_server_command_send_status_reply(
1461 cmd, SILC_COMMAND_IDENTIFY,
1462 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1466 id = silc_id_payload_get_id(idp);
1468 switch (silc_id_payload_get_type(idp)) {
1470 case SILC_ID_CLIENT:
1471 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1473 if (!entry && check_global)
1474 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1477 *clients = silc_realloc(*clients, sizeof(**clients) *
1478 (*clients_count + 1));
1479 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1481 /* If we are normal server and have not resolved information from
1482 router yet, do so now. */
1483 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1484 server->server_type == SILC_SERVER && !cmd->pending &&
1485 !server->standalone) {
1486 silc_server_command_identify_send_router(cmd);
1487 silc_free(*clients);
1488 silc_free(*servers);
1489 silc_free(*channels);
1492 silc_server_command_send_status_data(
1493 cmd, SILC_COMMAND_IDENTIFY,
1494 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1502 case SILC_ID_SERVER:
1503 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1505 if (!entry && check_global)
1506 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1509 *servers = silc_realloc(*servers, sizeof(**servers) *
1510 (*servers_count + 1));
1511 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1513 /* If we are normal server and have not resolved information from
1514 router yet, do so now. */
1515 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1516 server->server_type == SILC_SERVER && !cmd->pending &&
1517 !server->standalone) {
1518 silc_server_command_identify_send_router(cmd);
1519 silc_free(*clients);
1520 silc_free(*servers);
1521 silc_free(*channels);
1524 silc_server_command_send_status_data(
1525 cmd, SILC_COMMAND_IDENTIFY,
1526 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1533 case SILC_ID_CHANNEL:
1534 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1536 if (!entry && check_global)
1537 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1540 *channels = silc_realloc(*channels, sizeof(**channels) *
1541 (*channels_count + 1));
1542 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1544 /* If we are normal server and have not resolved information from
1545 router yet, do so now. */
1546 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1547 server->server_type == SILC_SERVER && !cmd->pending &&
1548 !server->standalone) {
1549 silc_server_command_identify_send_router(cmd);
1550 silc_free(*clients);
1551 silc_free(*servers);
1552 silc_free(*channels);
1555 silc_server_command_send_status_data(
1556 cmd, SILC_COMMAND_IDENTIFY,
1557 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1570 silc_free(*clients);
1571 silc_free(*servers);
1572 silc_free(*channels);
1576 /* Get the max count of reply messages allowed */
1577 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1586 /* Checks that all mandatory fields in client entry are present. If not
1587 then send WHOIS request to the server who owns the client. We use
1588 WHOIS because we want to get as much information as possible at once. */
1591 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1592 SilcClientEntry *clients,
1593 SilcUInt32 clients_count)
1595 SilcServer server = cmd->server;
1596 SilcClientEntry entry;
1597 SilcServerResolveContext resolve = NULL, r = NULL;
1598 SilcUInt32 resolve_count = 0;
1602 for (i = 0; i < clients_count; i++) {
1607 if (entry->nickname ||
1608 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1612 /* If we are normal server, and we've not resolved this client from
1613 router and it is global client, we'll check whether it is on some
1614 channel. If not then we cannot be sure about its validity, and
1615 we'll resolve it from router. */
1616 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1617 entry->connection || silc_hash_table_count(entry->channels))
1621 /* We need to resolve this entry since it is not complete */
1623 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1624 /* The entry is being resolved (and we are not the resolver) so attach
1625 to the command reply and we're done with this one. */
1626 silc_server_command_pending(server, SILC_COMMAND_NONE,
1627 entry->resolve_cmd_ident,
1628 silc_server_command_identify,
1629 silc_server_command_dup(cmd));
1632 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1633 /* We've resolved this and it still is not ready. We'll return
1634 and are that this will be handled again after it is resolved. */
1635 for (i = 0; i < resolve_count; i++) {
1636 for (k = 0; k < r->res_argc; k++)
1637 silc_free(r->res_argv[k]);
1638 silc_free(r->res_argv);
1639 silc_free(r->res_argv_lens);
1640 silc_free(r->res_argv_types);
1645 /* We'll resolve this client */
1649 for (k = 0; k < resolve_count; k++) {
1650 if (resolve[k].router == entry->router) {
1657 resolve = silc_realloc(resolve, sizeof(*resolve) *
1658 (resolve_count + 1));
1659 r = &resolve[resolve_count];
1660 memset(r, 0, sizeof(*r));
1661 r->router = entry->router;
1662 r->ident = ++server->cmd_ident;
1666 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1668 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1669 sizeof(*r->res_argv_lens) *
1671 r->res_argv_types = silc_realloc(r->res_argv_types,
1672 sizeof(*r->res_argv_types) *
1674 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1675 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1676 sizeof(**r->res_argv));
1677 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1678 r->res_argv_lens[r->res_argc] = idp->len;
1679 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1681 silc_buffer_free(idp);
1683 entry->resolve_cmd_ident = r->ident;
1684 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1685 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1690 /* Do the resolving */
1691 for (i = 0; i < resolve_count; i++) {
1696 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1697 now anyway so make it a good one. */
1698 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1699 r->res_argc, r->res_argv,
1703 silc_server_packet_send(server, r->router->connection,
1704 SILC_PACKET_COMMAND, cmd->packet->flags,
1705 res_cmd->data, res_cmd->len, FALSE);
1707 /* Reprocess this packet after received reply */
1708 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1710 silc_server_command_identify,
1711 silc_server_command_dup(cmd));
1712 cmd->pending = TRUE;
1714 silc_buffer_free(res_cmd);
1715 for (k = 0; k < r->res_argc; k++)
1716 silc_free(r->res_argv[k]);
1717 silc_free(r->res_argv);
1718 silc_free(r->res_argv_lens);
1719 silc_free(r->res_argv_types);
1728 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1729 SilcClientEntry *clients,
1730 SilcUInt32 clients_count,
1731 SilcServerEntry *servers,
1732 SilcUInt32 servers_count,
1733 SilcChannelEntry *channels,
1734 SilcUInt32 channels_count,
1737 SilcServer server = cmd->server;
1738 int i, k, len, valid_count;
1739 SilcBuffer packet, idp;
1740 SilcCommandStatus status;
1741 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1742 char nh[256], uh[256];
1743 SilcSocketConnection hsock;
1745 status = SILC_STATUS_OK;
1748 SilcClientEntry entry;
1750 /* Process only valid entries. */
1752 for (i = 0; i < clients_count; i++) {
1753 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1760 /* No valid entries found at all, just send error */
1763 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1765 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1766 SILC_STATUS_ERR_NO_SUCH_NICK,
1767 3, tmp, strlen(tmp));
1769 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1770 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1771 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1777 /* Process all valid client entries and send command replies */
1779 if (valid_count > 1)
1780 status = SILC_STATUS_LIST_START;
1782 for (i = 0, k = 0; i < clients_count; i++) {
1788 status = SILC_STATUS_LIST_ITEM;
1789 if (valid_count > 1 && k == valid_count - 1
1790 && !servers_count && !channels_count)
1791 status = SILC_STATUS_LIST_END;
1792 if (count && k - 1 == count)
1793 status = SILC_STATUS_LIST_END;
1794 if (count && k - 1 > count)
1797 /* Send IDENTIFY reply */
1799 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1800 memset(uh, 0, sizeof(uh));
1801 memset(nh, 0, sizeof(nh));
1802 strncat(nh, entry->nickname, strlen(entry->nickname));
1803 if (!strchr(entry->nickname, '@')) {
1804 strncat(nh, "@", 1);
1805 if (entry->servername) {
1806 strncat(nh, entry->servername, strlen(entry->servername));
1808 len = entry->router ? strlen(entry->router->server_name) :
1809 strlen(server->server_name);
1810 strncat(nh, entry->router ? entry->router->server_name :
1811 server->server_name, len);
1815 if (!entry->username) {
1816 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1817 status, 0, ident, 2,
1818 2, idp->data, idp->len,
1821 strncat(uh, entry->username, strlen(entry->username));
1822 if (!strchr(entry->username, '@')) {
1823 strncat(uh, "@", 1);
1824 hsock = (SilcSocketConnection)entry->connection;
1825 len = strlen(hsock->hostname);
1826 strncat(uh, hsock->hostname, len);
1829 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1830 status, 0, ident, 3,
1831 2, idp->data, idp->len,
1836 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1837 0, packet->data, packet->len, FALSE);
1839 silc_buffer_free(packet);
1840 silc_buffer_free(idp);
1847 SilcServerEntry entry;
1849 if (status == SILC_STATUS_OK && servers_count > 1)
1850 status = SILC_STATUS_LIST_START;
1852 for (i = 0, k = 0; i < servers_count; i++) {
1856 status = SILC_STATUS_LIST_ITEM;
1857 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1858 status = SILC_STATUS_LIST_END;
1859 if (count && k - 1 == count)
1860 status = SILC_STATUS_LIST_END;
1861 if (count && k - 1 > count)
1864 /* Send IDENTIFY reply */
1865 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1867 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1868 status, 0, ident, 2,
1869 2, idp->data, idp->len,
1870 3, entry->server_name,
1871 entry->server_name ?
1872 strlen(entry->server_name) : 0);
1873 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1874 0, packet->data, packet->len, FALSE);
1876 silc_buffer_free(packet);
1877 silc_buffer_free(idp);
1884 SilcChannelEntry entry;
1886 if (status == SILC_STATUS_OK && channels_count > 1)
1887 status = SILC_STATUS_LIST_START;
1889 for (i = 0, k = 0; i < channels_count; i++) {
1890 entry = channels[i];
1893 status = SILC_STATUS_LIST_ITEM;
1894 if (channels_count > 1 && k == channels_count - 1)
1895 status = SILC_STATUS_LIST_END;
1896 if (count && k - 1 == count)
1897 status = SILC_STATUS_LIST_END;
1898 if (count && k - 1 > count)
1901 /* Send IDENTIFY reply */
1902 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1904 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1905 status, 0, ident, 2,
1906 2, idp->data, idp->len,
1907 3, entry->channel_name,
1908 entry->channel_name ?
1909 strlen(entry->channel_name): 0);
1910 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1911 0, packet->data, packet->len, FALSE);
1913 silc_buffer_free(packet);
1914 silc_buffer_free(idp);
1922 silc_server_command_identify_process(SilcServerCommandContext cmd)
1924 SilcUInt32 count = 0;
1926 SilcClientEntry *clients = NULL;
1927 SilcServerEntry *servers = NULL;
1928 SilcChannelEntry *channels = NULL;
1929 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1931 /* Parse the IDENTIFY request */
1932 ret = silc_server_command_identify_parse(cmd,
1933 &clients, &clients_count,
1934 &servers, &servers_count,
1935 &channels, &channels_count,
1941 /* Check that all mandatory fields are present and request those data
1942 from the server who owns the client if necessary. */
1943 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1949 /* Send the command reply to the client */
1950 silc_server_command_identify_send_reply(cmd,
1951 clients, clients_count,
1952 servers, servers_count,
1953 channels, channels_count,
1959 silc_free(channels);
1963 SILC_SERVER_CMD_FUNC(identify)
1965 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1968 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1970 ret = silc_server_command_identify_process(cmd);
1971 silc_server_command_free(cmd);
1974 /* Server side of command NICK. Sets nickname for user. Setting
1975 nickname causes generation of a new client ID for the client. The
1976 new client ID is sent to the client after changing the nickname. */
1978 SILC_SERVER_CMD_FUNC(nick)
1980 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1981 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1982 SilcServer server = cmd->server;
1983 SilcBuffer packet, nidp, oidp = NULL;
1984 SilcClientID *new_id;
1985 SilcUInt32 nick_len;
1987 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1990 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1993 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1995 /* Check nickname */
1996 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
1999 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2001 SILC_STATUS_ERR_BAD_NICKNAME);
2005 /* Check for same nickname */
2006 if (!strcmp(client->nickname, nick)) {
2007 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2011 /* Create new Client ID */
2012 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2014 cmd->server->md5hash, nick,
2018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2019 SILC_STATUS_ERR_BAD_NICKNAME);
2022 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2025 /* Send notify about nickname change to our router. We send the new
2026 ID and ask to replace it with the old one. If we are router the
2027 packet is broadcasted. Send NICK_CHANGE notify. */
2028 if (!server->standalone)
2029 silc_server_send_notify_nick_change(server, server->router->connection,
2030 server->server_type == SILC_SERVER ?
2031 FALSE : TRUE, client->id,
2034 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2036 /* Remove old cache entry */
2037 silc_idcache_del_by_context(server->local_list->clients, client);
2040 silc_free(client->id);
2042 /* Save the nickname as this client is our local client */
2043 silc_free(client->nickname);
2045 client->nickname = strdup(nick);
2046 client->id = new_id;
2048 /* Update client cache */
2049 silc_idcache_add(server->local_list->clients, client->nickname,
2050 client->id, (void *)client, 0, NULL);
2052 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2054 /* Send NICK_CHANGE notify to the client's channels */
2055 silc_server_send_notify_on_channels(server, NULL, client,
2056 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2057 oidp->data, oidp->len,
2058 nidp->data, nidp->len,
2060 strlen(client->nickname));
2063 /* Send the new Client ID as reply command back to client */
2064 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2065 SILC_STATUS_OK, 0, ident, 1,
2066 2, nidp->data, nidp->len);
2067 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2068 0, packet->data, packet->len, FALSE);
2070 silc_buffer_free(packet);
2071 silc_buffer_free(nidp);
2073 silc_buffer_free(oidp);
2076 silc_server_command_free(cmd);
2079 /* Sends the LIST command reply */
2082 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2083 SilcChannelEntry *lch,
2084 SilcUInt32 lch_count,
2085 SilcChannelEntry *gch,
2086 SilcUInt32 gch_count)
2089 SilcBuffer packet, idp;
2090 SilcChannelEntry entry;
2091 SilcCommandStatus status;
2092 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2094 unsigned char usercount[4];
2096 int valid_lcount = 0, valid_rcount = 0;
2098 for (i = 0; i < lch_count; i++) {
2099 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2104 for (i = 0; i < gch_count; i++) {
2105 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2111 status = SILC_STATUS_OK;
2112 if ((lch_count + gch_count) > 1)
2113 status = SILC_STATUS_LIST_START;
2116 for (i = 0, k = 0; i < lch_count; i++) {
2122 status = SILC_STATUS_LIST_ITEM;
2123 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2124 status = SILC_STATUS_LIST_END;
2126 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2128 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2129 topic = "*private*";
2130 memset(usercount, 0, sizeof(usercount));
2132 topic = entry->topic;
2133 users = silc_hash_table_count(entry->user_list);
2134 SILC_PUT32_MSB(users, usercount);
2137 /* Send the reply */
2139 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2140 status, 0, ident, 4,
2141 2, idp->data, idp->len,
2142 3, entry->channel_name,
2143 strlen(entry->channel_name),
2144 4, topic, topic ? strlen(topic) : 0,
2146 silc_server_packet_send(cmd->server, cmd->sock,
2147 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2148 packet->len, FALSE);
2149 silc_buffer_free(packet);
2150 silc_buffer_free(idp);
2155 for (i = 0, k = 0; i < gch_count; i++) {
2161 status = SILC_STATUS_LIST_ITEM;
2162 if (valid_rcount > 1 && k == valid_rcount - 1)
2163 status = SILC_STATUS_LIST_END;
2165 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2167 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2168 topic = "*private*";
2169 memset(usercount, 0, sizeof(usercount));
2171 topic = entry->topic;
2172 users = entry->user_count;
2173 SILC_PUT32_MSB(users, usercount);
2176 /* Send the reply */
2178 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2179 status, 0, ident, 4,
2180 2, idp->data, idp->len,
2181 3, entry->channel_name,
2182 strlen(entry->channel_name),
2183 4, topic, topic ? strlen(topic) : 0,
2185 silc_server_packet_send(cmd->server, cmd->sock,
2186 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2187 packet->len, FALSE);
2188 silc_buffer_free(packet);
2189 silc_buffer_free(idp);
2194 /* Server side of LIST command. This lists the channel of the requested
2195 server. Secret channels are not listed. */
2197 SILC_SERVER_CMD_FUNC(list)
2199 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2200 SilcServer server = cmd->server;
2201 SilcChannelID *channel_id = NULL;
2204 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2205 SilcUInt32 lch_count = 0, gch_count = 0;
2207 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2209 /* If we are normal server, send the command to router, since we
2210 want to know all channels in the network. */
2211 if (!cmd->pending && server->server_type == SILC_SERVER &&
2212 !server->standalone) {
2214 SilcUInt16 old_ident;
2216 old_ident = silc_command_get_ident(cmd->payload);
2217 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2218 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2219 silc_server_packet_send(server, server->router->connection,
2220 SILC_PACKET_COMMAND, cmd->packet->flags,
2221 tmpbuf->data, tmpbuf->len, TRUE);
2223 /* Reprocess this packet after received reply from router */
2224 silc_server_command_pending(server, SILC_COMMAND_LIST,
2225 silc_command_get_ident(cmd->payload),
2226 silc_server_command_list,
2227 silc_server_command_dup(cmd));
2228 cmd->pending = TRUE;
2229 silc_command_set_ident(cmd->payload, old_ident);
2230 silc_buffer_free(tmpbuf);
2234 /* Get Channel ID */
2235 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2237 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2240 SILC_STATUS_ERR_NO_CHANNEL_ID);
2245 /* Get the channels from local list */
2246 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2249 /* Get the channels from global list */
2250 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2253 /* Send the reply */
2254 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2255 gchannels, gch_count);
2257 silc_free(lchannels);
2258 silc_free(gchannels);
2261 silc_server_command_free(cmd);
2264 /* Server side of TOPIC command. Sets topic for channel and/or returns
2265 current topic to client. */
2267 SILC_SERVER_CMD_FUNC(topic)
2269 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2270 SilcServer server = cmd->server;
2271 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2272 SilcChannelID *channel_id;
2273 SilcChannelEntry channel;
2274 SilcChannelClientEntry chl;
2275 SilcBuffer packet, idp;
2277 SilcUInt32 argc, tmp_len;
2278 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2280 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2282 argc = silc_argument_get_arg_num(cmd->args);
2284 /* Get Channel ID */
2285 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2288 SILC_STATUS_ERR_NO_CHANNEL_ID);
2291 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2294 SILC_STATUS_ERR_NO_CHANNEL_ID);
2298 /* Check whether the channel exists */
2299 channel = silc_idlist_find_channel_by_id(server->local_list,
2302 channel = silc_idlist_find_channel_by_id(server->global_list,
2305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2306 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2313 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2316 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2320 if (strlen(tmp) > 256) {
2321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2322 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2326 /* See whether the client is on channel and has rights to change topic */
2327 if (!silc_server_client_on_channel(client, channel, &chl)) {
2328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2329 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2333 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2334 channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2336 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2340 /* Set the topic for channel */
2341 silc_free(channel->topic);
2342 channel->topic = strdup(tmp);
2344 /* Send TOPIC_SET notify type to the network */
2345 if (!server->standalone)
2346 silc_server_send_notify_topic_set(server, server->router->connection,
2347 server->server_type == SILC_ROUTER ?
2348 TRUE : FALSE, channel,
2349 client->id, SILC_ID_CLIENT,
2352 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2354 /* Send notify about topic change to all clients on the channel */
2355 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2356 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2357 idp->data, idp->len,
2358 channel->topic, strlen(channel->topic));
2359 silc_buffer_free(idp);
2362 /* Send the topic to client as reply packet */
2363 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2364 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2365 SILC_STATUS_OK, 0, ident, 2,
2366 2, idp->data, idp->len,
2369 strlen(channel->topic) : 0);
2370 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2371 0, packet->data, packet->len, FALSE);
2373 silc_buffer_free(packet);
2374 silc_buffer_free(idp);
2375 silc_free(channel_id);
2378 silc_server_command_free(cmd);
2381 /* Server side of INVITE command. Invites some client to join some channel.
2382 This command is also used to manage the invite list of the channel. */
2384 SILC_SERVER_CMD_FUNC(invite)
2386 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2387 SilcServer server = cmd->server;
2388 SilcSocketConnection sock = cmd->sock, dest_sock;
2389 SilcChannelClientEntry chl;
2390 SilcClientEntry sender, dest;
2391 SilcClientID *dest_id = NULL;
2392 SilcChannelEntry channel;
2393 SilcChannelID *channel_id = NULL;
2394 SilcIDListData idata;
2395 SilcBuffer idp, idp2, packet;
2396 unsigned char *tmp, *add, *del;
2398 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2400 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2402 /* Get Channel ID */
2403 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406 SILC_STATUS_ERR_NO_CHANNEL_ID);
2409 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2412 SILC_STATUS_ERR_NO_CHANNEL_ID);
2416 /* Get the channel entry */
2417 channel = silc_idlist_find_channel_by_id(server->local_list,
2420 channel = silc_idlist_find_channel_by_id(server->global_list,
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2424 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2429 /* Check whether the sender of this command is on the channel. */
2430 sender = (SilcClientEntry)sock->user_data;
2431 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2433 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2437 /* Check whether the channel is invite-only channel. If yes then the
2438 sender of this command must be at least channel operator. */
2439 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2440 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2442 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2446 /* Get destination client ID */
2447 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2452 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2455 SILC_STATUS_ERR_NO_CLIENT_ID);
2459 /* Get the client entry */
2460 dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2462 if (server->server_type != SILC_SERVER || !resolve) {
2463 silc_server_command_send_status_reply(
2464 cmd, SILC_COMMAND_INVITE,
2465 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2469 /* The client info is being resolved. Reprocess this packet after
2470 receiving the reply to the query. */
2471 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2473 silc_server_command_invite,
2474 silc_server_command_dup(cmd));
2475 cmd->pending = TRUE;
2476 silc_free(channel_id);
2481 /* Check whether the requested client is already on the channel. */
2482 if (silc_server_client_on_channel(dest, channel, NULL)) {
2483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2484 SILC_STATUS_ERR_USER_ON_CHANNEL);
2488 /* Get route to the client */
2489 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2493 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2497 memset(invite, 0, sizeof(invite));
2498 strncat(invite, dest->nickname, strlen(dest->nickname));
2499 strncat(invite, "!", 1);
2500 strncat(invite, dest->username, strlen(dest->username));
2501 if (!strchr(dest->username, '@')) {
2502 strncat(invite, "@", 1);
2503 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2506 len = strlen(invite);
2507 if (!channel->invite_list)
2508 channel->invite_list = silc_calloc(len + 2,
2509 sizeof(*channel->invite_list));
2511 channel->invite_list = silc_realloc(channel->invite_list,
2512 sizeof(*channel->invite_list) *
2514 strlen(channel->invite_list) + 2));
2515 strncat(channel->invite_list, invite, len);
2516 strncat(channel->invite_list, ",", 1);
2518 /* Send notify to the client that is invited to the channel */
2519 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2520 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2521 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2523 SILC_NOTIFY_TYPE_INVITE, 3,
2524 idp->data, idp->len,
2525 channel->channel_name,
2526 strlen(channel->channel_name),
2527 idp2->data, idp2->len);
2528 silc_buffer_free(idp);
2529 silc_buffer_free(idp2);
2532 /* Add the client to the invite list of the channel */
2533 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2535 if (!channel->invite_list)
2536 channel->invite_list = silc_calloc(len + 2,
2537 sizeof(*channel->invite_list));
2539 channel->invite_list = silc_realloc(channel->invite_list,
2540 sizeof(*channel->invite_list) *
2542 strlen(channel->invite_list) + 2));
2543 if (add[len - 1] == ',')
2544 add[len - 1] = '\0';
2546 strncat(channel->invite_list, add, len);
2547 strncat(channel->invite_list, ",", 1);
2550 /* Get the invite to be removed and remove it from the list */
2551 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2552 if (del && channel->invite_list) {
2553 char *start, *end, *n;
2555 if (!strncmp(channel->invite_list, del,
2556 strlen(channel->invite_list) - 1)) {
2557 silc_free(channel->invite_list);
2558 channel->invite_list = NULL;
2560 start = strstr(channel->invite_list, del);
2561 if (start && strlen(start) >= len) {
2563 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2564 strncat(n, channel->invite_list, start - channel->invite_list);
2565 strncat(n, end + 1, ((channel->invite_list +
2566 strlen(channel->invite_list)) - end) - 1);
2567 silc_free(channel->invite_list);
2568 channel->invite_list = n;
2573 /* Send notify to the primary router */
2574 if (!server->standalone)
2575 silc_server_send_notify_invite(server, server->router->connection,
2576 server->server_type == SILC_ROUTER ?
2577 TRUE : FALSE, channel,
2578 sender->id, add, del);
2580 /* Send command reply */
2581 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2585 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2586 SILC_STATUS_OK, 0, ident, 2,
2588 3, channel->invite_list,
2589 channel->invite_list ?
2590 strlen(channel->invite_list) : 0);
2593 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2594 SILC_STATUS_OK, 0, ident, 1,
2596 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2597 packet->data, packet->len, FALSE);
2598 silc_buffer_free(packet);
2602 silc_free(channel_id);
2603 silc_server_command_free(cmd);
2608 SilcSocketConnection sock;
2612 /* Quits connection to client. This gets called if client won't
2613 close the connection even when it has issued QUIT command. */
2615 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2617 QuitInternal q = (QuitInternal)context;
2619 /* Free all client specific data, such as client entry and entires
2620 on channels this client may be on. */
2621 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2623 q->sock->user_data = NULL;
2625 /* Close the connection on our side */
2626 silc_server_close_connection(q->server, q->sock);
2628 silc_free(q->signoff);
2632 /* Quits SILC session. This is the normal way to disconnect client. */
2634 SILC_SERVER_CMD_FUNC(quit)
2636 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2637 SilcServer server = cmd->server;
2638 SilcSocketConnection sock = cmd->sock;
2640 unsigned char *tmp = NULL;
2643 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2645 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2649 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2653 q = silc_calloc(1, sizeof(*q));
2656 q->signoff = tmp ? strdup(tmp) : NULL;
2658 /* We quit the connection with little timeout */
2659 silc_schedule_task_add(server->schedule, sock->sock,
2660 silc_server_command_quit_cb, (void *)q,
2661 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2664 silc_server_command_free(cmd);
2667 /* Server side of command KILL. This command is used by router operator
2668 to remove an client from the SILC Network temporarily. */
2670 SILC_SERVER_CMD_FUNC(kill)
2672 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2673 SilcServer server = cmd->server;
2674 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2675 SilcClientEntry remote_client;
2676 SilcClientID *client_id;
2677 unsigned char *tmp, *comment;
2678 SilcUInt32 tmp_len, tmp_len2;
2681 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2683 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2686 /* KILL command works only on router */
2687 if (server->server_type != SILC_ROUTER) {
2688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2689 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2693 /* Check whether client has the permissions. */
2694 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2696 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2700 /* Get the client ID */
2701 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2704 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2707 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2710 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2714 /* Get the client entry */
2715 remote_client = silc_idlist_find_client_by_id(server->local_list,
2716 client_id, TRUE, NULL);
2718 if (!remote_client) {
2719 remote_client = silc_idlist_find_client_by_id(server->global_list,
2720 client_id, TRUE, NULL);
2722 if (!remote_client) {
2723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2724 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2730 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2734 /* Send reply to the sender */
2735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2738 /* Now do the killing */
2739 silc_server_kill_client(server, remote_client, comment, client->id,
2743 silc_server_command_free(cmd);
2746 /* Server side of command INFO. This sends information about us to
2747 the client. If client requested specific server we will send the
2748 command to that server. */
2750 SILC_SERVER_CMD_FUNC(info)
2752 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2753 SilcServer server = cmd->server;
2754 SilcBuffer packet, idp;
2757 char *dest_server, *server_info = NULL, *server_name;
2758 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2759 SilcServerEntry entry = NULL;
2760 SilcServerID *server_id = NULL;
2762 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2764 /* Get server name */
2765 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2768 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2770 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2773 SILC_STATUS_ERR_NO_SERVER_ID);
2779 /* Check whether we have this server cached */
2780 entry = silc_idlist_find_server_by_id(server->local_list,
2781 server_id, TRUE, NULL);
2783 entry = silc_idlist_find_server_by_id(server->global_list,
2784 server_id, TRUE, NULL);
2785 if (!entry && server->server_type != SILC_SERVER) {
2786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2787 SILC_STATUS_ERR_NO_SUCH_SERVER);
2793 /* Some buggy servers has sent request to router about themselves. */
2794 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2797 if ((!dest_server && !server_id && !entry) || (entry &&
2798 entry == server->id_entry) ||
2799 (dest_server && !cmd->pending &&
2800 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2801 /* Send our reply */
2802 char info_string[256];
2804 memset(info_string, 0, sizeof(info_string));
2805 snprintf(info_string, sizeof(info_string),
2806 "location: %s server: %s admin: %s <%s>",
2807 server->config->server_info->location,
2808 server->config->server_info->server_type,
2809 server->config->server_info->admin,
2810 server->config->server_info->email);
2812 server_info = info_string;
2813 entry = server->id_entry;
2815 /* Check whether we have this server cached */
2816 if (!entry && dest_server) {
2817 entry = silc_idlist_find_server_by_name(server->global_list,
2818 dest_server, TRUE, NULL);
2820 entry = silc_idlist_find_server_by_name(server->local_list,
2821 dest_server, TRUE, NULL);
2825 if (!cmd->pending &&
2826 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2827 /* Send to the server */
2829 SilcUInt16 old_ident;
2831 old_ident = silc_command_get_ident(cmd->payload);
2832 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2833 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2835 silc_server_packet_send(server, entry->connection,
2836 SILC_PACKET_COMMAND, cmd->packet->flags,
2837 tmpbuf->data, tmpbuf->len, TRUE);
2839 /* Reprocess this packet after received reply from router */
2840 silc_server_command_pending(server, SILC_COMMAND_INFO,
2841 silc_command_get_ident(cmd->payload),
2842 silc_server_command_info,
2843 silc_server_command_dup(cmd));
2844 cmd->pending = TRUE;
2845 silc_command_set_ident(cmd->payload, old_ident);
2846 silc_buffer_free(tmpbuf);
2850 if (!entry && !cmd->pending && !server->standalone) {
2851 /* Send to the primary router */
2853 SilcUInt16 old_ident;
2855 old_ident = silc_command_get_ident(cmd->payload);
2856 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2857 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2859 silc_server_packet_send(server, server->router->connection,
2860 SILC_PACKET_COMMAND, cmd->packet->flags,
2861 tmpbuf->data, tmpbuf->len, TRUE);
2863 /* Reprocess this packet after received reply from router */
2864 silc_server_command_pending(server, SILC_COMMAND_INFO,
2865 silc_command_get_ident(cmd->payload),
2866 silc_server_command_info,
2867 silc_server_command_dup(cmd));
2868 cmd->pending = TRUE;
2869 silc_command_set_ident(cmd->payload, old_ident);
2870 silc_buffer_free(tmpbuf);
2875 silc_free(server_id);
2878 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2879 SILC_STATUS_ERR_NO_SUCH_SERVER);
2883 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2885 server_info = entry->server_info;
2886 server_name = entry->server_name;
2888 /* Send the reply */
2889 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2890 SILC_STATUS_OK, 0, ident, 3,
2891 2, idp->data, idp->len,
2893 strlen(server_name),
2896 strlen(server_info) : 0);
2897 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2898 packet->data, packet->len, FALSE);
2900 silc_buffer_free(packet);
2901 silc_buffer_free(idp);
2904 silc_server_command_free(cmd);
2907 /* Server side of command PING. This just replies to the ping. */
2909 SILC_SERVER_CMD_FUNC(ping)
2911 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2912 SilcServer server = cmd->server;
2917 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2920 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2923 SILC_STATUS_ERR_NO_SERVER_ID);
2926 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2930 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2931 /* Send our reply */
2932 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2936 SILC_STATUS_ERR_NO_SUCH_SERVER);
2943 silc_server_command_free(cmd);
2946 /* Server side of command STATS. */
2948 SILC_SERVER_CMD_FUNC(stats)
2950 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2951 SilcServer server = cmd->server;
2952 SilcServerID *server_id;
2955 SilcBuffer packet, stats;
2956 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2959 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
2962 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2965 SILC_STATUS_ERR_NO_SERVER_ID);
2968 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2972 /* The ID must be ours */
2973 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
2974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2975 SILC_STATUS_ERR_NO_SUCH_SERVER);
2976 silc_free(server_id);
2979 silc_free(server_id);
2981 /* If we are router then just send everything we got. If we are normal
2982 server then we'll send this to our router to get all the latest
2983 statistical information. */
2984 if (!cmd->pending && server->server_type != SILC_ROUTER &&
2985 !server->standalone) {
2986 /* Send request to our router */
2987 SilcBuffer idp = silc_id_payload_encode(server->router->id,
2989 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
2990 ++server->cmd_ident, 1,
2991 1, idp->data, idp->len);
2992 silc_server_packet_send(server, server->router->connection,
2993 SILC_PACKET_COMMAND, 0, packet->data,
2994 packet->len, FALSE);
2996 /* Reprocess this packet after received reply from router */
2997 silc_server_command_pending(server, SILC_COMMAND_STATS,
2999 silc_server_command_stats,
3000 silc_server_command_dup(cmd));
3001 cmd->pending = TRUE;
3002 silc_buffer_free(packet);
3003 silc_buffer_free(idp);
3007 /* Send our reply to sender */
3008 uptime = time(NULL) - server->starttime;
3010 stats = silc_buffer_alloc_size(60);
3011 silc_buffer_format(stats,
3012 SILC_STR_UI_INT(server->starttime),
3013 SILC_STR_UI_INT(uptime),
3014 SILC_STR_UI_INT(server->stat.my_clients),
3015 SILC_STR_UI_INT(server->stat.my_channels),
3016 SILC_STR_UI_INT(server->stat.my_server_ops),
3017 SILC_STR_UI_INT(server->stat.my_router_ops),
3018 SILC_STR_UI_INT(server->stat.cell_clients),
3019 SILC_STR_UI_INT(server->stat.cell_channels),
3020 SILC_STR_UI_INT(server->stat.cell_servers),
3021 SILC_STR_UI_INT(server->stat.clients),
3022 SILC_STR_UI_INT(server->stat.channels),
3023 SILC_STR_UI_INT(server->stat.servers),
3024 SILC_STR_UI_INT(server->stat.routers),
3025 SILC_STR_UI_INT(server->stat.server_ops),
3026 SILC_STR_UI_INT(server->stat.router_ops),
3029 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3030 SILC_STATUS_OK, 0, ident, 2,
3032 3, stats->data, stats->len);
3033 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3034 0, packet->data, packet->len, FALSE);
3035 silc_buffer_free(packet);
3036 silc_buffer_free(stats);
3039 silc_server_command_free(cmd);
3042 /* Internal routine to join channel. The channel sent to this function
3043 has been either created or resolved from ID lists. This joins the sent
3044 client to the channel. */
3046 static void silc_server_command_join_channel(SilcServer server,
3047 SilcServerCommandContext cmd,
3048 SilcChannelEntry channel,
3049 SilcClientID *client_id,
3053 const unsigned char *auth,
3054 SilcUInt32 auth_len)
3056 SilcSocketConnection sock = cmd->sock;
3058 SilcUInt32 tmp_len, user_count;
3059 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3060 SilcClientEntry client;
3061 SilcChannelClientEntry chl;
3062 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3063 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3064 char check[512], check2[512];
3065 bool founder = FALSE;
3068 SILC_LOG_DEBUG(("Start"));
3073 /* Get the client entry */
3074 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3075 client = (SilcClientEntry)sock->user_data;
3077 client = silc_server_get_client_resolve(server, client_id, &resolve);
3083 silc_server_command_send_status_reply(
3084 cmd, SILC_COMMAND_JOIN,
3085 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3089 /* The client info is being resolved. Reprocess this packet after
3090 receiving the reply to the query. */
3091 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3093 silc_server_command_join,
3094 silc_server_command_dup(cmd));
3095 cmd->pending = TRUE;
3099 cmd->pending = FALSE;
3103 * Check founder auth payload if provided. If client can gain founder
3104 * privileges it can override various conditions on joining the channel,
3105 * and can have directly the founder mode set on the channel.
3107 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3108 SilcIDListData idata = (SilcIDListData)client;
3110 if (channel->founder_key && idata->public_key &&
3111 silc_pkcs_public_key_compare(channel->founder_key,
3112 idata->public_key)) {
3113 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3114 (void *)channel->founder_passwd :
3115 (void *)channel->founder_key);
3116 SilcUInt32 auth_data_len =
3117 (channel->founder_method == SILC_AUTH_PASSWORD ?
3118 channel->founder_passwd_len : 0);
3120 /* Check whether the client is to become founder */
3121 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3122 auth_data, auth_data_len,
3123 idata->hash, client->id, SILC_ID_CLIENT)) {
3124 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3131 * Check channel modes
3135 memset(check, 0, sizeof(check));
3136 memset(check2, 0, sizeof(check2));
3137 strncat(check, client->nickname, strlen(client->nickname));
3138 strncat(check, "!", 1);
3139 strncat(check, client->username, strlen(client->username));
3140 if (!strchr(client->username, '@')) {
3141 strncat(check, "@", 1);
3142 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3145 strncat(check2, client->nickname, strlen(client->nickname));
3146 if (!strchr(client->nickname, '@')) {
3147 strncat(check2, "@", 1);
3148 strncat(check2, server->server_name, strlen(server->server_name));
3150 strncat(check2, "!", 1);
3151 strncat(check2, client->username, strlen(client->username));
3152 if (!strchr(client->username, '@')) {
3153 strncat(check2, "@", 1);
3154 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3157 /* Check invite list if channel is invite-only channel */
3158 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3159 if (!channel->invite_list ||
3160 (!silc_string_match(channel->invite_list, check) &&
3161 !silc_string_match(channel->invite_list, check2))) {
3162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3163 SILC_STATUS_ERR_NOT_INVITED);
3168 /* Check ban list if it exists. If the client's nickname, server,
3169 username and/or hostname is in the ban list the access to the
3170 channel is denied. */
3171 if (channel->ban_list) {
3172 if (silc_string_match(channel->ban_list, check) ||
3173 silc_string_match(channel->ban_list, check2)) {
3174 silc_server_command_send_status_reply(
3175 cmd, SILC_COMMAND_JOIN,
3176 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3181 /* Check user count limit if set. */
3182 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3183 if (silc_hash_table_count(channel->user_list) + 1 >
3184 channel->user_limit) {
3185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3186 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3192 /* Check the channel passphrase if set. */
3193 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3194 /* Get passphrase */
3195 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3197 passphrase = silc_memdup(tmp, tmp_len);
3199 if (!passphrase || !channel->passphrase ||
3200 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3202 SILC_STATUS_ERR_BAD_PASSWORD);
3208 * Client is allowed to join to the channel. Make it happen.
3211 /* Check whether the client already is on the channel */
3212 if (silc_server_client_on_channel(client, channel, NULL)) {
3213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3214 SILC_STATUS_ERR_USER_ON_CHANNEL);
3218 /* Generate new channel key as protocol dictates */
3220 if (!silc_server_create_channel_key(server, channel, 0))
3223 /* Send the channel key. This is broadcasted to the channel but is not
3224 sent to the client who is joining to the channel. */
3225 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3226 silc_server_send_channel_key(server, NULL, channel,
3227 server->server_type == SILC_ROUTER ?
3228 FALSE : !server->standalone);
3231 /* Join the client to the channel by adding it to channel's user list.
3232 Add also the channel to client entry's channels list for fast cross-
3234 chl = silc_calloc(1, sizeof(*chl));
3236 chl->client = client;
3237 chl->channel = channel;
3238 silc_hash_table_add(channel->user_list, client, chl);
3239 silc_hash_table_add(client->channels, channel, chl);
3240 channel->user_count++;
3242 /* Get users on the channel */
3243 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3246 /* Encode Client ID Payload of the original client who wants to join */
3247 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3249 /* Encode command reply packet */
3250 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3251 SILC_PUT32_MSB(channel->mode, mode);
3252 SILC_PUT32_MSB(created, tmp2);
3253 SILC_PUT32_MSB(user_count, tmp3);
3255 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3256 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3257 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3260 strlen(channel->channel_key->
3262 channel->channel_key->cipher->name,
3263 channel->key_len / 8, channel->key);
3268 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3269 SILC_STATUS_OK, 0, ident, 13,
3270 2, channel->channel_name,
3271 strlen(channel->channel_name),
3272 3, chidp->data, chidp->len,
3273 4, clidp->data, clidp->len,
3276 7, keyp ? keyp->data : NULL,
3277 keyp ? keyp->len : 0,
3278 8, channel->ban_list,
3280 strlen(channel->ban_list) : 0,
3281 9, channel->invite_list,
3282 channel->invite_list ?
3283 strlen(channel->invite_list) : 0,
3286 strlen(channel->topic) : 0,
3287 11, silc_hmac_get_name(channel->hmac),
3288 strlen(silc_hmac_get_name(channel->
3291 13, user_list->data, user_list->len,
3292 14, mode_list->data,
3295 /* Send command reply */
3296 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3297 reply->data, reply->len, FALSE);
3299 /* Send JOIN notify to locally connected clients on the channel. If
3300 we are normal server then router will send or have sent JOIN notify
3301 already. However since we've added the client already to our channel
3302 we'll ignore it (in packet_receive.c) so we must send it here. If
3303 we are router then this will send it to local clients and local
3305 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3306 SILC_NOTIFY_TYPE_JOIN, 2,
3307 clidp->data, clidp->len,
3308 chidp->data, chidp->len);
3310 if (!cmd->pending) {
3311 /* Send JOIN notify packet to our primary router */
3312 if (!server->standalone)
3313 silc_server_send_notify_join(server, server->router->connection,
3314 server->server_type == SILC_ROUTER ?
3315 TRUE : FALSE, channel, client->id);
3318 /* Distribute the channel key to all backup routers. */
3319 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3320 keyp->data, keyp->len, FALSE, TRUE);
3323 /* If client became founder by providing correct founder auth data
3324 notify the mode change to the channel. */
3326 SILC_PUT32_MSB(chl->mode, mode);
3327 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3328 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3329 clidp->data, clidp->len,
3330 mode, 4, clidp->data, clidp->len);
3332 /* Set CUMODE notify type to network */
3333 if (!server->standalone)
3334 silc_server_send_notify_cumode(server, server->router->connection,
3335 server->server_type == SILC_ROUTER ?
3336 TRUE : FALSE, channel,
3337 chl->mode, client->id, SILC_ID_CLIENT,
3341 silc_buffer_free(reply);
3342 silc_buffer_free(clidp);
3343 silc_buffer_free(chidp);
3344 silc_buffer_free(keyp);
3345 silc_buffer_free(user_list);
3346 silc_buffer_free(mode_list);
3349 silc_free(passphrase);
3352 /* Server side of command JOIN. Joins client into requested channel. If
3353 the channel does not exist it will be created. */
3355 SILC_SERVER_CMD_FUNC(join)
3357 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3358 SilcServer server = cmd->server;
3359 unsigned char *auth;
3360 SilcUInt32 tmp_len, auth_len;
3361 char *tmp, *channel_name = NULL, *cipher, *hmac;
3362 SilcChannelEntry channel;
3363 SilcUInt32 umode = 0;
3364 bool created = FALSE, create_key = TRUE;
3365 SilcClientID *client_id;
3367 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3369 /* Get channel name */
3370 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3373 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3379 channel_name[255] = '\0';
3381 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3383 SILC_STATUS_ERR_BAD_CHANNEL);
3387 /* Get Client ID of the client who is joining to the channel */
3388 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3391 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3394 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3397 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3401 /* Get cipher, hmac name and auth payload */
3402 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3403 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3404 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3406 /* See if the channel exists */
3407 channel = silc_idlist_find_channel_by_name(server->local_list,
3408 channel_name, NULL);
3410 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3411 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3412 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3414 if (!channel || channel->disabled) {
3415 /* Channel not found */
3417 /* If we are standalone server we don't have a router, we just create
3418 the channel by ourselves. */
3419 if (server->standalone) {
3420 channel = silc_server_create_new_channel(server, server->id, cipher,
3421 hmac, channel_name, TRUE);
3423 silc_server_command_send_status_reply(
3424 cmd, SILC_COMMAND_JOIN,
3425 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3429 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3435 /* The channel does not exist on our server. If we are normal server
3436 we will send JOIN command to our router which will handle the
3437 joining procedure (either creates the channel if it doesn't exist
3438 or joins the client to it). */
3439 if (server->server_type != SILC_ROUTER) {
3441 SilcUInt16 old_ident;
3443 /* If this is pending command callback then we've resolved
3444 it and it didn't work, return since we've notified the
3445 client already in the command reply callback. */
3449 old_ident = silc_command_get_ident(cmd->payload);
3450 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3451 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3453 /* Send JOIN command to our router */
3454 silc_server_packet_send(server, (SilcSocketConnection)
3455 server->router->connection,
3456 SILC_PACKET_COMMAND, cmd->packet->flags,
3457 tmpbuf->data, tmpbuf->len, TRUE);
3459 /* Reprocess this packet after received reply from router */
3460 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3461 silc_command_get_ident(cmd->payload),
3462 silc_server_command_join,
3463 silc_server_command_dup(cmd));
3464 cmd->pending = TRUE;
3465 silc_command_set_ident(cmd->payload, old_ident);
3466 silc_buffer_free(tmpbuf);
3470 /* We are router and the channel does not seem exist so we will check
3471 our global list as well for the channel. */
3472 channel = silc_idlist_find_channel_by_name(server->global_list,
3473 channel_name, NULL);
3475 /* Channel really does not exist, create it */
3476 channel = silc_server_create_new_channel(server, server->id, cipher,
3477 hmac, channel_name, TRUE);
3479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3480 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3484 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3492 /* Channel not found */
3494 /* If the command came from router and we are normal server then
3495 something went wrong with the joining as the channel was not found.
3496 We can't do anything else but ignore this. */
3497 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3498 server->server_type != SILC_ROUTER)
3501 /* We are router and the channel does not seem exist so we will check
3502 our global list as well for the channel. */
3503 channel = silc_idlist_find_channel_by_name(server->global_list,
3504 channel_name, NULL);
3506 /* Channel really does not exist, create it */
3507 channel = silc_server_create_new_channel(server, server->id, cipher,
3508 hmac, channel_name, TRUE);
3510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3511 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3515 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3522 /* Check whether the channel was created by our router */
3523 if (cmd->pending && context2) {
3524 SilcServerCommandReplyContext reply = context2;
3526 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3527 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3528 SILC_GET32_MSB(created, tmp);
3529 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3530 create_key = FALSE; /* Router returned the key already */
3533 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3534 !silc_hash_table_count(channel->user_list))
3538 /* If the channel does not have global users and is also empty the client
3539 will be the channel founder and operator. */
3540 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3541 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3543 /* Join to the channel */
3544 silc_server_command_join_channel(server, cmd, channel, client_id,
3545 created, create_key, umode,
3548 silc_free(client_id);
3551 silc_server_command_free(cmd);
3554 /* Server side of command MOTD. Sends server's current "message of the
3555 day" to the client. */
3557 SILC_SERVER_CMD_FUNC(motd)
3559 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3560 SilcServer server = cmd->server;
3561 SilcBuffer packet, idp;
3562 char *motd, *dest_server;
3563 SilcUInt32 motd_len;
3564 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3566 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3568 /* Get server name */
3569 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3571 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3572 SILC_STATUS_ERR_NO_SUCH_SERVER);
3576 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3579 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3581 if (server->config && server->config->server_info &&
3582 server->config->server_info->motd_file) {
3584 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3589 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3596 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3602 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3603 packet->data, packet->len, FALSE);
3604 silc_buffer_free(packet);
3605 silc_buffer_free(idp);
3607 SilcServerEntry entry;
3609 /* Check whether we have this server cached */
3610 entry = silc_idlist_find_server_by_name(server->global_list,
3611 dest_server, TRUE, NULL);
3613 entry = silc_idlist_find_server_by_name(server->local_list,
3614 dest_server, TRUE, NULL);
3617 if (server->server_type != SILC_SERVER && !cmd->pending &&
3618 entry && !entry->motd) {
3619 /* Send to the server */
3621 SilcUInt16 old_ident;
3623 old_ident = silc_command_get_ident(cmd->payload);
3624 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3625 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3627 silc_server_packet_send(server, entry->connection,
3628 SILC_PACKET_COMMAND, cmd->packet->flags,
3629 tmpbuf->data, tmpbuf->len, TRUE);
3631 /* Reprocess this packet after received reply from router */
3632 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3633 silc_command_get_ident(cmd->payload),
3634 silc_server_command_motd,
3635 silc_server_command_dup(cmd));
3636 cmd->pending = TRUE;
3637 silc_command_set_ident(cmd->payload, old_ident);
3638 silc_buffer_free(tmpbuf);
3642 if (!entry && !cmd->pending && !server->standalone) {
3643 /* Send to the primary router */
3645 SilcUInt16 old_ident;
3647 old_ident = silc_command_get_ident(cmd->payload);
3648 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3649 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3651 silc_server_packet_send(server, server->router->connection,
3652 SILC_PACKET_COMMAND, cmd->packet->flags,
3653 tmpbuf->data, tmpbuf->len, TRUE);
3655 /* Reprocess this packet after received reply from router */
3656 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3657 silc_command_get_ident(cmd->payload),
3658 silc_server_command_motd,
3659 silc_server_command_dup(cmd));
3660 cmd->pending = TRUE;
3661 silc_command_set_ident(cmd->payload, old_ident);
3662 silc_buffer_free(tmpbuf);
3667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3668 SILC_STATUS_ERR_NO_SUCH_SERVER);
3672 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3673 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3674 SILC_STATUS_OK, 0, ident, 2,
3678 strlen(entry->motd) : 0);
3679 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3680 packet->data, packet->len, FALSE);
3681 silc_buffer_free(packet);
3682 silc_buffer_free(idp);
3686 silc_server_command_free(cmd);
3689 /* Server side of command UMODE. Client can use this command to set/unset
3690 user mode. Client actually cannot set itself to be as server/router
3691 operator so this can be used only to unset the modes. */
3693 SILC_SERVER_CMD_FUNC(umode)
3695 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3696 SilcServer server = cmd->server;
3697 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3699 unsigned char *tmp_mask, m[4];
3700 SilcUInt32 mask = 0;
3701 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3702 bool set_mask = FALSE;
3704 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3707 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3709 /* Get the client's mode mask */
3710 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3712 SILC_GET32_MSB(mask, tmp_mask);
3717 /* Check that mode changing is allowed. */
3718 if (!silc_server_check_umode_rights(server, client, mask)) {
3719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3720 SILC_STATUS_ERR_PERM_DENIED);
3724 /* Anonymous mode cannot be set by client */
3725 if (mask & SILC_UMODE_ANONYMOUS) {
3726 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3728 SILC_STATUS_ERR_PERM_DENIED);
3732 if (client->mode & SILC_UMODE_ANONYMOUS) {
3733 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3734 SILC_STATUS_ERR_PERM_DENIED);
3739 /* Change the mode */
3740 client->mode = mask;
3742 /* Send UMODE change to primary router */
3743 if (!server->standalone)
3744 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3745 client->id, client->mode);
3748 /* Send command reply to sender */
3749 SILC_PUT32_MSB(client->mode, m);
3750 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3751 SILC_STATUS_OK, 0, ident, 1,
3753 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3754 packet->data, packet->len, FALSE);
3755 silc_buffer_free(packet);
3758 silc_server_command_free(cmd);
3761 /* Server side command of CMODE. Changes channel mode */
3763 SILC_SERVER_CMD_FUNC(cmode)
3765 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3766 SilcServer server = cmd->server;
3767 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3768 SilcIDListData idata = (SilcIDListData)client;
3769 SilcChannelID *channel_id = NULL;
3770 SilcChannelEntry channel;
3771 SilcChannelClientEntry chl;
3772 SilcBuffer packet, cidp;
3773 unsigned char *tmp, *tmp_id, *tmp_mask;
3774 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3775 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3776 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3777 bool set_mask = FALSE;
3779 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3781 /* Get Channel ID */
3782 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3785 SILC_STATUS_ERR_NO_CHANNEL_ID);
3788 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3791 SILC_STATUS_ERR_NO_CHANNEL_ID);
3795 /* Get the channel mode mask */
3796 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3798 SILC_GET32_MSB(mode_mask, tmp_mask);
3802 /* Get channel entry */
3803 channel = silc_idlist_find_channel_by_id(server->local_list,
3806 channel = silc_idlist_find_channel_by_id(server->global_list,
3809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3810 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3815 /* Check whether this client is on the channel */
3816 if (!silc_server_client_on_channel(client, channel, &chl)) {
3817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3818 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3822 /* Check that client has rights to change any requested channel modes */
3823 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3827 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3828 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3832 /* If mode mask was not sent as argument then merely return the current
3833 mode mask to the sender. */
3836 SILC_PUT32_MSB(channel->mode, m);
3837 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3838 SILC_STATUS_OK, 0, ident, 2,
3839 2, tmp_id, tmp_len2,
3841 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3842 packet->data, packet->len, FALSE);
3843 silc_buffer_free(packet);
3848 * Check the modes. Modes that requires nothing special operation are
3852 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3853 /* Channel uses private keys to protect traffic. Client(s) has set the
3854 key locally they want to use, server does not know that key. */
3855 /* Nothing interesting to do here */
3857 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3858 /* The mode is removed and we need to generate and distribute
3859 new channel key. Clients are not using private channel keys
3860 anymore after this. */
3862 /* Re-generate channel key */
3863 if (!silc_server_create_channel_key(server, channel, 0))
3866 /* Send the channel key. This sends it to our local clients and if
3867 we are normal server to our router as well. */
3868 silc_server_send_channel_key(server, NULL, channel,
3869 server->server_type == SILC_ROUTER ?
3870 FALSE : !server->standalone);
3872 cipher = channel->channel_key->cipher->name;
3873 hmac = (char *)silc_hmac_get_name(channel->hmac);
3877 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3878 /* User limit is set on channel */
3879 SilcUInt32 user_limit;
3881 /* Get user limit */
3882 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3884 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3886 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3890 SILC_GET32_MSB(user_limit, tmp);
3891 channel->user_limit = user_limit;
3894 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3895 /* User limit mode is unset. Remove user limit */
3896 channel->user_limit = 0;
3899 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3900 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3901 /* Passphrase has been set to channel */
3903 /* Get the passphrase */
3904 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3907 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3911 /* Save the passphrase */
3912 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3915 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3916 /* Passphrase mode is unset. remove the passphrase */
3917 silc_free(channel->passphrase);
3918 channel->passphrase = NULL;
3922 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3923 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3924 /* Cipher to use protect the traffic */
3925 SilcCipher newkey, oldkey;
3928 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3931 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3935 /* Delete old cipher and allocate the new one */
3936 if (!silc_cipher_alloc(cipher, &newkey)) {
3937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3938 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3942 oldkey = channel->channel_key;
3943 channel->channel_key = newkey;
3945 /* Re-generate channel key */
3946 if (!silc_server_create_channel_key(server, channel, 0)) {
3947 /* We don't have new key, revert to old one */
3948 channel->channel_key = oldkey;
3952 /* Remove old channel key for good */
3953 silc_cipher_free(oldkey);
3955 /* Send the channel key. This sends it to our local clients and if
3956 we are normal server to our router as well. */
3957 silc_server_send_channel_key(server, NULL, channel,
3958 server->server_type == SILC_ROUTER ?
3959 FALSE : !server->standalone);
3962 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3963 /* Cipher mode is unset. Remove the cipher and revert back to
3965 SilcCipher newkey, oldkey;
3966 cipher = channel->cipher;
3968 /* Delete old cipher and allocate default one */
3969 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3971 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3975 oldkey = channel->channel_key;
3976 channel->channel_key = newkey;
3978 /* Re-generate channel key */
3979 if (!silc_server_create_channel_key(server, channel, 0)) {
3980 /* We don't have new key, revert to old one */
3981 channel->channel_key = oldkey;
3985 /* Remove old channel key for good */
3986 silc_cipher_free(oldkey);
3988 /* Send the channel key. This sends it to our local clients and if
3989 we are normal server to our router as well. */
3990 silc_server_send_channel_key(server, NULL, channel,
3991 server->server_type == SILC_ROUTER ?
3992 FALSE : !server->standalone);
3996 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3997 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3998 /* HMAC to use protect the traffic */
3999 unsigned char hash[32];
4003 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4006 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4010 /* Delete old hmac and allocate the new one */
4011 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4013 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4017 silc_hmac_free(channel->hmac);
4018 channel->hmac = newhmac;
4020 /* Set the HMAC key out of current channel key. The client must do
4022 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4023 channel->key_len / 8, hash);
4024 silc_hmac_set_key(channel->hmac, hash,
4025 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4026 memset(hash, 0, sizeof(hash));
4029 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4030 /* Hmac mode is unset. Remove the hmac and revert back to
4033 unsigned char hash[32];
4034 hmac = channel->hmac_name;
4036 /* Delete old hmac and allocate default one */
4037 silc_hmac_free(channel->hmac);
4038 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4040 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4044 silc_hmac_free(channel->hmac);
4045 channel->hmac = newhmac;
4047 /* Set the HMAC key out of current channel key. The client must do
4049 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4050 channel->key_len / 8,
4052 silc_hmac_set_key(channel->hmac, hash,
4053 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4054 memset(hash, 0, sizeof(hash));
4058 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4059 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4060 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4061 /* Set the founder authentication */
4062 SilcAuthPayload auth;
4064 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4067 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4071 auth = silc_auth_payload_parse(tmp, tmp_len);
4073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4074 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4078 /* Save the public key */
4079 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4080 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4083 channel->founder_method = silc_auth_get_method(auth);
4085 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4086 tmp = silc_auth_get_data(auth, &tmp_len);
4087 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4088 channel->founder_passwd_len = tmp_len;
4090 /* Verify the payload before setting the mode */
4091 if (!silc_auth_verify(auth, channel->founder_method,
4092 channel->founder_key, 0, idata->hash,
4093 client->id, SILC_ID_CLIENT)) {
4094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4095 SILC_STATUS_ERR_AUTH_FAILED);
4100 silc_auth_payload_free(auth);
4104 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4105 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4106 if (channel->founder_key)
4107 silc_pkcs_public_key_free(channel->founder_key);
4108 if (channel->founder_passwd) {
4109 silc_free(channel->founder_passwd);
4110 channel->founder_passwd = NULL;
4116 /* Finally, set the mode */
4117 channel->mode = mode_mask;
4119 /* Send CMODE_CHANGE notify. */
4120 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4121 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4122 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4123 cidp->data, cidp->len,
4125 cipher, cipher ? strlen(cipher) : 0,
4126 hmac, hmac ? strlen(hmac) : 0,
4127 passphrase, passphrase ?
4128 strlen(passphrase) : 0);
4130 /* Set CMODE notify type to network */
4131 if (!server->standalone)
4132 silc_server_send_notify_cmode(server, server->router->connection,
4133 server->server_type == SILC_ROUTER ?
4134 TRUE : FALSE, channel,
4135 mode_mask, client->id, SILC_ID_CLIENT,
4136 cipher, hmac, passphrase);
4138 /* Send command reply to sender */
4139 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4140 SILC_STATUS_OK, 0, ident, 2,
4141 2, tmp_id, tmp_len2,
4143 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4144 packet->data, packet->len, FALSE);
4146 silc_buffer_free(packet);
4147 silc_buffer_free(cidp);
4150 silc_free(channel_id);
4151 silc_server_command_free(cmd);
4154 /* Server side of CUMODE command. Changes client's mode on a channel. */
4156 SILC_SERVER_CMD_FUNC(cumode)
4158 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4159 SilcServer server = cmd->server;
4160 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4161 SilcIDListData idata = (SilcIDListData)client;
4162 SilcChannelID *channel_id;
4163 SilcClientID *client_id;
4164 SilcChannelEntry channel;
4165 SilcClientEntry target_client;
4166 SilcChannelClientEntry chl;
4167 SilcBuffer packet, idp;
4168 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4169 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4171 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4173 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4175 /* Get Channel ID */
4176 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4179 SILC_STATUS_ERR_NO_CHANNEL_ID);
4182 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4184 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4185 SILC_STATUS_ERR_NO_CHANNEL_ID);
4189 /* Get channel entry */
4190 channel = silc_idlist_find_channel_by_id(server->local_list,
4193 channel = silc_idlist_find_channel_by_id(server->global_list,
4196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4197 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4202 /* Check whether sender is on the channel */
4203 if (!silc_server_client_on_channel(client, channel, &chl)) {
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4205 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4208 sender_mask = chl->mode;
4210 /* Get the target client's channel mode mask */
4211 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4214 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4217 SILC_GET32_MSB(target_mask, tmp_mask);
4219 /* Get target Client ID */
4220 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4223 SILC_STATUS_ERR_NO_CLIENT_ID);
4226 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4229 SILC_STATUS_ERR_NO_CLIENT_ID);
4233 /* Get target client's entry */
4234 target_client = silc_idlist_find_client_by_id(server->local_list,
4235 client_id, TRUE, NULL);
4236 if (!target_client) {
4237 target_client = silc_idlist_find_client_by_id(server->global_list,
4238 client_id, TRUE, NULL);
4241 if (target_client != client &&
4242 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4243 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4245 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4249 /* Check whether target client is on the channel */
4250 if (target_client != client) {
4251 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4262 /* If the target client is founder, no one else can change their mode
4264 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4266 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4270 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4271 if (target_client != client) {
4272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4273 SILC_STATUS_ERR_NOT_YOU);
4277 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4278 /* The client tries to claim the founder rights. */
4279 unsigned char *tmp_auth;
4280 SilcUInt32 tmp_auth_len, auth_len;
4283 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4284 !channel->founder_key || !idata->public_key ||
4285 !silc_pkcs_public_key_compare(channel->founder_key,
4286 idata->public_key)) {
4287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4288 SILC_STATUS_ERR_NOT_YOU);
4292 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4295 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4299 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4300 (void *)channel->founder_passwd : (void *)channel->founder_key);
4301 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4302 channel->founder_passwd_len : 0);
4304 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4305 channel->founder_method, auth, auth_len,
4306 idata->hash, client->id, SILC_ID_CLIENT)) {
4307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4308 SILC_STATUS_ERR_AUTH_FAILED);
4312 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4316 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4317 if (target_client == client) {
4318 /* Remove channel founder rights from itself */
4319 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4323 SILC_STATUS_ERR_NOT_YOU);
4329 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4330 /* Promote to operator */
4331 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4332 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4333 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4335 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4339 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4343 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4344 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4345 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4347 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4351 /* Demote to normal user */
4352 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4357 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4358 if (target_client != client) {
4359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4360 SILC_STATUS_ERR_NOT_YOU);
4364 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4365 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4369 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4370 if (target_client != client) {
4371 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4372 SILC_STATUS_ERR_NOT_YOU);
4376 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4382 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4383 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4385 /* Send notify to channel, notify only if mode was actually changed. */
4387 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4388 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4389 idp->data, idp->len,
4393 /* Set CUMODE notify type to network */
4394 if (!server->standalone)
4395 silc_server_send_notify_cumode(server, server->router->connection,
4396 server->server_type == SILC_ROUTER ?
4397 TRUE : FALSE, channel,
4398 target_mask, client->id,
4403 /* Send command reply to sender */
4404 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4405 SILC_STATUS_OK, 0, ident, 3,
4407 3, tmp_ch_id, tmp_ch_len,
4408 4, tmp_id, tmp_len);
4409 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4410 packet->data, packet->len, FALSE);
4412 silc_buffer_free(packet);
4413 silc_free(channel_id);
4414 silc_free(client_id);
4415 silc_buffer_free(idp);
4418 silc_server_command_free(cmd);
4421 /* Server side of KICK command. Kicks client out of channel. */
4423 SILC_SERVER_CMD_FUNC(kick)
4425 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4426 SilcServer server = cmd->server;
4427 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4428 SilcClientEntry target_client;
4429 SilcChannelID *channel_id;
4430 SilcClientID *client_id;
4431 SilcChannelEntry channel;
4432 SilcChannelClientEntry chl;
4434 SilcUInt32 tmp_len, target_idp_len;
4435 unsigned char *tmp, *comment, *target_idp;
4437 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4439 /* Get Channel ID */
4440 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4443 SILC_STATUS_ERR_NO_CHANNEL_ID);
4446 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4449 SILC_STATUS_ERR_NO_CHANNEL_ID);
4453 /* Get channel entry */
4454 channel = silc_idlist_find_channel_by_id(server->local_list,
4457 channel = silc_idlist_find_channel_by_id(server->local_list,
4460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4461 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4466 /* Check whether sender is on the channel */
4467 if (!silc_server_client_on_channel(client, channel, &chl)) {
4468 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4469 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4473 /* Check that the kicker is channel operator or channel founder */
4474 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4476 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4480 /* Get target Client ID */
4481 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4484 SILC_STATUS_ERR_NO_CLIENT_ID);
4487 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4490 SILC_STATUS_ERR_NO_CLIENT_ID);
4494 /* Get target client's entry */
4495 target_client = silc_idlist_find_client_by_id(server->local_list,
4496 client_id, TRUE, NULL);
4497 if (!target_client) {
4498 target_client = silc_idlist_find_client_by_id(server->global_list,
4499 client_id, TRUE, NULL);
4502 /* Check whether target client is on the channel */
4503 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4505 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4509 /* Check that the target client is not channel founder. Channel founder
4510 cannot be kicked from the channel. */
4511 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4513 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4519 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4523 /* Send command reply to sender */
4524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4527 /* Send KICKED notify to local clients on the channel */
4528 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4529 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4530 SILC_NOTIFY_TYPE_KICKED, 3,
4531 target_idp, target_idp_len,
4532 comment, comment ? strlen(comment) : 0,
4533 idp->data, idp->len);
4534 silc_buffer_free(idp);
4536 /* Remove the client from the channel. If the channel does not exist
4537 after removing the client then the client kicked itself off the channel
4538 and we don't have to send anything after that. */
4539 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4540 target_client, FALSE))
4543 /* Send KICKED notify to primary route */
4544 if (!server->standalone)
4545 silc_server_send_notify_kicked(server, server->router->connection,
4546 server->server_type == SILC_ROUTER ?
4547 TRUE : FALSE, channel,
4548 target_client->id, client->id, comment);
4550 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4551 /* Re-generate channel key */
4552 if (!silc_server_create_channel_key(server, channel, 0))
4555 /* Send the channel key to the channel. The key of course is not sent
4556 to the client who was kicked off the channel. */
4557 silc_server_send_channel_key(server, target_client->connection, channel,
4558 server->server_type == SILC_ROUTER ?
4559 FALSE : !server->standalone);
4563 silc_server_command_free(cmd);
4566 /* Server side of OPER command. Client uses this comand to obtain server
4567 operator privileges to this server/router. */
4569 SILC_SERVER_CMD_FUNC(oper)
4571 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4572 SilcServer server = cmd->server;
4573 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4574 unsigned char *username, *auth;
4576 SilcServerConfigAdmin *admin;
4577 SilcIDListData idata = (SilcIDListData)client;
4578 bool result = FALSE;
4579 SilcPublicKey cached_key;
4581 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4583 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4586 /* Get the username */
4587 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4590 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4594 /* Get the admin configuration */
4595 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4596 username, client->nickname);
4598 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4599 username, client->nickname);
4601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4602 SILC_STATUS_ERR_AUTH_FAILED);
4607 /* Get the authentication payload */
4608 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4610 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4611 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4615 /* Verify the authentication data. If both passphrase and public key
4616 is set then try both of them. */
4617 if (admin->passphrase)
4618 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4619 admin->passphrase, admin->passphrase_len,
4620 idata->hash, client->id, SILC_ID_CLIENT);
4621 if (!result && admin->publickeys) {
4622 cached_key = silc_server_get_public_key(server, admin->publickeys);
4625 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4626 cached_key, 0, idata->hash,
4627 client->id, SILC_ID_CLIENT);
4630 /* Authentication failed */
4631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4632 SILC_STATUS_ERR_AUTH_FAILED);
4636 /* Client is now server operator */
4637 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4639 /* Update statistics */
4640 if (client->connection)
4641 server->stat.my_server_ops++;
4642 if (server->server_type == SILC_ROUTER)
4643 server->stat.server_ops++;
4645 /* Send UMODE change to primary router */
4646 if (!server->standalone)
4647 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4648 client->id, client->mode);
4650 /* Send reply to the sender */
4651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4655 silc_server_command_free(cmd);
4658 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4660 QuitInternal q = (QuitInternal)context;
4661 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4663 /* If there is pending outgoing data for the client then purge it
4664 to the network before closing connection. */
4665 silc_server_packet_queue_purge(q->server, q->sock);
4667 /* Close the connection on our side */
4668 client->router = NULL;
4669 client->connection = NULL;
4670 q->sock->user_data = NULL;
4671 silc_server_close_connection(q->server, q->sock);
4676 /* Server side of DETACH command. Detached the client from the network
4677 by closing the connection but preserving the session. */
4679 SILC_SERVER_CMD_FUNC(detach)
4681 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4682 SilcServer server = cmd->server;
4683 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4686 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4689 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4691 /* Send the user mode notify to notify that client is detached */
4692 client->mode |= SILC_UMODE_DETACHED;
4693 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4694 if (!server->standalone)
4695 silc_server_send_notify_umode(server, server->router->connection,
4696 server->server_type == SILC_SERVER ?
4697 FALSE : TRUE, client->id, client->mode);
4699 q = silc_calloc(1, sizeof(*q));
4701 q->sock = cmd->sock;
4702 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4703 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4705 /* Send reply to the sender */
4706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4710 silc_server_command_free(cmd);
4713 /* Server side of SILCOPER command. Client uses this comand to obtain router
4714 operator privileges to this router. */
4716 SILC_SERVER_CMD_FUNC(silcoper)
4718 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4719 SilcServer server = cmd->server;
4720 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4721 unsigned char *username, *auth;
4723 SilcServerConfigAdmin *admin;
4724 SilcIDListData idata = (SilcIDListData)client;
4725 bool result = FALSE;
4726 SilcPublicKey cached_key;
4728 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4730 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4733 if (server->server_type != SILC_ROUTER) {
4734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4735 SILC_STATUS_ERR_AUTH_FAILED);
4739 /* Get the username */
4740 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4742 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4743 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4747 /* Get the admin configuration */
4748 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4749 username, client->nickname);
4751 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4752 username, client->nickname);
4754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4755 SILC_STATUS_ERR_AUTH_FAILED);
4760 /* Get the authentication payload */
4761 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4764 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4768 /* Verify the authentication data. If both passphrase and public key
4769 is set then try both of them. */
4770 if (admin->passphrase)
4771 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4772 admin->passphrase, admin->passphrase_len,
4773 idata->hash, client->id, SILC_ID_CLIENT);
4774 if (!result && admin->publickeys) {
4775 cached_key = silc_server_get_public_key(server, admin->publickeys);
4778 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4779 cached_key, 0, idata->hash,
4780 client->id, SILC_ID_CLIENT);
4783 /* Authentication failed */
4784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4785 SILC_STATUS_ERR_AUTH_FAILED);
4789 /* Client is now router operator */
4790 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4792 /* Update statistics */
4793 if (client->connection)
4794 server->stat.my_router_ops++;
4795 if (server->server_type == SILC_ROUTER)
4796 server->stat.router_ops++;
4798 /* Send UMODE change to primary router */
4799 if (!server->standalone)
4800 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4801 client->id, client->mode);
4803 /* Send reply to the sender */
4804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4808 silc_server_command_free(cmd);
4811 /* Server side of command BAN. This is used to manage the ban list of the
4812 channel. To add clients and remove clients from the ban list. */
4814 SILC_SERVER_CMD_FUNC(ban)
4816 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4817 SilcServer server = cmd->server;
4818 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4820 SilcChannelEntry channel;
4821 SilcChannelClientEntry chl;
4822 SilcChannelID *channel_id = NULL;
4823 unsigned char *id, *add, *del;
4824 SilcUInt32 id_len, tmp_len;
4825 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4827 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4830 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4832 /* Get Channel ID */
4833 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4835 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4838 SILC_STATUS_ERR_NO_CHANNEL_ID);
4843 /* Get channel entry. The server must know about the channel since the
4844 client is expected to be on the channel. */
4845 channel = silc_idlist_find_channel_by_id(server->local_list,
4848 channel = silc_idlist_find_channel_by_id(server->global_list,
4851 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4852 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4857 /* Check whether this client is on the channel */
4858 if (!silc_server_client_on_channel(client, channel, &chl)) {
4859 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4860 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4864 /* The client must be at least channel operator. */
4865 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4866 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4867 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4871 /* Get the new ban and add it to the ban list */
4872 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4874 if (!channel->ban_list)
4875 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4877 channel->ban_list = silc_realloc(channel->ban_list,
4878 sizeof(*channel->ban_list) *
4880 strlen(channel->ban_list) + 2));
4881 if (add[tmp_len - 1] == ',')
4882 add[tmp_len - 1] = '\0';
4884 strncat(channel->ban_list, add, tmp_len);
4885 strncat(channel->ban_list, ",", 1);
4888 /* Get the ban to be removed and remove it from the list */
4889 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4890 if (del && channel->ban_list) {
4891 char *start, *end, *n;
4893 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4894 silc_free(channel->ban_list);
4895 channel->ban_list = NULL;
4897 start = strstr(channel->ban_list, del);
4898 if (start && strlen(start) >= tmp_len) {
4899 end = start + tmp_len;
4900 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4901 strncat(n, channel->ban_list, start - channel->ban_list);
4902 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4904 silc_free(channel->ban_list);
4905 channel->ban_list = n;
4910 /* Send the BAN notify type to our primary router. */
4911 if (!server->standalone && (add || del))
4912 silc_server_send_notify_ban(server, server->router->connection,
4913 server->server_type == SILC_ROUTER ?
4914 TRUE : FALSE, channel, add, del);
4916 /* Send the reply back to the client */
4918 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4919 SILC_STATUS_OK, 0, ident, 2,
4921 3, channel->ban_list,
4923 strlen(channel->ban_list) -1 : 0);
4924 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4925 packet->data, packet->len, FALSE);
4927 silc_buffer_free(packet);
4930 silc_free(channel_id);
4931 silc_server_command_free(cmd);
4934 /* Server side command of LEAVE. Removes client from a channel. */
4936 SILC_SERVER_CMD_FUNC(leave)
4938 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4939 SilcServer server = cmd->server;
4940 SilcSocketConnection sock = cmd->sock;
4941 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4942 SilcChannelID *id = NULL;
4943 SilcChannelEntry channel;
4947 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4949 /* Get Channel ID */
4950 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4953 SILC_STATUS_ERR_NO_CHANNEL_ID);
4956 id = silc_id_payload_parse_id(tmp, len, NULL);
4958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4959 SILC_STATUS_ERR_NO_CHANNEL_ID);
4963 /* Get channel entry */
4964 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4966 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4968 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4969 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4974 /* Check whether this client is on the channel */
4975 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4977 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4981 /* Notify routers that they should remove this client from their list
4982 of clients on the channel. Send LEAVE notify type. */
4983 if (!server->standalone)
4984 silc_server_send_notify_leave(server, server->router->connection,
4985 server->server_type == SILC_ROUTER ?
4986 TRUE : FALSE, channel, id_entry->id);
4988 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4989 SILC_STATUS_OK, 2, tmp, len);
4991 /* Remove client from channel */
4992 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4994 /* If the channel does not exist anymore we won't send anything */
4997 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4998 /* Re-generate channel key */
4999 if (!silc_server_create_channel_key(server, channel, 0))
5002 /* Send the channel key */
5003 silc_server_send_channel_key(server, NULL, channel,
5004 server->server_type == SILC_ROUTER ?
5005 FALSE : !server->standalone);
5010 silc_server_command_free(cmd);
5013 /* Server side of command USERS. Resolves clients and their USERS currently
5014 joined on the requested channel. The list of Client ID's and their modes
5015 on the channel is sent back. */
5017 SILC_SERVER_CMD_FUNC(users)
5019 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5020 SilcServer server = cmd->server;
5021 SilcChannelEntry channel;
5022 SilcChannelID *id = NULL;
5023 SilcBuffer packet, idp;
5024 unsigned char *channel_id;
5025 SilcUInt32 channel_id_len;
5026 SilcBuffer client_id_list;
5027 SilcBuffer client_mode_list;
5028 unsigned char lc[4];
5029 SilcUInt32 list_count = 0;
5030 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5033 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5035 /* Get Channel ID */
5036 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5038 /* Get channel name */
5039 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5041 if (!channel_id && !channel_name) {
5042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5043 SILC_STATUS_ERR_NO_CHANNEL_ID);
5048 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5051 SILC_STATUS_ERR_NO_CHANNEL_ID);
5056 /* If we are server and we don't know about this channel we will send
5057 the command to our router. If we know about the channel then we also
5058 have the list of users already. */
5060 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5062 channel = silc_idlist_find_channel_by_name(server->local_list,
5063 channel_name, NULL);
5065 if (!channel || channel->disabled) {
5066 if (server->server_type != SILC_ROUTER && !server->standalone &&
5070 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5071 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5073 /* Send USERS command */
5074 silc_server_packet_send(server, server->router->connection,
5075 SILC_PACKET_COMMAND, cmd->packet->flags,
5076 tmpbuf->data, tmpbuf->len, TRUE);
5078 /* Reprocess this packet after received reply */
5079 silc_server_command_pending(server, SILC_COMMAND_USERS,
5080 silc_command_get_ident(cmd->payload),
5081 silc_server_command_users,
5082 silc_server_command_dup(cmd));
5083 cmd->pending = TRUE;
5084 silc_command_set_ident(cmd->payload, ident);
5085 silc_buffer_free(tmpbuf);
5090 /* Check the global list as well. */
5092 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5094 channel = silc_idlist_find_channel_by_name(server->global_list,
5095 channel_name, NULL);
5097 /* Channel really does not exist */
5098 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5099 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5104 /* If the channel is private or secret do not send anything, unless the
5105 user requesting this command is on the channel. */
5106 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5107 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5108 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5111 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5116 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5118 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5123 /* Get the users list */
5124 silc_server_get_users_on_channel(server, channel, &client_id_list,
5125 &client_mode_list, &list_count);
5128 SILC_PUT32_MSB(list_count, lc);
5131 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5132 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5133 SILC_STATUS_OK, 0, ident, 4,
5134 2, idp->data, idp->len,
5136 4, client_id_list->data,
5137 client_id_list->len,
5138 5, client_mode_list->data,
5139 client_mode_list->len);
5140 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5141 packet->data, packet->len, FALSE);
5143 silc_buffer_free(idp);
5144 silc_buffer_free(packet);
5145 silc_buffer_free(client_id_list);
5146 silc_buffer_free(client_mode_list);
5150 silc_server_command_free(cmd);
5153 /* Server side of command GETKEY. This fetches the client's public key
5154 from the server where to the client is connected. */
5156 SILC_SERVER_CMD_FUNC(getkey)
5158 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5159 SilcServer server = cmd->server;
5161 SilcClientEntry client;
5162 SilcServerEntry server_entry;
5163 SilcClientID *client_id = NULL;
5164 SilcServerID *server_id = NULL;
5165 SilcIDPayload idp = NULL;
5166 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5167 unsigned char *tmp, *pkdata;
5168 SilcUInt32 tmp_len, pklen;
5169 SilcBuffer pk = NULL;
5171 SilcPublicKey public_key;
5173 SILC_LOG_DEBUG(("Start"));
5175 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5178 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5181 idp = silc_id_payload_parse(tmp, tmp_len);
5183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5184 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5188 id_type = silc_id_payload_get_type(idp);
5189 if (id_type == SILC_ID_CLIENT) {
5190 client_id = silc_id_payload_get_id(idp);
5192 /* If the client is not found from local list there is no chance it
5193 would be locally connected client so send the command further. */
5194 client = silc_idlist_find_client_by_id(server->local_list,
5195 client_id, TRUE, NULL);
5197 client = silc_idlist_find_client_by_id(server->global_list,
5198 client_id, TRUE, NULL);
5200 if ((!client && !cmd->pending && !server->standalone) ||
5201 (client && !client->connection && !cmd->pending) ||
5202 (client && !client->data.public_key && !cmd->pending)) {
5204 SilcUInt16 old_ident;
5205 SilcSocketConnection dest_sock;
5207 dest_sock = silc_server_get_client_route(server, NULL, 0,
5208 client_id, NULL, NULL);
5212 old_ident = silc_command_get_ident(cmd->payload);
5213 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5214 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5216 silc_server_packet_send(server, dest_sock,
5217 SILC_PACKET_COMMAND, cmd->packet->flags,
5218 tmpbuf->data, tmpbuf->len, TRUE);
5220 /* Reprocess this packet after received reply from router */
5221 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5222 silc_command_get_ident(cmd->payload),
5223 silc_server_command_getkey,
5224 silc_server_command_dup(cmd));
5225 cmd->pending = TRUE;
5226 silc_command_set_ident(cmd->payload, old_ident);
5227 silc_buffer_free(tmpbuf);
5232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5233 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5237 /* The client is locally connected, just get the public key and
5238 send it back. If they key does not exist then do not send it,
5239 send just OK reply */
5240 public_key = client->data.public_key;
5245 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5246 pk = silc_buffer_alloc(4 + tmp_len);
5247 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5248 silc_buffer_format(pk,
5249 SILC_STR_UI_SHORT(tmp_len),
5250 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5251 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5257 } else if (id_type == SILC_ID_SERVER) {
5258 server_id = silc_id_payload_get_id(idp);
5260 /* If the server is not found from local list there is no chance it
5261 would be locally connected server so send the command further. */
5262 server_entry = silc_idlist_find_server_by_id(server->local_list,
5263 server_id, TRUE, NULL);
5265 server_entry = silc_idlist_find_server_by_id(server->global_list,
5266 server_id, TRUE, NULL);
5268 if (server_entry != server->id_entry &&
5269 ((!server_entry && !cmd->pending && !server->standalone) ||
5270 (server_entry && !server_entry->connection && !cmd->pending &&
5271 !server->standalone) ||
5272 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5273 !server->standalone))) {
5275 SilcUInt16 old_ident;
5277 old_ident = silc_command_get_ident(cmd->payload);
5278 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5279 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5281 silc_server_packet_send(server, server->router->connection,
5282 SILC_PACKET_COMMAND, cmd->packet->flags,
5283 tmpbuf->data, tmpbuf->len, TRUE);
5285 /* Reprocess this packet after received reply from router */
5286 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5287 silc_command_get_ident(cmd->payload),
5288 silc_server_command_getkey,
5289 silc_server_command_dup(cmd));
5290 cmd->pending = TRUE;
5291 silc_command_set_ident(cmd->payload, old_ident);
5292 silc_buffer_free(tmpbuf);
5296 if (!server_entry) {
5297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5298 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5302 /* If they key does not exist then do not send it, send just OK reply */
5303 public_key = (!server_entry->data.public_key ?
5304 (server_entry == server->id_entry ? server->public_key :
5305 NULL) : server_entry->data.public_key);
5310 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5311 pk = silc_buffer_alloc(4 + tmp_len);
5312 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5313 silc_buffer_format(pk,
5314 SILC_STR_UI_SHORT(tmp_len),
5315 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5316 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5326 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5327 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5328 SILC_STATUS_OK, 0, ident,
5332 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5333 packet->data, packet->len, FALSE);
5334 silc_buffer_free(packet);
5337 silc_buffer_free(pk);
5341 silc_id_payload_free(idp);
5342 silc_free(client_id);
5343 silc_free(server_id);
5344 silc_server_command_free(cmd);
5348 /* Private range commands, specific to this implementation */
5350 /* Server side command of CONNECT. Connects us to the specified remote
5351 server or router. */
5353 SILC_SERVER_CMD_FUNC(connect)
5355 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5356 SilcServer server = cmd->server;
5357 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5358 unsigned char *tmp, *host;
5360 SilcUInt32 port = SILC_PORT;
5362 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5364 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5367 /* Check whether client has the permissions. */
5368 if (client->mode == SILC_UMODE_NONE) {
5369 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5370 SILC_STATUS_ERR_NO_SERVER_PRIV);
5374 if (server->server_type == SILC_ROUTER &&
5375 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5377 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5381 /* Get the remote server */
5382 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5385 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5390 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5392 SILC_GET32_MSB(port, tmp);
5394 /* Create the connection. It is done with timeout and is async. */
5395 silc_server_create_connection(server, host, port);
5397 /* Send reply to the sender */
5398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5402 silc_server_command_free(cmd);
5405 /* Server side command of CLOSE. Closes connection to a specified server. */
5407 SILC_SERVER_CMD_FUNC(close)
5409 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5410 SilcServer server = cmd->server;
5411 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5412 SilcServerEntry server_entry;
5413 SilcSocketConnection sock;
5416 unsigned char *name;
5417 SilcUInt32 port = SILC_PORT;
5419 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5421 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5424 /* Check whether client has the permissions. */
5425 if (client->mode == SILC_UMODE_NONE) {
5426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5427 SILC_STATUS_ERR_NO_SERVER_PRIV);
5431 /* Get the remote server */
5432 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5435 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5440 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5442 SILC_GET32_MSB(port, tmp);
5444 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5445 name, port, FALSE, NULL);
5447 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5448 name, port, FALSE, NULL);
5449 if (!server_entry) {
5450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5451 SILC_STATUS_ERR_NO_SERVER_ID);
5455 /* Send reply to the sender */
5456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5459 /* Close the connection to the server */
5460 sock = (SilcSocketConnection)server_entry->connection;
5462 /* If we shutdown primary router connection manually then don't trigger
5463 any reconnect or backup router connections, by setting the router
5465 if (server->router == server_entry) {
5466 server->id_entry->router = NULL;
5467 server->router = NULL;
5468 server->standalone = TRUE;
5470 silc_server_free_sock_user_data(server, sock, NULL);
5471 silc_server_close_connection(server, sock);
5474 silc_server_command_free(cmd);
5477 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5478 active connections. */
5480 SILC_SERVER_CMD_FUNC(shutdown)
5482 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5483 SilcServer server = cmd->server;
5484 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5486 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5488 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5491 /* Check whether client has the permission. */
5492 if (client->mode == SILC_UMODE_NONE) {
5493 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5494 SILC_STATUS_ERR_NO_SERVER_PRIV);
5498 /* Send reply to the sender */
5499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5502 /* Then, gracefully, or not, bring the server down. */
5503 silc_server_stop(server);
5507 silc_server_command_free(cmd);