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