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