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