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