updates.
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 Pekka Riikonen
8
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.
13   
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.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 static int silc_server_is_registered(SilcServer server,
26                                      SilcSocketConnection sock,
27                                      SilcServerCommandContext cmd,
28                                      SilcCommand command);
29 static void 
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
31                                       SilcCommand command,
32                                       SilcCommandStatus status);
33 static void 
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
35                                      SilcCommand command,
36                                      SilcCommandStatus status,
37                                      SilcUInt32 arg_type,
38                                      const unsigned char *arg,
39                                      SilcUInt32 arg_len);
40 static bool
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42                                         SilcServerCommandReplyContext cmdr,
43                                         SilcCommand command);
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
45
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
48 {
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(silcoper, SILCOPER,
70                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
71   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
72   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
73   SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
74
75   SILC_SERVER_CMD(connect, PRIV_CONNECT, 
76                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
77   SILC_SERVER_CMD(close, PRIV_CLOSE,
78                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
79   SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
80                   SILC_CF_OPER),
81
82   { NULL, 0 },
83 };
84
85 /* Performs several checks to the command. It first checks whether this
86    command was called as pending command callback. If it was then it checks
87    whether error occurred in the command reply where the pending command
88    callback was called. 
89
90    It also checks that the requested command includes correct amount
91    of arguments. */
92 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max)                 \
93 do {                                                                          \
94   SilcUInt32 _argc;                                                                   \
95                                                                               \
96   SILC_LOG_DEBUG(("Start"));                                                  \
97                                                                               \
98   if (silc_server_command_pending_error_check(cmd, context2, command)) {      \
99     silc_server_command_free(cmd);                                            \
100     return;                                                                   \
101   }                                                                           \
102                                                                               \
103   _argc = silc_argument_get_arg_num(cmd->args);                               \
104   if (_argc < min) {                                                          \
105     silc_server_command_send_status_reply(cmd, command,                       \
106                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
107     silc_server_command_free(cmd);                                            \
108     return;                                                                   \
109   }                                                                           \
110   if (_argc > max) {                                                          \
111     silc_server_command_send_status_reply(cmd, command,                       \
112                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);   \
113     silc_server_command_free(cmd);                                            \
114     return;                                                                   \
115   }                                                                           \
116 } while(0)
117
118 /* Returns TRUE if the connection is registered. Unregistered connections
119    usually cannot send commands hence the check. */
120
121 static int silc_server_is_registered(SilcServer server,
122                                      SilcSocketConnection sock,
123                                      SilcServerCommandContext cmd,
124                                      SilcCommand command)
125 {
126   SilcIDListData idata = (SilcIDListData)sock->user_data;
127
128   if (!idata)
129     return FALSE;
130
131   if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
132     return TRUE;
133
134   silc_server_command_send_status_reply(cmd, command,
135                                         SILC_STATUS_ERR_NOT_REGISTERED);
136   return FALSE;
137 }
138
139 /* Internal context to hold data when executed command with timeout. */
140 typedef struct {
141   SilcServerCommandContext ctx;
142   SilcServerCommand *cmd;
143 } *SilcServerCommandTimeout;
144
145 /* Timeout callback to process commands with timeout for client. Client's
146    commands are always executed with timeout. */
147
148 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
149 {
150   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
151   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
152
153   if (!client) {
154     silc_server_command_free(timeout->ctx);
155     silc_free(timeout);
156   }
157
158   /* Update access time */
159   client->last_command = time(NULL);
160
161   if (!(timeout->cmd->flags & SILC_CF_REG))
162     timeout->cmd->cb(timeout->ctx, NULL);
163   else if (silc_server_is_registered(timeout->ctx->server, 
164                                      timeout->ctx->sock, 
165                                      timeout->ctx, 
166                                      timeout->cmd->cmd))
167     timeout->cmd->cb(timeout->ctx, NULL);
168   else
169     silc_server_command_free(timeout->ctx);
170
171   silc_free(timeout);
172 }
173
174 /* Processes received command packet. */
175
176 void silc_server_command_process(SilcServer server,
177                                  SilcSocketConnection sock,
178                                  SilcPacketContext *packet)
179 {
180   SilcServerCommandContext ctx;
181   SilcServerCommand *cmd;
182   SilcCommand command;
183
184   /* Allocate command context. This must be free'd by the
185      command routine receiving it. */
186   ctx = silc_server_command_alloc();
187   ctx->server = server;
188   ctx->sock = silc_socket_dup(sock);
189   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
190   
191   /* Parse the command payload in the packet */
192   ctx->payload = silc_command_payload_parse(packet->buffer->data,
193                                             packet->buffer->len);
194   if (!ctx->payload) {
195     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
196     silc_buffer_free(packet->buffer);
197     silc_packet_context_free(packet);
198     silc_socket_free(ctx->sock);
199     silc_free(ctx);
200     return;
201   }
202   ctx->args = silc_command_get_args(ctx->payload);
203
204   /* Get the command */
205   command = silc_command_get(ctx->payload);
206   for (cmd = silc_command_list; cmd->cb; cmd++)
207     if (cmd->cmd == command)
208       break;
209
210   if (!cmd || !cmd->cb) {
211     silc_server_command_send_status_reply(ctx, command,
212                                           SILC_STATUS_ERR_UNKNOWN_COMMAND);
213     silc_server_command_free(ctx);
214     return;
215   }
216
217   /* Execute client's commands always with timeout.  Normally they are
218      executed with zero (0) timeout but if client is sending command more
219      frequently than once in 2 seconds, then the timeout may be 0 to 2
220      seconds. */
221   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
222     SilcClientEntry client = (SilcClientEntry)sock->user_data;
223     SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
224     int fast;
225
226     timeout->ctx = ctx;
227     timeout->cmd = cmd;
228
229     if (client->last_command && (time(NULL) - client->last_command) < 2) {
230       client->fast_command++;
231       fast = FALSE;
232     } else {
233       client->fast_command = ((client->fast_command - 1) <= 0 ? 0 : 
234                               client->fast_command--);
235       fast = TRUE;
236     }
237
238     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
239                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
240       silc_schedule_task_add(server->schedule, sock->sock, 
241                          silc_server_command_process_timeout,
242                          (void *)timeout, 
243                          2 - (time(NULL) - client->last_command), 0,
244                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
245     else
246       silc_schedule_task_add(server->schedule, sock->sock, 
247                          silc_server_command_process_timeout,
248                          (void *)timeout, 0, 1,
249                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
250     return;
251   }
252
253   /* Execute for server */
254
255   if (!(cmd->flags & SILC_CF_REG))
256     cmd->cb(ctx, NULL);
257   else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
258     cmd->cb(ctx, NULL);
259   else
260     silc_server_command_free(ctx);
261 }
262
263 /* Allocate Command Context */
264
265 SilcServerCommandContext silc_server_command_alloc()
266 {
267   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
268   ctx->users++;
269   return ctx;
270 }
271
272 /* Free's the command context allocated before executing the command */
273
274 void silc_server_command_free(SilcServerCommandContext ctx)
275 {
276   ctx->users--;
277   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
278                   ctx->users));
279   if (ctx->users < 1) {
280     if (ctx->payload)
281       silc_command_payload_free(ctx->payload);
282     if (ctx->packet)
283       silc_packet_context_free(ctx->packet);
284     if (ctx->sock)
285       silc_socket_free(ctx->sock); /* Decrease reference counter */
286     silc_free(ctx);
287   }
288 }
289
290 /* Duplicate Command Context by adding reference counter. The context won't
291    be free'd untill it hits zero. */
292
293 SilcServerCommandContext 
294 silc_server_command_dup(SilcServerCommandContext ctx)
295 {
296   ctx->users++;
297   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
298                   ctx->users));
299   return ctx;
300 }
301
302 /* Add new pending command to be executed when reply to a command has been
303    received. The `reply_cmd' is the command that will call the `callback'
304    with `context' when reply has been received.  It can be SILC_COMMAND_NONE
305    to match any command with the `ident'.  If `ident' is non-zero
306    the `callback' will be executed when received reply with command
307    identifier `ident'. If there already exists pending command for the
308    specified command, ident, callback and context this function has no
309    effect. */
310
311 bool silc_server_command_pending(SilcServer server,
312                                  SilcCommand reply_cmd,
313                                  SilcUInt16 ident,
314                                  SilcCommandCb callback,
315                                  void *context)
316 {
317   SilcServerCommandPending *reply;
318
319   /* Check whether identical pending already exists for same command,
320      ident, callback and callback context. If it does then it would be
321      error to register it again. */
322   silc_dlist_start(server->pending_commands);
323   while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
324     if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
325         reply->callback == callback && reply->context == context)
326       return FALSE;
327   }
328
329   reply = silc_calloc(1, sizeof(*reply));
330   reply->reply_cmd = reply_cmd;
331   reply->ident = ident;
332   reply->context = context;
333   reply->callback = callback;
334   silc_dlist_add(server->pending_commands, reply);
335
336   return TRUE;
337 }
338
339 /* Deletes pending command by reply command type. */
340
341 void silc_server_command_pending_del(SilcServer server,
342                                      SilcCommand reply_cmd,
343                                      SilcUInt16 ident)
344 {
345   SilcServerCommandPending *r;
346
347   silc_dlist_start(server->pending_commands);
348   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
349     if (r->reply_cmd == reply_cmd && r->ident == ident) {
350       silc_dlist_del(server->pending_commands, r);
351       break;
352     }
353   }
354 }
355
356 /* Checks for pending commands and marks callbacks to be called from
357    the command reply function. Returns TRUE if there were pending command. */
358
359 SilcServerCommandPendingCallbacks
360 silc_server_command_pending_check(SilcServer server,
361                                   SilcServerCommandReplyContext ctx,
362                                   SilcCommand command, 
363                                   SilcUInt16 ident,
364                                   SilcUInt32 *callbacks_count)
365 {
366   SilcServerCommandPending *r;
367   SilcServerCommandPendingCallbacks callbacks = NULL;
368   int i = 0;
369
370   silc_dlist_start(server->pending_commands);
371   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
372     if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
373         && r->ident == ident) {
374       callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
375       callbacks[i].context = r->context;
376       callbacks[i].callback = r->callback;
377       ctx->ident = ident;
378       i++;
379     }
380   }
381
382   *callbacks_count = i;
383   return callbacks;
384 }
385
386 /* Sends simple status message as command reply packet */
387
388 static void 
389 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
390                                       SilcCommand command,
391                                       SilcCommandStatus status)
392 {
393   SilcBuffer buffer;
394
395   SILC_LOG_DEBUG(("Sending command status %d", status));
396
397   buffer = 
398     silc_command_reply_payload_encode_va(command, status, 0,
399                                          silc_command_get_ident(cmd->payload),
400                                          0);
401   silc_server_packet_send(cmd->server, cmd->sock,
402                           SILC_PACKET_COMMAND_REPLY, 0, 
403                           buffer->data, buffer->len, FALSE);
404   silc_buffer_free(buffer);
405 }
406
407 /* Sends command status reply with one extra argument. The argument
408    type must be sent as argument. */
409
410 static void 
411 silc_server_command_send_status_data(SilcServerCommandContext cmd,
412                                      SilcCommand command,
413                                      SilcCommandStatus status,
414                                      SilcUInt32 arg_type,
415                                      const unsigned char *arg,
416                                      SilcUInt32 arg_len)
417 {
418   SilcBuffer buffer;
419
420   SILC_LOG_DEBUG(("Sending command status %d", status));
421
422   buffer = 
423     silc_command_reply_payload_encode_va(command, status, 0,
424                                          silc_command_get_ident(cmd->payload),
425                                          1, arg_type, arg, arg_len);
426   silc_server_packet_send(cmd->server, cmd->sock,
427                           SILC_PACKET_COMMAND_REPLY, 0, 
428                           buffer->data, buffer->len, FALSE);
429   silc_buffer_free(buffer);
430 }
431
432 /* This function can be called to check whether in the command reply
433    an error occurred. This function has no effect if this is called
434    when the command function was not called as pending command callback. 
435    This returns TRUE if error had occurred. */
436
437 static bool
438 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
439                                         SilcServerCommandReplyContext cmdr,
440                                         SilcCommand command)
441 {
442   if (!cmd->pending || !cmdr)
443     return FALSE;
444
445   if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
446     SilcBuffer buffer;
447
448     /* Send the same command reply payload */
449     silc_command_set_ident(cmdr->payload, 
450                            silc_command_get_ident(cmd->payload));
451     buffer = silc_command_payload_encode_payload(cmdr->payload);
452     silc_server_packet_send(cmd->server, cmd->sock,
453                             SILC_PACKET_COMMAND_REPLY, 0, 
454                             buffer->data, buffer->len, FALSE);
455     silc_buffer_free(buffer);
456     return TRUE;
457   }
458
459   return FALSE;
460 }
461
462 /******************************************************************************
463
464                               WHOIS Functions
465
466 ******************************************************************************/
467
468 static int
469 silc_server_command_whois_parse(SilcServerCommandContext cmd,
470                                 SilcClientID ***client_id,
471                                 SilcUInt32 *client_id_count,
472                                 char **nickname,
473                                 char **server_name,
474                                 int *count,
475                                 SilcCommand command)
476 {
477   unsigned char *tmp;
478   SilcUInt32 len;
479   SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
480   int i, k;
481
482   /* If client ID is in the command it must be used instead of nickname */
483   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
484   if (!tmp) {
485     /* No ID, get the nickname@server string and parse it. */
486     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
487     if (tmp) {
488       silc_parse_userfqdn(tmp, nickname, server_name);
489     } else {
490       silc_server_command_send_status_reply(cmd, command,
491                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
492       return FALSE;
493     }
494   } else {
495     /* Command includes ID, we must use that.  Also check whether the command
496        has more than one ID set - take them all. */
497
498     *client_id = silc_calloc(1, sizeof(**client_id));
499     (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
500     if ((*client_id)[0] == NULL) {
501       silc_free(*client_id);
502       silc_server_command_send_status_reply(cmd, command,
503                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
504       return FALSE;
505     }
506     *client_id_count = 1;
507
508     /* Take all ID's from the command packet */
509     if (argc > 1) {
510       for (k = 1, i = 1; i < argc; i++) {
511         tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
512         if (tmp) {
513           *client_id = silc_realloc(*client_id, sizeof(**client_id) *
514                                     (*client_id_count + 1));
515           (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
516           if ((*client_id)[k] == NULL) {
517             /* Cleanup all and fail */
518             for (i = 0; i < *client_id_count; i++)
519               silc_free((*client_id)[i]);
520             silc_free(*client_id);
521             silc_server_command_send_status_reply(
522                                          cmd, command,
523                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
524             return FALSE;
525           }
526           (*client_id_count)++;
527           k++;
528         }
529       }
530     }
531   }
532
533   /* Get the max count of reply messages allowed */
534   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
535   if (tmp)
536     *count = atoi(tmp);
537   else
538     *count = 0;
539
540   return TRUE;
541 }
542
543 /* Resolve context used by both WHOIS and IDENTIFY commands */
544 typedef struct {
545   SilcServerEntry router;
546   SilcUInt16 ident;
547   unsigned char **res_argv;
548   SilcUInt32 *res_argv_lens;
549   SilcUInt32 *res_argv_types;
550   SilcUInt32 res_argc;
551 } *SilcServerResolveContext;
552
553 static bool
554 silc_server_command_whois_check(SilcServerCommandContext cmd,
555                                 SilcClientEntry *clients,
556                                 SilcUInt32 clients_count)
557 {
558   SilcServer server = cmd->server;
559   SilcClientEntry entry;
560   SilcServerResolveContext resolve = NULL, r = NULL;
561   SilcUInt32 resolve_count = 0;
562   int i, k;
563   bool no_res = TRUE;
564
565   SILC_LOG_DEBUG(("Start"));
566
567   for (i = 0; i < clients_count; i++) {
568     entry = clients[i];
569     if (!entry)
570       continue;
571
572     if ((entry->nickname && entry->username && entry->userinfo) ||
573         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
574       if (!entry->router)
575         continue;
576
577       /* If we are normal server, and we've not resolved this client from
578          router and it is global client, we'll check whether it is on some
579          channel.  If not then we cannot be sure about its validity, and
580          we'll resolve it from router. */
581       if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
582           entry->connection || silc_hash_table_count(entry->channels))
583         continue;
584     }
585
586     /* We need to resolve this entry since it is not complete */
587
588     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
589       /* The entry is being resolved (and we are not the resolver) so attach
590          to the command reply and we're done with this one. */
591       silc_server_command_pending(server, SILC_COMMAND_NONE, 
592                                   entry->resolve_cmd_ident,
593                                   silc_server_command_whois,
594                                   silc_server_command_dup(cmd));
595       no_res = FALSE;
596     } else {
597       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
598         /* We've resolved this and it still is not ready.  We'll return
599            and are that this will be handled again after it is resolved. */
600         for (i = 0; i < resolve_count; i++) {
601           for (k = 0; k < r->res_argc; k++)
602             silc_free(r->res_argv[k]);
603           silc_free(r->res_argv);
604           silc_free(r->res_argv_lens);
605           silc_free(r->res_argv_types);
606         }
607         silc_free(resolve);
608         return FALSE;
609       } else {
610         /* We'll resolve this client */
611         SilcBuffer idp;
612
613         r = NULL;
614         for (k = 0; k < resolve_count; k++) {
615           if (resolve[k].router == entry->router) {
616             r = &resolve[k];
617             break;
618           }
619         }
620
621         if (!r) {
622           resolve = silc_realloc(resolve, sizeof(*resolve) * 
623                                  (resolve_count + 1));
624           r = &resolve[resolve_count];
625           memset(r, 0, sizeof(*r));
626           r->router = entry->router;
627           r->ident = ++server->cmd_ident;
628           resolve_count++;
629         }
630
631         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
632                                    (r->res_argc + 1));
633         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
634                                         sizeof(*r->res_argv_lens) *
635                                         (r->res_argc + 1));
636         r->res_argv_types = silc_realloc(r->res_argv_types, 
637                                          sizeof(*r->res_argv_types) *
638                                          (r->res_argc + 1));
639         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
640         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
641                                                sizeof(**r->res_argv));
642         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
643         r->res_argv_lens[r->res_argc] = idp->len;
644         r->res_argv_types[r->res_argc] = r->res_argc + 3;
645         r->res_argc++;
646         silc_buffer_free(idp);
647
648         entry->resolve_cmd_ident = r->ident;
649         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
650         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
651       }
652     }
653   }
654
655   /* Do the resolving */
656   for (i = 0; i < resolve_count; i++) {
657     SilcBuffer res_cmd;
658
659     r = &resolve[i];
660
661     /* Send WHOIS request. We send WHOIS since we're doing the requesting
662        now anyway so make it a good one. */
663     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
664                                           r->res_argc, r->res_argv, 
665                                           r->res_argv_lens,
666                                           r->res_argv_types, 
667                                           r->ident);
668     silc_server_packet_send(server, r->router->connection,
669                             SILC_PACKET_COMMAND, cmd->packet->flags,
670                             res_cmd->data, res_cmd->len, FALSE);
671
672     /* Reprocess this packet after received reply */
673     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
674                                 r->ident,
675                                 silc_server_command_whois,
676                                 silc_server_command_dup(cmd));
677     cmd->pending = TRUE;
678
679     silc_buffer_free(res_cmd);
680     for (k = 0; k < r->res_argc; k++)
681       silc_free(r->res_argv[k]);
682     silc_free(r->res_argv);
683     silc_free(r->res_argv_lens);
684     silc_free(r->res_argv_types);
685     no_res = FALSE;
686   }
687   silc_free(resolve);
688
689   return no_res;
690 }
691
692 static void
693 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
694                                      SilcClientEntry *clients,
695                                      SilcUInt32 clients_count,
696                                      int count,
697                                      const char *nickname,
698                                      SilcClientID **client_ids)
699 {
700   SilcServer server = cmd->server;
701   char *tmp;
702   int i, k, len, valid_count;
703   SilcBuffer packet, idp, channels;
704   SilcClientEntry entry;
705   SilcCommandStatus status;
706   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
707   char nh[256], uh[256];
708   unsigned char idle[4], mode[4];
709   unsigned char *fingerprint;
710   SilcSocketConnection hsock;
711
712   /* Process only valid clients and ignore those that are not registered. */
713   valid_count = 0;
714   for (i = 0; i < clients_count; i++) {
715     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
716       valid_count++;
717     else
718       clients[i] = NULL;
719   }
720
721   if (!valid_count) {
722     /* No valid clients found, send error reply */
723     if (nickname) {
724       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
725                                            SILC_STATUS_ERR_NO_SUCH_NICK,
726                                            3, nickname, strlen(nickname));
727     } else if (client_ids && client_ids[0]) {
728       SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
729       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
730                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
731                                            2, idp->data, idp->len);
732       silc_buffer_free(idp);
733     }
734     return;
735   }
736
737   /* Start processing found clients. */
738   if (valid_count > 1)
739     status = SILC_STATUS_LIST_START;
740   else
741     status = SILC_STATUS_OK;
742
743   for (i = 0, k = 0; i < clients_count; i++) {
744     entry = clients[i];
745     if (!entry)
746       continue;
747
748     if (k >= 1)
749       status = SILC_STATUS_LIST_ITEM;
750     if (valid_count > 1 && k == valid_count - 1)
751       status = SILC_STATUS_LIST_END;
752     if (count && k - 1 == count)
753       status = SILC_STATUS_LIST_END;
754
755     /* Send WHOIS reply */
756     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
757     tmp = silc_argument_get_first_arg(cmd->args, NULL);
758     
759     memset(uh, 0, sizeof(uh));
760     memset(nh, 0, sizeof(nh));
761     memset(idle, 0, sizeof(idle));
762     
763     strncat(nh, entry->nickname, strlen(entry->nickname));
764     if (!strchr(entry->nickname, '@')) {
765       strncat(nh, "@", 1);
766       if (entry->servername) {
767         strncat(nh, entry->servername, strlen(entry->servername));
768       } else {
769         len = entry->router ? strlen(entry->router->server_name) :
770           strlen(server->server_name);
771         strncat(nh, entry->router ? entry->router->server_name :
772                 server->server_name, len);
773       }
774     }
775       
776     strncat(uh, entry->username, strlen(entry->username));
777     if (!strchr(entry->username, '@')) {
778       strncat(uh, "@", 1);
779       hsock = (SilcSocketConnection)entry->connection;
780       len = strlen(hsock->hostname);
781       strncat(uh, hsock->hostname, len);
782     }
783
784     channels = silc_server_get_client_channel_list(server, entry);
785
786     if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
787       fingerprint = entry->data.fingerprint;
788     else
789       fingerprint = NULL;
790       
791     SILC_PUT32_MSB(entry->mode, mode);
792
793     if (entry->connection) {
794       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
795     }
796
797     packet = 
798       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
799                                            status, 0, ident, 8, 
800                                            2, idp->data, idp->len,
801                                            3, nh, strlen(nh),
802                                            4, uh, strlen(uh),
803                                            5, entry->userinfo, 
804                                            strlen(entry->userinfo),
805                                            6, channels ? channels->data : NULL,
806                                            channels ? channels->len : 0,
807                                            7, mode, 4,
808                                            8, idle, 4,
809                                            9, fingerprint,
810                                            fingerprint ? 20 : 0);
811
812     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
813                             0, packet->data, packet->len, FALSE);
814     
815     silc_buffer_free(packet);
816     silc_buffer_free(idp);
817     if (channels)
818       silc_buffer_free(channels);
819
820     k++;
821   }
822 }
823
824 static void 
825 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
826 {
827   SilcServer server = cmd->server;
828   SilcBuffer tmpbuf;
829   SilcUInt16 old_ident;
830
831   old_ident = silc_command_get_ident(cmd->payload);
832   silc_command_set_ident(cmd->payload, ++server->cmd_ident);
833   tmpbuf = silc_command_payload_encode_payload(cmd->payload);
834
835   /* Send WHOIS command to our router */
836   silc_server_packet_send(server, (SilcSocketConnection)
837                           server->router->connection,
838                           SILC_PACKET_COMMAND, cmd->packet->flags,
839                           tmpbuf->data, tmpbuf->len, TRUE);
840
841   /* Reprocess this packet after received reply from router */
842   silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
843                               silc_command_get_ident(cmd->payload),
844                               silc_server_command_whois,
845                               silc_server_command_dup(cmd));
846   cmd->pending = TRUE;
847   silc_command_set_ident(cmd->payload, old_ident);
848   silc_buffer_free(tmpbuf);
849 }
850
851 static int
852 silc_server_command_whois_process(SilcServerCommandContext cmd)
853 {
854   SilcServer server = cmd->server;
855   char *nick = NULL, *server_name = NULL;
856   int count = 0;
857   SilcClientEntry *clients = NULL, entry;
858   SilcClientID **client_id = NULL;
859   SilcUInt32 client_id_count = 0, clients_count = 0;
860   int i, ret = 0;
861   bool check_global = FALSE;
862
863   /* Parse the whois request */
864   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
865                                        &nick, &server_name, &count,
866                                        SILC_COMMAND_WHOIS))
867     return 0;
868
869   /* Send the WHOIS request to the router only if it included nickname.
870      Since nicknames can be expanded into many clients we need to send it
871      to router.  If the WHOIS included only client ID's we will check them
872      first locally since we just might have them. */
873   if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
874       server->server_type == SILC_SERVER && !cmd->pending &&
875       !server->standalone) {
876     silc_server_command_whois_send_router(cmd);
877     ret = -1;
878     goto out;
879   }
880
881   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
882     check_global = TRUE;
883   else if (server->server_type != SILC_SERVER)
884     check_global = TRUE;
885
886   /* Get all clients matching that ID or nickname from local list */
887   if (client_id_count) {
888     /* Check all Client ID's received in the command packet */
889     for (i = 0; i < client_id_count; i++) {
890       entry = silc_idlist_find_client_by_id(server->local_list, 
891                                             client_id[i], TRUE, NULL);
892       if (!entry && check_global)
893         entry = silc_idlist_find_client_by_id(server->global_list, 
894                                               client_id[i], TRUE, NULL);
895       if (entry) {
896         clients = silc_realloc(clients, sizeof(*clients) * 
897                                (clients_count + 1));
898         clients[clients_count++] = entry;
899       } else {
900         /* If we are normal server and did not send the request first to router
901            do it now, since we do not have the Client ID information. */
902         if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
903             server->server_type == SILC_SERVER && !cmd->pending && 
904             !server->standalone) {
905           silc_server_command_whois_send_router(cmd);
906           ret = -1;
907           goto out;
908         }
909       }
910     }
911   } else {
912     /* Find by nickname */
913     if (!silc_idlist_get_clients_by_hash(server->local_list, 
914                                          nick, server->md5hash,
915                                          &clients, &clients_count))
916       silc_idlist_get_clients_by_nickname(server->local_list, 
917                                           nick, server_name,
918                                           &clients, &clients_count);
919     if (check_global) {
920       if (!silc_idlist_get_clients_by_hash(server->global_list, 
921                                            nick, server->md5hash,
922                                            &clients, &clients_count))
923         silc_idlist_get_clients_by_nickname(server->global_list, 
924                                             nick, server_name,
925                                             &clients, &clients_count);
926     }
927   }
928   
929   if (!clients) {
930     /* If we are normal server and did not send the request first to router
931        do it now, since we do not have the information. */
932     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
933         server->server_type == SILC_SERVER && !cmd->pending && 
934         !server->standalone) {
935       silc_server_command_whois_send_router(cmd);
936       ret = -1;
937       goto out;
938     }
939
940     /* Such client(s) really does not exist in the SILC network. */
941     if (!client_id_count) {
942       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
943                                            SILC_STATUS_ERR_NO_SUCH_NICK,
944                                            3, nick, strlen(nick));
945     } else {
946       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
947       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
948                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
949                                            2, idp->data, idp->len);
950       silc_buffer_free(idp);
951     }
952     goto out;
953   }
954
955   /* Router always finds the client entry if it exists in the SILC network.
956      However, it might be incomplete entry and does not include all the
957      mandatory fields that WHOIS command reply requires. Check for these and
958      make query from the server who owns the client if some fields are 
959      missing. */
960   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
961     ret = -1;
962     goto out;
963   }
964
965   /* Send the command reply */
966   silc_server_command_whois_send_reply(cmd, clients, clients_count,
967                                        count, nick, client_id);
968
969  out:
970   if (client_id_count) {
971     for (i = 0; i < client_id_count; i++)
972       silc_free(client_id[i]);
973     silc_free(client_id);
974   }
975   silc_free(clients);
976   silc_free(nick);
977   silc_free(server_name);
978
979   return ret;
980 }
981
982 /* Server side of command WHOIS. Processes user's query and sends found 
983    results as command replies back to the client. */
984
985 SILC_SERVER_CMD_FUNC(whois)
986 {
987   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
988   int ret = 0;
989
990   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
991
992   ret = silc_server_command_whois_process(cmd);
993   silc_server_command_free(cmd);
994 }
995
996 /******************************************************************************
997
998                               WHOWAS Functions
999
1000 ******************************************************************************/
1001
1002 static int
1003 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1004                                  char **nickname,
1005                                  char **server_name,
1006                                  int *count)
1007 {
1008   unsigned char *tmp;
1009   SilcUInt32 len;
1010
1011   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1012   if (!tmp) {
1013     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1014                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1015     return FALSE;
1016   }
1017
1018   /* Get the nickname@server string and parse it. */
1019   silc_parse_userfqdn(tmp, nickname, server_name);
1020
1021   /* Get the max count of reply messages allowed */
1022   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1023   if (tmp)
1024     *count = atoi(tmp);
1025   else
1026     *count = 0;
1027
1028   return TRUE;
1029 }
1030
1031 static char
1032 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1033                                  SilcClientEntry *clients,
1034                                  SilcUInt32 clients_count)
1035 {
1036   SilcServer server = cmd->server;
1037   int i;
1038   SilcClientEntry entry;
1039
1040   for (i = 0; i < clients_count; i++) {
1041     entry = clients[i];
1042
1043     if (!entry->nickname || !entry->username) {
1044       SilcBuffer tmpbuf;
1045       SilcUInt16 old_ident;
1046
1047       if (!entry->router)
1048         continue;
1049       
1050       old_ident = silc_command_get_ident(cmd->payload);
1051       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1052       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1053
1054       /* Send WHOWAS command */
1055       silc_server_packet_send(server, entry->router->connection,
1056                               SILC_PACKET_COMMAND, cmd->packet->flags,
1057                               tmpbuf->data, tmpbuf->len, TRUE);
1058       
1059       /* Reprocess this packet after received reply */
1060       silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1061                                   silc_command_get_ident(cmd->payload),
1062                                   silc_server_command_whowas, 
1063                                   silc_server_command_dup(cmd));
1064       cmd->pending = TRUE;
1065       silc_command_set_ident(cmd->payload, old_ident);
1066
1067       silc_buffer_free(tmpbuf);
1068       return FALSE;
1069     }
1070   }
1071
1072   return TRUE;
1073 }
1074
1075 static void
1076 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1077                                       SilcClientEntry *clients,
1078                                       SilcUInt32 clients_count)
1079 {
1080   SilcServer server = cmd->server;
1081   char *tmp;
1082   int i, k, count = 0, len;
1083   SilcBuffer packet, idp;
1084   SilcClientEntry entry = NULL;
1085   SilcCommandStatus status;
1086   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1087   char nh[256], uh[256];
1088   int valid_count;
1089
1090   status = SILC_STATUS_OK;
1091
1092   /* Process only entries that are not registered anymore. */
1093   valid_count = 0;
1094   for (i = 0; i < clients_count; i++) {
1095     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1096       clients[i] = NULL;
1097     else
1098       valid_count++;
1099   }
1100
1101   if (!valid_count) {
1102     /* No valid entries found at all, just send error */
1103     unsigned char *tmp;
1104     
1105     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1106     if (tmp)
1107       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1108                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1109                                            3, tmp, strlen(tmp));
1110     return;
1111   }
1112
1113   if (valid_count > 1)
1114     status = SILC_STATUS_LIST_START;
1115
1116   for (i = 0, k = 0; i < clients_count; i++) {
1117     entry = clients[i];
1118     if (!entry)
1119       continue;
1120
1121     if (k >= 1)
1122       status = SILC_STATUS_LIST_ITEM;
1123     if (valid_count > 1 && k == valid_count - 1)
1124       status = SILC_STATUS_LIST_END;
1125     if (count && k - 1 == count)
1126       status = SILC_STATUS_LIST_END;
1127     if (count && k - 1 > count)
1128       break;
1129
1130     /* Send WHOWAS reply */
1131     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1132     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1133     memset(uh, 0, sizeof(uh));
1134     memset(nh, 0, sizeof(nh));
1135
1136     strncat(nh, entry->nickname, strlen(entry->nickname));
1137     if (!strchr(entry->nickname, '@')) {
1138       strncat(nh, "@", 1);
1139       if (entry->servername) {
1140         strncat(nh, entry->servername, strlen(entry->servername));
1141       } else {
1142         len = entry->router ? strlen(entry->router->server_name) :
1143           strlen(server->server_name);
1144         strncat(nh, entry->router ? entry->router->server_name :
1145                 server->server_name, len);
1146       }
1147     }
1148       
1149     strncat(uh, entry->username, strlen(entry->username));
1150     if (!strchr(entry->username, '@')) {
1151       strncat(uh, "@", 1);
1152       strcat(uh, "*private*");
1153     }
1154       
1155     packet = 
1156       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1157                                            status, 0, ident, 4, 
1158                                            2, idp->data, idp->len,
1159                                            3, nh, strlen(nh),
1160                                            4, uh, strlen(uh),
1161                                            5, entry->userinfo, 
1162                                            entry->userinfo ? 
1163                                            strlen(entry->userinfo) : 0);
1164     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1165                             0, packet->data, packet->len, FALSE);
1166     
1167     silc_buffer_free(packet);
1168     silc_buffer_free(idp);
1169
1170     k++;
1171   }
1172 }
1173
1174 static int
1175 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1176 {
1177   SilcServer server = cmd->server;
1178   char *nick = NULL, *server_name = NULL;
1179   int count = 0;
1180   SilcClientEntry *clients = NULL;
1181   SilcUInt32 clients_count = 0;
1182   int ret = 0;
1183   bool check_global = FALSE;
1184
1185   /* Protocol dictates that we must always send the received WHOWAS request
1186      to our router if we are normal server, so let's do it now unless we
1187      are standalone. We will not send any replies to the client until we
1188      have received reply from the router. */
1189   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1190       server->server_type == SILC_SERVER && !cmd->pending && 
1191       !server->standalone) {
1192     SilcBuffer tmpbuf;
1193     SilcUInt16 old_ident;
1194
1195     old_ident = silc_command_get_ident(cmd->payload);
1196     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1197     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1198
1199     /* Send WHOWAS command to our router */
1200     silc_server_packet_send(server, (SilcSocketConnection)
1201                             server->router->connection,
1202                             SILC_PACKET_COMMAND, cmd->packet->flags,
1203                             tmpbuf->data, tmpbuf->len, TRUE);
1204
1205     /* Reprocess this packet after received reply from router */
1206     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1207                                 silc_command_get_ident(cmd->payload),
1208                                 silc_server_command_whowas,
1209                                 silc_server_command_dup(cmd));
1210     cmd->pending = TRUE;
1211     silc_command_set_ident(cmd->payload, old_ident);
1212
1213     silc_buffer_free(tmpbuf);
1214     ret = -1;
1215     goto out;
1216   }
1217
1218   /* We are ready to process the command request. Let's search for the
1219      requested client and send reply to the requesting client. */
1220
1221   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1222     check_global = TRUE;
1223   else if (server->server_type != SILC_SERVER)
1224     check_global = TRUE;
1225
1226   /* Parse the whowas request */
1227   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1228     return 0;
1229
1230   /* Get all clients matching that nickname from local list */
1231   if (!silc_idlist_get_clients_by_nickname(server->local_list, 
1232                                            nick, server_name,
1233                                            &clients, &clients_count))
1234     silc_idlist_get_clients_by_hash(server->local_list, 
1235                                     nick, server->md5hash,
1236                                     &clients, &clients_count);
1237   
1238   /* Check global list as well */
1239   if (check_global) {
1240     if (!silc_idlist_get_clients_by_nickname(server->global_list, 
1241                                              nick, server_name,
1242                                              &clients, &clients_count))
1243       silc_idlist_get_clients_by_hash(server->global_list, 
1244                                       nick, server->md5hash,
1245                                       &clients, &clients_count);
1246   }
1247   
1248   if (!clients) {
1249     /* Such a client really does not exist in the SILC network. */
1250     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1251                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1252                                          3, nick, strlen(nick));
1253     goto out;
1254   }
1255
1256   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1257     ret = -1;
1258     goto out;
1259   }
1260
1261   /* Send the command reply to the client */
1262   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1263
1264  out:
1265   silc_free(clients);
1266   silc_free(nick);
1267   silc_free(server_name);
1268   return ret;
1269 }
1270
1271 /* Server side of command WHOWAS. */
1272
1273 SILC_SERVER_CMD_FUNC(whowas)
1274 {
1275   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1276   int ret = 0;
1277
1278   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1279
1280   ret = silc_server_command_whowas_process(cmd);
1281   silc_server_command_free(cmd);
1282 }
1283
1284 /******************************************************************************
1285
1286                               IDENTIFY Functions
1287
1288 ******************************************************************************/
1289
1290 static void 
1291 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1292 {
1293   SilcServer server = cmd->server;
1294   SilcBuffer tmpbuf;
1295   SilcUInt16 old_ident;
1296
1297   old_ident = silc_command_get_ident(cmd->payload);
1298   silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1299   tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1300
1301   /* Send IDENTIFY command to our router */
1302   silc_server_packet_send(server, (SilcSocketConnection)
1303                           server->router->connection,
1304                           SILC_PACKET_COMMAND, cmd->packet->flags,
1305                           tmpbuf->data, tmpbuf->len, TRUE);
1306
1307   /* Reprocess this packet after received reply from router */
1308   silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1309                               silc_command_get_ident(cmd->payload),
1310                               silc_server_command_identify,
1311                               silc_server_command_dup(cmd));
1312   cmd->pending = TRUE;
1313   silc_command_set_ident(cmd->payload, old_ident);
1314   silc_buffer_free(tmpbuf);
1315 }
1316
1317 static int
1318 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1319                                    SilcClientEntry **clients,
1320                                    SilcUInt32 *clients_count,
1321                                    SilcServerEntry **servers,
1322                                    SilcUInt32 *servers_count,
1323                                    SilcChannelEntry **channels,
1324                                    SilcUInt32 *channels_count,
1325                                    SilcUInt32 *count)
1326 {
1327   SilcServer server = cmd->server;
1328   unsigned char *tmp;
1329   SilcUInt32 len;
1330   SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1331   SilcIDPayload idp;
1332   bool check_global = FALSE;
1333   void *entry;
1334   int i;
1335   bool error = FALSE;
1336
1337   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1338     check_global = TRUE;
1339   else if (server->server_type != SILC_SERVER)
1340     check_global = TRUE;
1341
1342   /* If ID Payload is in the command it must be used instead of names */
1343   tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1344   if (!tmp) {
1345     /* No ID, get the names. */
1346
1347     /* If we are normal server and have not resolved information from
1348        router yet, do so now. */
1349     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1350         server->server_type == SILC_SERVER && !cmd->pending && 
1351         !server->standalone) {
1352       silc_server_command_identify_send_router(cmd);
1353       return -1;
1354     }
1355
1356     /* Try to get nickname@server. */
1357     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1358     if (tmp) {
1359       char *nick = NULL;
1360       char *nick_server = NULL;
1361
1362       silc_parse_userfqdn(tmp, &nick, &nick_server);
1363
1364       if (!silc_idlist_get_clients_by_hash(server->local_list, 
1365                                            nick, server->md5hash,
1366                                            clients, clients_count))
1367         silc_idlist_get_clients_by_nickname(server->local_list, 
1368                                             nick, nick_server,
1369                                             clients, clients_count);
1370       if (check_global) {
1371         if (!silc_idlist_get_clients_by_hash(server->global_list, 
1372                                              nick, server->md5hash,
1373                                              clients, clients_count))
1374           silc_idlist_get_clients_by_nickname(server->global_list, 
1375                                               nick, nick_server,
1376                                               clients, clients_count);
1377       }
1378
1379       silc_free(nick);
1380       silc_free(nick_server);
1381
1382       if (!(*clients)) {
1383         /* the nickname does not exist, send error reply */
1384         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1385                                              SILC_STATUS_ERR_NO_SUCH_NICK,
1386                                              3, tmp, strlen(tmp));
1387         return 0;
1388       }
1389     }
1390
1391     /* Try to get server name */
1392     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1393     if (tmp) {
1394       entry = silc_idlist_find_server_by_name(server->local_list,
1395                                               tmp, TRUE, NULL);
1396       if (!entry && check_global)
1397         entry = silc_idlist_find_server_by_name(server->global_list,
1398                                                 tmp, TRUE, NULL);
1399       if (entry) {
1400         *servers = silc_realloc(*servers, sizeof(**servers) * 
1401                                 (*servers_count + 1));
1402         (*servers)[(*servers_count)++] = entry;
1403       }
1404
1405       if (!(*servers)) {
1406         /* the server does not exist, send error reply */
1407         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1408                                              SILC_STATUS_ERR_NO_SUCH_SERVER,
1409                                              3, tmp, strlen(tmp));
1410         return 0;
1411       }
1412     }
1413
1414     /* Try to get channel name */
1415     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1416     if (tmp) {
1417       entry = silc_idlist_find_channel_by_name(server->local_list,
1418                                                tmp, NULL);
1419       if (!entry && check_global)
1420         entry = silc_idlist_find_channel_by_name(server->global_list,
1421                                                  tmp, NULL);
1422       if (entry) {
1423         *channels = silc_realloc(*channels, sizeof(**channels) * 
1424                                  (*channels_count + 1));
1425         (*channels)[(*channels_count)++] = entry;
1426       }
1427
1428       if (!(*channels)) {
1429         /* The channel does not exist, send error reply */
1430         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1431                                              SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1432                                              3, tmp, strlen(tmp));
1433         return 0;
1434       }
1435     }
1436
1437     if (!(*clients) && !(*servers) && !(*channels)) {
1438       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1439                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1440       return 0;
1441     }
1442   } else {
1443     /* Command includes ID, we must use that.  Also check whether the command
1444        has more than one ID set - take them all. */
1445
1446     /* Take all ID's from the command packet */
1447     for (i = 0; i < argc; i++) {
1448       void *id;
1449
1450       tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1451       if (!tmp)
1452         continue;
1453       
1454       idp = silc_id_payload_parse(tmp, len);
1455       if (!idp) {
1456         silc_free(*clients);
1457         silc_free(*servers);
1458         silc_free(*channels);
1459         silc_server_command_send_status_reply(
1460                                        cmd, SILC_COMMAND_IDENTIFY,
1461                                        SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1462         return 0;
1463       }
1464
1465       id = silc_id_payload_get_id(idp);
1466       
1467       switch (silc_id_payload_get_type(idp)) {
1468         
1469       case SILC_ID_CLIENT:
1470         entry = (void *)silc_idlist_find_client_by_id(server->local_list, 
1471                                                       id, TRUE, NULL);
1472         if (!entry && check_global)
1473           entry = (void *)silc_idlist_find_client_by_id(server->global_list, 
1474                                                         id, TRUE, NULL);
1475         if (entry) {
1476           *clients = silc_realloc(*clients, sizeof(**clients) * 
1477                                   (*clients_count + 1));
1478           (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1479         } else {
1480           /* If we are normal server and have not resolved information from
1481              router yet, do so now. */
1482           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1483               server->server_type == SILC_SERVER && !cmd->pending && 
1484               !server->standalone) {
1485             silc_server_command_identify_send_router(cmd);
1486             silc_free(*clients);
1487             silc_free(*servers);
1488             silc_free(*channels);
1489             return -1;
1490           } else {
1491             silc_server_command_send_status_data(
1492                                         cmd, SILC_COMMAND_IDENTIFY,
1493                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1494                                         2, tmp, len);
1495             error = TRUE;
1496           }
1497         }
1498
1499         break;
1500         
1501       case SILC_ID_SERVER:
1502         entry = (void *)silc_idlist_find_server_by_id(server->local_list, 
1503                                                       id, TRUE, NULL);
1504         if (!entry && check_global)
1505           entry = (void *)silc_idlist_find_server_by_id(server->global_list, 
1506                                                         id, TRUE, NULL);
1507         if (entry) {
1508           *servers = silc_realloc(*servers, sizeof(**servers) * 
1509                                   (*servers_count + 1));
1510           (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1511         } else {
1512           /* If we are normal server and have not resolved information from
1513              router yet, do so now. */
1514           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1515               server->server_type == SILC_SERVER && !cmd->pending && 
1516               !server->standalone) {
1517             silc_server_command_identify_send_router(cmd);
1518             silc_free(*clients);
1519             silc_free(*servers);
1520             silc_free(*channels);
1521             return -1;
1522           } else {
1523             silc_server_command_send_status_data(
1524                                          cmd, SILC_COMMAND_IDENTIFY,
1525                                          SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1526                                          2, tmp, len);
1527             error = TRUE;
1528           }
1529         }
1530         break;
1531         
1532       case SILC_ID_CHANNEL:
1533         entry = (void *)silc_idlist_find_channel_by_id(server->local_list, 
1534                                                        id, NULL);
1535         if (!entry && check_global)
1536           entry = (void *)silc_idlist_find_channel_by_id(server->global_list, 
1537                                                          id, NULL);
1538         if (entry) {
1539           *channels = silc_realloc(*channels, sizeof(**channels) * 
1540                                    (*channels_count + 1));
1541           (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1542         } else {
1543           /* If we are normal server and have not resolved information from
1544              router yet, do so now. */
1545           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1546               server->server_type == SILC_SERVER && !cmd->pending && 
1547               !server->standalone) {
1548             silc_server_command_identify_send_router(cmd);
1549             silc_free(*clients);
1550             silc_free(*servers);
1551             silc_free(*channels);
1552             return -1;
1553           } else {
1554             silc_server_command_send_status_data(
1555                                          cmd, SILC_COMMAND_IDENTIFY,
1556                                          SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1557                                          2, tmp, len);
1558             error = TRUE;
1559           }
1560         }
1561         break;
1562       }
1563
1564       silc_free(id);
1565     }
1566   }
1567
1568   if (error) {
1569     silc_free(*clients);
1570     silc_free(*servers);
1571     silc_free(*channels);
1572     return FALSE;
1573   }
1574   
1575   /* Get the max count of reply messages allowed */
1576   tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1577   if (tmp)
1578     *count = atoi(tmp);
1579   else
1580     *count = 0;
1581
1582   return 1;
1583 }
1584
1585 /* Checks that all mandatory fields in client entry are present. If not
1586    then send WHOIS request to the server who owns the client. We use
1587    WHOIS because we want to get as much information as possible at once. */
1588
1589 static bool
1590 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1591                                           SilcClientEntry *clients,
1592                                           SilcUInt32 clients_count)
1593 {
1594   SilcServer server = cmd->server;
1595   SilcClientEntry entry;
1596   SilcServerResolveContext resolve = NULL, r = NULL;
1597   SilcUInt32 resolve_count = 0;
1598   int i, k;
1599   bool no_res = TRUE;
1600
1601   for (i = 0; i < clients_count; i++) {
1602     entry = clients[i];
1603     if (!entry)
1604       continue;
1605
1606     if (entry->nickname || 
1607         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1608       if (!entry->router)
1609         continue;
1610
1611       /* If we are normal server, and we've not resolved this client from
1612          router and it is global client, we'll check whether it is on some
1613          channel.  If not then we cannot be sure about its validity, and
1614          we'll resolve it from router. */
1615       if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1616           entry->connection || silc_hash_table_count(entry->channels))
1617         continue;
1618     }
1619
1620     /* We need to resolve this entry since it is not complete */
1621
1622     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1623       /* The entry is being resolved (and we are not the resolver) so attach
1624          to the command reply and we're done with this one. */
1625       silc_server_command_pending(server, SILC_COMMAND_NONE, 
1626                                   entry->resolve_cmd_ident,
1627                                   silc_server_command_identify,
1628                                   silc_server_command_dup(cmd));
1629       no_res = FALSE;
1630     } else {
1631       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1632         /* We've resolved this and it still is not ready.  We'll return
1633            and are that this will be handled again after it is resolved. */
1634         for (i = 0; i < resolve_count; i++) {
1635           for (k = 0; k < r->res_argc; k++)
1636             silc_free(r->res_argv[k]);
1637           silc_free(r->res_argv);
1638           silc_free(r->res_argv_lens);
1639           silc_free(r->res_argv_types);
1640         }
1641         silc_free(resolve);
1642         return FALSE;
1643       } else {
1644         /* We'll resolve this client */
1645         SilcBuffer idp;
1646
1647         r = NULL;
1648         for (k = 0; k < resolve_count; k++) {
1649           if (resolve[k].router == entry->router) {
1650             r = &resolve[k];
1651             break;
1652           }
1653         }
1654
1655         if (!r) {
1656           resolve = silc_realloc(resolve, sizeof(*resolve) * 
1657                                  (resolve_count + 1));
1658           r = &resolve[resolve_count];
1659           memset(r, 0, sizeof(*r));
1660           r->router = entry->router;
1661           r->ident = ++server->cmd_ident;
1662           resolve_count++;
1663         }
1664
1665         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1666                                    (r->res_argc + 1));
1667         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
1668                                         sizeof(*r->res_argv_lens) *
1669                                         (r->res_argc + 1));
1670         r->res_argv_types = silc_realloc(r->res_argv_types, 
1671                                          sizeof(*r->res_argv_types) *
1672                                          (r->res_argc + 1));
1673         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1674         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
1675                                                sizeof(**r->res_argv));
1676         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1677         r->res_argv_lens[r->res_argc] = idp->len;
1678         r->res_argv_types[r->res_argc] = r->res_argc + 3;
1679         r->res_argc++;
1680         silc_buffer_free(idp);
1681
1682         entry->resolve_cmd_ident = r->ident;
1683         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1684         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1685       }
1686     }
1687   }
1688
1689   /* Do the resolving */
1690   for (i = 0; i < resolve_count; i++) {
1691     SilcBuffer res_cmd;
1692
1693     r = &resolve[i];
1694
1695     /* Send WHOIS request. We send WHOIS since we're doing the requesting
1696        now anyway so make it a good one. */
1697     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1698                                           r->res_argc, r->res_argv, 
1699                                           r->res_argv_lens,
1700                                           r->res_argv_types, 
1701                                           r->ident);
1702     silc_server_packet_send(server, r->router->connection,
1703                             SILC_PACKET_COMMAND, cmd->packet->flags,
1704                             res_cmd->data, res_cmd->len, FALSE);
1705
1706     /* Reprocess this packet after received reply */
1707     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1708                                 r->ident,
1709                                 silc_server_command_identify,
1710                                 silc_server_command_dup(cmd));
1711     cmd->pending = TRUE;
1712
1713     silc_buffer_free(res_cmd);
1714     for (k = 0; k < r->res_argc; k++)
1715       silc_free(r->res_argv[k]);
1716     silc_free(r->res_argv);
1717     silc_free(r->res_argv_lens);
1718     silc_free(r->res_argv_types);
1719     no_res = FALSE;
1720   }
1721   silc_free(resolve);
1722
1723   return no_res;
1724 }
1725
1726 static void
1727 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1728                                         SilcClientEntry *clients,
1729                                         SilcUInt32 clients_count,
1730                                         SilcServerEntry *servers,
1731                                         SilcUInt32 servers_count,
1732                                         SilcChannelEntry *channels,
1733                                         SilcUInt32 channels_count,
1734                                         int count)
1735 {
1736   SilcServer server = cmd->server;
1737   int i, k, len, valid_count;
1738   SilcBuffer packet, idp;
1739   SilcCommandStatus status;
1740   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1741   char nh[256], uh[256];
1742   SilcSocketConnection hsock;
1743
1744   status = SILC_STATUS_OK;
1745
1746   if (clients) {
1747     SilcClientEntry entry;
1748
1749     /* Process only valid entries. */
1750     valid_count = 0;
1751     for (i = 0; i < clients_count; i++) {
1752       if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1753         valid_count++;
1754       else
1755         clients[i] = NULL;
1756     }
1757
1758     if (!valid_count) {
1759       /* No valid entries found at all, just send error */
1760       unsigned char *tmp;
1761
1762       tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1763       if (tmp) {
1764         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1765                                              SILC_STATUS_ERR_NO_SUCH_NICK,
1766                                              3, tmp, strlen(tmp));
1767       } else {
1768         tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1769         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1770                                              SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1771                                              2, tmp, len);
1772       }
1773       return;
1774     }
1775
1776     /* Process all valid client entries and send command replies */
1777
1778     if (valid_count > 1)
1779       status = SILC_STATUS_LIST_START;
1780
1781     for (i = 0, k = 0; i < clients_count; i++) {
1782       entry = clients[i];
1783       if (!entry)
1784         continue;
1785
1786       if (k >= 1)
1787         status = SILC_STATUS_LIST_ITEM;
1788       if (valid_count > 1 && k == valid_count - 1 
1789           && !servers_count && !channels_count)
1790         status = SILC_STATUS_LIST_END;
1791       if (count && k - 1 == count)
1792         status = SILC_STATUS_LIST_END;
1793       if (count && k - 1 > count)
1794         break;
1795
1796       /* Send IDENTIFY reply */
1797
1798       idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1799       memset(uh, 0, sizeof(uh));
1800       memset(nh, 0, sizeof(nh));
1801       strncat(nh, entry->nickname, strlen(entry->nickname));
1802       if (!strchr(entry->nickname, '@')) {
1803         strncat(nh, "@", 1);
1804         if (entry->servername) {
1805           strncat(nh, entry->servername, strlen(entry->servername));
1806         } else {
1807           len = entry->router ? strlen(entry->router->server_name) :
1808             strlen(server->server_name);
1809           strncat(nh, entry->router ? entry->router->server_name :
1810                   server->server_name, len);
1811         }
1812       }
1813
1814       if (!entry->username) {
1815         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1816                                                       status, 0, ident, 2,
1817                                                       2, idp->data, idp->len, 
1818                                                       3, nh, strlen(nh));
1819       } else {
1820         strncat(uh, entry->username, strlen(entry->username));
1821         if (!strchr(entry->username, '@')) {
1822           strncat(uh, "@", 1);
1823           hsock = (SilcSocketConnection)entry->connection;
1824           len = strlen(hsock->hostname);
1825           strncat(uh, hsock->hostname, len);
1826         }
1827         
1828         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1829                                                       status, 0, ident, 3,
1830                                                       2, idp->data, idp->len, 
1831                                                       3, nh, strlen(nh),
1832                                                       4, uh, strlen(uh));
1833       }
1834       
1835       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1836                               0, packet->data, packet->len, FALSE);
1837       
1838       silc_buffer_free(packet);
1839       silc_buffer_free(idp);
1840       
1841       k++;
1842     }
1843   }
1844
1845   if (servers) {
1846     SilcServerEntry entry;
1847
1848     if (status == SILC_STATUS_OK && servers_count > 1)
1849       status = SILC_STATUS_LIST_START;
1850
1851     for (i = 0, k = 0; i < servers_count; i++) {
1852       entry = servers[i];
1853       
1854       if (k >= 1)
1855         status = SILC_STATUS_LIST_ITEM;
1856       if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1857         status = SILC_STATUS_LIST_END;
1858       if (count && k - 1 == count)
1859         status = SILC_STATUS_LIST_END;
1860       if (count && k - 1 > count)
1861         break;
1862       
1863       /* Send IDENTIFY reply */
1864       idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1865       packet = 
1866         silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1867                                              status, 0, ident, 2,
1868                                              2, idp->data, idp->len, 
1869                                              3, entry->server_name, 
1870                                              entry->server_name ? 
1871                                              strlen(entry->server_name) : 0);
1872       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1873                               0, packet->data, packet->len, FALSE);
1874       
1875       silc_buffer_free(packet);
1876       silc_buffer_free(idp);
1877       
1878       k++;
1879     }
1880   }
1881
1882   if (channels) {
1883     SilcChannelEntry entry;
1884
1885     if (status == SILC_STATUS_OK && channels_count > 1)
1886       status = SILC_STATUS_LIST_START;
1887
1888     for (i = 0, k = 0; i < channels_count; i++) {
1889       entry = channels[i];
1890       
1891       if (k >= 1)
1892         status = SILC_STATUS_LIST_ITEM;
1893       if (channels_count > 1 && k == channels_count - 1)
1894         status = SILC_STATUS_LIST_END;
1895       if (count && k - 1 == count)
1896         status = SILC_STATUS_LIST_END;
1897       if (count && k - 1 > count)
1898         break;
1899       
1900       /* Send IDENTIFY reply */
1901       idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1902       packet = 
1903         silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1904                                              status, 0, ident, 2,
1905                                              2, idp->data, idp->len, 
1906                                              3, entry->channel_name, 
1907                                              entry->channel_name ? 
1908                                              strlen(entry->channel_name): 0);
1909       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1910                               0, packet->data, packet->len, FALSE);
1911       
1912       silc_buffer_free(packet);
1913       silc_buffer_free(idp);
1914       
1915       k++;
1916     }
1917   }
1918 }
1919
1920 static int
1921 silc_server_command_identify_process(SilcServerCommandContext cmd)
1922 {
1923   SilcUInt32 count = 0;
1924   int ret = 0;
1925   SilcClientEntry *clients = NULL;
1926   SilcServerEntry *servers = NULL;
1927   SilcChannelEntry *channels = NULL;
1928   SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1929
1930   /* Parse the IDENTIFY request */
1931   ret = silc_server_command_identify_parse(cmd,
1932                                            &clients, &clients_count,
1933                                            &servers, &servers_count,
1934                                            &channels, &channels_count,
1935                                            &count);
1936   if (ret < 1)
1937     return ret;
1938   ret = 0;
1939
1940   /* Check that all mandatory fields are present and request those data
1941      from the server who owns the client if necessary. */
1942   if (clients && !silc_server_command_identify_check_client(cmd, clients, 
1943                                                             clients_count)) {
1944     ret = -1;
1945     goto out;
1946   }
1947
1948   /* Send the command reply to the client */
1949   silc_server_command_identify_send_reply(cmd, 
1950                                           clients, clients_count,
1951                                           servers, servers_count,
1952                                           channels, channels_count, 
1953                                           count);
1954
1955  out:
1956   silc_free(clients);
1957   silc_free(servers);
1958   silc_free(channels);
1959   return ret;
1960 }
1961
1962 SILC_SERVER_CMD_FUNC(identify)
1963 {
1964   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1965   int ret = 0;
1966
1967   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1968
1969   ret = silc_server_command_identify_process(cmd);
1970   silc_server_command_free(cmd);
1971 }
1972
1973 /* Server side of command NICK. Sets nickname for user. Setting
1974    nickname causes generation of a new client ID for the client. The
1975    new client ID is sent to the client after changing the nickname. */
1976
1977 SILC_SERVER_CMD_FUNC(nick)
1978 {
1979   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1980   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1981   SilcServer server = cmd->server;
1982   SilcBuffer packet, nidp, oidp = NULL;
1983   SilcClientID *new_id;
1984   SilcUInt32 nick_len;
1985   char *nick;
1986   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1987   int nickfail = 0;
1988
1989   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1990     goto out;
1991
1992   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1993
1994   /* Check nickname */
1995   nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
1996   if (nick_len > 128)
1997     nick[128] = '\0';
1998   if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
1999     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2000                                           SILC_STATUS_ERR_BAD_NICKNAME);
2001     goto out;
2002   }
2003
2004   /* Check for same nickname */
2005   if (!strcmp(client->nickname, nick)) {
2006     nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2007     goto send_reply;
2008   }
2009
2010   /* Create new Client ID */
2011   while (!silc_id_create_client_id(cmd->server, cmd->server->id, 
2012                                    cmd->server->rng, 
2013                                    cmd->server->md5hash, nick,
2014                                    &new_id)) {
2015     nickfail++;
2016     snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2017   }
2018
2019   /* Send notify about nickname change to our router. We send the new
2020      ID and ask to replace it with the old one. If we are router the
2021      packet is broadcasted. Send NICK_CHANGE notify. */
2022   if (!server->standalone)
2023     silc_server_send_notify_nick_change(server, server->router->connection, 
2024                                         server->server_type == SILC_SERVER ? 
2025                                         FALSE : TRUE, client->id,
2026                                         new_id, nick);
2027
2028   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2029
2030   /* Remove old cache entry */
2031   silc_idcache_del_by_context(server->local_list->clients, client);
2032
2033   /* Free old ID */
2034   silc_free(client->id);
2035
2036   /* Save the nickname as this client is our local client */
2037   silc_free(client->nickname);
2038
2039   client->nickname = strdup(nick);
2040   client->id = new_id;
2041
2042   /* Update client cache */
2043   silc_idcache_add(server->local_list->clients, client->nickname, 
2044                    client->id, (void *)client, 0, NULL);
2045
2046   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2047
2048   /* Send NICK_CHANGE notify to the client's channels */
2049   silc_server_send_notify_on_channels(server, NULL, client, 
2050                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2051                                       oidp->data, oidp->len, 
2052                                       nidp->data, nidp->len,
2053                                       client->nickname, 
2054                                       strlen(client->nickname));
2055
2056  send_reply:
2057   /* Send the new Client ID as reply command back to client */
2058   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
2059                                                 SILC_STATUS_OK, 0, ident, 1, 
2060                                                 2, nidp->data, nidp->len);
2061   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2062                           0, packet->data, packet->len, FALSE);
2063
2064   silc_buffer_free(packet);
2065   silc_buffer_free(nidp);
2066   if (oidp)
2067     silc_buffer_free(oidp);
2068   
2069  out:
2070   silc_server_command_free(cmd);
2071 }
2072
2073 /* Sends the LIST command reply */
2074
2075 static void
2076 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2077                                     SilcChannelEntry *lch, 
2078                                     SilcUInt32 lch_count,
2079                                     SilcChannelEntry *gch,
2080                                     SilcUInt32 gch_count)
2081 {
2082   int i, k;
2083   SilcBuffer packet, idp;
2084   SilcChannelEntry entry;
2085   SilcCommandStatus status;
2086   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2087   char *topic;
2088   unsigned char usercount[4];
2089   SilcUInt32 users;
2090   int valid_lcount = 0, valid_rcount = 0;
2091
2092   for (i = 0; i < lch_count; i++) {
2093     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2094       lch[i] = NULL;
2095     else
2096       valid_lcount++;
2097   }
2098   for (i = 0; i < gch_count; i++) {
2099     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2100       gch[i] = NULL;
2101     else
2102       valid_rcount++;
2103   }
2104
2105   status = SILC_STATUS_OK;
2106   if ((lch_count + gch_count) > 1)
2107     status = SILC_STATUS_LIST_START;
2108
2109   /* Local list */
2110   for (i = 0, k = 0; i < lch_count; i++) {
2111     entry = lch[i];
2112     if (!entry)
2113       continue;
2114
2115     if (k >= 1)
2116       status = SILC_STATUS_LIST_ITEM;
2117     if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2118       status = SILC_STATUS_LIST_END;
2119
2120     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2121
2122     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2123       topic = "*private*";
2124       memset(usercount, 0, sizeof(usercount));
2125     } else {
2126       topic = entry->topic;
2127       users = silc_hash_table_count(entry->user_list);
2128       SILC_PUT32_MSB(users, usercount);
2129     }
2130
2131     /* Send the reply */
2132     packet = 
2133       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2134                                            status, 0, ident, 4,
2135                                            2, idp->data, idp->len,
2136                                            3, entry->channel_name, 
2137                                            strlen(entry->channel_name),
2138                                            4, topic, topic ? strlen(topic) : 0,
2139                                            5, usercount, 4);
2140     silc_server_packet_send(cmd->server, cmd->sock, 
2141                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2142                             packet->len, FALSE);
2143     silc_buffer_free(packet);
2144     silc_buffer_free(idp);
2145     k++;
2146   }
2147
2148   /* Global list */
2149   for (i = 0, k = 0; i < gch_count; i++) {
2150     entry = gch[i];
2151     if (!entry)
2152       continue;
2153
2154     if (k >= 1)
2155       status = SILC_STATUS_LIST_ITEM;
2156     if (valid_rcount > 1 && k == valid_rcount - 1)
2157       status = SILC_STATUS_LIST_END;
2158
2159     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2160
2161     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2162       topic = "*private*";
2163       memset(usercount, 0, sizeof(usercount));
2164     } else {
2165       topic = entry->topic;
2166       users = entry->user_count;
2167       SILC_PUT32_MSB(users, usercount);
2168     }
2169
2170     /* Send the reply */
2171     packet = 
2172       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2173                                            status, 0, ident, 4,
2174                                            2, idp->data, idp->len,
2175                                            3, entry->channel_name, 
2176                                            strlen(entry->channel_name),
2177                                            4, topic, topic ? strlen(topic) : 0,
2178                                            5, usercount, 4);
2179     silc_server_packet_send(cmd->server, cmd->sock, 
2180                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2181                             packet->len, FALSE);
2182     silc_buffer_free(packet);
2183     silc_buffer_free(idp);
2184     k++;
2185   }
2186 }
2187
2188 /* Server side of LIST command. This lists the channel of the requested
2189    server. Secret channels are not listed. */
2190
2191 SILC_SERVER_CMD_FUNC(list)
2192 {
2193   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2194   SilcServer server = cmd->server;
2195   SilcChannelID *channel_id = NULL;
2196   unsigned char *tmp;
2197   SilcUInt32 tmp_len;
2198   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2199   SilcUInt32 lch_count = 0, gch_count = 0;
2200
2201   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2202
2203   /* If we are normal server, send the command to router, since we
2204      want to know all channels in the network. */
2205   if (!cmd->pending && server->server_type == SILC_SERVER && 
2206       !server->standalone) {
2207     SilcBuffer tmpbuf;
2208     SilcUInt16 old_ident;
2209     
2210     old_ident = silc_command_get_ident(cmd->payload);
2211     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2212     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2213     silc_server_packet_send(server, server->router->connection,
2214                             SILC_PACKET_COMMAND, cmd->packet->flags,
2215                             tmpbuf->data, tmpbuf->len, TRUE);
2216
2217     /* Reprocess this packet after received reply from router */
2218     silc_server_command_pending(server, SILC_COMMAND_LIST, 
2219                                 silc_command_get_ident(cmd->payload),
2220                                 silc_server_command_list, 
2221                                 silc_server_command_dup(cmd));
2222     cmd->pending = TRUE;
2223     silc_command_set_ident(cmd->payload, old_ident);
2224     silc_buffer_free(tmpbuf);
2225     goto out;
2226   }
2227
2228   /* Get Channel ID */
2229   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2230   if (tmp) {
2231     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2232     if (!channel_id) {
2233       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2234                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
2235       goto out;
2236     }
2237   }
2238
2239   /* Get the channels from local list */
2240   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2241                                        &lch_count);
2242   
2243   /* Get the channels from global list */
2244   gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2245                                        &gch_count);
2246
2247   /* Send the reply */
2248   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
2249                                       gchannels, gch_count);
2250
2251   silc_free(lchannels);
2252   silc_free(gchannels);
2253
2254  out:
2255   silc_server_command_free(cmd);
2256 }
2257
2258 /* Server side of TOPIC command. Sets topic for channel and/or returns
2259    current topic to client. */
2260
2261 SILC_SERVER_CMD_FUNC(topic)
2262 {
2263   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2264   SilcServer server = cmd->server;
2265   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2266   SilcChannelID *channel_id;
2267   SilcChannelEntry channel;
2268   SilcChannelClientEntry chl;
2269   SilcBuffer packet, idp;
2270   unsigned char *tmp;
2271   SilcUInt32 argc, tmp_len;
2272   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2273
2274   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2275
2276   argc = silc_argument_get_arg_num(cmd->args);
2277
2278   /* Get Channel ID */
2279   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2280   if (!tmp) {
2281     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2282                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2283     goto out;
2284   }
2285   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2286   if (!channel_id) {
2287     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2288                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2289     goto out;
2290   }
2291
2292   /* Check whether the channel exists */
2293   channel = silc_idlist_find_channel_by_id(server->local_list, 
2294                                            channel_id, NULL);
2295   if (!channel) {
2296     channel = silc_idlist_find_channel_by_id(server->global_list, 
2297                                              channel_id, NULL);
2298     if (!channel) {
2299       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2300                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2301       goto out;
2302     }
2303   }
2304
2305   if (argc > 1) {
2306     /* Get the topic */
2307     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2308     if (!tmp) {
2309       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2310                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2311       goto out;
2312     }
2313
2314     if (strlen(tmp) > 256) {
2315       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2316                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2317       goto out;
2318     }
2319
2320     /* See whether the client is on channel and has rights to change topic */
2321     if (!silc_server_client_on_channel(client, channel, &chl)) {
2322       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2323                                             SILC_STATUS_ERR_NOT_ON_CHANNEL);
2324       goto out;
2325     }
2326
2327     if (chl->mode == SILC_CHANNEL_UMODE_NONE && 
2328         channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2329       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2330                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2331       goto out;
2332     }
2333
2334     /* Set the topic for channel */
2335     silc_free(channel->topic);
2336     channel->topic = strdup(tmp);
2337
2338     /* Send TOPIC_SET notify type to the network */
2339     if (!server->standalone)
2340       silc_server_send_notify_topic_set(server, server->router->connection,
2341                                         server->server_type == SILC_ROUTER ?
2342                                         TRUE : FALSE, channel, 
2343                                         client->id, SILC_ID_CLIENT,
2344                                         channel->topic);
2345
2346     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2347
2348     /* Send notify about topic change to all clients on the channel */
2349     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
2350                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2351                                        idp->data, idp->len,
2352                                        channel->topic, strlen(channel->topic));
2353     silc_buffer_free(idp);
2354   }
2355
2356   /* Send the topic to client as reply packet */
2357   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2358   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2359                                                 SILC_STATUS_OK, 0, ident, 2, 
2360                                                 2, idp->data, idp->len,
2361                                                 3, channel->topic, 
2362                                                 channel->topic ? 
2363                                                 strlen(channel->topic) : 0);
2364   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2365                           0, packet->data, packet->len, FALSE);
2366
2367   silc_buffer_free(packet);
2368   silc_buffer_free(idp);
2369   silc_free(channel_id);
2370
2371  out:
2372   silc_server_command_free(cmd);
2373 }
2374
2375 /* Server side of INVITE command. Invites some client to join some channel. 
2376    This command is also used to manage the invite list of the channel. */
2377
2378 SILC_SERVER_CMD_FUNC(invite)
2379 {
2380   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2381   SilcServer server = cmd->server;
2382   SilcSocketConnection sock = cmd->sock, dest_sock;
2383   SilcChannelClientEntry chl;
2384   SilcClientEntry sender, dest;
2385   SilcClientID *dest_id = NULL;
2386   SilcChannelEntry channel;
2387   SilcChannelID *channel_id = NULL;
2388   SilcIDListData idata;
2389   SilcBuffer idp, idp2, packet;
2390   unsigned char *tmp, *add, *del;
2391   SilcUInt32 len;
2392   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2393
2394   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2395
2396   /* Get Channel ID */
2397   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2398   if (!tmp) {
2399     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2400                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2401     goto out;
2402   }
2403   channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2404   if (!channel_id) {
2405     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2407     goto out;
2408   }
2409
2410   /* Get the channel entry */
2411   channel = silc_idlist_find_channel_by_id(server->local_list, 
2412                                            channel_id, NULL);
2413   if (!channel) {
2414     channel = silc_idlist_find_channel_by_id(server->global_list, 
2415                                              channel_id, NULL);
2416     if (!channel) {
2417       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2418                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2419       goto out;
2420     }
2421   }
2422
2423   /* Check whether the sender of this command is on the channel. */
2424   sender = (SilcClientEntry)sock->user_data;
2425   if (!silc_server_client_on_channel(sender, channel, &chl)) {
2426     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2427                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2428     goto out;
2429   }
2430
2431   /* Check whether the channel is invite-only channel. If yes then the
2432      sender of this command must be at least channel operator. */
2433   if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2434       channel->mode & SILC_CHANNEL_MODE_INVITE) {
2435     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2436                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2437     goto out;
2438   }
2439
2440   /* Get destination client ID */
2441   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2442   if (tmp) {
2443     char invite[512];
2444     bool resolve;
2445
2446     dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2447     if (!dest_id) {
2448       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2449                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2450       goto out;
2451     }
2452
2453     /* Get the client entry */
2454     dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2455     if (!dest) {
2456       if (server->server_type != SILC_SERVER || !resolve) {
2457         silc_server_command_send_status_reply(
2458                                         cmd, SILC_COMMAND_INVITE,
2459                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2460         goto out;
2461       }
2462       
2463       /* The client info is being resolved. Reprocess this packet after
2464          receiving the reply to the query. */
2465       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2466                                   server->cmd_ident,
2467                                   silc_server_command_invite, 
2468                                   silc_server_command_dup(cmd));
2469       cmd->pending = TRUE;
2470       silc_free(channel_id);
2471       silc_free(dest_id);
2472       goto out;
2473     }
2474
2475     /* Check whether the requested client is already on the channel. */
2476     if (silc_server_client_on_channel(dest, channel, NULL)) {
2477       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2478                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2479       goto out;
2480     }
2481     
2482     /* Get route to the client */
2483     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2484     if (!dest_sock) {
2485       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2486                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2487       goto out;
2488     }
2489
2490     memset(invite, 0, sizeof(invite));
2491     strncat(invite, dest->nickname, strlen(dest->nickname));
2492     strncat(invite, "!", 1);
2493     strncat(invite, dest->username, strlen(dest->username));
2494     if (!strchr(dest->username, '@')) {
2495       strncat(invite, "@", 1);
2496       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2497     }
2498
2499     len = strlen(invite);
2500     if (!channel->invite_list)
2501       channel->invite_list = silc_calloc(len + 2, 
2502                                          sizeof(*channel->invite_list));
2503     else
2504       channel->invite_list = silc_realloc(channel->invite_list, 
2505                                           sizeof(*channel->invite_list) * 
2506                                           (len + 
2507                                            strlen(channel->invite_list) + 2));
2508     strncat(channel->invite_list, invite, len);
2509     strncat(channel->invite_list, ",", 1);
2510
2511     /* Send notify to the client that is invited to the channel */
2512     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2513     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2514     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2515                                  SILC_ID_CLIENT,
2516                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2517                                  idp->data, idp->len, 
2518                                  channel->channel_name, 
2519                                  strlen(channel->channel_name),
2520                                  idp2->data, idp2->len);
2521     silc_buffer_free(idp);
2522     silc_buffer_free(idp2);
2523   }
2524
2525   /* Add the client to the invite list of the channel */
2526   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2527   if (add) {
2528     if (!channel->invite_list)
2529       channel->invite_list = silc_calloc(len + 2, 
2530                                          sizeof(*channel->invite_list));
2531     else
2532       channel->invite_list = silc_realloc(channel->invite_list, 
2533                                           sizeof(*channel->invite_list) * 
2534                                           (len + 
2535                                            strlen(channel->invite_list) + 2));
2536     if (add[len - 1] == ',')
2537       add[len - 1] = '\0';
2538     
2539     strncat(channel->invite_list, add, len);
2540     strncat(channel->invite_list, ",", 1);
2541   }
2542
2543   /* Get the invite to be removed and remove it from the list */
2544   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2545   if (del && channel->invite_list) {
2546     char *start, *end, *n;
2547
2548     if (!strncmp(channel->invite_list, del, 
2549                  strlen(channel->invite_list) - 1)) {
2550       silc_free(channel->invite_list);
2551       channel->invite_list = NULL;
2552     } else {
2553       start = strstr(channel->invite_list, del);
2554       if (start && strlen(start) >= len) {
2555         end = start + len;
2556         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2557         strncat(n, channel->invite_list, start - channel->invite_list);
2558         strncat(n, end + 1, ((channel->invite_list + 
2559                               strlen(channel->invite_list)) - end) - 1);
2560         silc_free(channel->invite_list);
2561         channel->invite_list = n;
2562       }
2563     }
2564   }
2565
2566   /* Send notify to the primary router */
2567   if (!server->standalone)
2568     silc_server_send_notify_invite(server, server->router->connection,
2569                                    server->server_type == SILC_ROUTER ?
2570                                    TRUE : FALSE, channel,
2571                                    sender->id, add, del);
2572
2573   /* Send command reply */
2574   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2575
2576   if (add || del)
2577     packet = 
2578       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2579                                            SILC_STATUS_OK, 0, ident, 2,
2580                                            2, tmp, len,
2581                                            3, channel->invite_list,
2582                                            channel->invite_list ?
2583                                            strlen(channel->invite_list) : 0);
2584   else
2585     packet = 
2586       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2587                                            SILC_STATUS_OK, 0, ident, 1,
2588                                            2, tmp, len);
2589   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2590                           packet->data, packet->len, FALSE);
2591   silc_buffer_free(packet);
2592
2593  out:
2594   silc_free(dest_id);
2595   silc_free(channel_id);
2596   silc_server_command_free(cmd);
2597 }
2598
2599 typedef struct {
2600   SilcServer server;
2601   SilcSocketConnection sock;
2602   char *signoff;
2603 } *QuitInternal;
2604
2605 /* Quits connection to client. This gets called if client won't
2606    close the connection even when it has issued QUIT command. */
2607
2608 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2609 {
2610   QuitInternal q = (QuitInternal)context;
2611
2612   /* Free all client specific data, such as client entry and entires
2613      on channels this client may be on. */
2614   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2615                                TRUE, q->signoff);
2616   q->sock->user_data = NULL;
2617
2618   /* Close the connection on our side */
2619   silc_server_close_connection(q->server, q->sock);
2620
2621   silc_free(q->signoff);
2622   silc_free(q);
2623 }
2624
2625 /* Quits SILC session. This is the normal way to disconnect client. */
2626  
2627 SILC_SERVER_CMD_FUNC(quit)
2628 {
2629   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2630   SilcServer server = cmd->server;
2631   SilcSocketConnection sock = cmd->sock;
2632   QuitInternal q;
2633   unsigned char *tmp = NULL;
2634   SilcUInt32 len = 0;
2635
2636   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2637
2638   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2639     goto out;
2640
2641   /* Get destination ID */
2642   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2643   if (len > 128)
2644     tmp = NULL;
2645
2646   q = silc_calloc(1, sizeof(*q));
2647   q->server = server;
2648   q->sock = sock;
2649   q->signoff = tmp ? strdup(tmp) : NULL;
2650
2651   /* We quit the connection with little timeout */
2652   silc_schedule_task_add(server->schedule, sock->sock,
2653                      silc_server_command_quit_cb, (void *)q,
2654                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2655
2656  out:
2657   silc_server_command_free(cmd);
2658 }
2659
2660 /* Server side of command KILL. This command is used by router operator
2661    to remove an client from the SILC Network temporarily. */
2662
2663 SILC_SERVER_CMD_FUNC(kill)
2664 {
2665   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2666   SilcServer server = cmd->server;
2667   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2668   SilcClientEntry remote_client;
2669   SilcClientID *client_id;
2670   unsigned char *tmp, *comment;
2671   SilcUInt32 tmp_len, tmp_len2;
2672   SilcBuffer killer;
2673   bool local;
2674
2675   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2676
2677   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2678     goto out;
2679
2680   /* KILL command works only on router */
2681   if (server->server_type != SILC_ROUTER) {
2682     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2683                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2684     goto out;
2685   }
2686
2687   /* Check whether client has the permissions. */
2688   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2689     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2690                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2691     goto out;
2692   }
2693
2694   /* Get the client ID */
2695   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2696   if (!tmp) {
2697     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2698                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2699     goto out;
2700   }
2701   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2702   if (!client_id) {
2703     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2704                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2705     goto out;
2706   }
2707
2708   /* Get the client entry */
2709   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2710                                                 client_id, TRUE, NULL);
2711   local = TRUE;
2712   if (!remote_client) {
2713     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2714                                                   client_id, TRUE, NULL);
2715     local = FALSE;
2716     if (!remote_client) {
2717       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2718                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2719       goto out;
2720     }
2721   }
2722
2723   /* Get comment */
2724   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2725   if (tmp_len2 > 128)
2726     tmp_len2 = 128;
2727
2728   /* Send reply to the sender */
2729   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2730                                         SILC_STATUS_OK);
2731
2732   /* Send the KILL notify packets. First send it to the channel, then
2733      to our primary router and then directly to the client who is being
2734      killed right now. */
2735
2736   /* Send KILLED notify to the channels. It is not sent to the client
2737      as it will be sent differently destined directly to the client and not
2738      to the channel. */
2739   killer = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2740   silc_server_send_notify_on_channels(server, remote_client, 
2741                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2742                                       3, tmp, tmp_len,
2743                                       comment, comment ? tmp_len2 : 0,
2744                                       killer->data, killer->len);
2745   silc_buffer_free(killer);
2746
2747   /* Send KILLED notify to primary route */
2748   if (!server->standalone)
2749     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2750                                    remote_client->id, comment, client->id);
2751
2752   /* Send KILLED notify to the client directly */
2753   silc_server_send_notify_killed(server, remote_client->connection ? 
2754                                  remote_client->connection : 
2755                                  remote_client->router->connection, FALSE,
2756                                  remote_client->id, comment, client->id);
2757
2758   /* Remove the client from all channels. This generates new keys to the
2759      channels as well. */
2760   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2761                                    NULL, TRUE);
2762
2763   /* Remove the client entry, If it is locally connected then we will also
2764      disconnect the client here */
2765   if (remote_client->connection) {
2766     /* Remove locally conneted client */
2767     SilcSocketConnection sock = remote_client->connection;
2768     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2769     silc_server_close_connection(server, sock);
2770   } else {
2771     /* Update statistics */
2772     if (remote_client->connection)
2773       server->stat.my_clients--;
2774     if (server->stat.cell_clients)
2775       server->stat.cell_clients--;
2776     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2777     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2778
2779     /* Remove remote client */
2780     silc_idlist_del_client(local ? server->local_list :
2781                            server->global_list, remote_client);
2782   }
2783
2784  out:
2785   silc_server_command_free(cmd);
2786 }
2787
2788 /* Server side of command INFO. This sends information about us to 
2789    the client. If client requested specific server we will send the 
2790    command to that server. */
2791
2792 SILC_SERVER_CMD_FUNC(info)
2793 {
2794   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2795   SilcServer server = cmd->server;
2796   SilcBuffer packet, idp;
2797   unsigned char *tmp;
2798   SilcUInt32 tmp_len;
2799   char *dest_server, *server_info = NULL, *server_name;
2800   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2801   SilcServerEntry entry = NULL;
2802   SilcServerID *server_id = NULL;
2803
2804   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2805
2806   /* Get server name */
2807   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2808
2809   /* Get Server ID */
2810   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2811   if (tmp) {
2812     server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2813     if (!server_id) {
2814       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2815                                             SILC_STATUS_ERR_NO_SERVER_ID);
2816       goto out;
2817     }
2818   }
2819
2820   if (server_id) {
2821     /* Check whether we have this server cached */
2822     entry = silc_idlist_find_server_by_id(server->local_list,
2823                                           server_id, TRUE, NULL);
2824     if (!entry) {
2825       entry = silc_idlist_find_server_by_id(server->global_list,
2826                                             server_id, TRUE, NULL);
2827       if (!entry && server->server_type != SILC_SERVER) {
2828         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2829                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2830         goto out;
2831       }
2832     }
2833   }
2834
2835   /* Some buggy servers has sent request to router about themselves. */
2836   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2837     goto out;
2838
2839   if ((!dest_server && !server_id && !entry) || (entry && 
2840                                                  entry == server->id_entry) ||
2841       (dest_server && !cmd->pending && 
2842        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2843     /* Send our reply */
2844     char info_string[256];
2845
2846     memset(info_string, 0, sizeof(info_string));
2847     snprintf(info_string, sizeof(info_string), 
2848              "location: %s server: %s admin: %s <%s>",
2849              server->config->server_info->location,
2850              server->config->server_info->server_type,
2851              server->config->server_info->admin,
2852              server->config->server_info->email);
2853
2854     server_info = info_string;
2855     entry = server->id_entry;
2856   } else {
2857     /* Check whether we have this server cached */
2858     if (!entry && dest_server) {
2859       entry = silc_idlist_find_server_by_name(server->global_list,
2860                                               dest_server, TRUE, NULL);
2861       if (!entry) {
2862         entry = silc_idlist_find_server_by_name(server->local_list,
2863                                                 dest_server, TRUE, NULL);
2864       }
2865     }
2866
2867     if (!cmd->pending &&
2868         server->server_type != SILC_SERVER && entry && !entry->server_info) {
2869       /* Send to the server */
2870       SilcBuffer tmpbuf;
2871       SilcUInt16 old_ident;
2872
2873       old_ident = silc_command_get_ident(cmd->payload);
2874       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2875       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2876
2877       silc_server_packet_send(server, entry->connection,
2878                               SILC_PACKET_COMMAND, cmd->packet->flags,
2879                               tmpbuf->data, tmpbuf->len, TRUE);
2880
2881       /* Reprocess this packet after received reply from router */
2882       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2883                                   silc_command_get_ident(cmd->payload),
2884                                   silc_server_command_info,
2885                                   silc_server_command_dup(cmd));
2886       cmd->pending = TRUE;
2887       silc_command_set_ident(cmd->payload, old_ident);
2888       silc_buffer_free(tmpbuf);
2889       goto out;
2890     }
2891
2892     if (!entry && !cmd->pending && !server->standalone) {
2893       /* Send to the primary router */
2894       SilcBuffer tmpbuf;
2895       SilcUInt16 old_ident;
2896
2897       old_ident = silc_command_get_ident(cmd->payload);
2898       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2899       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2900
2901       silc_server_packet_send(server, server->router->connection,
2902                               SILC_PACKET_COMMAND, cmd->packet->flags,
2903                               tmpbuf->data, tmpbuf->len, TRUE);
2904
2905       /* Reprocess this packet after received reply from router */
2906       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2907                                   silc_command_get_ident(cmd->payload),
2908                                   silc_server_command_info,
2909                                   silc_server_command_dup(cmd));
2910       cmd->pending = TRUE;
2911       silc_command_set_ident(cmd->payload, old_ident);
2912       silc_buffer_free(tmpbuf);
2913       goto out;
2914     }
2915   }
2916
2917   silc_free(server_id);
2918
2919   if (!entry) {
2920     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2921                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2922     goto out;
2923   }
2924
2925   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2926   if (!server_info)
2927     server_info = entry->server_info;
2928   server_name = entry->server_name;
2929
2930   /* Send the reply */
2931   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2932                                                 SILC_STATUS_OK, 0, ident, 3,
2933                                                 2, idp->data, idp->len,
2934                                                 3, server_name, 
2935                                                 strlen(server_name),
2936                                                 4, server_info, 
2937                                                 server_info ? 
2938                                                 strlen(server_info) : 0);
2939   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2940                           packet->data, packet->len, FALSE);
2941     
2942   silc_buffer_free(packet);
2943   silc_buffer_free(idp);
2944
2945  out:
2946   silc_server_command_free(cmd);
2947 }
2948
2949 /* Server side of command PING. This just replies to the ping. */
2950
2951 SILC_SERVER_CMD_FUNC(ping)
2952 {
2953   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2954   SilcServer server = cmd->server;
2955   SilcServerID *id;
2956   SilcUInt32 len;
2957   unsigned char *tmp;
2958
2959   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2960
2961   /* Get Server ID */
2962   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2963   if (!tmp) {
2964     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2965                                           SILC_STATUS_ERR_NO_SERVER_ID);
2966     goto out;
2967   }
2968   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2969   if (!id)
2970     goto out;
2971
2972   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2973     /* Send our reply */
2974     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2975                                           SILC_STATUS_OK);
2976   } else {
2977     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2978                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2979     goto out;
2980   }
2981
2982   silc_free(id);
2983
2984  out:
2985   silc_server_command_free(cmd);
2986 }
2987
2988 /* Server side of command STATS. */
2989
2990 SILC_SERVER_CMD_FUNC(stats)
2991 {
2992   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2993   SilcServer server = cmd->server;
2994   SilcServerID *server_id;
2995   unsigned char *tmp;
2996   SilcUInt32 tmp_len;
2997   SilcBuffer packet, stats;
2998   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2999   SilcUInt32 uptime;
3000
3001   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3002
3003   /* Get Server ID */
3004   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3005   if (!tmp) {
3006     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3007                                           SILC_STATUS_ERR_NO_SERVER_ID);
3008     goto out;
3009   }
3010   server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3011   if (!server_id)
3012     goto out;
3013
3014   /* The ID must be ours */
3015   if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3016     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3017                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3018     silc_free(server_id);
3019     goto out;
3020   }
3021   silc_free(server_id);
3022
3023   /* If we are router then just send everything we got. If we are normal
3024      server then we'll send this to our router to get all the latest
3025      statistical information. */
3026   if (!cmd->pending && server->server_type != SILC_ROUTER && 
3027       !server->standalone) {
3028     /* Send request to our router */
3029     SilcBuffer idp = silc_id_payload_encode(server->router->id, 
3030                                             SILC_ID_SERVER);
3031     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, 
3032                                             ++server->cmd_ident, 1,
3033                                             1, idp->data, idp->len);
3034     silc_server_packet_send(server, server->router->connection,
3035                             SILC_PACKET_COMMAND, 0, packet->data,
3036                             packet->len, FALSE);
3037
3038     /* Reprocess this packet after received reply from router */
3039     silc_server_command_pending(server, SILC_COMMAND_STATS, 
3040                                 server->cmd_ident,
3041                                 silc_server_command_stats,
3042                                 silc_server_command_dup(cmd));
3043     cmd->pending = TRUE;
3044     silc_buffer_free(packet);
3045     silc_buffer_free(idp);
3046     goto out;
3047   }
3048
3049   /* Send our reply to sender */
3050   uptime = time(NULL) - server->starttime;
3051
3052   stats = silc_buffer_alloc_size(60);
3053   silc_buffer_format(stats,
3054                      SILC_STR_UI_INT(server->starttime),
3055                      SILC_STR_UI_INT(uptime),
3056                      SILC_STR_UI_INT(server->stat.my_clients),
3057                      SILC_STR_UI_INT(server->stat.my_channels),
3058                      SILC_STR_UI_INT(server->stat.my_server_ops),
3059                      SILC_STR_UI_INT(server->stat.my_router_ops),
3060                      SILC_STR_UI_INT(server->stat.cell_clients),
3061                      SILC_STR_UI_INT(server->stat.cell_channels),
3062                      SILC_STR_UI_INT(server->stat.cell_servers),
3063                      SILC_STR_UI_INT(server->stat.clients),
3064                      SILC_STR_UI_INT(server->stat.channels),
3065                      SILC_STR_UI_INT(server->stat.servers),
3066                      SILC_STR_UI_INT(server->stat.routers),
3067                      SILC_STR_UI_INT(server->stat.server_ops),
3068                      SILC_STR_UI_INT(server->stat.router_ops),
3069                      SILC_STR_END);
3070
3071   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS, 
3072                                                 SILC_STATUS_OK, 0, ident, 2,
3073                                                 2, tmp, tmp_len,
3074                                                 3, stats->data, stats->len);
3075   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3076                           0, packet->data, packet->len, FALSE);
3077   silc_buffer_free(packet);
3078   silc_buffer_free(stats);
3079
3080  out:
3081   silc_server_command_free(cmd);
3082 }
3083
3084 /* Internal routine to join channel. The channel sent to this function
3085    has been either created or resolved from ID lists. This joins the sent
3086    client to the channel. */
3087
3088 static void silc_server_command_join_channel(SilcServer server, 
3089                                              SilcServerCommandContext cmd,
3090                                              SilcChannelEntry channel,
3091                                              SilcClientID *client_id,
3092                                              bool created,
3093                                              bool create_key,
3094                                              SilcUInt32 umode,
3095                                              const unsigned char *auth,
3096                                              SilcUInt32 auth_len)
3097 {
3098   SilcSocketConnection sock = cmd->sock;
3099   unsigned char *tmp;
3100   SilcUInt32 tmp_len, user_count;
3101   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3102   SilcClientEntry client;
3103   SilcChannelClientEntry chl;
3104   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3105   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3106   char check[512], check2[512];
3107   bool founder = FALSE;
3108   bool resolve;
3109
3110   SILC_LOG_DEBUG(("Start"));
3111
3112   if (!channel)
3113     return;
3114
3115   /* Get the client entry */
3116   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3117     client = (SilcClientEntry)sock->user_data;
3118   } else {
3119     client = silc_server_get_client_resolve(server, client_id, &resolve);
3120     if (!client) {
3121       if (cmd->pending)
3122         goto out;
3123
3124       if (!resolve) {
3125         silc_server_command_send_status_reply(
3126                                          cmd, SILC_COMMAND_JOIN,
3127                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3128         goto out;
3129       }
3130
3131       /* The client info is being resolved. Reprocess this packet after
3132          receiving the reply to the query. */
3133       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
3134                                   server->cmd_ident,
3135                                   silc_server_command_join, 
3136                                   silc_server_command_dup(cmd));
3137       cmd->pending = TRUE;
3138       goto out;
3139     }
3140
3141     cmd->pending = FALSE;
3142   }
3143
3144   /*
3145    * Check founder auth payload if provided.  If client can gain founder
3146    * privileges it can override various conditions on joining the channel,
3147    * and can have directly the founder mode set on the channel.
3148    */
3149   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3150     SilcIDListData idata = (SilcIDListData)client;
3151
3152     if (channel->founder_key && idata->public_key &&
3153         silc_pkcs_public_key_compare(channel->founder_key, 
3154                                      idata->public_key)) {
3155       void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3156                          (void *)channel->founder_passwd : 
3157                          (void *)channel->founder_key);
3158       SilcUInt32 auth_data_len = 
3159         (channel->founder_method == SILC_AUTH_PASSWORD ?
3160          channel->founder_passwd_len : 0);
3161
3162       /* Check whether the client is to become founder */
3163       if (silc_auth_verify_data(auth, auth_len, channel->founder_method, 
3164                                 auth_data, auth_data_len,
3165                                 idata->hash, client->id, SILC_ID_CLIENT)) {
3166         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3167         founder = TRUE;
3168       }
3169     }
3170   }
3171
3172   /*
3173    * Check channel modes
3174    */
3175
3176   if (!umode) {
3177     memset(check, 0, sizeof(check));
3178     memset(check2, 0, sizeof(check2));
3179     strncat(check, client->nickname, strlen(client->nickname));
3180     strncat(check, "!", 1);
3181     strncat(check, client->username, strlen(client->username));
3182     if (!strchr(client->username, '@')) {
3183       strncat(check, "@", 1);
3184       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3185     }
3186
3187     strncat(check2, client->nickname, strlen(client->nickname));
3188     if (!strchr(client->nickname, '@')) {
3189       strncat(check2, "@", 1);
3190       strncat(check2, server->server_name, strlen(server->server_name));
3191     }
3192     strncat(check2, "!", 1);
3193     strncat(check2, client->username, strlen(client->username));
3194     if (!strchr(client->username, '@')) {
3195       strncat(check2, "@", 1);
3196       strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3197     }
3198     
3199     /* Check invite list if channel is invite-only channel */
3200     if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3201       if (!channel->invite_list ||
3202           (!silc_string_match(channel->invite_list, check) &&
3203            !silc_string_match(channel->invite_list, check2))) {
3204         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3205                                               SILC_STATUS_ERR_NOT_INVITED);
3206         goto out;
3207       }
3208     }
3209
3210     /* Check ban list if it exists. If the client's nickname, server,
3211        username and/or hostname is in the ban list the access to the
3212        channel is denied. */
3213     if (channel->ban_list) {
3214       if (silc_string_match(channel->ban_list, check) ||
3215           silc_string_match(channel->ban_list, check2)) {
3216         silc_server_command_send_status_reply(
3217                                       cmd, SILC_COMMAND_JOIN,
3218                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3219         goto out;
3220       }
3221     }
3222     
3223     /* Check user count limit if set. */
3224     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3225       if (silc_hash_table_count(channel->user_list) + 1 > 
3226           channel->user_limit) {
3227         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3228                                               SILC_STATUS_ERR_CHANNEL_IS_FULL);
3229         goto out;
3230       }
3231     }
3232   }
3233
3234   /* Check the channel passphrase if set. */
3235   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3236     /* Get passphrase */
3237     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3238     if (tmp)
3239       passphrase = silc_memdup(tmp, tmp_len);
3240   
3241     if (!passphrase || !channel->passphrase ||
3242         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3243       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3244                                             SILC_STATUS_ERR_BAD_PASSWORD);
3245       goto out;
3246     }
3247   }
3248
3249   /*
3250    * Client is allowed to join to the channel. Make it happen.
3251    */
3252
3253   /* Check whether the client already is on the channel */
3254   if (silc_server_client_on_channel(client, channel, NULL)) {
3255     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3256                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
3257     goto out;
3258   }
3259
3260   /* Generate new channel key as protocol dictates */
3261   if (create_key) {
3262     if (!silc_server_create_channel_key(server, channel, 0))
3263       goto out;
3264
3265     /* Send the channel key. This is broadcasted to the channel but is not
3266        sent to the client who is joining to the channel. */
3267     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3268       silc_server_send_channel_key(server, NULL, channel, 
3269                                    server->server_type == SILC_ROUTER ? 
3270                                    FALSE : !server->standalone);
3271   }
3272
3273   /* Join the client to the channel by adding it to channel's user list.
3274      Add also the channel to client entry's channels list for fast cross-
3275      referencing. */
3276   chl = silc_calloc(1, sizeof(*chl));
3277   chl->mode = umode;
3278   chl->client = client;
3279   chl->channel = channel;
3280   silc_hash_table_add(channel->user_list, client, chl);
3281   silc_hash_table_add(client->channels, channel, chl);
3282   channel->user_count++;
3283
3284   /* Get users on the channel */
3285   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3286                                    &user_count);
3287
3288   /* Encode Client ID Payload of the original client who wants to join */
3289   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3290
3291   /* Encode command reply packet */
3292   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3293   SILC_PUT32_MSB(channel->mode, mode);
3294   SILC_PUT32_MSB(created, tmp2);
3295   SILC_PUT32_MSB(user_count, tmp3);
3296
3297   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3298     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3299     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
3300                                            strlen(channel->channel_key->
3301                                                   cipher->name),
3302                                            channel->channel_key->cipher->name,
3303                                            channel->key_len / 8, channel->key);
3304     silc_free(tmp);
3305   }
3306
3307   reply = 
3308     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3309                                          SILC_STATUS_OK, 0, ident, 13,
3310                                          2, channel->channel_name,
3311                                          strlen(channel->channel_name),
3312                                          3, chidp->data, chidp->len,
3313                                          4, clidp->data, clidp->len,
3314                                          5, mode, 4,
3315                                          6, tmp2, 4,
3316                                          7, keyp ? keyp->data : NULL, 
3317                                          keyp ? keyp->len : 0,
3318                                          8, channel->ban_list, 
3319                                          channel->ban_list ?
3320                                          strlen(channel->ban_list) : 0,
3321                                          9, channel->invite_list,
3322                                          channel->invite_list ?
3323                                          strlen(channel->invite_list) : 0,
3324                                          10, channel->topic,
3325                                          channel->topic ?
3326                                          strlen(channel->topic) : 0,
3327                                          11, silc_hmac_get_name(channel->hmac),
3328                                          strlen(silc_hmac_get_name(channel->
3329                                                                    hmac)),
3330                                          12, tmp3, 4,
3331                                          13, user_list->data, user_list->len,
3332                                          14, mode_list->data, 
3333                                          mode_list->len);
3334
3335   /* Send command reply */
3336   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3337                           reply->data, reply->len, FALSE);
3338
3339   /* Send JOIN notify to locally connected clients on the channel. If
3340      we are normal server then router will send or have sent JOIN notify
3341      already. However since we've added the client already to our channel
3342      we'll ignore it (in packet_receive.c) so we must send it here. If
3343      we are router then this will send it to local clients and local
3344      servers. */
3345   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3346                                      SILC_NOTIFY_TYPE_JOIN, 2,
3347                                      clidp->data, clidp->len,
3348                                      chidp->data, chidp->len);
3349
3350   if (!cmd->pending) {
3351     /* Send JOIN notify packet to our primary router */
3352     if (!server->standalone)
3353       silc_server_send_notify_join(server, server->router->connection,
3354                                    server->server_type == SILC_ROUTER ?
3355                                    TRUE : FALSE, channel, client->id);
3356
3357     if (keyp)
3358       /* Distribute the channel key to all backup routers. */
3359       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3360                               keyp->data, keyp->len, FALSE, TRUE);
3361   }
3362
3363   /* If client became founder by providing correct founder auth data
3364      notify the mode change to the channel. */
3365   if (founder) {
3366     SILC_PUT32_MSB(chl->mode, mode);
3367     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3368                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3369                                        clidp->data, clidp->len,
3370                                        mode, 4, clidp->data, clidp->len);
3371       
3372     /* Set CUMODE notify type to network */
3373     if (!server->standalone)
3374       silc_server_send_notify_cumode(server, server->router->connection,
3375                                      server->server_type == SILC_ROUTER ? 
3376                                      TRUE : FALSE, channel,
3377                                      chl->mode, client->id, SILC_ID_CLIENT,
3378                                      client->id);
3379   }
3380
3381   silc_buffer_free(reply);
3382   silc_buffer_free(clidp);
3383   silc_buffer_free(chidp);
3384   silc_buffer_free(keyp);
3385   silc_buffer_free(user_list);
3386   silc_buffer_free(mode_list);
3387
3388  out:
3389   silc_free(passphrase);
3390 }
3391
3392 /* Server side of command JOIN. Joins client into requested channel. If 
3393    the channel does not exist it will be created. */
3394
3395 SILC_SERVER_CMD_FUNC(join)
3396 {
3397   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3398   SilcServer server = cmd->server;
3399   unsigned char *auth;
3400   SilcUInt32 tmp_len, auth_len;
3401   char *tmp, *channel_name = NULL, *cipher, *hmac;
3402   SilcChannelEntry channel;
3403   SilcUInt32 umode = 0;
3404   bool created = FALSE, create_key = TRUE;
3405   SilcClientID *client_id;
3406
3407   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3408
3409   /* Get channel name */
3410   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3411   if (!tmp) {
3412     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3413                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3414     goto out;
3415   }
3416   channel_name = tmp;
3417
3418   if (tmp_len > 256)
3419     channel_name[255] = '\0';
3420
3421   if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3422     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3423                                           SILC_STATUS_ERR_BAD_CHANNEL);
3424     goto out;
3425   }
3426
3427   /* Get Client ID of the client who is joining to the channel */
3428   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3429   if (!tmp) {
3430     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3431                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3432     goto out;
3433   }
3434   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3435   if (!client_id) {
3436     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3437                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3438     goto out;
3439   }
3440
3441   /* Get cipher, hmac name and auth payload */
3442   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3443   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3444   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3445
3446   /* See if the channel exists */
3447   channel = silc_idlist_find_channel_by_name(server->local_list, 
3448                                              channel_name, NULL);
3449
3450   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3451     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3452     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3453
3454     if (!channel || channel->disabled) {
3455       /* Channel not found */
3456
3457       /* If we are standalone server we don't have a router, we just create 
3458          the channel by ourselves. */
3459       if (server->standalone) {
3460         channel = silc_server_create_new_channel(server, server->id, cipher, 
3461                                                  hmac, channel_name, TRUE);
3462         if (!channel) {
3463           silc_server_command_send_status_reply(
3464                                          cmd, SILC_COMMAND_JOIN,
3465                                          SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3466           goto out;
3467         }
3468         
3469         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3470         created = TRUE;
3471         create_key = FALSE;
3472         
3473       } else {
3474
3475         /* The channel does not exist on our server. If we are normal server 
3476            we will send JOIN command to our router which will handle the
3477            joining procedure (either creates the channel if it doesn't exist 
3478            or joins the client to it). */
3479         if (server->server_type != SILC_ROUTER) {
3480           SilcBuffer tmpbuf;
3481           SilcUInt16 old_ident;
3482
3483           /* If this is pending command callback then we've resolved
3484              it and it didn't work, return since we've notified the
3485              client already in the command reply callback. */
3486           if (cmd->pending)
3487             goto out;
3488           
3489           old_ident = silc_command_get_ident(cmd->payload);
3490           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3491           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3492           
3493           /* Send JOIN command to our router */
3494           silc_server_packet_send(server, (SilcSocketConnection)
3495                                   server->router->connection,
3496                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3497                                   tmpbuf->data, tmpbuf->len, TRUE);
3498           
3499           /* Reprocess this packet after received reply from router */
3500           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3501                                       silc_command_get_ident(cmd->payload),
3502                                       silc_server_command_join,
3503                                       silc_server_command_dup(cmd));
3504           cmd->pending = TRUE;
3505           silc_command_set_ident(cmd->payload, old_ident);
3506           silc_buffer_free(tmpbuf);
3507           goto out;
3508         }
3509         
3510         /* We are router and the channel does not seem exist so we will check
3511            our global list as well for the channel. */
3512         channel = silc_idlist_find_channel_by_name(server->global_list, 
3513                                                    channel_name, NULL);
3514         if (!channel) {
3515           /* Channel really does not exist, create it */
3516           channel = silc_server_create_new_channel(server, server->id, cipher, 
3517                                                    hmac, channel_name, TRUE);
3518           if (!channel) {
3519             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3520                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3521             goto out;
3522           }
3523
3524           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3525           created = TRUE;
3526           create_key = FALSE;
3527         }
3528       }
3529     }
3530   } else {
3531     if (!channel) {
3532       /* Channel not found */
3533
3534       /* If the command came from router and we are normal server then
3535          something went wrong with the joining as the channel was not found.
3536          We can't do anything else but ignore this. */
3537       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3538           server->server_type != SILC_ROUTER)
3539         goto out;
3540       
3541       /* We are router and the channel does not seem exist so we will check
3542          our global list as well for the channel. */
3543       channel = silc_idlist_find_channel_by_name(server->global_list, 
3544                                                  channel_name, NULL);
3545       if (!channel) {
3546         /* Channel really does not exist, create it */
3547         channel = silc_server_create_new_channel(server, server->id, cipher, 
3548                                                  hmac, channel_name, TRUE);
3549         if (!channel) {
3550           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3551                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3552           goto out;
3553         }
3554
3555         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3556         created = TRUE;
3557         create_key = FALSE;
3558       }
3559     }
3560   }
3561
3562   /* Check whether the channel was created by our router */
3563   if (cmd->pending && context2) {
3564     SilcServerCommandReplyContext reply = context2;
3565
3566     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3567       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3568       SILC_GET32_MSB(created, tmp);
3569       if (silc_argument_get_arg_type(reply->args, 7, NULL))
3570         create_key = FALSE;     /* Router returned the key already */
3571     }
3572
3573     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3574         !silc_hash_table_count(channel->user_list))
3575       created = TRUE;
3576   }
3577
3578   /* If the channel does not have global users and is also empty the client
3579      will be the channel founder and operator. */
3580   if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3581     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3582
3583   /* Join to the channel */
3584   silc_server_command_join_channel(server, cmd, channel, client_id,
3585                                    created, create_key, umode,
3586                                    auth, auth_len);
3587
3588   silc_free(client_id);
3589
3590  out:
3591   silc_server_command_free(cmd);
3592 }
3593
3594 /* Server side of command MOTD. Sends server's current "message of the
3595    day" to the client. */
3596
3597 SILC_SERVER_CMD_FUNC(motd)
3598 {
3599   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3600   SilcServer server = cmd->server;
3601   SilcBuffer packet, idp;
3602   char *motd, *dest_server;
3603   SilcUInt32 motd_len;
3604   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3605   
3606   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3607
3608   /* Get server name */
3609   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3610   if (!dest_server) {
3611     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3612                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3613     goto out;
3614   }
3615
3616   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3617     /* Send our MOTD */
3618
3619     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3620
3621     if (server->config && server->config->server_info &&
3622         server->config->server_info->motd_file) {
3623       /* Send motd */
3624       motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3625       if (!motd)
3626         goto out;
3627       
3628       motd[motd_len] = 0;
3629       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3630                                                     SILC_STATUS_OK, 0, 
3631                                                     ident, 2,
3632                                                     2, idp, idp->len,
3633                                                     3, motd, motd_len);
3634     } else {
3635       /* No motd */
3636       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3637                                                     SILC_STATUS_OK, 0, 
3638                                                     ident, 1,
3639                                                     2, idp, idp->len);
3640     }
3641
3642     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3643                             packet->data, packet->len, FALSE);
3644     silc_buffer_free(packet);
3645     silc_buffer_free(idp);
3646   } else {
3647     SilcServerEntry entry;
3648
3649     /* Check whether we have this server cached */
3650     entry = silc_idlist_find_server_by_name(server->global_list,
3651                                             dest_server, TRUE, NULL);
3652     if (!entry) {
3653       entry = silc_idlist_find_server_by_name(server->local_list,
3654                                               dest_server, TRUE, NULL);
3655     }
3656
3657     if (server->server_type != SILC_SERVER && !cmd->pending && 
3658         entry && !entry->motd) {
3659       /* Send to the server */
3660       SilcBuffer tmpbuf;
3661       SilcUInt16 old_ident;
3662
3663       old_ident = silc_command_get_ident(cmd->payload);
3664       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3665       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3666
3667       silc_server_packet_send(server, entry->connection,
3668                               SILC_PACKET_COMMAND, cmd->packet->flags,
3669                               tmpbuf->data, tmpbuf->len, TRUE);
3670
3671       /* Reprocess this packet after received reply from router */
3672       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3673                                   silc_command_get_ident(cmd->payload),
3674                                   silc_server_command_motd,
3675                                   silc_server_command_dup(cmd));
3676       cmd->pending = TRUE;
3677       silc_command_set_ident(cmd->payload, old_ident);
3678       silc_buffer_free(tmpbuf);
3679       goto out;
3680     }
3681
3682     if (!entry && !cmd->pending && !server->standalone) {
3683       /* Send to the primary router */
3684       SilcBuffer tmpbuf;
3685       SilcUInt16 old_ident;
3686
3687       old_ident = silc_command_get_ident(cmd->payload);
3688       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3689       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3690
3691       silc_server_packet_send(server, server->router->connection,
3692                               SILC_PACKET_COMMAND, cmd->packet->flags,
3693                               tmpbuf->data, tmpbuf->len, TRUE);
3694
3695       /* Reprocess this packet after received reply from router */
3696       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3697                                   silc_command_get_ident(cmd->payload),
3698                                   silc_server_command_motd,
3699                                   silc_server_command_dup(cmd));
3700       cmd->pending = TRUE;
3701       silc_command_set_ident(cmd->payload, old_ident);
3702       silc_buffer_free(tmpbuf);
3703       goto out;
3704     }
3705
3706     if (!entry) {
3707       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3708                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3709       goto out;
3710     }
3711
3712     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3713     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3714                                                   SILC_STATUS_OK, 0, ident, 2,
3715                                                   2, idp, idp->len,
3716                                                   3, entry->motd,
3717                                                   entry->motd ? 
3718                                                   strlen(entry->motd) : 0);
3719     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3720                             packet->data, packet->len, FALSE);
3721     silc_buffer_free(packet);
3722     silc_buffer_free(idp);
3723   }
3724
3725  out:
3726   silc_server_command_free(cmd);
3727 }
3728
3729 /* Server side of command UMODE. Client can use this command to set/unset
3730    user mode. Client actually cannot set itself to be as server/router
3731    operator so this can be used only to unset the modes. */
3732
3733 SILC_SERVER_CMD_FUNC(umode)
3734 {
3735   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3736   SilcServer server = cmd->server;
3737   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3738   SilcBuffer packet;
3739   unsigned char *tmp_mask;
3740   SilcUInt32 mask;
3741   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3742
3743   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3744     goto out;
3745
3746   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3747
3748   /* Get the client's mode mask */
3749   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3750   if (!tmp_mask) {
3751     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3752                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3753     goto out;
3754   }
3755   SILC_GET32_MSB(mask, tmp_mask);
3756
3757   /* Check that mode changing is allowed. */
3758   if (!silc_server_check_umode_rights(server, client, mask)) {
3759     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3760                                           SILC_STATUS_ERR_PERM_DENIED);
3761     goto out;
3762   }
3763
3764   /* Change the mode */
3765   client->mode = mask;
3766
3767   /* Send UMODE change to primary router */
3768   if (!server->standalone)
3769     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3770                                   client->id, client->mode);
3771
3772   /* Send command reply to sender */
3773   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3774                                                 SILC_STATUS_OK, 0, ident, 1,
3775                                                 2, tmp_mask, 4);
3776   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3777                           packet->data, packet->len, FALSE);
3778   silc_buffer_free(packet);
3779
3780  out:
3781   silc_server_command_free(cmd);
3782 }
3783
3784 /* Server side command of CMODE. Changes channel mode */
3785
3786 SILC_SERVER_CMD_FUNC(cmode)
3787 {
3788   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3789   SilcServer server = cmd->server;
3790   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3791   SilcIDListData idata = (SilcIDListData)client;
3792   SilcChannelID *channel_id;
3793   SilcChannelEntry channel;
3794   SilcChannelClientEntry chl;
3795   SilcBuffer packet, cidp;
3796   unsigned char *tmp, *tmp_id, *tmp_mask;
3797   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3798   SilcUInt32 mode_mask, tmp_len, tmp_len2;
3799   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3800
3801   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3802
3803   /* Get Channel ID */
3804   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3805   if (!tmp_id) {
3806     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3807                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3808     goto out;
3809   }
3810   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3811   if (!channel_id) {
3812     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3813                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3814     goto out;
3815   }
3816
3817   /* Get the channel mode mask */
3818   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3819   if (!tmp_mask) {
3820     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3821                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3822     goto out;
3823   }
3824   SILC_GET32_MSB(mode_mask, tmp_mask);
3825
3826   /* Get channel entry */
3827   channel = silc_idlist_find_channel_by_id(server->local_list, 
3828                                            channel_id, NULL);
3829   if (!channel) {
3830     channel = silc_idlist_find_channel_by_id(server->global_list, 
3831                                              channel_id, NULL);
3832     if (!channel) {
3833       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3834                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3835       goto out;
3836     }
3837   }
3838
3839   /* Check whether this client is on the channel */
3840   if (!silc_server_client_on_channel(client, channel, &chl)) {
3841     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3842                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3843     goto out;
3844   }
3845
3846   /* Check that client has rights to change any requested channel modes */
3847   if (!silc_server_check_cmode_rights(server, channel, chl, mode_mask)) {
3848     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3849                                           (chl->mode == 0 ? 
3850                                            SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3851                                            SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3852     goto out;
3853   }
3854
3855   /*
3856    * Check the modes. Modes that requires nothing special operation are
3857    * not checked here.
3858    */
3859
3860   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3861     /* Channel uses private keys to protect traffic. Client(s) has set the
3862        key locally they want to use, server does not know that key. */
3863     /* Nothing interesting to do here */
3864   } else {
3865     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3866       /* The mode is removed and we need to generate and distribute
3867          new channel key. Clients are not using private channel keys
3868          anymore after this. */
3869       
3870       /* Re-generate channel key */
3871       if (!silc_server_create_channel_key(server, channel, 0))
3872         goto out;
3873         
3874       /* Send the channel key. This sends it to our local clients and if
3875          we are normal server to our router as well. */
3876       silc_server_send_channel_key(server, NULL, channel, 
3877                                    server->server_type == SILC_ROUTER ? 
3878                                    FALSE : !server->standalone);
3879         
3880       cipher = channel->channel_key->cipher->name;
3881       hmac = (char *)silc_hmac_get_name(channel->hmac);
3882     }
3883   }
3884
3885   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3886     /* User limit is set on channel */
3887     SilcUInt32 user_limit;
3888       
3889     /* Get user limit */
3890     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3891     if (!tmp) {
3892       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3893         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3894                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3895         goto out;
3896       }
3897     } else {
3898       SILC_GET32_MSB(user_limit, tmp);
3899       channel->user_limit = user_limit;
3900     }
3901   } else {
3902     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3903       /* User limit mode is unset. Remove user limit */
3904       channel->user_limit = 0;
3905   }
3906
3907   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3908     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3909       /* Passphrase has been set to channel */
3910       
3911       /* Get the passphrase */
3912       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3913       if (!tmp) {
3914         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3915                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3916         goto out;
3917       }
3918
3919       /* Save the passphrase */
3920       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3921     }
3922   } else {
3923     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3924       /* Passphrase mode is unset. remove the passphrase */
3925       silc_free(channel->passphrase);
3926       channel->passphrase = NULL;
3927     }
3928   }
3929
3930   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3931     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3932       /* Cipher to use protect the traffic */
3933       SilcCipher newkey, oldkey;
3934
3935       /* Get cipher */
3936       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3937       if (!cipher) {
3938         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3939                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3940         goto out;
3941       }
3942
3943       /* Delete old cipher and allocate the new one */
3944       if (!silc_cipher_alloc(cipher, &newkey)) {
3945         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3946                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3947         goto out;
3948       }
3949
3950       oldkey = channel->channel_key;
3951       channel->channel_key = newkey;
3952
3953       /* Re-generate channel key */
3954       if (!silc_server_create_channel_key(server, channel, 0)) {
3955         /* We don't have new key, revert to old one */
3956         channel->channel_key = oldkey;
3957         goto out;
3958       }
3959
3960       /* Remove old channel key for good */
3961       silc_cipher_free(oldkey);
3962
3963       /* Send the channel key. This sends it to our local clients and if
3964          we are normal server to our router as well. */
3965       silc_server_send_channel_key(server, NULL, channel, 
3966                                    server->server_type == SILC_ROUTER ? 
3967                                    FALSE : !server->standalone);
3968     }
3969   } else {
3970     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3971       /* Cipher mode is unset. Remove the cipher and revert back to 
3972          default cipher */
3973       SilcCipher newkey, oldkey;
3974       cipher = channel->cipher;
3975
3976       /* Delete old cipher and allocate default one */
3977       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3978         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3979                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3980         goto out;
3981       }
3982
3983       oldkey = channel->channel_key;
3984       channel->channel_key = newkey;
3985
3986       /* Re-generate channel key */
3987       if (!silc_server_create_channel_key(server, channel, 0)) {
3988         /* We don't have new key, revert to old one */
3989         channel->channel_key = oldkey;
3990         goto out;
3991       }
3992       
3993       /* Remove old channel key for good */
3994       silc_cipher_free(oldkey);
3995
3996       /* Send the channel key. This sends it to our local clients and if
3997          we are normal server to our router as well. */
3998       silc_server_send_channel_key(server, NULL, channel, 
3999                                    server->server_type == SILC_ROUTER ? 
4000                                    FALSE : !server->standalone);
4001     }
4002   }
4003
4004   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4005     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4006       /* HMAC to use protect the traffic */
4007       unsigned char hash[32];
4008       SilcHmac newhmac;
4009
4010       /* Get hmac */
4011       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4012       if (!hmac) {
4013         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4014                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4015         goto out;
4016       }
4017
4018       /* Delete old hmac and allocate the new one */
4019       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4020         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4021                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4022         goto out;
4023       }
4024
4025       silc_hmac_free(channel->hmac);
4026       channel->hmac = newhmac;
4027
4028       /* Set the HMAC key out of current channel key. The client must do
4029          this locally. */
4030       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4031                      channel->key_len / 8, hash);
4032       silc_hmac_set_key(channel->hmac, hash, 
4033                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4034       memset(hash, 0, sizeof(hash));
4035     }
4036   } else {
4037     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4038       /* Hmac mode is unset. Remove the hmac and revert back to 
4039          default hmac */
4040       SilcHmac newhmac;
4041       unsigned char hash[32];
4042       hmac = channel->hmac_name;
4043
4044       /* Delete old hmac and allocate default one */
4045       silc_hmac_free(channel->hmac);
4046       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4047         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4048                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4049         goto out;
4050       }
4051
4052       silc_hmac_free(channel->hmac);
4053       channel->hmac = newhmac;
4054
4055       /* Set the HMAC key out of current channel key. The client must do
4056          this locally. */
4057       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4058                      channel->key_len / 8, 
4059                      hash);
4060       silc_hmac_set_key(channel->hmac, hash, 
4061                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4062       memset(hash, 0, sizeof(hash));
4063     }
4064   }
4065
4066   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4067     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4068       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4069         /* Set the founder authentication */
4070         SilcAuthPayload auth;
4071         
4072         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4073         if (!tmp) {
4074           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4075                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4076           goto out;
4077         }
4078
4079         auth = silc_auth_payload_parse(tmp, tmp_len);
4080         if (!auth) {
4081           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4082                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4083           goto out;
4084         }
4085
4086         /* Save the public key */
4087         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4088         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4089         silc_free(tmp);
4090         
4091         channel->founder_method = silc_auth_get_method(auth);
4092
4093         if (channel->founder_method == SILC_AUTH_PASSWORD) {
4094           tmp = silc_auth_get_data(auth, &tmp_len);
4095           channel->founder_passwd = silc_memdup(tmp, tmp_len);
4096           channel->founder_passwd_len = tmp_len;
4097         } else {
4098           /* Verify the payload before setting the mode */
4099           if (!silc_auth_verify(auth, channel->founder_method, 
4100                                 channel->founder_key, 0, idata->hash,
4101                                 client->id, SILC_ID_CLIENT)) {
4102             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4103                                                   SILC_STATUS_ERR_AUTH_FAILED);
4104             goto out;
4105           }
4106         }
4107
4108         silc_auth_payload_free(auth);
4109       }
4110     }
4111   } else {
4112     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4113       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4114         if (channel->founder_key)
4115           silc_pkcs_public_key_free(channel->founder_key);
4116         if (channel->founder_passwd) {
4117           silc_free(channel->founder_passwd);
4118           channel->founder_passwd = NULL;
4119         }
4120       }
4121     }
4122   }
4123
4124   /* Finally, set the mode */
4125   channel->mode = mode_mask;
4126
4127   /* Send CMODE_CHANGE notify. */
4128   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4129   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4130                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4131                                      cidp->data, cidp->len, 
4132                                      tmp_mask, 4,
4133                                      cipher, cipher ? strlen(cipher) : 0,
4134                                      hmac, hmac ? strlen(hmac) : 0,
4135                                      passphrase, passphrase ? 
4136                                      strlen(passphrase) : 0);
4137
4138   /* Set CMODE notify type to network */
4139   if (!server->standalone)
4140     silc_server_send_notify_cmode(server, server->router->connection,
4141                                   server->server_type == SILC_ROUTER ? 
4142                                   TRUE : FALSE, channel,
4143                                   mode_mask, client->id, SILC_ID_CLIENT,
4144                                   cipher, hmac, passphrase);
4145
4146   /* Send command reply to sender */
4147   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4148                                                 SILC_STATUS_OK, 0, ident, 2,
4149                                                 2, tmp_id, tmp_len2,
4150                                                 3, tmp_mask, 4);
4151   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4152                           packet->data, packet->len, FALSE);
4153     
4154   silc_buffer_free(packet);
4155   silc_free(channel_id);
4156   silc_buffer_free(cidp);
4157
4158  out:
4159   silc_server_command_free(cmd);
4160 }
4161
4162 /* Server side of CUMODE command. Changes client's mode on a channel. */
4163
4164 SILC_SERVER_CMD_FUNC(cumode)
4165 {
4166   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4167   SilcServer server = cmd->server;
4168   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4169   SilcIDListData idata = (SilcIDListData)client;
4170   SilcChannelID *channel_id;
4171   SilcClientID *client_id;
4172   SilcChannelEntry channel;
4173   SilcClientEntry target_client;
4174   SilcChannelClientEntry chl;
4175   SilcBuffer packet, idp;
4176   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4177   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4178   int notify = FALSE;
4179   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4180
4181   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4182
4183   /* Get Channel ID */
4184   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4185   if (!tmp_ch_id) {
4186     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4187                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4188     goto out;
4189   }
4190   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4191   if (!channel_id) {
4192     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4193                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4194     goto out;
4195   }
4196
4197   /* Get channel entry */
4198   channel = silc_idlist_find_channel_by_id(server->local_list, 
4199                                            channel_id, NULL);
4200   if (!channel) {
4201     channel = silc_idlist_find_channel_by_id(server->global_list, 
4202                                              channel_id, NULL);
4203     if (!channel) {
4204       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4205                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4206       goto out;
4207     }
4208   }
4209
4210   /* Check whether sender is on the channel */
4211   if (!silc_server_client_on_channel(client, channel, &chl)) {
4212     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4213                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4214     goto out;
4215   }
4216   sender_mask = chl->mode;
4217   
4218   /* Get the target client's channel mode mask */
4219   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4220   if (!tmp_mask) {
4221     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4222                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4223     goto out;
4224   }
4225   SILC_GET32_MSB(target_mask, tmp_mask);
4226
4227   /* Get target Client ID */
4228   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4229   if (!tmp_id) {
4230     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4231                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4232     goto out;
4233   }
4234   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4235   if (!client_id) {
4236     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4237                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4238     goto out;
4239   }
4240
4241   /* Get target client's entry */
4242   target_client = silc_idlist_find_client_by_id(server->local_list, 
4243                                                 client_id, TRUE, NULL);
4244   if (!target_client) {
4245     target_client = silc_idlist_find_client_by_id(server->global_list, 
4246                                                   client_id, TRUE, NULL);
4247   }
4248
4249   if (target_client != client &&
4250       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4251       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4252     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4254     goto out;
4255   }
4256
4257   /* Check whether target client is on the channel */
4258   if (target_client != client) {
4259     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4260       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4261                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4262       goto out;
4263     }
4264   }
4265
4266   /* 
4267    * Change the mode 
4268    */
4269
4270   /* If the target client is founder, no one else can change their mode
4271      but themselves. */
4272   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4273     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4274                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4275     goto out;
4276   }
4277
4278   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4279     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4280       /* The client tries to claim the founder rights. */
4281       unsigned char *tmp_auth;
4282       SilcUInt32 tmp_auth_len, auth_len;
4283       void *auth;
4284       
4285       if (target_client != client) {
4286         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4287                                               SILC_STATUS_ERR_NOT_YOU);
4288         goto out;
4289       }
4290
4291       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4292           !channel->founder_key || !idata->public_key ||
4293           !silc_pkcs_public_key_compare(channel->founder_key, 
4294                                         idata->public_key)) {
4295         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4296                                               SILC_STATUS_ERR_NOT_YOU);
4297         goto out;
4298       }
4299
4300       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4301       if (!tmp_auth) {
4302         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4303                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4304         goto out;
4305       }
4306
4307       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4308               (void *)channel->founder_passwd : (void *)channel->founder_key);
4309       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4310                   channel->founder_passwd_len : 0);
4311       
4312       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4313                                  channel->founder_method, auth, auth_len,
4314                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4315         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4316                                               SILC_STATUS_ERR_AUTH_FAILED);
4317         goto out;
4318       }
4319       
4320       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4321       notify = TRUE;
4322     }
4323   } else {
4324     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4325       if (target_client == client) {
4326         /* Remove channel founder rights from itself */
4327         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4328         notify = TRUE;
4329       } else {
4330         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4331                                               SILC_STATUS_ERR_NOT_YOU);
4332         goto out;
4333       }
4334     }
4335   }
4336
4337   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4338     /* Promote to operator */
4339     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4340       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4341           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4342         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4343                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4344         goto out;
4345       }
4346
4347       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4348       notify = TRUE;
4349     }
4350   } else {
4351     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4352       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4353           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4354         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4355                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4356         goto out;
4357       }
4358
4359       /* Demote to normal user */
4360       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4361       notify = TRUE;
4362     }
4363   }
4364
4365   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4366   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4367
4368   /* Send notify to channel, notify only if mode was actually changed. */
4369   if (notify) {
4370     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4371                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4372                                        idp->data, idp->len,
4373                                        tmp_mask, 4, 
4374                                        tmp_id, tmp_len);
4375
4376     /* Set CUMODE notify type to network */
4377     if (!server->standalone)
4378       silc_server_send_notify_cumode(server, server->router->connection,
4379                                      server->server_type == SILC_ROUTER ? 
4380                                      TRUE : FALSE, channel,
4381                                      target_mask, client->id, 
4382                                      SILC_ID_CLIENT,
4383                                      target_client->id);
4384   }
4385
4386   /* Send command reply to sender */
4387   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4388                                                 SILC_STATUS_OK, 0, ident, 3,
4389                                                 2, tmp_mask, 4,
4390                                                 3, tmp_ch_id, tmp_ch_len,
4391                                                 4, tmp_id, tmp_len);
4392   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4393                           packet->data, packet->len, FALSE);
4394     
4395   silc_buffer_free(packet);
4396   silc_free(channel_id);
4397   silc_free(client_id);
4398   silc_buffer_free(idp);
4399
4400  out:
4401   silc_server_command_free(cmd);
4402 }
4403
4404 /* Server side of KICK command. Kicks client out of channel. */
4405
4406 SILC_SERVER_CMD_FUNC(kick)
4407 {
4408   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4409   SilcServer server = cmd->server;
4410   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4411   SilcClientEntry target_client;
4412   SilcChannelID *channel_id;
4413   SilcClientID *client_id;
4414   SilcChannelEntry channel;
4415   SilcChannelClientEntry chl;
4416   SilcBuffer idp;
4417   SilcUInt32 tmp_len, target_idp_len;
4418   unsigned char *tmp, *comment, *target_idp;
4419
4420   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4421
4422   /* Get Channel ID */
4423   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4424   if (!tmp) {
4425     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4426                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4427     goto out;
4428   }
4429   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4430   if (!channel_id) {
4431     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4432                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4433     goto out;
4434   }
4435
4436   /* Get channel entry */
4437   channel = silc_idlist_find_channel_by_id(server->local_list, 
4438                                            channel_id, NULL);
4439   if (!channel) {
4440     channel = silc_idlist_find_channel_by_id(server->local_list, 
4441                                              channel_id, NULL);
4442     if (!channel) {
4443       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4444                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4445       goto out;
4446     }
4447   }
4448
4449   /* Check whether sender is on the channel */
4450   if (!silc_server_client_on_channel(client, channel, &chl)) {
4451     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4452                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4453     goto out;
4454   }
4455
4456   /* Check that the kicker is channel operator or channel founder */
4457   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4458     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4459                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4460     goto out;
4461   }
4462   
4463   /* Get target Client ID */
4464   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4465   if (!target_idp) {
4466     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4467                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4468     goto out;
4469   }
4470   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4471   if (!client_id) {
4472     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4473                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4474     goto out;
4475   }
4476
4477   /* Get target client's entry */
4478   target_client = silc_idlist_find_client_by_id(server->local_list, 
4479                                                 client_id, TRUE, NULL);
4480   if (!target_client) {
4481     target_client = silc_idlist_find_client_by_id(server->global_list, 
4482                                                   client_id, TRUE, NULL);
4483   }
4484
4485   /* Check whether target client is on the channel */
4486   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4487     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4488                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4489     goto out;
4490   }
4491
4492   /* Check that the target client is not channel founder. Channel founder
4493      cannot be kicked from the channel. */
4494   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4495     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4496                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4497     goto out;
4498   }
4499   
4500   /* Get comment */
4501   tmp_len = 0;
4502   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4503   if (tmp_len > 128)
4504     comment = NULL;
4505
4506   /* Send command reply to sender */
4507   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4508                                         SILC_STATUS_OK);
4509
4510   /* Send KICKED notify to local clients on the channel */
4511   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4512   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4513                                      SILC_NOTIFY_TYPE_KICKED, 3,
4514                                      target_idp, target_idp_len,
4515                                      comment, comment ? strlen(comment) : 0,
4516                                      idp->data, idp->len);
4517   silc_buffer_free(idp);
4518
4519   /* Remove the client from the channel. If the channel does not exist
4520      after removing the client then the client kicked itself off the channel
4521      and we don't have to send anything after that. */
4522   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4523                                            target_client, FALSE))
4524     goto out;
4525
4526   /* Send KICKED notify to primary route */
4527   if (!server->standalone)
4528     silc_server_send_notify_kicked(server, server->router->connection,
4529                                    server->server_type == SILC_ROUTER ?
4530                                    TRUE : FALSE, channel,
4531                                    target_client->id, client->id, comment);
4532
4533   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4534     /* Re-generate channel key */
4535     if (!silc_server_create_channel_key(server, channel, 0))
4536       goto out;
4537     
4538     /* Send the channel key to the channel. The key of course is not sent
4539        to the client who was kicked off the channel. */
4540     silc_server_send_channel_key(server, target_client->connection, channel, 
4541                                  server->server_type == SILC_ROUTER ? 
4542                                  FALSE : !server->standalone);
4543   }
4544
4545  out:
4546   silc_server_command_free(cmd);
4547 }
4548
4549 /* Server side of OPER command. Client uses this comand to obtain server
4550    operator privileges to this server/router. */
4551
4552 SILC_SERVER_CMD_FUNC(oper)
4553 {
4554   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4555   SilcServer server = cmd->server;
4556   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4557   unsigned char *username, *auth;
4558   SilcUInt32 tmp_len;
4559   SilcServerConfigAdmin *admin;
4560   SilcIDListData idata = (SilcIDListData)client;
4561   bool result = FALSE;
4562   SilcPublicKey cached_key;
4563
4564   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4565
4566   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4567     goto out;
4568
4569   /* Get the username */
4570   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4571   if (!username) {
4572     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4573                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4574     goto out;
4575   }
4576
4577   /* Get the admin configuration */
4578   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4579                                         username, client->nickname);
4580   if (!admin) {
4581     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4582                                           username, client->nickname);
4583     if (!admin) {
4584       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4585                                             SILC_STATUS_ERR_AUTH_FAILED);
4586       goto out;
4587     }
4588   }
4589
4590   /* Get the authentication payload */
4591   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4592   if (!auth) {
4593     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4594                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4595     goto out;
4596   }
4597
4598   /* Verify the authentication data. If both passphrase and public key
4599      is set then try both of them. */
4600   if (admin->passphrase)
4601     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4602                                    admin->passphrase, admin->passphrase_len,
4603                                    idata->hash, client->id, SILC_ID_CLIENT);
4604   if (!result && admin->publickeys) {
4605     cached_key = silc_server_get_public_key(server, admin->publickeys);
4606     if (!cached_key)
4607       goto out;
4608     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4609                                    cached_key, 0, idata->hash, 
4610                                    client->id, SILC_ID_CLIENT);
4611   }
4612   if (!result) {
4613     /* Authentication failed */
4614     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4615                                           SILC_STATUS_ERR_AUTH_FAILED);
4616     goto out;
4617   }
4618
4619   /* Client is now server operator */
4620   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4621
4622   /* Update statistics */
4623   if (client->connection)
4624     server->stat.my_server_ops++;
4625   if (server->server_type == SILC_ROUTER)
4626     server->stat.server_ops++;
4627
4628   /* Send UMODE change to primary router */
4629   if (!server->standalone)
4630     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4631                                   client->id, client->mode);
4632
4633   /* Send reply to the sender */
4634   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4635                                         SILC_STATUS_OK);
4636
4637  out:
4638   silc_server_command_free(cmd);
4639 }
4640
4641 /* Server side of SILCOPER command. Client uses this comand to obtain router
4642    operator privileges to this router. */
4643
4644 SILC_SERVER_CMD_FUNC(silcoper)
4645 {
4646   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4647   SilcServer server = cmd->server;
4648   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4649   unsigned char *username, *auth;
4650   SilcUInt32 tmp_len;
4651   SilcServerConfigAdmin *admin;
4652   SilcIDListData idata = (SilcIDListData)client;
4653   bool result = FALSE;
4654   SilcPublicKey cached_key;
4655
4656   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4657
4658   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4659     goto out;
4660
4661   if (server->server_type != SILC_ROUTER) {
4662     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4663                                           SILC_STATUS_ERR_AUTH_FAILED);
4664     goto out;
4665   }
4666
4667   /* Get the username */
4668   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4669   if (!username) {
4670     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4671                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4672     goto out;
4673   }
4674
4675   /* Get the admin configuration */
4676   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4677                                         username, client->nickname);
4678   if (!admin) {
4679     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4680                                           username, client->nickname);
4681     if (!admin) {
4682       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4683                                             SILC_STATUS_ERR_AUTH_FAILED);
4684       goto out;
4685     }
4686   }
4687
4688   /* Get the authentication payload */
4689   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4690   if (!auth) {
4691     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4692                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4693     goto out;
4694   }
4695
4696   /* Verify the authentication data. If both passphrase and public key
4697      is set then try both of them. */
4698   if (admin->passphrase)
4699     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4700                                    admin->passphrase, admin->passphrase_len,
4701                                    idata->hash, client->id, SILC_ID_CLIENT);
4702   if (!result && admin->publickeys) {
4703     cached_key = silc_server_get_public_key(server, admin->publickeys);
4704     if (!cached_key)
4705       goto out;
4706     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4707                                    cached_key, 0, idata->hash, 
4708                                    client->id, SILC_ID_CLIENT);
4709   }
4710   if (!result) {
4711     /* Authentication failed */
4712     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4713                                           SILC_STATUS_ERR_AUTH_FAILED);
4714     goto out;
4715   }
4716
4717   /* Client is now router operator */
4718   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4719
4720   /* Update statistics */
4721   if (client->connection)
4722     server->stat.my_router_ops++;
4723   if (server->server_type == SILC_ROUTER)
4724     server->stat.router_ops++;
4725
4726   /* Send UMODE change to primary router */
4727   if (!server->standalone)
4728     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4729                                   client->id, client->mode);
4730
4731   /* Send reply to the sender */
4732   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4733                                         SILC_STATUS_OK);
4734
4735  out:
4736   silc_server_command_free(cmd);
4737 }
4738
4739 /* Server side of command BAN. This is used to manage the ban list of the
4740    channel. To add clients and remove clients from the ban list. */
4741
4742 SILC_SERVER_CMD_FUNC(ban)
4743 {
4744   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4745   SilcServer server = cmd->server;
4746   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4747   SilcBuffer packet;
4748   SilcChannelEntry channel;
4749   SilcChannelClientEntry chl;
4750   SilcChannelID *channel_id = NULL;
4751   unsigned char *id, *add, *del;
4752   SilcUInt32 id_len, tmp_len;
4753   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4754
4755   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4756     goto out;
4757
4758   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4759
4760   /* Get Channel ID */
4761   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4762   if (id) {
4763     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4764     if (!channel_id) {
4765       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4766                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4767       goto out;
4768     }
4769   }
4770
4771   /* Get channel entry. The server must know about the channel since the
4772      client is expected to be on the channel. */
4773   channel = silc_idlist_find_channel_by_id(server->local_list, 
4774                                            channel_id, NULL);
4775   if (!channel) {
4776     channel = silc_idlist_find_channel_by_id(server->global_list, 
4777                                              channel_id, NULL);
4778     if (!channel) {
4779       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4780                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4781       goto out;
4782     }
4783   }
4784
4785   /* Check whether this client is on the channel */
4786   if (!silc_server_client_on_channel(client, channel, &chl)) {
4787     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4788                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4789     goto out;
4790   }
4791
4792   /* The client must be at least channel operator. */
4793   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4794     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4795                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4796     goto out;
4797   }
4798
4799   /* Get the new ban and add it to the ban list */
4800   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4801   if (add) {
4802     if (!channel->ban_list)
4803       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4804     else
4805       channel->ban_list = silc_realloc(channel->ban_list, 
4806                                        sizeof(*channel->ban_list) * 
4807                                        (tmp_len + 
4808                                         strlen(channel->ban_list) + 2));
4809     if (add[tmp_len - 1] == ',')
4810       add[tmp_len - 1] = '\0';
4811
4812     strncat(channel->ban_list, add, tmp_len);
4813     strncat(channel->ban_list, ",", 1);
4814   }
4815
4816   /* Get the ban to be removed and remove it from the list */
4817   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4818   if (del && channel->ban_list) {
4819     char *start, *end, *n;
4820
4821     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4822       silc_free(channel->ban_list);
4823       channel->ban_list = NULL;
4824     } else {
4825       start = strstr(channel->ban_list, del);
4826       if (start && strlen(start) >= tmp_len) {
4827         end = start + tmp_len;
4828         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4829         strncat(n, channel->ban_list, start - channel->ban_list);
4830         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4831                              end) - 1);
4832         silc_free(channel->ban_list);
4833         channel->ban_list = n;
4834       }
4835     }
4836   }
4837
4838   /* Send the BAN notify type to our primary router. */
4839   if (!server->standalone && (add || del))
4840     silc_server_send_notify_ban(server, server->router->connection,
4841                                 server->server_type == SILC_ROUTER ?
4842                                 TRUE : FALSE, channel, add, del);
4843
4844   /* Send the reply back to the client */
4845   packet = 
4846     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4847                                          SILC_STATUS_OK, 0, ident, 2,
4848                                          2, id, id_len,
4849                                          3, channel->ban_list, 
4850                                          channel->ban_list ? 
4851                                          strlen(channel->ban_list) -1 : 0);
4852   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4853                           packet->data, packet->len, FALSE);
4854     
4855   silc_buffer_free(packet);
4856
4857  out:
4858   silc_free(channel_id);
4859   silc_server_command_free(cmd);
4860 }
4861
4862 /* Server side command of LEAVE. Removes client from a channel. */
4863
4864 SILC_SERVER_CMD_FUNC(leave)
4865 {
4866   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4867   SilcServer server = cmd->server;
4868   SilcSocketConnection sock = cmd->sock;
4869   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4870   SilcChannelID *id = NULL;
4871   SilcChannelEntry channel;
4872   SilcUInt32 len;
4873   unsigned char *tmp;
4874
4875   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4876
4877   /* Get Channel ID */
4878   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4879   if (!tmp) {
4880     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4881                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4882     goto out;
4883   }
4884   id = silc_id_payload_parse_id(tmp, len, NULL);
4885   if (!id) {
4886     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4887                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4888     goto out;
4889   }
4890
4891   /* Get channel entry */
4892   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4893   if (!channel) {
4894     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4895     if (!channel) {
4896       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4897                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4898       goto out;
4899     }
4900   }
4901
4902   /* Check whether this client is on the channel */
4903   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4904     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4905                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4906     goto out;
4907   }
4908
4909   /* Notify routers that they should remove this client from their list
4910      of clients on the channel. Send LEAVE notify type. */
4911   if (!server->standalone)
4912     silc_server_send_notify_leave(server, server->router->connection,
4913                                   server->server_type == SILC_ROUTER ?
4914                                   TRUE : FALSE, channel, id_entry->id);
4915
4916   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4917                                        SILC_STATUS_OK, 2, tmp, len);
4918
4919   /* Remove client from channel */
4920   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4921                                            TRUE))
4922     /* If the channel does not exist anymore we won't send anything */
4923     goto out;
4924
4925   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4926     /* Re-generate channel key */
4927     if (!silc_server_create_channel_key(server, channel, 0))
4928       goto out;
4929
4930     /* Send the channel key */
4931     silc_server_send_channel_key(server, NULL, channel, 
4932                                  server->server_type == SILC_ROUTER ? 
4933                                  FALSE : !server->standalone);
4934   }
4935
4936  out:
4937   silc_free(id);
4938   silc_server_command_free(cmd);
4939 }
4940
4941 /* Server side of command USERS. Resolves clients and their USERS currently
4942    joined on the requested channel. The list of Client ID's and their modes
4943    on the channel is sent back. */
4944
4945 SILC_SERVER_CMD_FUNC(users)
4946 {
4947   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4948   SilcServer server = cmd->server;
4949   SilcChannelEntry channel;
4950   SilcChannelID *id = NULL;
4951   SilcBuffer packet, idp;
4952   unsigned char *channel_id;
4953   SilcUInt32 channel_id_len;
4954   SilcBuffer client_id_list;
4955   SilcBuffer client_mode_list;
4956   unsigned char lc[4];
4957   SilcUInt32 list_count = 0;
4958   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4959   char *channel_name;
4960
4961   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4962
4963   /* Get Channel ID */
4964   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4965
4966   /* Get channel name */
4967   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4968
4969   if (!channel_id && !channel_name) {
4970     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4971                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4972     goto out;
4973   }
4974
4975   if (channel_id) {
4976     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4977     if (!id) {
4978       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4979                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4980       goto out;
4981     }
4982   }
4983
4984   /* If we are server and we don't know about this channel we will send
4985      the command to our router. If we know about the channel then we also
4986      have the list of users already. */
4987   if (id)
4988     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4989   else
4990     channel = silc_idlist_find_channel_by_name(server->local_list, 
4991                                                channel_name, NULL);
4992
4993   if (!channel || channel->disabled) {
4994     if (server->server_type != SILC_ROUTER && !server->standalone &&
4995         !cmd->pending) {
4996       SilcBuffer tmpbuf;
4997       
4998       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4999       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5000       
5001       /* Send USERS command */
5002       silc_server_packet_send(server, server->router->connection,
5003                               SILC_PACKET_COMMAND, cmd->packet->flags,
5004                               tmpbuf->data, tmpbuf->len, TRUE);
5005       
5006       /* Reprocess this packet after received reply */
5007       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5008                                   silc_command_get_ident(cmd->payload),
5009                                   silc_server_command_users,
5010                                   silc_server_command_dup(cmd));
5011       cmd->pending = TRUE;
5012       silc_command_set_ident(cmd->payload, ident);
5013       silc_buffer_free(tmpbuf);
5014       silc_free(id);
5015       goto out;
5016     }
5017
5018     /* Check the global list as well. */
5019     if (id)
5020       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5021     else
5022       channel = silc_idlist_find_channel_by_name(server->global_list, 
5023                                                  channel_name, NULL);
5024     if (!channel) {
5025       /* Channel really does not exist */
5026       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5027                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5028       goto out;
5029     }
5030   }
5031
5032   /* If the channel is private or secret do not send anything, unless the
5033      user requesting this command is on the channel. */
5034   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5035     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5036         && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
5037                                           NULL)) {
5038       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5039                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5040       goto out;
5041     }
5042   } else {
5043     if (channel->mode & 
5044         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5045       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5046                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5047       goto out;
5048     }
5049   }
5050
5051   /* Get the users list */
5052   silc_server_get_users_on_channel(server, channel, &client_id_list,
5053                                    &client_mode_list, &list_count);
5054
5055   /* List count */
5056   SILC_PUT32_MSB(list_count, lc);
5057
5058   /* Send reply */
5059   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5060   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5061                                                 SILC_STATUS_OK, 0, ident, 4,
5062                                                 2, idp->data, idp->len,
5063                                                 3, lc, 4,
5064                                                 4, client_id_list->data,
5065                                                 client_id_list->len,
5066                                                 5, client_mode_list->data,
5067                                                 client_mode_list->len);
5068   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5069                           packet->data, packet->len, FALSE);
5070     
5071   silc_buffer_free(idp);
5072   silc_buffer_free(packet);
5073   silc_buffer_free(client_id_list);
5074   silc_buffer_free(client_mode_list);
5075   silc_free(id);
5076
5077  out:
5078   silc_server_command_free(cmd);
5079 }
5080
5081 /* Server side of command GETKEY. This fetches the client's public key
5082    from the server where to the client is connected. */
5083
5084 SILC_SERVER_CMD_FUNC(getkey)
5085 {
5086   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5087   SilcServer server = cmd->server;
5088   SilcBuffer packet;
5089   SilcClientEntry client;
5090   SilcServerEntry server_entry;
5091   SilcClientID *client_id = NULL;
5092   SilcServerID *server_id = NULL;
5093   SilcIDPayload idp = NULL;
5094   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5095   unsigned char *tmp, *pkdata;
5096   SilcUInt32 tmp_len, pklen;
5097   SilcBuffer pk = NULL;
5098   SilcIdType id_type;
5099   SilcPublicKey public_key;
5100
5101   SILC_LOG_DEBUG(("Start"));
5102
5103   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5104   if (!tmp) {
5105     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5106                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5107     goto out;
5108   }
5109   idp = silc_id_payload_parse(tmp, tmp_len);
5110   if (!idp) {
5111     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5112                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5113     goto out;
5114   }
5115
5116   id_type = silc_id_payload_get_type(idp);
5117   if (id_type == SILC_ID_CLIENT) {
5118     client_id = silc_id_payload_get_id(idp);
5119
5120     /* If the client is not found from local list there is no chance it
5121        would be locally connected client so send the command further. */
5122     client = silc_idlist_find_client_by_id(server->local_list, 
5123                                            client_id, TRUE, NULL);
5124     if (!client)
5125       client = silc_idlist_find_client_by_id(server->global_list, 
5126                                              client_id, TRUE, NULL);
5127     
5128     if ((!client && !cmd->pending && !server->standalone) ||
5129         (client && !client->connection && !cmd->pending) ||
5130         (client && !client->data.public_key && !cmd->pending)) {
5131       SilcBuffer tmpbuf;
5132       SilcUInt16 old_ident;
5133       SilcSocketConnection dest_sock;
5134       
5135       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5136                                                client_id, NULL);
5137       if (!dest_sock)
5138         goto out;
5139       
5140       old_ident = silc_command_get_ident(cmd->payload);
5141       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5142       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5143       
5144       silc_server_packet_send(server, dest_sock,
5145                               SILC_PACKET_COMMAND, cmd->packet->flags,
5146                               tmpbuf->data, tmpbuf->len, TRUE);
5147       
5148       /* Reprocess this packet after received reply from router */
5149       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5150                                   silc_command_get_ident(cmd->payload),
5151                                   silc_server_command_getkey,
5152                                   silc_server_command_dup(cmd));
5153       cmd->pending = TRUE;
5154       silc_command_set_ident(cmd->payload, old_ident);
5155       silc_buffer_free(tmpbuf);
5156       goto out;
5157     }
5158
5159     if (!client) {
5160       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5161                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5162       goto out;
5163     }
5164
5165     /* The client is locally connected, just get the public key and
5166        send it back. If they key does not exist then do not send it, 
5167        send just OK reply */
5168     public_key = client->data.public_key;
5169     if (!public_key) {
5170       pkdata = NULL;
5171       pklen = 0;
5172     } else {
5173       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5174       pk = silc_buffer_alloc(4 + tmp_len);
5175       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5176       silc_buffer_format(pk,
5177                          SILC_STR_UI_SHORT(tmp_len),
5178                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5179                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5180                          SILC_STR_END);
5181       silc_free(tmp);
5182       pkdata = pk->data;
5183       pklen = pk->len;
5184     }
5185   } else if (id_type == SILC_ID_SERVER) {
5186     server_id = silc_id_payload_get_id(idp);
5187
5188     /* If the server is not found from local list there is no chance it
5189        would be locally connected server so send the command further. */
5190     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5191                                                  server_id, TRUE, NULL);
5192     if (!server_entry)
5193       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5194                                                    server_id, TRUE, NULL);
5195     
5196     if (server_entry != server->id_entry &&
5197         ((!server_entry && !cmd->pending && !server->standalone) ||
5198          (server_entry && !server_entry->connection && !cmd->pending &&
5199           !server->standalone) ||
5200          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5201           !server->standalone))) {
5202       SilcBuffer tmpbuf;
5203       SilcUInt16 old_ident;
5204       
5205       old_ident = silc_command_get_ident(cmd->payload);
5206       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5207       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5208       
5209       silc_server_packet_send(server, server->router->connection,
5210                               SILC_PACKET_COMMAND, cmd->packet->flags,
5211                               tmpbuf->data, tmpbuf->len, TRUE);
5212       
5213       /* Reprocess this packet after received reply from router */
5214       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5215                                   silc_command_get_ident(cmd->payload),
5216                                   silc_server_command_getkey,
5217                                   silc_server_command_dup(cmd));
5218       cmd->pending = TRUE;
5219       silc_command_set_ident(cmd->payload, old_ident);
5220       silc_buffer_free(tmpbuf);
5221       goto out;
5222     }
5223
5224     if (!server_entry) {
5225       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5226                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5227       goto out;
5228     }
5229
5230     /* If they key does not exist then do not send it, send just OK reply */
5231     public_key = (!server_entry->data.public_key ? 
5232                   (server_entry == server->id_entry ? server->public_key :
5233                    NULL) : server_entry->data.public_key);
5234     if (!public_key) {
5235       pkdata = NULL;
5236       pklen = 0;
5237     } else {
5238       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5239       pk = silc_buffer_alloc(4 + tmp_len);
5240       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5241       silc_buffer_format(pk,
5242                          SILC_STR_UI_SHORT(tmp_len),
5243                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5244                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5245                          SILC_STR_END);
5246       silc_free(tmp);
5247       pkdata = pk->data;
5248       pklen = pk->len;
5249     }
5250   } else {
5251     goto out;
5252   }
5253
5254   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5255   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5256                                                 SILC_STATUS_OK, 0, ident, 
5257                                                 pkdata ? 2 : 1,
5258                                                 2, tmp, tmp_len,
5259                                                 3, pkdata, pklen);
5260   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5261                           packet->data, packet->len, FALSE);
5262   silc_buffer_free(packet);
5263
5264   if (pk)
5265     silc_buffer_free(pk);
5266
5267  out:
5268   if (idp)
5269     silc_id_payload_free(idp);
5270   silc_free(client_id);
5271   silc_free(server_id);
5272   silc_server_command_free(cmd);
5273 }
5274
5275
5276 /* Private range commands, specific to this implementation */
5277
5278 /* Server side command of CONNECT. Connects us to the specified remote
5279    server or router. */
5280
5281 SILC_SERVER_CMD_FUNC(connect)
5282 {
5283   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5284   SilcServer server = cmd->server;
5285   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5286   unsigned char *tmp, *host;
5287   SilcUInt32 tmp_len;
5288   SilcUInt32 port = SILC_PORT;
5289
5290   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5291
5292   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5293     goto out;
5294
5295   /* Check whether client has the permissions. */
5296   if (client->mode == SILC_UMODE_NONE) {
5297     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5298                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5299     goto out;
5300   }
5301
5302   if (server->server_type == SILC_ROUTER && 
5303       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5304     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5305                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
5306     goto out;
5307   }
5308
5309   /* Get the remote server */
5310   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5311   if (!host) {
5312     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5313                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5314     goto out;
5315   }
5316
5317   /* Get port */
5318   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5319   if (tmp)
5320     SILC_GET32_MSB(port, tmp);
5321
5322   /* Create the connection. It is done with timeout and is async. */
5323   silc_server_create_connection(server, host, port);
5324
5325   /* Send reply to the sender */
5326   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5327                                         SILC_STATUS_OK);
5328
5329  out:
5330   silc_server_command_free(cmd);
5331 }
5332
5333 /* Server side command of CLOSE. Closes connection to a specified server. */
5334  
5335 SILC_SERVER_CMD_FUNC(close)
5336 {
5337   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5338   SilcServer server = cmd->server;
5339   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5340   SilcServerEntry server_entry;
5341   SilcSocketConnection sock;
5342   unsigned char *tmp;
5343   SilcUInt32 tmp_len;
5344   unsigned char *name;
5345   SilcUInt32 port = SILC_PORT;
5346
5347   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5348
5349   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5350     goto out;
5351
5352   /* Check whether client has the permissions. */
5353   if (client->mode == SILC_UMODE_NONE) {
5354     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5355                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5356     goto out;
5357   }
5358
5359   /* Get the remote server */
5360   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5361   if (!name) {
5362     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5363                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5364     goto out;
5365   }
5366
5367   /* Get port */
5368   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5369   if (tmp)
5370     SILC_GET32_MSB(port, tmp);
5371
5372   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5373                                                  name, port, FALSE, NULL);
5374   if (!server_entry)
5375     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5376                                                    name, port, FALSE, NULL);
5377   if (!server_entry) {
5378     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5379                                           SILC_STATUS_ERR_NO_SERVER_ID);
5380     goto out;
5381   }
5382
5383   /* Send reply to the sender */
5384   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5385                                         SILC_STATUS_OK);
5386
5387   /* Close the connection to the server */
5388   sock = (SilcSocketConnection)server_entry->connection;
5389
5390   /* If we shutdown primary router connection manually then don't trigger
5391      any reconnect or backup router connections, by setting the router
5392      to NULL here. */
5393   if (server->router == server_entry) {
5394     server->id_entry->router = NULL;
5395     server->router = NULL;
5396     server->standalone = TRUE;
5397   }
5398   silc_server_free_sock_user_data(server, sock, NULL);
5399   silc_server_close_connection(server, sock);
5400   
5401  out:
5402   silc_server_command_free(cmd);
5403 }
5404
5405 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5406    active connections. */
5407  
5408 SILC_SERVER_CMD_FUNC(shutdown)
5409 {
5410   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5411   SilcServer server = cmd->server;
5412   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5413
5414   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5415
5416   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5417     goto out;
5418
5419   /* Check whether client has the permission. */
5420   if (client->mode == SILC_UMODE_NONE) {
5421     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5422                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5423     goto out;
5424   }
5425
5426   /* Send reply to the sender */
5427   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5428                                         SILC_STATUS_OK);
5429
5430   /* Then, gracefully, or not, bring the server down. */
5431   silc_server_stop(server);
5432   exit(0);
5433
5434  out:
5435   silc_server_command_free(cmd);
5436 }