udpates
[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] <= 32) 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     if (nick[i] == '@') return TRUE;
1948   }
1949
1950   return FALSE;
1951 }
1952
1953 /* Server side of command NICK. Sets nickname for user. Setting
1954    nickname causes generation of a new client ID for the client. The
1955    new client ID is sent to the client after changing the nickname. */
1956
1957 SILC_SERVER_CMD_FUNC(nick)
1958 {
1959   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1960   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1961   SilcServer server = cmd->server;
1962   SilcBuffer packet, nidp, oidp;
1963   SilcClientID *new_id;
1964   char *nick;
1965   uint16 ident = silc_command_get_ident(cmd->payload);
1966   int nickfail = 0;
1967
1968   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1969     goto out;
1970
1971   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1972
1973   /* Check nickname */
1974   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1975   if (silc_server_command_bad_chars(nick) == TRUE) {
1976     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1977                                           SILC_STATUS_ERR_BAD_NICKNAME);
1978     goto out;
1979   }
1980
1981   if (strlen(nick) > 128)
1982     nick[128] = '\0';
1983
1984   /* Create new Client ID */
1985   while (!silc_id_create_client_id(cmd->server, cmd->server->id, 
1986                                    cmd->server->rng, 
1987                                    cmd->server->md5hash, nick,
1988                                    &new_id)) {
1989     nickfail++;
1990     snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
1991   }
1992
1993   /* Send notify about nickname change to our router. We send the new
1994      ID and ask to replace it with the old one. If we are router the
1995      packet is broadcasted. Send NICK_CHANGE notify. */
1996   if (!server->standalone)
1997     silc_server_send_notify_nick_change(server, server->router->connection, 
1998                                         server->server_type == SILC_SERVER ? 
1999                                         FALSE : TRUE, client->id,
2000                                         new_id);
2001
2002   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2003
2004   /* Remove old cache entry */
2005   silc_idcache_del_by_context(server->local_list->clients, client);
2006
2007   /* Free old ID */
2008   silc_free(client->id);
2009
2010   /* Save the nickname as this client is our local client */
2011   silc_free(client->nickname);
2012
2013   client->nickname = strdup(nick);
2014   client->id = new_id;
2015
2016   /* Update client cache */
2017   silc_idcache_add(server->local_list->clients, client->nickname, 
2018                    client->id, (void *)client, FALSE);
2019
2020   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2021
2022   /* Send NICK_CHANGE notify to the client's channels */
2023   silc_server_send_notify_on_channels(server, NULL, client, 
2024                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2025                                       oidp->data, oidp->len, 
2026                                       nidp->data, nidp->len);
2027
2028   /* Send the new Client ID as reply command back to client */
2029   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
2030                                                 SILC_STATUS_OK, ident, 1, 
2031                                                 2, nidp->data, nidp->len);
2032   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2033                           0, packet->data, packet->len, FALSE);
2034
2035   silc_buffer_free(packet);
2036   silc_buffer_free(nidp);
2037   silc_buffer_free(oidp);
2038   
2039  out:
2040   silc_server_command_free(cmd);
2041 }
2042
2043 /* Sends the LIST command reply */
2044
2045 static void
2046 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2047                                     SilcChannelEntry *lch, 
2048                                     uint32 lch_count,
2049                                     SilcChannelEntry *gch,
2050                                     uint32 gch_count)
2051 {
2052   int i;
2053   SilcBuffer packet, idp;
2054   SilcChannelEntry entry;
2055   SilcCommandStatus status;
2056   uint16 ident = silc_command_get_ident(cmd->payload);
2057   char *topic;
2058   unsigned char usercount[4];
2059   uint32 users;
2060
2061   for (i = 0; i < lch_count; i++)
2062     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2063       lch[i] = NULL;
2064   for (i = 0; i < gch_count; i++)
2065     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2066       gch[i] = NULL;
2067
2068   status = SILC_STATUS_OK;
2069   if ((lch_count + gch_count) > 1)
2070     status = SILC_STATUS_LIST_START;
2071
2072   /* Local list */
2073   for (i = 0; i < lch_count; i++) {
2074     entry = lch[i];
2075
2076     if (!entry)
2077       continue;
2078
2079     if (i >= 1)
2080       status = SILC_STATUS_LIST_ITEM;
2081
2082     if (i == lch_count - 1 && gch_count)
2083       break;
2084     if (lch_count > 1 && i == lch_count - 1)
2085       status = SILC_STATUS_LIST_END;
2086
2087     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2088
2089     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2090       topic = "*private*";
2091       memset(usercount, 0, sizeof(usercount));
2092     } else {
2093       topic = entry->topic;
2094       users = silc_hash_table_count(entry->user_list);
2095       SILC_PUT32_MSB(users, usercount);
2096     }
2097
2098     /* Send the reply */
2099     if (topic)
2100       packet = 
2101         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2102                                              status, ident, 4, 
2103                                              2, idp->data, idp->len,
2104                                              3, entry->channel_name, 
2105                                              strlen(entry->channel_name),
2106                                              4, topic, strlen(topic),
2107                                              5, usercount, 4);
2108     else
2109       packet = 
2110         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2111                                              status, ident, 3, 
2112                                              2, idp->data, idp->len,
2113                                              3, entry->channel_name, 
2114                                              strlen(entry->channel_name),
2115                                              5, usercount, 4);
2116     silc_server_packet_send(cmd->server, cmd->sock, 
2117                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2118                             packet->len, FALSE);
2119     silc_buffer_free(packet);
2120     silc_buffer_free(idp);
2121   }
2122
2123   status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
2124
2125   /* Global list */
2126   for (i = 0; i < gch_count; i++) {
2127     entry = gch[i];
2128
2129     if (!entry)
2130       continue;
2131
2132     if (i >= 1)
2133       status = SILC_STATUS_LIST_ITEM;
2134
2135     if (gch_count > 1 && i == lch_count - 1)
2136       status = SILC_STATUS_LIST_END;
2137
2138     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2139
2140     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2141       topic = "*private*";
2142       memset(usercount, 0, sizeof(usercount));
2143     } else {
2144       topic = entry->topic;
2145       users = silc_hash_table_count(entry->user_list);
2146       SILC_PUT32_MSB(users, usercount);
2147     }
2148
2149     /* Send the reply */
2150     if (topic)
2151       packet = 
2152         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2153                                              status, ident, 4, 
2154                                              2, idp->data, idp->len,
2155                                              3, entry->channel_name, 
2156                                              strlen(entry->channel_name),
2157                                              4, topic, strlen(topic),
2158                                              5, usercount, 4);
2159     else
2160       packet = 
2161         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2162                                              status, ident, 3, 
2163                                              2, idp->data, idp->len,
2164                                              3, entry->channel_name, 
2165                                              strlen(entry->channel_name),
2166                                              5, usercount, 4);
2167     silc_server_packet_send(cmd->server, cmd->sock, 
2168                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2169                             packet->len, FALSE);
2170     silc_buffer_free(packet);
2171     silc_buffer_free(idp);
2172   }
2173 }
2174
2175 /* Server side of LIST command. This lists the channel of the requested
2176    server. Secret channels are not listed. */
2177
2178 SILC_SERVER_CMD_FUNC(list)
2179 {
2180   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2181   SilcServer server = cmd->server;
2182   SilcChannelID *channel_id = NULL;
2183   unsigned char *tmp;
2184   uint32 tmp_len;
2185   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2186   uint32 lch_count = 0, gch_count = 0;
2187
2188   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 2);
2189
2190   /* Get Channel ID */
2191   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2192   if (tmp) {
2193     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2194     if (!channel_id) {
2195       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2196                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
2197       goto out;
2198     }
2199   }
2200
2201   /* Get the channels from local list */
2202   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2203                                        &lch_count);
2204   
2205   /* Get the channels from global list if we are router */
2206   if (server->server_type != SILC_SERVER) 
2207     gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2208                                          &gch_count);
2209
2210   /* Send the reply */
2211   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
2212                                       gchannels, gch_count);
2213
2214  out:
2215   silc_server_command_free(cmd);
2216 }
2217
2218 /* Server side of TOPIC command. Sets topic for channel and/or returns
2219    current topic to client. */
2220
2221 SILC_SERVER_CMD_FUNC(topic)
2222 {
2223   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2224   SilcServer server = cmd->server;
2225   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2226   SilcChannelID *channel_id;
2227   SilcChannelEntry channel;
2228   SilcChannelClientEntry chl;
2229   SilcBuffer packet, idp;
2230   unsigned char *tmp;
2231   uint32 argc, tmp_len;
2232   uint16 ident = silc_command_get_ident(cmd->payload);
2233
2234   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2235
2236   argc = silc_argument_get_arg_num(cmd->args);
2237
2238   /* Get Channel ID */
2239   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2240   if (!tmp) {
2241     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2242                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2243     goto out;
2244   }
2245   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2246   if (!channel_id) {
2247     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2248                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2249     goto out;
2250   }
2251
2252   /* Check whether the channel exists */
2253   channel = silc_idlist_find_channel_by_id(server->local_list, 
2254                                            channel_id, NULL);
2255   if (!channel) {
2256     channel = silc_idlist_find_channel_by_id(server->global_list, 
2257                                              channel_id, NULL);
2258     if (!channel) {
2259       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2260                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2261       goto out;
2262     }
2263   }
2264
2265   if (argc > 1) {
2266     /* Get the topic */
2267     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2268     if (!tmp) {
2269       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2270                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2271       goto out;
2272     }
2273
2274     if (strlen(tmp) > 256) {
2275       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2276                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2277       goto out;
2278     }
2279
2280     /* See whether the client is on channel and has rights to change topic */
2281     if (!silc_hash_table_find(channel->user_list, client, NULL, 
2282                               (void *)&chl)) {
2283       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2284                                             SILC_STATUS_ERR_NOT_ON_CHANNEL);
2285       goto out;
2286     }
2287
2288     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2289       if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2290         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2291                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2292         goto out;
2293       }
2294     }
2295
2296     /* Set the topic for channel */
2297     silc_free(channel->topic);
2298     channel->topic = strdup(tmp);
2299
2300     /* Send TOPIC_SET notify type to the network */
2301     if (!server->standalone)
2302       silc_server_send_notify_topic_set(server, server->router->connection,
2303                                         server->server_type == SILC_ROUTER ?
2304                                         TRUE : FALSE, channel, client->id,
2305                                         channel->topic);
2306
2307     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2308
2309     /* Send notify about topic change to all clients on the channel */
2310     silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2311                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2312                                        idp->data, idp->len,
2313                                        channel->topic, strlen(channel->topic));
2314     silc_buffer_free(idp);
2315   }
2316
2317   /* Send the topic to client as reply packet */
2318   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2319   if (channel->topic)
2320     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2321                                                   SILC_STATUS_OK, ident, 2, 
2322                                                   2, idp->data, idp->len,
2323                                                   3, channel->topic, 
2324                                                   strlen(channel->topic));
2325   else
2326     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2327                                                   SILC_STATUS_OK, ident, 1, 
2328                                                   2, idp->data, idp->len);
2329   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2330                           0, packet->data, packet->len, FALSE);
2331
2332   silc_buffer_free(packet);
2333   silc_buffer_free(idp);
2334   silc_free(channel_id);
2335
2336  out:
2337   silc_server_command_free(cmd);
2338 }
2339
2340 /* Server side of INVITE command. Invites some client to join some channel. 
2341    This command is also used to manage the invite list of the channel. */
2342
2343 SILC_SERVER_CMD_FUNC(invite)
2344 {
2345   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2346   SilcServer server = cmd->server;
2347   SilcSocketConnection sock = cmd->sock, dest_sock;
2348   SilcChannelClientEntry chl;
2349   SilcClientEntry sender, dest;
2350   SilcClientID *dest_id = NULL;
2351   SilcChannelEntry channel;
2352   SilcChannelID *channel_id = NULL;
2353   SilcIDListData idata;
2354   SilcBuffer idp, idp2, packet;
2355   unsigned char *tmp, *add, *del;
2356   uint32 len;
2357   uint16 ident = silc_command_get_ident(cmd->payload);
2358
2359   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2360
2361   /* Get Channel ID */
2362   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2363   if (!tmp) {
2364     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2365                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2366     goto out;
2367   }
2368   channel_id = silc_id_payload_parse_id(tmp, len);
2369   if (!channel_id) {
2370     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2371                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2372     goto out;
2373   }
2374
2375   /* Get the channel entry */
2376   channel = silc_idlist_find_channel_by_id(server->local_list, 
2377                                            channel_id, NULL);
2378   if (!channel) {
2379     channel = silc_idlist_find_channel_by_id(server->global_list, 
2380                                              channel_id, NULL);
2381     if (!channel) {
2382       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2383                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2384       goto out;
2385     }
2386   }
2387
2388   /* Check whether the sender of this command is on the channel. */
2389   sender = (SilcClientEntry)sock->user_data;
2390   if (!silc_server_client_on_channel(sender, channel)) {
2391     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2392                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2393     goto out;
2394   }
2395
2396   /* Check whether the channel is invite-only channel. If yes then the
2397      sender of this command must be at least channel operator. */
2398   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2399     silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2400     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2401       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2402                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2403       goto out;
2404     }
2405   }
2406
2407   /* Get destination client ID */
2408   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2409   if (tmp) {
2410     char invite[512];
2411
2412     dest_id = silc_id_payload_parse_id(tmp, len);
2413     if (!dest_id) {
2414       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2415                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2416       goto out;
2417     }
2418
2419     /* Get the client entry */
2420     dest = silc_server_get_client_resolve(server, dest_id);
2421     if (!dest) {
2422       if (server->server_type != SILC_SERVER) {
2423         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2424                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2425         goto out;
2426       }
2427       
2428       /* The client info is being resolved. Reprocess this packet after
2429          receiving the reply to the query. */
2430       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2431                                   server->cmd_ident,
2432                                   silc_server_command_destructor,
2433                                   silc_server_command_invite, 
2434                                   silc_server_command_dup(cmd));
2435       cmd->pending = TRUE;
2436       silc_free(channel_id);
2437       silc_free(dest_id);
2438       return;
2439     }
2440
2441     /* Check whether the requested client is already on the channel. */
2442     if (silc_server_client_on_channel(dest, channel)) {
2443       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2444                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2445       goto out;
2446     }
2447     
2448     /* Get route to the client */
2449     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2450     if (!dest_sock) {
2451       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2452                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2453       goto out;
2454     }
2455
2456     memset(invite, 0, sizeof(invite));
2457     strncat(invite, dest->nickname, strlen(dest->nickname));
2458     strncat(invite, "!", 1);
2459     strncat(invite, dest->username, strlen(dest->username));
2460     if (!strchr(dest->username, '@')) {
2461       strncat(invite, "@", 1);
2462       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2463     }
2464
2465     len = strlen(invite);
2466     if (!channel->invite_list)
2467       channel->invite_list = silc_calloc(len + 2, 
2468                                          sizeof(*channel->invite_list));
2469     else
2470       channel->invite_list = silc_realloc(channel->invite_list, 
2471                                           sizeof(*channel->invite_list) * 
2472                                           (len + 
2473                                            strlen(channel->invite_list) + 2));
2474     strncat(channel->invite_list, invite, len);
2475     strncat(channel->invite_list, ",", 1);
2476
2477     /* Send notify to the client that is invited to the channel */
2478     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2479     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2480     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2481                                  SILC_ID_CLIENT,
2482                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2483                                  idp->data, idp->len, 
2484                                  channel->channel_name, 
2485                                  strlen(channel->channel_name),
2486                                  idp2->data, idp2->len);
2487     silc_buffer_free(idp);
2488     silc_buffer_free(idp2);
2489   }
2490
2491   /* Add the client to the invite list of the channel */
2492   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2493   if (add) {
2494     if (!channel->invite_list)
2495       channel->invite_list = silc_calloc(len + 2, 
2496                                          sizeof(*channel->invite_list));
2497     else
2498       channel->invite_list = silc_realloc(channel->invite_list, 
2499                                           sizeof(*channel->invite_list) * 
2500                                           (len + 
2501                                            strlen(channel->invite_list) + 2));
2502     if (add[len - 1] == ',')
2503       add[len - 1] = '\0';
2504     
2505     strncat(channel->invite_list, add, len);
2506     strncat(channel->invite_list, ",", 1);
2507   }
2508
2509   /* Get the invite to be removed and remove it from the list */
2510   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2511   if (del && channel->invite_list) {
2512     char *start, *end, *n;
2513
2514     if (!strncmp(channel->invite_list, del, 
2515                  strlen(channel->invite_list) - 1)) {
2516       silc_free(channel->invite_list);
2517       channel->invite_list = NULL;
2518     } else {
2519       start = strstr(channel->invite_list, del);
2520       if (start && strlen(start) >= len) {
2521         end = start + len;
2522         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2523         strncat(n, channel->invite_list, start - channel->invite_list);
2524         strncat(n, end + 1, ((channel->invite_list + 
2525                               strlen(channel->invite_list)) - end) - 1);
2526         silc_free(channel->invite_list);
2527         channel->invite_list = n;
2528       }
2529     }
2530   }
2531
2532   /* Send notify to the primary router */
2533   if (!server->standalone)
2534     silc_server_send_notify_invite(server, server->router->connection,
2535                                    server->server_type == SILC_ROUTER ?
2536                                    TRUE : FALSE, channel,
2537                                    sender->id, add, del);
2538
2539   /* Send command reply */
2540   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2541
2542   if (add || del)
2543     packet = 
2544       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2545                                            SILC_STATUS_OK, ident, 2,
2546                                            2, tmp, len,
2547                                            3, channel->invite_list,
2548                                            channel->invite_list ?
2549                                            strlen(channel->invite_list) : 0);
2550   else
2551     packet = 
2552       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2553                                            SILC_STATUS_OK, ident, 1,
2554                                            2, tmp, len);
2555   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2556                           packet->data, packet->len, FALSE);
2557   silc_buffer_free(packet);
2558
2559  out:
2560   silc_free(dest_id);
2561   silc_free(channel_id);
2562   silc_server_command_free(cmd);
2563 }
2564
2565 typedef struct {
2566   SilcServer server;
2567   SilcSocketConnection sock;
2568   char *signoff;
2569 } *QuitInternal;
2570
2571 /* Quits connection to client. This gets called if client won't
2572    close the connection even when it has issued QUIT command. */
2573
2574 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2575 {
2576   QuitInternal q = (QuitInternal)context;
2577
2578   /* Free all client specific data, such as client entry and entires
2579      on channels this client may be on. */
2580   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2581                                TRUE, q->signoff);
2582   q->sock->user_data = NULL;
2583
2584   /* Close the connection on our side */
2585   silc_server_close_connection(q->server, q->sock);
2586
2587   silc_free(q->signoff);
2588   silc_free(q);
2589 }
2590
2591 /* Quits SILC session. This is the normal way to disconnect client. */
2592  
2593 SILC_SERVER_CMD_FUNC(quit)
2594 {
2595   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2596   SilcServer server = cmd->server;
2597   SilcSocketConnection sock = cmd->sock;
2598   QuitInternal q;
2599   unsigned char *tmp = NULL;
2600   uint32 len = 0;
2601
2602   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2603
2604   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2605     goto out;
2606
2607   /* Get destination ID */
2608   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2609   if (len > 128)
2610     tmp = NULL;
2611
2612   q = silc_calloc(1, sizeof(*q));
2613   q->server = server;
2614   q->sock = sock;
2615   q->signoff = tmp ? strdup(tmp) : NULL;
2616
2617   /* We quit the connection with little timeout */
2618   silc_schedule_task_add(server->schedule, sock->sock,
2619                      silc_server_command_quit_cb, (void *)q,
2620                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2621
2622  out:
2623   silc_server_command_free(cmd);
2624 }
2625
2626 /* Server side of command KILL. This command is used by router operator
2627    to remove an client from the SILC Network temporarily. */
2628
2629 SILC_SERVER_CMD_FUNC(kill)
2630 {
2631   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2632   SilcServer server = cmd->server;
2633   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2634   SilcClientEntry remote_client;
2635   SilcClientID *client_id;
2636   unsigned char *tmp, *comment;
2637   uint32 tmp_len, tmp_len2;
2638
2639   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2640
2641   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2642     goto out;
2643
2644   /* KILL command works only on router */
2645   if (server->server_type != SILC_ROUTER) {
2646     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2647                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2648     goto out;
2649   }
2650
2651   /* Check whether client has the permissions. */
2652   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2653     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2654                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2655     goto out;
2656   }
2657
2658   /* Get the client ID */
2659   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2660   if (!tmp) {
2661     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2662                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2663     goto out;
2664   }
2665   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2666   if (!client_id) {
2667     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2668                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2669     goto out;
2670   }
2671
2672   /* Get the client entry */
2673   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2674                                                 client_id, TRUE, NULL);
2675   if (!remote_client) {
2676     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2677                                                   client_id, TRUE, NULL);
2678     if (!remote_client) {
2679       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2680                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2681       goto out;
2682     }
2683   }
2684
2685   /* Get comment */
2686   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2687   if (tmp_len2 > 128)
2688     comment = NULL;
2689
2690   /* Send reply to the sender */
2691   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2692                                         SILC_STATUS_OK);
2693
2694   /* Send the KILL notify packets. First send it to the channel, then
2695      to our primary router and then directly to the client who is being
2696      killed right now. */
2697
2698   /* Send KILLED notify to the channels. It is not sent to the client
2699      as it will be sent differently destined directly to the client and not
2700      to the channel. */
2701   silc_server_send_notify_on_channels(server, remote_client, 
2702                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2703                                       comment ? 2 : 1,
2704                                       tmp, tmp_len,
2705                                       comment, comment ? tmp_len2 : 0);
2706
2707   /* Send KILLED notify to primary route */
2708   if (!server->standalone)
2709     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2710                                    remote_client->id, comment);
2711
2712   /* Send KILLED notify to the client directly */
2713   silc_server_send_notify_killed(server, remote_client->connection ? 
2714                                  remote_client->connection : 
2715                                  remote_client->router->connection, FALSE,
2716                                  remote_client->id, comment);
2717
2718   /* Remove the client from all channels. This generates new keys to the
2719      channels as well. */
2720   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2721                                    NULL, TRUE);
2722
2723   /* Remove the client entry, If it is locally connected then we will also
2724      disconnect the client here */
2725   if (remote_client->connection) {
2726     /* Remove locally conneted client */
2727     SilcSocketConnection sock = remote_client->connection;
2728     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2729     silc_server_close_connection(server, sock);
2730   } else {
2731     /* Remove remote client */
2732     if (!silc_idlist_del_client(server->global_list, remote_client))
2733       silc_idlist_del_client(server->local_list, remote_client);
2734   }
2735
2736  out:
2737   silc_server_command_free(cmd);
2738 }
2739
2740 /* Server side of command INFO. This sends information about us to 
2741    the client. If client requested specific server we will send the 
2742    command to that server. */
2743
2744 SILC_SERVER_CMD_FUNC(info)
2745 {
2746   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2747   SilcServer server = cmd->server;
2748   SilcBuffer packet, idp;
2749   unsigned char *tmp;
2750   uint32 tmp_len;
2751   char *dest_server, *server_info = NULL, *server_name;
2752   uint16 ident = silc_command_get_ident(cmd->payload);
2753   SilcServerEntry entry = NULL;
2754   SilcServerID *server_id = NULL;
2755
2756   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2757
2758   /* Get server name */
2759   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2760
2761   /* Get Server ID */
2762   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2763   if (tmp) {
2764     server_id = silc_id_payload_parse_id(tmp, tmp_len);
2765     if (!server_id) {
2766       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2767                                             SILC_STATUS_ERR_NO_SERVER_ID);
2768       goto out;
2769     }
2770   }
2771
2772   if (server_id) {
2773     /* Check whether we have this server cached */
2774     entry = silc_idlist_find_server_by_id(server->local_list,
2775                                           server_id, TRUE, NULL);
2776     if (!entry) {
2777       entry = silc_idlist_find_server_by_id(server->global_list,
2778                                             server_id, TRUE, NULL);
2779       if (!entry && server->server_type != SILC_SERVER) {
2780         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2781                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2782         goto out;
2783       }
2784     }
2785   }
2786
2787   /* Some buggy servers has sent request to router about themselves. */
2788   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2789     goto out;
2790
2791   if ((!dest_server && !server_id && !entry) || (entry && 
2792                                                  entry == server->id_entry) ||
2793       (dest_server && !cmd->pending && 
2794        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2795     /* Send our reply */
2796     char info_string[256];
2797
2798     memset(info_string, 0, sizeof(info_string));
2799     snprintf(info_string, sizeof(info_string), 
2800              "location: %s server: %s admin: %s <%s>",
2801              server->config->admin_info->location,
2802              server->config->admin_info->server_type,
2803              server->config->admin_info->admin_name,
2804              server->config->admin_info->admin_email);
2805
2806     server_info = info_string;
2807     entry = server->id_entry;
2808   } else {
2809     /* Check whether we have this server cached */
2810     if (!entry && dest_server) {
2811       entry = silc_idlist_find_server_by_name(server->global_list,
2812                                               dest_server, TRUE, NULL);
2813       if (!entry) {
2814         entry = silc_idlist_find_server_by_name(server->local_list,
2815                                                 dest_server, TRUE, NULL);
2816       }
2817     }
2818
2819     if (!cmd->pending &&
2820         server->server_type != SILC_SERVER && entry && !entry->server_info) {
2821       /* Send to the server */
2822       SilcBuffer tmpbuf;
2823       uint16 old_ident;
2824
2825       old_ident = silc_command_get_ident(cmd->payload);
2826       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2827       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2828
2829       silc_server_packet_send(server, entry->connection,
2830                               SILC_PACKET_COMMAND, cmd->packet->flags,
2831                               tmpbuf->data, tmpbuf->len, TRUE);
2832
2833       /* Reprocess this packet after received reply from router */
2834       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2835                                   silc_command_get_ident(cmd->payload),
2836                                   silc_server_command_destructor,
2837                                   silc_server_command_info,
2838                                   silc_server_command_dup(cmd));
2839       cmd->pending = TRUE;
2840       silc_command_set_ident(cmd->payload, old_ident);
2841       silc_buffer_free(tmpbuf);
2842       return;
2843     }
2844
2845     if (!entry && !cmd->pending && !server->standalone) {
2846       /* Send to the primary router */
2847       SilcBuffer tmpbuf;
2848       uint16 old_ident;
2849
2850       old_ident = silc_command_get_ident(cmd->payload);
2851       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2852       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2853
2854       silc_server_packet_send(server, server->router->connection,
2855                               SILC_PACKET_COMMAND, cmd->packet->flags,
2856                               tmpbuf->data, tmpbuf->len, TRUE);
2857
2858       /* Reprocess this packet after received reply from router */
2859       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2860                                   silc_command_get_ident(cmd->payload),
2861                                   silc_server_command_destructor,
2862                                   silc_server_command_info,
2863                                   silc_server_command_dup(cmd));
2864       cmd->pending = TRUE;
2865       silc_command_set_ident(cmd->payload, old_ident);
2866       silc_buffer_free(tmpbuf);
2867       return;
2868     }
2869   }
2870
2871   silc_free(server_id);
2872
2873   if (!entry) {
2874     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2875                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2876     goto out;
2877   }
2878
2879   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2880   if (!server_info)
2881     server_info = entry->server_info;
2882   server_name = entry->server_name;
2883
2884   /* Send the reply */
2885   if (server_info)
2886     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2887                                                   SILC_STATUS_OK, ident, 3,
2888                                                   2, idp->data, idp->len,
2889                                                   3, server_name, 
2890                                                   strlen(server_name),
2891                                                   4, server_info, 
2892                                                   strlen(server_info));
2893   else
2894     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2895                                                   SILC_STATUS_OK, ident, 2,
2896                                                   2, idp->data, idp->len,
2897                                                   3, server_name, 
2898                                                   strlen(server_name));
2899   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2900                           packet->data, packet->len, FALSE);
2901     
2902   silc_buffer_free(packet);
2903   silc_buffer_free(idp);
2904
2905  out:
2906   silc_server_command_free(cmd);
2907 }
2908
2909 /* Server side of command PING. This just replies to the ping. */
2910
2911 SILC_SERVER_CMD_FUNC(ping)
2912 {
2913   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2914   SilcServer server = cmd->server;
2915   SilcServerID *id;
2916   uint32 len;
2917   unsigned char *tmp;
2918
2919   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2920
2921   /* Get Server ID */
2922   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2923   if (!tmp) {
2924     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2925                                           SILC_STATUS_ERR_NO_SERVER_ID);
2926     goto out;
2927   }
2928   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2929   if (!id)
2930     goto out;
2931
2932   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2933     /* Send our reply */
2934     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2935                                           SILC_STATUS_OK);
2936   } else {
2937     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2938                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2939     goto out;
2940   }
2941
2942   silc_free(id);
2943
2944  out:
2945   silc_server_command_free(cmd);
2946 }
2947
2948 /* Internal routine to join channel. The channel sent to this function
2949    has been either created or resolved from ID lists. This joins the sent
2950    client to the channel. */
2951
2952 static void silc_server_command_join_channel(SilcServer server, 
2953                                              SilcServerCommandContext cmd,
2954                                              SilcChannelEntry channel,
2955                                              SilcClientID *client_id,
2956                                              bool created,
2957                                              bool create_key,
2958                                              uint32 umode)
2959 {
2960   SilcSocketConnection sock = cmd->sock;
2961   unsigned char *tmp;
2962   uint32 tmp_len, user_count;
2963   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2964   SilcClientEntry client;
2965   SilcChannelClientEntry chl;
2966   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2967   uint16 ident = silc_command_get_ident(cmd->payload);
2968   char check[512], check2[512];
2969
2970   SILC_LOG_DEBUG(("Start"));
2971
2972   if (!channel)
2973     return;
2974
2975   /* Get the client entry */
2976   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2977     client = (SilcClientEntry)sock->user_data;
2978   } else {
2979     client = silc_server_get_client_resolve(server, client_id);
2980     if (!client) {
2981       if (cmd->pending)
2982         goto out;
2983
2984       /* The client info is being resolved. Reprocess this packet after
2985          receiving the reply to the query. */
2986       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2987                                   server->cmd_ident, NULL,
2988                                   silc_server_command_join, 
2989                                   silc_server_command_dup(cmd));
2990       cmd->pending = TRUE;
2991       return;
2992     }
2993
2994     cmd->pending = FALSE;
2995   }
2996
2997   /*
2998    * Check channel modes
2999    */
3000
3001   memset(check, 0, sizeof(check));
3002   memset(check2, 0, sizeof(check2));
3003   strncat(check, client->nickname, strlen(client->nickname));
3004   strncat(check, "!", 1);
3005   strncat(check, client->username, strlen(client->username));
3006   if (!strchr(client->username, '@')) {
3007     strncat(check, "@", 1);
3008     strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3009   }
3010
3011   strncat(check2, client->nickname, strlen(client->nickname));
3012   if (!strchr(client->nickname, '@')) {
3013     strncat(check2, "@", 1);
3014     strncat(check2, server->server_name, strlen(server->server_name));
3015   }
3016   strncat(check2, "!", 1);
3017   strncat(check2, client->username, strlen(client->username));
3018   if (!strchr(client->username, '@')) {
3019     strncat(check2, "@", 1);
3020     strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3021   }
3022
3023   /* Check invite list if channel is invite-only channel */
3024   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3025     if (!channel->invite_list ||
3026         (!silc_string_match(channel->invite_list, check) &&
3027          !silc_string_match(channel->invite_list, check2))) {
3028       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3029                                             SILC_STATUS_ERR_NOT_INVITED);
3030       goto out;
3031     }
3032   }
3033
3034   /* Check ban list if it exists. If the client's nickname, server,
3035      username and/or hostname is in the ban list the access to the
3036      channel is denied. */
3037   if (channel->ban_list) {
3038     if (silc_string_match(channel->ban_list, check) ||
3039         silc_string_match(channel->ban_list, check2)) {
3040       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3041                               SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3042       goto out;
3043     }
3044   }
3045
3046   /* Get passphrase */
3047   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3048   if (tmp) {
3049     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3050     memcpy(passphrase, tmp, tmp_len);
3051   }
3052   
3053   /* Check the channel passphrase if set. */
3054   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3055     if (!passphrase || memcmp(channel->passphrase, passphrase,
3056                               strlen(channel->passphrase))) {
3057       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3058                                             SILC_STATUS_ERR_BAD_PASSWORD);
3059       goto out;
3060     }
3061   }
3062
3063   /* Check user count limit if set. */
3064   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3065     if (silc_hash_table_count(channel->user_list) + 1 > 
3066         channel->user_limit) {
3067       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3068                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
3069       goto out;
3070     }
3071   }
3072
3073   /*
3074    * Client is allowed to join to the channel. Make it happen.
3075    */
3076
3077   /* Check whether the client already is on the channel */
3078   if (silc_server_client_on_channel(client, channel)) {
3079     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3080                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
3081     goto out;
3082   }
3083
3084   /* Generate new channel key as protocol dictates */
3085   if (create_key) {
3086     if (!silc_server_create_channel_key(server, channel, 0))
3087       goto out;
3088
3089     /* Send the channel key. This is broadcasted to the channel but is not
3090        sent to the client who is joining to the channel. */
3091     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3092       silc_server_send_channel_key(server, NULL, channel, 
3093                                    server->server_type == SILC_ROUTER ? 
3094                                    FALSE : !server->standalone);
3095   }
3096
3097   /* Join the client to the channel by adding it to channel's user list.
3098      Add also the channel to client entry's channels list for fast cross-
3099      referencing. */
3100   chl = silc_calloc(1, sizeof(*chl));
3101   chl->mode = umode;
3102   chl->client = client;
3103   chl->channel = channel;
3104   silc_hash_table_add(channel->user_list, client, chl);
3105   silc_hash_table_add(client->channels, channel, chl);
3106
3107   /* Get users on the channel */
3108   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3109                                    &user_count);
3110
3111   /* Encode Client ID Payload of the original client who wants to join */
3112   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3113
3114   /* Encode command reply packet */
3115   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3116   SILC_PUT32_MSB(channel->mode, mode);
3117   SILC_PUT32_MSB(created, tmp2);
3118   SILC_PUT32_MSB(user_count, tmp3);
3119
3120   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3121     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3122     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
3123                                            strlen(channel->channel_key->
3124                                                   cipher->name),
3125                                            channel->channel_key->cipher->name,
3126                                            channel->key_len / 8, channel->key);
3127     silc_free(tmp);
3128   }
3129
3130   reply = 
3131     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3132                                          SILC_STATUS_OK, ident, 13,
3133                                          2, channel->channel_name,
3134                                          strlen(channel->channel_name),
3135                                          3, chidp->data, chidp->len,
3136                                          4, clidp->data, clidp->len,
3137                                          5, mode, 4,
3138                                          6, tmp2, 4,
3139                                          7, keyp ? keyp->data : NULL, 
3140                                          keyp ? keyp->len : 0,
3141                                          8, channel->ban_list, 
3142                                          channel->ban_list ?
3143                                          strlen(channel->ban_list) : 0,
3144                                          9, channel->invite_list,
3145                                          channel->invite_list ?
3146                                          strlen(channel->invite_list) : 0,
3147                                          10, channel->topic,
3148                                          channel->topic ?
3149                                          strlen(channel->topic) : 0,
3150                                          11, silc_hmac_get_name(channel->hmac),
3151                                          strlen(silc_hmac_get_name(channel->
3152                                                                    hmac)),
3153                                          12, tmp3, 4,
3154                                          13, user_list->data, user_list->len,
3155                                          14, mode_list->data, 
3156                                          mode_list->len);
3157
3158   /* Send command reply */
3159   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3160                           reply->data, reply->len, FALSE);
3161
3162   /* Send JOIN notify to locally connected clients on the channel. If
3163      we are normal server then router will send or have sent JOIN notify
3164      already. However since we've added the client already to our channel
3165      we'll ignore it (in packet_receive.c) so we must send it here. If
3166      we are router then this will send it to local clients and local
3167      servers. */
3168   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3169                                      SILC_NOTIFY_TYPE_JOIN, 2,
3170                                      clidp->data, clidp->len,
3171                                      chidp->data, chidp->len);
3172
3173   if (!cmd->pending) {
3174     /* Send JOIN notify packet to our primary router */
3175     if (!server->standalone)
3176       silc_server_send_notify_join(server, server->router->connection,
3177                                    server->server_type == SILC_ROUTER ?
3178                                    TRUE : FALSE, channel, client->id);
3179
3180     if (keyp)
3181       /* Distribute the channel key to all backup routers. */
3182       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3183                               keyp->data, keyp->len, FALSE, TRUE);
3184   }
3185
3186   silc_buffer_free(reply);
3187   silc_buffer_free(clidp);
3188   silc_buffer_free(chidp);
3189   silc_buffer_free(keyp);
3190   silc_buffer_free(user_list);
3191   silc_buffer_free(mode_list);
3192
3193  out:
3194   silc_free(passphrase);
3195 }
3196
3197 /* Server side of command JOIN. Joins client into requested channel. If 
3198    the channel does not exist it will be created. */
3199
3200 SILC_SERVER_CMD_FUNC(join)
3201 {
3202   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3203   SilcServer server = cmd->server;
3204   uint32 tmp_len;
3205   char *tmp, *channel_name = NULL, *cipher, *hmac;
3206   SilcChannelEntry channel;
3207   uint32 umode = 0;
3208   bool created = FALSE, create_key = TRUE;
3209   SilcClientID *client_id;
3210
3211   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3212
3213   /* Get channel name */
3214   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3215   if (!tmp) {
3216     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3217                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3218     goto out;
3219   }
3220   channel_name = tmp;
3221
3222   if (strlen(channel_name) > 256)
3223     channel_name[255] = '\0';
3224
3225   if (silc_server_command_bad_chars(channel_name) == TRUE) {
3226     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3227                                           SILC_STATUS_ERR_BAD_CHANNEL);
3228     goto out;
3229   }
3230
3231   /* Get Client ID of the client who is joining to the channel */
3232   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3233   if (!tmp) {
3234     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3235                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3236     goto out;
3237   }
3238   client_id = silc_id_payload_parse_id(tmp, tmp_len);
3239   if (!client_id) {
3240     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3241                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3242     goto out;
3243   }
3244
3245   /* Get cipher and hmac name */
3246   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3247   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3248
3249   /* See if the channel exists */
3250   channel = silc_idlist_find_channel_by_name(server->local_list, 
3251                                              channel_name, NULL);
3252
3253   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3254     /* If this is coming from client the Client ID in the command packet must
3255        be same as the client's ID. */
3256     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3257       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3258       if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3259         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3260                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3261         goto out;
3262       }
3263     }
3264
3265     if (!channel || !channel->id) {
3266       /* Channel not found */
3267
3268       /* If we are standalone server we don't have a router, we just create 
3269          the channel by ourselves. */
3270       if (server->standalone) {
3271         channel = silc_server_create_new_channel(server, server->id, cipher, 
3272                                                  hmac, channel_name, TRUE);
3273         if (!channel) {
3274           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3275                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3276           goto out;
3277         }
3278         
3279         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3280         created = TRUE;
3281         create_key = FALSE;
3282         
3283       } else {
3284
3285         /* The channel does not exist on our server. If we are normal server 
3286            we will send JOIN command to our router which will handle the
3287            joining procedure (either creates the channel if it doesn't exist 
3288            or joins the client to it). */
3289         if (server->server_type != SILC_ROUTER) {
3290           SilcBuffer tmpbuf;
3291           uint16 old_ident;
3292
3293           /* If this is pending command callback then we've resolved
3294              it and it didn't work, return since we've notified the
3295              client already in the command reply callback. */
3296           if (cmd->pending)
3297             goto out;
3298           
3299           old_ident = silc_command_get_ident(cmd->payload);
3300           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3301           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3302           
3303           /* Send JOIN command to our router */
3304           silc_server_packet_send(server, (SilcSocketConnection)
3305                                   server->router->connection,
3306                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3307                                   tmpbuf->data, tmpbuf->len, TRUE);
3308           
3309           /* Reprocess this packet after received reply from router */
3310           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3311                                       silc_command_get_ident(cmd->payload),
3312                                       silc_server_command_destructor,
3313                                       silc_server_command_join,
3314                                       silc_server_command_dup(cmd));
3315           cmd->pending = TRUE;
3316           return;
3317         }
3318         
3319         /* We are router and the channel does not seem exist so we will check
3320            our global list as well for the channel. */
3321         channel = silc_idlist_find_channel_by_name(server->global_list, 
3322                                                    channel_name, NULL);
3323         if (!channel) {
3324           /* Channel really does not exist, create it */
3325           channel = silc_server_create_new_channel(server, server->id, cipher, 
3326                                                    hmac, channel_name, TRUE);
3327           if (!channel) {
3328             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3329                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3330             goto out;
3331           }
3332
3333           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3334           created = TRUE;
3335           create_key = FALSE;
3336         }
3337       }
3338     }
3339   } else {
3340     if (!channel) {
3341       /* Channel not found */
3342
3343       /* If the command came from router and we are normal server then
3344          something went wrong with the joining as the channel was not found.
3345          We can't do anything else but ignore this. */
3346       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3347           server->server_type != SILC_ROUTER)
3348         goto out;
3349       
3350       /* We are router and the channel does not seem exist so we will check
3351          our global list as well for the channel. */
3352       channel = silc_idlist_find_channel_by_name(server->global_list, 
3353                                                  channel_name, NULL);
3354       if (!channel) {
3355         /* Channel really does not exist, create it */
3356         channel = silc_server_create_new_channel(server, server->id, cipher, 
3357                                                  hmac, channel_name, TRUE);
3358         if (!channel) {
3359           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3360                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3361           goto out;
3362         }
3363
3364         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3365         created = TRUE;
3366         create_key = FALSE;
3367       }
3368     }
3369   }
3370
3371   /* Check whether the channel was created by our router */
3372   if (cmd->pending && context2) {
3373     SilcServerCommandReplyContext reply = 
3374       (SilcServerCommandReplyContext)context2;
3375     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3376       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3377       SILC_GET32_MSB(created, tmp);
3378       create_key = FALSE;       /* Router returned the key already */
3379     }
3380   }
3381
3382   /* If the channel does not have global users and is also empty the client
3383      will be the channel founder and operator. */
3384   if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3385     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3386
3387   /* Join to the channel */
3388   silc_server_command_join_channel(server, cmd, channel, client_id,
3389                                    created, create_key, umode);
3390
3391   silc_free(client_id);
3392
3393  out:
3394   silc_server_command_free(cmd);
3395 }
3396
3397 /* Server side of command MOTD. Sends server's current "message of the
3398    day" to the client. */
3399
3400 SILC_SERVER_CMD_FUNC(motd)
3401 {
3402   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3403   SilcServer server = cmd->server;
3404   SilcBuffer packet, idp;
3405   char *motd, *dest_server;
3406   uint32 motd_len;
3407   uint16 ident = silc_command_get_ident(cmd->payload);
3408   
3409   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3410
3411   /* Get server name */
3412   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3413   if (!dest_server) {
3414     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3415                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3416     goto out;
3417   }
3418
3419   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3420     /* Send our MOTD */
3421
3422     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3423
3424     if (server->config && server->config->motd && 
3425         server->config->motd->motd_file) {
3426       /* Send motd */
3427       motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3428       if (!motd)
3429         goto out;
3430       
3431       motd[motd_len] = 0;
3432       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3433                                                     SILC_STATUS_OK, ident, 2,
3434                                                     2, idp, idp->len,
3435                                                     3, motd, motd_len);
3436       goto out;
3437     } else {
3438       /* No motd */
3439       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3440                                                     SILC_STATUS_OK, ident, 1,
3441                                                     2, idp, idp->len);
3442     }
3443
3444     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3445                             packet->data, packet->len, FALSE);
3446     silc_buffer_free(packet);
3447     silc_buffer_free(idp);
3448   } else {
3449     SilcServerEntry entry;
3450
3451     /* Check whether we have this server cached */
3452     entry = silc_idlist_find_server_by_name(server->global_list,
3453                                             dest_server, TRUE, NULL);
3454     if (!entry) {
3455       entry = silc_idlist_find_server_by_name(server->local_list,
3456                                               dest_server, TRUE, NULL);
3457     }
3458
3459     if (server->server_type != SILC_SERVER && !cmd->pending && 
3460         entry && !entry->motd) {
3461       /* Send to the server */
3462       SilcBuffer tmpbuf;
3463       uint16 old_ident;
3464
3465       old_ident = silc_command_get_ident(cmd->payload);
3466       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3467       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3468
3469       silc_server_packet_send(server, entry->connection,
3470                               SILC_PACKET_COMMAND, cmd->packet->flags,
3471                               tmpbuf->data, tmpbuf->len, TRUE);
3472
3473       /* Reprocess this packet after received reply from router */
3474       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3475                                   silc_command_get_ident(cmd->payload),
3476                                   silc_server_command_destructor,
3477                                   silc_server_command_motd,
3478                                   silc_server_command_dup(cmd));
3479       cmd->pending = TRUE;
3480       silc_command_set_ident(cmd->payload, old_ident);
3481       silc_buffer_free(tmpbuf);
3482       return;
3483     }
3484
3485     if (!entry && !cmd->pending && !server->standalone) {
3486       /* Send to the primary router */
3487       SilcBuffer tmpbuf;
3488       uint16 old_ident;
3489
3490       old_ident = silc_command_get_ident(cmd->payload);
3491       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3492       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3493
3494       silc_server_packet_send(server, server->router->connection,
3495                               SILC_PACKET_COMMAND, cmd->packet->flags,
3496                               tmpbuf->data, tmpbuf->len, TRUE);
3497
3498       /* Reprocess this packet after received reply from router */
3499       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3500                                   silc_command_get_ident(cmd->payload),
3501                                   silc_server_command_destructor,
3502                                   silc_server_command_motd,
3503                                   silc_server_command_dup(cmd));
3504       cmd->pending = TRUE;
3505       silc_command_set_ident(cmd->payload, old_ident);
3506       silc_buffer_free(tmpbuf);
3507       return;
3508     }
3509
3510     if (!entry) {
3511       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3512                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3513       goto out;
3514     }
3515
3516     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3517
3518     if (entry->motd)
3519       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3520                                                     SILC_STATUS_OK, ident, 2,
3521                                                     2, idp, idp->len,
3522                                                     3, entry->motd,
3523                                                     strlen(entry->motd));
3524     else
3525       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3526                                                     SILC_STATUS_OK, ident, 1,
3527                                                     2, idp, idp->len);
3528
3529     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3530                             packet->data, packet->len, FALSE);
3531     silc_buffer_free(packet);
3532     silc_buffer_free(idp);
3533   }
3534
3535  out:
3536   silc_server_command_free(cmd);
3537 }
3538
3539 /* Server side of command UMODE. Client can use this command to set/unset
3540    user mode. Client actually cannot set itself to be as server/router
3541    operator so this can be used only to unset the modes. */
3542
3543 SILC_SERVER_CMD_FUNC(umode)
3544 {
3545   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3546   SilcServer server = cmd->server;
3547   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3548   SilcBuffer packet;
3549   unsigned char *tmp_mask;
3550   uint32 mask;
3551   uint16 ident = silc_command_get_ident(cmd->payload);
3552
3553   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3554     goto out;
3555
3556   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3557
3558   /* Get the client's mode mask */
3559   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3560   if (!tmp_mask) {
3561     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3562                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3563     goto out;
3564   }
3565   SILC_GET32_MSB(mask, tmp_mask);
3566
3567   /* 
3568    * Change the mode 
3569    */
3570
3571   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3572     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3573       /* Cannot operator mode */
3574       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3575                                             SILC_STATUS_ERR_PERM_DENIED);
3576       goto out;
3577     }
3578   } else {
3579     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3580       /* Remove the server operator rights */
3581       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3582   }
3583
3584   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3585     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3586       /* Cannot operator mode */
3587       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3588                                             SILC_STATUS_ERR_PERM_DENIED);
3589       goto out;
3590     }
3591   } else {
3592     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3593       /* Remove the router operator rights */
3594       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3595   }
3596
3597   if (mask & SILC_UMODE_GONE) {
3598     client->mode |= SILC_UMODE_GONE;
3599   } else {
3600     if (client->mode & SILC_UMODE_GONE)
3601       /* Remove the gone status */
3602       client->mode &= ~SILC_UMODE_GONE;
3603   }
3604
3605   /* Send UMODE change to primary router */
3606   if (!server->standalone)
3607     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3608                                   client->id, client->mode);
3609
3610   /* Send command reply to sender */
3611   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3612                                                 SILC_STATUS_OK, ident, 1,
3613                                                 2, tmp_mask, 4);
3614   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3615                           packet->data, packet->len, FALSE);
3616   silc_buffer_free(packet);
3617
3618  out:
3619   silc_server_command_free(cmd);
3620 }
3621
3622 /* Checks that client has rights to add or remove channel modes. If any
3623    of the checks fails FALSE is returned. */
3624
3625 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3626                                    SilcChannelClientEntry client,
3627                                    uint32 mode)
3628 {
3629   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3630   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3631
3632   /* Check whether has rights to change anything */
3633   if (!is_op && !is_fo)
3634     return FALSE;
3635
3636   /* Check whether has rights to change everything */
3637   if (is_op && is_fo)
3638     return TRUE;
3639
3640   /* We know that client is channel operator, check that they are not
3641      changing anything that requires channel founder rights. Rest of the
3642      modes are available automatically for channel operator. */
3643
3644   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3645     if (is_op && !is_fo)
3646       return FALSE;
3647   } else {
3648     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3649       if (is_op && !is_fo)
3650         return FALSE;
3651     }
3652   }
3653   
3654   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3655     if (is_op && !is_fo)
3656       return FALSE;
3657   } else {
3658     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3659       if (is_op && !is_fo)
3660         return FALSE;
3661     }
3662   }
3663
3664   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3665     if (is_op && !is_fo)
3666       return FALSE;
3667   } else {
3668     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3669       if (is_op && !is_fo)
3670         return FALSE;
3671     }
3672   }
3673   
3674   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3675     if (is_op && !is_fo)
3676       return FALSE;
3677   } else {
3678     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3679       if (is_op && !is_fo)
3680         return FALSE;
3681     }
3682   }
3683   
3684   return TRUE;
3685 }
3686
3687 /* Server side command of CMODE. Changes channel mode */
3688
3689 SILC_SERVER_CMD_FUNC(cmode)
3690 {
3691   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3692   SilcServer server = cmd->server;
3693   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3694   SilcIDListData idata = (SilcIDListData)client;
3695   SilcChannelID *channel_id;
3696   SilcChannelEntry channel;
3697   SilcChannelClientEntry chl;
3698   SilcBuffer packet, cidp;
3699   unsigned char *tmp, *tmp_id, *tmp_mask;
3700   char *cipher = NULL, *hmac = NULL;
3701   uint32 mode_mask, tmp_len, tmp_len2;
3702   uint16 ident = silc_command_get_ident(cmd->payload);
3703
3704   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3705
3706   /* Get Channel ID */
3707   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3708   if (!tmp_id) {
3709     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3710                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3711     goto out;
3712   }
3713   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3714   if (!channel_id) {
3715     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3716                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3717     goto out;
3718   }
3719
3720   /* Get the channel mode mask */
3721   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3722   if (!tmp_mask) {
3723     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3724                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3725     goto out;
3726   }
3727   SILC_GET32_MSB(mode_mask, tmp_mask);
3728
3729   /* Get channel entry */
3730   channel = silc_idlist_find_channel_by_id(server->local_list, 
3731                                            channel_id, NULL);
3732   if (!channel) {
3733     channel = silc_idlist_find_channel_by_id(server->global_list, 
3734                                              channel_id, NULL);
3735     if (!channel) {
3736       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3737                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3738       goto out;
3739     }
3740   }
3741
3742   /* Check whether this client is on the channel */
3743   if (!silc_server_client_on_channel(client, channel)) {
3744     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3745                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3746     goto out;
3747   }
3748
3749   /* Get entry to the channel user list */
3750   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3751
3752   /* Check that client has rights to change any requested channel modes */
3753   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3754     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3755                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3756     goto out;
3757   }
3758
3759   /*
3760    * Check the modes. Modes that requires nothing special operation are
3761    * not checked here.
3762    */
3763
3764   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3765     /* Channel uses private keys to protect traffic. Client(s) has set the
3766        key locally they want to use, server does not know that key. */
3767     /* Nothing interesting to do here */
3768   } else {
3769     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3770       /* The mode is removed and we need to generate and distribute
3771          new channel key. Clients are not using private channel keys
3772          anymore after this. */
3773
3774       /* Re-generate channel key */
3775       if (!silc_server_create_channel_key(server, channel, 0))
3776         goto out;
3777       
3778       /* Send the channel key. This sends it to our local clients and if
3779          we are normal server to our router as well. */
3780       silc_server_send_channel_key(server, NULL, channel, 
3781                                    server->server_type == SILC_ROUTER ? 
3782                                    FALSE : !server->standalone);
3783
3784       cipher = channel->channel_key->cipher->name;
3785       hmac = (char *)silc_hmac_get_name(channel->hmac);
3786     }
3787   }
3788   
3789   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3790     /* User limit is set on channel */
3791     uint32 user_limit;
3792       
3793     /* Get user limit */
3794     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3795     if (!tmp) {
3796       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3797         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3798                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3799         goto out;
3800       }
3801     } else {
3802       SILC_GET32_MSB(user_limit, tmp);
3803       channel->user_limit = user_limit;
3804     }
3805   } else {
3806     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3807       /* User limit mode is unset. Remove user limit */
3808       channel->user_limit = 0;
3809   }
3810
3811   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3812     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3813       /* Passphrase has been set to channel */
3814       
3815       /* Get the passphrase */
3816       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3817       if (!tmp) {
3818         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3819                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3820         goto out;
3821       }
3822
3823       /* Save the passphrase */
3824       channel->passphrase = strdup(tmp);
3825     }
3826   } else {
3827     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3828       /* Passphrase mode is unset. remove the passphrase */
3829       if (channel->passphrase) {
3830         silc_free(channel->passphrase);
3831         channel->passphrase = NULL;
3832       }
3833     }
3834   }
3835
3836   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3837     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3838       /* Cipher to use protect the traffic */
3839
3840       /* Get cipher */
3841       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3842       if (!cipher) {
3843         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3844                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3845         goto out;
3846       }
3847
3848       /* Delete old cipher and allocate the new one */
3849       silc_cipher_free(channel->channel_key);
3850       if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3851         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3852                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3853         goto out;
3854       }
3855
3856       /* Re-generate channel key */
3857       if (!silc_server_create_channel_key(server, channel, 0))
3858         goto out;
3859     
3860       /* Send the channel key. This sends it to our local clients and if
3861          we are normal server to our router as well. */
3862       silc_server_send_channel_key(server, NULL, channel, 
3863                                    server->server_type == SILC_ROUTER ? 
3864                                    FALSE : !server->standalone);
3865     }
3866   } else {
3867     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3868       /* Cipher mode is unset. Remove the cipher and revert back to 
3869          default cipher */
3870       cipher = channel->cipher;
3871
3872       /* Delete old cipher and allocate default one */
3873       silc_cipher_free(channel->channel_key);
3874       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, 
3875                              &channel->channel_key)) {
3876         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3877                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3878         goto out;
3879       }
3880
3881       /* Re-generate channel key */
3882       if (!silc_server_create_channel_key(server, channel, 0))
3883         goto out;
3884       
3885       /* Send the channel key. This sends it to our local clients and if
3886          we are normal server to our router as well. */
3887       silc_server_send_channel_key(server, NULL, channel, 
3888                                    server->server_type == SILC_ROUTER ? 
3889                                    FALSE : !server->standalone);
3890     }
3891   }
3892
3893   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3894     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3895       /* HMAC to use protect the traffic */
3896       unsigned char hash[32];
3897
3898       /* Get hmac */
3899       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3900       if (!hmac) {
3901         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3902                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3903         goto out;
3904       }
3905
3906       /* Delete old hmac and allocate the new one */
3907       silc_hmac_free(channel->hmac);
3908       if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3909         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3910                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3911         goto out;
3912       }
3913
3914       /* Set the HMAC key out of current channel key. The client must do
3915          this locally. */
3916       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
3917                      channel->key_len / 8, 
3918                      hash);
3919       silc_hmac_set_key(channel->hmac, hash, 
3920                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3921       memset(hash, 0, sizeof(hash));
3922     }
3923   } else {
3924     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3925       /* Hmac mode is unset. Remove the hmac and revert back to 
3926          default hmac */
3927       unsigned char hash[32];
3928       hmac = channel->hmac_name;
3929
3930       /* Delete old hmac and allocate default one */
3931       silc_hmac_free(channel->hmac);
3932       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, 
3933                            &channel->hmac)) {
3934         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3935                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3936         goto out;
3937       }
3938
3939       /* Set the HMAC key out of current channel key. The client must do
3940          this locally. */
3941       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
3942                      channel->key_len / 8, 
3943                      hash);
3944       silc_hmac_set_key(channel->hmac, hash, 
3945                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3946       memset(hash, 0, sizeof(hash));
3947     }
3948   }
3949
3950   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3951     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3952       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3953         /* Set the founder authentication */
3954         SilcAuthPayload auth;
3955         
3956         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3957         if (!tmp) {
3958           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3959                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3960           goto out;
3961         }
3962
3963         auth = silc_auth_payload_parse(tmp, tmp_len);
3964         if (!auth) {
3965           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3966                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3967           goto out;
3968         }
3969
3970         /* Save the public key */
3971         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3972         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3973         silc_free(tmp);
3974         
3975         channel->founder_method = silc_auth_get_method(auth);
3976
3977         if (channel->founder_method == SILC_AUTH_PASSWORD) {
3978           tmp = silc_auth_get_data(auth, &tmp_len);
3979           channel->founder_passwd = 
3980             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3981           memcpy(channel->founder_passwd, tmp, tmp_len);
3982           channel->founder_passwd_len = tmp_len;
3983         } else {
3984           /* Verify the payload before setting the mode */
3985           if (!silc_auth_verify(auth, channel->founder_method, 
3986                                 channel->founder_key, 0, idata->hash,
3987                                 client->id, SILC_ID_CLIENT)) {
3988             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3989                                                   SILC_STATUS_ERR_AUTH_FAILED);
3990             goto out;
3991           }
3992         }
3993
3994         silc_auth_payload_free(auth);
3995       }
3996     }
3997   } else {
3998     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3999       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4000         if (channel->founder_key)
4001           silc_pkcs_public_key_free(channel->founder_key);
4002         if (channel->founder_passwd) {
4003           silc_free(channel->founder_passwd);
4004           channel->founder_passwd = NULL;
4005         }
4006       }
4007     }
4008   }
4009
4010   /* Finally, set the mode */
4011   channel->mode = mode_mask;
4012
4013   /* Send CMODE_CHANGE notify */
4014   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4015   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4016                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
4017                                      cidp->data, cidp->len, 
4018                                      tmp_mask, 4,
4019                                      cipher, cipher ? strlen(cipher) : 0,
4020                                      hmac, hmac ? strlen(hmac) : 0);
4021
4022   /* Set CMODE notify type to network */
4023   if (!server->standalone)
4024     silc_server_send_notify_cmode(server, server->router->connection,
4025                                   server->server_type == SILC_ROUTER ? 
4026                                   TRUE : FALSE, channel,
4027                                   mode_mask, client->id, SILC_ID_CLIENT,
4028                                   cipher, hmac);
4029
4030   /* Send command reply to sender */
4031   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4032                                                 SILC_STATUS_OK, ident, 2,
4033                                                 2, tmp_id, tmp_len2,
4034                                                 3, tmp_mask, 4);
4035   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4036                           packet->data, packet->len, FALSE);
4037     
4038   silc_buffer_free(packet);
4039   silc_free(channel_id);
4040   silc_free(cidp);
4041
4042  out:
4043   silc_server_command_free(cmd);
4044 }
4045
4046 /* Server side of CUMODE command. Changes client's mode on a channel. */
4047
4048 SILC_SERVER_CMD_FUNC(cumode)
4049 {
4050   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4051   SilcServer server = cmd->server;
4052   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4053   SilcIDListData idata = (SilcIDListData)client;
4054   SilcChannelID *channel_id;
4055   SilcClientID *client_id;
4056   SilcChannelEntry channel;
4057   SilcClientEntry target_client;
4058   SilcChannelClientEntry chl;
4059   SilcBuffer packet, idp;
4060   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4061   uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4062   int notify = FALSE;
4063   uint16 ident = silc_command_get_ident(cmd->payload);
4064
4065   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4066
4067   /* Get Channel ID */
4068   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4069   if (!tmp_ch_id) {
4070     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4071                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4072     goto out;
4073   }
4074   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4075   if (!channel_id) {
4076     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4077                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4078     goto out;
4079   }
4080
4081   /* Get channel entry */
4082   channel = silc_idlist_find_channel_by_id(server->local_list, 
4083                                            channel_id, NULL);
4084   if (!channel) {
4085     channel = silc_idlist_find_channel_by_id(server->global_list, 
4086                                              channel_id, NULL);
4087     if (!channel) {
4088       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4089                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4090       goto out;
4091     }
4092   }
4093
4094   /* Check whether sender is on the channel */
4095   if (!silc_server_client_on_channel(client, channel)) {
4096     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4097                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4098     goto out;
4099   }
4100
4101   /* Check that client has rights to change other's rights */
4102   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4103   sender_mask = chl->mode;
4104   
4105   /* Get the target client's channel mode mask */
4106   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4107   if (!tmp_mask) {
4108     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4109                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4110     goto out;
4111   }
4112   SILC_GET32_MSB(target_mask, tmp_mask);
4113
4114   /* Get target Client ID */
4115   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4116   if (!tmp_id) {
4117     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4118                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4119     goto out;
4120   }
4121   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4122   if (!client_id) {
4123     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4124                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4125     goto out;
4126   }
4127
4128   /* Get target client's entry */
4129   target_client = silc_idlist_find_client_by_id(server->local_list, 
4130                                                 client_id, TRUE, NULL);
4131   if (!target_client) {
4132     target_client = silc_idlist_find_client_by_id(server->global_list, 
4133                                                   client_id, TRUE, NULL);
4134   }
4135
4136   if (target_client != client &&
4137       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4138       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4139     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4140                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4141     goto out;
4142   }
4143
4144   /* Check whether target client is on the channel */
4145   if (target_client != client) {
4146     if (!silc_server_client_on_channel(target_client, channel)) {
4147       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4148                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4149       goto out;
4150     }
4151
4152     /* Get entry to the channel user list */
4153     silc_hash_table_find(channel->user_list, target_client, NULL, 
4154                          (void *)&chl);
4155   }
4156
4157   /* 
4158    * Change the mode 
4159    */
4160
4161   /* If the target client is founder, no one else can change their mode
4162      but themselves. */
4163   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4164     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4165                                           SILC_STATUS_ERR_NOT_YOU);
4166     goto out;
4167   }
4168
4169   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4170     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4171       /* The client tries to claim the founder rights. */
4172       unsigned char *tmp_auth;
4173       uint32 tmp_auth_len, auth_len;
4174       void *auth;
4175       
4176       if (target_client != client) {
4177         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4178                                               SILC_STATUS_ERR_NOT_YOU);
4179         goto out;
4180       }
4181
4182       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4183           !channel->founder_key) {
4184         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4185                                               SILC_STATUS_ERR_NOT_YOU);
4186         goto out;
4187       }
4188
4189       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4190       if (!tmp_auth) {
4191         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4192                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4193         goto out;
4194       }
4195       
4196       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4197               (void *)channel->founder_passwd : (void *)channel->founder_key);
4198       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4199                   channel->founder_passwd_len : 0);
4200       
4201       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4202                                  channel->founder_method, auth, auth_len,
4203                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4204         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4205                                               SILC_STATUS_ERR_AUTH_FAILED);
4206         goto out;
4207       }
4208       
4209       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4210       notify = TRUE;
4211     }
4212   } else {
4213     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4214       if (target_client == client) {
4215         /* Remove channel founder rights from itself */
4216         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4217         notify = TRUE;
4218       } else {
4219         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4220                                               SILC_STATUS_ERR_NOT_YOU);
4221         goto out;
4222       }
4223     }
4224   }
4225
4226   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4227     /* Promote to operator */
4228     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4229       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4230           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4231         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4232                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4233         goto out;
4234       }
4235
4236       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4237       notify = TRUE;
4238     }
4239   } else {
4240     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4241       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4242           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4243         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4244                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4245         goto out;
4246       }
4247
4248       /* Demote to normal user */
4249       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4250       notify = TRUE;
4251     }
4252   }
4253
4254   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4255   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4256
4257   /* Send notify to channel, notify only if mode was actually changed. */
4258   if (notify) {
4259     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4260                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4261                                        idp->data, idp->len,
4262                                        tmp_mask, 4, 
4263                                        tmp_id, tmp_len);
4264
4265     /* Set CUMODE notify type to network */
4266     if (!server->standalone)
4267       silc_server_send_notify_cumode(server, server->router->connection,
4268                                      server->server_type == SILC_ROUTER ? 
4269                                      TRUE : FALSE, channel,
4270                                      target_mask, client->id, 
4271                                      SILC_ID_CLIENT,
4272                                      target_client->id);
4273   }
4274
4275   /* Send command reply to sender */
4276   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4277                                                 SILC_STATUS_OK, ident, 3,
4278                                                 2, tmp_mask, 4,
4279                                                 3, tmp_ch_id, tmp_ch_len,
4280                                                 4, tmp_id, tmp_len);
4281   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4282                           packet->data, packet->len, FALSE);
4283     
4284   silc_buffer_free(packet);
4285   silc_free(channel_id);
4286   silc_free(client_id);
4287   silc_buffer_free(idp);
4288
4289  out:
4290   silc_server_command_free(cmd);
4291 }
4292
4293 /* Server side of KICK command. Kicks client out of channel. */
4294
4295 SILC_SERVER_CMD_FUNC(kick)
4296 {
4297   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4298   SilcServer server = cmd->server;
4299   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4300   SilcClientEntry target_client;
4301   SilcChannelID *channel_id;
4302   SilcClientID *client_id;
4303   SilcChannelEntry channel;
4304   SilcChannelClientEntry chl;
4305   SilcBuffer idp;
4306   uint32 tmp_len;
4307   unsigned char *tmp, *comment;
4308
4309   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4310
4311   /* Get Channel ID */
4312   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4313   if (!tmp) {
4314     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4315                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4316     goto out;
4317   }
4318   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4319   if (!channel_id) {
4320     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4321                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4322     goto out;
4323   }
4324
4325   /* Get channel entry */
4326   channel = silc_idlist_find_channel_by_id(server->local_list, 
4327                                            channel_id, NULL);
4328   if (!channel) {
4329     channel = silc_idlist_find_channel_by_id(server->local_list, 
4330                                              channel_id, NULL);
4331     if (!channel) {
4332       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4333                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4334       goto out;
4335     }
4336   }
4337
4338   /* Check whether sender is on the channel */
4339   if (!silc_server_client_on_channel(client, channel)) {
4340     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4341                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4342     goto out;
4343   }
4344
4345   /* Check that the kicker is channel operator or channel founder */
4346   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4347   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4348     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4349                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4350     goto out;
4351   }
4352   
4353   /* Get target Client ID */
4354   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4355   if (!tmp) {
4356     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4357                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4358     goto out;
4359   }
4360   client_id = silc_id_payload_parse_id(tmp, tmp_len);
4361   if (!client_id) {
4362     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4363                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4364     goto out;
4365   }
4366
4367   /* Get target client's entry */
4368   target_client = silc_idlist_find_client_by_id(server->local_list, 
4369                                                 client_id, TRUE, NULL);
4370   if (!target_client) {
4371     target_client = silc_idlist_find_client_by_id(server->global_list, 
4372                                                   client_id, TRUE, NULL);
4373   }
4374
4375   /* Check that the target client is not channel founder. Channel founder
4376      cannot be kicked from the channel. */
4377   silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4378   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4379     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4380                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4381     goto out;
4382   }
4383   
4384   /* Check whether target client is on the channel */
4385   if (!silc_server_client_on_channel(target_client, channel)) {
4386     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4387                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4388     goto out;
4389   }
4390
4391   /* Get comment */
4392   tmp_len = 0;
4393   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4394   if (tmp_len > 128)
4395     comment = NULL;
4396
4397   /* Send command reply to sender */
4398   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4399                                         SILC_STATUS_OK);
4400
4401   /* Send KICKED notify to local clients on the channel */
4402   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4403   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4404                                      SILC_NOTIFY_TYPE_KICKED, 
4405                                      comment ? 2 : 1,
4406                                      idp->data, idp->len,
4407                                      comment, comment ? strlen(comment) : 0);
4408   silc_buffer_free(idp);
4409
4410   /* Remove the client from the channel. If the channel does not exist
4411      after removing the client then the client kicked itself off the channel
4412      and we don't have to send anything after that. */
4413   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4414                                            target_client, FALSE))
4415     goto out;
4416
4417   /* Send KICKED notify to primary route */
4418   if (!server->standalone)
4419     silc_server_send_notify_kicked(server, server->router->connection,
4420                                    server->server_type == SILC_ROUTER ?
4421                                    TRUE : FALSE, channel,
4422                                    target_client->id, comment);
4423
4424   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4425     /* Re-generate channel key */
4426     if (!silc_server_create_channel_key(server, channel, 0))
4427       goto out;
4428     
4429     /* Send the channel key to the channel. The key of course is not sent
4430        to the client who was kicked off the channel. */
4431     silc_server_send_channel_key(server, target_client->connection, channel, 
4432                                  server->server_type == SILC_ROUTER ? 
4433                                  FALSE : !server->standalone);
4434   }
4435
4436  out:
4437   silc_server_command_free(cmd);
4438 }
4439
4440 /* Server side of OPER command. Client uses this comand to obtain server
4441    operator privileges to this server/router. */
4442
4443 SILC_SERVER_CMD_FUNC(oper)
4444 {
4445   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4446   SilcServer server = cmd->server;
4447   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4448   unsigned char *username, *auth;
4449   uint32 tmp_len;
4450   SilcServerConfigSectionAdminConnection *admin;
4451   SilcIDListData idata = (SilcIDListData)client;
4452
4453   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4454
4455   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4456     goto out;
4457
4458   /* Get the username */
4459   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4460   if (!username) {
4461     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4462                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4463     goto out;
4464   }
4465
4466   /* Get the admin configuration */
4467   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4468                                         username, client->nickname);
4469   if (!admin) {
4470     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4471                                           username, client->nickname);
4472     if (!admin) {
4473       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4474                                             SILC_STATUS_ERR_AUTH_FAILED);
4475       goto out;
4476     }
4477   }
4478
4479   /* Get the authentication payload */
4480   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4481   if (!auth) {
4482     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4483                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4484     goto out;
4485   }
4486
4487   /* Verify the authentication data */
4488   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4489                              admin->auth_data, admin->auth_data_len,
4490                              idata->hash, client->id, SILC_ID_CLIENT)) {
4491     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4492                                           SILC_STATUS_ERR_AUTH_FAILED);
4493     goto out;
4494   }
4495
4496   /* Client is now server operator */
4497   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4498
4499   /* Send UMODE change to primary router */
4500   if (!server->standalone)
4501     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4502                                   client->id, client->mode);
4503
4504   /* Send reply to the sender */
4505   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4506                                         SILC_STATUS_OK);
4507
4508  out:
4509   silc_server_command_free(cmd);
4510 }
4511
4512 /* Server side of SILCOPER command. Client uses this comand to obtain router
4513    operator privileges to this router. */
4514
4515 SILC_SERVER_CMD_FUNC(silcoper)
4516 {
4517   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4518   SilcServer server = cmd->server;
4519   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4520   unsigned char *username, *auth;
4521   uint32 tmp_len;
4522   SilcServerConfigSectionAdminConnection *admin;
4523   SilcIDListData idata = (SilcIDListData)client;
4524
4525   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4526
4527   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4528     goto out;
4529
4530   if (server->server_type != SILC_ROUTER) {
4531     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4532                                           SILC_STATUS_ERR_AUTH_FAILED);
4533     goto out;
4534   }
4535
4536   /* Get the username */
4537   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4538   if (!username) {
4539     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4540                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4541     goto out;
4542   }
4543
4544   /* Get the admin configuration */
4545   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4546                                         username, client->nickname);
4547   if (!admin) {
4548     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4549                                           username, client->nickname);
4550     if (!admin) {
4551       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4552                                             SILC_STATUS_ERR_AUTH_FAILED);
4553       goto out;
4554     }
4555   }
4556
4557   /* Get the authentication payload */
4558   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4559   if (!auth) {
4560     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4561                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4562     goto out;
4563   }
4564
4565   /* Verify the authentication data */
4566   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4567                              admin->auth_data, admin->auth_data_len,
4568                              idata->hash, client->id, SILC_ID_CLIENT)) {
4569     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4570                                           SILC_STATUS_ERR_AUTH_FAILED);
4571     goto out;
4572   }
4573
4574   /* Client is now router operator */
4575   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4576
4577   /* Send UMODE change to primary router */
4578   if (!server->standalone)
4579     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4580                                   client->id, client->mode);
4581
4582   /* Send reply to the sender */
4583   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4584                                         SILC_STATUS_OK);
4585
4586  out:
4587   silc_server_command_free(cmd);
4588 }
4589
4590 /* Server side command of CONNECT. Connects us to the specified remote
4591    server or router. */
4592
4593 SILC_SERVER_CMD_FUNC(connect)
4594 {
4595   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4596   SilcServer server = cmd->server;
4597   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4598   unsigned char *tmp, *host;
4599   uint32 tmp_len;
4600   uint32 port = SILC_PORT;
4601
4602   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4603
4604   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4605     goto out;
4606
4607   /* Check whether client has the permissions. */
4608   if (client->mode == SILC_UMODE_NONE) {
4609     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4610                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4611     goto out;
4612   }
4613
4614   if (server->server_type == SILC_ROUTER && 
4615       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4616     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4617                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4618     goto out;
4619   }
4620
4621   /* Get the remote server */
4622   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4623   if (!host) {
4624     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4625                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4626     goto out;
4627   }
4628
4629   /* Get port */
4630   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4631   if (tmp)
4632     SILC_GET32_MSB(port, tmp);
4633
4634   /* Create the connection. It is done with timeout and is async. */
4635   silc_server_create_connection(server, host, port);
4636
4637   /* Send reply to the sender */
4638   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4639                                         SILC_STATUS_OK);
4640
4641  out:
4642   silc_server_command_free(cmd);
4643 }
4644
4645 /* Server side of command BAN. This is used to manage the ban list of the
4646    channel. To add clients and remove clients from the ban list. */
4647
4648 SILC_SERVER_CMD_FUNC(ban)
4649 {
4650   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4651   SilcServer server = cmd->server;
4652   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4653   SilcBuffer packet;
4654   SilcChannelEntry channel;
4655   SilcChannelClientEntry chl;
4656   SilcChannelID *channel_id = NULL;
4657   unsigned char *id, *add, *del;
4658   uint32 id_len, tmp_len;
4659   uint16 ident = silc_command_get_ident(cmd->payload);
4660
4661   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4662     goto out;
4663
4664   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4665
4666   /* Get Channel ID */
4667   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4668   if (id) {
4669     channel_id = silc_id_payload_parse_id(id, id_len);
4670     if (!channel_id) {
4671       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4672                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4673       goto out;
4674     }
4675   }
4676
4677   /* Get channel entry. The server must know about the channel since the
4678      client is expected to be on the channel. */
4679   channel = silc_idlist_find_channel_by_id(server->local_list, 
4680                                            channel_id, NULL);
4681   if (!channel) {
4682     channel = silc_idlist_find_channel_by_id(server->global_list, 
4683                                              channel_id, NULL);
4684     if (!channel) {
4685       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4686                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4687       goto out;
4688     }
4689   }
4690
4691   /* Check whether this client is on the channel */
4692   if (!silc_server_client_on_channel(client, channel)) {
4693     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4694                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4695     goto out;
4696   }
4697
4698   /* Get entry to the channel user list */
4699   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4700
4701   /* The client must be at least channel operator. */
4702   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4703     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4704                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4705     goto out;
4706   }
4707
4708   /* Get the new ban and add it to the ban list */
4709   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4710   if (add) {
4711     if (!channel->ban_list)
4712       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4713     else
4714       channel->ban_list = silc_realloc(channel->ban_list, 
4715                                        sizeof(*channel->ban_list) * 
4716                                        (tmp_len + 
4717                                         strlen(channel->ban_list) + 2));
4718     if (add[tmp_len - 1] == ',')
4719       add[tmp_len - 1] = '\0';
4720
4721     strncat(channel->ban_list, add, tmp_len);
4722     strncat(channel->ban_list, ",", 1);
4723   }
4724
4725   /* Get the ban to be removed and remove it from the list */
4726   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4727   if (del && channel->ban_list) {
4728     char *start, *end, *n;
4729
4730     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4731       silc_free(channel->ban_list);
4732       channel->ban_list = NULL;
4733     } else {
4734       start = strstr(channel->ban_list, del);
4735       if (start && strlen(start) >= tmp_len) {
4736         end = start + tmp_len;
4737         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4738         strncat(n, channel->ban_list, start - channel->ban_list);
4739         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4740                              end) - 1);
4741         silc_free(channel->ban_list);
4742         channel->ban_list = n;
4743       }
4744     }
4745   }
4746
4747   /* Send the BAN notify type to our primary router. */
4748   if (!server->standalone && (add || del))
4749     silc_server_send_notify_ban(server, server->router->connection,
4750                                 server->server_type == SILC_ROUTER ?
4751                                 TRUE : FALSE, channel, add, del);
4752
4753   /* Send the reply back to the client */
4754   if (channel->ban_list)
4755     packet = 
4756       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4757                                            SILC_STATUS_OK, ident, 2,
4758                                            2, id, id_len,
4759                                            3, channel->ban_list, 
4760                                            strlen(channel->ban_list) - 1);
4761   else
4762     packet = 
4763       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4764                                            SILC_STATUS_OK, ident, 1,
4765                                            2, id, id_len);
4766
4767   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4768                           packet->data, packet->len, FALSE);
4769     
4770   silc_buffer_free(packet);
4771
4772  out:
4773   silc_free(channel_id);
4774   silc_server_command_free(cmd);
4775 }
4776
4777 /* Server side command of CLOSE. Closes connection to a specified server. */
4778  
4779 SILC_SERVER_CMD_FUNC(close)
4780 {
4781   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4782   SilcServer server = cmd->server;
4783   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4784   SilcServerEntry server_entry;
4785   SilcSocketConnection sock;
4786   unsigned char *tmp;
4787   uint32 tmp_len;
4788   unsigned char *name;
4789   uint32 port = SILC_PORT;
4790
4791   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4792
4793   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4794     goto out;
4795
4796   /* Check whether client has the permissions. */
4797   if (client->mode == SILC_UMODE_NONE) {
4798     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4799                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4800     goto out;
4801   }
4802
4803   /* Get the remote server */
4804   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4805   if (!name) {
4806     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4807                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4808     goto out;
4809   }
4810
4811   /* Get port */
4812   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4813   if (tmp)
4814     SILC_GET32_MSB(port, tmp);
4815
4816   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4817                                                  name, port, FALSE, NULL);
4818   if (!server_entry)
4819     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4820                                                    name, port, FALSE, NULL);
4821   if (!server_entry) {
4822     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4823                                           SILC_STATUS_ERR_NO_SERVER_ID);
4824     goto out;
4825   }
4826
4827   /* Send reply to the sender */
4828   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4829                                         SILC_STATUS_OK);
4830
4831   /* Close the connection to the server */
4832   sock = (SilcSocketConnection)server_entry->connection;
4833
4834   /* If we shutdown primary router connection manually then don't trigger
4835      any reconnect or backup router connections, by setting the router
4836      to NULL here. */
4837   if (server->router == server_entry) {
4838     server->id_entry->router = NULL;
4839     server->router = NULL;
4840     server->standalone = TRUE;
4841   }
4842   silc_server_free_sock_user_data(server, sock);
4843   silc_server_close_connection(server, sock);
4844   
4845  out:
4846   silc_server_command_free(cmd);
4847 }
4848
4849 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4850    active connections. */
4851  
4852 SILC_SERVER_CMD_FUNC(shutdown)
4853 {
4854   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4855   SilcServer server = cmd->server;
4856   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4857
4858   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4859
4860   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4861     goto out;
4862
4863   /* Check whether client has the permission. */
4864   if (client->mode == SILC_UMODE_NONE) {
4865     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4866                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4867     goto out;
4868   }
4869
4870   /* Send reply to the sender */
4871   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4872                                         SILC_STATUS_OK);
4873
4874   /* Then, gracefully, or not, bring the server down. */
4875   silc_server_stop(server);
4876   exit(0);
4877
4878  out:
4879   silc_server_command_free(cmd);
4880 }
4881  
4882 /* Server side command of LEAVE. Removes client from a channel. */
4883
4884 SILC_SERVER_CMD_FUNC(leave)
4885 {
4886   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4887   SilcServer server = cmd->server;
4888   SilcSocketConnection sock = cmd->sock;
4889   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4890   SilcChannelID *id = NULL;
4891   SilcChannelEntry channel;
4892   uint32 len;
4893   unsigned char *tmp;
4894
4895   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4896
4897   /* Get Channel ID */
4898   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4899   if (!tmp) {
4900     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4901                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4902     goto out;
4903   }
4904   id = silc_id_payload_parse_id(tmp, len);
4905   if (!id) {
4906     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4907                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4908     goto out;
4909   }
4910
4911   /* Get channel entry */
4912   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4913   if (!channel) {
4914     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4915     if (!channel) {
4916       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4917                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4918       goto out;
4919     }
4920   }
4921
4922   /* Check whether this client is on the channel */
4923   if (!silc_server_client_on_channel(id_entry, channel)) {
4924     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4925                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4926     goto out;
4927   }
4928
4929   /* Notify routers that they should remove this client from their list
4930      of clients on the channel. Send LEAVE notify type. */
4931   if (!server->standalone)
4932     silc_server_send_notify_leave(server, server->router->connection,
4933                                   server->server_type == SILC_ROUTER ?
4934                                   TRUE : FALSE, channel, id_entry->id);
4935
4936   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4937                                         SILC_STATUS_OK);
4938
4939   /* Remove client from channel */
4940   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4941                                            TRUE))
4942     /* If the channel does not exist anymore we won't send anything */
4943     goto out;
4944
4945   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4946     /* Re-generate channel key */
4947     if (!silc_server_create_channel_key(server, channel, 0))
4948       goto out;
4949
4950     /* Send the channel key */
4951     silc_server_send_channel_key(server, NULL, channel, 
4952                                  server->server_type == SILC_ROUTER ? 
4953                                  FALSE : !server->standalone);
4954   }
4955
4956  out:
4957   silc_free(id);
4958   silc_server_command_free(cmd);
4959 }
4960
4961 /* Server side of command USERS. Resolves clients and their USERS currently
4962    joined on the requested channel. The list of Client ID's and their modes
4963    on the channel is sent back. */
4964
4965 SILC_SERVER_CMD_FUNC(users)
4966 {
4967   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4968   SilcServer server = cmd->server;
4969   SilcChannelEntry channel;
4970   SilcChannelID *id = NULL;
4971   SilcBuffer packet, idp;
4972   unsigned char *channel_id;
4973   uint32 channel_id_len;
4974   SilcBuffer client_id_list;
4975   SilcBuffer client_mode_list;
4976   unsigned char lc[4];
4977   uint32 list_count = 0;
4978   uint16 ident = silc_command_get_ident(cmd->payload);
4979   char *channel_name;
4980
4981   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4982
4983   /* Get Channel ID */
4984   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4985
4986   /* Get channel name */
4987   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4988
4989   if (!channel_id && !channel_name) {
4990     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4991                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4992     goto out;
4993   }
4994
4995   if (channel_id) {
4996     id = silc_id_payload_parse_id(channel_id, channel_id_len);
4997     if (!id) {
4998       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4999                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
5000       goto out;
5001     }
5002   }
5003
5004   /* If we are server and we don't know about this channel we will send
5005      the command to our router. If we know about the channel then we also
5006      have the list of users already. */
5007   if (id)
5008     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5009   else
5010     channel = silc_idlist_find_channel_by_name(server->local_list, 
5011                                                channel_name, NULL);
5012
5013   if (!channel) {
5014     if (server->server_type != SILC_ROUTER && !server->standalone &&
5015         !cmd->pending) {
5016       SilcBuffer tmpbuf;
5017       
5018       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5019       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5020       
5021       /* Send USERS command */
5022       silc_server_packet_send(server, server->router->connection,
5023                               SILC_PACKET_COMMAND, cmd->packet->flags,
5024                               tmpbuf->data, tmpbuf->len, TRUE);
5025       
5026       /* Reprocess this packet after received reply */
5027       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5028                                   silc_command_get_ident(cmd->payload),
5029                                   silc_server_command_destructor,
5030                                   silc_server_command_users,
5031                                   silc_server_command_dup(cmd));
5032       cmd->pending = TRUE;
5033       silc_command_set_ident(cmd->payload, ident);
5034       
5035       silc_buffer_free(tmpbuf);
5036       silc_free(id);
5037       return;
5038     }
5039
5040     /* Check the global list as well. */
5041     if (id)
5042       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5043     else
5044       channel = silc_idlist_find_channel_by_name(server->global_list, 
5045                                                  channel_name, NULL);
5046     if (!channel) {
5047       /* Channel really does not exist */
5048       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5049                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5050       goto out;
5051     }
5052   }
5053
5054   /* If the channel is private or secret do not send anything, unless the
5055      user requesting this command is on the channel. */
5056   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5057     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5058         && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5059       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5060                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5061       goto out;
5062     }
5063   } else {
5064     if (channel->mode & 
5065         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5066       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5067                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5068       goto out;
5069     }
5070   }
5071
5072   /* Get the users list */
5073   silc_server_get_users_on_channel(server, channel, &client_id_list,
5074                                    &client_mode_list, &list_count);
5075
5076   /* List count */
5077   SILC_PUT32_MSB(list_count, lc);
5078
5079   /* Send reply */
5080   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5081   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5082                                                 SILC_STATUS_OK, ident, 4,
5083                                                 2, idp->data, idp->len,
5084                                                 3, lc, 4,
5085                                                 4, client_id_list->data,
5086                                                 client_id_list->len,
5087                                                 5, client_mode_list->data,
5088                                                 client_mode_list->len);
5089   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5090                           packet->data, packet->len, FALSE);
5091     
5092   silc_buffer_free(idp);
5093   silc_buffer_free(packet);
5094   silc_buffer_free(client_id_list);
5095   silc_buffer_free(client_mode_list);
5096   silc_free(id);
5097
5098  out:
5099   silc_server_command_free(cmd);
5100 }
5101
5102 /* Server side of command GETKEY. This fetches the client's public key
5103    from the server where to the client is connected. */
5104
5105 SILC_SERVER_CMD_FUNC(getkey)
5106 {
5107   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5108   SilcServer server = cmd->server;
5109   SilcBuffer packet;
5110   SilcClientEntry client;
5111   SilcServerEntry server_entry;
5112   SilcClientID *client_id = NULL;
5113   SilcServerID *server_id = NULL;
5114   SilcIDPayload idp = NULL;
5115   uint16 ident = silc_command_get_ident(cmd->payload);
5116   unsigned char *tmp, *pkdata;
5117   uint32 tmp_len, pklen;
5118   SilcBuffer pk = NULL;
5119   SilcIdType id_type;
5120
5121   SILC_LOG_DEBUG(("Start"));
5122
5123   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5124   if (!tmp) {
5125     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5126                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5127     goto out;
5128   }
5129   idp = silc_id_payload_parse_data(tmp, tmp_len);
5130   if (!idp) {
5131     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5132                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5133     goto out;
5134   }
5135
5136   id_type = silc_id_payload_get_type(idp);
5137   if (id_type == SILC_ID_CLIENT) {
5138     client_id = silc_id_payload_get_id(idp);
5139
5140     /* If the client is not found from local list there is no chance it
5141        would be locally connected client so send the command further. */
5142     client = silc_idlist_find_client_by_id(server->local_list, 
5143                                            client_id, TRUE, NULL);
5144     if (!client)
5145       client = silc_idlist_find_client_by_id(server->global_list, 
5146                                              client_id, TRUE, NULL);
5147     
5148     if ((!client && !cmd->pending && !server->standalone) ||
5149         (client && !client->connection && !cmd->pending) ||
5150         (client && !client->data.public_key && !cmd->pending)) {
5151       SilcBuffer tmpbuf;
5152       uint16 old_ident;
5153       SilcSocketConnection dest_sock;
5154       
5155       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5156                                                client_id, NULL);
5157       if (!dest_sock)
5158         goto out;
5159       
5160       old_ident = silc_command_get_ident(cmd->payload);
5161       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5162       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5163       
5164       silc_server_packet_send(server, dest_sock,
5165                               SILC_PACKET_COMMAND, cmd->packet->flags,
5166                               tmpbuf->data, tmpbuf->len, TRUE);
5167       
5168       /* Reprocess this packet after received reply from router */
5169       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5170                                   silc_command_get_ident(cmd->payload),
5171                                   silc_server_command_destructor,
5172                                   silc_server_command_getkey,
5173                                   silc_server_command_dup(cmd));
5174       cmd->pending = TRUE;
5175       
5176       silc_command_set_ident(cmd->payload, old_ident);
5177       silc_buffer_free(tmpbuf);
5178       return;
5179     }
5180
5181     if (!client) {
5182       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5183                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5184       goto out;
5185     }
5186
5187     /* The client is locally connected, just get the public key and
5188        send it back. If they key does not exist then do not send it, 
5189        send just OK reply */
5190     if (!client->data.public_key) {
5191       pkdata = NULL;
5192       pklen = 0;
5193     } else {
5194       tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5195       pk = silc_buffer_alloc(4 + tmp_len);
5196       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5197       silc_buffer_format(pk,
5198                          SILC_STR_UI_SHORT(tmp_len),
5199                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5200                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5201                          SILC_STR_END);
5202       silc_free(tmp);
5203       pkdata = pk->data;
5204       pklen = pk->len;
5205     }
5206   } else if (id_type == SILC_ID_SERVER) {
5207     server_id = silc_id_payload_get_id(idp);
5208
5209     /* If the server is not found from local list there is no chance it
5210        would be locally connected server so send the command further. */
5211     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5212                                                  server_id, TRUE, NULL);
5213     if (!server_entry)
5214       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5215                                                    server_id, TRUE, NULL);
5216     
5217     if (server_entry != server->id_entry &&
5218         ((!server_entry && !cmd->pending && !server->standalone) ||
5219          (server_entry && !server_entry->connection && !cmd->pending &&
5220           !server->standalone) ||
5221          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5222           !server->standalone))) {
5223       SilcBuffer tmpbuf;
5224       uint16 old_ident;
5225       
5226       old_ident = silc_command_get_ident(cmd->payload);
5227       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5228       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5229       
5230       silc_server_packet_send(server, server->router->connection,
5231                               SILC_PACKET_COMMAND, cmd->packet->flags,
5232                               tmpbuf->data, tmpbuf->len, TRUE);
5233       
5234       /* Reprocess this packet after received reply from router */
5235       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5236                                   silc_command_get_ident(cmd->payload),
5237                                   silc_server_command_destructor,
5238                                   silc_server_command_getkey,
5239                                   silc_server_command_dup(cmd));
5240       cmd->pending = TRUE;
5241       
5242       silc_command_set_ident(cmd->payload, old_ident);
5243       silc_buffer_free(tmpbuf);
5244       return;
5245     }
5246
5247     if (!server_entry) {
5248       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5249                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5250       goto out;
5251     }
5252
5253     /* If they key does not exist then do not send it, send just OK reply */
5254     if (!server_entry->data.public_key) {
5255       pkdata = NULL;
5256       pklen = 0;
5257     } else {
5258       tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, 
5259                                         &tmp_len);
5260       pk = silc_buffer_alloc(4 + tmp_len);
5261       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5262       silc_buffer_format(pk,
5263                          SILC_STR_UI_SHORT(tmp_len),
5264                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5265                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5266                          SILC_STR_END);
5267       silc_free(tmp);
5268       pkdata = pk->data;
5269       pklen = pk->len;
5270     }
5271   } else {
5272     goto out;
5273   }
5274
5275   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5276   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5277                                                 SILC_STATUS_OK, ident, 
5278                                                 pkdata ? 2 : 1,
5279                                                 2, tmp, tmp_len,
5280                                                 3, pkdata, pklen);
5281   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5282                           packet->data, packet->len, FALSE);
5283   silc_buffer_free(packet);
5284
5285   if (pk)
5286     silc_buffer_free(pk);
5287
5288  out:
5289   if (idp)
5290     silc_id_payload_free(idp);
5291   silc_free(client_id);
5292   silc_free(server_id);
5293   silc_server_command_free(cmd);
5294 }