updates.
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 static int silc_server_is_registered(SilcServer server,
26                                      SilcSocketConnection sock,
27                                      SilcServerCommandContext cmd,
28                                      SilcCommand command);
29 static void 
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
31                                       SilcCommand command,
32                                       SilcCommandStatus status);
33 static void 
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
35                                      SilcCommand command,
36                                      SilcCommandStatus status,
37                                      unsigned int arg_type,
38                                      unsigned char *arg,
39                                      unsigned int 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   unsigned int _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                                  unsigned short 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                                      unsigned short 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                                       unsigned short 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                                      unsigned int arg_type,
374                                      unsigned char *arg,
375                                      unsigned int 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                                 unsigned int *client_id_count,
401                                 char **nickname,
402                                 char **server_name,
403                                 int *count,
404                                 SilcCommand command)
405 {
406   unsigned char *tmp;
407   unsigned int len;
408   unsigned int 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                                 unsigned int 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       unsigned short 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                                      unsigned int 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   unsigned short 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, clients_count = 0;
657   SilcClientEntry *clients = NULL, entry;
658   SilcClientID **client_id = NULL;
659   unsigned int client_id_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     unsigned short 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, clients_count = 0;
799   SilcClientEntry *clients = NULL, entry;
800   SilcClientID **client_id = NULL;
801   unsigned int client_id_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   unsigned int 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                                  unsigned int 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       unsigned short 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                                       unsigned int 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   unsigned short 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, clients_count = 0;
1115   SilcClientEntry *clients = NULL;
1116   int ret = 0;
1117
1118   /* Protocol dictates that we must always send the received WHOWAS request
1119      to our router if we are normal server, so let's do it now unless we
1120      are standalone. We will not send any replies to the client until we
1121      have received reply from the router. */
1122   if (server->server_type == SILC_SERVER && 
1123       !cmd->pending && !server->standalone) {
1124     SilcBuffer tmpbuf;
1125     unsigned short old_ident;
1126
1127     old_ident = silc_command_get_ident(cmd->payload);
1128     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1129     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1130
1131     /* Send WHOWAS command to our router */
1132     silc_server_packet_send(server, (SilcSocketConnection)
1133                             server->router->connection,
1134                             SILC_PACKET_COMMAND, cmd->packet->flags,
1135                             tmpbuf->data, tmpbuf->len, TRUE);
1136
1137     /* Reprocess this packet after received reply from router */
1138     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1139                                 silc_command_get_ident(cmd->payload),
1140                                 silc_server_command_destructor,
1141                                 silc_server_command_whowas,
1142                                 silc_server_command_dup(cmd));
1143     cmd->pending = TRUE;
1144
1145     silc_command_set_ident(cmd->payload, old_ident);
1146
1147     silc_buffer_free(tmpbuf);
1148     ret = -1;
1149     goto out;
1150   }
1151
1152   /* We are ready to process the command request. Let's search for the
1153      requested client and send reply to the requesting client. */
1154
1155   /* Parse the whowas request */
1156   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1157     return 0;
1158
1159   /* Get all clients matching that nickname from local list */
1160   if (!silc_idlist_get_clients_by_nickname(server->local_list, 
1161                                            nick, server_name,
1162                                            &clients, &clients_count))
1163     silc_idlist_get_clients_by_hash(server->local_list, 
1164                                     nick, server->md5hash,
1165                                     &clients, &clients_count);
1166   
1167   /* Check global list as well */
1168   if (!silc_idlist_get_clients_by_nickname(server->global_list, 
1169                                            nick, server_name,
1170                                            &clients, &clients_count))
1171     silc_idlist_get_clients_by_hash(server->global_list, 
1172                                     nick, server->md5hash,
1173                                     &clients, &clients_count);
1174   
1175   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1176     ret = -1;
1177     goto out;
1178   }
1179
1180   /* Send the command reply to the client */
1181   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1182
1183  out:
1184   if (clients)
1185     silc_free(clients);
1186   if (nick)
1187     silc_free(nick);
1188   if (server_name)
1189     silc_free(server_name);
1190
1191   return ret;
1192 }
1193
1194 static int
1195 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1196 {
1197   SilcServer server = cmd->server;
1198   char *nick = NULL, *server_name = NULL;
1199   int count = 0, clients_count = 0;
1200   SilcClientEntry *clients = NULL;
1201   int ret = 0;
1202
1203   /* Parse the whowas request */
1204   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1205     return 0;
1206
1207   /* Process the command request. Let's search for the requested client and
1208      send reply to the requesting server. */
1209
1210   if (!silc_idlist_get_clients_by_nickname(server->local_list, 
1211                                            nick, server_name,
1212                                            &clients, &clients_count))
1213     silc_idlist_get_clients_by_hash(server->local_list, 
1214                                     nick, server->md5hash,
1215                                     &clients, &clients_count);
1216   
1217   /* If we are router we will check our global list as well. */
1218   if (server->server_type == SILC_ROUTER) {
1219     if (!silc_idlist_get_clients_by_nickname(server->global_list, 
1220                                              nick, server_name,
1221                                              &clients, &clients_count))
1222       silc_idlist_get_clients_by_hash(server->global_list, 
1223                                       nick, server->md5hash,
1224                                       &clients, &clients_count);
1225   }
1226
1227   if (!clients) {
1228     /* Such a client really does not exist in the SILC network. */
1229     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1230                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1231                                          3, nick, strlen(nick));
1232     goto out;
1233   }
1234
1235   /* Send the command reply to the client */
1236   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1237
1238  out:
1239   if (clients)
1240     silc_free(clients);
1241   if (nick)
1242     silc_free(nick);
1243   if (server_name)
1244     silc_free(server_name);
1245
1246   return ret;
1247 }
1248
1249 /* Server side of command WHOWAS. */
1250
1251 SILC_SERVER_CMD_FUNC(whowas)
1252 {
1253   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1254   int ret = 0;
1255
1256   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1257
1258   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1259     ret = silc_server_command_whowas_from_client(cmd);
1260   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1261            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1262     ret = silc_server_command_whowas_from_server(cmd);
1263
1264   if (!ret)
1265     silc_server_command_free(cmd);
1266 }
1267
1268 /******************************************************************************
1269
1270                               IDENTIFY Functions
1271
1272 ******************************************************************************/
1273
1274 /* Checks that all mandatory fields are present. If not then send WHOIS 
1275    request to the server who owns the client. We use WHOIS because we want
1276    to get as much information as possible at once. */
1277
1278 static char
1279 silc_server_command_identify_check(SilcServerCommandContext cmd,
1280                                    SilcClientEntry *clients,
1281                                    unsigned int clients_count)
1282 {
1283   SilcServer server = cmd->server;
1284   int i;
1285   SilcClientEntry entry;
1286
1287   for (i = 0; i < clients_count; i++) {
1288     entry = clients[i];
1289
1290     if (!entry || entry->data.registered == FALSE)
1291       continue;
1292
1293     if (!entry->nickname) {
1294       SilcBuffer tmpbuf;
1295       unsigned short old_ident;
1296       
1297       if (!entry->router)
1298         continue;
1299       
1300       old_ident = silc_command_get_ident(cmd->payload);
1301       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1302       silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1303       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1304       
1305       /* Send WHOIS request. We send WHOIS since we're doing the requesting
1306          now anyway so make it a good one. */
1307       silc_server_packet_send(server, entry->router->connection,
1308                               SILC_PACKET_COMMAND, cmd->packet->flags,
1309                               tmpbuf->data, tmpbuf->len, TRUE);
1310       
1311       /* Reprocess this packet after received reply */
1312       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1313                                   silc_command_get_ident(cmd->payload),
1314                                   silc_server_command_destructor,
1315                                   silc_server_command_identify,
1316                                   silc_server_command_dup(cmd));
1317
1318       cmd->pending = TRUE;
1319       
1320       /* Put old data back to the Command Payload we just changed */
1321       silc_command_set_ident(cmd->payload, old_ident);
1322       silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1323
1324       silc_buffer_free(tmpbuf);
1325       return FALSE;
1326     }
1327   }
1328
1329   return TRUE;
1330 }
1331
1332 static void
1333 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1334                                         SilcClientEntry *clients,
1335                                         unsigned int clients_count,
1336                                         int count)
1337 {
1338   SilcServer server = cmd->server;
1339   char *tmp;
1340   int i, k, len;
1341   SilcBuffer packet, idp;
1342   SilcClientEntry entry;
1343   SilcCommandStatus status;
1344   unsigned short ident = silc_command_get_ident(cmd->payload);
1345   char nh[256], uh[256];
1346   SilcSocketConnection hsock;
1347
1348   len = 0;
1349   for (i = 0; i < clients_count; i++)
1350     if (clients[i]->data.registered)
1351       len++;
1352
1353   status = SILC_STATUS_OK;
1354   if (len > 1)
1355     status = SILC_STATUS_LIST_START;
1356
1357   for (i = 0, k = 0; i < clients_count; i++) {
1358     entry = clients[i];
1359
1360     if (entry->data.registered == FALSE) {
1361       if (clients_count == 1) {
1362         SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1363         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1364                                              SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1365                                              2, idp->data, idp->len);
1366         silc_buffer_free(idp);
1367       }
1368       continue;
1369     }
1370
1371     if (k >= 1)
1372       status = SILC_STATUS_LIST_ITEM;
1373
1374     if (clients_count > 1 && k == clients_count - 1)
1375       status = SILC_STATUS_LIST_END;
1376
1377     if (count && k - 1 == count)
1378       status = SILC_STATUS_LIST_END;
1379
1380     if (count && k - 1 > count)
1381       break;
1382
1383     /* Send IDENTIFY reply */
1384     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1385     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1386     
1387     memset(uh, 0, sizeof(uh));
1388     memset(nh, 0, sizeof(nh));
1389       
1390     strncat(nh, entry->nickname, strlen(entry->nickname));
1391     if (!strchr(entry->nickname, '@')) {
1392       strncat(nh, "@", 1);
1393       len = entry->router ? strlen(entry->router->server_name) :
1394         strlen(server->server_name);
1395       strncat(nh, entry->router ? entry->router->server_name :
1396               server->server_name, len);
1397     }
1398       
1399     if (!entry->username) {
1400       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1401                                                     status, ident, 2,
1402                                                     2, idp->data, idp->len, 
1403                                                     3, nh, strlen(nh));
1404     } else {
1405       strncat(uh, entry->username, strlen(entry->username));
1406       if (!strchr(entry->username, '@')) {
1407         strncat(uh, "@", 1);
1408         hsock = (SilcSocketConnection)entry->connection;
1409         len = strlen(hsock->hostname);
1410         strncat(uh, hsock->hostname, len);
1411       }
1412       
1413       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1414                                                     status, ident, 3,
1415                                                     2, idp->data, idp->len, 
1416                                                     3, nh, strlen(nh),
1417                                                     4, uh, strlen(uh));
1418     }
1419       
1420     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1421                             0, packet->data, packet->len, FALSE);
1422     
1423     silc_buffer_free(packet);
1424     silc_buffer_free(idp);
1425
1426     k++;
1427   }
1428 }
1429
1430 static int
1431 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1432 {
1433   SilcServer server = cmd->server;
1434   char *nick = NULL, *server_name = NULL;
1435   int count = 0, clients_count = 0; 
1436   SilcClientEntry *clients = NULL, entry;
1437   SilcClientID **client_id = NULL;
1438   unsigned int client_id_count = 0;
1439   int i, ret = 0;
1440
1441   /* Protocol dictates that we must always send the received IDENTIFY request
1442      to our router if we are normal server, so let's do it now unless we
1443      are standalone. We will not send any replies to the client until we
1444      have received reply from the router. */
1445   if (server->server_type == SILC_SERVER && 
1446       !cmd->pending && !server->standalone) {
1447     SilcBuffer tmpbuf;
1448     unsigned short old_ident;
1449
1450     old_ident = silc_command_get_ident(cmd->payload);
1451     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1452     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1453
1454     /* Send IDENTIFY command to our router */
1455     silc_server_packet_send(server, (SilcSocketConnection)
1456                             server->router->connection,
1457                             SILC_PACKET_COMMAND, cmd->packet->flags,
1458                             tmpbuf->data, tmpbuf->len, TRUE);
1459
1460     /* Reprocess this packet after received reply from router */
1461     silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1462                                 silc_command_get_ident(cmd->payload),
1463                                 silc_server_command_destructor,
1464                                 silc_server_command_identify,
1465                                 silc_server_command_dup(cmd));
1466     cmd->pending = TRUE;
1467
1468     silc_command_set_ident(cmd->payload, old_ident);
1469
1470     silc_buffer_free(tmpbuf);
1471     ret = -1;
1472     goto out;
1473   }
1474
1475   /* We are ready to process the command request. Let's search for the
1476      requested client and send reply to the requesting client. */
1477
1478   /* Parse the IDENTIFY request */
1479   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1480                                        &nick, &server_name, &count,
1481                                        SILC_COMMAND_IDENTIFY))
1482     return 0;
1483
1484   /* Get all clients matching that ID or nickname from local list */
1485   if (client_id_count) { 
1486     /* Check all Client ID's received in the command packet */
1487     for (i = 0; i < client_id_count; i++) {
1488       entry = silc_idlist_find_client_by_id(server->local_list, 
1489                                             client_id[i], NULL);
1490       if (entry) {
1491         clients = silc_realloc(clients, sizeof(*clients) * 
1492                                (clients_count + 1));
1493         clients[clients_count++] = entry;
1494       }
1495     }
1496   } else {
1497     if (!silc_idlist_get_clients_by_hash(server->local_list, 
1498                                          nick, server->md5hash,
1499                                          &clients, &clients_count))
1500       silc_idlist_get_clients_by_nickname(server->local_list, 
1501                                           nick, server_name,
1502                                           &clients, &clients_count);
1503   }
1504   
1505   /* Check global list as well */
1506   if (client_id_count) {
1507     /* Check all Client ID's received in the command packet */
1508     for (i = 0; i < client_id_count; i++) {
1509       entry = silc_idlist_find_client_by_id(server->global_list, 
1510                                             client_id[i], NULL);
1511       if (entry) {
1512         clients = silc_realloc(clients, sizeof(*clients) * 
1513                                (clients_count + 1));
1514         clients[clients_count++] = entry;
1515       }
1516     }
1517   } else {
1518     if (!silc_idlist_get_clients_by_hash(server->global_list, 
1519                                          nick, server->md5hash,
1520                                          &clients, &clients_count))
1521       silc_idlist_get_clients_by_nickname(server->global_list, 
1522                                           nick, server_name,
1523                                           &clients, &clients_count);
1524   }
1525   
1526   if (!clients) {
1527     /* Such a client really does not exist in the SILC network. */
1528     if (!client_id_count) {
1529       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1530                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1531                                            3, nick, strlen(nick));
1532     } else {
1533       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1534       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1535                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1536                                            2, idp->data, idp->len);
1537       silc_buffer_free(idp);
1538     }
1539     goto out;
1540   }
1541
1542   /* Check that all mandatory fields are present and request those data
1543      from the server who owns the client if necessary. */
1544   if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1545     ret = -1;
1546     goto out;
1547   }
1548
1549   /* Send the command reply to the client */
1550   silc_server_command_identify_send_reply(cmd, clients, clients_count,
1551                                           count);
1552
1553  out:
1554   if (client_id_count) {
1555     for (i = 0; i < client_id_count; i++)
1556       silc_free(client_id[i]);
1557     silc_free(client_id);
1558   }
1559   if (clients)
1560     silc_free(clients);
1561   if (nick)
1562     silc_free(nick);
1563   if (server_name)
1564     silc_free(server_name);
1565
1566   return ret;
1567 }
1568
1569 static int
1570 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1571 {
1572   SilcServer server = cmd->server;
1573   char *nick = NULL, *server_name = NULL;
1574   int count = 0, clients_count = 0;
1575   SilcClientEntry *clients = NULL, entry;
1576   SilcClientID **client_id = NULL;
1577   unsigned int client_id_count = 0;
1578   int i, ret = 0;
1579
1580   /* Parse the IDENTIFY request */
1581   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1582                                        &nick, &server_name, &count,
1583                                        SILC_COMMAND_IDENTIFY))
1584     return 0;
1585
1586   /* Process the command request. Let's search for the requested client and
1587      send reply to the requesting server. */
1588
1589   if (client_id_count) {
1590     /* Check all Client ID's received in the command packet */
1591     for (i = 0; i < client_id_count; i++) {
1592       entry = silc_idlist_find_client_by_id(server->local_list, 
1593                                             client_id[i], NULL);
1594       if (entry) {
1595         clients = silc_realloc(clients, sizeof(*clients) * 
1596                                (clients_count + 1));
1597         clients[clients_count++] = entry;
1598       }
1599     }
1600   } else {
1601     if (!silc_idlist_get_clients_by_hash(server->local_list, 
1602                                          nick, server->md5hash,
1603                                          &clients, &clients_count))
1604       silc_idlist_get_clients_by_nickname(server->local_list, 
1605                                           nick, server_name,
1606                                           &clients, &clients_count);
1607   }
1608   
1609   /* If we are router we will check our global list as well. */
1610   if (server->server_type == SILC_ROUTER) {
1611     if (client_id_count) {
1612       /* Check all Client ID's received in the command packet */
1613       for (i = 0; i < client_id_count; i++) {
1614         entry = silc_idlist_find_client_by_id(server->global_list, 
1615                                               client_id[i], NULL);
1616         if (entry) {
1617           clients = silc_realloc(clients, sizeof(*clients) * 
1618                                  (clients_count + 1));
1619           clients[clients_count++] = entry;
1620         }
1621       }
1622     } else {
1623       if (!silc_idlist_get_clients_by_hash(server->global_list, 
1624                                            nick, server->md5hash,
1625                                            &clients, &clients_count))
1626         silc_idlist_get_clients_by_nickname(server->global_list, 
1627                                             nick, server_name,
1628                                             &clients, &clients_count);
1629     }
1630   }
1631
1632   if (!clients) {
1633     /* Such a client really does not exist in the SILC network. */
1634     if (!client_id_count) {
1635       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1636                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1637                                            3, nick, strlen(nick));
1638     } else {
1639       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1640       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1641                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1642                                            2, idp->data, idp->len);
1643       silc_buffer_free(idp);
1644     }
1645     goto out;
1646   }
1647
1648   /* Check that all mandatory fields are present and request those data
1649      from the server who owns the client if necessary. */
1650   if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1651     ret = -1;
1652     goto out;
1653   }
1654
1655   /* Send the command reply */
1656   silc_server_command_identify_send_reply(cmd, clients, clients_count, count);
1657
1658  out:
1659   if (client_id_count) {
1660     for (i = 0; i < client_id_count; i++)
1661       silc_free(client_id[i]);
1662     silc_free(client_id);
1663   }
1664   if (clients)
1665     silc_free(clients);
1666   if (nick)
1667     silc_free(nick);
1668   if (server_name)
1669     silc_free(server_name);
1670
1671   return ret;
1672 }
1673
1674 SILC_SERVER_CMD_FUNC(identify)
1675 {
1676   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1677   int ret = 0;
1678
1679   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1680
1681   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1682     ret = silc_server_command_identify_from_client(cmd);
1683   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1684            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1685     ret = silc_server_command_identify_from_server(cmd);
1686
1687   if (!ret)
1688     silc_server_command_free(cmd);
1689 }
1690
1691 /* Checks string for bad characters and returns TRUE if they are found. */
1692
1693 static int silc_server_command_bad_chars(char *nick)
1694 {
1695   if (strchr(nick, '\\')) return TRUE;
1696   if (strchr(nick, '\"')) return TRUE;
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
1704   return FALSE;
1705 }
1706
1707 /* Server side of command NICK. Sets nickname for user. Setting
1708    nickname causes generation of a new client ID for the client. The
1709    new client ID is sent to the client after changing the nickname. */
1710
1711 SILC_SERVER_CMD_FUNC(nick)
1712 {
1713   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1714   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1715   SilcServer server = cmd->server;
1716   SilcBuffer packet, nidp, oidp;
1717   SilcClientID *new_id;
1718   char *nick;
1719   unsigned short ident = silc_command_get_ident(cmd->payload);
1720
1721   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1722     goto out;
1723
1724   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1725
1726   /* Check nickname */
1727   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1728   if (silc_server_command_bad_chars(nick) == TRUE) {
1729     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1730                                           SILC_STATUS_ERR_BAD_NICKNAME);
1731     goto out;
1732   }
1733
1734   if (strlen(nick) > 128)
1735     nick[127] = '\0';
1736
1737   /* Create new Client ID */
1738   silc_id_create_client_id(cmd->server->id, cmd->server->rng, 
1739                            cmd->server->md5hash, nick,
1740                            &new_id);
1741
1742   /* Send notify about nickname change to our router. We send the new
1743      ID and ask to replace it with the old one. If we are router the
1744      packet is broadcasted. Send NICK_CHANGE notify. */
1745   if (!server->standalone)
1746     silc_server_send_notify_nick_change(server, server->router->connection, 
1747                                         server->server_type == SILC_SERVER ? 
1748                                         FALSE : TRUE, client->id,
1749                                         new_id, SILC_ID_CLIENT_LEN);
1750
1751   /* Remove old cache entry */
1752   silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
1753                          client->id); 
1754
1755   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1756
1757   /* Free old ID */
1758   if (client->id) {
1759     memset(client->id, 0, SILC_ID_CLIENT_LEN);
1760     silc_free(client->id);
1761   }
1762
1763   /* Save the nickname as this client is our local client */
1764   if (client->nickname)
1765     silc_free(client->nickname);
1766
1767   client->nickname = strdup(nick);
1768   client->id = new_id;
1769
1770   /* Update client cache */
1771   silc_idcache_add(server->local_list->clients, client->nickname, 
1772                    strlen(client->nickname), SILC_ID_CLIENT, client->id, 
1773                    (void *)client, TRUE, FALSE);
1774
1775   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1776
1777   /* Send NICK_CHANGE notify to the client's channels */
1778   silc_server_send_notify_on_channels(server, NULL, client, 
1779                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1780                                       oidp->data, oidp->len, 
1781                                       nidp->data, nidp->len);
1782
1783   /* Send the new Client ID as reply command back to client */
1784   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
1785                                                 SILC_STATUS_OK, ident, 1, 
1786                                                 2, nidp->data, nidp->len);
1787   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1788                           0, packet->data, packet->len, FALSE);
1789
1790   silc_buffer_free(packet);
1791   silc_buffer_free(nidp);
1792   silc_buffer_free(oidp);
1793   
1794  out:
1795   silc_server_command_free(cmd);
1796 }
1797
1798 /* Sends the LIST command reply */
1799
1800 static void
1801 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1802                                     SilcChannelEntry *lch, 
1803                                     unsigned int lch_count,
1804                                     SilcChannelEntry *gch,
1805                                     unsigned int gch_count)
1806 {
1807   int i;
1808   SilcBuffer packet, idp;
1809   SilcChannelEntry entry;
1810   SilcCommandStatus status;
1811   unsigned short ident = silc_command_get_ident(cmd->payload);
1812   char *topic;
1813   unsigned char usercount[4];
1814   unsigned int users;
1815
1816   for (i = 0; i < lch_count; i++)
1817     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1818       lch[i] = NULL;
1819   for (i = 0; i < gch_count; i++)
1820     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1821       gch[i] = NULL;
1822
1823   status = SILC_STATUS_OK;
1824   if ((lch_count + gch_count) > 1)
1825     status = SILC_STATUS_LIST_START;
1826
1827   /* Local list */
1828   for (i = 0; i < lch_count; i++) {
1829     entry = lch[i];
1830
1831     if (!entry)
1832       continue;
1833
1834     if (i >= 1)
1835       status = SILC_STATUS_LIST_ITEM;
1836
1837     if (i == lch_count - 1 && gch_count)
1838       break;
1839     if (lch_count > 1 && i == lch_count - 1)
1840       status = SILC_STATUS_LIST_END;
1841
1842     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1843
1844     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1845       topic = "*private*";
1846       memset(usercount, 0, sizeof(usercount));
1847     } else {
1848       topic = entry->topic;
1849       users = silc_list_count(entry->user_list);
1850       SILC_PUT32_MSB(users, usercount);
1851     }
1852
1853     /* Send the reply */
1854     if (topic)
1855       packet = 
1856         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1857                                              status, ident, 4, 
1858                                              2, idp->data, idp->len,
1859                                              3, entry->channel_name, 
1860                                              strlen(entry->channel_name),
1861                                              4, topic, strlen(topic),
1862                                              5, usercount, 4);
1863     else
1864       packet = 
1865         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1866                                              status, ident, 3, 
1867                                              2, idp->data, idp->len,
1868                                              3, entry->channel_name, 
1869                                              strlen(entry->channel_name),
1870                                              5, usercount, 4);
1871     silc_server_packet_send(cmd->server, cmd->sock, 
1872                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
1873                             packet->len, FALSE);
1874     silc_buffer_free(packet);
1875     silc_buffer_free(idp);
1876   }
1877
1878   status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1879
1880   /* Global list */
1881   for (i = 0; i < gch_count; i++) {
1882     entry = gch[i];
1883
1884     if (!entry)
1885       continue;
1886
1887     if (i >= 1)
1888       status = SILC_STATUS_LIST_ITEM;
1889
1890     if (gch_count > 1 && i == lch_count - 1)
1891       status = SILC_STATUS_LIST_END;
1892
1893     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1894
1895     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1896       topic = "*private*";
1897       memset(usercount, 0, sizeof(usercount));
1898     } else {
1899       topic = entry->topic;
1900       users = silc_list_count(entry->user_list);
1901       SILC_PUT32_MSB(users, usercount);
1902     }
1903
1904     /* Send the reply */
1905     if (topic)
1906       packet = 
1907         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1908                                              status, ident, 4, 
1909                                              2, idp->data, idp->len,
1910                                              3, entry->channel_name, 
1911                                              strlen(entry->channel_name),
1912                                              4, topic, strlen(topic),
1913                                              5, usercount, 4);
1914     else
1915       packet = 
1916         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1917                                              status, ident, 3, 
1918                                              2, idp->data, idp->len,
1919                                              3, entry->channel_name, 
1920                                              strlen(entry->channel_name),
1921                                              5, usercount, 4);
1922     silc_server_packet_send(cmd->server, cmd->sock, 
1923                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
1924                             packet->len, FALSE);
1925     silc_buffer_free(packet);
1926     silc_buffer_free(idp);
1927   }
1928 }
1929
1930 /* Server side of LIST command. This lists the channel of the requested
1931    server. Secret channels are not listed. */
1932
1933 SILC_SERVER_CMD_FUNC(list)
1934 {
1935   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1936   SilcServer server = cmd->server;
1937   SilcChannelID *channel_id = NULL;
1938   unsigned char *tmp;
1939   unsigned int tmp_len;
1940   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1941   unsigned int lch_count = 0, gch_count = 0;
1942
1943   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1944
1945   /* Get Channel ID */
1946   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1947   if (tmp) {
1948     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1949     if (!channel_id) {
1950       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1951                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
1952       goto out;
1953     }
1954   }
1955
1956   /* Get the channels from local list */
1957   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1958                                        &lch_count);
1959   
1960   /* Get the channels from global list if we are router */
1961   if (server->server_type == SILC_ROUTER) 
1962     gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1963                                          &gch_count);
1964
1965   /* Send the reply */
1966   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
1967                                       gchannels, gch_count);
1968
1969  out:
1970   silc_server_command_free(cmd);
1971 }
1972
1973 /* Server side of TOPIC command. Sets topic for channel and/or returns
1974    current topic to client. */
1975
1976 SILC_SERVER_CMD_FUNC(topic)
1977 {
1978   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1979   SilcServer server = cmd->server;
1980   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1981   SilcChannelID *channel_id;
1982   SilcChannelEntry channel;
1983   SilcChannelClientEntry chl;
1984   SilcBuffer packet, idp;
1985   unsigned char *tmp;
1986   unsigned int argc, tmp_len;
1987   unsigned short ident = silc_command_get_ident(cmd->payload);
1988
1989   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1990
1991   argc = silc_argument_get_arg_num(cmd->args);
1992
1993   /* Get Channel ID */
1994   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1995   if (!tmp) {
1996     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1997                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1998     goto out;
1999   }
2000   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2001   if (!channel_id) {
2002     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2003                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2004     goto out;
2005   }
2006
2007   /* Check whether the channel exists */
2008   channel = silc_idlist_find_channel_by_id(server->local_list, 
2009                                            channel_id, NULL);
2010   if (!channel) {
2011     channel = silc_idlist_find_channel_by_id(server->global_list, 
2012                                              channel_id, NULL);
2013     if (!channel) {
2014       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2015                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2016       goto out;
2017     }
2018   }
2019
2020   if (argc > 1) {
2021     /* Get the topic */
2022     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2023     if (!tmp) {
2024       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2025                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2026       goto out;
2027     }
2028
2029     if (strlen(tmp) > 256) {
2030       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2031                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2032       goto out;
2033     }
2034
2035     /* See whether has rights to change topic */
2036     silc_list_start(channel->user_list);
2037     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2038       if (chl->client == client)
2039         break;
2040
2041     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2042       if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2043         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2044                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2045         goto out;
2046       }
2047     }
2048
2049     /* Set the topic for channel */
2050     if (channel->topic)
2051       silc_free(channel->topic);
2052     channel->topic = strdup(tmp);
2053
2054     /* Send TOPIC_SET notify type to the network */
2055     if (!server->standalone)
2056       silc_server_send_notify_topic_set(server, server->router->connection,
2057                                         server->server_type == SILC_ROUTER ?
2058                                         TRUE : FALSE, channel, client->id,
2059                                         SILC_ID_CLIENT_LEN, channel->topic);
2060
2061     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2062
2063     /* Send notify about topic change to all clients on the channel */
2064     silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2065                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2066                                        idp->data, idp->len,
2067                                        channel->topic, strlen(channel->topic));
2068     silc_buffer_free(idp);
2069   }
2070
2071   /* Send the topic to client as reply packet */
2072   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2073   if (channel->topic)
2074     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2075                                                   SILC_STATUS_OK, ident, 2, 
2076                                                   2, idp->data, idp->len,
2077                                                   3, channel->topic, 
2078                                                   strlen(channel->topic));
2079   else
2080     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2081                                                   SILC_STATUS_OK, ident, 1, 
2082                                                   2, idp->data, idp->len);
2083   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2084                           0, packet->data, packet->len, FALSE);
2085
2086   silc_buffer_free(packet);
2087   silc_buffer_free(idp);
2088   silc_free(channel_id);
2089
2090  out:
2091   silc_server_command_free(cmd);
2092 }
2093
2094 /* Server side of INVITE command. Invites some client to join some channel. 
2095    This command is also used to manage the invite list of the channel. */
2096
2097 SILC_SERVER_CMD_FUNC(invite)
2098 {
2099   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2100   SilcServer server = cmd->server;
2101   SilcSocketConnection sock = cmd->sock, dest_sock;
2102   SilcChannelClientEntry chl;
2103   SilcClientEntry sender, dest;
2104   SilcClientID *dest_id = NULL;
2105   SilcChannelEntry channel;
2106   SilcChannelID *channel_id = NULL;
2107   SilcIDListData idata;
2108   SilcBuffer idp, idp2, packet;
2109   unsigned char *tmp, *add, *del;
2110   unsigned int len;
2111   unsigned short ident = silc_command_get_ident(cmd->payload);
2112
2113   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2114
2115   /* Get Channel ID */
2116   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2117   if (!tmp) {
2118     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2119                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2120     goto out;
2121   }
2122   channel_id = silc_id_payload_parse_id(tmp, len);
2123   if (!channel_id) {
2124     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2125                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2126     goto out;
2127   }
2128
2129   /* Get the channel entry */
2130   channel = silc_idlist_find_channel_by_id(server->local_list, 
2131                                            channel_id, NULL);
2132   if (!channel) {
2133     channel = silc_idlist_find_channel_by_id(server->global_list, 
2134                                              channel_id, NULL);
2135     if (!channel) {
2136       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2137                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2138       goto out;
2139     }
2140   }
2141
2142   /* Check whether the sender of this command is on the channel. */
2143   sender = (SilcClientEntry)sock->user_data;
2144   if (!silc_server_client_on_channel(sender, channel)) {
2145     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2146                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2147     goto out;
2148   }
2149
2150   /* Check whether the channel is invite-only channel. If yes then the
2151      sender of this command must be at least channel operator. */
2152   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2153     silc_list_start(channel->user_list);
2154     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2155       if (chl->client == sender) {
2156         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2157           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2158                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2159           goto out;
2160         }
2161         break;
2162       }
2163   }
2164
2165   /* Get destination client ID */
2166   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2167   if (tmp) {
2168     char invite[512];
2169
2170     dest_id = silc_id_payload_parse_id(tmp, len);
2171     if (!dest_id) {
2172       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2173                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2174       goto out;
2175     }
2176
2177     /* Get the client entry */
2178     dest = silc_server_get_client_resolve(server, dest_id);
2179     if (!dest) {
2180       if (server->server_type == SILC_ROUTER) {
2181         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2182                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2183         goto out;
2184       }
2185       
2186       /* The client info is being resolved. Reprocess this packet after
2187          receiving the reply to the query. */
2188       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2189                                   server->cmd_ident,
2190                                   silc_server_command_destructor,
2191                                   silc_server_command_invite, 
2192                                   silc_server_command_dup(cmd));
2193       cmd->pending = TRUE;
2194       silc_free(channel_id);
2195       silc_free(dest_id);
2196       return;
2197     }
2198
2199     /* Check whether the requested client is already on the channel. */
2200     if (silc_server_client_on_channel(dest, channel)) {
2201       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2202                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2203       goto out;
2204     }
2205     
2206     /* Get route to the client */
2207     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2208
2209     memset(invite, 0, sizeof(invite));
2210     strncat(invite, dest->nickname, strlen(dest->nickname));
2211     strncat(invite, "!", 1);
2212     strncat(invite, dest->username, strlen(dest->username));
2213     if (!strchr(dest->username, '@')) {
2214       strncat(invite, "@", 1);
2215       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2216     }
2217
2218     len = strlen(invite);
2219     if (!channel->invite_list)
2220       channel->invite_list = silc_calloc(len + 2, 
2221                                          sizeof(*channel->invite_list));
2222     else
2223       channel->invite_list = silc_realloc(channel->invite_list, 
2224                                           sizeof(*channel->invite_list) * 
2225                                           (len + 
2226                                            strlen(channel->invite_list) + 2));
2227     strncat(channel->invite_list, invite, len);
2228     strncat(channel->invite_list, ",", 1);
2229
2230     /* Send notify to the client that is invited to the channel */
2231     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2232     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2233     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2234                                  SILC_ID_CLIENT,
2235                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2236                                  idp->data, idp->len, 
2237                                  channel->channel_name, 
2238                                  strlen(channel->channel_name),
2239                                  idp2->data, idp2->len);
2240     silc_buffer_free(idp);
2241     silc_buffer_free(idp2);
2242   }
2243
2244   /* Add the client to the invite list of the channel */
2245   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2246   if (add) {
2247     if (!channel->invite_list)
2248       channel->invite_list = silc_calloc(len + 2, 
2249                                          sizeof(*channel->invite_list));
2250     else
2251       channel->invite_list = silc_realloc(channel->invite_list, 
2252                                           sizeof(*channel->invite_list) * 
2253                                           (len + 
2254                                            strlen(channel->invite_list) + 2));
2255     if (add[len - 1] == ',')
2256       add[len - 1] = '\0';
2257     
2258     strncat(channel->invite_list, add, len);
2259     strncat(channel->invite_list, ",", 1);
2260   }
2261
2262   /* Get the invite to be removed and remove it from the list */
2263   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2264   if (del && channel->invite_list) {
2265     char *start, *end, *n;
2266
2267     if (!strncmp(channel->invite_list, del, 
2268                  strlen(channel->invite_list) - 1)) {
2269       silc_free(channel->invite_list);
2270       channel->invite_list = NULL;
2271     } else {
2272       start = strstr(channel->invite_list, del);
2273       if (start && strlen(start) >= len) {
2274         end = start + len;
2275         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2276         strncat(n, channel->invite_list, start - channel->invite_list);
2277         strncat(n, end + 1, ((channel->invite_list + 
2278                               strlen(channel->invite_list)) - end) - 1);
2279         silc_free(channel->invite_list);
2280         channel->invite_list = n;
2281       }
2282     }
2283   }
2284
2285   /* Send notify to the primary router */
2286   if (!server->standalone)
2287     silc_server_send_notify_invite(server, server->router->connection,
2288                                    server->server_type == SILC_ROUTER ?
2289                                    TRUE : FALSE, channel,
2290                                    sender->id, SILC_ID_CLIENT_LEN,
2291                                    add, del);
2292
2293   /* Send command reply */
2294   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2295   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2296                                                 SILC_STATUS_OK, ident, 2,
2297                                                 2, tmp, len,
2298                                                 3, channel->invite_list,
2299                                                 channel->invite_list ?
2300                                                 strlen(channel->invite_list) :
2301                                                 0);
2302   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2303                           packet->data, packet->len, FALSE);
2304   silc_buffer_free(packet);
2305
2306  out:
2307   if (dest_id)
2308     silc_free(dest_id);
2309   if (channel_id)
2310     silc_free(channel_id);
2311   silc_server_command_free(cmd);
2312 }
2313
2314 typedef struct {
2315   SilcServer server;
2316   SilcSocketConnection sock;
2317   char *signoff;
2318 } *QuitInternal;
2319
2320 /* Quits connection to client. This gets called if client won't
2321    close the connection even when it has issued QUIT command. */
2322
2323 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2324 {
2325   QuitInternal q = (QuitInternal)context;
2326
2327   /* Free all client specific data, such as client entry and entires
2328      on channels this client may be on. */
2329   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2330                                TRUE, q->signoff);
2331   q->sock->user_data = NULL;
2332
2333   /* Close the connection on our side */
2334   silc_server_close_connection(q->server, q->sock);
2335
2336   silc_free(q->signoff);
2337   silc_free(q);
2338 }
2339
2340 /* Quits SILC session. This is the normal way to disconnect client. */
2341  
2342 SILC_SERVER_CMD_FUNC(quit)
2343 {
2344   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2345   SilcServer server = cmd->server;
2346   SilcSocketConnection sock = cmd->sock;
2347   QuitInternal q;
2348   unsigned char *tmp = NULL;
2349   unsigned int len = 0;
2350
2351   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2352
2353   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2354     goto out;
2355
2356   /* Get destination ID */
2357   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2358   if (len > 128)
2359     tmp = NULL;
2360
2361   q = silc_calloc(1, sizeof(*q));
2362   q->server = server;
2363   q->sock = sock;
2364   q->signoff = tmp ? strdup(tmp) : NULL;
2365
2366   /* We quit the connection with little timeout */
2367   silc_task_register(server->timeout_queue, sock->sock,
2368                      silc_server_command_quit_cb, (void *)q,
2369                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2370
2371  out:
2372   silc_server_command_free(cmd);
2373 }
2374
2375 /* Server side of command KILL. This command is used by router operator
2376    to remove an client from the SILC Network temporarily. */
2377
2378 SILC_SERVER_CMD_FUNC(kill)
2379 {
2380   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2381   SilcServer server = cmd->server;
2382   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2383   SilcClientEntry remote_client;
2384   SilcClientID *client_id;
2385   unsigned char *tmp, *comment;
2386   unsigned int tmp_len, tmp_len2;
2387
2388   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2389
2390   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2391     goto out;
2392
2393   /* KILL command works only on router */
2394   if (server->server_type != SILC_ROUTER) {
2395     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2396                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2397     goto out;
2398   }
2399
2400   /* Check whether client has the permissions. */
2401   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2402     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2403                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2404     goto out;
2405   }
2406
2407   /* Get the client ID */
2408   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2409   if (!tmp) {
2410     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2411                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2412     goto out;
2413   }
2414   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2415   if (!client_id) {
2416     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2417                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2418     goto out;
2419   }
2420
2421   /* Get the client entry */
2422   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2423                                                 client_id, NULL);
2424   if (!remote_client) {
2425     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2426                                                   client_id, NULL);
2427     if (!remote_client) {
2428       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2429                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2430       goto out;
2431     }
2432   }
2433
2434   /* Get comment */
2435   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2436   if (tmp_len2 > 128)
2437     comment = NULL;
2438
2439   /* Send reply to the sender */
2440   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2441                                         SILC_STATUS_OK);
2442
2443   /* Send the KILL notify packets. First send it to the channel, then
2444      to our primary router and then directly to the client who is being
2445      killed right now. */
2446
2447   /* Send KILLED notify to the channels. It is not sent to the client
2448      as it will be sent differently destined directly to the client and not
2449      to the channel. */
2450   silc_server_send_notify_on_channels(server, remote_client, 
2451                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2452                                       comment ? 2 : 1,
2453                                       tmp, tmp_len,
2454                                       comment, comment ? tmp_len2 : 0);
2455
2456   /* Send KILLED notify to primary route */
2457   if (!server->standalone)
2458     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2459                                    remote_client->id, SILC_ID_CLIENT_LEN,
2460                                    comment);
2461
2462   /* Send KILLED notify to the client directly */
2463   silc_server_send_notify_killed(server, remote_client->connection ? 
2464                                  remote_client->connection : 
2465                                  remote_client->router->connection, FALSE,
2466                                  remote_client->id, SILC_ID_CLIENT_LEN,
2467                                  comment);
2468
2469   /* Remove the client from all channels. This generates new keys to the
2470      channels as well. */
2471   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2472                                    NULL, TRUE);
2473
2474   /* Remove the client entry, If it is locally connected then we will also
2475      disconnect the client here */
2476   if (remote_client->data.registered && remote_client->connection) {
2477     /* Remove locally conneted client */
2478     SilcSocketConnection sock = remote_client->connection;
2479     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2480     silc_server_close_connection(server, sock);
2481   } else {
2482     /* Remove remote client */
2483     if (!silc_idlist_del_client(server->global_list, remote_client))
2484       silc_idlist_del_client(server->local_list, remote_client);
2485   }
2486
2487  out:
2488   silc_server_command_free(cmd);
2489 }
2490
2491 /* Server side of command INFO. This sends information about us to 
2492    the client. If client requested specific server we will send the 
2493    command to that server. */
2494
2495 SILC_SERVER_CMD_FUNC(info)
2496 {
2497   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2498   SilcServer server = cmd->server;
2499   SilcBuffer packet, idp;
2500   unsigned char *tmp;
2501   unsigned int tmp_len;
2502   char *dest_server, *server_info = NULL, *server_name;
2503   unsigned short ident = silc_command_get_ident(cmd->payload);
2504   SilcServerEntry entry = NULL;
2505   SilcServerID *server_id = NULL;
2506
2507   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2508
2509   /* Get server name */
2510   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2511
2512   /* Get Server ID */
2513   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2514   if (tmp) {
2515     server_id = silc_id_payload_parse_id(tmp, tmp_len);
2516     if (!server_id) {
2517       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2518                                             SILC_STATUS_ERR_NO_SERVER_ID);
2519       goto out;
2520     }
2521   }
2522
2523   if (server_id) {
2524     /* Check whether we have this server cached */
2525     entry = silc_idlist_find_server_by_id(server->local_list,
2526                                           server_id, NULL);
2527     if (!entry) {
2528       entry = silc_idlist_find_server_by_id(server->global_list,
2529                                             server_id, NULL);
2530       if (!entry && server->server_type == SILC_ROUTER) {
2531         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2532                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2533         goto out;
2534       }
2535     }
2536   }
2537
2538   if ((!dest_server && !server_id) || 
2539       (dest_server && !cmd->pending && 
2540        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2541     /* Send our reply */
2542     char info_string[256];
2543
2544     memset(info_string, 0, sizeof(info_string));
2545     snprintf(info_string, sizeof(info_string), 
2546              "location: %s server: %s admin: %s <%s>",
2547              server->config->admin_info->location,
2548              server->config->admin_info->server_type,
2549              server->config->admin_info->admin_name,
2550              server->config->admin_info->admin_email);
2551
2552     server_info = info_string;
2553     entry = server->id_entry;
2554   } else {
2555     /* Check whether we have this server cached */
2556     if (!entry && dest_server) {
2557       entry = silc_idlist_find_server_by_name(server->global_list,
2558                                               dest_server, NULL);
2559       if (!entry) {
2560         entry = silc_idlist_find_server_by_name(server->local_list,
2561                                                 dest_server, NULL);
2562       }
2563     }
2564
2565     if (!cmd->pending &&
2566         server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2567       /* Send to the server */
2568       SilcBuffer tmpbuf;
2569       unsigned short old_ident;
2570
2571       old_ident = silc_command_get_ident(cmd->payload);
2572       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2573       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2574
2575       silc_server_packet_send(server, entry->connection,
2576                               SILC_PACKET_COMMAND, cmd->packet->flags,
2577                               tmpbuf->data, tmpbuf->len, TRUE);
2578
2579       /* Reprocess this packet after received reply from router */
2580       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2581                                   silc_command_get_ident(cmd->payload),
2582                                   silc_server_command_destructor,
2583                                   silc_server_command_info,
2584                                   silc_server_command_dup(cmd));
2585       cmd->pending = TRUE;
2586       silc_command_set_ident(cmd->payload, old_ident);
2587       silc_buffer_free(tmpbuf);
2588       return;
2589     }
2590
2591     if (!entry && !cmd->pending && !server->standalone) {
2592       /* Send to the primary router */
2593       SilcBuffer tmpbuf;
2594       unsigned short old_ident;
2595
2596       old_ident = silc_command_get_ident(cmd->payload);
2597       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2598       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2599
2600       silc_server_packet_send(server, server->router->connection,
2601                               SILC_PACKET_COMMAND, cmd->packet->flags,
2602                               tmpbuf->data, tmpbuf->len, TRUE);
2603
2604       /* Reprocess this packet after received reply from router */
2605       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2606                                   silc_command_get_ident(cmd->payload),
2607                                   silc_server_command_destructor,
2608                                   silc_server_command_info,
2609                                   silc_server_command_dup(cmd));
2610       cmd->pending = TRUE;
2611       silc_command_set_ident(cmd->payload, old_ident);
2612       silc_buffer_free(tmpbuf);
2613       return;
2614     }
2615   }
2616
2617   if (server_id)
2618     silc_free(server_id);
2619
2620   if (!entry) {
2621     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2622                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2623     goto out;
2624   }
2625
2626   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2627   if (!server_info)
2628     server_info = entry->server_info;
2629   server_name = entry->server_name;
2630
2631   /* Send the reply */
2632   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2633                                                 SILC_STATUS_OK, ident, 3,
2634                                                 2, idp->data, idp->len,
2635                                                 3, server_name, 
2636                                                 strlen(server_name),
2637                                                 4, server_info, 
2638                                                 strlen(server_info));
2639   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2640                           packet->data, packet->len, FALSE);
2641     
2642   silc_buffer_free(packet);
2643   silc_buffer_free(idp);
2644
2645  out:
2646   silc_server_command_free(cmd);
2647 }
2648
2649 /* Server side of command PING. This just replies to the ping. */
2650
2651 SILC_SERVER_CMD_FUNC(ping)
2652 {
2653   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2654   SilcServer server = cmd->server;
2655   SilcServerID *id;
2656   unsigned int len;
2657   unsigned char *tmp;
2658
2659   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2660
2661   /* Get Server ID */
2662   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2663   if (!tmp) {
2664     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2665                                           SILC_STATUS_ERR_NO_SERVER_ID);
2666     goto out;
2667   }
2668   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2669   if (!id)
2670     goto out;
2671
2672   if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2673     /* Send our reply */
2674     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2675                                           SILC_STATUS_OK);
2676   } else {
2677     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2678                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2679     goto out;
2680   }
2681
2682   silc_free(id);
2683
2684  out:
2685   silc_server_command_free(cmd);
2686 }
2687
2688 /* Internal routine to join channel. The channel sent to this function
2689    has been either created or resolved from ID lists. This joins the sent
2690    client to the channel. */
2691
2692 static void silc_server_command_join_channel(SilcServer server, 
2693                                              SilcServerCommandContext cmd,
2694                                              SilcChannelEntry channel,
2695                                              SilcClientID *client_id,
2696                                              int created,
2697                                              unsigned int umode)
2698 {
2699   SilcSocketConnection sock = cmd->sock;
2700   unsigned char *tmp;
2701   unsigned int tmp_len, user_count;
2702   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2703   SilcClientEntry client;
2704   SilcChannelClientEntry chl;
2705   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2706   unsigned short ident = silc_command_get_ident(cmd->payload);
2707   char check[512];
2708
2709   SILC_LOG_DEBUG(("Start"));
2710
2711   if (!channel)
2712     return;
2713
2714   /* Get the client entry */
2715   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2716     client = (SilcClientEntry)sock->user_data;
2717   } else {
2718     client = silc_idlist_find_client_by_id(server->local_list, client_id, 
2719                                            NULL);
2720     if (!client)
2721       goto out;
2722   }
2723
2724   /*
2725    * Check channel modes
2726    */
2727
2728   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2729     strncat(check, client->nickname, strlen(client->nickname));
2730     if (!strchr(client->nickname, '@')) {
2731       strncat(check, "@", 1);
2732       strncat(check, server->server_name, strlen(server->server_name));
2733     }
2734     strncat(check, "!", 1);
2735     strncat(check, client->username, strlen(client->username));
2736     if (!strchr(client->username, '@')) {
2737       strncat(check, "@", 1);
2738       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2739     }
2740   }
2741
2742   /* Check invite list if channel is invite-only channel */
2743   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
2744       channel->mode & SILC_CHANNEL_MODE_INVITE) {
2745     if (!channel->invite_list) {
2746       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2747                                             SILC_STATUS_ERR_NOT_INVITED);
2748       goto out;
2749     }
2750
2751     if (!silc_string_match(channel->invite_list, check)) {
2752       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2753                                             SILC_STATUS_ERR_NOT_INVITED);
2754       goto out;
2755     }
2756   }
2757
2758   /* Check ban list if it exists. If the client's nickname, server,
2759      username and/or hostname is in the ban list the access to the
2760      channel is denied. */
2761   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2762     if (silc_string_match(channel->ban_list, check)) {
2763       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2764                               SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2765       goto out;
2766     }
2767   }
2768
2769   /* Get passphrase */
2770   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2771   if (tmp) {
2772     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2773     memcpy(passphrase, tmp, tmp_len);
2774   }
2775   
2776   /* Check the channel passphrase if set. */
2777   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2778     if (!passphrase || memcmp(channel->passphrase, passphrase,
2779                               strlen(channel->passphrase))) {
2780       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2781                                             SILC_STATUS_ERR_BAD_PASSWORD);
2782       goto out;
2783     }
2784   }
2785
2786   /* Check user count limit if set. */
2787   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2788     if (silc_list_count(channel->user_list) + 1 > 
2789         channel->user_limit) {
2790       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2791                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
2792       goto out;
2793     }
2794   }
2795
2796   /*
2797    * Client is allowed to join to the channel. Make it happen.
2798    */
2799
2800   /* Check whether the client already is on the channel */
2801   if (silc_server_client_on_channel(client, channel)) {
2802     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2803                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
2804     goto out;
2805   }
2806
2807   /* Generate new channel key as protocol dictates */
2808   if ((!created && silc_list_count(channel->user_list) > 0) || 
2809       !channel->channel_key)
2810     silc_server_create_channel_key(server, channel, 0);
2811
2812   /* Send the channel key. This is broadcasted to the channel but is not
2813      sent to the client who is joining to the channel. */
2814   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2815     silc_server_send_channel_key(server, NULL, channel, 
2816                                  server->server_type == SILC_ROUTER ? 
2817                                  FALSE : !server->standalone);
2818
2819   /* Join the client to the channel by adding it to channel's user list.
2820      Add also the channel to client entry's channels list for fast cross-
2821      referencing. */
2822   chl = silc_calloc(1, sizeof(*chl));
2823   chl->mode = umode;
2824   chl->client = client;
2825   chl->channel = channel;
2826   silc_list_add(channel->user_list, chl);
2827   silc_list_add(client->channels, chl);
2828
2829   /* Get users on the channel */
2830   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2831                                    &user_count);
2832
2833   /* Encode Client ID Payload of the original client who wants to join */
2834   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2835
2836   /* Encode command reply packet */
2837   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2838   SILC_PUT32_MSB(channel->mode, mode);
2839   SILC_PUT32_MSB(created, tmp2);
2840   SILC_PUT32_MSB(user_count, tmp3);
2841
2842   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2843     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2844     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
2845                                            strlen(channel->channel_key->
2846                                                   cipher->name),
2847                                            channel->channel_key->cipher->name,
2848                                            channel->key_len / 8, channel->key);
2849     silc_free(tmp);
2850   }
2851
2852   reply = 
2853     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2854                                          SILC_STATUS_OK, ident, 13,
2855                                          2, channel->channel_name,
2856                                          strlen(channel->channel_name),
2857                                          3, chidp->data, chidp->len,
2858                                          4, clidp->data, clidp->len,
2859                                          5, mode, 4,
2860                                          6, tmp2, 4,
2861                                          7, keyp ? keyp->data : NULL, 
2862                                          keyp ? keyp->len : 0,
2863                                          8, channel->ban_list, 
2864                                          channel->ban_list ?
2865                                          strlen(channel->ban_list) : 0,
2866                                          9, channel->invite_list,
2867                                          channel->invite_list ?
2868                                          strlen(channel->invite_list) : 0,
2869                                          10, channel->topic,
2870                                          channel->topic ?
2871                                          strlen(channel->topic) : 0,
2872                                          11, channel->hmac->hmac->name,
2873                                          strlen(channel->hmac->hmac->name),
2874                                          12, tmp3, 4,
2875                                          13, user_list->data, user_list->len,
2876                                          14, mode_list->data, 
2877                                          mode_list->len);
2878
2879   /* Send command reply */
2880   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
2881                           reply->data, reply->len, FALSE);
2882
2883   if (!cmd->pending) {
2884     /* Send JOIN notify to locally connected clients on the channel */
2885     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2886                                        SILC_NOTIFY_TYPE_JOIN, 2,
2887                                        clidp->data, clidp->len,
2888                                        chidp->data, chidp->len);
2889
2890     /* Send JOIN notify packet to our primary router */
2891     if (!server->standalone)
2892       silc_server_send_notify_join(server, server->router->connection,
2893                                    server->server_type == SILC_ROUTER ?
2894                                    TRUE : FALSE, channel, client->id,
2895                                    SILC_ID_CLIENT_LEN);
2896   }
2897
2898   silc_buffer_free(reply);
2899   silc_buffer_free(clidp);
2900   silc_buffer_free(chidp);
2901   silc_buffer_free(keyp);
2902   silc_buffer_free(user_list);
2903   silc_buffer_free(mode_list);
2904
2905  out:
2906   if (passphrase)
2907     silc_free(passphrase);
2908 }
2909
2910 /* Server side of command JOIN. Joins client into requested channel. If 
2911    the channel does not exist it will be created. */
2912
2913 SILC_SERVER_CMD_FUNC(join)
2914 {
2915   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2916   SilcServer server = cmd->server;
2917   int tmp_len;
2918   char *tmp, *channel_name = NULL, *cipher, *hmac;
2919   SilcChannelEntry channel;
2920   unsigned int umode = 0;
2921   int created = FALSE;
2922   SilcClientID *client_id;
2923
2924   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2925
2926   /* Get channel name */
2927   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2928   if (!tmp) {
2929     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2930                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2931     goto out;
2932   }
2933   channel_name = tmp;
2934
2935   if (strlen(channel_name) > 256)
2936     channel_name[255] = '\0';
2937
2938   if (silc_server_command_bad_chars(channel_name) == TRUE) {
2939     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2940                                           SILC_STATUS_ERR_BAD_CHANNEL);
2941     silc_free(channel_name);
2942     goto out;
2943   }
2944
2945   /* Get Client ID of the client who is joining to the channel */
2946   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2947   if (!tmp) {
2948     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2949                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2950     goto out;
2951   }
2952   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2953   if (!client_id) {
2954     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2955                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2956     goto out;
2957   }
2958
2959   /* Get cipher and hmac name */
2960   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2961   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2962
2963   /* See if the channel exists */
2964   channel = silc_idlist_find_channel_by_name(server->local_list, 
2965                                              channel_name, NULL);
2966
2967   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2968     /* If this is coming from client the Client ID in the command packet must
2969        be same as the client's ID. */
2970     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2971       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2972       if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2973         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2974                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2975         goto out;
2976       }
2977     }
2978
2979     if (!channel || !channel->id) {
2980       /* Channel not found */
2981
2982       /* If we are standalone server we don't have a router, we just create 
2983          the channel by ourselves. */
2984       if (server->standalone) {
2985         channel = silc_server_create_new_channel(server, server->id, cipher, 
2986                                                  hmac, channel_name, TRUE);
2987         if (!channel) {
2988           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2989                                      SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2990           goto out;
2991         }
2992
2993         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2994         created = TRUE;
2995
2996       } else {
2997
2998         /* The channel does not exist on our server. If we are normal server 
2999            we will send JOIN command to our router which will handle the
3000            joining procedure (either creates the channel if it doesn't exist 
3001            or joins the client to it). */
3002         if (server->server_type == SILC_SERVER) {
3003           SilcBuffer tmpbuf;
3004           unsigned short old_ident;
3005           
3006           old_ident = silc_command_get_ident(cmd->payload);
3007           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3008           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3009           
3010           /* Send JOIN command to our router */
3011           silc_server_packet_send(server, (SilcSocketConnection)
3012                                   server->router->connection,
3013                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3014                                   tmpbuf->data, tmpbuf->len, TRUE);
3015           
3016           /* Reprocess this packet after received reply from router */
3017           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3018                                       silc_command_get_ident(cmd->payload),
3019                                       silc_server_command_destructor,
3020                                       silc_server_command_join,
3021                                       silc_server_command_dup(cmd));
3022           cmd->pending = TRUE;
3023           return;
3024         }
3025         
3026         /* We are router and the channel does not seem exist so we will check
3027            our global list as well for the channel. */
3028         channel = silc_idlist_find_channel_by_name(server->global_list, 
3029                                                    channel_name, NULL);
3030         if (!channel) {
3031           /* Channel really does not exist, create it */
3032           channel = silc_server_create_new_channel(server, server->id, cipher, 
3033                                                    hmac, channel_name, TRUE);
3034           if (!channel) {
3035             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3036                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3037             goto out;
3038           }
3039
3040           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3041           created = TRUE;
3042         }
3043       }
3044     }
3045   } else {
3046     if (!channel) {
3047       /* Channel not found */
3048
3049       /* If the command came from router and/or we are normal server then
3050          something went wrong with the joining as the channel was not found.
3051          We can't do anything else but ignore this. */
3052       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3053           server->server_type == SILC_SERVER)
3054         goto out;
3055       
3056       /* We are router and the channel does not seem exist so we will check
3057          our global list as well for the channel. */
3058       channel = silc_idlist_find_channel_by_name(server->global_list, 
3059                                                  channel_name, NULL);
3060       if (!channel) {
3061         /* Channel really does not exist, create it */
3062         channel = silc_server_create_new_channel(server, server->id, cipher, 
3063                                                  hmac, channel_name, TRUE);
3064         if (!channel) {
3065           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3066                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3067           goto out;
3068         }
3069
3070         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3071         created = TRUE;
3072       }
3073     }
3074   }
3075
3076   /* If the channel does not have global users and is also empty it means the
3077      channel was created globally (by our router) and the client will be the
3078      channel founder and operator. */
3079   if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3080     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3081     created = TRUE;             /* Created globally by our router */
3082   }
3083
3084   /* Join to the channel */
3085   silc_server_command_join_channel(server, cmd, channel, client_id,
3086                                    created, umode);
3087
3088   silc_free(client_id);
3089
3090  out:
3091   silc_server_command_free(cmd);
3092 }
3093
3094 /* Server side of command MOTD. Sends server's current "message of the
3095    day" to the client. */
3096
3097 SILC_SERVER_CMD_FUNC(motd)
3098 {
3099   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3100   SilcServer server = cmd->server;
3101   SilcBuffer packet, idp;
3102   char *motd, *dest_server;
3103   int motd_len;
3104   unsigned short ident = silc_command_get_ident(cmd->payload);
3105   
3106   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3107
3108   /* Get server name */
3109   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3110   if (!dest_server) {
3111     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3112                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3113     goto out;
3114   }
3115
3116   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3117     /* Send our MOTD */
3118
3119     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3120
3121     if (server->config && server->config->motd && 
3122         server->config->motd->motd_file) {
3123       /* Send motd */
3124       motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3125       if (!motd)
3126         goto out;
3127       
3128       motd[motd_len] = 0;
3129       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3130                                                     SILC_STATUS_OK, ident, 2,
3131                                                     2, idp, idp->len,
3132                                                     3, motd, motd_len);
3133       goto out;
3134     } else {
3135       /* No motd */
3136       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3137                                                     SILC_STATUS_OK, ident, 1,
3138                                                     2, idp, idp->len);
3139     }
3140
3141     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3142                             packet->data, packet->len, FALSE);
3143     silc_buffer_free(packet);
3144     silc_buffer_free(idp);
3145   } else {
3146     SilcServerEntry entry;
3147
3148     /* Check whether we have this server cached */
3149     entry = silc_idlist_find_server_by_name(server->global_list,
3150                                             dest_server, NULL);
3151     if (!entry) {
3152       entry = silc_idlist_find_server_by_name(server->local_list,
3153                                               dest_server, NULL);
3154     }
3155
3156     if (server->server_type == SILC_ROUTER && !cmd->pending && 
3157         entry && !entry->motd) {
3158       /* Send to the server */
3159       SilcBuffer tmpbuf;
3160       unsigned short old_ident;
3161
3162       old_ident = silc_command_get_ident(cmd->payload);
3163       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3164       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3165
3166       silc_server_packet_send(server, entry->connection,
3167                               SILC_PACKET_COMMAND, cmd->packet->flags,
3168                               tmpbuf->data, tmpbuf->len, TRUE);
3169
3170       /* Reprocess this packet after received reply from router */
3171       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3172                                   silc_command_get_ident(cmd->payload),
3173                                   silc_server_command_destructor,
3174                                   silc_server_command_motd,
3175                                   silc_server_command_dup(cmd));
3176       cmd->pending = TRUE;
3177       silc_command_set_ident(cmd->payload, old_ident);
3178       silc_buffer_free(tmpbuf);
3179       return;
3180     }
3181
3182     if (!entry && !cmd->pending && !server->standalone) {
3183       /* Send to the primary router */
3184       SilcBuffer tmpbuf;
3185       unsigned short old_ident;
3186
3187       old_ident = silc_command_get_ident(cmd->payload);
3188       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3189       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3190
3191       silc_server_packet_send(server, server->router->connection,
3192                               SILC_PACKET_COMMAND, cmd->packet->flags,
3193                               tmpbuf->data, tmpbuf->len, TRUE);
3194
3195       /* Reprocess this packet after received reply from router */
3196       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3197                                   silc_command_get_ident(cmd->payload),
3198                                   silc_server_command_destructor,
3199                                   silc_server_command_motd,
3200                                   silc_server_command_dup(cmd));
3201       cmd->pending = TRUE;
3202       silc_command_set_ident(cmd->payload, old_ident);
3203       silc_buffer_free(tmpbuf);
3204       return;
3205     }
3206
3207     if (!entry) {
3208       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3209                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3210       goto out;
3211     }
3212
3213     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3214
3215     if (entry->motd)
3216       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3217                                                     SILC_STATUS_OK, ident, 2,
3218                                                     2, idp, idp->len,
3219                                                     3, entry->motd,
3220                                                     strlen(entry->motd));
3221     else
3222       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3223                                                     SILC_STATUS_OK, ident, 1,
3224                                                     2, idp, idp->len);
3225
3226     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3227                             packet->data, packet->len, FALSE);
3228     silc_buffer_free(packet);
3229     silc_buffer_free(idp);
3230   }
3231
3232  out:
3233   silc_server_command_free(cmd);
3234 }
3235
3236 /* Server side of command UMODE. Client can use this command to set/unset
3237    user mode. Client actually cannot set itself to be as server/router
3238    operator so this can be used only to unset the modes. */
3239
3240 SILC_SERVER_CMD_FUNC(umode)
3241 {
3242   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3243   SilcServer server = cmd->server;
3244   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3245   SilcBuffer packet;
3246   unsigned char *tmp_mask;
3247   unsigned int mask;
3248   unsigned short ident = silc_command_get_ident(cmd->payload);
3249
3250   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3251     goto out;
3252
3253   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3254
3255   /* Get the client's mode mask */
3256   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3257   if (!tmp_mask) {
3258     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3259                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3260     goto out;
3261   }
3262   SILC_GET32_MSB(mask, tmp_mask);
3263
3264   /* 
3265    * Change the mode 
3266    */
3267
3268   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3269     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3270       /* Cannot operator mode */
3271       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3272                                             SILC_STATUS_ERR_PERM_DENIED);
3273       goto out;
3274     }
3275   } else {
3276     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3277       /* Remove the server operator rights */
3278       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3279   }
3280
3281   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3282     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3283       /* Cannot operator mode */
3284       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3285                                             SILC_STATUS_ERR_PERM_DENIED);
3286       goto out;
3287     }
3288   } else {
3289     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3290       /* Remove the router operator rights */
3291       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3292   }
3293
3294   if (mask & SILC_UMODE_GONE) {
3295     client->mode |= SILC_UMODE_GONE;
3296   } else {
3297     if (client->mode & SILC_UMODE_GONE)
3298       /* Remove the gone status */
3299       client->mode &= ~SILC_UMODE_GONE;
3300   }
3301
3302   /* Send UMODE change to primary router */
3303   if (!server->standalone)
3304     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3305                                   client->id, SILC_ID_CLIENT_LEN,
3306                                   client->mode);
3307
3308   /* Send command reply to sender */
3309   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3310                                                 SILC_STATUS_OK, ident, 1,
3311                                                 2, tmp_mask, 4);
3312   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3313                           packet->data, packet->len, FALSE);
3314   silc_buffer_free(packet);
3315
3316  out:
3317   silc_server_command_free(cmd);
3318 }
3319
3320 /* Checks that client has rights to add or remove channel modes. If any
3321    of the checks fails FALSE is returned. */
3322
3323 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3324                                    SilcChannelClientEntry client,
3325                                    unsigned int mode)
3326 {
3327   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3328   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3329
3330   /* Check whether has rights to change anything */
3331   if (!is_op && !is_fo)
3332     return FALSE;
3333
3334   /* Check whether has rights to change everything */
3335   if (is_op && is_fo)
3336     return TRUE;
3337
3338   /* We know that client is channel operator, check that they are not
3339      changing anything that requires channel founder rights. Rest of the
3340      modes are available automatically for channel operator. */
3341
3342   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3343     if (is_op && !is_fo)
3344       return FALSE;
3345   } else {
3346     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3347       if (is_op && !is_fo)
3348         return FALSE;
3349     }
3350   }
3351   
3352   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3353     if (is_op && !is_fo)
3354       return FALSE;
3355   } else {
3356     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3357       if (is_op && !is_fo)
3358         return FALSE;
3359     }
3360   }
3361
3362   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3363     if (is_op && !is_fo)
3364       return FALSE;
3365   } else {
3366     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3367       if (is_op && !is_fo)
3368         return FALSE;
3369     }
3370   }
3371   
3372   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3373     if (is_op && !is_fo)
3374       return FALSE;
3375   } else {
3376     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3377       if (is_op && !is_fo)
3378         return FALSE;
3379     }
3380   }
3381   
3382   return TRUE;
3383 }
3384
3385 /* Server side command of CMODE. Changes channel mode */
3386
3387 SILC_SERVER_CMD_FUNC(cmode)
3388 {
3389   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3390   SilcServer server = cmd->server;
3391   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3392   SilcIDListData idata = (SilcIDListData)client;
3393   SilcChannelID *channel_id;
3394   SilcChannelEntry channel;
3395   SilcChannelClientEntry chl;
3396   SilcBuffer packet, cidp;
3397   unsigned char *tmp, *tmp_id, *tmp_mask;
3398   char *cipher = NULL, *hmac = NULL;
3399   unsigned int mode_mask, tmp_len, tmp_len2;
3400   unsigned short ident = silc_command_get_ident(cmd->payload);
3401
3402   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3403
3404   /* Get Channel ID */
3405   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3406   if (!tmp_id) {
3407     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3408                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3409     goto out;
3410   }
3411   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3412   if (!channel_id) {
3413     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3414                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3415     goto out;
3416   }
3417
3418   /* Get the channel mode mask */
3419   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3420   if (!tmp_mask) {
3421     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3422                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3423     goto out;
3424   }
3425   SILC_GET32_MSB(mode_mask, tmp_mask);
3426
3427   /* Get channel entry */
3428   channel = silc_idlist_find_channel_by_id(server->local_list, 
3429                                            channel_id, NULL);
3430   if (!channel) {
3431     channel = silc_idlist_find_channel_by_id(server->global_list, 
3432                                              channel_id, NULL);
3433     if (!channel) {
3434       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3435                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3436       goto out;
3437     }
3438   }
3439
3440   /* Check whether this client is on the channel */
3441   if (!silc_server_client_on_channel(client, channel)) {
3442     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3443                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3444     goto out;
3445   }
3446
3447   /* Get entry to the channel user list */
3448   silc_list_start(channel->user_list);
3449   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3450     if (chl->client == client)
3451       break;
3452
3453   /* Check that client has rights to change any requested channel modes */
3454   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3455     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3456                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3457     goto out;
3458   }
3459
3460   /*
3461    * Check the modes. Modes that requires nothing special operation are
3462    * not checked here.
3463    */
3464
3465   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3466     /* Channel uses private keys to protect traffic. Client(s) has set the
3467        key locally they want to use, server does not know that key. */
3468     /* Nothing interesting to do here */
3469   } else {
3470     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3471       /* The mode is removed and we need to generate and distribute
3472          new channel key. Clients are not using private channel keys
3473          anymore after this. */
3474
3475       /* Re-generate channel key */
3476       silc_server_create_channel_key(server, channel, 0);
3477       
3478       /* Send the channel key. This sends it to our local clients and if
3479          we are normal server to our router as well. */
3480       silc_server_send_channel_key(server, NULL, channel, 
3481                                    server->server_type == SILC_ROUTER ? 
3482                                    FALSE : !server->standalone);
3483
3484       cipher = channel->channel_key->cipher->name;
3485       hmac = channel->hmac->hmac->name;
3486     }
3487   }
3488   
3489   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3490     /* User limit is set on channel */
3491     unsigned int user_limit;
3492       
3493     /* Get user limit */
3494     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3495     if (!tmp) {
3496       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3497         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3498                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3499         goto out;
3500       }
3501     } else {
3502       SILC_GET32_MSB(user_limit, tmp);
3503       channel->user_limit = user_limit;
3504     }
3505   } else {
3506     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3507       /* User limit mode is unset. Remove user limit */
3508       channel->user_limit = 0;
3509   }
3510
3511   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3512     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3513       /* Passphrase has been set to channel */
3514       
3515       /* Get the passphrase */
3516       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3517       if (!tmp) {
3518         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3519                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3520         goto out;
3521       }
3522
3523       /* Save the passphrase */
3524       channel->passphrase = strdup(tmp);
3525     }
3526   } else {
3527     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3528       /* Passphrase mode is unset. remove the passphrase */
3529       if (channel->passphrase) {
3530         silc_free(channel->passphrase);
3531         channel->passphrase = NULL;
3532       }
3533     }
3534   }
3535
3536   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3537     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3538       /* Cipher to use protect the traffic */
3539
3540       /* Get cipher */
3541       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3542       if (!cipher) {
3543         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3544                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3545         goto out;
3546       }
3547
3548       /* Delete old cipher and allocate the new one */
3549       silc_cipher_free(channel->channel_key);
3550       if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3551         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3552                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3553         goto out;
3554       }
3555
3556       /* Re-generate channel key */
3557       silc_server_create_channel_key(server, channel, 0);
3558     
3559       /* Send the channel key. This sends it to our local clients and if
3560          we are normal server to our router as well. */
3561       silc_server_send_channel_key(server, NULL, channel, 
3562                                    server->server_type == SILC_ROUTER ? 
3563                                    FALSE : !server->standalone);
3564     }
3565   } else {
3566     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3567       /* Cipher mode is unset. Remove the cipher and revert back to 
3568          default cipher */
3569       cipher = channel->cipher;
3570
3571       /* Delete old cipher and allocate default one */
3572       silc_cipher_free(channel->channel_key);
3573       if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc", 
3574                              &channel->channel_key)) {
3575         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3576                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3577         goto out;
3578       }
3579
3580       /* Re-generate channel key */
3581       silc_server_create_channel_key(server, channel, 0);
3582       
3583       /* Send the channel key. This sends it to our local clients and if
3584          we are normal server to our router as well. */
3585       silc_server_send_channel_key(server, NULL, channel, 
3586                                    server->server_type == SILC_ROUTER ? 
3587                                    FALSE : !server->standalone);
3588     }
3589   }
3590
3591   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3592     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3593       /* HMAC to use protect the traffic */
3594       unsigned char hash[32];
3595
3596       /* Get hmac */
3597       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3598       if (!hmac) {
3599         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3600                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3601         goto out;
3602       }
3603
3604       /* Delete old hmac and allocate the new one */
3605       silc_hmac_free(channel->hmac);
3606       if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3607         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3608                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3609         goto out;
3610       }
3611
3612       /* Set the HMAC key out of current channel key. The client must do
3613          this locally. */
3614       silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
3615                      hash);
3616       silc_hmac_set_key(channel->hmac, hash, 
3617                         silc_hash_len(channel->hmac->hash));
3618       memset(hash, 0, sizeof(hash));
3619     }
3620   } else {
3621     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3622       /* Hmac mode is unset. Remove the hmac and revert back to 
3623          default hmac */
3624       unsigned char hash[32];
3625       hmac = channel->hmac_name;
3626
3627       /* Delete old hmac and allocate default one */
3628       silc_hmac_free(channel->hmac);
3629       if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL, 
3630                            &channel->hmac)) {
3631         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3632                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3633         goto out;
3634       }
3635
3636       /* Set the HMAC key out of current channel key. The client must do
3637          this locally. */
3638       silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
3639                      hash);
3640       silc_hmac_set_key(channel->hmac, hash, 
3641                         silc_hash_len(channel->hmac->hash));
3642       memset(hash, 0, sizeof(hash));
3643     }
3644   }
3645
3646   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3647     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3648       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3649         /* Set the founder authentication */
3650         SilcAuthPayload auth;
3651         
3652         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3653         if (!tmp) {
3654           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3655                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3656           goto out;
3657         }
3658
3659         auth = silc_auth_payload_parse(tmp, tmp_len);
3660         if (!auth) {
3661           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3662                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3663           goto out;
3664         }
3665
3666         /* Save the public key */
3667         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3668         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3669         silc_free(tmp);
3670         
3671         channel->founder_method = silc_auth_get_method(auth);
3672
3673         if (channel->founder_method == SILC_AUTH_PASSWORD) {
3674           tmp = silc_auth_get_data(auth, &tmp_len);
3675           channel->founder_passwd = 
3676             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3677           memcpy(channel->founder_passwd, tmp, tmp_len);
3678           channel->founder_passwd_len = tmp_len;
3679         }
3680
3681         silc_auth_payload_free(auth);
3682       }
3683     }
3684   } else {
3685     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3686       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3687         if (channel->founder_key)
3688           silc_pkcs_public_key_free(channel->founder_key);
3689         if (channel->founder_passwd) {
3690           silc_free(channel->founder_passwd);
3691           channel->founder_passwd = NULL;
3692         }
3693       }
3694     }
3695   }
3696
3697   /* Finally, set the mode */
3698   channel->mode = mode_mask;
3699
3700   /* Send CMODE_CHANGE notify */
3701   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3702   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3703                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3704                                      cidp->data, cidp->len, 
3705                                      tmp_mask, 4,
3706                                      cipher, cipher ? strlen(cipher) : 0,
3707                                      hmac, hmac ? strlen(hmac) : 0);
3708
3709   /* Set CMODE notify type to network */
3710   if (!server->standalone)
3711     silc_server_send_notify_cmode(server, server->router->connection,
3712                                   server->server_type == SILC_ROUTER ? 
3713                                   TRUE : FALSE, channel,
3714                                   mode_mask, client->id, SILC_ID_CLIENT,
3715                                   SILC_ID_CLIENT_LEN,
3716                                   cipher, hmac);
3717
3718   /* Send command reply to sender */
3719   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3720                                                 SILC_STATUS_OK, ident, 1,
3721                                                 2, tmp_mask, 4);
3722   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3723                           packet->data, packet->len, FALSE);
3724     
3725   silc_buffer_free(packet);
3726   silc_free(channel_id);
3727   silc_free(cidp);
3728
3729  out:
3730   silc_server_command_free(cmd);
3731 }
3732
3733 /* Server side of CUMODE command. Changes client's mode on a channel. */
3734
3735 SILC_SERVER_CMD_FUNC(cumode)
3736 {
3737   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3738   SilcServer server = cmd->server;
3739   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3740   SilcIDListData idata = (SilcIDListData)client;
3741   SilcChannelID *channel_id;
3742   SilcClientID *client_id;
3743   SilcChannelEntry channel;
3744   SilcClientEntry target_client;
3745   SilcChannelClientEntry chl;
3746   SilcBuffer packet, idp;
3747   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3748   unsigned int target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3749   int notify = FALSE;
3750   unsigned short ident = silc_command_get_ident(cmd->payload);
3751
3752   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3753
3754   /* Get Channel ID */
3755   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3756   if (!tmp_ch_id) {
3757     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3758                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3759     goto out;
3760   }
3761   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3762   if (!channel_id) {
3763     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3764                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3765     goto out;
3766   }
3767
3768   /* Get channel entry */
3769   channel = silc_idlist_find_channel_by_id(server->local_list, 
3770                                            channel_id, NULL);
3771   if (!channel) {
3772     channel = silc_idlist_find_channel_by_id(server->global_list, 
3773                                              channel_id, NULL);
3774     if (!channel) {
3775       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3776                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3777       goto out;
3778     }
3779   }
3780
3781   /* Check whether sender is on the channel */
3782   if (!silc_server_client_on_channel(client, channel)) {
3783     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3784                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3785     goto out;
3786   }
3787
3788   /* Check that client has rights to change other's rights */
3789   silc_list_start(channel->user_list);
3790   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3791     if (chl->client == client) {
3792       sender_mask = chl->mode;
3793       break;
3794     }
3795   }
3796   
3797   /* Get the target client's channel mode mask */
3798   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3799   if (!tmp_mask) {
3800     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3801                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3802     goto out;
3803   }
3804   SILC_GET32_MSB(target_mask, tmp_mask);
3805
3806   /* Get target Client ID */
3807   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3808   if (!tmp_id) {
3809     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3810                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3811     goto out;
3812   }
3813   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3814   if (!client_id) {
3815     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3816                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3817     goto out;
3818   }
3819
3820   /* Get target client's entry */
3821   target_client = silc_idlist_find_client_by_id(server->local_list, 
3822                                                 client_id, NULL);
3823   if (!target_client) {
3824     target_client = silc_idlist_find_client_by_id(server->global_list, 
3825                                                   client_id, NULL);
3826   }
3827
3828   if (target_client != client &&
3829       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3830       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3831     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3832                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3833     goto out;
3834   }
3835
3836   /* Check whether target client is on the channel */
3837   if (target_client != client) {
3838     if (!silc_server_client_on_channel(target_client, channel)) {
3839       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3840                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3841       goto out;
3842     }
3843
3844     /* Get entry to the channel user list */
3845     silc_list_start(channel->user_list);
3846     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3847       if (chl->client == target_client)
3848         break;
3849   }
3850
3851   /* 
3852    * Change the mode 
3853    */
3854
3855   /* If the target client is founder, no one else can change their mode
3856      but themselves. */
3857   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3858     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3859                                           SILC_STATUS_ERR_NOT_YOU);
3860     goto out;
3861   }
3862
3863   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3864     /* The client tries to claim the founder rights. */
3865     unsigned char *tmp_auth;
3866     unsigned int tmp_auth_len, auth_len;
3867     void *auth;
3868     
3869     if (target_client != client) {
3870       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3871                                             SILC_STATUS_ERR_NOT_YOU);
3872       goto out;
3873     }
3874
3875     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3876         !channel->founder_key) {
3877       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3878                                             SILC_STATUS_ERR_NOT_YOU);
3879       goto out;
3880     }
3881
3882     tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3883     if (!tmp_auth) {
3884       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3885                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3886       goto out;
3887     }
3888
3889     auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3890             (void *)channel->founder_passwd : (void *)channel->founder_key);
3891     auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3892                 channel->founder_passwd_len : 0);
3893     
3894     if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3895                                channel->founder_method, auth, auth_len,
3896                                idata->hash, client->id, SILC_ID_CLIENT)) {
3897       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3898                                             SILC_STATUS_ERR_AUTH_FAILED);
3899       goto out;
3900     }
3901
3902     sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3903     notify = TRUE;
3904   } else {
3905     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3906       if (target_client == client) {
3907         /* Remove channel founder rights from itself */
3908         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3909         notify = TRUE;
3910       } else {
3911         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3912                                               SILC_STATUS_ERR_NOT_YOU);
3913         goto out;
3914       }
3915     }
3916   }
3917
3918   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3919     /* Promote to operator */
3920     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3921       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3922           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3923         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3924                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3925         goto out;
3926       }
3927
3928       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3929       notify = TRUE;
3930     }
3931   } else {
3932     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3933       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3934           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3935         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3936                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3937         goto out;
3938       }
3939
3940       /* Demote to normal user */
3941       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3942       notify = TRUE;
3943     }
3944   }
3945
3946   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3947   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3948
3949   /* Send notify to channel, notify only if mode was actually changed. */
3950   if (notify) {
3951     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3952                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3953                                        idp->data, idp->len,
3954                                        tmp_mask, 4, 
3955                                        tmp_id, tmp_len);
3956
3957     /* Set CUMODE notify type to network */
3958     if (!server->standalone)
3959       silc_server_send_notify_cumode(server, server->router->connection,
3960                                      server->server_type == SILC_ROUTER ? 
3961                                      TRUE : FALSE, channel,
3962                                      target_mask, client->id, 
3963                                      SILC_ID_CLIENT_LEN,
3964                                      target_client->id, 
3965                                      SILC_ID_CLIENT_LEN);
3966   }
3967
3968   /* Send command reply to sender */
3969   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3970                                                 SILC_STATUS_OK, ident, 2,
3971                                                 2, tmp_mask, 4,
3972                                                 3, tmp_id, tmp_len);
3973   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3974                           packet->data, packet->len, FALSE);
3975     
3976   silc_buffer_free(packet);
3977   silc_free(channel_id);
3978   silc_free(client_id);
3979   silc_buffer_free(idp);
3980
3981  out:
3982   silc_server_command_free(cmd);
3983 }
3984
3985 /* Server side of KICK command. Kicks client out of channel. */
3986
3987 SILC_SERVER_CMD_FUNC(kick)
3988 {
3989   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3990   SilcServer server = cmd->server;
3991   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3992   SilcClientEntry target_client;
3993   SilcChannelID *channel_id;
3994   SilcClientID *client_id;
3995   SilcChannelEntry channel;
3996   SilcChannelClientEntry chl;
3997   SilcBuffer idp;
3998   unsigned int tmp_len;
3999   unsigned char *tmp, *comment;
4000
4001   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4002
4003   /* Get Channel ID */
4004   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4005   if (!tmp) {
4006     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4007                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4008     goto out;
4009   }
4010   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4011   if (!channel_id) {
4012     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4013                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4014     goto out;
4015   }
4016
4017   /* Get channel entry */
4018   channel = silc_idlist_find_channel_by_id(server->local_list, 
4019                                            channel_id, NULL);
4020   if (!channel) {
4021     channel = silc_idlist_find_channel_by_id(server->local_list, 
4022                                              channel_id, NULL);
4023     if (!channel) {
4024       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4025                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4026       goto out;
4027     }
4028   }
4029
4030   /* Check whether sender is on the channel */
4031   if (!silc_server_client_on_channel(client, channel)) {
4032     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4033                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4034     goto out;
4035   }
4036
4037   /* Check that the kicker is channel operator or channel founder */
4038   silc_list_start(channel->user_list);
4039   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4040     if (chl->client == client) {
4041       if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4042         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4043                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4044         goto out;
4045       }
4046       break;
4047     }
4048   }
4049   
4050   /* Get target Client ID */
4051   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4052   if (!tmp) {
4053     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4054                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4055     goto out;
4056   }
4057   client_id = silc_id_payload_parse_id(tmp, tmp_len);
4058   if (!client_id) {
4059     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4060                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4061     goto out;
4062   }
4063
4064   /* Get target client's entry */
4065   target_client = silc_idlist_find_client_by_id(server->local_list, 
4066                                                 client_id, NULL);
4067   if (!target_client) {
4068     target_client = silc_idlist_find_client_by_id(server->global_list, 
4069                                                   client_id, NULL);
4070   }
4071
4072   /* Check that the target client is not channel founder. Channel founder
4073      cannot be kicked from the channel. */
4074   silc_list_start(channel->user_list);
4075   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4076     if (chl->client == target_client) {
4077       if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4078         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4079                                   SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4080         goto out;
4081       }
4082       break;
4083     }
4084   }
4085   
4086   /* Check whether target client is on the channel */
4087   if (!silc_server_client_on_channel(target_client, channel)) {
4088     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4089                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4090     goto out;
4091   }
4092
4093   /* Get comment */
4094   tmp_len = 0;
4095   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4096   if (tmp_len > 128)
4097     comment = NULL;
4098
4099   /* Send command reply to sender */
4100   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4101                                         SILC_STATUS_OK);
4102
4103   /* Send KICKED notify to local clients on the channel */
4104   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4105   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4106                                      SILC_NOTIFY_TYPE_KICKED, 
4107                                      comment ? 2 : 1,
4108                                      idp->data, idp->len,
4109                                      comment, comment ? strlen(comment) : 0);
4110   silc_buffer_free(idp);
4111
4112   /* Remove the client from the channel. If the channel does not exist
4113      after removing the client then the client kicked itself off the channel
4114      and we don't have to send anything after that. */
4115   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4116                                            target_client, FALSE))
4117     goto out;
4118
4119   /* Send KICKED notify to primary route */
4120   if (!server->standalone)
4121     silc_server_send_notify_kicked(server, server->router->connection,
4122                                    server->server_type == SILC_ROUTER ?
4123                                    TRUE : FALSE, channel,
4124                                    target_client->id, SILC_ID_CLIENT_LEN,
4125                                    comment);
4126
4127   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4128     /* Re-generate channel key */
4129     silc_server_create_channel_key(server, channel, 0);
4130     
4131     /* Send the channel key to the channel. The key of course is not sent
4132        to the client who was kicked off the channel. */
4133     silc_server_send_channel_key(server, target_client->connection, channel, 
4134                                  server->server_type == SILC_ROUTER ? 
4135                                  FALSE : !server->standalone);
4136   }
4137
4138  out:
4139   silc_server_command_free(cmd);
4140 }
4141
4142 /* Server side of OPER command. Client uses this comand to obtain server
4143    operator privileges to this server/router. */
4144
4145 SILC_SERVER_CMD_FUNC(oper)
4146 {
4147   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4148   SilcServer server = cmd->server;
4149   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4150   unsigned char *username, *auth;
4151   unsigned int tmp_len;
4152   SilcServerConfigSectionAdminConnection *admin;
4153   SilcIDListData idata = (SilcIDListData)client;
4154
4155   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4156
4157   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4158     goto out;
4159
4160   /* Get the username */
4161   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4162   if (!username) {
4163     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4164                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4165     goto out;
4166   }
4167
4168   /* Get the admin configuration */
4169   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4170                                         username, client->nickname);
4171   if (!admin) {
4172     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4173                                           username, client->nickname);
4174     if (!admin) {
4175       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4176                                             SILC_STATUS_ERR_AUTH_FAILED);
4177       goto out;
4178     }
4179   }
4180
4181   /* Get the authentication payload */
4182   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4183   if (!auth) {
4184     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4185                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4186     goto out;
4187   }
4188
4189   /* Verify the authentication data */
4190   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4191                              admin->auth_data, admin->auth_data_len,
4192                              idata->hash, client->id, SILC_ID_CLIENT)) {
4193     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4194                                           SILC_STATUS_ERR_AUTH_FAILED);
4195     goto out;
4196   }
4197
4198   /* Client is now server operator */
4199   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4200
4201   /* Send UMODE change to primary router */
4202   if (!server->standalone)
4203     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4204                                   client->id, SILC_ID_CLIENT_LEN,
4205                                   client->mode);
4206
4207   /* Send reply to the sender */
4208   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4209                                         SILC_STATUS_OK);
4210
4211  out:
4212   silc_server_command_free(cmd);
4213 }
4214
4215 /* Server side of SILCOPER command. Client uses this comand to obtain router
4216    operator privileges to this router. */
4217
4218 SILC_SERVER_CMD_FUNC(silcoper)
4219 {
4220   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4221   SilcServer server = cmd->server;
4222   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4223   unsigned char *username, *auth;
4224   unsigned int tmp_len;
4225   SilcServerConfigSectionAdminConnection *admin;
4226   SilcIDListData idata = (SilcIDListData)client;
4227
4228   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4229
4230   if (server->server_type == SILC_SERVER)
4231     goto out;
4232
4233   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4234     goto out;
4235
4236   /* Get the username */
4237   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4238   if (!username) {
4239     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4240                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4241     goto out;
4242   }
4243
4244   /* Get the admin configuration */
4245   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4246                                         username, client->nickname);
4247   if (!admin) {
4248     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4249                                           username, client->nickname);
4250     if (!admin) {
4251       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4252                                             SILC_STATUS_ERR_AUTH_FAILED);
4253       goto out;
4254     }
4255   }
4256
4257   /* Get the authentication payload */
4258   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4259   if (!auth) {
4260     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4261                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4262     goto out;
4263   }
4264
4265   /* Verify the authentication data */
4266   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4267                              admin->auth_data, admin->auth_data_len,
4268                              idata->hash, client->id, SILC_ID_CLIENT)) {
4269     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4270                                           SILC_STATUS_ERR_AUTH_FAILED);
4271     goto out;
4272   }
4273
4274   /* Client is now router operator */
4275   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4276
4277   /* Send UMODE change to primary router */
4278   if (!server->standalone)
4279     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4280                                   client->id, SILC_ID_CLIENT_LEN,
4281                                   client->mode);
4282
4283   /* Send reply to the sender */
4284   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4285                                         SILC_STATUS_OK);
4286
4287  out:
4288   silc_server_command_free(cmd);
4289 }
4290
4291 /* Server side command of CONNECT. Connects us to the specified remote
4292    server or router. */
4293
4294 SILC_SERVER_CMD_FUNC(connect)
4295 {
4296   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4297   SilcServer server = cmd->server;
4298   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4299   unsigned char *tmp, *host;
4300   unsigned int tmp_len;
4301   unsigned int port = SILC_PORT;
4302
4303   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4304
4305   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4306     goto out;
4307
4308   /* Check whether client has the permissions. */
4309   if (client->mode == SILC_UMODE_NONE) {
4310     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4311                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4312     goto out;
4313   }
4314
4315   if (server->server_type == SILC_ROUTER && 
4316       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4317     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4318                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4319     goto out;
4320   }
4321
4322   /* Get the remote server */
4323   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4324   if (!host) {
4325     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4326                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4327     goto out;
4328   }
4329
4330   /* Get port */
4331   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4332   if (tmp)
4333     SILC_GET32_MSB(port, tmp);
4334
4335   /* Create the connection. It is done with timeout and is async. */
4336   silc_server_create_connection(server, host, port);
4337
4338   /* Send reply to the sender */
4339   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4340                                         SILC_STATUS_OK);
4341
4342  out:
4343   silc_server_command_free(cmd);
4344 }
4345
4346 /* Server side of command BAN. This is used to manage the ban list of the
4347    channel. To add clients and remove clients from the ban list. */
4348
4349 SILC_SERVER_CMD_FUNC(ban)
4350 {
4351   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4352   SilcServer server = cmd->server;
4353   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4354   SilcBuffer packet;
4355   SilcChannelEntry channel;
4356   SilcChannelClientEntry chl;
4357   SilcChannelID *channel_id = NULL;
4358   unsigned char *id, *add, *del;
4359   unsigned int id_len, tmp_len;
4360   unsigned short ident = silc_command_get_ident(cmd->payload);
4361
4362   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4363     goto out;
4364
4365   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4366
4367   /* Get Channel ID */
4368   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4369   if (id) {
4370     channel_id = silc_id_payload_parse_id(id, id_len);
4371     if (!channel_id) {
4372       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4373                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4374       goto out;
4375     }
4376   }
4377
4378   /* Get channel entry. The server must know about the channel since the
4379      client is expected to be on the channel. */
4380   channel = silc_idlist_find_channel_by_id(server->local_list, 
4381                                            channel_id, NULL);
4382   if (!channel) {
4383     channel = silc_idlist_find_channel_by_id(server->global_list, 
4384                                              channel_id, NULL);
4385     if (!channel) {
4386       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4387                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4388       goto out;
4389     }
4390   }
4391
4392   /* Check whether this client is on the channel */
4393   if (!silc_server_client_on_channel(client, channel)) {
4394     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4395                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4396     goto out;
4397   }
4398
4399   /* Get entry to the channel user list */
4400   silc_list_start(channel->user_list);
4401   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4402     if (chl->client == client)
4403       break;
4404
4405   /* The client must be at least channel operator. */
4406   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4407     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4408                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4409     goto out;
4410   }
4411
4412   /* Get the new ban and add it to the ban list */
4413   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4414   if (add) {
4415     if (!channel->ban_list)
4416       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4417     else
4418       channel->ban_list = silc_realloc(channel->ban_list, 
4419                                        sizeof(*channel->ban_list) * 
4420                                        (tmp_len + 
4421                                         strlen(channel->ban_list) + 2));
4422     if (add[tmp_len - 1] == ',')
4423       add[tmp_len - 1] = '\0';
4424
4425     strncat(channel->ban_list, add, tmp_len);
4426     strncat(channel->ban_list, ",", 1);
4427   }
4428
4429   /* Get the ban to be removed and remove it from the list */
4430   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4431   if (del && channel->ban_list) {
4432     char *start, *end, *n;
4433
4434     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4435       silc_free(channel->ban_list);
4436       channel->ban_list = NULL;
4437     } else {
4438       start = strstr(channel->ban_list, del);
4439       if (start && strlen(start) >= tmp_len) {
4440         end = start + tmp_len;
4441         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4442         strncat(n, channel->ban_list, start - channel->ban_list);
4443         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4444                              end) - 1);
4445         silc_free(channel->ban_list);
4446         channel->ban_list = n;
4447       }
4448     }
4449   }
4450
4451   /* Send the BAN notify type to our primary router. */
4452   if (!server->standalone && (add || del))
4453     silc_server_send_notify_ban(server, server->router->connection,
4454                                 server->server_type == SILC_ROUTER ?
4455                                 TRUE : FALSE, channel, add, del);
4456
4457   /* Send the reply back to the client */
4458   if (channel->ban_list)
4459     packet = 
4460       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4461                                            SILC_STATUS_OK, ident, 2,
4462                                            2, id, id_len,
4463                                            3, channel->ban_list, 
4464                                            strlen(channel->ban_list) - 1);
4465   else
4466     packet = 
4467       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4468                                            SILC_STATUS_OK, ident, 1,
4469                                            2, id, id_len);
4470
4471   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4472                           packet->data, packet->len, FALSE);
4473     
4474   silc_buffer_free(packet);
4475
4476  out:
4477   if (channel_id)
4478     silc_free(channel_id);
4479   silc_server_command_free(cmd);
4480 }
4481
4482 /* Server side command of CLOSE. Closes connection to a specified server. */
4483  
4484 SILC_SERVER_CMD_FUNC(close)
4485 {
4486   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4487   SilcServer server = cmd->server;
4488   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4489   SilcServerEntry server_entry;
4490   SilcSocketConnection sock;
4491   unsigned char *tmp;
4492   unsigned int tmp_len;
4493   unsigned char *name;
4494   unsigned int port = SILC_PORT;
4495
4496   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4497
4498   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4499     goto out;
4500
4501   /* Check whether client has the permissions. */
4502   if (client->mode == SILC_UMODE_NONE) {
4503     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4504                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4505     goto out;
4506   }
4507
4508   /* Get the remote server */
4509   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4510   if (!name) {
4511     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4512                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4513     goto out;
4514   }
4515
4516   /* Get port */
4517   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4518   if (tmp)
4519     SILC_GET32_MSB(port, tmp);
4520
4521   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4522                                                  name, port, NULL);
4523   if (!server_entry) {
4524     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4525                                           SILC_STATUS_ERR_NO_SERVER_ID);
4526     goto out;
4527   }
4528
4529   /* Send reply to the sender */
4530   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4531                                         SILC_STATUS_OK);
4532
4533   /* Close the connection to the server */
4534   sock = (SilcSocketConnection)server_entry->connection;
4535   silc_server_free_sock_user_data(server, sock);
4536   silc_server_close_connection(server, sock);
4537   
4538  out:
4539   silc_server_command_free(cmd);
4540 }
4541
4542 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4543    active connections. */
4544  
4545 SILC_SERVER_CMD_FUNC(shutdown)
4546 {
4547   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4548   SilcServer server = cmd->server;
4549   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4550
4551   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4552
4553   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4554     goto out;
4555
4556   /* Check whether client has the permission. */
4557   if (client->mode == SILC_UMODE_NONE) {
4558     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4559                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4560     goto out;
4561   }
4562
4563   /* Send reply to the sender */
4564   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4565                                         SILC_STATUS_OK);
4566
4567   /* Then, gracefully, or not, bring the server down. */
4568   silc_server_stop(server);
4569   exit(0);
4570
4571  out:
4572   silc_server_command_free(cmd);
4573 }
4574  
4575 /* Server side command of LEAVE. Removes client from a channel. */
4576
4577 SILC_SERVER_CMD_FUNC(leave)
4578 {
4579   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4580   SilcServer server = cmd->server;
4581   SilcSocketConnection sock = cmd->sock;
4582   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4583   SilcChannelID *id = NULL;
4584   SilcChannelEntry channel;
4585   unsigned int len;
4586   unsigned char *tmp;
4587
4588   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4589
4590   /* Get Channel ID */
4591   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4592   if (!tmp) {
4593     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4594                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4595     goto out;
4596   }
4597   id = silc_id_payload_parse_id(tmp, len);
4598   if (!id) {
4599     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4600                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4601     goto out;
4602   }
4603
4604   /* Get channel entry */
4605   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4606   if (!channel) {
4607     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4608     if (!channel) {
4609       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4610                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4611       goto out;
4612     }
4613   }
4614
4615   /* Check whether this client is on the channel */
4616   if (!silc_server_client_on_channel(id_entry, channel)) {
4617     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4618                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4619     goto out;
4620   }
4621
4622   /* Notify routers that they should remove this client from their list
4623      of clients on the channel. Send LEAVE notify type. */
4624   if (!server->standalone)
4625     silc_server_send_notify_leave(server, server->router->connection,
4626                                   server->server_type == SILC_ROUTER ?
4627                                   TRUE : FALSE, channel, id_entry->id,
4628                                   SILC_ID_CLIENT_LEN);
4629
4630   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4631                                         SILC_STATUS_OK);
4632
4633   /* Remove client from channel */
4634   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4635                                            TRUE))
4636     /* If the channel does not exist anymore we won't send anything */
4637     goto out;
4638
4639   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4640     /* Re-generate channel key */
4641     silc_server_create_channel_key(server, channel, 0);
4642
4643     /* Send the channel key */
4644     silc_server_send_channel_key(server, NULL, channel, 
4645                                  server->server_type == SILC_ROUTER ? 
4646                                  FALSE : !server->standalone);
4647   }
4648
4649   silc_free(id);
4650
4651  out:
4652   if (id)
4653     silc_free(id);
4654   silc_server_command_free(cmd);
4655 }
4656
4657 /* Server side of command USERS. Resolves clients and their USERS currently
4658    joined on the requested channel. The list of Client ID's and their modes
4659    on the channel is sent back. */
4660
4661 SILC_SERVER_CMD_FUNC(users)
4662 {
4663   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4664   SilcServer server = cmd->server;
4665   SilcChannelEntry channel;
4666   SilcChannelID *id;
4667   SilcBuffer packet;
4668   unsigned char *channel_id;
4669   unsigned int channel_id_len;
4670   SilcBuffer client_id_list;
4671   SilcBuffer client_mode_list;
4672   unsigned char lc[4];
4673   unsigned int list_count = 0;
4674   unsigned short ident = silc_command_get_ident(cmd->payload);
4675
4676   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4677
4678   /* Get Channel ID */
4679   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4680   if (!channel_id) {
4681     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4682                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4683     goto out;
4684   }
4685   id = silc_id_payload_parse_id(channel_id, channel_id_len);
4686   if (!id) {
4687     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4688                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4689     goto out;
4690   }
4691
4692   /* If we are server and we don't know about this channel we will send
4693      the command to our router. If we know about the channel then we also
4694      have the list of users already. */
4695   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4696   if (!channel) {
4697     if (server->server_type == SILC_SERVER && !server->standalone &&
4698         !cmd->pending) {
4699       SilcBuffer tmpbuf;
4700       
4701       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4702       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4703       
4704       /* Send USERS command */
4705       silc_server_packet_send(server, server->router->connection,
4706                               SILC_PACKET_COMMAND, cmd->packet->flags,
4707                               tmpbuf->data, tmpbuf->len, TRUE);
4708       
4709       /* Reprocess this packet after received reply */
4710       silc_server_command_pending(server, SILC_COMMAND_USERS, 
4711                                   silc_command_get_ident(cmd->payload),
4712                                   silc_server_command_destructor,
4713                                   silc_server_command_users,
4714                                   silc_server_command_dup(cmd));
4715       cmd->pending = TRUE;
4716       silc_command_set_ident(cmd->payload, ident);
4717       
4718       silc_buffer_free(tmpbuf);
4719       silc_free(id);
4720       return;
4721     }
4722
4723     /* We are router and we will check the global list as well. */
4724     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4725     if (!channel) {
4726       /* Channel really does not exist */
4727       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4728                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4729       goto out;
4730     }
4731   }
4732
4733   /* Get the users list */
4734   silc_server_get_users_on_channel(server, channel, &client_id_list,
4735                                    &client_mode_list, &list_count);
4736
4737   /* List count */
4738   SILC_PUT32_MSB(list_count, lc);
4739
4740   /* Send reply */
4741   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4742                                                 SILC_STATUS_OK, ident, 4,
4743                                                 2, channel_id, channel_id_len,
4744                                                 3, lc, 4,
4745                                                 4, client_id_list->data,
4746                                                 client_id_list->len,
4747                                                 5, client_mode_list->data,
4748                                                 client_mode_list->len);
4749   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4750                           packet->data, packet->len, FALSE);
4751     
4752   silc_buffer_free(packet);
4753   silc_buffer_free(client_id_list);
4754   silc_buffer_free(client_mode_list);
4755   silc_free(id);
4756
4757  out:
4758   silc_server_command_free(cmd);
4759 }