5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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,
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(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
83 /* Performs several checks to the command. It first checks whether this
84 command was called as pending command callback. If it was then it checks
85 whether error occurred in the command reply where the pending command
88 It also checks that the requested command includes correct amount
90 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
94 SILC_LOG_DEBUG(("Start")); \
96 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
97 silc_server_command_free(cmd); \
101 _argc = silc_argument_get_arg_num(cmd->args); \
103 silc_server_command_send_status_reply(cmd, command, \
104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
105 silc_server_command_free(cmd); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
111 silc_server_command_free(cmd); \
116 /* Returns TRUE if the connection is registered. Unregistered connections
117 usually cannot send commands hence the check. */
119 static int silc_server_is_registered(SilcServer server,
120 SilcSocketConnection sock,
121 SilcServerCommandContext cmd,
124 SilcIDListData idata = (SilcIDListData)sock->user_data;
125 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
128 silc_server_command_send_status_reply(cmd, command,
129 SILC_STATUS_ERR_NOT_REGISTERED);
130 silc_server_command_free(cmd);
134 /* Internal context to hold data when executed command with timeout. */
136 SilcServerCommandContext ctx;
137 SilcServerCommand *cmd;
138 } *SilcServerCommandTimeout;
140 /* Timeout callback to process commands with timeout for client. Client's
141 commands are always executed with timeout. */
143 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
145 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
146 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
148 /* Update access time */
149 client->last_command = time(NULL);
151 if (!(timeout->cmd->flags & SILC_CF_REG))
152 timeout->cmd->cb(timeout->ctx, NULL);
153 else if (silc_server_is_registered(timeout->ctx->server,
157 timeout->cmd->cb(timeout->ctx, NULL);
162 /* Processes received command packet. */
164 void silc_server_command_process(SilcServer server,
165 SilcSocketConnection sock,
166 SilcPacketContext *packet)
168 SilcServerCommandContext ctx;
169 SilcServerCommand *cmd;
172 /* Allocate command context. This must be free'd by the
173 command routine receiving it. */
174 ctx = silc_server_command_alloc();
175 ctx->server = server;
176 ctx->sock = silc_socket_dup(sock);
177 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
179 /* Parse the command payload in the packet */
180 ctx->payload = silc_command_payload_parse(packet->buffer);
182 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
183 silc_buffer_free(packet->buffer);
184 silc_packet_context_free(packet);
185 silc_socket_free(ctx->sock);
189 ctx->args = silc_command_get_args(ctx->payload);
191 /* Get the command */
192 command = silc_command_get(ctx->payload);
193 for (cmd = silc_command_list; cmd->cb; cmd++)
194 if (cmd->cmd == command)
198 silc_server_command_send_status_reply(ctx, command,
199 SILC_STATUS_ERR_UNKNOWN_COMMAND);
200 silc_server_command_free(ctx);
204 /* Execute client's commands always with timeout. Normally they are
205 executed with zero (0) timeout but if client is sending command more
206 frequently than once in 2 seconds, then the timeout may be 0 to 2
208 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
209 SilcClientEntry client = (SilcClientEntry)sock->user_data;
210 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
216 if (client->last_command && (time(NULL) - client->last_command) < 2) {
217 client->fast_command++;
220 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
221 client->fast_command--);
225 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
226 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
227 silc_schedule_task_add(server->schedule, sock->sock,
228 silc_server_command_process_timeout,
230 2 - (time(NULL) - client->last_command), 0,
232 SILC_TASK_PRI_NORMAL);
234 silc_schedule_task_add(server->schedule, sock->sock,
235 silc_server_command_process_timeout,
239 SILC_TASK_PRI_NORMAL);
243 /* Execute for server */
245 if (!(cmd->flags & SILC_CF_REG))
247 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
251 /* Allocate Command Context */
253 SilcServerCommandContext silc_server_command_alloc()
255 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
260 /* Free's the command context allocated before executing the command */
262 void silc_server_command_free(SilcServerCommandContext ctx)
265 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
267 if (ctx->users < 1) {
269 silc_command_payload_free(ctx->payload);
271 silc_packet_context_free(ctx->packet);
273 silc_socket_free(ctx->sock); /* Decrease reference counter */
278 /* Duplicate Command Context by adding reference counter. The context won't
279 be free'd untill it hits zero. */
281 SilcServerCommandContext
282 silc_server_command_dup(SilcServerCommandContext ctx)
285 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
290 /* Add new pending command to be executed when reply to a command has been
291 received. The `reply_cmd' is the command that will call the `callback'
292 with `context' when reply has been received. It can be SILC_COMMAND_NONE
293 to match any command with the `ident'. If `ident' is non-zero
294 the `callback' will be executed when received reply with command
295 identifier `ident'. */
297 void silc_server_command_pending(SilcServer server,
298 SilcCommand reply_cmd,
300 SilcServerPendingDestructor destructor,
301 SilcCommandCb callback,
304 SilcServerCommandPending *reply;
306 reply = silc_calloc(1, sizeof(*reply));
307 reply->reply_cmd = reply_cmd;
308 reply->ident = ident;
309 reply->context = context;
310 reply->callback = callback;
311 reply->destructor = destructor;
312 silc_dlist_add(server->pending_commands, reply);
315 /* Deletes pending command by reply command type. */
317 void silc_server_command_pending_del(SilcServer server,
318 SilcCommand reply_cmd,
321 SilcServerCommandPending *r;
323 silc_dlist_start(server->pending_commands);
324 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
325 if (r->reply_cmd == reply_cmd && r->ident == ident) {
326 silc_dlist_del(server->pending_commands, r);
332 /* Checks for pending commands and marks callbacks to be called from
333 the command reply function. Returns TRUE if there were pending command. */
335 SilcServerCommandPendingCallbacks
336 silc_server_command_pending_check(SilcServer server,
337 SilcServerCommandReplyContext ctx,
340 uint32 *callbacks_count)
342 SilcServerCommandPending *r;
343 SilcServerCommandPendingCallbacks callbacks = NULL;
346 silc_dlist_start(server->pending_commands);
347 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
348 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
349 && r->ident == ident) {
350 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
351 callbacks[i].context = r->context;
352 callbacks[i].callback = r->callback;
353 callbacks[i].destructor = r->destructor;
359 *callbacks_count = i;
363 /* Destructor function for pending callbacks. This is called when using
364 pending commands to free the context given for the pending command. */
366 static void silc_server_command_destructor(void *context)
368 silc_server_command_free((SilcServerCommandContext)context);
371 /* Sends simple status message as command reply packet */
374 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
376 SilcCommandStatus status)
380 SILC_LOG_DEBUG(("Sending command status %d", status));
383 silc_command_reply_payload_encode_va(command, status,
384 silc_command_get_ident(cmd->payload),
386 silc_server_packet_send(cmd->server, cmd->sock,
387 SILC_PACKET_COMMAND_REPLY, 0,
388 buffer->data, buffer->len, FALSE);
389 silc_buffer_free(buffer);
392 /* Sends command status reply with one extra argument. The argument
393 type must be sent as argument. */
396 silc_server_command_send_status_data(SilcServerCommandContext cmd,
398 SilcCommandStatus status,
405 SILC_LOG_DEBUG(("Sending command status %d", status));
408 silc_command_reply_payload_encode_va(command, status,
409 silc_command_get_ident(cmd->payload),
410 1, arg_type, arg, arg_len);
411 silc_server_packet_send(cmd->server, cmd->sock,
412 SILC_PACKET_COMMAND_REPLY, 0,
413 buffer->data, buffer->len, FALSE);
414 silc_buffer_free(buffer);
417 /* This function can be called to check whether in the command reply
418 an error occurred. This function has no effect if this is called
419 when the command function was not called as pending command callback.
420 This returns TRUE if error had occurred. */
423 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
424 SilcServerCommandReplyContext cmdr,
427 SilcCommandStatus status;
429 if (!cmd->pending || !cmdr)
432 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
433 if (status != SILC_STATUS_OK &&
434 status != SILC_STATUS_LIST_START &&
435 status != SILC_STATUS_LIST_ITEM &&
436 status != SILC_STATUS_LIST_END) {
437 /* Send the error message */
438 silc_server_command_send_status_reply(cmd, command, status);
445 /******************************************************************************
449 ******************************************************************************/
452 silc_server_command_whois_parse(SilcServerCommandContext cmd,
453 SilcClientID ***client_id,
454 uint32 *client_id_count,
462 uint32 argc = silc_argument_get_arg_num(cmd->args);
465 /* If client ID is in the command it must be used instead of nickname */
466 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
468 /* No ID, get the nickname@server string and parse it. */
469 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
471 silc_parse_userfqdn(tmp, nickname, server_name);
473 silc_server_command_send_status_reply(cmd, command,
474 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
478 /* Command includes ID, we must use that. Also check whether the command
479 has more than one ID set - take them all. */
481 *client_id = silc_calloc(1, sizeof(**client_id));
482 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
483 if ((*client_id)[0] == NULL) {
484 silc_free(*client_id);
487 *client_id_count = 1;
489 /* Take all ID's from the command packet */
491 for (k = 1, i = 1; i < argc; i++) {
492 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
494 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
495 (*client_id_count + 1));
496 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
497 if ((*client_id)[k] == NULL) {
498 /* Cleanup all and fail */
499 for (i = 0; i < *client_id_count; i++)
500 silc_free((*client_id)[i]);
501 silc_free(*client_id);
504 (*client_id_count)++;
511 /* Get the max count of reply messages allowed */
512 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
521 /* Resolve context used by both WHOIS and IDENTIFY commands */
523 SilcServerEntry router;
525 unsigned char **res_argv;
526 uint32 *res_argv_lens;
527 uint32 *res_argv_types;
529 } *SilcServerResolveContext;
532 silc_server_command_whois_check(SilcServerCommandContext cmd,
533 SilcClientEntry *clients,
534 uint32 clients_count)
536 SilcServer server = cmd->server;
537 SilcClientEntry entry;
538 SilcServerResolveContext resolve = NULL, r = NULL;
539 uint32 resolve_count = 0;
543 for (i = 0; i < clients_count; i++) {
546 if (!entry || (entry->nickname && entry->username && entry->userinfo) ||
547 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
551 /* We need to resolve this entry since it is not complete */
553 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
554 /* The entry is being resolved (and we are not the resolver) so attach
555 to the command reply and we're done with this one. */
556 silc_server_command_pending(server, SILC_COMMAND_NONE,
557 entry->resolve_cmd_ident,
558 silc_server_command_destructor,
559 silc_server_command_whois,
560 silc_server_command_dup(cmd));
563 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
564 /* We've resolved this and it still is not ready. We'll return
565 and are that this will be handled again after it is resolved. */
566 for (i = 0; i < resolve_count; i++) {
567 for (k = 0; k < r->res_argc; k++)
568 silc_free(r->res_argv[k]);
569 silc_free(r->res_argv);
570 silc_free(r->res_argv_lens);
571 silc_free(r->res_argv_types);
576 /* We'll resolve this client */
580 for (k = 0; k < resolve_count; k++) {
581 if (resolve[k].router == entry->router) {
588 resolve = silc_realloc(resolve, sizeof(*resolve) *
589 (resolve_count + 1));
590 r = &resolve[resolve_count];
591 memset(r, 0, sizeof(*r));
592 r->router = entry->router;
593 r->ident = ++server->cmd_ident;
597 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
599 r->res_argv_lens = silc_realloc(r->res_argv_lens,
600 sizeof(*r->res_argv_lens) *
602 r->res_argv_types = silc_realloc(r->res_argv_types,
603 sizeof(*r->res_argv_types) *
605 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
606 r->res_argv[r->res_argc] = silc_calloc(idp->len,
607 sizeof(**r->res_argv));
608 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
609 r->res_argv_lens[r->res_argc] = idp->len;
610 r->res_argv_types[r->res_argc] = r->res_argc + 3;
612 silc_buffer_free(idp);
614 entry->resolve_cmd_ident = r->ident;
615 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
616 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
621 /* Do the resolving */
622 for (i = 0; i < resolve_count; i++) {
627 /* Send WHOIS request. We send WHOIS since we're doing the requesting
628 now anyway so make it a good one. */
629 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
630 r->res_argc, r->res_argv,
634 silc_server_packet_send(server, r->router->connection,
635 SILC_PACKET_COMMAND, cmd->packet->flags,
636 res_cmd->data, res_cmd->len, FALSE);
638 /* Reprocess this packet after received reply */
639 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
641 silc_server_command_destructor,
642 silc_server_command_whois,
643 silc_server_command_dup(cmd));
646 silc_buffer_free(res_cmd);
647 for (k = 0; k < r->res_argc; k++)
648 silc_free(r->res_argv[k]);
649 silc_free(r->res_argv);
650 silc_free(r->res_argv_lens);
651 silc_free(r->res_argv_types);
660 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
661 SilcClientEntry *clients,
662 uint32 clients_count,
665 SilcServer server = cmd->server;
668 SilcBuffer packet, idp, channels;
669 SilcClientEntry entry;
670 SilcCommandStatus status;
671 uint16 ident = silc_command_get_ident(cmd->payload);
672 char nh[256], uh[256];
673 unsigned char idle[4], mode[4];
674 SilcSocketConnection hsock;
677 for (i = 0; i < clients_count; i++)
678 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
681 status = SILC_STATUS_OK;
683 status = SILC_STATUS_LIST_START;
685 for (i = 0, k = 0; i < clients_count; i++) {
688 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
689 if (clients_count == 1) {
690 if (entry->nickname) {
691 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
692 SILC_STATUS_ERR_NO_SUCH_NICK,
694 strlen(entry->nickname));
696 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
697 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
698 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
699 2, idp->data, idp->len);
700 silc_buffer_free(idp);
707 status = SILC_STATUS_LIST_ITEM;
709 if (clients_count > 1 && k == clients_count - 1)
710 status = SILC_STATUS_LIST_END;
712 if (count && k - 1 == count)
713 status = SILC_STATUS_LIST_END;
715 if (count && k - 1 > count)
718 /* Sanity check, however these should never fail. However, as
719 this sanity check has been added here they have failed. */
720 if (!entry->nickname || !entry->username || !entry->userinfo)
723 /* Send WHOIS reply */
724 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
725 tmp = silc_argument_get_first_arg(cmd->args, NULL);
727 memset(uh, 0, sizeof(uh));
728 memset(nh, 0, sizeof(nh));
729 memset(idle, 0, sizeof(idle));
731 strncat(nh, entry->nickname, strlen(entry->nickname));
732 if (!strchr(entry->nickname, '@')) {
734 if (entry->servername) {
735 strncat(nh, entry->servername, strlen(entry->servername));
737 len = entry->router ? strlen(entry->router->server_name) :
738 strlen(server->server_name);
739 strncat(nh, entry->router ? entry->router->server_name :
740 server->server_name, len);
744 strncat(uh, entry->username, strlen(entry->username));
745 if (!strchr(entry->username, '@')) {
747 hsock = (SilcSocketConnection)entry->connection;
748 len = strlen(hsock->hostname);
749 strncat(uh, hsock->hostname, len);
752 channels = silc_server_get_client_channel_list(server, entry);
754 SILC_PUT32_MSB(entry->mode, mode);
756 if (entry->connection) {
757 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
761 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
763 2, idp->data, idp->len,
767 strlen(entry->userinfo),
773 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
775 2, idp->data, idp->len,
779 strlen(entry->userinfo),
783 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
784 0, packet->data, packet->len, FALSE);
786 silc_buffer_free(packet);
787 silc_buffer_free(idp);
789 silc_buffer_free(channels);
796 silc_server_command_whois_process(SilcServerCommandContext cmd)
798 SilcServer server = cmd->server;
799 char *nick = NULL, *server_name = NULL;
801 SilcClientEntry *clients = NULL, entry;
802 SilcClientID **client_id = NULL;
803 uint32 client_id_count = 0, clients_count = 0;
805 bool check_global = FALSE;
807 /* Protocol dictates that we must always send the received WHOIS request
808 to our router if we are normal server, so let's do it now unless we
809 are standalone. We will not send any replies to the client until we
810 have received reply from the router. */
811 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
812 server->server_type == SILC_SERVER && !cmd->pending &&
813 !server->standalone) {
817 old_ident = silc_command_get_ident(cmd->payload);
818 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
819 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
821 /* Send WHOIS command to our router */
822 silc_server_packet_send(server, (SilcSocketConnection)
823 server->router->connection,
824 SILC_PACKET_COMMAND, cmd->packet->flags,
825 tmpbuf->data, tmpbuf->len, TRUE);
827 /* Reprocess this packet after received reply from router */
828 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
829 silc_command_get_ident(cmd->payload),
830 silc_server_command_destructor,
831 silc_server_command_whois,
832 silc_server_command_dup(cmd));
835 silc_command_set_ident(cmd->payload, old_ident);
837 silc_buffer_free(tmpbuf);
842 /* We are ready to process the command request. Let's search for the
843 requested client and send reply to the requesting client. */
845 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
847 else if (server->server_type == SILC_ROUTER)
850 /* Parse the whois request */
851 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
852 &nick, &server_name, &count,
856 /* Get all clients matching that ID or nickname from local list */
857 if (client_id_count) {
858 /* Check all Client ID's received in the command packet */
859 for (i = 0; i < client_id_count; i++) {
860 entry = silc_idlist_find_client_by_id(server->local_list,
861 client_id[i], TRUE, NULL);
862 if (!entry && check_global)
863 entry = silc_idlist_find_client_by_id(server->global_list,
864 client_id[i], TRUE, NULL);
866 clients = silc_realloc(clients, sizeof(*clients) *
867 (clients_count + 1));
868 clients[clients_count++] = entry;
872 if (!silc_idlist_get_clients_by_hash(server->local_list,
873 nick, server->md5hash,
874 &clients, &clients_count))
875 silc_idlist_get_clients_by_nickname(server->local_list,
877 &clients, &clients_count);
879 if (!silc_idlist_get_clients_by_hash(server->global_list,
880 nick, server->md5hash,
881 &clients, &clients_count))
882 silc_idlist_get_clients_by_nickname(server->global_list,
884 &clients, &clients_count);
889 /* Such client(s) really does not exist in the SILC network. */
890 if (!client_id_count) {
891 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
892 SILC_STATUS_ERR_NO_SUCH_NICK,
893 3, nick, strlen(nick));
895 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
896 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
897 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
898 2, idp->data, idp->len);
899 silc_buffer_free(idp);
904 /* Router always finds the client entry if it exists in the SILC network.
905 However, it might be incomplete entry and does not include all the
906 mandatory fields that WHOIS command reply requires. Check for these and
907 make query from the server who owns the client if some fields are
909 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
914 /* Send the command reply */
915 silc_server_command_whois_send_reply(cmd, clients, clients_count,
919 if (client_id_count) {
920 for (i = 0; i < client_id_count; i++)
921 silc_free(client_id[i]);
922 silc_free(client_id);
929 silc_free(server_name);
934 /* Server side of command WHOIS. Processes user's query and sends found
935 results as command replies back to the client. */
937 SILC_SERVER_CMD_FUNC(whois)
939 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
942 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
944 ret = silc_server_command_whois_process(cmd);
947 silc_server_command_free(cmd);
950 /******************************************************************************
954 ******************************************************************************/
957 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
965 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
968 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
972 /* Get the nickname@server string and parse it. */
973 silc_parse_userfqdn(tmp, nickname, server_name);
975 /* Get the max count of reply messages allowed */
976 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
986 silc_server_command_whowas_check(SilcServerCommandContext cmd,
987 SilcClientEntry *clients,
988 uint32 clients_count)
990 SilcServer server = cmd->server;
992 SilcClientEntry entry;
994 for (i = 0; i < clients_count; i++) {
997 if (!entry->nickname || !entry->username) {
1004 old_ident = silc_command_get_ident(cmd->payload);
1005 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1006 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1008 /* Send WHOWAS command */
1009 silc_server_packet_send(server, entry->router->connection,
1010 SILC_PACKET_COMMAND, cmd->packet->flags,
1011 tmpbuf->data, tmpbuf->len, TRUE);
1013 /* Reprocess this packet after received reply */
1014 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1015 silc_command_get_ident(cmd->payload),
1016 silc_server_command_destructor,
1017 silc_server_command_whowas,
1018 silc_server_command_dup(cmd));
1019 cmd->pending = TRUE;
1021 silc_command_set_ident(cmd->payload, old_ident);
1023 silc_buffer_free(tmpbuf);
1032 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1033 SilcClientEntry *clients,
1034 uint32 clients_count)
1036 SilcServer server = cmd->server;
1038 int i, count = 0, len;
1039 SilcBuffer packet, idp;
1040 SilcClientEntry entry = NULL;
1041 SilcCommandStatus status;
1042 uint16 ident = silc_command_get_ident(cmd->payload);
1044 char nh[256], uh[256];
1046 status = SILC_STATUS_OK;
1047 if (clients_count > 1)
1048 status = SILC_STATUS_LIST_START;
1050 for (i = 0; i < clients_count; i++) {
1053 /* We will take only clients that are not valid anymore. They are the
1054 ones that are not registered anymore but still have a ID. They
1055 have disconnected us, and thus valid for WHOWAS. */
1056 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED)
1058 if (entry->id == NULL)
1061 if (count && i - 1 == count)
1066 if (clients_count > 2)
1067 status = SILC_STATUS_LIST_ITEM;
1069 if (clients_count > 1 && i == clients_count - 1)
1070 status = SILC_STATUS_LIST_END;
1072 /* Sanity check, however these should never fail. However, as
1073 this sanity check has been added here they have failed. */
1074 if (!entry->nickname || !entry->username)
1077 /* Send WHOWAS reply */
1078 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1079 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1081 memset(uh, 0, sizeof(uh));
1082 memset(nh, 0, sizeof(nh));
1084 strncat(nh, entry->nickname, strlen(entry->nickname));
1085 if (!strchr(entry->nickname, '@')) {
1086 strncat(nh, "@", 1);
1087 if (entry->servername) {
1088 strncat(nh, entry->servername, strlen(entry->servername));
1090 len = entry->router ? strlen(entry->router->server_name) :
1091 strlen(server->server_name);
1092 strncat(nh, entry->router ? entry->router->server_name :
1093 server->server_name, len);
1097 strncat(uh, entry->username, strlen(entry->username));
1098 if (!strchr(entry->username, '@')) {
1099 strncat(uh, "@", 1);
1100 strcat(uh, "*private*");
1103 if (entry->userinfo)
1105 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1107 2, idp->data, idp->len,
1111 strlen(entry->userinfo));
1114 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1116 2, idp->data, idp->len,
1120 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1121 0, packet->data, packet->len, FALSE);
1123 silc_buffer_free(packet);
1124 silc_buffer_free(idp);
1127 if (found == FALSE && entry)
1128 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1129 SILC_STATUS_ERR_NO_SUCH_NICK,
1131 strlen(entry->nickname));
1135 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1137 SilcServer server = cmd->server;
1138 char *nick = NULL, *server_name = NULL;
1140 SilcClientEntry *clients = NULL;
1141 uint32 clients_count = 0;
1143 bool check_global = FALSE;
1145 /* Protocol dictates that we must always send the received WHOWAS request
1146 to our router if we are normal server, so let's do it now unless we
1147 are standalone. We will not send any replies to the client until we
1148 have received reply from the router. */
1149 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1150 server->server_type == SILC_SERVER && !cmd->pending &&
1151 !server->standalone) {
1155 old_ident = silc_command_get_ident(cmd->payload);
1156 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1157 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1159 /* Send WHOWAS command to our router */
1160 silc_server_packet_send(server, (SilcSocketConnection)
1161 server->router->connection,
1162 SILC_PACKET_COMMAND, cmd->packet->flags,
1163 tmpbuf->data, tmpbuf->len, TRUE);
1165 /* Reprocess this packet after received reply from router */
1166 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1167 silc_command_get_ident(cmd->payload),
1168 silc_server_command_destructor,
1169 silc_server_command_whowas,
1170 silc_server_command_dup(cmd));
1171 cmd->pending = TRUE;
1173 silc_command_set_ident(cmd->payload, old_ident);
1175 silc_buffer_free(tmpbuf);
1180 /* We are ready to process the command request. Let's search for the
1181 requested client and send reply to the requesting client. */
1183 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1184 check_global = TRUE;
1185 else if (server->server_type == SILC_ROUTER)
1186 check_global = TRUE;
1188 /* Parse the whowas request */
1189 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1192 /* Get all clients matching that nickname from local list */
1193 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1195 &clients, &clients_count))
1196 silc_idlist_get_clients_by_hash(server->local_list,
1197 nick, server->md5hash,
1198 &clients, &clients_count);
1200 /* Check global list as well */
1202 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1204 &clients, &clients_count))
1205 silc_idlist_get_clients_by_hash(server->global_list,
1206 nick, server->md5hash,
1207 &clients, &clients_count);
1211 /* Such a client really does not exist in the SILC network. */
1212 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1213 SILC_STATUS_ERR_NO_SUCH_NICK,
1214 3, nick, strlen(nick));
1218 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1219 !silc_server_command_whowas_check(cmd, clients, clients_count)) {
1224 /* Send the command reply to the client */
1225 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1230 silc_free(server_name);
1235 /* Server side of command WHOWAS. */
1237 SILC_SERVER_CMD_FUNC(whowas)
1239 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1242 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1244 ret = silc_server_command_whowas_process(cmd);
1247 silc_server_command_free(cmd);
1250 /******************************************************************************
1254 ******************************************************************************/
1257 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1258 SilcClientEntry **clients,
1259 uint32 *clients_count,
1260 SilcServerEntry **servers,
1261 uint32 *servers_count,
1262 SilcChannelEntry **channels,
1263 uint32 *channels_count,
1266 SilcServer server = cmd->server;
1269 uint32 argc = silc_argument_get_arg_num(cmd->args);
1271 bool check_global = FALSE;
1276 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1277 check_global = TRUE;
1278 else if (server->server_type == SILC_ROUTER)
1279 check_global = TRUE;
1281 /* If ID Payload is in the command it must be used instead of names */
1282 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1284 /* No ID, get the names. */
1286 /* Try to get nickname@server. */
1287 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1290 char *nick_server = NULL;
1292 silc_parse_userfqdn(tmp, &nick, &nick_server);
1294 if (!silc_idlist_get_clients_by_hash(server->local_list,
1295 nick, server->md5hash,
1296 clients, clients_count))
1297 silc_idlist_get_clients_by_nickname(server->local_list,
1299 clients, clients_count);
1301 if (!silc_idlist_get_clients_by_hash(server->global_list,
1302 nick, server->md5hash,
1303 clients, clients_count))
1304 silc_idlist_get_clients_by_nickname(server->global_list,
1306 clients, clients_count);
1310 silc_free(nick_server);
1313 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1314 SILC_STATUS_ERR_NO_SUCH_NICK,
1315 3, tmp, strlen(tmp));
1320 /* Try to get server name */
1321 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1323 entry = silc_idlist_find_server_by_name(server->local_list,
1325 if (!entry && check_global)
1326 entry = silc_idlist_find_server_by_name(server->local_list,
1329 *servers = silc_realloc(*servers, sizeof(**servers) *
1330 (*servers_count + 1));
1331 (*servers)[(*servers_count)++] = entry;
1335 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1336 SILC_STATUS_ERR_NO_SUCH_SERVER,
1337 3, tmp, strlen(tmp));
1342 /* Try to get channel name */
1343 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1345 entry = silc_idlist_find_channel_by_name(server->local_list,
1347 if (!entry && check_global)
1348 entry = silc_idlist_find_channel_by_name(server->local_list,
1351 *channels = silc_realloc(*channels, sizeof(**channels) *
1352 (*channels_count + 1));
1353 (*channels)[(*channels_count)++] = entry;
1357 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1358 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1359 3, tmp, strlen(tmp));
1364 if (!(*clients) && !(*servers) && !(*channels)) {
1365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1366 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1370 /* Command includes ID, we must use that. Also check whether the command
1371 has more than one ID set - take them all. */
1373 /* Take all ID's from the command packet */
1374 for (i = 0; i < argc; i++) {
1377 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1381 idp = silc_id_payload_parse_data(tmp, len);
1383 silc_free(*clients);
1384 silc_free(*servers);
1385 silc_free(*channels);
1386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1387 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1391 id = silc_id_payload_get_id(idp);
1393 switch (silc_id_payload_get_type(idp)) {
1395 case SILC_ID_CLIENT:
1396 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1398 if (!entry && check_global)
1399 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1402 *clients = silc_realloc(*clients, sizeof(**clients) *
1403 (*clients_count + 1));
1404 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1406 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1407 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1414 case SILC_ID_SERVER:
1415 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1417 if (!entry && check_global)
1418 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1421 *servers = silc_realloc(*servers, sizeof(**servers) *
1422 (*servers_count + 1));
1423 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1425 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1426 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1432 case SILC_ID_CHANNEL:
1433 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1435 if (!entry && check_global)
1436 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1439 *channels = silc_realloc(*channels, sizeof(**channels) *
1440 (*channels_count + 1));
1441 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1443 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1444 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1456 silc_free(*clients);
1457 silc_free(*servers);
1458 silc_free(*channels);
1462 /* Get the max count of reply messages allowed */
1463 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1472 /* Checks that all mandatory fields in client entry are present. If not
1473 then send WHOIS request to the server who owns the client. We use
1474 WHOIS because we want to get as much information as possible at once. */
1477 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1478 SilcClientEntry *clients,
1479 uint32 clients_count)
1481 SilcServer server = cmd->server;
1482 SilcClientEntry entry;
1483 SilcServerResolveContext resolve = NULL, r = NULL;
1484 uint32 resolve_count = 0;
1488 for (i = 0; i < clients_count; i++) {
1491 if (!entry || entry->nickname ||
1492 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
1496 /* We need to resolve this entry since it is not complete */
1498 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1499 /* The entry is being resolved (and we are not the resolver) so attach
1500 to the command reply and we're done with this one. */
1501 silc_server_command_pending(server, SILC_COMMAND_NONE,
1502 entry->resolve_cmd_ident,
1503 silc_server_command_destructor,
1504 silc_server_command_identify,
1505 silc_server_command_dup(cmd));
1508 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1509 /* We've resolved this and it still is not ready. We'll return
1510 and are that this will be handled again after it is resolved. */
1511 for (i = 0; i < resolve_count; i++) {
1512 for (k = 0; k < r->res_argc; k++)
1513 silc_free(r->res_argv[k]);
1514 silc_free(r->res_argv);
1515 silc_free(r->res_argv_lens);
1516 silc_free(r->res_argv_types);
1521 /* We'll resolve this client */
1525 for (k = 0; k < resolve_count; k++) {
1526 if (resolve[k].router == entry->router) {
1533 resolve = silc_realloc(resolve, sizeof(*resolve) *
1534 (resolve_count + 1));
1535 r = &resolve[resolve_count];
1536 memset(r, 0, sizeof(*r));
1537 r->router = entry->router;
1538 r->ident = ++server->cmd_ident;
1542 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1544 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1545 sizeof(*r->res_argv_lens) *
1547 r->res_argv_types = silc_realloc(r->res_argv_types,
1548 sizeof(*r->res_argv_types) *
1550 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1551 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1552 sizeof(**r->res_argv));
1553 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1554 r->res_argv_lens[r->res_argc] = idp->len;
1555 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1557 silc_buffer_free(idp);
1559 entry->resolve_cmd_ident = r->ident;
1560 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1561 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1566 /* Do the resolving */
1567 for (i = 0; i < resolve_count; i++) {
1572 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1573 now anyway so make it a good one. */
1574 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1575 r->res_argc, r->res_argv,
1579 silc_server_packet_send(server, r->router->connection,
1580 SILC_PACKET_COMMAND, cmd->packet->flags,
1581 res_cmd->data, res_cmd->len, FALSE);
1583 /* Reprocess this packet after received reply */
1584 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1586 silc_server_command_destructor,
1587 silc_server_command_identify,
1588 silc_server_command_dup(cmd));
1589 cmd->pending = TRUE;
1591 silc_buffer_free(res_cmd);
1592 for (k = 0; k < r->res_argc; k++)
1593 silc_free(r->res_argv[k]);
1594 silc_free(r->res_argv);
1595 silc_free(r->res_argv_lens);
1596 silc_free(r->res_argv_types);
1605 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1606 SilcClientEntry *clients,
1607 uint32 clients_count,
1608 SilcServerEntry *servers,
1609 uint32 servers_count,
1610 SilcChannelEntry *channels,
1611 uint32 channels_count,
1614 SilcServer server = cmd->server;
1616 SilcBuffer packet, idp;
1617 SilcCommandStatus status;
1618 uint16 ident = silc_command_get_ident(cmd->payload);
1619 char nh[256], uh[256];
1620 SilcSocketConnection hsock;
1622 status = SILC_STATUS_OK;
1625 SilcClientEntry entry;
1628 for (i = 0; i < clients_count; i++)
1629 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1633 status = SILC_STATUS_LIST_START;
1635 for (i = 0, k = 0; i < clients_count; i++) {
1638 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1639 if (clients_count == 1) {
1640 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1641 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1642 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1643 2, idp->data, idp->len);
1644 silc_buffer_free(idp);
1650 status = SILC_STATUS_LIST_ITEM;
1651 if (clients_count > 1 && k == clients_count - 1
1652 && !servers_count && !channels_count)
1653 status = SILC_STATUS_LIST_END;
1654 if (count && k - 1 == count)
1655 status = SILC_STATUS_LIST_END;
1656 if (count && k - 1 > count)
1659 /* Send IDENTIFY reply */
1660 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1662 memset(uh, 0, sizeof(uh));
1663 memset(nh, 0, sizeof(nh));
1665 strncat(nh, entry->nickname, strlen(entry->nickname));
1666 if (!strchr(entry->nickname, '@')) {
1667 strncat(nh, "@", 1);
1668 if (entry->servername) {
1669 strncat(nh, entry->servername, strlen(entry->servername));
1671 len = entry->router ? strlen(entry->router->server_name) :
1672 strlen(server->server_name);
1673 strncat(nh, entry->router ? entry->router->server_name :
1674 server->server_name, len);
1678 if (!entry->username) {
1679 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1681 2, idp->data, idp->len,
1684 strncat(uh, entry->username, strlen(entry->username));
1685 if (!strchr(entry->username, '@')) {
1686 strncat(uh, "@", 1);
1687 hsock = (SilcSocketConnection)entry->connection;
1688 len = strlen(hsock->hostname);
1689 strncat(uh, hsock->hostname, len);
1692 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1694 2, idp->data, idp->len,
1699 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1700 0, packet->data, packet->len, FALSE);
1702 silc_buffer_free(packet);
1703 silc_buffer_free(idp);
1709 status = (status == SILC_STATUS_LIST_ITEM ?
1710 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1713 SilcServerEntry entry;
1715 if (status == SILC_STATUS_OK && servers_count > 1)
1716 status = SILC_STATUS_LIST_START;
1718 for (i = 0, k = 0; i < servers_count; i++) {
1722 status = SILC_STATUS_LIST_ITEM;
1723 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1724 status = SILC_STATUS_LIST_END;
1725 if (count && k - 1 == count)
1726 status = SILC_STATUS_LIST_END;
1727 if (count && k - 1 > count)
1730 /* Send IDENTIFY reply */
1731 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1732 if (entry->server_name) {
1734 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1736 2, idp->data, idp->len,
1737 3, entry->server_name,
1738 strlen(entry->server_name));
1740 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1742 2, idp->data, idp->len);
1745 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1746 0, packet->data, packet->len, FALSE);
1748 silc_buffer_free(packet);
1749 silc_buffer_free(idp);
1755 status = (status == SILC_STATUS_LIST_ITEM ?
1756 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1759 SilcChannelEntry entry;
1761 if (status == SILC_STATUS_OK && channels_count > 1)
1762 status = SILC_STATUS_LIST_START;
1764 for (i = 0, k = 0; i < channels_count; i++) {
1765 entry = channels[i];
1768 status = SILC_STATUS_LIST_ITEM;
1769 if (channels_count > 1 && k == channels_count - 1)
1770 status = SILC_STATUS_LIST_END;
1771 if (count && k - 1 == count)
1772 status = SILC_STATUS_LIST_END;
1773 if (count && k - 1 > count)
1776 /* Send IDENTIFY reply */
1777 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1778 if (entry->channel_name) {
1780 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1782 2, idp->data, idp->len,
1783 3, entry->channel_name,
1784 strlen(entry->channel_name));
1786 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1788 2, idp->data, idp->len);
1791 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1792 0, packet->data, packet->len, FALSE);
1794 silc_buffer_free(packet);
1795 silc_buffer_free(idp);
1803 silc_server_command_identify_process(SilcServerCommandContext cmd)
1805 SilcServer server = cmd->server;
1808 SilcClientEntry *clients = NULL;
1809 SilcServerEntry *servers = NULL;
1810 SilcChannelEntry *channels = NULL;
1811 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1813 /* Protocol dictates that we must always send the received IDENTIFY request
1814 to our router if we are normal server, so let's do it now unless we
1815 are standalone. We will not send any replies to the client until we
1816 have received reply from the router. */
1817 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1818 server->server_type == SILC_SERVER && !cmd->pending &&
1819 !server->standalone) {
1823 old_ident = silc_command_get_ident(cmd->payload);
1824 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1825 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1827 /* Send IDENTIFY command to our router */
1828 silc_server_packet_send(server, (SilcSocketConnection)
1829 server->router->connection,
1830 SILC_PACKET_COMMAND, cmd->packet->flags,
1831 tmpbuf->data, tmpbuf->len, TRUE);
1833 /* Reprocess this packet after received reply from router */
1834 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1835 silc_command_get_ident(cmd->payload),
1836 silc_server_command_destructor,
1837 silc_server_command_identify,
1838 silc_server_command_dup(cmd));
1839 cmd->pending = TRUE;
1841 silc_command_set_ident(cmd->payload, old_ident);
1843 silc_buffer_free(tmpbuf);
1848 /* We are ready to process the command request. Let's search for the
1849 requested client and send reply to the requesting client. */
1851 /* Parse the IDENTIFY request */
1852 if (!silc_server_command_identify_parse(cmd,
1853 &clients, &clients_count,
1854 &servers, &servers_count,
1855 &channels, &channels_count,
1859 /* Check that all mandatory fields are present and request those data
1860 from the server who owns the client if necessary. */
1861 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1867 /* Send the command reply to the client */
1868 silc_server_command_identify_send_reply(cmd,
1869 clients, clients_count,
1870 servers, servers_count,
1871 channels, channels_count,
1877 silc_free(channels);
1882 SILC_SERVER_CMD_FUNC(identify)
1884 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1887 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1889 ret = silc_server_command_identify_process(cmd);
1892 silc_server_command_free(cmd);
1895 /* Checks string for bad characters and returns TRUE if they are found. */
1897 static int silc_server_command_bad_chars(char *nick)
1899 if (strchr(nick, '\\')) return TRUE;
1900 if (strchr(nick, '\"')) return TRUE;
1901 if (strchr(nick, '´')) return TRUE;
1902 if (strchr(nick, '`')) return TRUE;
1903 if (strchr(nick, '\'')) return TRUE;
1904 if (strchr(nick, '*')) return TRUE;
1905 if (strchr(nick, '/')) return TRUE;
1906 if (strchr(nick, '@')) return TRUE;
1911 /* Server side of command NICK. Sets nickname for user. Setting
1912 nickname causes generation of a new client ID for the client. The
1913 new client ID is sent to the client after changing the nickname. */
1915 SILC_SERVER_CMD_FUNC(nick)
1917 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1918 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1919 SilcServer server = cmd->server;
1920 SilcBuffer packet, nidp, oidp;
1921 SilcClientID *new_id;
1923 uint16 ident = silc_command_get_ident(cmd->payload);
1926 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1929 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1931 /* Check nickname */
1932 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1933 if (silc_server_command_bad_chars(nick) == TRUE) {
1934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1935 SILC_STATUS_ERR_BAD_NICKNAME);
1939 if (strlen(nick) > 128)
1942 /* Create new Client ID */
1943 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1945 cmd->server->md5hash, nick,
1948 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
1951 /* Send notify about nickname change to our router. We send the new
1952 ID and ask to replace it with the old one. If we are router the
1953 packet is broadcasted. Send NICK_CHANGE notify. */
1954 if (!server->standalone)
1955 silc_server_send_notify_nick_change(server, server->router->connection,
1956 server->server_type == SILC_SERVER ?
1957 FALSE : TRUE, client->id,
1960 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1962 /* Remove old cache entry */
1963 silc_idcache_del_by_context(server->local_list->clients, client);
1966 silc_free(client->id);
1968 /* Save the nickname as this client is our local client */
1969 silc_free(client->nickname);
1971 client->nickname = strdup(nick);
1972 client->id = new_id;
1974 /* Update client cache */
1975 silc_idcache_add(server->local_list->clients, client->nickname,
1976 client->id, (void *)client, FALSE);
1978 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1980 /* Send NICK_CHANGE notify to the client's channels */
1981 silc_server_send_notify_on_channels(server, NULL, client,
1982 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1983 oidp->data, oidp->len,
1984 nidp->data, nidp->len);
1986 /* Send the new Client ID as reply command back to client */
1987 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1988 SILC_STATUS_OK, ident, 1,
1989 2, nidp->data, nidp->len);
1990 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1991 0, packet->data, packet->len, FALSE);
1993 silc_buffer_free(packet);
1994 silc_buffer_free(nidp);
1995 silc_buffer_free(oidp);
1998 silc_server_command_free(cmd);
2001 /* Sends the LIST command reply */
2004 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2005 SilcChannelEntry *lch,
2007 SilcChannelEntry *gch,
2011 SilcBuffer packet, idp;
2012 SilcChannelEntry entry;
2013 SilcCommandStatus status;
2014 uint16 ident = silc_command_get_ident(cmd->payload);
2016 unsigned char usercount[4];
2019 for (i = 0; i < lch_count; i++)
2020 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2022 for (i = 0; i < gch_count; i++)
2023 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2026 status = SILC_STATUS_OK;
2027 if ((lch_count + gch_count) > 1)
2028 status = SILC_STATUS_LIST_START;
2031 for (i = 0; i < lch_count; i++) {
2038 status = SILC_STATUS_LIST_ITEM;
2040 if (i == lch_count - 1 && gch_count)
2042 if (lch_count > 1 && i == lch_count - 1)
2043 status = SILC_STATUS_LIST_END;
2045 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2047 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2048 topic = "*private*";
2049 memset(usercount, 0, sizeof(usercount));
2051 topic = entry->topic;
2052 users = silc_hash_table_count(entry->user_list);
2053 SILC_PUT32_MSB(users, usercount);
2056 /* Send the reply */
2059 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2061 2, idp->data, idp->len,
2062 3, entry->channel_name,
2063 strlen(entry->channel_name),
2064 4, topic, strlen(topic),
2068 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2070 2, idp->data, idp->len,
2071 3, entry->channel_name,
2072 strlen(entry->channel_name),
2074 silc_server_packet_send(cmd->server, cmd->sock,
2075 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2076 packet->len, FALSE);
2077 silc_buffer_free(packet);
2078 silc_buffer_free(idp);
2081 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
2084 for (i = 0; i < gch_count; i++) {
2091 status = SILC_STATUS_LIST_ITEM;
2093 if (gch_count > 1 && i == lch_count - 1)
2094 status = SILC_STATUS_LIST_END;
2096 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2098 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2099 topic = "*private*";
2100 memset(usercount, 0, sizeof(usercount));
2102 topic = entry->topic;
2103 users = silc_hash_table_count(entry->user_list);
2104 SILC_PUT32_MSB(users, usercount);
2107 /* Send the reply */
2110 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2112 2, idp->data, idp->len,
2113 3, entry->channel_name,
2114 strlen(entry->channel_name),
2115 4, topic, strlen(topic),
2119 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2121 2, idp->data, idp->len,
2122 3, entry->channel_name,
2123 strlen(entry->channel_name),
2125 silc_server_packet_send(cmd->server, cmd->sock,
2126 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2127 packet->len, FALSE);
2128 silc_buffer_free(packet);
2129 silc_buffer_free(idp);
2133 /* Server side of LIST command. This lists the channel of the requested
2134 server. Secret channels are not listed. */
2136 SILC_SERVER_CMD_FUNC(list)
2138 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2139 SilcServer server = cmd->server;
2140 SilcChannelID *channel_id = NULL;
2143 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2144 uint32 lch_count = 0, gch_count = 0;
2146 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 2);
2148 /* Get Channel ID */
2149 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2151 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2153 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2154 SILC_STATUS_ERR_NO_CHANNEL_ID);
2159 /* Get the channels from local list */
2160 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2163 /* Get the channels from global list if we are router */
2164 if (server->server_type == SILC_ROUTER)
2165 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2168 /* Send the reply */
2169 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2170 gchannels, gch_count);
2173 silc_server_command_free(cmd);
2176 /* Server side of TOPIC command. Sets topic for channel and/or returns
2177 current topic to client. */
2179 SILC_SERVER_CMD_FUNC(topic)
2181 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2182 SilcServer server = cmd->server;
2183 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2184 SilcChannelID *channel_id;
2185 SilcChannelEntry channel;
2186 SilcChannelClientEntry chl;
2187 SilcBuffer packet, idp;
2189 uint32 argc, tmp_len;
2190 uint16 ident = silc_command_get_ident(cmd->payload);
2192 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2194 argc = silc_argument_get_arg_num(cmd->args);
2196 /* Get Channel ID */
2197 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2200 SILC_STATUS_ERR_NO_CHANNEL_ID);
2203 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2206 SILC_STATUS_ERR_NO_CHANNEL_ID);
2210 /* Check whether the channel exists */
2211 channel = silc_idlist_find_channel_by_id(server->local_list,
2214 channel = silc_idlist_find_channel_by_id(server->global_list,
2217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2218 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2225 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2228 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2232 if (strlen(tmp) > 256) {
2233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2234 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2238 /* See whether the client is on channel and has rights to change topic */
2239 if (!silc_hash_table_find(channel->user_list, client, NULL,
2241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2242 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2246 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2247 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2248 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2249 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2254 /* Set the topic for channel */
2256 silc_free(channel->topic);
2257 channel->topic = strdup(tmp);
2259 /* Send TOPIC_SET notify type to the network */
2260 if (!server->standalone)
2261 silc_server_send_notify_topic_set(server, server->router->connection,
2262 server->server_type == SILC_ROUTER ?
2263 TRUE : FALSE, channel, client->id,
2266 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2268 /* Send notify about topic change to all clients on the channel */
2269 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2270 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2271 idp->data, idp->len,
2272 channel->topic, strlen(channel->topic));
2273 silc_buffer_free(idp);
2276 /* Send the topic to client as reply packet */
2277 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2279 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2280 SILC_STATUS_OK, ident, 2,
2281 2, idp->data, idp->len,
2283 strlen(channel->topic));
2285 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2286 SILC_STATUS_OK, ident, 1,
2287 2, idp->data, idp->len);
2288 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2289 0, packet->data, packet->len, FALSE);
2291 silc_buffer_free(packet);
2292 silc_buffer_free(idp);
2293 silc_free(channel_id);
2296 silc_server_command_free(cmd);
2299 /* Server side of INVITE command. Invites some client to join some channel.
2300 This command is also used to manage the invite list of the channel. */
2302 SILC_SERVER_CMD_FUNC(invite)
2304 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2305 SilcServer server = cmd->server;
2306 SilcSocketConnection sock = cmd->sock, dest_sock;
2307 SilcChannelClientEntry chl;
2308 SilcClientEntry sender, dest;
2309 SilcClientID *dest_id = NULL;
2310 SilcChannelEntry channel;
2311 SilcChannelID *channel_id = NULL;
2312 SilcIDListData idata;
2313 SilcBuffer idp, idp2, packet;
2314 unsigned char *tmp, *add, *del;
2316 uint16 ident = silc_command_get_ident(cmd->payload);
2318 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2320 /* Get Channel ID */
2321 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2324 SILC_STATUS_ERR_NO_CHANNEL_ID);
2327 channel_id = silc_id_payload_parse_id(tmp, len);
2329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2330 SILC_STATUS_ERR_NO_CHANNEL_ID);
2334 /* Get the channel entry */
2335 channel = silc_idlist_find_channel_by_id(server->local_list,
2338 channel = silc_idlist_find_channel_by_id(server->global_list,
2341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2342 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2347 /* Check whether the sender of this command is on the channel. */
2348 sender = (SilcClientEntry)sock->user_data;
2349 if (!silc_server_client_on_channel(sender, channel)) {
2350 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2351 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2355 /* Check whether the channel is invite-only channel. If yes then the
2356 sender of this command must be at least channel operator. */
2357 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2358 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2359 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2361 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2366 /* Get destination client ID */
2367 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2371 dest_id = silc_id_payload_parse_id(tmp, len);
2373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2374 SILC_STATUS_ERR_NO_CLIENT_ID);
2378 /* Get the client entry */
2379 dest = silc_server_get_client_resolve(server, dest_id);
2381 if (server->server_type == SILC_ROUTER) {
2382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2383 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2387 /* The client info is being resolved. Reprocess this packet after
2388 receiving the reply to the query. */
2389 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2391 silc_server_command_destructor,
2392 silc_server_command_invite,
2393 silc_server_command_dup(cmd));
2394 cmd->pending = TRUE;
2395 silc_free(channel_id);
2400 /* Check whether the requested client is already on the channel. */
2401 if (silc_server_client_on_channel(dest, channel)) {
2402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2403 SILC_STATUS_ERR_USER_ON_CHANNEL);
2407 /* Get route to the client */
2408 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2411 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2415 memset(invite, 0, sizeof(invite));
2416 strncat(invite, dest->nickname, strlen(dest->nickname));
2417 strncat(invite, "!", 1);
2418 strncat(invite, dest->username, strlen(dest->username));
2419 if (!strchr(dest->username, '@')) {
2420 strncat(invite, "@", 1);
2421 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2424 len = strlen(invite);
2425 if (!channel->invite_list)
2426 channel->invite_list = silc_calloc(len + 2,
2427 sizeof(*channel->invite_list));
2429 channel->invite_list = silc_realloc(channel->invite_list,
2430 sizeof(*channel->invite_list) *
2432 strlen(channel->invite_list) + 2));
2433 strncat(channel->invite_list, invite, len);
2434 strncat(channel->invite_list, ",", 1);
2436 /* Send notify to the client that is invited to the channel */
2437 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2438 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2439 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2441 SILC_NOTIFY_TYPE_INVITE, 3,
2442 idp->data, idp->len,
2443 channel->channel_name,
2444 strlen(channel->channel_name),
2445 idp2->data, idp2->len);
2446 silc_buffer_free(idp);
2447 silc_buffer_free(idp2);
2450 /* Add the client to the invite list of the channel */
2451 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2453 if (!channel->invite_list)
2454 channel->invite_list = silc_calloc(len + 2,
2455 sizeof(*channel->invite_list));
2457 channel->invite_list = silc_realloc(channel->invite_list,
2458 sizeof(*channel->invite_list) *
2460 strlen(channel->invite_list) + 2));
2461 if (add[len - 1] == ',')
2462 add[len - 1] = '\0';
2464 strncat(channel->invite_list, add, len);
2465 strncat(channel->invite_list, ",", 1);
2468 /* Get the invite to be removed and remove it from the list */
2469 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2470 if (del && channel->invite_list) {
2471 char *start, *end, *n;
2473 if (!strncmp(channel->invite_list, del,
2474 strlen(channel->invite_list) - 1)) {
2475 silc_free(channel->invite_list);
2476 channel->invite_list = NULL;
2478 start = strstr(channel->invite_list, del);
2479 if (start && strlen(start) >= len) {
2481 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2482 strncat(n, channel->invite_list, start - channel->invite_list);
2483 strncat(n, end + 1, ((channel->invite_list +
2484 strlen(channel->invite_list)) - end) - 1);
2485 silc_free(channel->invite_list);
2486 channel->invite_list = n;
2491 /* Send notify to the primary router */
2492 if (!server->standalone)
2493 silc_server_send_notify_invite(server, server->router->connection,
2494 server->server_type == SILC_ROUTER ?
2495 TRUE : FALSE, channel,
2496 sender->id, add, del);
2498 /* Send command reply */
2499 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2503 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2504 SILC_STATUS_OK, ident, 2,
2506 3, channel->invite_list,
2507 channel->invite_list ?
2508 strlen(channel->invite_list) : 0);
2511 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2512 SILC_STATUS_OK, ident, 1,
2514 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2515 packet->data, packet->len, FALSE);
2516 silc_buffer_free(packet);
2522 silc_free(channel_id);
2523 silc_server_command_free(cmd);
2528 SilcSocketConnection sock;
2532 /* Quits connection to client. This gets called if client won't
2533 close the connection even when it has issued QUIT command. */
2535 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2537 QuitInternal q = (QuitInternal)context;
2539 /* Free all client specific data, such as client entry and entires
2540 on channels this client may be on. */
2541 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2543 q->sock->user_data = NULL;
2545 /* Close the connection on our side */
2546 silc_server_close_connection(q->server, q->sock);
2548 silc_free(q->signoff);
2552 /* Quits SILC session. This is the normal way to disconnect client. */
2554 SILC_SERVER_CMD_FUNC(quit)
2556 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2557 SilcServer server = cmd->server;
2558 SilcSocketConnection sock = cmd->sock;
2560 unsigned char *tmp = NULL;
2563 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2565 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2568 /* Get destination ID */
2569 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2573 q = silc_calloc(1, sizeof(*q));
2576 q->signoff = tmp ? strdup(tmp) : NULL;
2578 /* We quit the connection with little timeout */
2579 silc_schedule_task_add(server->schedule, sock->sock,
2580 silc_server_command_quit_cb, (void *)q,
2581 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2584 silc_server_command_free(cmd);
2587 /* Server side of command KILL. This command is used by router operator
2588 to remove an client from the SILC Network temporarily. */
2590 SILC_SERVER_CMD_FUNC(kill)
2592 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2593 SilcServer server = cmd->server;
2594 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2595 SilcClientEntry remote_client;
2596 SilcClientID *client_id;
2597 unsigned char *tmp, *comment;
2598 uint32 tmp_len, tmp_len2;
2600 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2602 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2605 /* KILL command works only on router */
2606 if (server->server_type != SILC_ROUTER) {
2607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2608 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2612 /* Check whether client has the permissions. */
2613 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2615 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2619 /* Get the client ID */
2620 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2623 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2626 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2629 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2633 /* Get the client entry */
2634 remote_client = silc_idlist_find_client_by_id(server->local_list,
2635 client_id, TRUE, NULL);
2636 if (!remote_client) {
2637 remote_client = silc_idlist_find_client_by_id(server->global_list,
2638 client_id, TRUE, NULL);
2639 if (!remote_client) {
2640 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2641 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2647 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2651 /* Send reply to the sender */
2652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2655 /* Send the KILL notify packets. First send it to the channel, then
2656 to our primary router and then directly to the client who is being
2657 killed right now. */
2659 /* Send KILLED notify to the channels. It is not sent to the client
2660 as it will be sent differently destined directly to the client and not
2662 silc_server_send_notify_on_channels(server, remote_client,
2663 remote_client, SILC_NOTIFY_TYPE_KILLED,
2666 comment, comment ? tmp_len2 : 0);
2668 /* Send KILLED notify to primary route */
2669 if (!server->standalone)
2670 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2671 remote_client->id, comment);
2673 /* Send KILLED notify to the client directly */
2674 silc_server_send_notify_killed(server, remote_client->connection ?
2675 remote_client->connection :
2676 remote_client->router->connection, FALSE,
2677 remote_client->id, comment);
2679 /* Remove the client from all channels. This generates new keys to the
2680 channels as well. */
2681 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2684 /* Remove the client entry, If it is locally connected then we will also
2685 disconnect the client here */
2686 if (remote_client->connection) {
2687 /* Remove locally conneted client */
2688 SilcSocketConnection sock = remote_client->connection;
2689 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2690 silc_server_close_connection(server, sock);
2692 /* Remove remote client */
2693 if (!silc_idlist_del_client(server->global_list, remote_client))
2694 silc_idlist_del_client(server->local_list, remote_client);
2698 silc_server_command_free(cmd);
2701 /* Server side of command INFO. This sends information about us to
2702 the client. If client requested specific server we will send the
2703 command to that server. */
2705 SILC_SERVER_CMD_FUNC(info)
2707 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2708 SilcServer server = cmd->server;
2709 SilcBuffer packet, idp;
2712 char *dest_server, *server_info = NULL, *server_name;
2713 uint16 ident = silc_command_get_ident(cmd->payload);
2714 SilcServerEntry entry = NULL;
2715 SilcServerID *server_id = NULL;
2717 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2719 /* Get server name */
2720 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2723 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2725 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2728 SILC_STATUS_ERR_NO_SERVER_ID);
2734 /* Check whether we have this server cached */
2735 entry = silc_idlist_find_server_by_id(server->local_list,
2736 server_id, TRUE, NULL);
2738 entry = silc_idlist_find_server_by_id(server->global_list,
2739 server_id, TRUE, NULL);
2740 if (!entry && server->server_type == SILC_ROUTER) {
2741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2742 SILC_STATUS_ERR_NO_SUCH_SERVER);
2748 /* Some buggy servers has sent request to router about themselves. */
2749 if (server->server_type == SILC_ROUTER && cmd->sock->user_data == entry)
2752 if ((!dest_server && !server_id && !entry) || (entry &&
2753 entry == server->id_entry) ||
2754 (dest_server && !cmd->pending &&
2755 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2756 /* Send our reply */
2757 char info_string[256];
2759 memset(info_string, 0, sizeof(info_string));
2760 snprintf(info_string, sizeof(info_string),
2761 "location: %s server: %s admin: %s <%s>",
2762 server->config->admin_info->location,
2763 server->config->admin_info->server_type,
2764 server->config->admin_info->admin_name,
2765 server->config->admin_info->admin_email);
2767 server_info = info_string;
2768 entry = server->id_entry;
2770 /* Check whether we have this server cached */
2771 if (!entry && dest_server) {
2772 entry = silc_idlist_find_server_by_name(server->global_list,
2773 dest_server, TRUE, NULL);
2775 entry = silc_idlist_find_server_by_name(server->local_list,
2776 dest_server, TRUE, NULL);
2780 if (!cmd->pending &&
2781 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2782 /* Send to the server */
2786 old_ident = silc_command_get_ident(cmd->payload);
2787 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2788 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2790 silc_server_packet_send(server, entry->connection,
2791 SILC_PACKET_COMMAND, cmd->packet->flags,
2792 tmpbuf->data, tmpbuf->len, TRUE);
2794 /* Reprocess this packet after received reply from router */
2795 silc_server_command_pending(server, SILC_COMMAND_INFO,
2796 silc_command_get_ident(cmd->payload),
2797 silc_server_command_destructor,
2798 silc_server_command_info,
2799 silc_server_command_dup(cmd));
2800 cmd->pending = TRUE;
2801 silc_command_set_ident(cmd->payload, old_ident);
2802 silc_buffer_free(tmpbuf);
2806 if (!entry && !cmd->pending && !server->standalone) {
2807 /* Send to the primary router */
2811 old_ident = silc_command_get_ident(cmd->payload);
2812 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2813 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2815 silc_server_packet_send(server, server->router->connection,
2816 SILC_PACKET_COMMAND, cmd->packet->flags,
2817 tmpbuf->data, tmpbuf->len, TRUE);
2819 /* Reprocess this packet after received reply from router */
2820 silc_server_command_pending(server, SILC_COMMAND_INFO,
2821 silc_command_get_ident(cmd->payload),
2822 silc_server_command_destructor,
2823 silc_server_command_info,
2824 silc_server_command_dup(cmd));
2825 cmd->pending = TRUE;
2826 silc_command_set_ident(cmd->payload, old_ident);
2827 silc_buffer_free(tmpbuf);
2833 silc_free(server_id);
2836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2837 SILC_STATUS_ERR_NO_SUCH_SERVER);
2841 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2843 server_info = entry->server_info;
2844 server_name = entry->server_name;
2846 /* Send the reply */
2848 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2849 SILC_STATUS_OK, ident, 3,
2850 2, idp->data, idp->len,
2852 strlen(server_name),
2854 strlen(server_info));
2856 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2857 SILC_STATUS_OK, ident, 2,
2858 2, idp->data, idp->len,
2860 strlen(server_name));
2861 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2862 packet->data, packet->len, FALSE);
2864 silc_buffer_free(packet);
2865 silc_buffer_free(idp);
2868 silc_server_command_free(cmd);
2871 /* Server side of command PING. This just replies to the ping. */
2873 SILC_SERVER_CMD_FUNC(ping)
2875 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2876 SilcServer server = cmd->server;
2881 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2884 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2887 SILC_STATUS_ERR_NO_SERVER_ID);
2890 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2894 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2895 /* Send our reply */
2896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2900 SILC_STATUS_ERR_NO_SUCH_SERVER);
2907 silc_server_command_free(cmd);
2910 /* Internal routine to join channel. The channel sent to this function
2911 has been either created or resolved from ID lists. This joins the sent
2912 client to the channel. */
2914 static void silc_server_command_join_channel(SilcServer server,
2915 SilcServerCommandContext cmd,
2916 SilcChannelEntry channel,
2917 SilcClientID *client_id,
2921 SilcSocketConnection sock = cmd->sock;
2923 uint32 tmp_len, user_count;
2924 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2925 SilcClientEntry client;
2926 SilcChannelClientEntry chl;
2927 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2928 uint16 ident = silc_command_get_ident(cmd->payload);
2929 char check[512], check2[512];
2931 SILC_LOG_DEBUG(("Start"));
2936 /* Get the client entry */
2937 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2938 client = (SilcClientEntry)sock->user_data;
2940 client = silc_server_get_client_resolve(server, client_id);
2945 /* The client info is being resolved. Reprocess this packet after
2946 receiving the reply to the query. */
2947 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2948 server->cmd_ident, NULL,
2949 silc_server_command_join,
2950 silc_server_command_dup(cmd));
2951 cmd->pending = TRUE;
2955 cmd->pending = FALSE;
2959 * Check channel modes
2962 memset(check, 0, sizeof(check));
2963 memset(check2, 0, sizeof(check2));
2964 strncat(check, client->nickname, strlen(client->nickname));
2965 strncat(check, "!", 1);
2966 strncat(check, client->username, strlen(client->username));
2967 if (!strchr(client->username, '@')) {
2968 strncat(check, "@", 1);
2969 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2972 strncat(check2, client->nickname, strlen(client->nickname));
2973 if (!strchr(client->nickname, '@')) {
2974 strncat(check2, "@", 1);
2975 strncat(check2, server->server_name, strlen(server->server_name));
2977 strncat(check2, "!", 1);
2978 strncat(check2, client->username, strlen(client->username));
2979 if (!strchr(client->username, '@')) {
2980 strncat(check2, "@", 1);
2981 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
2984 /* Check invite list if channel is invite-only channel */
2985 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2986 if (!channel->invite_list ||
2987 (!silc_string_match(channel->invite_list, check) &&
2988 !silc_string_match(channel->invite_list, check2))) {
2989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2990 SILC_STATUS_ERR_NOT_INVITED);
2995 /* Check ban list if it exists. If the client's nickname, server,
2996 username and/or hostname is in the ban list the access to the
2997 channel is denied. */
2998 if (channel->ban_list) {
2999 if (silc_string_match(channel->ban_list, check) ||
3000 silc_string_match(channel->ban_list, check2)) {
3001 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3002 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3007 /* Get passphrase */
3008 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3010 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3011 memcpy(passphrase, tmp, tmp_len);
3014 /* Check the channel passphrase if set. */
3015 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3016 if (!passphrase || memcmp(channel->passphrase, passphrase,
3017 strlen(channel->passphrase))) {
3018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3019 SILC_STATUS_ERR_BAD_PASSWORD);
3024 /* Check user count limit if set. */
3025 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3026 if (silc_hash_table_count(channel->user_list) + 1 >
3027 channel->user_limit) {
3028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3029 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3035 * Client is allowed to join to the channel. Make it happen.
3038 /* Check whether the client already is on the channel */
3039 if (silc_server_client_on_channel(client, channel)) {
3040 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3041 SILC_STATUS_ERR_USER_ON_CHANNEL);
3045 /* Generate new channel key as protocol dictates */
3046 if ((!created && silc_hash_table_count(channel->user_list) > 0) ||
3047 !channel->channel_key)
3048 if (!silc_server_create_channel_key(server, channel, 0))
3051 /* Send the channel key. This is broadcasted to the channel but is not
3052 sent to the client who is joining to the channel. */
3053 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3054 silc_server_send_channel_key(server, NULL, channel,
3055 server->server_type == SILC_ROUTER ?
3056 FALSE : !server->standalone);
3058 /* Join the client to the channel by adding it to channel's user list.
3059 Add also the channel to client entry's channels list for fast cross-
3061 chl = silc_calloc(1, sizeof(*chl));
3063 chl->client = client;
3064 chl->channel = channel;
3065 silc_hash_table_add(channel->user_list, client, chl);
3066 silc_hash_table_add(client->channels, channel, chl);
3068 /* Get users on the channel */
3069 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3072 /* Encode Client ID Payload of the original client who wants to join */
3073 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3075 /* Encode command reply packet */
3076 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3077 SILC_PUT32_MSB(channel->mode, mode);
3078 SILC_PUT32_MSB(created, tmp2);
3079 SILC_PUT32_MSB(user_count, tmp3);
3081 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3082 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3083 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3084 strlen(channel->channel_key->
3086 channel->channel_key->cipher->name,
3087 channel->key_len / 8, channel->key);
3092 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3093 SILC_STATUS_OK, ident, 13,
3094 2, channel->channel_name,
3095 strlen(channel->channel_name),
3096 3, chidp->data, chidp->len,
3097 4, clidp->data, clidp->len,
3100 7, keyp ? keyp->data : NULL,
3101 keyp ? keyp->len : 0,
3102 8, channel->ban_list,
3104 strlen(channel->ban_list) : 0,
3105 9, channel->invite_list,
3106 channel->invite_list ?
3107 strlen(channel->invite_list) : 0,
3110 strlen(channel->topic) : 0,
3111 11, channel->hmac->hmac->name,
3112 strlen(channel->hmac->hmac->name),
3114 13, user_list->data, user_list->len,
3115 14, mode_list->data,
3118 /* Send command reply */
3119 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3120 reply->data, reply->len, FALSE);
3122 if (!cmd->pending) {
3123 /* Send JOIN notify to locally connected clients on the channel */
3124 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3125 SILC_NOTIFY_TYPE_JOIN, 2,
3126 clidp->data, clidp->len,
3127 chidp->data, chidp->len);
3129 /* Send JOIN notify packet to our primary router */
3130 if (!server->standalone)
3131 silc_server_send_notify_join(server, server->router->connection,
3132 server->server_type == SILC_ROUTER ?
3133 TRUE : FALSE, channel, client->id);
3136 silc_buffer_free(reply);
3137 silc_buffer_free(clidp);
3138 silc_buffer_free(chidp);
3139 silc_buffer_free(keyp);
3140 silc_buffer_free(user_list);
3141 silc_buffer_free(mode_list);
3145 silc_free(passphrase);
3148 /* Server side of command JOIN. Joins client into requested channel. If
3149 the channel does not exist it will be created. */
3151 SILC_SERVER_CMD_FUNC(join)
3153 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3154 SilcServer server = cmd->server;
3156 char *tmp, *channel_name = NULL, *cipher, *hmac;
3157 SilcChannelEntry channel;
3159 int created = FALSE;
3160 SilcClientID *client_id;
3162 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3164 /* Get channel name */
3165 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3168 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3173 if (strlen(channel_name) > 256)
3174 channel_name[255] = '\0';
3176 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3178 SILC_STATUS_ERR_BAD_CHANNEL);
3182 /* Get Client ID of the client who is joining to the channel */
3183 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3186 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3189 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3192 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3196 /* Get cipher and hmac name */
3197 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3198 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3200 /* See if the channel exists */
3201 channel = silc_idlist_find_channel_by_name(server->local_list,
3202 channel_name, NULL);
3204 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3205 /* If this is coming from client the Client ID in the command packet must
3206 be same as the client's ID. */
3207 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3208 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3209 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3211 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3216 if (!channel || !channel->id) {
3217 /* Channel not found */
3219 /* If we are standalone server we don't have a router, we just create
3220 the channel by ourselves. */
3221 if (server->standalone) {
3222 channel = silc_server_create_new_channel(server, server->id, cipher,
3223 hmac, channel_name, TRUE);
3225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3226 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3230 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3235 /* The channel does not exist on our server. If we are normal server
3236 we will send JOIN command to our router which will handle the
3237 joining procedure (either creates the channel if it doesn't exist
3238 or joins the client to it). */
3239 if (server->server_type == SILC_SERVER) {
3243 /* If this is pending command callback then we've resolved
3244 it and it didn't work, return since we've notified the
3245 client already in the command reply callback. */
3249 old_ident = silc_command_get_ident(cmd->payload);
3250 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3251 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3253 /* Send JOIN command to our router */
3254 silc_server_packet_send(server, (SilcSocketConnection)
3255 server->router->connection,
3256 SILC_PACKET_COMMAND, cmd->packet->flags,
3257 tmpbuf->data, tmpbuf->len, TRUE);
3259 /* Reprocess this packet after received reply from router */
3260 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3261 silc_command_get_ident(cmd->payload),
3262 silc_server_command_destructor,
3263 silc_server_command_join,
3264 silc_server_command_dup(cmd));
3265 cmd->pending = TRUE;
3269 /* We are router and the channel does not seem exist so we will check
3270 our global list as well for the channel. */
3271 channel = silc_idlist_find_channel_by_name(server->global_list,
3272 channel_name, NULL);
3274 /* Channel really does not exist, create it */
3275 channel = silc_server_create_new_channel(server, server->id, cipher,
3276 hmac, channel_name, TRUE);
3278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3279 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3283 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3290 /* Channel not found */
3292 /* If the command came from router and/or we are normal server then
3293 something went wrong with the joining as the channel was not found.
3294 We can't do anything else but ignore this. */
3295 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3296 server->server_type == SILC_SERVER)
3299 /* We are router and the channel does not seem exist so we will check
3300 our global list as well for the channel. */
3301 channel = silc_idlist_find_channel_by_name(server->global_list,
3302 channel_name, NULL);
3304 /* Channel really does not exist, create it */
3305 channel = silc_server_create_new_channel(server, server->id, cipher,
3306 hmac, channel_name, TRUE);
3308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3309 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3313 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3319 /* If the channel does not have global users and is also empty it means the
3320 channel was created globally (by our router) and the client will be the
3321 channel founder and operator. */
3322 if (!channel->global_users && !silc_hash_table_count(channel->user_list)) {
3323 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3324 created = TRUE; /* Created globally by our router */
3327 /* Join to the channel */
3328 silc_server_command_join_channel(server, cmd, channel, client_id,
3331 silc_free(client_id);
3334 silc_server_command_free(cmd);
3337 /* Server side of command MOTD. Sends server's current "message of the
3338 day" to the client. */
3340 SILC_SERVER_CMD_FUNC(motd)
3342 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3343 SilcServer server = cmd->server;
3344 SilcBuffer packet, idp;
3345 char *motd, *dest_server;
3347 uint16 ident = silc_command_get_ident(cmd->payload);
3349 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3351 /* Get server name */
3352 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3355 SILC_STATUS_ERR_NO_SUCH_SERVER);
3359 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3362 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3364 if (server->config && server->config->motd &&
3365 server->config->motd->motd_file) {
3367 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3372 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3373 SILC_STATUS_OK, ident, 2,
3379 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3380 SILC_STATUS_OK, ident, 1,
3384 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3385 packet->data, packet->len, FALSE);
3386 silc_buffer_free(packet);
3387 silc_buffer_free(idp);
3389 SilcServerEntry entry;
3391 /* Check whether we have this server cached */
3392 entry = silc_idlist_find_server_by_name(server->global_list,
3393 dest_server, TRUE, NULL);
3395 entry = silc_idlist_find_server_by_name(server->local_list,
3396 dest_server, TRUE, NULL);
3399 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3400 entry && !entry->motd) {
3401 /* Send to the server */
3405 old_ident = silc_command_get_ident(cmd->payload);
3406 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3407 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3409 silc_server_packet_send(server, entry->connection,
3410 SILC_PACKET_COMMAND, cmd->packet->flags,
3411 tmpbuf->data, tmpbuf->len, TRUE);
3413 /* Reprocess this packet after received reply from router */
3414 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3415 silc_command_get_ident(cmd->payload),
3416 silc_server_command_destructor,
3417 silc_server_command_motd,
3418 silc_server_command_dup(cmd));
3419 cmd->pending = TRUE;
3420 silc_command_set_ident(cmd->payload, old_ident);
3421 silc_buffer_free(tmpbuf);
3425 if (!entry && !cmd->pending && !server->standalone) {
3426 /* Send to the primary router */
3430 old_ident = silc_command_get_ident(cmd->payload);
3431 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3432 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3434 silc_server_packet_send(server, server->router->connection,
3435 SILC_PACKET_COMMAND, cmd->packet->flags,
3436 tmpbuf->data, tmpbuf->len, TRUE);
3438 /* Reprocess this packet after received reply from router */
3439 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3440 silc_command_get_ident(cmd->payload),
3441 silc_server_command_destructor,
3442 silc_server_command_motd,
3443 silc_server_command_dup(cmd));
3444 cmd->pending = TRUE;
3445 silc_command_set_ident(cmd->payload, old_ident);
3446 silc_buffer_free(tmpbuf);
3451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3452 SILC_STATUS_ERR_NO_SUCH_SERVER);
3456 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3459 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3460 SILC_STATUS_OK, ident, 2,
3463 strlen(entry->motd));
3465 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3466 SILC_STATUS_OK, ident, 1,
3469 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3470 packet->data, packet->len, FALSE);
3471 silc_buffer_free(packet);
3472 silc_buffer_free(idp);
3476 silc_server_command_free(cmd);
3479 /* Server side of command UMODE. Client can use this command to set/unset
3480 user mode. Client actually cannot set itself to be as server/router
3481 operator so this can be used only to unset the modes. */
3483 SILC_SERVER_CMD_FUNC(umode)
3485 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3486 SilcServer server = cmd->server;
3487 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3489 unsigned char *tmp_mask;
3491 uint16 ident = silc_command_get_ident(cmd->payload);
3493 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3496 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3498 /* Get the client's mode mask */
3499 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3502 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3505 SILC_GET32_MSB(mask, tmp_mask);
3511 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3512 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3513 /* Cannot operator mode */
3514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3515 SILC_STATUS_ERR_PERM_DENIED);
3519 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3520 /* Remove the server operator rights */
3521 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3524 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3525 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3526 /* Cannot operator mode */
3527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3528 SILC_STATUS_ERR_PERM_DENIED);
3532 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3533 /* Remove the router operator rights */
3534 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3537 if (mask & SILC_UMODE_GONE) {
3538 client->mode |= SILC_UMODE_GONE;
3540 if (client->mode & SILC_UMODE_GONE)
3541 /* Remove the gone status */
3542 client->mode &= ~SILC_UMODE_GONE;
3545 /* Send UMODE change to primary router */
3546 if (!server->standalone)
3547 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3548 client->id, client->mode);
3550 /* Send command reply to sender */
3551 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3552 SILC_STATUS_OK, ident, 1,
3554 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3555 packet->data, packet->len, FALSE);
3556 silc_buffer_free(packet);
3559 silc_server_command_free(cmd);
3562 /* Checks that client has rights to add or remove channel modes. If any
3563 of the checks fails FALSE is returned. */
3565 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3566 SilcChannelClientEntry client,
3569 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3570 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3572 /* Check whether has rights to change anything */
3573 if (!is_op && !is_fo)
3576 /* Check whether has rights to change everything */
3580 /* We know that client is channel operator, check that they are not
3581 changing anything that requires channel founder rights. Rest of the
3582 modes are available automatically for channel operator. */
3584 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3585 if (is_op && !is_fo)
3588 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3589 if (is_op && !is_fo)
3594 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3595 if (is_op && !is_fo)
3598 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3599 if (is_op && !is_fo)
3604 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3605 if (is_op && !is_fo)
3608 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3609 if (is_op && !is_fo)
3614 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3615 if (is_op && !is_fo)
3618 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3619 if (is_op && !is_fo)
3627 /* Server side command of CMODE. Changes channel mode */
3629 SILC_SERVER_CMD_FUNC(cmode)
3631 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3632 SilcServer server = cmd->server;
3633 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3634 SilcIDListData idata = (SilcIDListData)client;
3635 SilcChannelID *channel_id;
3636 SilcChannelEntry channel;
3637 SilcChannelClientEntry chl;
3638 SilcBuffer packet, cidp;
3639 unsigned char *tmp, *tmp_id, *tmp_mask;
3640 char *cipher = NULL, *hmac = NULL;
3641 uint32 mode_mask, tmp_len, tmp_len2;
3642 uint16 ident = silc_command_get_ident(cmd->payload);
3644 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3646 /* Get Channel ID */
3647 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3650 SILC_STATUS_ERR_NO_CHANNEL_ID);
3653 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3656 SILC_STATUS_ERR_NO_CHANNEL_ID);
3660 /* Get the channel mode mask */
3661 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3664 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3667 SILC_GET32_MSB(mode_mask, tmp_mask);
3669 /* Get channel entry */
3670 channel = silc_idlist_find_channel_by_id(server->local_list,
3673 channel = silc_idlist_find_channel_by_id(server->global_list,
3676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3677 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3682 /* Check whether this client is on the channel */
3683 if (!silc_server_client_on_channel(client, channel)) {
3684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3685 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3689 /* Get entry to the channel user list */
3690 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3692 /* Check that client has rights to change any requested channel modes */
3693 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3695 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3700 * Check the modes. Modes that requires nothing special operation are
3704 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3705 /* Channel uses private keys to protect traffic. Client(s) has set the
3706 key locally they want to use, server does not know that key. */
3707 /* Nothing interesting to do here */
3709 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3710 /* The mode is removed and we need to generate and distribute
3711 new channel key. Clients are not using private channel keys
3712 anymore after this. */
3714 /* Re-generate channel key */
3715 if (!silc_server_create_channel_key(server, channel, 0))
3718 /* Send the channel key. This sends it to our local clients and if
3719 we are normal server to our router as well. */
3720 silc_server_send_channel_key(server, NULL, channel,
3721 server->server_type == SILC_ROUTER ?
3722 FALSE : !server->standalone);
3724 cipher = channel->channel_key->cipher->name;
3725 hmac = channel->hmac->hmac->name;
3729 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3730 /* User limit is set on channel */
3733 /* Get user limit */
3734 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3736 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3738 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3742 SILC_GET32_MSB(user_limit, tmp);
3743 channel->user_limit = user_limit;
3746 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3747 /* User limit mode is unset. Remove user limit */
3748 channel->user_limit = 0;
3751 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3752 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3753 /* Passphrase has been set to channel */
3755 /* Get the passphrase */
3756 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3759 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3763 /* Save the passphrase */
3764 channel->passphrase = strdup(tmp);
3767 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3768 /* Passphrase mode is unset. remove the passphrase */
3769 if (channel->passphrase) {
3770 silc_free(channel->passphrase);
3771 channel->passphrase = NULL;
3776 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3777 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3778 /* Cipher to use protect the traffic */
3781 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3784 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3788 /* Delete old cipher and allocate the new one */
3789 silc_cipher_free(channel->channel_key);
3790 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3792 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3796 /* Re-generate channel key */
3797 if (!silc_server_create_channel_key(server, channel, 0))
3800 /* Send the channel key. This sends it to our local clients and if
3801 we are normal server to our router as well. */
3802 silc_server_send_channel_key(server, NULL, channel,
3803 server->server_type == SILC_ROUTER ?
3804 FALSE : !server->standalone);
3807 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3808 /* Cipher mode is unset. Remove the cipher and revert back to
3810 cipher = channel->cipher;
3812 /* Delete old cipher and allocate default one */
3813 silc_cipher_free(channel->channel_key);
3814 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3815 &channel->channel_key)) {
3816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3817 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3821 /* Re-generate channel key */
3822 if (!silc_server_create_channel_key(server, channel, 0))
3825 /* Send the channel key. This sends it to our local clients and if
3826 we are normal server to our router as well. */
3827 silc_server_send_channel_key(server, NULL, channel,
3828 server->server_type == SILC_ROUTER ?
3829 FALSE : !server->standalone);
3833 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3834 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3835 /* HMAC to use protect the traffic */
3836 unsigned char hash[32];
3839 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3842 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3846 /* Delete old hmac and allocate the new one */
3847 silc_hmac_free(channel->hmac);
3848 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3850 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3854 /* Set the HMAC key out of current channel key. The client must do
3856 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3858 silc_hmac_set_key(channel->hmac, hash,
3859 silc_hash_len(channel->hmac->hash));
3860 memset(hash, 0, sizeof(hash));
3863 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3864 /* Hmac mode is unset. Remove the hmac and revert back to
3866 unsigned char hash[32];
3867 hmac = channel->hmac_name;
3869 /* Delete old hmac and allocate default one */
3870 silc_hmac_free(channel->hmac);
3871 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL,
3873 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3874 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3878 /* Set the HMAC key out of current channel key. The client must do
3880 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3882 silc_hmac_set_key(channel->hmac, hash,
3883 silc_hash_len(channel->hmac->hash));
3884 memset(hash, 0, sizeof(hash));
3888 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3889 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3890 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3891 /* Set the founder authentication */
3892 SilcAuthPayload auth;
3894 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3897 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3901 auth = silc_auth_payload_parse(tmp, tmp_len);
3903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3904 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3908 /* Save the public key */
3909 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3910 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3913 channel->founder_method = silc_auth_get_method(auth);
3915 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3916 tmp = silc_auth_get_data(auth, &tmp_len);
3917 channel->founder_passwd =
3918 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3919 memcpy(channel->founder_passwd, tmp, tmp_len);
3920 channel->founder_passwd_len = tmp_len;
3922 /* Verify the payload before setting the mode */
3923 if (!silc_auth_verify(auth, channel->founder_method,
3924 channel->founder_key, 0, idata->hash,
3925 client->id, SILC_ID_CLIENT)) {
3926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3927 SILC_STATUS_ERR_AUTH_FAILED);
3932 silc_auth_payload_free(auth);
3936 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3937 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3938 if (channel->founder_key)
3939 silc_pkcs_public_key_free(channel->founder_key);
3940 if (channel->founder_passwd) {
3941 silc_free(channel->founder_passwd);
3942 channel->founder_passwd = NULL;
3948 /* Finally, set the mode */
3949 channel->mode = mode_mask;
3951 /* Send CMODE_CHANGE notify */
3952 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3953 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3954 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3955 cidp->data, cidp->len,
3957 cipher, cipher ? strlen(cipher) : 0,
3958 hmac, hmac ? strlen(hmac) : 0);
3960 /* Set CMODE notify type to network */
3961 if (!server->standalone)
3962 silc_server_send_notify_cmode(server, server->router->connection,
3963 server->server_type == SILC_ROUTER ?
3964 TRUE : FALSE, channel,
3965 mode_mask, client->id, SILC_ID_CLIENT,
3968 /* Send command reply to sender */
3969 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3970 SILC_STATUS_OK, ident, 2,
3971 2, tmp_id, tmp_len2,
3973 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3974 packet->data, packet->len, FALSE);
3976 silc_buffer_free(packet);
3977 silc_free(channel_id);
3981 silc_server_command_free(cmd);
3984 /* Server side of CUMODE command. Changes client's mode on a channel. */
3986 SILC_SERVER_CMD_FUNC(cumode)
3988 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3989 SilcServer server = cmd->server;
3990 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3991 SilcIDListData idata = (SilcIDListData)client;
3992 SilcChannelID *channel_id;
3993 SilcClientID *client_id;
3994 SilcChannelEntry channel;
3995 SilcClientEntry target_client;
3996 SilcChannelClientEntry chl;
3997 SilcBuffer packet, idp;
3998 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3999 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4001 uint16 ident = silc_command_get_ident(cmd->payload);
4003 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4005 /* Get Channel ID */
4006 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4009 SILC_STATUS_ERR_NO_CHANNEL_ID);
4012 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4015 SILC_STATUS_ERR_NO_CHANNEL_ID);
4019 /* Get channel entry */
4020 channel = silc_idlist_find_channel_by_id(server->local_list,
4023 channel = silc_idlist_find_channel_by_id(server->global_list,
4026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4027 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4032 /* Check whether sender is on the channel */
4033 if (!silc_server_client_on_channel(client, channel)) {
4034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4035 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4039 /* Check that client has rights to change other's rights */
4040 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4041 sender_mask = chl->mode;
4043 /* Get the target client's channel mode mask */
4044 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4047 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4050 SILC_GET32_MSB(target_mask, tmp_mask);
4052 /* Get target Client ID */
4053 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4056 SILC_STATUS_ERR_NO_CLIENT_ID);
4059 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4062 SILC_STATUS_ERR_NO_CLIENT_ID);
4066 /* Get target client's entry */
4067 target_client = silc_idlist_find_client_by_id(server->local_list,
4068 client_id, TRUE, NULL);
4069 if (!target_client) {
4070 target_client = silc_idlist_find_client_by_id(server->global_list,
4071 client_id, TRUE, NULL);
4074 if (target_client != client &&
4075 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4076 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4078 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4082 /* Check whether target client is on the channel */
4083 if (target_client != client) {
4084 if (!silc_server_client_on_channel(target_client, channel)) {
4085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4086 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4090 /* Get entry to the channel user list */
4091 silc_hash_table_find(channel->user_list, target_client, NULL,
4099 /* If the target client is founder, no one else can change their mode
4101 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4103 SILC_STATUS_ERR_NOT_YOU);
4107 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4108 /* The client tries to claim the founder rights. */
4109 unsigned char *tmp_auth;
4110 uint32 tmp_auth_len, auth_len;
4113 if (target_client != client) {
4114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4115 SILC_STATUS_ERR_NOT_YOU);
4119 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4120 !channel->founder_key) {
4121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4122 SILC_STATUS_ERR_NOT_YOU);
4126 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4128 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4129 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4133 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4134 (void *)channel->founder_passwd : (void *)channel->founder_key);
4135 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4136 channel->founder_passwd_len : 0);
4138 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4139 channel->founder_method, auth, auth_len,
4140 idata->hash, client->id, SILC_ID_CLIENT)) {
4141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4142 SILC_STATUS_ERR_AUTH_FAILED);
4146 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4149 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4150 if (target_client == client) {
4151 /* Remove channel founder rights from itself */
4152 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4155 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4156 SILC_STATUS_ERR_NOT_YOU);
4162 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4163 /* Promote to operator */
4164 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4165 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4166 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4168 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4172 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4176 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4177 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4178 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4180 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4184 /* Demote to normal user */
4185 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4190 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4191 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4193 /* Send notify to channel, notify only if mode was actually changed. */
4195 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4196 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4197 idp->data, idp->len,
4201 /* Set CUMODE notify type to network */
4202 if (!server->standalone)
4203 silc_server_send_notify_cumode(server, server->router->connection,
4204 server->server_type == SILC_ROUTER ?
4205 TRUE : FALSE, channel,
4206 target_mask, client->id,
4211 /* Send command reply to sender */
4212 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4213 SILC_STATUS_OK, ident, 3,
4215 3, tmp_ch_id, tmp_ch_len,
4216 4, tmp_id, tmp_len);
4217 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4218 packet->data, packet->len, FALSE);
4220 silc_buffer_free(packet);
4221 silc_free(channel_id);
4222 silc_free(client_id);
4223 silc_buffer_free(idp);
4226 silc_server_command_free(cmd);
4229 /* Server side of KICK command. Kicks client out of channel. */
4231 SILC_SERVER_CMD_FUNC(kick)
4233 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4234 SilcServer server = cmd->server;
4235 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4236 SilcClientEntry target_client;
4237 SilcChannelID *channel_id;
4238 SilcClientID *client_id;
4239 SilcChannelEntry channel;
4240 SilcChannelClientEntry chl;
4243 unsigned char *tmp, *comment;
4245 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4247 /* Get Channel ID */
4248 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4251 SILC_STATUS_ERR_NO_CHANNEL_ID);
4254 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4257 SILC_STATUS_ERR_NO_CHANNEL_ID);
4261 /* Get channel entry */
4262 channel = silc_idlist_find_channel_by_id(server->local_list,
4265 channel = silc_idlist_find_channel_by_id(server->local_list,
4268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4269 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4274 /* Check whether sender is on the channel */
4275 if (!silc_server_client_on_channel(client, channel)) {
4276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4277 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4281 /* Check that the kicker is channel operator or channel founder */
4282 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4283 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4285 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4289 /* Get target Client ID */
4290 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4293 SILC_STATUS_ERR_NO_CLIENT_ID);
4296 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4299 SILC_STATUS_ERR_NO_CLIENT_ID);
4303 /* Get target client's entry */
4304 target_client = silc_idlist_find_client_by_id(server->local_list,
4305 client_id, TRUE, NULL);
4306 if (!target_client) {
4307 target_client = silc_idlist_find_client_by_id(server->global_list,
4308 client_id, TRUE, NULL);
4311 /* Check that the target client is not channel founder. Channel founder
4312 cannot be kicked from the channel. */
4313 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4314 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4316 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4320 /* Check whether target client is on the channel */
4321 if (!silc_server_client_on_channel(target_client, channel)) {
4322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4323 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4329 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4333 /* Send command reply to sender */
4334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4337 /* Send KICKED notify to local clients on the channel */
4338 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4339 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4340 SILC_NOTIFY_TYPE_KICKED,
4342 idp->data, idp->len,
4343 comment, comment ? strlen(comment) : 0);
4344 silc_buffer_free(idp);
4346 /* Remove the client from the channel. If the channel does not exist
4347 after removing the client then the client kicked itself off the channel
4348 and we don't have to send anything after that. */
4349 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4350 target_client, FALSE))
4353 /* Send KICKED notify to primary route */
4354 if (!server->standalone)
4355 silc_server_send_notify_kicked(server, server->router->connection,
4356 server->server_type == SILC_ROUTER ?
4357 TRUE : FALSE, channel,
4358 target_client->id, comment);
4360 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4361 /* Re-generate channel key */
4362 if (!silc_server_create_channel_key(server, channel, 0))
4365 /* Send the channel key to the channel. The key of course is not sent
4366 to the client who was kicked off the channel. */
4367 silc_server_send_channel_key(server, target_client->connection, channel,
4368 server->server_type == SILC_ROUTER ?
4369 FALSE : !server->standalone);
4373 silc_server_command_free(cmd);
4376 /* Server side of OPER command. Client uses this comand to obtain server
4377 operator privileges to this server/router. */
4379 SILC_SERVER_CMD_FUNC(oper)
4381 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4382 SilcServer server = cmd->server;
4383 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4384 unsigned char *username, *auth;
4386 SilcServerConfigSectionAdminConnection *admin;
4387 SilcIDListData idata = (SilcIDListData)client;
4389 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4391 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4394 /* Get the username */
4395 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4398 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4402 /* Get the admin configuration */
4403 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4404 username, client->nickname);
4406 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4407 username, client->nickname);
4409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4410 SILC_STATUS_ERR_AUTH_FAILED);
4415 /* Get the authentication payload */
4416 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4419 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4423 /* Verify the authentication data */
4424 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4425 admin->auth_data, admin->auth_data_len,
4426 idata->hash, client->id, SILC_ID_CLIENT)) {
4427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4428 SILC_STATUS_ERR_AUTH_FAILED);
4432 /* Client is now server operator */
4433 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4435 /* Send UMODE change to primary router */
4436 if (!server->standalone)
4437 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4438 client->id, client->mode);
4440 /* Send reply to the sender */
4441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4445 silc_server_command_free(cmd);
4448 /* Server side of SILCOPER command. Client uses this comand to obtain router
4449 operator privileges to this router. */
4451 SILC_SERVER_CMD_FUNC(silcoper)
4453 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4454 SilcServer server = cmd->server;
4455 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4456 unsigned char *username, *auth;
4458 SilcServerConfigSectionAdminConnection *admin;
4459 SilcIDListData idata = (SilcIDListData)client;
4461 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4463 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4466 if (server->server_type == SILC_SERVER) {
4467 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4468 SILC_STATUS_ERR_AUTH_FAILED);
4472 /* Get the username */
4473 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4476 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4480 /* Get the admin configuration */
4481 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4482 username, client->nickname);
4484 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4485 username, client->nickname);
4487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4488 SILC_STATUS_ERR_AUTH_FAILED);
4493 /* Get the authentication payload */
4494 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4497 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4501 /* Verify the authentication data */
4502 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4503 admin->auth_data, admin->auth_data_len,
4504 idata->hash, client->id, SILC_ID_CLIENT)) {
4505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4506 SILC_STATUS_ERR_AUTH_FAILED);
4510 /* Client is now router operator */
4511 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4513 /* Send UMODE change to primary router */
4514 if (!server->standalone)
4515 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4516 client->id, client->mode);
4518 /* Send reply to the sender */
4519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4523 silc_server_command_free(cmd);
4526 /* Server side command of CONNECT. Connects us to the specified remote
4527 server or router. */
4529 SILC_SERVER_CMD_FUNC(connect)
4531 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4532 SilcServer server = cmd->server;
4533 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4534 unsigned char *tmp, *host;
4536 uint32 port = SILC_PORT;
4538 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4540 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4543 /* Check whether client has the permissions. */
4544 if (client->mode == SILC_UMODE_NONE) {
4545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4546 SILC_STATUS_ERR_NO_SERVER_PRIV);
4550 if (server->server_type == SILC_ROUTER &&
4551 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4553 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4557 /* Get the remote server */
4558 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4561 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4566 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4568 SILC_GET32_MSB(port, tmp);
4570 /* Create the connection. It is done with timeout and is async. */
4571 silc_server_create_connection(server, host, port);
4573 /* Send reply to the sender */
4574 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4578 silc_server_command_free(cmd);
4581 /* Server side of command BAN. This is used to manage the ban list of the
4582 channel. To add clients and remove clients from the ban list. */
4584 SILC_SERVER_CMD_FUNC(ban)
4586 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4587 SilcServer server = cmd->server;
4588 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4590 SilcChannelEntry channel;
4591 SilcChannelClientEntry chl;
4592 SilcChannelID *channel_id = NULL;
4593 unsigned char *id, *add, *del;
4594 uint32 id_len, tmp_len;
4595 uint16 ident = silc_command_get_ident(cmd->payload);
4597 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4600 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4602 /* Get Channel ID */
4603 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4605 channel_id = silc_id_payload_parse_id(id, id_len);
4607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4608 SILC_STATUS_ERR_NO_CHANNEL_ID);
4613 /* Get channel entry. The server must know about the channel since the
4614 client is expected to be on the channel. */
4615 channel = silc_idlist_find_channel_by_id(server->local_list,
4618 channel = silc_idlist_find_channel_by_id(server->global_list,
4621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4622 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4627 /* Check whether this client is on the channel */
4628 if (!silc_server_client_on_channel(client, channel)) {
4629 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4630 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4634 /* Get entry to the channel user list */
4635 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4637 /* The client must be at least channel operator. */
4638 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4640 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4644 /* Get the new ban and add it to the ban list */
4645 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4647 if (!channel->ban_list)
4648 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4650 channel->ban_list = silc_realloc(channel->ban_list,
4651 sizeof(*channel->ban_list) *
4653 strlen(channel->ban_list) + 2));
4654 if (add[tmp_len - 1] == ',')
4655 add[tmp_len - 1] = '\0';
4657 strncat(channel->ban_list, add, tmp_len);
4658 strncat(channel->ban_list, ",", 1);
4661 /* Get the ban to be removed and remove it from the list */
4662 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4663 if (del && channel->ban_list) {
4664 char *start, *end, *n;
4666 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4667 silc_free(channel->ban_list);
4668 channel->ban_list = NULL;
4670 start = strstr(channel->ban_list, del);
4671 if (start && strlen(start) >= tmp_len) {
4672 end = start + tmp_len;
4673 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4674 strncat(n, channel->ban_list, start - channel->ban_list);
4675 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4677 silc_free(channel->ban_list);
4678 channel->ban_list = n;
4683 /* Send the BAN notify type to our primary router. */
4684 if (!server->standalone && (add || del))
4685 silc_server_send_notify_ban(server, server->router->connection,
4686 server->server_type == SILC_ROUTER ?
4687 TRUE : FALSE, channel, add, del);
4689 /* Send the reply back to the client */
4690 if (channel->ban_list)
4692 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4693 SILC_STATUS_OK, ident, 2,
4695 3, channel->ban_list,
4696 strlen(channel->ban_list) - 1);
4699 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4700 SILC_STATUS_OK, ident, 1,
4703 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4704 packet->data, packet->len, FALSE);
4706 silc_buffer_free(packet);
4710 silc_free(channel_id);
4711 silc_server_command_free(cmd);
4714 /* Server side command of CLOSE. Closes connection to a specified server. */
4716 SILC_SERVER_CMD_FUNC(close)
4718 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4719 SilcServer server = cmd->server;
4720 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4721 SilcServerEntry server_entry;
4722 SilcSocketConnection sock;
4725 unsigned char *name;
4726 uint32 port = SILC_PORT;
4728 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4730 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4733 /* Check whether client has the permissions. */
4734 if (client->mode == SILC_UMODE_NONE) {
4735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4736 SILC_STATUS_ERR_NO_SERVER_PRIV);
4740 /* Get the remote server */
4741 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4744 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4749 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4751 SILC_GET32_MSB(port, tmp);
4753 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4754 name, port, FALSE, NULL);
4755 if (!server_entry) {
4756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4757 SILC_STATUS_ERR_NO_SERVER_ID);
4761 /* Send reply to the sender */
4762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4765 /* Close the connection to the server */
4766 sock = (SilcSocketConnection)server_entry->connection;
4767 silc_server_free_sock_user_data(server, sock);
4768 silc_server_close_connection(server, sock);
4771 silc_server_command_free(cmd);
4774 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4775 active connections. */
4777 SILC_SERVER_CMD_FUNC(shutdown)
4779 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4780 SilcServer server = cmd->server;
4781 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4783 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4785 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4788 /* Check whether client has the permission. */
4789 if (client->mode == SILC_UMODE_NONE) {
4790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4791 SILC_STATUS_ERR_NO_SERVER_PRIV);
4795 /* Send reply to the sender */
4796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4799 /* Then, gracefully, or not, bring the server down. */
4800 silc_server_stop(server);
4804 silc_server_command_free(cmd);
4807 /* Server side command of LEAVE. Removes client from a channel. */
4809 SILC_SERVER_CMD_FUNC(leave)
4811 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4812 SilcServer server = cmd->server;
4813 SilcSocketConnection sock = cmd->sock;
4814 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4815 SilcChannelID *id = NULL;
4816 SilcChannelEntry channel;
4820 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4822 /* Get Channel ID */
4823 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4826 SILC_STATUS_ERR_NO_CHANNEL_ID);
4829 id = silc_id_payload_parse_id(tmp, len);
4831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4832 SILC_STATUS_ERR_NO_CHANNEL_ID);
4836 /* Get channel entry */
4837 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4839 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4842 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4847 /* Check whether this client is on the channel */
4848 if (!silc_server_client_on_channel(id_entry, channel)) {
4849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4850 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4854 /* Notify routers that they should remove this client from their list
4855 of clients on the channel. Send LEAVE notify type. */
4856 if (!server->standalone)
4857 silc_server_send_notify_leave(server, server->router->connection,
4858 server->server_type == SILC_ROUTER ?
4859 TRUE : FALSE, channel, id_entry->id);
4861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4864 /* Remove client from channel */
4865 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4867 /* If the channel does not exist anymore we won't send anything */
4870 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4871 /* Re-generate channel key */
4872 if (!silc_server_create_channel_key(server, channel, 0))
4875 /* Send the channel key */
4876 silc_server_send_channel_key(server, NULL, channel,
4877 server->server_type == SILC_ROUTER ?
4878 FALSE : !server->standalone);
4884 silc_server_command_free(cmd);
4887 /* Server side of command USERS. Resolves clients and their USERS currently
4888 joined on the requested channel. The list of Client ID's and their modes
4889 on the channel is sent back. */
4891 SILC_SERVER_CMD_FUNC(users)
4893 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4894 SilcServer server = cmd->server;
4895 SilcChannelEntry channel;
4896 SilcChannelID *id = NULL;
4897 SilcBuffer packet, idp;
4898 unsigned char *channel_id;
4899 uint32 channel_id_len;
4900 SilcBuffer client_id_list;
4901 SilcBuffer client_mode_list;
4902 unsigned char lc[4];
4903 uint32 list_count = 0;
4904 uint16 ident = silc_command_get_ident(cmd->payload);
4907 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4909 /* Get Channel ID */
4910 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4912 /* Get channel name */
4913 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4915 if (!channel_id && !channel_name) {
4916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4917 SILC_STATUS_ERR_NO_CHANNEL_ID);
4922 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4925 SILC_STATUS_ERR_NO_CHANNEL_ID);
4930 /* If we are server and we don't know about this channel we will send
4931 the command to our router. If we know about the channel then we also
4932 have the list of users already. */
4934 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4936 channel = silc_idlist_find_channel_by_name(server->local_list,
4937 channel_name, NULL);
4940 if (server->server_type == SILC_SERVER && !server->standalone &&
4944 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4945 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4947 /* Send USERS command */
4948 silc_server_packet_send(server, server->router->connection,
4949 SILC_PACKET_COMMAND, cmd->packet->flags,
4950 tmpbuf->data, tmpbuf->len, TRUE);
4952 /* Reprocess this packet after received reply */
4953 silc_server_command_pending(server, SILC_COMMAND_USERS,
4954 silc_command_get_ident(cmd->payload),
4955 silc_server_command_destructor,
4956 silc_server_command_users,
4957 silc_server_command_dup(cmd));
4958 cmd->pending = TRUE;
4959 silc_command_set_ident(cmd->payload, ident);
4961 silc_buffer_free(tmpbuf);
4966 /* Check the global list as well. */
4968 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4970 channel = silc_idlist_find_channel_by_name(server->global_list,
4971 channel_name, NULL);
4973 /* Channel really does not exist */
4974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4975 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4980 /* If the channel is private or secret do not send anything, unless the
4981 user requesting this command is on the channel. */
4982 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4983 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4984 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
4985 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4986 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4991 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
4992 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4993 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4998 /* Get the users list */
4999 silc_server_get_users_on_channel(server, channel, &client_id_list,
5000 &client_mode_list, &list_count);
5003 SILC_PUT32_MSB(list_count, lc);
5006 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5007 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5008 SILC_STATUS_OK, ident, 4,
5009 2, idp->data, idp->len,
5011 4, client_id_list->data,
5012 client_id_list->len,
5013 5, client_mode_list->data,
5014 client_mode_list->len);
5015 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5016 packet->data, packet->len, FALSE);
5018 silc_buffer_free(idp);
5019 silc_buffer_free(packet);
5020 silc_buffer_free(client_id_list);
5021 silc_buffer_free(client_mode_list);
5026 silc_server_command_free(cmd);
5029 /* Server side of command GETKEY. This fetches the client's public key
5030 from the server where to the client is connected. */
5032 SILC_SERVER_CMD_FUNC(getkey)
5034 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5035 SilcServer server = cmd->server;
5037 SilcClientEntry client;
5038 SilcServerEntry server_entry;
5039 SilcClientID *client_id = NULL;
5040 SilcServerID *server_id = NULL;
5041 SilcIDPayload idp = NULL;
5042 uint16 ident = silc_command_get_ident(cmd->payload);
5043 unsigned char *tmp, *pkdata;
5044 uint32 tmp_len, pklen;
5045 SilcBuffer pk = NULL;
5048 SILC_LOG_DEBUG(("Start"));
5050 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5053 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5056 idp = silc_id_payload_parse_data(tmp, tmp_len);
5058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5059 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5063 id_type = silc_id_payload_get_type(idp);
5064 if (id_type == SILC_ID_CLIENT) {
5065 client_id = silc_id_payload_get_id(idp);
5067 /* If the client is not found from local list there is no chance it
5068 would be locally connected client so send the command further. */
5069 client = silc_idlist_find_client_by_id(server->local_list,
5070 client_id, TRUE, NULL);
5072 client = silc_idlist_find_client_by_id(server->global_list,
5073 client_id, TRUE, NULL);
5075 if ((!client && !cmd->pending && !server->standalone) ||
5076 (client && !client->connection && !cmd->pending &&
5077 !server->standalone) ||
5078 (client && !client->data.public_key && !cmd->pending &&
5079 !server->standalone)) {
5082 SilcSocketConnection dest_sock;
5084 dest_sock = silc_server_get_client_route(server, NULL, 0,
5089 old_ident = silc_command_get_ident(cmd->payload);
5090 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5091 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5093 silc_server_packet_send(server, dest_sock,
5094 SILC_PACKET_COMMAND, cmd->packet->flags,
5095 tmpbuf->data, tmpbuf->len, TRUE);
5097 /* Reprocess this packet after received reply from router */
5098 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5099 silc_command_get_ident(cmd->payload),
5100 silc_server_command_destructor,
5101 silc_server_command_getkey,
5102 silc_server_command_dup(cmd));
5103 cmd->pending = TRUE;
5105 silc_command_set_ident(cmd->payload, old_ident);
5106 silc_buffer_free(tmpbuf);
5111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5112 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5116 /* The client is locally connected, just get the public key and
5117 send it back. If they key does not exist then do not send it,
5118 send just OK reply */
5119 if (!client->data.public_key) {
5123 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5124 pk = silc_buffer_alloc(4 + tmp_len);
5125 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5126 silc_buffer_format(pk,
5127 SILC_STR_UI_SHORT(tmp_len),
5128 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5129 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5135 } else if (id_type == SILC_ID_SERVER) {
5136 server_id = silc_id_payload_get_id(idp);
5138 /* If the server is not found from local list there is no chance it
5139 would be locally connected server so send the command further. */
5140 server_entry = silc_idlist_find_server_by_id(server->local_list,
5141 server_id, TRUE, NULL);
5143 server_entry = silc_idlist_find_server_by_id(server->global_list,
5144 server_id, TRUE, NULL);
5146 if (server_entry != server->id_entry &&
5147 ((!server_entry && !cmd->pending && !server->standalone) ||
5148 (server_entry && !server_entry->connection && !cmd->pending &&
5149 !server->standalone) ||
5150 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5151 !server->standalone))) {
5155 old_ident = silc_command_get_ident(cmd->payload);
5156 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5157 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5159 silc_server_packet_send(server, server->router->connection,
5160 SILC_PACKET_COMMAND, cmd->packet->flags,
5161 tmpbuf->data, tmpbuf->len, TRUE);
5163 /* Reprocess this packet after received reply from router */
5164 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5165 silc_command_get_ident(cmd->payload),
5166 silc_server_command_destructor,
5167 silc_server_command_getkey,
5168 silc_server_command_dup(cmd));
5169 cmd->pending = TRUE;
5171 silc_command_set_ident(cmd->payload, old_ident);
5172 silc_buffer_free(tmpbuf);
5176 if (!server_entry) {
5177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5178 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5182 /* If they key does not exist then do not send it, send just OK reply */
5183 if (!server_entry->data.public_key) {
5187 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5189 pk = silc_buffer_alloc(4 + tmp_len);
5190 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5191 silc_buffer_format(pk,
5192 SILC_STR_UI_SHORT(tmp_len),
5193 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5194 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5204 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5205 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5206 SILC_STATUS_OK, ident,
5210 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5211 packet->data, packet->len, FALSE);
5212 silc_buffer_free(packet);
5215 silc_buffer_free(pk);
5219 silc_id_payload_free(idp);
5220 silc_free(client_id);
5221 silc_free(server_id);
5222 silc_server_command_free(cmd);