5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
38 const unsigned char *arg,
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42 SilcServerCommandReplyContext cmdr,
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
71 SILC_SERVER_CMD(silcoper, SILCOPER,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
75 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(connect, PRIV_CONNECT,
78 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
79 SILC_SERVER_CMD(close, PRIV_CLOSE,
80 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
81 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
87 /* Performs several checks to the command. It first checks whether this
88 command was called as pending command callback. If it was then it checks
89 whether error occurred in the command reply where the pending command
92 It also checks that the requested command includes correct amount
94 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
98 SILC_LOG_DEBUG(("Start")); \
100 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
101 silc_server_command_free(cmd); \
105 _argc = silc_argument_get_arg_num(cmd->args); \
107 silc_server_command_send_status_reply(cmd, command, \
108 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
109 silc_server_command_free(cmd); \
113 silc_server_command_send_status_reply(cmd, command, \
114 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
115 silc_server_command_free(cmd); \
120 /* Returns TRUE if the connection is registered. Unregistered connections
121 usually cannot send commands hence the check. */
123 static int silc_server_is_registered(SilcServer server,
124 SilcSocketConnection sock,
125 SilcServerCommandContext cmd,
128 SilcIDListData idata = (SilcIDListData)sock->user_data;
133 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
136 silc_server_command_send_status_reply(cmd, command,
137 SILC_STATUS_ERR_NOT_REGISTERED);
141 /* Internal context to hold data when executed command with timeout. */
143 SilcServerCommandContext ctx;
144 SilcServerCommand *cmd;
145 } *SilcServerCommandTimeout;
147 /* Timeout callback to process commands with timeout for client. Client's
148 commands are always executed with timeout. */
150 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
152 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
153 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
156 silc_server_command_free(timeout->ctx);
160 /* Update access time */
161 client->last_command = time(NULL);
163 if (!(timeout->cmd->flags & SILC_CF_REG))
164 timeout->cmd->cb(timeout->ctx, NULL);
165 else if (silc_server_is_registered(timeout->ctx->server,
169 timeout->cmd->cb(timeout->ctx, NULL);
171 silc_server_command_free(timeout->ctx);
176 /* Processes received command packet. */
178 void silc_server_command_process(SilcServer server,
179 SilcSocketConnection sock,
180 SilcPacketContext *packet)
182 SilcServerCommandContext ctx;
183 SilcServerCommand *cmd;
186 /* Allocate command context. This must be free'd by the
187 command routine receiving it. */
188 ctx = silc_server_command_alloc();
189 ctx->server = server;
190 ctx->sock = silc_socket_dup(sock);
191 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
193 /* Parse the command payload in the packet */
194 ctx->payload = silc_command_payload_parse(packet->buffer->data,
195 packet->buffer->len);
197 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
198 silc_buffer_free(packet->buffer);
199 silc_packet_context_free(packet);
200 silc_socket_free(ctx->sock);
204 ctx->args = silc_command_get_args(ctx->payload);
206 /* Get the command */
207 command = silc_command_get(ctx->payload);
208 for (cmd = silc_command_list; cmd->cb; cmd++)
209 if (cmd->cmd == command)
212 if (!cmd || !cmd->cb) {
213 silc_server_command_send_status_reply(ctx, command,
214 SILC_STATUS_ERR_UNKNOWN_COMMAND);
215 silc_server_command_free(ctx);
219 /* Execute client's commands always with timeout. Normally they are
220 executed with zero (0) timeout but if client is sending command more
221 frequently than once in 2 seconds, then the timeout may be 0 to 2
223 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
224 SilcClientEntry client = (SilcClientEntry)sock->user_data;
225 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
231 if (client->last_command && (time(NULL) - client->last_command) < 2) {
232 client->fast_command++;
235 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
236 client->fast_command--);
240 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
241 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
242 silc_schedule_task_add(server->schedule, sock->sock,
243 silc_server_command_process_timeout,
245 2 - (time(NULL) - client->last_command), 0,
246 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
248 silc_schedule_task_add(server->schedule, sock->sock,
249 silc_server_command_process_timeout,
250 (void *)timeout, 0, 1,
251 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
255 /* Execute for server */
257 if (!(cmd->flags & SILC_CF_REG))
259 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
262 silc_server_command_free(ctx);
265 /* Allocate Command Context */
267 SilcServerCommandContext silc_server_command_alloc()
269 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
274 /* Free's the command context allocated before executing the command */
276 void silc_server_command_free(SilcServerCommandContext ctx)
279 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
281 if (ctx->users < 1) {
283 silc_command_payload_free(ctx->payload);
285 silc_packet_context_free(ctx->packet);
287 silc_socket_free(ctx->sock); /* Decrease reference counter */
292 /* Duplicate Command Context by adding reference counter. The context won't
293 be free'd untill it hits zero. */
295 SilcServerCommandContext
296 silc_server_command_dup(SilcServerCommandContext ctx)
299 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
304 /* Add new pending command to be executed when reply to a command has been
305 received. The `reply_cmd' is the command that will call the `callback'
306 with `context' when reply has been received. It can be SILC_COMMAND_NONE
307 to match any command with the `ident'. If `ident' is non-zero
308 the `callback' will be executed when received reply with command
309 identifier `ident'. If there already exists pending command for the
310 specified command, ident, callback and context this function has no
313 bool silc_server_command_pending(SilcServer server,
314 SilcCommand reply_cmd,
316 SilcCommandCb callback,
319 SilcServerCommandPending *reply;
321 /* Check whether identical pending already exists for same command,
322 ident, callback and callback context. If it does then it would be
323 error to register it again. */
324 silc_dlist_start(server->pending_commands);
325 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
326 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
327 reply->callback == callback && reply->context == context)
331 reply = silc_calloc(1, sizeof(*reply));
332 reply->reply_cmd = reply_cmd;
333 reply->ident = ident;
334 reply->context = context;
335 reply->callback = callback;
336 silc_dlist_add(server->pending_commands, reply);
341 /* Deletes pending command by reply command type. */
343 void silc_server_command_pending_del(SilcServer server,
344 SilcCommand reply_cmd,
347 SilcServerCommandPending *r;
349 silc_dlist_start(server->pending_commands);
350 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
351 if (r->reply_cmd == reply_cmd && r->ident == ident) {
352 silc_dlist_del(server->pending_commands, r);
358 /* Checks for pending commands and marks callbacks to be called from
359 the command reply function. Returns TRUE if there were pending command. */
361 SilcServerCommandPendingCallbacks
362 silc_server_command_pending_check(SilcServer server,
363 SilcServerCommandReplyContext ctx,
366 SilcUInt32 *callbacks_count)
368 SilcServerCommandPending *r;
369 SilcServerCommandPendingCallbacks callbacks = NULL;
372 silc_dlist_start(server->pending_commands);
373 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
374 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
375 && r->ident == ident) {
376 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
377 callbacks[i].context = r->context;
378 callbacks[i].callback = r->callback;
384 *callbacks_count = i;
388 /* Sends simple status message as command reply packet */
391 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
397 SILC_LOG_DEBUG(("Sending command status %d", status));
400 silc_command_reply_payload_encode_va(command, status, 0,
401 silc_command_get_ident(cmd->payload),
403 silc_server_packet_send(cmd->server, cmd->sock,
404 SILC_PACKET_COMMAND_REPLY, 0,
405 buffer->data, buffer->len, FALSE);
406 silc_buffer_free(buffer);
409 /* Sends command status reply with one extra argument. The argument
410 type must be sent as argument. */
413 silc_server_command_send_status_data(SilcServerCommandContext cmd,
417 const unsigned char *arg,
422 SILC_LOG_DEBUG(("Sending command status %d", status));
425 silc_command_reply_payload_encode_va(command, status, 0,
426 silc_command_get_ident(cmd->payload),
427 1, arg_type, arg, arg_len);
428 silc_server_packet_send(cmd->server, cmd->sock,
429 SILC_PACKET_COMMAND_REPLY, 0,
430 buffer->data, buffer->len, FALSE);
431 silc_buffer_free(buffer);
434 /* This function can be called to check whether in the command reply
435 an error occurred. This function has no effect if this is called
436 when the command function was not called as pending command callback.
437 This returns TRUE if error had occurred. */
440 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
441 SilcServerCommandReplyContext cmdr,
444 if (!cmd->pending || !cmdr)
447 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
450 /* Send the same command reply payload */
451 silc_command_set_ident(cmdr->payload,
452 silc_command_get_ident(cmd->payload));
453 buffer = silc_command_payload_encode_payload(cmdr->payload);
454 silc_server_packet_send(cmd->server, cmd->sock,
455 SILC_PACKET_COMMAND_REPLY, 0,
456 buffer->data, buffer->len, FALSE);
457 silc_buffer_free(buffer);
464 /******************************************************************************
468 ******************************************************************************/
471 silc_server_command_whois_parse(SilcServerCommandContext cmd,
472 SilcClientID ***client_id,
473 SilcUInt32 *client_id_count,
481 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
484 /* If client ID is in the command it must be used instead of nickname */
485 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
487 /* No ID, get the nickname@server string and parse it. */
488 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
490 silc_parse_userfqdn(tmp, nickname, server_name);
492 silc_server_command_send_status_reply(cmd, command,
493 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
497 /* Command includes ID, we must use that. Also check whether the command
498 has more than one ID set - take them all. */
500 *client_id = silc_calloc(1, sizeof(**client_id));
501 (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
502 if ((*client_id)[0] == NULL) {
503 silc_free(*client_id);
504 silc_server_command_send_status_reply(cmd, command,
505 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
508 *client_id_count = 1;
510 /* Take all ID's from the command packet */
512 for (k = 1, i = 1; i < argc; i++) {
513 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
515 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
516 (*client_id_count + 1));
517 (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
518 if ((*client_id)[k] == NULL) {
519 /* Cleanup all and fail */
520 for (i = 0; i < *client_id_count; i++)
521 silc_free((*client_id)[i]);
522 silc_free(*client_id);
523 silc_server_command_send_status_reply(
525 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
528 (*client_id_count)++;
535 /* Get the max count of reply messages allowed */
536 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
538 SILC_GET32_MSB(*count, tmp);
546 /* Resolve context used by both WHOIS and IDENTIFY commands */
548 SilcServerEntry router;
550 unsigned char **res_argv;
551 SilcUInt32 *res_argv_lens;
552 SilcUInt32 *res_argv_types;
554 } *SilcServerResolveContext;
557 silc_server_command_whois_check(SilcServerCommandContext cmd,
558 SilcClientEntry *clients,
559 SilcUInt32 clients_count)
561 SilcServer server = cmd->server;
562 SilcClientEntry entry;
563 SilcServerResolveContext resolve = NULL, r = NULL;
564 SilcUInt32 resolve_count = 0;
568 SILC_LOG_DEBUG(("Start"));
570 for (i = 0; i < clients_count; i++) {
575 if ((entry->nickname && entry->username && entry->userinfo) ||
576 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
580 /* If we are normal server, and we've not resolved this client from
581 router and it is global client, we'll check whether it is on some
582 channel. If not then we cannot be sure about its validity, and
583 we'll resolve it from router. */
584 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
585 entry->connection || silc_hash_table_count(entry->channels))
589 /* We need to resolve this entry since it is not complete */
591 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
592 /* The entry is being resolved (and we are not the resolver) so attach
593 to the command reply and we're done with this one. */
594 silc_server_command_pending(server, SILC_COMMAND_NONE,
595 entry->resolve_cmd_ident,
596 silc_server_command_whois,
597 silc_server_command_dup(cmd));
600 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
601 /* We've resolved this and it still is not ready. We'll return
602 and are that this will be handled again after it is resolved. */
603 for (i = 0; i < resolve_count; i++) {
604 for (k = 0; k < r->res_argc; k++)
605 silc_free(r->res_argv[k]);
606 silc_free(r->res_argv);
607 silc_free(r->res_argv_lens);
608 silc_free(r->res_argv_types);
613 /* We'll resolve this client */
617 for (k = 0; k < resolve_count; k++) {
618 if (resolve[k].router == entry->router) {
625 resolve = silc_realloc(resolve, sizeof(*resolve) *
626 (resolve_count + 1));
627 r = &resolve[resolve_count];
628 memset(r, 0, sizeof(*r));
629 r->router = entry->router;
630 r->ident = ++server->cmd_ident;
634 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
636 r->res_argv_lens = silc_realloc(r->res_argv_lens,
637 sizeof(*r->res_argv_lens) *
639 r->res_argv_types = silc_realloc(r->res_argv_types,
640 sizeof(*r->res_argv_types) *
642 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
643 r->res_argv[r->res_argc] = silc_calloc(idp->len,
644 sizeof(**r->res_argv));
645 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
646 r->res_argv_lens[r->res_argc] = idp->len;
647 r->res_argv_types[r->res_argc] = r->res_argc + 3;
649 silc_buffer_free(idp);
651 entry->resolve_cmd_ident = r->ident;
652 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
653 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
658 /* Do the resolving */
659 for (i = 0; i < resolve_count; i++) {
664 /* Send WHOIS request. We send WHOIS since we're doing the requesting
665 now anyway so make it a good one. */
666 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
667 r->res_argc, r->res_argv,
671 silc_server_packet_send(server, r->router->connection,
672 SILC_PACKET_COMMAND, cmd->packet->flags,
673 res_cmd->data, res_cmd->len, FALSE);
675 /* Reprocess this packet after received reply */
676 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
678 silc_server_command_whois,
679 silc_server_command_dup(cmd));
682 silc_buffer_free(res_cmd);
683 for (k = 0; k < r->res_argc; k++)
684 silc_free(r->res_argv[k]);
685 silc_free(r->res_argv);
686 silc_free(r->res_argv_lens);
687 silc_free(r->res_argv_types);
696 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
697 SilcClientEntry *clients,
698 SilcUInt32 clients_count,
700 const char *nickname,
701 SilcClientID **client_ids)
703 SilcServer server = cmd->server;
705 int i, k, len, valid_count;
706 SilcBuffer packet, idp, channels, umode_list = NULL;
707 SilcClientEntry entry;
709 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
710 char nh[256], uh[256];
711 unsigned char idle[4], mode[4];
712 unsigned char *fingerprint;
713 SilcSocketConnection hsock;
715 /* Process only valid clients and ignore those that are not registered. */
717 for (i = 0; i < clients_count; i++) {
718 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
725 /* No valid clients found, send error reply */
727 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
728 SILC_STATUS_ERR_NO_SUCH_NICK,
729 3, nickname, strlen(nickname));
730 } else if (client_ids && client_ids[0]) {
731 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
732 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
733 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
734 2, idp->data, idp->len);
735 silc_buffer_free(idp);
740 /* Start processing found clients. */
742 status = SILC_STATUS_LIST_START;
744 status = SILC_STATUS_OK;
746 for (i = 0, k = 0; i < clients_count; i++) {
752 status = SILC_STATUS_LIST_ITEM;
753 if (valid_count > 1 && k == valid_count - 1)
754 status = SILC_STATUS_LIST_END;
755 if (count && k - 1 == count)
756 status = SILC_STATUS_LIST_END;
758 /* Send WHOIS reply */
759 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
760 tmp = silc_argument_get_first_arg(cmd->args, NULL);
762 memset(uh, 0, sizeof(uh));
763 memset(nh, 0, sizeof(nh));
764 memset(idle, 0, sizeof(idle));
766 strncat(nh, entry->nickname, strlen(entry->nickname));
767 if (!strchr(entry->nickname, '@')) {
769 if (entry->servername) {
770 strncat(nh, entry->servername, strlen(entry->servername));
772 len = entry->router ? strlen(entry->router->server_name) :
773 strlen(server->server_name);
774 strncat(nh, entry->router ? entry->router->server_name :
775 server->server_name, len);
779 strncat(uh, entry->username, strlen(entry->username));
780 if (!strchr(entry->username, '@') && entry->connection) {
782 hsock = (SilcSocketConnection)entry->connection;
783 len = strlen(hsock->hostname);
784 strncat(uh, hsock->hostname, len);
787 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
788 channels = silc_server_get_client_channel_list(server, entry, FALSE,
791 channels = silc_server_get_client_channel_list(server, entry, TRUE,
794 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
795 fingerprint = entry->data.fingerprint;
799 SILC_PUT32_MSB(entry->mode, mode);
801 if (entry->connection) {
802 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
806 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
808 2, idp->data, idp->len,
812 strlen(entry->userinfo),
813 6, channels ? channels->data : NULL,
814 channels ? channels->len : 0,
818 fingerprint ? 20 : 0,
819 10, umode_list ? umode_list->data :
820 NULL, umode_list ? umode_list->len :
823 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
824 0, packet->data, packet->len, FALSE);
826 silc_buffer_free(packet);
827 silc_buffer_free(idp);
829 silc_buffer_free(channels);
831 silc_buffer_free(umode_list);
840 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
842 SilcServer server = cmd->server;
844 SilcUInt16 old_ident;
846 old_ident = silc_command_get_ident(cmd->payload);
847 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
848 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
850 /* Send WHOIS command to our router */
851 silc_server_packet_send(server, (SilcSocketConnection)
852 server->router->connection,
853 SILC_PACKET_COMMAND, cmd->packet->flags,
854 tmpbuf->data, tmpbuf->len, TRUE);
856 /* Reprocess this packet after received reply from router */
857 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
858 silc_command_get_ident(cmd->payload),
859 silc_server_command_whois,
860 silc_server_command_dup(cmd));
862 silc_command_set_ident(cmd->payload, old_ident);
863 silc_buffer_free(tmpbuf);
867 silc_server_command_whois_process(SilcServerCommandContext cmd)
869 SilcServer server = cmd->server;
870 char *nick = NULL, *server_name = NULL;
872 SilcClientEntry *clients = NULL, entry;
873 SilcClientID **client_id = NULL;
874 SilcUInt32 client_id_count = 0, clients_count = 0;
876 bool check_global = FALSE;
878 /* Parse the whois request */
879 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
880 &nick, &server_name, &count,
884 /* Send the WHOIS request to the router only if it included nickname.
885 Since nicknames can be expanded into many clients we need to send it
886 to router. If the WHOIS included only client ID's we will check them
887 first locally since we just might have them. */
888 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
889 server->server_type == SILC_SERVER && !cmd->pending &&
890 !server->standalone) {
891 silc_server_command_whois_send_router(cmd);
896 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
898 else if (server->server_type != SILC_SERVER)
901 /* Get all clients matching that ID or nickname from local list */
902 if (client_id_count) {
903 /* Check all Client ID's received in the command packet */
904 for (i = 0; i < client_id_count; i++) {
905 entry = silc_idlist_find_client_by_id(server->local_list,
906 client_id[i], TRUE, NULL);
907 if (!entry && check_global)
908 entry = silc_idlist_find_client_by_id(server->global_list,
909 client_id[i], TRUE, NULL);
911 clients = silc_realloc(clients, sizeof(*clients) *
912 (clients_count + 1));
913 clients[clients_count++] = entry;
915 /* If we are normal server and did not send the request first to router
916 do it now, since we do not have the Client ID information. */
917 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
918 server->server_type == SILC_SERVER && !cmd->pending &&
919 !server->standalone) {
920 silc_server_command_whois_send_router(cmd);
927 /* Find by nickname */
928 if (!silc_idlist_get_clients_by_hash(server->local_list,
929 nick, server->md5hash,
930 &clients, &clients_count))
931 silc_idlist_get_clients_by_nickname(server->local_list,
933 &clients, &clients_count);
935 if (!silc_idlist_get_clients_by_hash(server->global_list,
936 nick, server->md5hash,
937 &clients, &clients_count))
938 silc_idlist_get_clients_by_nickname(server->global_list,
940 &clients, &clients_count);
945 /* If we are normal server and did not send the request first to router
946 do it now, since we do not have the information. */
947 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
948 server->server_type == SILC_SERVER && !cmd->pending &&
949 !server->standalone) {
950 silc_server_command_whois_send_router(cmd);
955 /* Such client(s) really does not exist in the SILC network. */
956 if (!client_id_count) {
957 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
958 SILC_STATUS_ERR_NO_SUCH_NICK,
959 3, nick, strlen(nick));
961 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
962 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
963 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
964 2, idp->data, idp->len);
965 silc_buffer_free(idp);
970 /* Router always finds the client entry if it exists in the SILC network.
971 However, it might be incomplete entry and does not include all the
972 mandatory fields that WHOIS command reply requires. Check for these and
973 make query from the server who owns the client if some fields are
975 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
980 /* Send the command reply */
981 silc_server_command_whois_send_reply(cmd, clients, clients_count,
982 count, nick, client_id);
985 if (client_id_count) {
986 for (i = 0; i < client_id_count; i++)
987 silc_free(client_id[i]);
988 silc_free(client_id);
992 silc_free(server_name);
997 /* Server side of command WHOIS. Processes user's query and sends found
998 results as command replies back to the client. */
1000 SILC_SERVER_CMD_FUNC(whois)
1002 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1005 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1007 ret = silc_server_command_whois_process(cmd);
1008 silc_server_command_free(cmd);
1011 /******************************************************************************
1015 ******************************************************************************/
1018 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1026 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1029 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1033 /* Get the nickname@server string and parse it. */
1034 silc_parse_userfqdn(tmp, nickname, server_name);
1036 /* Get the max count of reply messages allowed */
1037 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1039 SILC_GET32_MSB(*count, tmp);
1048 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1049 SilcClientEntry *clients,
1050 SilcUInt32 clients_count)
1052 SilcServer server = cmd->server;
1054 SilcClientEntry entry;
1056 for (i = 0; i < clients_count; i++) {
1059 if (!entry->nickname || !entry->username) {
1061 SilcUInt16 old_ident;
1066 old_ident = silc_command_get_ident(cmd->payload);
1067 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1068 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1070 /* Send WHOWAS command */
1071 silc_server_packet_send(server, entry->router->connection,
1072 SILC_PACKET_COMMAND, cmd->packet->flags,
1073 tmpbuf->data, tmpbuf->len, TRUE);
1075 /* Reprocess this packet after received reply */
1076 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1077 silc_command_get_ident(cmd->payload),
1078 silc_server_command_whowas,
1079 silc_server_command_dup(cmd));
1080 cmd->pending = TRUE;
1081 silc_command_set_ident(cmd->payload, old_ident);
1083 silc_buffer_free(tmpbuf);
1092 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1093 SilcClientEntry *clients,
1094 SilcUInt32 clients_count)
1096 SilcServer server = cmd->server;
1098 int i, k, count = 0, len;
1099 SilcBuffer packet, idp;
1100 SilcClientEntry entry = NULL;
1102 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1103 char nh[256], uh[256];
1106 status = SILC_STATUS_OK;
1108 /* Process only entries that are not registered anymore. */
1110 for (i = 0; i < clients_count; i++) {
1111 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1118 /* No valid entries found at all, just send error */
1121 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1123 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1124 SILC_STATUS_ERR_NO_SUCH_NICK,
1125 3, tmp, strlen(tmp));
1129 if (valid_count > 1)
1130 status = SILC_STATUS_LIST_START;
1132 for (i = 0, k = 0; i < clients_count; i++) {
1138 status = SILC_STATUS_LIST_ITEM;
1139 if (valid_count > 1 && k == valid_count - 1)
1140 status = SILC_STATUS_LIST_END;
1141 if (count && k - 1 == count)
1142 status = SILC_STATUS_LIST_END;
1143 if (count && k - 1 > count)
1146 /* Send WHOWAS reply */
1147 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1148 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1149 memset(uh, 0, sizeof(uh));
1150 memset(nh, 0, sizeof(nh));
1152 strncat(nh, entry->nickname, strlen(entry->nickname));
1153 if (!strchr(entry->nickname, '@')) {
1154 strncat(nh, "@", 1);
1155 if (entry->servername) {
1156 strncat(nh, entry->servername, strlen(entry->servername));
1158 len = entry->router ? strlen(entry->router->server_name) :
1159 strlen(server->server_name);
1160 strncat(nh, entry->router ? entry->router->server_name :
1161 server->server_name, len);
1165 strncat(uh, entry->username, strlen(entry->username));
1166 if (!strchr(entry->username, '@')) {
1167 strncat(uh, "@", 1);
1168 strcat(uh, "*private*");
1172 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1173 status, 0, ident, 4,
1174 2, idp->data, idp->len,
1179 strlen(entry->userinfo) : 0);
1180 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1181 0, packet->data, packet->len, FALSE);
1183 silc_buffer_free(packet);
1184 silc_buffer_free(idp);
1191 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1193 SilcServer server = cmd->server;
1194 char *nick = NULL, *server_name = NULL;
1196 SilcClientEntry *clients = NULL;
1197 SilcUInt32 clients_count = 0;
1199 bool check_global = FALSE;
1201 /* Protocol dictates that we must always send the received WHOWAS request
1202 to our router if we are normal server, so let's do it now unless we
1203 are standalone. We will not send any replies to the client until we
1204 have received reply from the router. */
1205 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1206 server->server_type == SILC_SERVER && !cmd->pending &&
1207 !server->standalone) {
1209 SilcUInt16 old_ident;
1211 old_ident = silc_command_get_ident(cmd->payload);
1212 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1213 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1215 /* Send WHOWAS command to our router */
1216 silc_server_packet_send(server, (SilcSocketConnection)
1217 server->router->connection,
1218 SILC_PACKET_COMMAND, cmd->packet->flags,
1219 tmpbuf->data, tmpbuf->len, TRUE);
1221 /* Reprocess this packet after received reply from router */
1222 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1223 silc_command_get_ident(cmd->payload),
1224 silc_server_command_whowas,
1225 silc_server_command_dup(cmd));
1226 cmd->pending = TRUE;
1227 silc_command_set_ident(cmd->payload, old_ident);
1229 silc_buffer_free(tmpbuf);
1234 /* We are ready to process the command request. Let's search for the
1235 requested client and send reply to the requesting client. */
1237 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1238 check_global = TRUE;
1239 else if (server->server_type != SILC_SERVER)
1240 check_global = TRUE;
1242 /* Parse the whowas request */
1243 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1246 /* Get all clients matching that nickname from local list */
1247 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1249 &clients, &clients_count))
1250 silc_idlist_get_clients_by_hash(server->local_list,
1251 nick, server->md5hash,
1252 &clients, &clients_count);
1254 /* Check global list as well */
1256 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1258 &clients, &clients_count))
1259 silc_idlist_get_clients_by_hash(server->global_list,
1260 nick, server->md5hash,
1261 &clients, &clients_count);
1265 /* Such a client really does not exist in the SILC network. */
1266 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1267 SILC_STATUS_ERR_NO_SUCH_NICK,
1268 3, nick, strlen(nick));
1272 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1277 /* Send the command reply to the client */
1278 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1283 silc_free(server_name);
1287 /* Server side of command WHOWAS. */
1289 SILC_SERVER_CMD_FUNC(whowas)
1291 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1294 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1296 ret = silc_server_command_whowas_process(cmd);
1297 silc_server_command_free(cmd);
1300 /******************************************************************************
1304 ******************************************************************************/
1307 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1309 SilcServer server = cmd->server;
1311 SilcUInt16 old_ident;
1313 old_ident = silc_command_get_ident(cmd->payload);
1314 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1315 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1317 /* Send IDENTIFY command to our router */
1318 silc_server_packet_send(server, (SilcSocketConnection)
1319 server->router->connection,
1320 SILC_PACKET_COMMAND, cmd->packet->flags,
1321 tmpbuf->data, tmpbuf->len, TRUE);
1323 /* Reprocess this packet after received reply from router */
1324 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1325 silc_command_get_ident(cmd->payload),
1326 silc_server_command_identify,
1327 silc_server_command_dup(cmd));
1328 cmd->pending = TRUE;
1329 silc_command_set_ident(cmd->payload, old_ident);
1330 silc_buffer_free(tmpbuf);
1334 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1335 SilcClientEntry **clients,
1336 SilcUInt32 *clients_count,
1337 SilcServerEntry **servers,
1338 SilcUInt32 *servers_count,
1339 SilcChannelEntry **channels,
1340 SilcUInt32 *channels_count,
1343 SilcServer server = cmd->server;
1346 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1348 bool check_global = FALSE;
1353 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1354 check_global = TRUE;
1355 else if (server->server_type != SILC_SERVER)
1356 check_global = TRUE;
1358 /* If ID Payload is in the command it must be used instead of names */
1359 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1361 /* No ID, get the names. */
1363 /* If we are normal server and have not resolved information from
1364 router yet, do so now. */
1365 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1366 server->server_type == SILC_SERVER && !cmd->pending &&
1367 !server->standalone) {
1368 silc_server_command_identify_send_router(cmd);
1372 /* Try to get nickname@server. */
1373 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1376 char *nick_server = NULL;
1378 silc_parse_userfqdn(tmp, &nick, &nick_server);
1380 if (!silc_idlist_get_clients_by_hash(server->local_list,
1381 nick, server->md5hash,
1382 clients, clients_count))
1383 silc_idlist_get_clients_by_nickname(server->local_list,
1385 clients, clients_count);
1387 if (!silc_idlist_get_clients_by_hash(server->global_list,
1388 nick, server->md5hash,
1389 clients, clients_count))
1390 silc_idlist_get_clients_by_nickname(server->global_list,
1392 clients, clients_count);
1396 silc_free(nick_server);
1399 /* the nickname does not exist, send error reply */
1400 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1401 SILC_STATUS_ERR_NO_SUCH_NICK,
1402 3, tmp, strlen(tmp));
1407 /* Try to get server name */
1408 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1410 entry = silc_idlist_find_server_by_name(server->local_list,
1412 if (!entry && check_global)
1413 entry = silc_idlist_find_server_by_name(server->global_list,
1416 *servers = silc_realloc(*servers, sizeof(**servers) *
1417 (*servers_count + 1));
1418 (*servers)[(*servers_count)++] = entry;
1422 /* the server does not exist, send error reply */
1423 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1424 SILC_STATUS_ERR_NO_SUCH_SERVER,
1425 3, tmp, strlen(tmp));
1430 /* Try to get channel name */
1431 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1433 entry = silc_idlist_find_channel_by_name(server->local_list,
1435 if (!entry && check_global)
1436 entry = silc_idlist_find_channel_by_name(server->global_list,
1439 *channels = silc_realloc(*channels, sizeof(**channels) *
1440 (*channels_count + 1));
1441 (*channels)[(*channels_count)++] = entry;
1445 /* The channel does not exist, send error reply */
1446 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1447 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1448 3, tmp, strlen(tmp));
1453 if (!(*clients) && !(*servers) && !(*channels)) {
1454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1455 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1459 /* Command includes ID, we must use that. Also check whether the command
1460 has more than one ID set - take them all. */
1462 /* Take all ID's from the command packet */
1463 for (i = 0; i < argc; i++) {
1466 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1470 idp = silc_id_payload_parse(tmp, len);
1472 silc_free(*clients);
1473 silc_free(*servers);
1474 silc_free(*channels);
1475 silc_server_command_send_status_reply(
1476 cmd, SILC_COMMAND_IDENTIFY,
1477 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1481 id = silc_id_payload_get_id(idp);
1483 switch (silc_id_payload_get_type(idp)) {
1485 case SILC_ID_CLIENT:
1486 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1488 if (!entry && check_global)
1489 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1492 *clients = silc_realloc(*clients, sizeof(**clients) *
1493 (*clients_count + 1));
1494 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1496 /* If we are normal server and have not resolved information from
1497 router yet, do so now. */
1498 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1499 server->server_type == SILC_SERVER && !cmd->pending &&
1500 !server->standalone) {
1501 silc_server_command_identify_send_router(cmd);
1502 silc_free(*clients);
1503 silc_free(*servers);
1504 silc_free(*channels);
1507 silc_server_command_send_status_data(
1508 cmd, SILC_COMMAND_IDENTIFY,
1509 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1517 case SILC_ID_SERVER:
1518 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1520 if (!entry && check_global)
1521 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1524 *servers = silc_realloc(*servers, sizeof(**servers) *
1525 (*servers_count + 1));
1526 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1528 /* If we are normal server and have not resolved information from
1529 router yet, do so now. */
1530 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1531 server->server_type == SILC_SERVER && !cmd->pending &&
1532 !server->standalone) {
1533 silc_server_command_identify_send_router(cmd);
1534 silc_free(*clients);
1535 silc_free(*servers);
1536 silc_free(*channels);
1539 silc_server_command_send_status_data(
1540 cmd, SILC_COMMAND_IDENTIFY,
1541 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1548 case SILC_ID_CHANNEL:
1549 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1551 if (!entry && check_global)
1552 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1555 *channels = silc_realloc(*channels, sizeof(**channels) *
1556 (*channels_count + 1));
1557 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1559 /* If we are normal server and have not resolved information from
1560 router yet, do so now. */
1561 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1562 server->server_type == SILC_SERVER && !cmd->pending &&
1563 !server->standalone) {
1564 silc_server_command_identify_send_router(cmd);
1565 silc_free(*clients);
1566 silc_free(*servers);
1567 silc_free(*channels);
1570 silc_server_command_send_status_data(
1571 cmd, SILC_COMMAND_IDENTIFY,
1572 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1585 silc_free(*clients);
1586 silc_free(*servers);
1587 silc_free(*channels);
1591 /* Get the max count of reply messages allowed */
1592 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1594 SILC_GET32_MSB(*count, tmp);
1602 /* Checks that all mandatory fields in client entry are present. If not
1603 then send WHOIS request to the server who owns the client. We use
1604 WHOIS because we want to get as much information as possible at once. */
1607 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1608 SilcClientEntry *clients,
1609 SilcUInt32 clients_count)
1611 SilcServer server = cmd->server;
1612 SilcClientEntry entry;
1613 SilcServerResolveContext resolve = NULL, r = NULL;
1614 SilcUInt32 resolve_count = 0;
1618 for (i = 0; i < clients_count; i++) {
1623 if (entry->nickname ||
1624 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1628 /* If we are normal server, and we've not resolved this client from
1629 router and it is global client, we'll check whether it is on some
1630 channel. If not then we cannot be sure about its validity, and
1631 we'll resolve it from router. */
1632 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1633 entry->connection || silc_hash_table_count(entry->channels))
1637 /* We need to resolve this entry since it is not complete */
1639 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1640 /* The entry is being resolved (and we are not the resolver) so attach
1641 to the command reply and we're done with this one. */
1642 silc_server_command_pending(server, SILC_COMMAND_NONE,
1643 entry->resolve_cmd_ident,
1644 silc_server_command_identify,
1645 silc_server_command_dup(cmd));
1648 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1649 /* We've resolved this and it still is not ready. We'll return
1650 and are that this will be handled again after it is resolved. */
1651 for (i = 0; i < resolve_count; i++) {
1652 for (k = 0; k < r->res_argc; k++)
1653 silc_free(r->res_argv[k]);
1654 silc_free(r->res_argv);
1655 silc_free(r->res_argv_lens);
1656 silc_free(r->res_argv_types);
1661 /* We'll resolve this client */
1665 for (k = 0; k < resolve_count; k++) {
1666 if (resolve[k].router == entry->router) {
1673 resolve = silc_realloc(resolve, sizeof(*resolve) *
1674 (resolve_count + 1));
1675 r = &resolve[resolve_count];
1676 memset(r, 0, sizeof(*r));
1677 r->router = entry->router;
1678 r->ident = ++server->cmd_ident;
1682 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1684 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1685 sizeof(*r->res_argv_lens) *
1687 r->res_argv_types = silc_realloc(r->res_argv_types,
1688 sizeof(*r->res_argv_types) *
1690 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1691 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1692 sizeof(**r->res_argv));
1693 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1694 r->res_argv_lens[r->res_argc] = idp->len;
1695 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1697 silc_buffer_free(idp);
1699 entry->resolve_cmd_ident = r->ident;
1700 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1701 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1706 /* Do the resolving */
1707 for (i = 0; i < resolve_count; i++) {
1712 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1713 now anyway so make it a good one. */
1714 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1715 r->res_argc, r->res_argv,
1719 silc_server_packet_send(server, r->router->connection,
1720 SILC_PACKET_COMMAND, cmd->packet->flags,
1721 res_cmd->data, res_cmd->len, FALSE);
1723 /* Reprocess this packet after received reply */
1724 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1726 silc_server_command_identify,
1727 silc_server_command_dup(cmd));
1728 cmd->pending = TRUE;
1730 silc_buffer_free(res_cmd);
1731 for (k = 0; k < r->res_argc; k++)
1732 silc_free(r->res_argv[k]);
1733 silc_free(r->res_argv);
1734 silc_free(r->res_argv_lens);
1735 silc_free(r->res_argv_types);
1744 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1745 SilcClientEntry *clients,
1746 SilcUInt32 clients_count,
1747 SilcServerEntry *servers,
1748 SilcUInt32 servers_count,
1749 SilcChannelEntry *channels,
1750 SilcUInt32 channels_count,
1753 SilcServer server = cmd->server;
1754 int i, k, len, valid_count;
1755 SilcBuffer packet, idp;
1757 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1758 char nh[256], uh[256];
1759 SilcSocketConnection hsock;
1761 status = SILC_STATUS_OK;
1764 SilcClientEntry entry;
1766 /* Process only valid entries. */
1768 for (i = 0; i < clients_count; i++) {
1769 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1776 /* No valid entries found at all, just send error */
1779 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1781 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1782 SILC_STATUS_ERR_NO_SUCH_NICK,
1783 3, tmp, strlen(tmp));
1785 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1786 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1787 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1793 /* Process all valid client entries and send command replies */
1795 if (valid_count > 1)
1796 status = SILC_STATUS_LIST_START;
1798 for (i = 0, k = 0; i < clients_count; i++) {
1804 status = SILC_STATUS_LIST_ITEM;
1805 if (valid_count > 1 && k == valid_count - 1
1806 && !servers_count && !channels_count)
1807 status = SILC_STATUS_LIST_END;
1808 if (count && k - 1 == count)
1809 status = SILC_STATUS_LIST_END;
1810 if (count && k - 1 > count)
1813 /* Send IDENTIFY reply */
1815 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1816 memset(uh, 0, sizeof(uh));
1817 memset(nh, 0, sizeof(nh));
1818 strncat(nh, entry->nickname, strlen(entry->nickname));
1819 if (!strchr(entry->nickname, '@')) {
1820 strncat(nh, "@", 1);
1821 if (entry->servername) {
1822 strncat(nh, entry->servername, strlen(entry->servername));
1824 len = entry->router ? strlen(entry->router->server_name) :
1825 strlen(server->server_name);
1826 strncat(nh, entry->router ? entry->router->server_name :
1827 server->server_name, len);
1831 if (!entry->username) {
1832 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1833 status, 0, ident, 2,
1834 2, idp->data, idp->len,
1837 strncat(uh, entry->username, strlen(entry->username));
1838 if (!strchr(entry->username, '@') && entry->connection) {
1839 strncat(uh, "@", 1);
1840 hsock = (SilcSocketConnection)entry->connection;
1841 len = strlen(hsock->hostname);
1842 strncat(uh, hsock->hostname, len);
1845 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1846 status, 0, ident, 3,
1847 2, idp->data, idp->len,
1852 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1853 0, packet->data, packet->len, FALSE);
1855 silc_buffer_free(packet);
1856 silc_buffer_free(idp);
1863 SilcServerEntry entry;
1865 if (status == SILC_STATUS_OK && servers_count > 1)
1866 status = SILC_STATUS_LIST_START;
1868 for (i = 0, k = 0; i < servers_count; i++) {
1872 status = SILC_STATUS_LIST_ITEM;
1873 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1874 status = SILC_STATUS_LIST_END;
1875 if (count && k - 1 == count)
1876 status = SILC_STATUS_LIST_END;
1877 if (count && k - 1 > count)
1880 /* Send IDENTIFY reply */
1881 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1883 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1884 status, 0, ident, 2,
1885 2, idp->data, idp->len,
1886 3, entry->server_name,
1887 entry->server_name ?
1888 strlen(entry->server_name) : 0);
1889 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1890 0, packet->data, packet->len, FALSE);
1892 silc_buffer_free(packet);
1893 silc_buffer_free(idp);
1900 SilcChannelEntry entry;
1902 if (status == SILC_STATUS_OK && channels_count > 1)
1903 status = SILC_STATUS_LIST_START;
1905 for (i = 0, k = 0; i < channels_count; i++) {
1906 entry = channels[i];
1909 status = SILC_STATUS_LIST_ITEM;
1910 if (channels_count > 1 && k == channels_count - 1)
1911 status = SILC_STATUS_LIST_END;
1912 if (count && k - 1 == count)
1913 status = SILC_STATUS_LIST_END;
1914 if (count && k - 1 > count)
1917 /* Send IDENTIFY reply */
1918 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1920 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1921 status, 0, ident, 2,
1922 2, idp->data, idp->len,
1923 3, entry->channel_name,
1924 entry->channel_name ?
1925 strlen(entry->channel_name): 0);
1926 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1927 0, packet->data, packet->len, FALSE);
1929 silc_buffer_free(packet);
1930 silc_buffer_free(idp);
1938 silc_server_command_identify_process(SilcServerCommandContext cmd)
1940 SilcUInt32 count = 0;
1942 SilcClientEntry *clients = NULL;
1943 SilcServerEntry *servers = NULL;
1944 SilcChannelEntry *channels = NULL;
1945 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1947 /* Parse the IDENTIFY request */
1948 ret = silc_server_command_identify_parse(cmd,
1949 &clients, &clients_count,
1950 &servers, &servers_count,
1951 &channels, &channels_count,
1957 /* Check that all mandatory fields are present and request those data
1958 from the server who owns the client if necessary. */
1959 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1965 /* Send the command reply to the client */
1966 silc_server_command_identify_send_reply(cmd,
1967 clients, clients_count,
1968 servers, servers_count,
1969 channels, channels_count,
1975 silc_free(channels);
1979 SILC_SERVER_CMD_FUNC(identify)
1981 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1984 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1986 ret = silc_server_command_identify_process(cmd);
1987 silc_server_command_free(cmd);
1990 /* Server side of command NICK. Sets nickname for user. Setting
1991 nickname causes generation of a new client ID for the client. The
1992 new client ID is sent to the client after changing the nickname. */
1994 SILC_SERVER_CMD_FUNC(nick)
1996 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1997 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1998 SilcServer server = cmd->server;
1999 SilcBuffer packet, nidp, oidp = NULL;
2000 SilcClientID *new_id;
2001 SilcUInt32 nick_len;
2003 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2006 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2009 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2011 /* Check nickname */
2012 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2015 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2017 SILC_STATUS_ERR_BAD_NICKNAME);
2021 /* Check for same nickname */
2022 if (!strcmp(client->nickname, nick)) {
2023 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2027 /* Create new Client ID */
2028 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2030 cmd->server->md5hash, nick,
2034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2035 SILC_STATUS_ERR_BAD_NICKNAME);
2038 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2041 /* Send notify about nickname change to our router. We send the new
2042 ID and ask to replace it with the old one. If we are router the
2043 packet is broadcasted. Send NICK_CHANGE notify. */
2044 if (!server->standalone)
2045 silc_server_send_notify_nick_change(server, server->router->connection,
2046 server->server_type == SILC_SERVER ?
2047 FALSE : TRUE, client->id,
2050 /* Check if anyone is watching the old nickname */
2051 if (server->server_type == SILC_ROUTER)
2052 silc_server_check_watcher_list(server, client, nick,
2053 SILC_NOTIFY_TYPE_NICK_CHANGE);
2055 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2057 /* Remove old cache entry */
2058 silc_idcache_del_by_context(server->local_list->clients, client);
2060 silc_free(client->id);
2061 client->id = new_id;
2063 silc_free(client->nickname);
2064 client->nickname = strdup(nick);
2066 /* Update client cache */
2067 silc_idcache_add(server->local_list->clients, client->nickname,
2068 client->id, (void *)client, 0, NULL);
2070 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2072 /* Send NICK_CHANGE notify to the client's channels */
2073 silc_server_send_notify_on_channels(server, NULL, client,
2074 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2075 oidp->data, oidp->len,
2076 nidp->data, nidp->len,
2078 strlen(client->nickname));
2080 /* Check if anyone is watching the new nickname */
2081 if (server->server_type == SILC_ROUTER)
2082 silc_server_check_watcher_list(server, client, NULL,
2083 SILC_NOTIFY_TYPE_NICK_CHANGE);
2086 /* Send the new Client ID as reply command back to client */
2087 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2088 SILC_STATUS_OK, 0, ident, 1,
2089 2, nidp->data, nidp->len);
2090 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2091 0, packet->data, packet->len, FALSE);
2093 silc_buffer_free(packet);
2094 silc_buffer_free(nidp);
2096 silc_buffer_free(oidp);
2099 silc_server_command_free(cmd);
2102 /* Sends the LIST command reply */
2105 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2106 SilcChannelEntry *lch,
2107 SilcUInt32 lch_count,
2108 SilcChannelEntry *gch,
2109 SilcUInt32 gch_count)
2112 SilcBuffer packet, idp;
2113 SilcChannelEntry entry;
2115 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2117 unsigned char usercount[4];
2119 int valid_lcount = 0, valid_rcount = 0;
2121 for (i = 0; i < lch_count; i++) {
2122 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2127 for (i = 0; i < gch_count; i++) {
2128 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2134 status = SILC_STATUS_OK;
2135 if ((lch_count + gch_count) > 1)
2136 status = SILC_STATUS_LIST_START;
2139 for (i = 0, k = 0; i < lch_count; i++) {
2145 status = SILC_STATUS_LIST_ITEM;
2146 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2147 status = SILC_STATUS_LIST_END;
2149 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2151 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2152 topic = "*private*";
2153 memset(usercount, 0, sizeof(usercount));
2155 topic = entry->topic;
2156 users = silc_hash_table_count(entry->user_list);
2157 SILC_PUT32_MSB(users, usercount);
2160 /* Send the reply */
2162 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2163 status, 0, ident, 4,
2164 2, idp->data, idp->len,
2165 3, entry->channel_name,
2166 strlen(entry->channel_name),
2167 4, topic, topic ? strlen(topic) : 0,
2169 silc_server_packet_send(cmd->server, cmd->sock,
2170 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2171 packet->len, FALSE);
2172 silc_buffer_free(packet);
2173 silc_buffer_free(idp);
2178 for (i = 0, k = 0; i < gch_count; i++) {
2184 status = SILC_STATUS_LIST_ITEM;
2185 if (valid_rcount > 1 && k == valid_rcount - 1)
2186 status = SILC_STATUS_LIST_END;
2188 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2190 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2191 topic = "*private*";
2192 memset(usercount, 0, sizeof(usercount));
2194 topic = entry->topic;
2195 users = entry->user_count;
2196 SILC_PUT32_MSB(users, usercount);
2199 /* Send the reply */
2201 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2202 status, 0, ident, 4,
2203 2, idp->data, idp->len,
2204 3, entry->channel_name,
2205 strlen(entry->channel_name),
2206 4, topic, topic ? strlen(topic) : 0,
2208 silc_server_packet_send(cmd->server, cmd->sock,
2209 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2210 packet->len, FALSE);
2211 silc_buffer_free(packet);
2212 silc_buffer_free(idp);
2217 /* Server side of LIST command. This lists the channel of the requested
2218 server. Secret channels are not listed. */
2220 SILC_SERVER_CMD_FUNC(list)
2222 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2223 SilcServer server = cmd->server;
2224 SilcChannelID *channel_id = NULL;
2227 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2228 SilcUInt32 lch_count = 0, gch_count = 0;
2230 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2232 /* If we are normal server, send the command to router, since we
2233 want to know all channels in the network. */
2234 if (!cmd->pending && server->server_type == SILC_SERVER &&
2235 !server->standalone) {
2237 SilcUInt16 old_ident;
2239 old_ident = silc_command_get_ident(cmd->payload);
2240 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2241 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2242 silc_server_packet_send(server, server->router->connection,
2243 SILC_PACKET_COMMAND, cmd->packet->flags,
2244 tmpbuf->data, tmpbuf->len, TRUE);
2246 /* Reprocess this packet after received reply from router */
2247 silc_server_command_pending(server, SILC_COMMAND_LIST,
2248 silc_command_get_ident(cmd->payload),
2249 silc_server_command_list,
2250 silc_server_command_dup(cmd));
2251 cmd->pending = TRUE;
2252 silc_command_set_ident(cmd->payload, old_ident);
2253 silc_buffer_free(tmpbuf);
2257 /* Get Channel ID */
2258 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2260 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2263 SILC_STATUS_ERR_NO_CHANNEL_ID);
2268 /* Get the channels from local list */
2269 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2272 /* Get the channels from global list */
2273 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2276 /* Send the reply */
2277 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2278 gchannels, gch_count);
2280 silc_free(lchannels);
2281 silc_free(gchannels);
2284 silc_server_command_free(cmd);
2287 /* Server side of TOPIC command. Sets topic for channel and/or returns
2288 current topic to client. */
2290 SILC_SERVER_CMD_FUNC(topic)
2292 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2293 SilcServer server = cmd->server;
2294 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2295 SilcChannelID *channel_id;
2296 SilcChannelEntry channel;
2297 SilcChannelClientEntry chl;
2298 SilcBuffer packet, idp;
2300 SilcUInt32 argc, tmp_len;
2301 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2303 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2305 argc = silc_argument_get_arg_num(cmd->args);
2307 /* Get Channel ID */
2308 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2311 SILC_STATUS_ERR_NO_CHANNEL_ID);
2314 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2317 SILC_STATUS_ERR_NO_CHANNEL_ID);
2321 /* Check whether the channel exists */
2322 channel = silc_idlist_find_channel_by_id(server->local_list,
2325 channel = silc_idlist_find_channel_by_id(server->global_list,
2328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2329 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2336 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2339 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2343 if (strlen(tmp) > 256) {
2344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2345 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2349 /* See whether the client is on channel and has rights to change topic */
2350 if (!silc_server_client_on_channel(client, channel, &chl)) {
2351 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2352 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2356 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2357 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2358 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2360 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2364 /* Set the topic for channel */
2365 silc_free(channel->topic);
2366 channel->topic = strdup(tmp);
2368 /* Send TOPIC_SET notify type to the network */
2369 if (!server->standalone)
2370 silc_server_send_notify_topic_set(server, server->router->connection,
2371 server->server_type == SILC_ROUTER ?
2372 TRUE : FALSE, channel,
2373 client->id, SILC_ID_CLIENT,
2376 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2378 /* Send notify about topic change to all clients on the channel */
2379 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2380 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2381 idp->data, idp->len,
2382 channel->topic, strlen(channel->topic));
2383 silc_buffer_free(idp);
2386 /* Send the topic to client as reply packet */
2387 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2388 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2389 SILC_STATUS_OK, 0, ident, 2,
2390 2, idp->data, idp->len,
2393 strlen(channel->topic) : 0);
2394 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2395 0, packet->data, packet->len, FALSE);
2397 silc_buffer_free(packet);
2398 silc_buffer_free(idp);
2399 silc_free(channel_id);
2402 silc_server_command_free(cmd);
2405 /* Server side of INVITE command. Invites some client to join some channel.
2406 This command is also used to manage the invite list of the channel. */
2408 SILC_SERVER_CMD_FUNC(invite)
2410 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2411 SilcServer server = cmd->server;
2412 SilcSocketConnection sock = cmd->sock, dest_sock;
2413 SilcChannelClientEntry chl;
2414 SilcClientEntry sender, dest;
2415 SilcClientID *dest_id = NULL;
2416 SilcChannelEntry channel;
2417 SilcChannelID *channel_id = NULL;
2418 SilcIDListData idata;
2419 SilcBuffer idp, idp2, packet;
2420 unsigned char *tmp, *add, *del;
2422 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2424 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2426 /* Get Channel ID */
2427 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2430 SILC_STATUS_ERR_NO_CHANNEL_ID);
2433 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2436 SILC_STATUS_ERR_NO_CHANNEL_ID);
2440 /* Get the channel entry */
2441 channel = silc_idlist_find_channel_by_id(server->local_list,
2444 channel = silc_idlist_find_channel_by_id(server->global_list,
2447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2448 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2453 /* Check whether the sender of this command is on the channel. */
2454 sender = (SilcClientEntry)sock->user_data;
2455 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2457 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2461 /* Check whether the channel is invite-only channel. If yes then the
2462 sender of this command must be at least channel operator. */
2463 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2464 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2465 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2467 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2471 /* Get destination client ID */
2472 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2477 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2480 SILC_STATUS_ERR_NO_CLIENT_ID);
2484 /* Get the client entry */
2485 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2487 if (server->server_type != SILC_SERVER || !resolve) {
2488 silc_server_command_send_status_reply(
2489 cmd, SILC_COMMAND_INVITE,
2490 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2494 /* The client info is being resolved. Reprocess this packet after
2495 receiving the reply to the query. */
2496 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2498 silc_server_command_invite,
2499 silc_server_command_dup(cmd));
2500 cmd->pending = TRUE;
2501 silc_free(channel_id);
2506 /* Check whether the requested client is already on the channel. */
2507 if (silc_server_client_on_channel(dest, channel, NULL)) {
2508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2509 SILC_STATUS_ERR_USER_ON_CHANNEL);
2513 /* Get route to the client */
2514 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2518 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2522 memset(invite, 0, sizeof(invite));
2523 strncat(invite, dest->nickname, strlen(dest->nickname));
2524 strncat(invite, "!", 1);
2525 strncat(invite, dest->username, strlen(dest->username));
2526 if (!strchr(dest->username, '@')) {
2527 strncat(invite, "@", 1);
2528 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2531 len = strlen(invite);
2532 if (!channel->invite_list)
2533 channel->invite_list = silc_calloc(len + 2,
2534 sizeof(*channel->invite_list));
2536 channel->invite_list = silc_realloc(channel->invite_list,
2537 sizeof(*channel->invite_list) *
2539 strlen(channel->invite_list) + 2));
2540 strncat(channel->invite_list, invite, len);
2541 strncat(channel->invite_list, ",", 1);
2543 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2544 /* Send notify to the client that is invited to the channel */
2545 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2546 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2547 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2549 SILC_NOTIFY_TYPE_INVITE, 3,
2550 idp->data, idp->len,
2551 channel->channel_name,
2552 strlen(channel->channel_name),
2553 idp2->data, idp2->len);
2554 silc_buffer_free(idp);
2555 silc_buffer_free(idp2);
2559 /* Add the client to the invite list of the channel */
2560 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2562 if (!channel->invite_list)
2563 channel->invite_list = silc_calloc(len + 2,
2564 sizeof(*channel->invite_list));
2566 channel->invite_list = silc_realloc(channel->invite_list,
2567 sizeof(*channel->invite_list) *
2569 strlen(channel->invite_list) + 2));
2570 if (add[len - 1] == ',')
2571 add[len - 1] = '\0';
2573 strncat(channel->invite_list, add, len);
2574 strncat(channel->invite_list, ",", 1);
2577 /* Get the invite to be removed and remove it from the list */
2578 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2579 if (del && channel->invite_list) {
2580 char *start, *end, *n;
2582 if (!strncmp(channel->invite_list, del,
2583 strlen(channel->invite_list) - 1)) {
2584 silc_free(channel->invite_list);
2585 channel->invite_list = NULL;
2587 start = strstr(channel->invite_list, del);
2588 if (start && strlen(start) >= len) {
2590 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2591 strncat(n, channel->invite_list, start - channel->invite_list);
2592 strncat(n, end + 1, ((channel->invite_list +
2593 strlen(channel->invite_list)) - end) - 1);
2594 silc_free(channel->invite_list);
2595 channel->invite_list = n;
2600 /* Send notify to the primary router */
2601 if (!server->standalone)
2602 silc_server_send_notify_invite(server, server->router->connection,
2603 server->server_type == SILC_ROUTER ?
2604 TRUE : FALSE, channel,
2605 sender->id, add, del);
2607 /* Send command reply */
2608 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2612 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2613 SILC_STATUS_OK, 0, ident, 2,
2615 3, channel->invite_list,
2616 channel->invite_list ?
2617 strlen(channel->invite_list) : 0);
2620 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2621 SILC_STATUS_OK, 0, ident, 1,
2623 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2624 packet->data, packet->len, FALSE);
2625 silc_buffer_free(packet);
2629 silc_free(channel_id);
2630 silc_server_command_free(cmd);
2635 SilcSocketConnection sock;
2639 /* Quits connection to client. This gets called if client won't
2640 close the connection even when it has issued QUIT command. */
2642 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2644 QuitInternal q = (QuitInternal)context;
2646 /* Free all client specific data, such as client entry and entires
2647 on channels this client may be on. */
2648 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2650 q->sock->user_data = NULL;
2652 /* Close the connection on our side */
2653 silc_server_close_connection(q->server, q->sock);
2655 silc_free(q->signoff);
2659 /* Quits SILC session. This is the normal way to disconnect client. */
2661 SILC_SERVER_CMD_FUNC(quit)
2663 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2664 SilcServer server = cmd->server;
2665 SilcSocketConnection sock = cmd->sock;
2667 unsigned char *tmp = NULL;
2670 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2672 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2676 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2680 q = silc_calloc(1, sizeof(*q));
2683 q->signoff = tmp ? strdup(tmp) : NULL;
2685 /* We quit the connection with little timeout */
2686 silc_schedule_task_add(server->schedule, sock->sock,
2687 silc_server_command_quit_cb, (void *)q,
2688 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2691 silc_server_command_free(cmd);
2694 /* Server side of command KILL. This command is used by router operator
2695 to remove an client from the SILC Network temporarily. */
2697 SILC_SERVER_CMD_FUNC(kill)
2699 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2700 SilcServer server = cmd->server;
2701 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2702 SilcClientEntry remote_client;
2703 SilcClientID *client_id;
2704 unsigned char *tmp, *comment;
2705 SilcUInt32 tmp_len, tmp_len2;
2708 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2710 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2713 /* KILL command works only on router */
2714 if (server->server_type != SILC_ROUTER) {
2715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2716 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2720 /* Check whether client has the permissions. */
2721 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2722 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2723 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2727 /* Get the client ID */
2728 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2731 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2734 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2737 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2741 /* Get the client entry */
2742 remote_client = silc_idlist_find_client_by_id(server->local_list,
2743 client_id, TRUE, NULL);
2745 if (!remote_client) {
2746 remote_client = silc_idlist_find_client_by_id(server->global_list,
2747 client_id, TRUE, NULL);
2749 if (!remote_client) {
2750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2751 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2757 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2761 /* Send reply to the sender */
2762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2765 /* Check if anyone is watching this nickname */
2766 if (server->server_type == SILC_ROUTER)
2767 silc_server_check_watcher_list(server, client, NULL,
2768 SILC_NOTIFY_TYPE_KILLED);
2770 /* Now do the killing */
2771 silc_server_kill_client(server, remote_client, comment, client->id,
2775 silc_server_command_free(cmd);
2778 /* Server side of command INFO. This sends information about us to
2779 the client. If client requested specific server we will send the
2780 command to that server. */
2782 SILC_SERVER_CMD_FUNC(info)
2784 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2785 SilcServer server = cmd->server;
2786 SilcBuffer packet, idp;
2789 char *dest_server, *server_info = NULL, *server_name;
2790 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2791 SilcServerEntry entry = NULL;
2792 SilcServerID *server_id = NULL;
2794 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2796 /* Get server name */
2797 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2800 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2802 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2805 SILC_STATUS_ERR_NO_SERVER_ID);
2811 /* Check whether we have this server cached */
2812 entry = silc_idlist_find_server_by_id(server->local_list,
2813 server_id, TRUE, NULL);
2815 entry = silc_idlist_find_server_by_id(server->global_list,
2816 server_id, TRUE, NULL);
2817 if (!entry && server->server_type != SILC_SERVER) {
2818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2819 SILC_STATUS_ERR_NO_SUCH_SERVER);
2825 /* Some buggy servers has sent request to router about themselves. */
2826 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2829 if ((!dest_server && !server_id && !entry) || (entry &&
2830 entry == server->id_entry) ||
2831 (dest_server && !cmd->pending &&
2832 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2833 /* Send our reply */
2834 char info_string[256];
2836 memset(info_string, 0, sizeof(info_string));
2837 snprintf(info_string, sizeof(info_string),
2838 "location: %s server: %s admin: %s <%s>",
2839 server->config->server_info->location,
2840 server->config->server_info->server_type,
2841 server->config->server_info->admin,
2842 server->config->server_info->email);
2844 server_info = info_string;
2845 entry = server->id_entry;
2847 /* Check whether we have this server cached */
2848 if (!entry && dest_server) {
2849 entry = silc_idlist_find_server_by_name(server->global_list,
2850 dest_server, TRUE, NULL);
2852 entry = silc_idlist_find_server_by_name(server->local_list,
2853 dest_server, TRUE, NULL);
2857 if (!cmd->pending &&
2858 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2859 /* Send to the server */
2861 SilcUInt16 old_ident;
2863 old_ident = silc_command_get_ident(cmd->payload);
2864 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2865 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2867 silc_server_packet_send(server, entry->connection,
2868 SILC_PACKET_COMMAND, cmd->packet->flags,
2869 tmpbuf->data, tmpbuf->len, TRUE);
2871 /* Reprocess this packet after received reply from router */
2872 silc_server_command_pending(server, SILC_COMMAND_INFO,
2873 silc_command_get_ident(cmd->payload),
2874 silc_server_command_info,
2875 silc_server_command_dup(cmd));
2876 cmd->pending = TRUE;
2877 silc_command_set_ident(cmd->payload, old_ident);
2878 silc_buffer_free(tmpbuf);
2882 if (!entry && !cmd->pending && !server->standalone) {
2883 /* Send to the primary router */
2885 SilcUInt16 old_ident;
2887 old_ident = silc_command_get_ident(cmd->payload);
2888 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2889 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2891 silc_server_packet_send(server, server->router->connection,
2892 SILC_PACKET_COMMAND, cmd->packet->flags,
2893 tmpbuf->data, tmpbuf->len, TRUE);
2895 /* Reprocess this packet after received reply from router */
2896 silc_server_command_pending(server, SILC_COMMAND_INFO,
2897 silc_command_get_ident(cmd->payload),
2898 silc_server_command_info,
2899 silc_server_command_dup(cmd));
2900 cmd->pending = TRUE;
2901 silc_command_set_ident(cmd->payload, old_ident);
2902 silc_buffer_free(tmpbuf);
2907 silc_free(server_id);
2910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2911 SILC_STATUS_ERR_NO_SUCH_SERVER);
2915 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2917 server_info = entry->server_info;
2918 server_name = entry->server_name;
2920 /* Send the reply */
2921 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2922 SILC_STATUS_OK, 0, ident, 3,
2923 2, idp->data, idp->len,
2925 strlen(server_name),
2928 strlen(server_info) : 0);
2929 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2930 packet->data, packet->len, FALSE);
2932 silc_buffer_free(packet);
2933 silc_buffer_free(idp);
2936 silc_server_command_free(cmd);
2939 /* Server side of command PING. This just replies to the ping. */
2941 SILC_SERVER_CMD_FUNC(ping)
2943 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2944 SilcServer server = cmd->server;
2949 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2952 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2955 SILC_STATUS_ERR_NO_SERVER_ID);
2958 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2962 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2963 /* Send our reply */
2964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2968 SILC_STATUS_ERR_NO_SUCH_SERVER);
2975 silc_server_command_free(cmd);
2978 /* Server side of command STATS. */
2980 SILC_SERVER_CMD_FUNC(stats)
2982 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2983 SilcServer server = cmd->server;
2984 SilcServerID *server_id;
2987 SilcBuffer packet, stats;
2988 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2991 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
2994 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2997 SILC_STATUS_ERR_NO_SERVER_ID);
3000 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3004 /* The ID must be ours */
3005 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3006 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3007 SILC_STATUS_ERR_NO_SUCH_SERVER);
3008 silc_free(server_id);
3011 silc_free(server_id);
3013 /* If we are router then just send everything we got. If we are normal
3014 server then we'll send this to our router to get all the latest
3015 statistical information. */
3016 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3017 !server->standalone) {
3018 /* Send request to our router */
3019 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3021 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3022 ++server->cmd_ident, 1,
3023 1, idp->data, idp->len);
3024 silc_server_packet_send(server, server->router->connection,
3025 SILC_PACKET_COMMAND, 0, packet->data,
3026 packet->len, FALSE);
3028 /* Reprocess this packet after received reply from router */
3029 silc_server_command_pending(server, SILC_COMMAND_STATS,
3031 silc_server_command_stats,
3032 silc_server_command_dup(cmd));
3033 cmd->pending = TRUE;
3034 silc_buffer_free(packet);
3035 silc_buffer_free(idp);
3039 /* Send our reply to sender */
3040 uptime = time(NULL) - server->starttime;
3042 stats = silc_buffer_alloc_size(60);
3043 silc_buffer_format(stats,
3044 SILC_STR_UI_INT(server->starttime),
3045 SILC_STR_UI_INT(uptime),
3046 SILC_STR_UI_INT(server->stat.my_clients),
3047 SILC_STR_UI_INT(server->stat.my_channels),
3048 SILC_STR_UI_INT(server->stat.my_server_ops),
3049 SILC_STR_UI_INT(server->stat.my_router_ops),
3050 SILC_STR_UI_INT(server->stat.cell_clients),
3051 SILC_STR_UI_INT(server->stat.cell_channels),
3052 SILC_STR_UI_INT(server->stat.cell_servers),
3053 SILC_STR_UI_INT(server->stat.clients),
3054 SILC_STR_UI_INT(server->stat.channels),
3055 SILC_STR_UI_INT(server->stat.servers),
3056 SILC_STR_UI_INT(server->stat.routers),
3057 SILC_STR_UI_INT(server->stat.server_ops),
3058 SILC_STR_UI_INT(server->stat.router_ops),
3061 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3062 SILC_STATUS_OK, 0, ident, 2,
3064 3, stats->data, stats->len);
3065 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3066 0, packet->data, packet->len, FALSE);
3067 silc_buffer_free(packet);
3068 silc_buffer_free(stats);
3071 silc_server_command_free(cmd);
3074 /* Internal routine to join channel. The channel sent to this function
3075 has been either created or resolved from ID lists. This joins the sent
3076 client to the channel. */
3078 static void silc_server_command_join_channel(SilcServer server,
3079 SilcServerCommandContext cmd,
3080 SilcChannelEntry channel,
3081 SilcClientID *client_id,
3085 const unsigned char *auth,
3086 SilcUInt32 auth_len)
3088 SilcSocketConnection sock = cmd->sock;
3090 SilcUInt32 tmp_len, user_count;
3091 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3092 SilcClientEntry client;
3093 SilcChannelClientEntry chl;
3094 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3095 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3096 char check[512], check2[512];
3097 bool founder = FALSE;
3100 SILC_LOG_DEBUG(("Start"));
3105 /* Get the client entry */
3106 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3107 client = (SilcClientEntry)sock->user_data;
3109 client = silc_server_get_client_resolve(server, client_id, FALSE,
3116 silc_server_command_send_status_reply(
3117 cmd, SILC_COMMAND_JOIN,
3118 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3122 /* The client info is being resolved. Reprocess this packet after
3123 receiving the reply to the query. */
3124 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3126 silc_server_command_join,
3127 silc_server_command_dup(cmd));
3128 cmd->pending = TRUE;
3132 cmd->pending = FALSE;
3136 * Check founder auth payload if provided. If client can gain founder
3137 * privileges it can override various conditions on joining the channel,
3138 * and can have directly the founder mode set on the channel.
3140 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3141 SilcIDListData idata = (SilcIDListData)client;
3143 if (channel->founder_key && idata->public_key &&
3144 silc_pkcs_public_key_compare(channel->founder_key,
3145 idata->public_key)) {
3146 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3147 (void *)channel->founder_passwd :
3148 (void *)channel->founder_key);
3149 SilcUInt32 auth_data_len =
3150 (channel->founder_method == SILC_AUTH_PASSWORD ?
3151 channel->founder_passwd_len : 0);
3153 /* Check whether the client is to become founder */
3154 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3155 auth_data, auth_data_len,
3156 idata->hash, client->id, SILC_ID_CLIENT)) {
3157 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3164 * Check channel modes
3168 memset(check, 0, sizeof(check));
3169 memset(check2, 0, sizeof(check2));
3170 strncat(check, client->nickname, strlen(client->nickname));
3171 strncat(check, "!", 1);
3172 strncat(check, client->username, strlen(client->username));
3173 if (!strchr(client->username, '@')) {
3174 strncat(check, "@", 1);
3175 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3178 strncat(check2, client->nickname, strlen(client->nickname));
3179 if (!strchr(client->nickname, '@')) {
3180 strncat(check2, "@", 1);
3181 strncat(check2, server->server_name, strlen(server->server_name));
3183 strncat(check2, "!", 1);
3184 strncat(check2, client->username, strlen(client->username));
3185 if (!strchr(client->username, '@')) {
3186 strncat(check2, "@", 1);
3187 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3190 /* Check invite list if channel is invite-only channel */
3191 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3192 if (!channel->invite_list ||
3193 (!silc_string_match(channel->invite_list, check) &&
3194 !silc_string_match(channel->invite_list, check2))) {
3195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3196 SILC_STATUS_ERR_NOT_INVITED);
3201 /* Check ban list if it exists. If the client's nickname, server,
3202 username and/or hostname is in the ban list the access to the
3203 channel is denied. */
3204 if (channel->ban_list) {
3205 if (silc_string_match(channel->ban_list, check) ||
3206 silc_string_match(channel->ban_list, check2)) {
3207 silc_server_command_send_status_reply(
3208 cmd, SILC_COMMAND_JOIN,
3209 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3214 /* Check user count limit if set. */
3215 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3216 if (silc_hash_table_count(channel->user_list) + 1 >
3217 channel->user_limit) {
3218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3219 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3225 /* Check the channel passphrase if set. */
3226 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3227 /* Get passphrase */
3228 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3230 passphrase = silc_memdup(tmp, tmp_len);
3232 if (!passphrase || !channel->passphrase ||
3233 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3234 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3235 SILC_STATUS_ERR_BAD_PASSWORD);
3241 * Client is allowed to join to the channel. Make it happen.
3244 /* Check whether the client already is on the channel */
3245 if (silc_server_client_on_channel(client, channel, NULL)) {
3246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3247 SILC_STATUS_ERR_USER_ON_CHANNEL);
3251 /* Generate new channel key as protocol dictates */
3253 if (!silc_server_create_channel_key(server, channel, 0))
3256 /* Send the channel key. This is broadcasted to the channel but is not
3257 sent to the client who is joining to the channel. */
3258 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3259 silc_server_send_channel_key(server, NULL, channel,
3260 server->server_type == SILC_ROUTER ?
3261 FALSE : !server->standalone);
3264 /* Join the client to the channel by adding it to channel's user list.
3265 Add also the channel to client entry's channels list for fast cross-
3267 chl = silc_calloc(1, sizeof(*chl));
3269 chl->client = client;
3270 chl->channel = channel;
3271 silc_hash_table_add(channel->user_list, client, chl);
3272 silc_hash_table_add(client->channels, channel, chl);
3273 channel->user_count++;
3275 /* Get users on the channel */
3276 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3279 /* Encode Client ID Payload of the original client who wants to join */
3280 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3282 /* Encode command reply packet */
3283 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3284 SILC_PUT32_MSB(channel->mode, mode);
3285 SILC_PUT32_MSB(created, tmp2);
3286 SILC_PUT32_MSB(user_count, tmp3);
3288 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3289 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3290 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3293 strlen(channel->channel_key->
3295 channel->channel_key->cipher->name,
3296 channel->key_len / 8, channel->key);
3301 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3302 SILC_STATUS_OK, 0, ident, 13,
3303 2, channel->channel_name,
3304 strlen(channel->channel_name),
3305 3, chidp->data, chidp->len,
3306 4, clidp->data, clidp->len,
3309 7, keyp ? keyp->data : NULL,
3310 keyp ? keyp->len : 0,
3311 8, channel->ban_list,
3313 strlen(channel->ban_list) : 0,
3314 9, channel->invite_list,
3315 channel->invite_list ?
3316 strlen(channel->invite_list) : 0,
3319 strlen(channel->topic) : 0,
3320 11, silc_hmac_get_name(channel->hmac),
3321 strlen(silc_hmac_get_name(channel->
3324 13, user_list->data, user_list->len,
3325 14, mode_list->data,
3328 /* Send command reply */
3329 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3330 reply->data, reply->len, FALSE);
3332 /* Send JOIN notify to locally connected clients on the channel. If
3333 we are normal server then router will send or have sent JOIN notify
3334 already. However since we've added the client already to our channel
3335 we'll ignore it (in packet_receive.c) so we must send it here. If
3336 we are router then this will send it to local clients and local
3338 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3339 SILC_NOTIFY_TYPE_JOIN, 2,
3340 clidp->data, clidp->len,
3341 chidp->data, chidp->len);
3343 if (!cmd->pending) {
3344 /* Send JOIN notify packet to our primary router */
3345 if (!server->standalone)
3346 silc_server_send_notify_join(server, server->router->connection,
3347 server->server_type == SILC_ROUTER ?
3348 TRUE : FALSE, channel, client->id);
3351 /* Distribute the channel key to all backup routers. */
3352 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3353 keyp->data, keyp->len, FALSE, TRUE);
3356 /* If client became founder by providing correct founder auth data
3357 notify the mode change to the channel. */
3359 SILC_PUT32_MSB(chl->mode, mode);
3360 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3361 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3362 clidp->data, clidp->len,
3363 mode, 4, clidp->data, clidp->len);
3365 /* Set CUMODE notify type to network */
3366 if (!server->standalone)
3367 silc_server_send_notify_cumode(server, server->router->connection,
3368 server->server_type == SILC_ROUTER ?
3369 TRUE : FALSE, channel,
3370 chl->mode, client->id, SILC_ID_CLIENT,
3374 silc_buffer_free(reply);
3375 silc_buffer_free(clidp);
3376 silc_buffer_free(chidp);
3377 silc_buffer_free(keyp);
3378 silc_buffer_free(user_list);
3379 silc_buffer_free(mode_list);
3382 silc_free(passphrase);
3385 /* Server side of command JOIN. Joins client into requested channel. If
3386 the channel does not exist it will be created. */
3388 SILC_SERVER_CMD_FUNC(join)
3390 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3391 SilcServer server = cmd->server;
3392 unsigned char *auth;
3393 SilcUInt32 tmp_len, auth_len;
3394 char *tmp, *channel_name = NULL, *cipher, *hmac;
3395 SilcChannelEntry channel;
3396 SilcUInt32 umode = 0;
3397 bool created = FALSE, create_key = TRUE;
3398 SilcClientID *client_id;
3400 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3402 /* Get channel name */
3403 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3406 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3412 channel_name[255] = '\0';
3414 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3416 SILC_STATUS_ERR_BAD_CHANNEL);
3420 /* Get Client ID of the client who is joining to the channel */
3421 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3424 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3427 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3430 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3434 /* Get cipher, hmac name and auth payload */
3435 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3436 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3437 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3439 /* See if the channel exists */
3440 channel = silc_idlist_find_channel_by_name(server->local_list,
3441 channel_name, NULL);
3443 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3444 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3445 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3447 if (!channel || channel->disabled) {
3448 /* Channel not found */
3450 /* If we are standalone server we don't have a router, we just create
3451 the channel by ourselves. */
3452 if (server->standalone) {
3453 channel = silc_server_create_new_channel(server, server->id, cipher,
3454 hmac, channel_name, TRUE);
3456 silc_server_command_send_status_reply(
3457 cmd, SILC_COMMAND_JOIN,
3458 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3462 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3468 /* The channel does not exist on our server. If we are normal server
3469 we will send JOIN command to our router which will handle the
3470 joining procedure (either creates the channel if it doesn't exist
3471 or joins the client to it). */
3472 if (server->server_type != SILC_ROUTER) {
3474 SilcUInt16 old_ident;
3476 /* If this is pending command callback then we've resolved
3477 it and it didn't work, return since we've notified the
3478 client already in the command reply callback. */
3482 old_ident = silc_command_get_ident(cmd->payload);
3483 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3484 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3486 /* Send JOIN command to our router */
3487 silc_server_packet_send(server, (SilcSocketConnection)
3488 server->router->connection,
3489 SILC_PACKET_COMMAND, cmd->packet->flags,
3490 tmpbuf->data, tmpbuf->len, TRUE);
3492 /* Reprocess this packet after received reply from router */
3493 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3494 silc_command_get_ident(cmd->payload),
3495 silc_server_command_join,
3496 silc_server_command_dup(cmd));
3497 cmd->pending = TRUE;
3498 silc_command_set_ident(cmd->payload, old_ident);
3499 silc_buffer_free(tmpbuf);
3503 /* We are router and the channel does not seem exist so we will check
3504 our global list as well for the channel. */
3505 channel = silc_idlist_find_channel_by_name(server->global_list,
3506 channel_name, NULL);
3508 /* Channel really does not exist, create it */
3509 channel = silc_server_create_new_channel(server, server->id, cipher,
3510 hmac, channel_name, TRUE);
3512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3513 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3517 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3525 /* Channel not found */
3527 /* If the command came from router and we are normal server then
3528 something went wrong with the joining as the channel was not found.
3529 We can't do anything else but ignore this. */
3530 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3531 server->server_type != SILC_ROUTER)
3534 /* We are router and the channel does not seem exist so we will check
3535 our global list as well for the channel. */
3536 channel = silc_idlist_find_channel_by_name(server->global_list,
3537 channel_name, NULL);
3539 /* Channel really does not exist, create it */
3540 channel = silc_server_create_new_channel(server, server->id, cipher,
3541 hmac, channel_name, TRUE);
3543 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3544 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3548 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3555 /* Check whether the channel was created by our router */
3556 if (cmd->pending && context2) {
3557 SilcServerCommandReplyContext reply = context2;
3559 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3560 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3561 SILC_GET32_MSB(created, tmp);
3562 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3563 create_key = FALSE; /* Router returned the key already */
3566 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3567 !silc_hash_table_count(channel->user_list))
3571 /* If the channel does not have global users and is also empty the client
3572 will be the channel founder and operator. */
3573 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3574 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3576 /* Join to the channel */
3577 silc_server_command_join_channel(server, cmd, channel, client_id,
3578 created, create_key, umode,
3581 silc_free(client_id);
3584 silc_server_command_free(cmd);
3587 /* Server side of command MOTD. Sends server's current "message of the
3588 day" to the client. */
3590 SILC_SERVER_CMD_FUNC(motd)
3592 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3593 SilcServer server = cmd->server;
3594 SilcBuffer packet, idp;
3595 char *motd, *dest_server;
3596 SilcUInt32 motd_len;
3597 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3599 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3601 /* Get server name */
3602 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3604 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3605 SILC_STATUS_ERR_NO_SUCH_SERVER);
3609 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3612 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3614 if (server->config && server->config->server_info &&
3615 server->config->server_info->motd_file) {
3617 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3622 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3629 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3635 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3636 packet->data, packet->len, FALSE);
3637 silc_buffer_free(packet);
3638 silc_buffer_free(idp);
3640 SilcServerEntry entry;
3642 /* Check whether we have this server cached */
3643 entry = silc_idlist_find_server_by_name(server->global_list,
3644 dest_server, TRUE, NULL);
3646 entry = silc_idlist_find_server_by_name(server->local_list,
3647 dest_server, TRUE, NULL);
3650 if (server->server_type != SILC_SERVER && !cmd->pending &&
3651 entry && !entry->motd) {
3652 /* Send to the server */
3654 SilcUInt16 old_ident;
3656 old_ident = silc_command_get_ident(cmd->payload);
3657 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3658 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3660 silc_server_packet_send(server, entry->connection,
3661 SILC_PACKET_COMMAND, cmd->packet->flags,
3662 tmpbuf->data, tmpbuf->len, TRUE);
3664 /* Reprocess this packet after received reply from router */
3665 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3666 silc_command_get_ident(cmd->payload),
3667 silc_server_command_motd,
3668 silc_server_command_dup(cmd));
3669 cmd->pending = TRUE;
3670 silc_command_set_ident(cmd->payload, old_ident);
3671 silc_buffer_free(tmpbuf);
3675 if (!entry && !cmd->pending && !server->standalone) {
3676 /* Send to the primary router */
3678 SilcUInt16 old_ident;
3680 old_ident = silc_command_get_ident(cmd->payload);
3681 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3682 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3684 silc_server_packet_send(server, server->router->connection,
3685 SILC_PACKET_COMMAND, cmd->packet->flags,
3686 tmpbuf->data, tmpbuf->len, TRUE);
3688 /* Reprocess this packet after received reply from router */
3689 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3690 silc_command_get_ident(cmd->payload),
3691 silc_server_command_motd,
3692 silc_server_command_dup(cmd));
3693 cmd->pending = TRUE;
3694 silc_command_set_ident(cmd->payload, old_ident);
3695 silc_buffer_free(tmpbuf);
3700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3701 SILC_STATUS_ERR_NO_SUCH_SERVER);
3705 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3706 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3707 SILC_STATUS_OK, 0, ident, 2,
3711 strlen(entry->motd) : 0);
3712 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3713 packet->data, packet->len, FALSE);
3714 silc_buffer_free(packet);
3715 silc_buffer_free(idp);
3719 silc_server_command_free(cmd);
3722 /* Server side of command UMODE. Client can use this command to set/unset
3723 user mode. Client actually cannot set itself to be as server/router
3724 operator so this can be used only to unset the modes. */
3726 SILC_SERVER_CMD_FUNC(umode)
3728 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3729 SilcServer server = cmd->server;
3730 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3732 unsigned char *tmp_mask, m[4];
3733 SilcUInt32 mask = 0;
3734 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3735 bool set_mask = FALSE;
3737 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3740 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3742 /* Get the client's mode mask */
3743 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3745 SILC_GET32_MSB(mask, tmp_mask);
3750 /* Check that mode changing is allowed. */
3751 if (!silc_server_check_umode_rights(server, client, mask)) {
3752 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3753 SILC_STATUS_ERR_PERM_DENIED);
3757 /* Anonymous mode cannot be set by client */
3758 if (mask & SILC_UMODE_ANONYMOUS) {
3759 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3760 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3761 SILC_STATUS_ERR_PERM_DENIED);
3765 if (client->mode & SILC_UMODE_ANONYMOUS) {
3766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3767 SILC_STATUS_ERR_PERM_DENIED);
3772 /* Change the mode */
3773 client->mode = mask;
3775 /* Send UMODE change to primary router */
3776 if (!server->standalone)
3777 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3778 client->id, client->mode);
3780 /* Check if anyone is watching this nickname */
3781 if (server->server_type == SILC_ROUTER)
3782 silc_server_check_watcher_list(server, client, NULL,
3783 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3786 /* Send command reply to sender */
3787 SILC_PUT32_MSB(client->mode, m);
3788 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3789 SILC_STATUS_OK, 0, ident, 1,
3791 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3792 packet->data, packet->len, FALSE);
3793 silc_buffer_free(packet);
3796 silc_server_command_free(cmd);
3799 /* Server side command of CMODE. Changes channel mode */
3801 SILC_SERVER_CMD_FUNC(cmode)
3803 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3804 SilcServer server = cmd->server;
3805 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3806 SilcIDListData idata = (SilcIDListData)client;
3807 SilcChannelID *channel_id = NULL;
3808 SilcChannelEntry channel;
3809 SilcChannelClientEntry chl;
3810 SilcBuffer packet, cidp;
3811 unsigned char *tmp, *tmp_id, *tmp_mask;
3812 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3813 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3814 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3815 bool set_mask = FALSE;
3817 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3819 /* Get Channel ID */
3820 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3823 SILC_STATUS_ERR_NO_CHANNEL_ID);
3826 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3829 SILC_STATUS_ERR_NO_CHANNEL_ID);
3833 /* Get the channel mode mask */
3834 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3836 SILC_GET32_MSB(mode_mask, tmp_mask);
3840 /* Get channel entry */
3841 channel = silc_idlist_find_channel_by_id(server->local_list,
3844 channel = silc_idlist_find_channel_by_id(server->global_list,
3847 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3848 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3853 /* Check whether this client is on the channel */
3854 if (!silc_server_client_on_channel(client, channel, &chl)) {
3855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3856 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3860 /* Check that client has rights to change any requested channel modes */
3861 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3863 silc_server_command_send_status_reply(
3864 cmd, SILC_COMMAND_CMODE,
3865 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
3866 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3867 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3871 /* If mode mask was not sent as argument then merely return the current
3872 mode mask to the sender. */
3875 SILC_PUT32_MSB(channel->mode, m);
3876 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3877 SILC_STATUS_OK, 0, ident, 2,
3878 2, tmp_id, tmp_len2,
3880 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3881 packet->data, packet->len, FALSE);
3882 silc_buffer_free(packet);
3887 * Check the modes. Modes that requires nothing special operation are
3891 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3892 /* Channel uses private keys to protect traffic. Client(s) has set the
3893 key locally they want to use, server does not know that key. */
3894 /* Nothing interesting to do here */
3896 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3897 /* The mode is removed and we need to generate and distribute
3898 new channel key. Clients are not using private channel keys
3899 anymore after this. */
3901 /* Re-generate channel key */
3902 if (!silc_server_create_channel_key(server, channel, 0))
3905 /* Send the channel key. This sends it to our local clients and if
3906 we are normal server to our router as well. */
3907 silc_server_send_channel_key(server, NULL, channel,
3908 server->server_type == SILC_ROUTER ?
3909 FALSE : !server->standalone);
3911 cipher = channel->channel_key->cipher->name;
3912 hmac = (char *)silc_hmac_get_name(channel->hmac);
3916 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3917 /* User limit is set on channel */
3918 SilcUInt32 user_limit;
3920 /* Get user limit */
3921 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3923 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3925 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3929 SILC_GET32_MSB(user_limit, tmp);
3930 channel->user_limit = user_limit;
3933 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3934 /* User limit mode is unset. Remove user limit */
3935 channel->user_limit = 0;
3938 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3939 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3940 /* Passphrase has been set to channel */
3942 /* Get the passphrase */
3943 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3945 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3946 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3950 /* Save the passphrase */
3951 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3954 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3955 /* Passphrase mode is unset. remove the passphrase */
3956 silc_free(channel->passphrase);
3957 channel->passphrase = NULL;
3961 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3962 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3963 /* Cipher to use protect the traffic */
3964 SilcCipher newkey, oldkey;
3967 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3970 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3974 /* Delete old cipher and allocate the new one */
3975 if (!silc_cipher_alloc(cipher, &newkey)) {
3976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3977 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3981 oldkey = channel->channel_key;
3982 channel->channel_key = newkey;
3984 /* Re-generate channel key */
3985 if (!silc_server_create_channel_key(server, channel, 0)) {
3986 /* We don't have new key, revert to old one */
3987 channel->channel_key = oldkey;
3991 /* Remove old channel key for good */
3992 silc_cipher_free(oldkey);
3994 /* Send the channel key. This sends it to our local clients and if
3995 we are normal server to our router as well. */
3996 silc_server_send_channel_key(server, NULL, channel,
3997 server->server_type == SILC_ROUTER ?
3998 FALSE : !server->standalone);
4001 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4002 /* Cipher mode is unset. Remove the cipher and revert back to
4004 SilcCipher newkey, oldkey;
4005 cipher = channel->cipher;
4007 /* Delete old cipher and allocate default one */
4008 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4010 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4014 oldkey = channel->channel_key;
4015 channel->channel_key = newkey;
4017 /* Re-generate channel key */
4018 if (!silc_server_create_channel_key(server, channel, 0)) {
4019 /* We don't have new key, revert to old one */
4020 channel->channel_key = oldkey;
4024 /* Remove old channel key for good */
4025 silc_cipher_free(oldkey);
4027 /* Send the channel key. This sends it to our local clients and if
4028 we are normal server to our router as well. */
4029 silc_server_send_channel_key(server, NULL, channel,
4030 server->server_type == SILC_ROUTER ?
4031 FALSE : !server->standalone);
4035 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4036 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4037 /* HMAC to use protect the traffic */
4038 unsigned char hash[32];
4042 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4045 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4049 /* Delete old hmac and allocate the new one */
4050 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4052 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4056 silc_hmac_free(channel->hmac);
4057 channel->hmac = newhmac;
4059 /* Set the HMAC key out of current channel key. The client must do
4061 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4062 channel->key_len / 8, hash);
4063 silc_hmac_set_key(channel->hmac, hash,
4064 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4065 memset(hash, 0, sizeof(hash));
4068 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4069 /* Hmac mode is unset. Remove the hmac and revert back to
4072 unsigned char hash[32];
4073 hmac = channel->hmac_name;
4075 /* Delete old hmac and allocate default one */
4076 silc_hmac_free(channel->hmac);
4077 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4079 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4083 silc_hmac_free(channel->hmac);
4084 channel->hmac = newhmac;
4086 /* Set the HMAC key out of current channel key. The client must do
4088 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4089 channel->key_len / 8,
4091 silc_hmac_set_key(channel->hmac, hash,
4092 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4093 memset(hash, 0, sizeof(hash));
4097 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4098 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4099 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4100 /* Set the founder authentication */
4101 SilcAuthPayload auth;
4103 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4105 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4106 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4110 auth = silc_auth_payload_parse(tmp, tmp_len);
4112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4113 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4117 /* Save the public key */
4118 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4119 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4122 channel->founder_method = silc_auth_get_method(auth);
4124 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4125 tmp = silc_auth_get_data(auth, &tmp_len);
4126 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4127 channel->founder_passwd_len = tmp_len;
4129 /* Verify the payload before setting the mode */
4130 if (!silc_auth_verify(auth, channel->founder_method,
4131 channel->founder_key, 0, idata->hash,
4132 client->id, SILC_ID_CLIENT)) {
4133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4134 SILC_STATUS_ERR_AUTH_FAILED);
4139 silc_auth_payload_free(auth);
4143 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4144 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4145 if (channel->founder_key)
4146 silc_pkcs_public_key_free(channel->founder_key);
4147 if (channel->founder_passwd) {
4148 silc_free(channel->founder_passwd);
4149 channel->founder_passwd = NULL;
4155 /* Finally, set the mode */
4156 channel->mode = mode_mask;
4158 /* Send CMODE_CHANGE notify. */
4159 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4160 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4161 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4162 cidp->data, cidp->len,
4164 cipher, cipher ? strlen(cipher) : 0,
4165 hmac, hmac ? strlen(hmac) : 0,
4166 passphrase, passphrase ?
4167 strlen(passphrase) : 0);
4169 /* Set CMODE notify type to network */
4170 if (!server->standalone)
4171 silc_server_send_notify_cmode(server, server->router->connection,
4172 server->server_type == SILC_ROUTER ?
4173 TRUE : FALSE, channel,
4174 mode_mask, client->id, SILC_ID_CLIENT,
4175 cipher, hmac, passphrase);
4177 /* Send command reply to sender */
4178 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4179 SILC_STATUS_OK, 0, ident, 2,
4180 2, tmp_id, tmp_len2,
4182 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4183 packet->data, packet->len, FALSE);
4185 silc_buffer_free(packet);
4186 silc_buffer_free(cidp);
4189 silc_free(channel_id);
4190 silc_server_command_free(cmd);
4193 /* Server side of CUMODE command. Changes client's mode on a channel. */
4195 SILC_SERVER_CMD_FUNC(cumode)
4197 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4198 SilcServer server = cmd->server;
4199 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4200 SilcIDListData idata = (SilcIDListData)client;
4201 SilcChannelID *channel_id;
4202 SilcClientID *client_id;
4203 SilcChannelEntry channel;
4204 SilcClientEntry target_client;
4205 SilcChannelClientEntry chl;
4206 SilcBuffer packet, idp;
4207 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4208 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4210 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4212 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4214 /* Get Channel ID */
4215 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4218 SILC_STATUS_ERR_NO_CHANNEL_ID);
4221 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4224 SILC_STATUS_ERR_NO_CHANNEL_ID);
4228 /* Get channel entry */
4229 channel = silc_idlist_find_channel_by_id(server->local_list,
4232 channel = silc_idlist_find_channel_by_id(server->global_list,
4235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4236 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4241 /* Check whether sender is on the channel */
4242 if (!silc_server_client_on_channel(client, channel, &chl)) {
4243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4244 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4247 sender_mask = chl->mode;
4249 /* Get the target client's channel mode mask */
4250 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4256 SILC_GET32_MSB(target_mask, tmp_mask);
4258 /* Get target Client ID */
4259 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4262 SILC_STATUS_ERR_NO_CLIENT_ID);
4265 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4268 SILC_STATUS_ERR_NO_CLIENT_ID);
4272 /* Get target client's entry */
4273 target_client = silc_idlist_find_client_by_id(server->local_list,
4274 client_id, TRUE, NULL);
4275 if (!target_client) {
4276 target_client = silc_idlist_find_client_by_id(server->global_list,
4277 client_id, TRUE, NULL);
4280 if (target_client != client &&
4281 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4282 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4284 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4288 /* Check whether target client is on the channel */
4289 if (target_client != client) {
4290 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4292 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4301 /* If the target client is founder, no one else can change their mode
4303 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4305 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4309 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4310 if (target_client != client) {
4311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4312 SILC_STATUS_ERR_NOT_YOU);
4316 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4317 /* The client tries to claim the founder rights. */
4318 unsigned char *tmp_auth;
4319 SilcUInt32 tmp_auth_len, auth_len;
4322 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4323 !channel->founder_key || !idata->public_key ||
4324 !silc_pkcs_public_key_compare(channel->founder_key,
4325 idata->public_key)) {
4326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4327 SILC_STATUS_ERR_NOT_YOU);
4331 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4334 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4338 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4339 (void *)channel->founder_passwd : (void *)channel->founder_key);
4340 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4341 channel->founder_passwd_len : 0);
4343 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4344 channel->founder_method, auth, auth_len,
4345 idata->hash, client->id, SILC_ID_CLIENT)) {
4346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4347 SILC_STATUS_ERR_AUTH_FAILED);
4351 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4355 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4356 if (target_client == client) {
4357 /* Remove channel founder rights from itself */
4358 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4362 SILC_STATUS_ERR_NOT_YOU);
4368 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4369 /* Promote to operator */
4370 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4371 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4372 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4374 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4378 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4382 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4383 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4384 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4386 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4390 /* Demote to normal user */
4391 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4396 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4397 if (target_client != client) {
4398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4399 SILC_STATUS_ERR_NOT_YOU);
4403 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4404 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4408 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4409 if (target_client != client) {
4410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4411 SILC_STATUS_ERR_NOT_YOU);
4415 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4420 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4421 if (target_client != client) {
4422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4423 SILC_STATUS_ERR_NOT_YOU);
4427 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4428 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4432 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4433 if (target_client != client) {
4434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4435 SILC_STATUS_ERR_NOT_YOU);
4439 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4444 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4445 if (target_client != client) {
4446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4447 SILC_STATUS_ERR_NOT_YOU);
4451 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4452 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4456 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4457 if (target_client != client) {
4458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4459 SILC_STATUS_ERR_NOT_YOU);
4463 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4468 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4469 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4471 /* Send notify to channel, notify only if mode was actually changed. */
4473 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4474 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4475 idp->data, idp->len,
4479 /* Set CUMODE notify type to network */
4480 if (!server->standalone)
4481 silc_server_send_notify_cumode(server, server->router->connection,
4482 server->server_type == SILC_ROUTER ?
4483 TRUE : FALSE, channel,
4484 target_mask, client->id,
4489 /* Send command reply to sender */
4490 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4491 SILC_STATUS_OK, 0, ident, 3,
4493 3, tmp_ch_id, tmp_ch_len,
4494 4, tmp_id, tmp_len);
4495 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4496 packet->data, packet->len, FALSE);
4498 silc_buffer_free(packet);
4499 silc_free(channel_id);
4500 silc_free(client_id);
4501 silc_buffer_free(idp);
4504 silc_server_command_free(cmd);
4507 /* Server side of KICK command. Kicks client out of channel. */
4509 SILC_SERVER_CMD_FUNC(kick)
4511 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4512 SilcServer server = cmd->server;
4513 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4514 SilcClientEntry target_client;
4515 SilcChannelID *channel_id;
4516 SilcClientID *client_id;
4517 SilcChannelEntry channel;
4518 SilcChannelClientEntry chl;
4520 SilcUInt32 tmp_len, target_idp_len;
4521 unsigned char *tmp, *comment, *target_idp;
4523 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4525 /* Get Channel ID */
4526 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4529 SILC_STATUS_ERR_NO_CHANNEL_ID);
4532 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4535 SILC_STATUS_ERR_NO_CHANNEL_ID);
4539 /* Get channel entry */
4540 channel = silc_idlist_find_channel_by_id(server->local_list,
4543 channel = silc_idlist_find_channel_by_id(server->local_list,
4546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4547 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4552 /* Check whether sender is on the channel */
4553 if (!silc_server_client_on_channel(client, channel, &chl)) {
4554 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4555 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4559 /* Check that the kicker is channel operator or channel founder */
4560 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4561 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4562 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4563 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4567 /* Get target Client ID */
4568 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4570 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4571 SILC_STATUS_ERR_NO_CLIENT_ID);
4574 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4576 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4577 SILC_STATUS_ERR_NO_CLIENT_ID);
4581 /* Get target client's entry */
4582 target_client = silc_idlist_find_client_by_id(server->local_list,
4583 client_id, TRUE, NULL);
4584 if (!target_client) {
4585 target_client = silc_idlist_find_client_by_id(server->global_list,
4586 client_id, TRUE, NULL);
4589 /* Check whether target client is on the channel */
4590 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4591 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4592 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4596 /* Check that the target client is not channel founder. Channel founder
4597 cannot be kicked from the channel. */
4598 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4600 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4606 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4610 /* Send command reply to sender */
4611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4614 /* Send KICKED notify to local clients on the channel */
4615 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4616 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4617 SILC_NOTIFY_TYPE_KICKED, 3,
4618 target_idp, target_idp_len,
4619 comment, comment ? strlen(comment) : 0,
4620 idp->data, idp->len);
4621 silc_buffer_free(idp);
4623 /* Remove the client from the channel. If the channel does not exist
4624 after removing the client then the client kicked itself off the channel
4625 and we don't have to send anything after that. */
4626 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4627 target_client, FALSE))
4630 /* Send KICKED notify to primary route */
4631 if (!server->standalone)
4632 silc_server_send_notify_kicked(server, server->router->connection,
4633 server->server_type == SILC_ROUTER ?
4634 TRUE : FALSE, channel,
4635 target_client->id, client->id, comment);
4637 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4638 /* Re-generate channel key */
4639 if (!silc_server_create_channel_key(server, channel, 0))
4642 /* Send the channel key to the channel. The key of course is not sent
4643 to the client who was kicked off the channel. */
4644 silc_server_send_channel_key(server, target_client->connection, channel,
4645 server->server_type == SILC_ROUTER ?
4646 FALSE : !server->standalone);
4650 silc_server_command_free(cmd);
4653 /* Server side of OPER command. Client uses this comand to obtain server
4654 operator privileges to this server/router. */
4656 SILC_SERVER_CMD_FUNC(oper)
4658 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4659 SilcServer server = cmd->server;
4660 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4661 unsigned char *username, *auth;
4663 SilcServerConfigAdmin *admin;
4664 SilcIDListData idata = (SilcIDListData)client;
4665 bool result = FALSE;
4666 SilcPublicKey cached_key;
4668 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4670 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4673 /* Get the username */
4674 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4677 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4681 /* Get the admin configuration */
4682 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4683 username, client->nickname);
4685 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4686 username, client->nickname);
4688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4689 SILC_STATUS_ERR_AUTH_FAILED);
4694 /* Get the authentication payload */
4695 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4698 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4702 /* Verify the authentication data. If both passphrase and public key
4703 is set then try both of them. */
4704 if (admin->passphrase)
4705 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4706 admin->passphrase, admin->passphrase_len,
4707 idata->hash, client->id, SILC_ID_CLIENT);
4708 if (!result && admin->publickeys) {
4709 cached_key = silc_server_get_public_key(server, admin->publickeys);
4712 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4713 cached_key, 0, idata->hash,
4714 client->id, SILC_ID_CLIENT);
4717 /* Authentication failed */
4718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4719 SILC_STATUS_ERR_AUTH_FAILED);
4723 /* Client is now server operator */
4724 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4726 /* Update statistics */
4727 if (client->connection)
4728 server->stat.my_server_ops++;
4729 if (server->server_type == SILC_ROUTER)
4730 server->stat.server_ops++;
4732 /* Send UMODE change to primary router */
4733 if (!server->standalone)
4734 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4735 client->id, client->mode);
4737 /* Check if anyone is watching this nickname */
4738 if (server->server_type == SILC_ROUTER)
4739 silc_server_check_watcher_list(server, client, NULL,
4740 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4742 /* Send reply to the sender */
4743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4747 silc_server_command_free(cmd);
4750 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4752 QuitInternal q = (QuitInternal)context;
4753 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4755 /* If there is pending outgoing data for the client then purge it
4756 to the network before closing connection. */
4757 silc_server_packet_queue_purge(q->server, q->sock);
4759 /* Close the connection on our side */
4760 client->router = NULL;
4761 client->connection = NULL;
4762 q->sock->user_data = NULL;
4763 silc_server_close_connection(q->server, q->sock);
4768 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4770 QuitInternal q = (QuitInternal)context;
4771 SilcClientEntry client = (SilcClientEntry)q->sock;
4773 SILC_LOG_DEBUG(("Start"));
4775 if (client->mode & SILC_UMODE_DETACHED)
4776 silc_server_free_client_data(q->server, NULL, client, TRUE,
4781 /* Server side of DETACH command. Detached the client from the network
4782 by closing the connection but preserving the session. */
4784 SILC_SERVER_CMD_FUNC(detach)
4786 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4787 SilcServer server = cmd->server;
4788 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4791 if (server->config->detach_disabled) {
4792 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4793 SILC_STATUS_ERR_UNKNOWN_COMMAND);
4797 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4800 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4802 /* Send the user mode notify to notify that client is detached */
4803 client->mode |= SILC_UMODE_DETACHED;
4804 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4805 if (!server->standalone)
4806 silc_server_send_notify_umode(server, server->router->connection,
4807 server->server_type == SILC_SERVER ?
4808 FALSE : TRUE, client->id, client->mode);
4810 /* Check if anyone is watching this nickname */
4811 if (server->server_type == SILC_ROUTER)
4812 silc_server_check_watcher_list(server, client, NULL,
4813 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4815 q = silc_calloc(1, sizeof(*q));
4817 q->sock = cmd->sock;
4818 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4819 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4821 if (server->config->detach_timeout) {
4822 q = silc_calloc(1, sizeof(*q));
4824 q->sock = (void *)client;
4825 silc_schedule_task_add(server->schedule, 0,
4826 silc_server_command_detach_timeout,
4827 q, server->config->detach_timeout * 60,
4828 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4831 /* Send reply to the sender */
4832 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4836 silc_server_command_free(cmd);
4839 /* Server side of WATCH command. */
4841 SILC_SERVER_CMD_FUNC(watch)
4843 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4844 SilcServer server = cmd->server;
4845 char *add_nick, *del_nick;
4846 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
4848 unsigned char hash[16], *tmp;
4849 SilcClientEntry client;
4850 SilcClientID *client_id = NULL;
4852 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4854 if (server->server_type == SILC_SERVER && !server->standalone) {
4855 if (!cmd->pending) {
4856 /* Send the command to router */
4858 SilcUInt16 old_ident;
4860 old_ident = silc_command_get_ident(cmd->payload);
4861 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4862 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4864 silc_server_packet_send(server, server->router->connection,
4865 SILC_PACKET_COMMAND, cmd->packet->flags,
4866 tmpbuf->data, tmpbuf->len, TRUE);
4868 /* Reprocess this packet after received reply from router */
4869 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4870 silc_command_get_ident(cmd->payload),
4871 silc_server_command_watch,
4872 silc_server_command_dup(cmd));
4873 cmd->pending = TRUE;
4874 silc_command_set_ident(cmd->payload, old_ident);
4875 silc_buffer_free(tmpbuf);
4876 } else if (context2) {
4877 /* Received reply from router, just send same data to the client. */
4878 SilcServerCommandReplyContext reply = context2;
4880 silc_command_get_status(reply->payload, &status, NULL);
4881 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status);
4887 /* We are router and keep the watch list for local cell */
4889 /* Get the client ID */
4890 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4893 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4896 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4898 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4899 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4903 /* Get the client entry which must be in local list */
4904 client = silc_idlist_find_client_by_id(server->local_list,
4905 client_id, TRUE, NULL);
4907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4908 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4913 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4914 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4915 if (!add_nick && !del_nick) {
4916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4917 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4921 if (add_nick && add_nick_len > 128)
4922 add_nick[128] = '\0';
4923 if (del_nick && del_nick_len > 128)
4924 del_nick[128] = '\0';
4926 memset(nick, 0, sizeof(nick));
4928 /* Add new nickname to be watched in our cell */
4930 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
4931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4932 SILC_STATUS_ERR_BAD_NICKNAME);
4936 /* Hash the nick, we have the hash saved, not nicks because we can
4937 do one to one mapping to the nick from Client ID hash this way. */
4938 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
4939 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4941 /* Check whether this client is already watching this nickname */
4942 if (silc_hash_table_find_by_context(server->watcher_list, hash,
4944 /* Nickname is alredy being watched for this client */
4945 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4946 SILC_STATUS_ERR_NICKNAME_IN_USE);
4950 /* Get the nickname from the watcher list and use the same key in
4951 new entries as well. If key doesn't exist then create it. */
4952 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
4953 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4955 /* Add the client to the watcher list with the specified nickname hash. */
4956 silc_hash_table_add(server->watcher_list, tmp, client);
4959 /* Delete nickname from watch list */
4961 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
4962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4963 SILC_STATUS_ERR_BAD_NICKNAME);
4967 /* Hash the nick, we have the hash saved, not nicks because we can
4968 do one to one mapping to the nick from Client ID hash this way. */
4969 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
4970 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4972 /* Check that this client is watching for this nickname */
4973 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4974 client, (void **)&tmp)) {
4975 /* Nickname is alredy being watched for this client */
4976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4977 SILC_STATUS_ERR_NO_SUCH_NICK);
4981 /* Delete the nickname from the watcher list. */
4982 silc_hash_table_del_by_context(server->watcher_list, hash, client);
4984 /* Now check whether there still exists entries with this key, if not
4985 then free the key to not leak memory. */
4986 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4994 silc_free(client_id);
4995 silc_server_command_free(cmd);
4998 /* Server side of SILCOPER command. Client uses this comand to obtain router
4999 operator privileges to this router. */
5001 SILC_SERVER_CMD_FUNC(silcoper)
5003 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5004 SilcServer server = cmd->server;
5005 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5006 unsigned char *username, *auth;
5008 SilcServerConfigAdmin *admin;
5009 SilcIDListData idata = (SilcIDListData)client;
5010 bool result = FALSE;
5011 SilcPublicKey cached_key;
5013 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5015 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5018 if (server->server_type != SILC_ROUTER) {
5019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5020 SILC_STATUS_ERR_AUTH_FAILED);
5024 /* Get the username */
5025 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5028 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5032 /* Get the admin configuration */
5033 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5034 username, client->nickname);
5036 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5037 username, client->nickname);
5039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5040 SILC_STATUS_ERR_AUTH_FAILED);
5045 /* Get the authentication payload */
5046 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5049 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5053 /* Verify the authentication data. If both passphrase and public key
5054 is set then try both of them. */
5055 if (admin->passphrase)
5056 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5057 admin->passphrase, admin->passphrase_len,
5058 idata->hash, client->id, SILC_ID_CLIENT);
5059 if (!result && admin->publickeys) {
5060 cached_key = silc_server_get_public_key(server, admin->publickeys);
5063 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5064 cached_key, 0, idata->hash,
5065 client->id, SILC_ID_CLIENT);
5068 /* Authentication failed */
5069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5070 SILC_STATUS_ERR_AUTH_FAILED);
5074 /* Client is now router operator */
5075 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5077 /* Update statistics */
5078 if (client->connection)
5079 server->stat.my_router_ops++;
5080 if (server->server_type == SILC_ROUTER)
5081 server->stat.router_ops++;
5083 /* Send UMODE change to primary router */
5084 if (!server->standalone)
5085 silc_server_send_notify_umode(server, server->router->connection, TRUE,
5086 client->id, client->mode);
5088 /* Check if anyone is watching this nickname */
5089 if (server->server_type == SILC_ROUTER)
5090 silc_server_check_watcher_list(server, client, NULL,
5091 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5093 /* Send reply to the sender */
5094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5098 silc_server_command_free(cmd);
5101 /* Server side of command BAN. This is used to manage the ban list of the
5102 channel. To add clients and remove clients from the ban list. */
5104 SILC_SERVER_CMD_FUNC(ban)
5106 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5107 SilcServer server = cmd->server;
5108 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5110 SilcChannelEntry channel;
5111 SilcChannelClientEntry chl;
5112 SilcChannelID *channel_id = NULL;
5113 unsigned char *id, *add, *del;
5114 SilcUInt32 id_len, tmp_len;
5115 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5117 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5120 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5122 /* Get Channel ID */
5123 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5125 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5128 SILC_STATUS_ERR_NO_CHANNEL_ID);
5133 /* Get channel entry. The server must know about the channel since the
5134 client is expected to be on the channel. */
5135 channel = silc_idlist_find_channel_by_id(server->local_list,
5138 channel = silc_idlist_find_channel_by_id(server->global_list,
5141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5142 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5147 /* Check whether this client is on the channel */
5148 if (!silc_server_client_on_channel(client, channel, &chl)) {
5149 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5150 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5154 /* The client must be at least channel operator. */
5155 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5157 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
5161 /* Get the new ban and add it to the ban list */
5162 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5164 if (!channel->ban_list)
5165 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5167 channel->ban_list = silc_realloc(channel->ban_list,
5168 sizeof(*channel->ban_list) *
5170 strlen(channel->ban_list) + 2));
5171 if (add[tmp_len - 1] == ',')
5172 add[tmp_len - 1] = '\0';
5174 strncat(channel->ban_list, add, tmp_len);
5175 strncat(channel->ban_list, ",", 1);
5178 /* Get the ban to be removed and remove it from the list */
5179 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5180 if (del && channel->ban_list) {
5181 char *start, *end, *n;
5183 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5184 silc_free(channel->ban_list);
5185 channel->ban_list = NULL;
5187 start = strstr(channel->ban_list, del);
5188 if (start && strlen(start) >= tmp_len) {
5189 end = start + tmp_len;
5190 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5191 strncat(n, channel->ban_list, start - channel->ban_list);
5192 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5194 silc_free(channel->ban_list);
5195 channel->ban_list = n;
5200 /* Send the BAN notify type to our primary router. */
5201 if (!server->standalone && (add || del))
5202 silc_server_send_notify_ban(server, server->router->connection,
5203 server->server_type == SILC_ROUTER ?
5204 TRUE : FALSE, channel, add, del);
5206 /* Send the reply back to the client */
5208 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5209 SILC_STATUS_OK, 0, ident, 2,
5211 3, channel->ban_list,
5213 strlen(channel->ban_list) -1 : 0);
5214 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5215 packet->data, packet->len, FALSE);
5217 silc_buffer_free(packet);
5220 silc_free(channel_id);
5221 silc_server_command_free(cmd);
5224 /* Server side command of LEAVE. Removes client from a channel. */
5226 SILC_SERVER_CMD_FUNC(leave)
5228 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5229 SilcServer server = cmd->server;
5230 SilcSocketConnection sock = cmd->sock;
5231 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5232 SilcChannelID *id = NULL;
5233 SilcChannelEntry channel;
5237 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5239 /* Get Channel ID */
5240 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5243 SILC_STATUS_ERR_NO_CHANNEL_ID);
5246 id = silc_id_payload_parse_id(tmp, len, NULL);
5248 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5249 SILC_STATUS_ERR_NO_CHANNEL_ID);
5253 /* Get channel entry */
5254 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5256 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5259 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5264 /* Check whether this client is on the channel */
5265 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5267 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5271 /* Notify routers that they should remove this client from their list
5272 of clients on the channel. Send LEAVE notify type. */
5273 if (!server->standalone)
5274 silc_server_send_notify_leave(server, server->router->connection,
5275 server->server_type == SILC_ROUTER ?
5276 TRUE : FALSE, channel, id_entry->id);
5278 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5279 SILC_STATUS_OK, 2, tmp, len);
5281 /* Remove client from channel */
5282 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5284 /* If the channel does not exist anymore we won't send anything */
5287 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5288 /* Re-generate channel key */
5289 if (!silc_server_create_channel_key(server, channel, 0))
5292 /* Send the channel key */
5293 silc_server_send_channel_key(server, NULL, channel,
5294 server->server_type == SILC_ROUTER ?
5295 FALSE : !server->standalone);
5300 silc_server_command_free(cmd);
5303 /* Server side of command USERS. Resolves clients and their USERS currently
5304 joined on the requested channel. The list of Client ID's and their modes
5305 on the channel is sent back. */
5307 SILC_SERVER_CMD_FUNC(users)
5309 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5310 SilcServer server = cmd->server;
5311 SilcChannelEntry channel;
5312 SilcChannelID *id = NULL;
5313 SilcBuffer packet, idp;
5314 unsigned char *channel_id;
5315 SilcUInt32 channel_id_len;
5316 SilcBuffer client_id_list;
5317 SilcBuffer client_mode_list;
5318 unsigned char lc[4];
5319 SilcUInt32 list_count = 0;
5320 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5323 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5325 /* Get Channel ID */
5326 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5328 /* Get channel name */
5329 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5331 if (!channel_id && !channel_name) {
5332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5333 SILC_STATUS_ERR_NO_CHANNEL_ID);
5338 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5341 SILC_STATUS_ERR_NO_CHANNEL_ID);
5346 /* If we are server and we don't know about this channel we will send
5347 the command to our router. If we know about the channel then we also
5348 have the list of users already. */
5350 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5352 channel = silc_idlist_find_channel_by_name(server->local_list,
5353 channel_name, NULL);
5355 if (!channel || channel->disabled || !channel->users_resolved) {
5356 if (server->server_type != SILC_ROUTER && !server->standalone &&
5360 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5361 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5363 /* Send USERS command */
5364 silc_server_packet_send(server, server->router->connection,
5365 SILC_PACKET_COMMAND, cmd->packet->flags,
5366 tmpbuf->data, tmpbuf->len, TRUE);
5368 /* Reprocess this packet after received reply */
5369 silc_server_command_pending(server, SILC_COMMAND_USERS,
5370 silc_command_get_ident(cmd->payload),
5371 silc_server_command_users,
5372 silc_server_command_dup(cmd));
5373 cmd->pending = TRUE;
5374 silc_command_set_ident(cmd->payload, ident);
5375 silc_buffer_free(tmpbuf);
5380 /* Check the global list as well. */
5382 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5384 channel = silc_idlist_find_channel_by_name(server->global_list,
5385 channel_name, NULL);
5387 /* Channel really does not exist */
5388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5389 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5394 /* If the channel is private or secret do not send anything, unless the
5395 user requesting this command is on the channel or is server */
5396 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5397 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5398 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5401 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5406 /* Get the users list */
5407 silc_server_get_users_on_channel(server, channel, &client_id_list,
5408 &client_mode_list, &list_count);
5411 SILC_PUT32_MSB(list_count, lc);
5414 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5415 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5416 SILC_STATUS_OK, 0, ident, 4,
5417 2, idp->data, idp->len,
5419 4, client_id_list->data,
5420 client_id_list->len,
5421 5, client_mode_list->data,
5422 client_mode_list->len);
5423 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5424 packet->data, packet->len, FALSE);
5426 silc_buffer_free(idp);
5427 silc_buffer_free(packet);
5428 silc_buffer_free(client_id_list);
5429 silc_buffer_free(client_mode_list);
5433 silc_server_command_free(cmd);
5436 /* Server side of command GETKEY. This fetches the client's public key
5437 from the server where to the client is connected. */
5439 SILC_SERVER_CMD_FUNC(getkey)
5441 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5442 SilcServer server = cmd->server;
5444 SilcClientEntry client;
5445 SilcServerEntry server_entry;
5446 SilcClientID *client_id = NULL;
5447 SilcServerID *server_id = NULL;
5448 SilcIDPayload idp = NULL;
5449 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5450 unsigned char *tmp, *pkdata;
5451 SilcUInt32 tmp_len, pklen;
5452 SilcBuffer pk = NULL;
5454 SilcPublicKey public_key;
5456 SILC_LOG_DEBUG(("Start"));
5458 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5461 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5464 idp = silc_id_payload_parse(tmp, tmp_len);
5466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5467 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5471 id_type = silc_id_payload_get_type(idp);
5472 if (id_type == SILC_ID_CLIENT) {
5473 client_id = silc_id_payload_get_id(idp);
5475 /* If the client is not found from local list there is no chance it
5476 would be locally connected client so send the command further. */
5477 client = silc_idlist_find_client_by_id(server->local_list,
5478 client_id, TRUE, NULL);
5480 client = silc_idlist_find_client_by_id(server->global_list,
5481 client_id, TRUE, NULL);
5483 if ((!client && !cmd->pending && !server->standalone) ||
5484 (client && !client->connection && !cmd->pending &&
5485 !(client->mode & SILC_UMODE_DETACHED)) ||
5486 (client && !client->data.public_key && !cmd->pending)) {
5488 SilcUInt16 old_ident;
5489 SilcSocketConnection dest_sock;
5491 dest_sock = silc_server_get_client_route(server, NULL, 0,
5492 client_id, NULL, NULL);
5496 old_ident = silc_command_get_ident(cmd->payload);
5497 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5498 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5500 silc_server_packet_send(server, dest_sock,
5501 SILC_PACKET_COMMAND, cmd->packet->flags,
5502 tmpbuf->data, tmpbuf->len, TRUE);
5504 /* Reprocess this packet after received reply from router */
5505 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5506 silc_command_get_ident(cmd->payload),
5507 silc_server_command_getkey,
5508 silc_server_command_dup(cmd));
5509 cmd->pending = TRUE;
5510 silc_command_set_ident(cmd->payload, old_ident);
5511 silc_buffer_free(tmpbuf);
5516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5517 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5521 /* The client is locally connected, just get the public key and
5522 send it back. If they key does not exist then do not send it,
5523 send just OK reply */
5524 public_key = client->data.public_key;
5529 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5530 pk = silc_buffer_alloc(4 + tmp_len);
5531 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5532 silc_buffer_format(pk,
5533 SILC_STR_UI_SHORT(tmp_len),
5534 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5535 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5541 } else if (id_type == SILC_ID_SERVER) {
5542 server_id = silc_id_payload_get_id(idp);
5544 /* If the server is not found from local list there is no chance it
5545 would be locally connected server so send the command further. */
5546 server_entry = silc_idlist_find_server_by_id(server->local_list,
5547 server_id, TRUE, NULL);
5549 server_entry = silc_idlist_find_server_by_id(server->global_list,
5550 server_id, TRUE, NULL);
5552 if (server_entry != server->id_entry &&
5553 ((!server_entry && !cmd->pending && !server->standalone) ||
5554 (server_entry && !server_entry->connection && !cmd->pending &&
5555 !server->standalone) ||
5556 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5557 !server->standalone))) {
5559 SilcUInt16 old_ident;
5561 old_ident = silc_command_get_ident(cmd->payload);
5562 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5563 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5565 silc_server_packet_send(server, server->router->connection,
5566 SILC_PACKET_COMMAND, cmd->packet->flags,
5567 tmpbuf->data, tmpbuf->len, TRUE);
5569 /* Reprocess this packet after received reply from router */
5570 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5571 silc_command_get_ident(cmd->payload),
5572 silc_server_command_getkey,
5573 silc_server_command_dup(cmd));
5574 cmd->pending = TRUE;
5575 silc_command_set_ident(cmd->payload, old_ident);
5576 silc_buffer_free(tmpbuf);
5580 if (!server_entry) {
5581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5582 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5586 /* If they key does not exist then do not send it, send just OK reply */
5587 public_key = (!server_entry->data.public_key ?
5588 (server_entry == server->id_entry ? server->public_key :
5589 NULL) : server_entry->data.public_key);
5594 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5595 pk = silc_buffer_alloc(4 + tmp_len);
5596 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5597 silc_buffer_format(pk,
5598 SILC_STR_UI_SHORT(tmp_len),
5599 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5600 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5610 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5611 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5612 SILC_STATUS_OK, 0, ident,
5616 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5617 packet->data, packet->len, FALSE);
5618 silc_buffer_free(packet);
5621 silc_buffer_free(pk);
5625 silc_id_payload_free(idp);
5626 silc_free(client_id);
5627 silc_free(server_id);
5628 silc_server_command_free(cmd);
5632 /* Private range commands, specific to this implementation */
5634 /* Server side command of CONNECT. Connects us to the specified remote
5635 server or router. */
5637 SILC_SERVER_CMD_FUNC(connect)
5639 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5640 SilcServer server = cmd->server;
5641 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5642 unsigned char *tmp, *host;
5644 SilcUInt32 port = SILC_PORT;
5646 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5648 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5651 /* Check whether client has the permissions. */
5652 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5653 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5655 SILC_STATUS_ERR_NO_SERVER_PRIV);
5659 if (server->server_type == SILC_ROUTER &&
5660 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5662 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5666 /* Get the remote server */
5667 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5670 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5675 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5677 SILC_GET32_MSB(port, tmp);
5679 /* Create the connection. It is done with timeout and is async. */
5680 silc_server_create_connection(server, host, port);
5682 /* Send reply to the sender */
5683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5687 silc_server_command_free(cmd);
5690 /* Server side command of CLOSE. Closes connection to a specified server. */
5692 SILC_SERVER_CMD_FUNC(close)
5694 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5695 SilcServer server = cmd->server;
5696 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5697 SilcServerEntry server_entry;
5698 SilcSocketConnection sock;
5701 unsigned char *name;
5702 SilcUInt32 port = SILC_PORT;
5704 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5706 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5709 /* Check whether client has the permissions. */
5710 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5711 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5713 SILC_STATUS_ERR_NO_SERVER_PRIV);
5717 /* Get the remote server */
5718 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5721 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5726 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5728 SILC_GET32_MSB(port, tmp);
5730 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5731 name, port, FALSE, NULL);
5733 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5734 name, port, FALSE, NULL);
5735 if (!server_entry) {
5736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5737 SILC_STATUS_ERR_NO_SERVER_ID);
5741 /* Send reply to the sender */
5742 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5745 /* Close the connection to the server */
5746 sock = (SilcSocketConnection)server_entry->connection;
5748 /* If we shutdown primary router connection manually then don't trigger
5749 any reconnect or backup router connections, by setting the router
5751 if (server->router == server_entry) {
5752 server->id_entry->router = NULL;
5753 server->router = NULL;
5754 server->standalone = TRUE;
5756 silc_server_free_sock_user_data(server, sock, NULL);
5757 silc_server_close_connection(server, sock);
5760 silc_server_command_free(cmd);
5763 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5764 active connections. */
5766 SILC_SERVER_CMD_FUNC(shutdown)
5768 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5769 SilcServer server = cmd->server;
5770 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5772 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5774 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5777 /* Check whether client has the permission. */
5778 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5779 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5780 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5781 SILC_STATUS_ERR_NO_SERVER_PRIV);
5785 /* Send reply to the sender */
5786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5789 /* Then, gracefully, or not, bring the server down. */
5790 silc_server_stop(server);
5794 silc_server_command_free(cmd);