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