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