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