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