Added connection authentication request support.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 14 Jan 2007 15:31:35 +0000 (15:31 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 14 Jan 2007 15:31:35 +0000 (15:31 +0000)
Fixed channel reference counting.

13 files changed:
lib/silcclient/client.c
lib/silcclient/client.h
lib/silcclient/client_channel.c
lib/silcclient/client_channel.h
lib/silcclient/client_connect.c
lib/silcclient/client_connect.h
lib/silcclient/client_ftp.c
lib/silcclient/client_internal.h
lib/silcclient/client_keyagr.c
lib/silcclient/client_notify.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/silcclient.h

index f89314419e6dc4c274da851483b349fefca8bc25..d46f081837a6bf03fa0f575c85e504f697cda547 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2006 Pekka Riikonen
+  Copyright (C) 1997 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -64,7 +64,6 @@ static void silc_client_connection_finished(SilcFSMThread fsm,
   silc_fsm_free(fsm);
 }
 
-
 /* Packet FSM thread destructor */
 
 static void silc_client_packet_destructor(SilcFSMThread thread,
@@ -101,7 +100,6 @@ static SilcBool silc_client_packet_receive(SilcPacketEngine engine,
   case SILC_PACKET_KEY_EXCHANGE_2:
   case SILC_PACKET_REKEY_DONE:
   case SILC_PACKET_CONNECTION_AUTH:
-  case SILC_PACKET_CONNECTION_AUTH_REQUEST:
     return FALSE;
     break;
   }
@@ -307,7 +305,7 @@ SILC_FSM_STATE(silc_client_connection_st_packet)
 
   case SILC_PACKET_FTP:
     /* File transfer packet */
-    //    silc_client_ftp(client, conn, packet);
+//    silc_fsm_next(fsm, silc_client_ftp);
     break;
 
   case SILC_PACKET_CHANNEL_KEY:
@@ -356,9 +354,8 @@ SILC_FSM_STATE(silc_client_connection_st_packet)
     break;
 
   case SILC_PACKET_CONNECTION_AUTH_REQUEST:
-    /* Reply to connection authentication request to resolve authentication
-       method from server. */
-    //    silc_client_connection_auth_request(client, conn, packet);
+    /** Connection auth resolve reply */
+    silc_fsm_next(fsm, silc_client_connect_auth_request);
     break;
 
   case SILC_PACKET_REKEY:
@@ -427,7 +424,6 @@ SILC_FSM_STATE(silc_client_connection_st_close)
   silc_packet_stream_destroy(conn->stream);
 
   SILC_LOG_DEBUG(("Finishing connection machine"));
-
   SILC_FSM_FINISH;
 }
 
@@ -857,114 +853,6 @@ void silc_client_close_connection(SilcClient client,
   }
 }
 
-#if 0
-/* Processes incoming connection authentication method request packet.
-   It is a reply to our previously sent request. The packet can be used
-   to resolve the authentication method for the current session if the
-   client does not know it beforehand. */
-
-void silc_client_connection_auth_request(SilcClient client,
-                                        SilcClientConnection conn,
-                                        SilcPacketContext *packet)
-{
-  SilcClientConnection conn = (SilcClientConnection)sock->user_data;
-  SilcUInt16 conn_type, auth_meth;
-  int ret;
-
-  /* If we haven't send our request then ignore this one. */
-  if (!conn->internal->connauth)
-    return;
-
-  /* Parse the payload */
-  ret = silc_buffer_unformat(packet->buffer,
-                            SILC_STR_UI_SHORT(&conn_type),
-                            SILC_STR_UI_SHORT(&auth_meth),
-                            SILC_STR_END);
-  if (ret == -1)
-    auth_meth = SILC_AUTH_NONE;
-
-  /* Call the request callback to notify application for received
-     authentication method information. */
-  if (conn->internal->connauth->callback)
-    (*conn->internal->connauth->callback)(client, conn, auth_meth,
-                                         conn->internal->connauth->context);
-
-  silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout);
-
-  silc_free(conn->internal->connauth);
-  conn->internal->connauth = NULL;
-}
-
-/* Timeout task callback called if the server does not reply to our
-   connection authentication method request in the specified time interval. */
-
-SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
-{
-  SilcClientConnection conn = (SilcClientConnection)context;
-  SilcClient client = conn->client;
-
-  if (!conn->internal->connauth)
-    return;
-
-  /* Call the request callback to notify application */
-  if (conn->internal->connauth->callback)
-    (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE,
-                                         conn->internal->connauth->context);
-
-  silc_free(conn->internal->connauth);
-  conn->internal->connauth = NULL;
-}
-
-/* This function can be used to request the current authentication method
-   from the server. This may be called when connecting to the server
-   and the client library requests the authentication data from the
-   application. If the application does not know the current authentication
-   method it can request it from the server using this function.
-   The `callback' with `context' will be called after the server has
-   replied back with the current authentication method. */
-
-void
-silc_client_request_authentication_method(SilcClient client,
-                                         SilcClientConnection conn,
-                                         SilcConnectionAuthRequest callback,
-                                         void *context)
-{
-  SilcClientConnAuthRequest connauth;
-  SilcBuffer packet;
-
-  assert(client && conn);
-  connauth = silc_calloc(1, sizeof(*connauth));
-  connauth->callback = callback;
-  connauth->context = context;
-
-  if (conn->internal->connauth)
-    silc_free(conn->internal->connauth);
-
-  conn->internal->connauth = connauth;
-
-  /* Assemble the request packet and send it to the server */
-  packet = silc_buffer_alloc(4);
-  silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
-  silc_buffer_format(packet,
-                    SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
-                    SILC_STR_UI_SHORT(SILC_AUTH_NONE),
-                    SILC_STR_END);
-  silc_client_packet_send(client, conn->sock,
-                         SILC_PACKET_CONNECTION_AUTH_REQUEST,
-                         NULL, 0, NULL, NULL,
-                         packet->data, packet->len, FALSE);
-  silc_buffer_free(packet);
-
-  /* Register a timeout in case server does not reply anything back. */
-  connauth->timeout =
-    silc_schedule_task_add(client->schedule, conn->sock->sock,
-                          silc_client_request_authentication_method_timeout,
-                          conn,
-                          client->internal->params->connauth_request_secs, 0,
-                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-}
-#endif /* 0 */
-
 /* Allocates new client object. This has to be done before client may
    work. After calling this one must call silc_client_init to initialize
    the client. The `application' is application specific user data pointer
@@ -997,9 +885,6 @@ SilcClient silc_client_alloc(SilcClientOperations *ops,
   if (params)
     memcpy(new_client->internal->params, params, sizeof(*params));
 
-  if (!new_client->internal->params->connauth_request_secs)
-    new_client->internal->params->connauth_request_secs = 2;
-
   new_client->internal->params->
     nickname_format[sizeof(new_client->internal->
                           params->nickname_format) - 1] = 0;
index ab56cfbba7073166cba3c6f1f648d8138ead549f..147dcbd1caa51338603e3c93eab895e50296f44b 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2006 Pekka Riikonen
+  Copyright (C) 1997 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -39,7 +39,7 @@ typedef struct SilcClientCommandReplyContextStruct
 typedef struct SilcChannelUserStruct *SilcChannelUser;
 typedef struct SilcClientInternalStruct *SilcClientInternal;
 typedef struct SilcClientConnectionInternalStruct
-                                          *SilcClientConnectionInternal;
+     *SilcClientConnectionInternal;
 typedef struct SilcChannelPrivateKeyStruct *SilcChannelPrivateKey;
 
 
index 59902d840c9e29bc99c20bccfd5d9bfe2d40be59..e7753b9400e8c99fec30b2043739ea3bd89c9c49 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2004, 2006 Pekka Riikonen
+  Copyright (C) 1997 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -701,6 +701,8 @@ SilcBool silc_client_add_to_channel(SilcClient client,
   if (silc_client_on_channel(channel, client_entry))
     return TRUE;
 
+  SILC_LOG_DEBUG(("Add client %s to channel", client_entry->nickname));
+
   chu = silc_calloc(1, sizeof(*chu));
   if (!chu)
     return FALSE;
@@ -731,10 +733,16 @@ SilcBool silc_client_remove_from_channel(SilcClient client,
   if (!chu)
     return FALSE;
 
+  SILC_LOG_DEBUG(("Remove client %s from channel", client_entry->nickname));
+
   silc_hash_table_del(chu->client->channels, chu->channel);
   silc_hash_table_del(chu->channel->user_list, chu->client);
   silc_free(chu);
 
+  /* If channel became empty, delete it */
+  if (!silc_hash_table_count(channel->user_list))
+    silc_client_del_channel(client, conn, channel);
+
   silc_client_unref_client(client, conn, client_entry);
   silc_client_unref_channel(client, conn, channel);
 
@@ -750,10 +758,20 @@ void silc_client_remove_from_channels(SilcClient client,
   SilcHashTableList htl;
   SilcChannelUser chu;
 
+  if (!silc_hash_table_count(client_entry->channels))
+    return;
+
+  SILC_LOG_DEBUG(("Remove client from all joined channels"));
+
   silc_hash_table_list(client_entry->channels, &htl);
   while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
     silc_hash_table_del(chu->client->channels, chu->channel);
     silc_hash_table_del(chu->channel->user_list, chu->client);
+
+    /* If channel became empty, delete it */
+    if (!silc_hash_table_count(chu->channel->user_list))
+      silc_client_del_channel(client, conn, chu->channel);
+
     silc_client_unref_client(client, conn, chu->client);
     silc_client_unref_channel(client, conn, chu->channel);
     silc_free(chu);
index d72e21897dbed687ef2d3f513fefc2fd5e91b523..ed590e07c20f808dfef7ee05ba38075a2703eb22 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2006 Pekka Riikonen
+  Copyright (C) 2006 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index b9267fb1854213890ab5d0cb7b37736e0a8b2b11..06215fb8c47f1c7f2d93ae08fbc892bdc799c36f 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2006 Pekka Riikonen
+  Copyright (C) 2006 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -278,21 +278,16 @@ static void silc_client_rekey_completion(SilcSKE ske,
 
 /* Callback called by application to return authentication data */
 
-static void silc_client_connect_auth_method(SilcBool success,
-                                           SilcAuthMethod auth_meth,
+static void silc_client_connect_auth_method(SilcAuthMethod auth_meth,
                                            void *auth, SilcUInt32 auth_len,
                                            void *context)
 {
   SilcFSMThread fsm = context;
   SilcClientConnection conn = silc_fsm_get_context(fsm);
 
-  conn->internal->params.auth_method = SILC_AUTH_NONE;
-
-  if (success) {
-    conn->internal->params.auth_method = auth_meth;
-    conn->internal->params.auth = auth;
-    conn->internal->params.auth_len = auth_len;
-  }
+  conn->internal->params.auth_method = auth_meth;
+  conn->internal->params.auth = auth;
+  conn->internal->params.auth_len = auth_len;
 
   SILC_FSM_CALL_CONTINUE(fsm);
 }
@@ -324,6 +319,42 @@ static void silc_client_connect_auth_completion(SilcConnAuth connauth,
   SILC_FSM_CALL_CONTINUE(fsm);
 }
 
+/********************** CONNECTION_AUTH_REQUEST packet **********************/
+
+/* Received connection authentication request packet.  We get the
+   required authentication method here. */
+
+SILC_FSM_STATE(silc_client_connect_auth_request)
+{
+  SilcClientConnection conn = fsm_context;
+  SilcPacket packet = state_context;
+  SilcUInt16 conn_type, auth_meth;
+
+  if (!conn->internal->auth_request) {
+    silc_packet_free(packet);
+    SILC_FSM_FINISH;
+  }
+
+  /* Parse the payload */
+  if (silc_buffer_unformat(&packet->buffer,
+                          SILC_STR_UI_SHORT(&conn_type),
+                          SILC_STR_UI_SHORT(&auth_meth),
+                          SILC_STR_END) < 0)
+    auth_meth = SILC_AUTH_NONE;
+
+  silc_packet_free(packet);
+
+  SILC_LOG_DEBUG(("Resolved authentication method: %s",
+                 (auth_meth == SILC_AUTH_NONE ? "none" :
+                  auth_meth == SILC_AUTH_PASSWORD ? "passphrase" :
+                  "public key")));
+  conn->internal->params.auth_method = auth_meth;
+
+  /* Continue authentication */
+  silc_fsm_continue_sync(&conn->internal->event_thread);
+  SILC_FSM_FINISH;
+}
+
 /*************************** Connect remote host ****************************/
 
 /* Connection timeout callback */
@@ -472,7 +503,7 @@ SILC_FSM_STATE(silc_client_st_connect_key_exchange)
     silc_fsm_next(fsm, silc_client_st_connect_setup_udp);
   else
     /** Run key exchange (TCP) */
-    silc_fsm_next(fsm, silc_client_st_connect_auth);
+    silc_fsm_next(fsm, silc_client_st_connect_auth_resolve);
 
   SILC_FSM_CALL(conn->internal->op = silc_ske_initiator(conn->internal->ske,
                                                        conn->stream,
@@ -521,13 +552,48 @@ SILC_FSM_STATE(silc_client_st_connect_setup_udp)
   silc_stream_destroy(old);
 
   /** Start authentication */
-  silc_fsm_next(fsm, silc_client_st_connect_auth);
+  silc_fsm_next(fsm, silc_client_st_connect_auth_resolve);
   SILC_FSM_CONTINUE;
 }
 
-/* Get authentication method to be used in authentication protocol */
+/* Resolved authentication method to be used in authentication protocol */
+
+SILC_FSM_STATE(silc_client_st_connect_auth_resolve)
+{
+  SilcClientConnection conn = fsm_context;
+
+  SILC_LOG_DEBUG(("Resolve authentication method"));
+
+  if (conn->internal->disconnected) {
+    /** Disconnected */
+    silc_fsm_next(fsm, silc_client_st_connect_error);
+    SILC_FSM_CONTINUE;
+  }
+
+  /* If authentication method and data is set, use them */
+  if (conn->internal->params.auth_set) {
+    /** Got authentication data */
+    silc_fsm_next(fsm, silc_client_st_connect_auth_start);
+    SILC_FSM_CONTINUE;
+  }
+
+  /* Send connection authentication request packet */
+  silc_packet_send_va(conn->stream,
+                     SILC_PACKET_CONNECTION_AUTH_REQUEST, 0,
+                     SILC_STR_UI_SHORT(SILC_CONN_CLIENT),
+                     SILC_STR_UI_SHORT(SILC_AUTH_NONE),
+                     SILC_STR_END);
+
+  /** Wait for authentication method */
+  conn->internal->auth_request = TRUE;
+  conn->internal->params.auth_method = SILC_AUTH_NONE;
+  silc_fsm_next_later(fsm, silc_client_st_connect_auth_data, 2, 0);
+  SILC_FSM_WAIT;
+}
+
+/* Get authentication data to be used in authentication protocol */
 
-SILC_FSM_STATE(silc_client_st_connect_auth)
+SILC_FSM_STATE(silc_client_st_connect_auth_data)
 {
   SilcClientConnection conn = fsm_context;
   SilcClient client = conn->client;
@@ -540,21 +606,16 @@ SILC_FSM_STATE(silc_client_st_connect_auth)
     SILC_FSM_CONTINUE;
   }
 
-  silc_fsm_next(fsm, silc_client_st_connect_auth_start);
+  conn->internal->auth_request = FALSE;
 
-  /* If authentication data not provided, ask from application */
-  if (!conn->internal->params.auth_set)
-    SILC_FSM_CALL(client->internal->ops->get_auth_method(
+  /** Get authentication data */
+  silc_fsm_next(fsm, silc_client_st_connect_auth_start);
+  SILC_FSM_CALL(client->internal->ops->get_auth_method(
                                    client, conn,
                                    conn->remote_host,
                                    conn->remote_port,
+                                   conn->internal->params.auth_method,
                                    silc_client_connect_auth_method, fsm));
-
-  if (conn->internal->params.auth_method == SILC_AUTH_PUBLIC_KEY)
-    conn->internal->params.auth = conn->private_key;
-
-  /* We have authentication data */
-  SILC_FSM_CONTINUE;
 }
 
 /* Start connection authentication with remote host */
@@ -573,6 +634,10 @@ SILC_FSM_STATE(silc_client_st_connect_auth_start)
     SILC_FSM_CONTINUE;
   }
 
+  /* We always use the same key for connection authentication and SKE */
+  if (conn->internal->params.auth_method == SILC_AUTH_PUBLIC_KEY)
+    conn->internal->params.auth = conn->private_key;
+
   /* Allocate connection authentication protocol */
   connauth = silc_connauth_alloc(conn->internal->schedule,
                                 conn->internal->ske,
index 0ee3c9cab313958527e8c0204bd6b4f05473b86e..9c825f39bea88a5256d634a3bf2d3cb09fb45419 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2006 Pekka Riikonen
+  Copyright (C) 2006 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 #ifndef CLIENT_CONNECT_H
 #define CLIENT_CONNECT_H
 
-/* States */
+SILC_FSM_STATE(silc_client_connect_auth_request);
 SILC_FSM_STATE(silc_client_st_connect);
 SILC_FSM_STATE(silc_client_st_connect_set_stream);
 SILC_FSM_STATE(silc_client_st_connect_key_exchange);
 SILC_FSM_STATE(silc_client_st_connect_setup_udp);
-SILC_FSM_STATE(silc_client_st_connect_auth);
+SILC_FSM_STATE(silc_client_st_connect_auth_resolve);
+SILC_FSM_STATE(silc_client_st_connect_auth_data);
 SILC_FSM_STATE(silc_client_st_connect_auth_start);
 SILC_FSM_STATE(silc_client_st_connected);
 SILC_FSM_STATE(silc_client_st_connect_error);
index 09aac70782c21c3f1854aef78c0ac50b6bc8ab20..ecb361c99615ae9c6243b6493c4b2a6ba7bd90fe 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 - 2004 Pekka Riikonen
+  Copyright (C) 2001 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -867,9 +867,7 @@ silc_client_file_send(SilcClient client,
   session->filepath = strdup(filepath);
   silc_dlist_add(conn->internal->ftp_sessions, session);
 
-  path = silc_calloc(strlen(filepath) + 9, sizeof(*path));
-  silc_strncat(path, strlen(filepath) + 9, "file://", 7);
-  silc_strncat(path, strlen(filepath) + 9, filepath, strlen(filepath));
+  silc_asprintf(&path, "file://%s", filepath);
 
   /* Allocate memory filesystem and put the file to it */
   if (strrchr(path, '/'))
@@ -1089,30 +1087,77 @@ SilcClientFileError silc_client_file_close(SilcClient client,
   return SILC_CLIENT_FILE_OK;
 }
 
-/* Callback called after remote client information has been resolved.
-   This will try to find existing session for the client entry.  If found
-   then continue with the key agreement protocol.  If not then it means
-   this is a file transfer request and we let the application know. */
+/************************** FTP Request Processing **************************/
 
-static void silc_client_ftp_resolve_cb(SilcClient client,
-                                      SilcClientConnection conn,
-                                      SilcClientEntry *clients,
-                                      SilcUInt32 clients_count,
-                                      void *context)
+/* Client resolving callback.  Continues with the FTP processing */
+
+static void silc_client_ftp_client_resolved(SilcClient client,
+                                           SilcClientConnection conn,
+                                           SilcStatus status,
+                                           SilcDList clients,
+                                           void *context)
 {
-  SilcPacketContext *packet = (SilcPacketContext *)context;
-  SilcClientFtpSession session;
-  SilcKeyAgreementPayload payload = NULL;
-  SilcClientEntry client_entry;
+  SilcFSMThread thread = context;
+  SilcPacket packet = silc_fsm_get_state_context(thread);
+
+  /* If no client found, ignore the packet, a silent error */
+  if (!clients) {
+    silc_packet_free(packet);
+    silc_fsm_finish(thread);
+    return;
+  }
+
+  /* Continue processing the packet */
+  SILC_FSM_CALL_CONTINUE(context);
+}
+
+/* Received file transfer packet.  Only file transfer requests get here.
+   The actual file transfer is handled by the SFTP library when we give it
+   the packet stream wrapped into SilcStream context. */
+
+SILC_FSM_STATE(silc_client_ftp)
+{
+  SilcClientConnection conn = fsm_context;
+  SilcClient client = conn->client;
+  SilcPacket packet = state_context;
+  SilcClientID remote_id;
+  SilcClientEntry remote_client;
+  SilcKeyAgreementPayload payload;
+  SilcUInt8 type;
   char *hostname;
   SilcUInt16 port;
+  int ret;
 
-  SILC_LOG_DEBUG(("Start"));
+  SILC_LOG_DEBUG(("Process file transfer packet"));
+
+  if (silc_buffer_len(&packet->buffer) < 1)
+    goto out;
 
-  if (!clients)
+  /* We support file transfer type number 1 (== SFTP) */
+  if (packet->buffer.data[0] != 0x01) {
+    SILC_LOG_DEBUG(("Unsupported file transfer type %d",
+                   packet->buffer.data[0]));
     goto out;
+  }
+
+  if (!silc_id_str2id(packet->src_id, packet->src_id_len,
+                     SILC_ID_CLIENT, &remote_id, sizeof(remote_id))) {
+    SILC_LOG_DEBUG(("Invalid client ID"));
+    goto out;
+  }
+
+  /* Check whether we know this client already */
+  remote_client = silc_client_get_client_by_id(client, conn, &remote_id);
+  if (!remote_client || !remote_client->nickname[0]) {
+    /** Resolve client info */
+    silc_client_unref_client(client, conn, remote_client);
+    SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
+                                        client, conn, &remote_id, NULL,
+                                        silc_client_ftp_client_resolved,
+                                        fsm));
+    /* NOT REACHED */
+  }
 
-  client_entry = clients[0];
 
   silc_dlist_start(conn->internal->ftp_sessions);
   while ((session = silc_dlist_get(conn->internal->ftp_sessions))
@@ -1123,10 +1168,12 @@ static void silc_client_ftp_resolve_cb(SilcClient client,
   }
 
   /* Parse the key agreement payload */
-  payload = silc_key_agreement_payload_parse(packet->buffer->data,
-                                            packet->buffer->len);
-  if (!payload)
+  payload = silc_key_agreement_payload_parse(packet->buffer->data + 1,
+                                            packet->buffer->len - 1);
+  if (!payload) {
+    SILC_LOG_DEBUG(("Invalid key agreement payload"));
     goto out;
+  }
 
   hostname = silc_key_agreement_get_hostname(payload);
   port = silc_key_agreement_get_port(payload);
@@ -1185,65 +1232,9 @@ static void silc_client_ftp_resolve_cb(SilcClient client,
                          session->filepath, session->monitor_context);
   }
 
- out:
-  if (payload)
-    silc_key_agreement_payload_free(payload);
-  silc_packet_context_free(packet);
-}
-
-/* Called when file transfer packet is received. This will parse the
-   packet and give it to the file transfer protocol. */
-
-void silc_client_ftp(SilcClient client,
-                    SilcSocketConnection sock,
-                    SilcPacketContext *packet)
-{
-  SilcClientConnection conn = (SilcClientConnection)sock->user_data;
-  SilcUInt8 type;
-  int ret;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  /* Parse the payload */
-  ret = silc_buffer_unformat(packet->buffer,
-                            SILC_STR_UI_CHAR(&type),
-                            SILC_STR_END);
-  if (ret == -1)
-    return;
-
-  /* We support only type number 1 (== SFTP) */
-  if (type != 1)
-    return;
 
-  silc_buffer_pull(packet->buffer, 1);
 
-  /* If we have active FTP session then give the packet directly to the
-     protocol processor. */
-  if (conn->internal->active_session) {
-    /* Give it to the SFTP */
-    if (conn->internal->active_session->server)
-      silc_sftp_server_receive_process(conn->internal->active_session->sftp,
-                                      sock, packet);
-    else
-      silc_sftp_client_receive_process(conn->internal->active_session->sftp,
-                                      sock, packet);
-  } else {
-    /* We don't have active session, resolve the remote client information
-       and then try to find the correct session. */
-    SilcClientID *remote_id;
-
-    if (packet->src_id_type != SILC_ID_CLIENT)
-      return;
-
-    remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
-                              SILC_ID_CLIENT);
-    if (!remote_id)
-      return;
-
-    /* Resolve the client */
-    silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
-                                        NULL, silc_client_ftp_resolve_cb,
-                                        silc_packet_context_dup(packet));
-    silc_free(remote_id);
-  }
+ out:
+  silc_packet_free(packet);
+  SILC_FSM_FINISH;
 }
index 75425acb0c10b8b63098b3c673dd01c1533d2261..c7bc0434a75c36009d737df2a02bbaa251bad56f 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2006 Pekka Riikonen
+  Copyright (C) 1997 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -49,39 +49,6 @@ typedef struct {
   void *completion_context;
 } *VerifyKeyContext;
 
-/* Context to hold the connection authentication request callbacks that
-   will be called when the server has replied back to our request about
-   current authentication method in the session. */
-typedef struct {
-  SilcConnectionAuthRequest callback;
-  void *context;
-  SilcTask timeout;
-} *SilcClientConnAuthRequest;
-
-/* Generic rekey context for connections */
-typedef struct {
-  /* Current sending encryption key, provided for re-key. The `pfs'
-     is TRUE if the Perfect Forward Secrecy is performed in re-key. */
-  unsigned char *send_enc_key;
-  SilcUInt32 enc_key_len;
-  int ske_group;
-  SilcBool pfs;
-  SilcUInt32 timeout;
-  void *context;
-} *SilcClientRekey;
-
-/* Internal context for connection process. This is needed as we
-   doing asynchronous connecting. */
-typedef struct {
-  SilcClient client;
-  SilcClientConnection conn;
-  SilcTask task;
-  int sock;
-  char *host;
-  int port;
-  void *context;
-} SilcClientInternalConnectContext;
-
 /* Structure to hold away messages set by user. This is mainly created
    for future extensions where away messages could be set according filters
    such as nickname and hostname. For now only one away message can
@@ -160,7 +127,7 @@ struct SilcClientConnectionInternalStruct {
   SilcClientConnectionParams params;    /* Connection parameters */
   SilcFSMStruct fsm;                    /* Connection FSM */
   SilcFSMThreadStruct event_thread;      /* FSM thread for events */
-  SilcFSMEventStruct wait_event;                /* Event signaller */
+  SilcFSMEventStruct wait_event;        /* Event signaller */
   SilcSchedule schedule;                /* Connection's scheduler */
   SilcMutex lock;                       /* Connection lock */
   SilcSKE ske;                          /* Key exchange protocol */
@@ -173,6 +140,7 @@ struct SilcClientConnectionInternalStruct {
   SilcBuffer remote_idp;                /* Remote ID Payload */
   SilcAsyncOperation op;                /* Protocols async operation */
   SilcAsyncOperation cop;               /* Async operation for application */
+  SilcHashTable attrs;                  /* Configured user attributes */
 
   SilcIDCache client_cache;             /* Client entry cache */
   SilcIDCache channel_cache;            /* Channel entry cache */
@@ -193,13 +161,12 @@ struct SilcClientConnectionInternalStruct {
   unsigned int registering        : 1;  /* Set when registering to network */
   unsigned int rekey_responder    : 1;   /* Set when rekeying as responder */
   unsigned int callback_called    : 1;   /* Set when connect callback called */
+  unsigned int auth_request       : 1;   /* Set when requesting auth method */
 
   SilcClientAway *away;
-  SilcClientConnAuthRequest connauth;
   SilcDList ftp_sessions;
   SilcUInt32 next_session_id;
   SilcClientFtpSession active_session;
-  SilcHashTable attrs;
   SilcHashTable privmsg_wait;           /* Waited private messages */
 };
 
index a0c791d81cbe90fb316f904e8095e4941a095137..3effa0569d56607d5c5c2b2a2ec889e2b67d77fe 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 - 2006 Pekka Riikonen
+  Copyright (C) 2001 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -186,7 +186,7 @@ static void silc_client_keyagr_completion(SilcSKE ske,
   silc_client_keyagr_free(client, conn, client_entry);
 }
 
-/* Starts key agreement as responder.  */
+/* Starts key agreement as responder. */
 
 static void silc_client_process_key_agreement(SilcClient client,
                                              SilcClientConnection conn,
index 90c184903c265959a8d1520f6c6496dd605fb976..7cdb688c5e0cbcadc544290eeb805be007569e8f 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2006 Pekka Riikonen
+  Copyright (C) 1997 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -75,7 +75,7 @@ static SilcBool silc_client_notify_wait_continue(SilcClient client,
   /* Continue after last command reply received */
   if (SILC_STATUS_IS_ERROR(status) || status == SILC_STATUS_OK ||
       status == SILC_STATUS_LIST_END)
-    SILC_FSM_CALL_CONTINUE(notify->fsm);
+    SILC_FSM_CALL_CONTINUE_SYNC(notify->fsm);
 
   return TRUE;
 }
@@ -471,10 +471,12 @@ SILC_FSM_STATE(silc_client_notify_signoff)
   SilcClient client = conn->client;
   SilcClientNotify notify = state_context;
   SilcNotifyPayload payload = notify->payload;
+  SilcPacket packet = notify->packet;
   SilcNotifyType type = silc_notify_get_type(payload);
   SilcArgumentPayload args = silc_notify_get_args(payload);
   SilcClientEntry client_entry;
-   unsigned char *tmp;
+  SilcChannelEntry channel;
+  unsigned char *tmp;
   SilcUInt32 tmp_len;
   SilcID id;
 
@@ -497,8 +499,19 @@ SILC_FSM_STATE(silc_client_notify_signoff)
   /* Notify application */
   NOTIFY(client, conn, type, client_entry, tmp);
 
+  /* Remove from channel */
+  if (packet->dst_id_type == SILC_ID_CHANNEL) {
+    if (silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL,
+                      &id.u.channel_id, sizeof(id.u.channel_id))) {
+      channel = silc_client_get_channel_by_id(client, conn, &id.u.channel_id);
+      if (channel) {
+       silc_client_remove_from_channel(client, conn, channel, client_entry);
+       silc_client_unref_channel(client, conn, channel);
+      }
+    }
+  }
+
   /* Delete client */
-  silc_client_remove_from_channels(client, conn, client_entry);
   silc_client_del_client(client, conn, client_entry);
   silc_client_unref_client(client, conn, client_entry);
 
index a10505566f57608c2d79d2461f0efa8b9a7be83c..91f35f3275c194e51d47a2d46491bde70d96ce8b 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2006 Pekka Riikonen
+  Copyright (C) 1997 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -119,9 +119,6 @@ static void silc_client_command_resolve_continue(SilcClient client,
   if (status != SILC_STATUS_OK)
     silc_fsm_next(&cmd->thread, silc_client_command_continue_error);
 
-  if (clients)
-    silc_dlist_uninit(clients);
-
   /* Continue with the command */
   SILC_FSM_CALL_CONTINUE(&cmd->thread);
 }
@@ -854,7 +851,8 @@ SILC_FSM_STATE(silc_client_command_list)
 {
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
-  SilcChannelEntry channel;
+  SilcClient client = conn->client;
+  SilcChannelEntry channel = NULL;
   SilcBuffer idp = NULL;
 
   if (cmd->argc == 2) {
@@ -871,6 +869,7 @@ SILC_FSM_STATE(silc_client_command_list)
                                1, 1, silc_buffer_datalen(idp));
 
   silc_buffer_free(idp);
+  silc_client_unref_channel(client, conn, channel);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -888,6 +887,7 @@ SILC_FSM_STATE(silc_client_command_topic)
 {
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
+  SilcClient client = conn->client;
   SilcChannelEntry channel;
   SilcBuffer idp;
   char *name;
@@ -934,6 +934,7 @@ SILC_FSM_STATE(silc_client_command_topic)
                                1, silc_buffer_datalen(idp));
 
   silc_buffer_free(idp);
+  silc_client_unref_channel(client, conn, channel);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -957,7 +958,7 @@ SILC_FSM_STATE(silc_client_command_invite)
   SilcClientConnection conn = cmd->conn;
   SilcClient client = conn->client;
   SilcClientEntry client_entry = NULL;
-  SilcChannelEntry channel;
+  SilcChannelEntry channel = NULL;
   SilcBuffer clidp, chidp, args = NULL;
   SilcPublicKey pubkey = NULL;
   SilcDList clients = NULL;
@@ -980,6 +981,7 @@ SILC_FSM_STATE(silc_client_command_invite)
     }
 
     channel = conn->current_channel;
+    silc_client_ref_channel(client, conn, channel);
   } else {
     name = cmd->argv[1];
 
@@ -1058,6 +1060,7 @@ SILC_FSM_STATE(silc_client_command_invite)
   silc_buffer_free(args);
   silc_free(nickname);
   silc_client_list_free(client, conn, clients);
+  silc_client_unref_channel(client, conn, channel);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -1280,7 +1283,8 @@ SILC_FSM_STATE(silc_client_command_join)
 {
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
-  SilcChannelEntry channel;
+  SilcClient client = conn->client;
+  SilcChannelEntry channel = NULL;
   SilcBuffer auth = NULL, cauth = NULL;
   char *name, *passphrase = NULL, *pu8, *cipher = NULL, *hmac = NULL;
   int i, passphrase_len = 0;
@@ -1378,6 +1382,7 @@ SILC_FSM_STATE(silc_client_command_join)
   if (passphrase)
     memset(passphrase, 0, strlen(passphrase));
   silc_free(passphrase);
+  silc_client_unref_channel(client, conn, channel);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -1387,6 +1392,7 @@ SILC_FSM_STATE(silc_client_command_join)
   SILC_FSM_CONTINUE;
 
  out:
+  silc_client_unref_channel(client, conn, channel);
   SILC_FSM_FINISH;
 }
 
@@ -1574,7 +1580,7 @@ SILC_FSM_STATE(silc_client_command_cmode)
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
   SilcClient client = conn->client;
-  SilcChannelEntry channel;
+  SilcChannelEntry channel = NULL;
   SilcBuffer chidp, auth = NULL, pk = NULL;
   unsigned char *name, *cp, modebuf[4], tmp[4], *arg = NULL;
   SilcUInt32 mode, add, type, len, arg_len = 0;
@@ -1594,6 +1600,7 @@ SILC_FSM_STATE(silc_client_command_cmode)
     }
 
     channel = conn->current_channel;
+    silc_client_ref_channel(client, conn, channel);
   } else {
     name = cmd->argv[1];
 
@@ -1847,6 +1854,7 @@ SILC_FSM_STATE(silc_client_command_cmode)
   silc_buffer_free(chidp);
   silc_buffer_free(auth);
   silc_buffer_free(pk);
+  silc_client_unref_channel(client, conn, channel);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -1856,6 +1864,7 @@ SILC_FSM_STATE(silc_client_command_cmode)
   SILC_FSM_CONTINUE;
 
  out:
+  silc_client_unref_channel(client, conn, channel);
   SILC_FSM_FINISH;
 }
 
@@ -1868,7 +1877,7 @@ SILC_FSM_STATE(silc_client_command_cumode)
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
   SilcClient client = conn->client;
-  SilcChannelEntry channel;
+  SilcChannelEntry channel = NULL;
   SilcChannelUser chu;
   SilcClientEntry client_entry;
   SilcBuffer clidp, chidp, auth = NULL;
@@ -1892,6 +1901,7 @@ SILC_FSM_STATE(silc_client_command_cumode)
     }
 
     channel = conn->current_channel;
+    silc_client_ref_channel(client, conn, channel);
   } else {
     name = cmd->argv[1];
 
@@ -2026,6 +2036,7 @@ SILC_FSM_STATE(silc_client_command_cumode)
     silc_buffer_free(auth);
   silc_free(nickname);
   silc_client_list_free(client, conn, clients);
+  silc_client_unref_channel(client, conn, channel);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -2035,6 +2046,7 @@ SILC_FSM_STATE(silc_client_command_cumode)
   SILC_FSM_CONTINUE;
 
  out:
+  silc_client_unref_channel(client, conn, channel);
   silc_client_list_free(client, conn, clients);
   silc_free(nickname);
   SILC_FSM_FINISH;
@@ -2049,7 +2061,7 @@ SILC_FSM_STATE(silc_client_command_kick)
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
   SilcClient client = conn->client;
-  SilcChannelEntry channel;
+  SilcChannelEntry channel = NULL;
   SilcBuffer idp, idp2;
   SilcClientEntry target;
   SilcDList clients = NULL;
@@ -2116,6 +2128,7 @@ SILC_FSM_STATE(silc_client_command_kick)
   silc_buffer_free(idp2);
   silc_free(nickname);
   silc_client_list_free(client, conn, clients);
+  silc_client_unref_channel(client, conn, channel);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -2125,6 +2138,7 @@ SILC_FSM_STATE(silc_client_command_kick)
   SILC_FSM_CONTINUE;
 
  out:
+  silc_client_unref_channel(client, conn, channel);
   silc_free(nickname);
   SILC_FSM_FINISH;
 }
@@ -2262,6 +2276,7 @@ SILC_FSM_STATE(silc_client_command_ban)
 {
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
+  SilcClient client = conn->client;
   SilcChannelEntry channel;
   SilcBuffer chidp, args = NULL;
   char *name, *ban = NULL;
@@ -2283,6 +2298,7 @@ SILC_FSM_STATE(silc_client_command_ban)
     }
 
     channel = conn->current_channel;
+    silc_client_ref_channel(client, conn, channel);
   } else {
     name = cmd->argv[1];
 
@@ -2332,6 +2348,7 @@ SILC_FSM_STATE(silc_client_command_ban)
 
   silc_buffer_free(chidp);
   silc_buffer_free(args);
+  silc_client_unref_channel(client, conn, channel);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -2446,6 +2463,7 @@ SILC_FSM_STATE(silc_client_command_leave)
 {
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
+  SilcClient client = conn->client;
   SilcChannelEntry channel;
   SilcBuffer idp;
   char *name;
@@ -2488,6 +2506,8 @@ SILC_FSM_STATE(silc_client_command_leave)
   if (conn->current_channel == channel)
     conn->current_channel = NULL;
 
+  silc_client_unref_channel(client, conn, channel);
+
   /** Wait for command reply */
   silc_fsm_next(fsm, silc_client_command_reply_wait);
   SILC_FSM_CONTINUE;
index cf68fddd75776cc2f91df04893872259182fdfe1..c1c7b190c2436e2487320dcebc4b2cfc05b718db 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2006 Pekka Riikonen
+  Copyright (C) 1997 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -233,6 +233,8 @@ SILC_FSM_STATE(silc_client_command_reply_timeout)
   if (conn->internal->disconnected) {
     SILC_LOG_DEBUG(("Command %s canceled", silc_get_command_name(cmd->cmd)));
     silc_list_del(conn->internal->pending_commands, cmd);
+    if (!cmd->called)
+      ERROR_CALLBACK(SILC_STATUS_ERR_TIMEDOUT);
     SILC_FSM_FINISH;
   }
 
@@ -922,7 +924,7 @@ SILC_FSM_STATE(silc_client_command_reply_kill)
   /* Notify application */
   silc_client_command_callback(cmd, client_entry);
 
-  /* Remove the client from all channels and free it */
+  /* Remove the client */
   if (client_entry) {
     silc_client_remove_from_channels(client, conn, client_entry);
     silc_client_del_client(client, conn, client_entry);
@@ -1814,7 +1816,7 @@ SILC_FSM_STATE(silc_client_command_reply_users)
   SilcUInt16 idp_len, mode;
   SilcHashTableList htl;
   SilcBufferStruct client_id_list, client_mode_list;
-  SilcChannelEntry channel;
+  SilcChannelEntry channel = NULL;
   SilcClientEntry client_entry;
   SilcID id;
   int i;
@@ -1858,6 +1860,7 @@ SILC_FSM_STATE(silc_client_command_reply_users)
   /* Resolve users we do not know about */
   if (!cmd->resolved) {
     cmd->resolved = TRUE;
+    silc_client_unref_channel(client, conn, channel);
     SILC_FSM_CALL(silc_client_get_clients_by_list(
                          client, conn, list_count, &client_id_list,
                          silc_client_command_reply_users_resolved, cmd));
@@ -1903,6 +1906,7 @@ SILC_FSM_STATE(silc_client_command_reply_users)
   silc_hash_table_list_reset(&htl);
 
  out:
+  silc_client_unref_channel(client, conn, channel);
   silc_fsm_next(fsm, silc_client_command_reply_processed);
   SILC_FSM_CONTINUE;
 }
index 69083194cebaddbe5760cd83e6d10e9208be9d1d..659301fc55bb30fe6ae7f2c9afc1e38a732b0f95 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2006 Pekka Riikonen
+  Copyright (C) 2000 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -427,18 +427,23 @@ typedef void (*SilcVerifyPublicKey)(SilcBool success, void *context);
  *
  * DESCRIPTION
  *
- *    Authentication method resolving callback. This is called by the
- *    application to return the resolved authentication method. The client
+ *    Authentication data resolving callback. This is called by the
+ *    application to return the resolved authentication data. The client
  *    library has called the get_auth_method client operation and given
- *    this function pointer as argument. The `success' will indicate whether
- *    the authentication method could be resolved. The `auth_meth' is the
- *    resolved authentication method. The `auth_data' and the `auth_data_len'
+ *    this function pointer as argument. The `auth_meth' is the selected
+ *    authentication method. The `auth_data' and the `auth_data_len'
  *    are the resolved authentication data. The `context' is the libary's
  *    context sent to the get_auth_method client operation.
  *
+ *    If the `auth_method' is SILC_AUTH_PASSWORD then `auth' and `auth_len'
+ *    is the passphrase and its length.  If it is SILC_AUTH_PUBLIC_KEY the
+ *    `auth' must be NULL.  The library will use the private key given as
+ *    argument to silc_client_connect_to_server, silc_client_connect_to_client
+ *    or silc_client_key_exchange.  If it is SILC_AUTH_NONE, both `auth' and
+ *    `auth_len' are ignored.
+ *
  ***/
-typedef void (*SilcGetAuthMeth)(SilcBool success,
-                               SilcAuthMethod auth_meth,
+typedef void (*SilcGetAuthMeth)(SilcAuthMethod auth_meth,
                                void *auth, SilcUInt32 auth_len,
                                void *context);
 
@@ -561,19 +566,26 @@ typedef struct {
                        SilcStatus error, va_list ap);
 
   /* Find authentication method and authentication data by hostname and
-     port. The hostname may be IP address as well. When the authentication
-     method has been resolved the `completion' callback with the found
-     authentication method and authentication data is called. The `conn'
-     may be NULL. */
+     port. The hostname may be IP address as well. The `auth_method' is
+     the authentication method the remote connection requires.  It is
+     however possible that remote accepts also some other authentication
+     method.  Application should use the method that may have been
+     configured for this connection.  If none has been configured it should
+     use the required `auth_method'.  If the `auth_method' is
+     SILC_AUTH_NONE, server does not require any authentication or the
+     required authentication method is not known.  The `completion'
+     callback must be called to deliver the chosen authentication method
+     and data. The `conn' may be NULL. */
   void (*get_auth_method)(SilcClient client, SilcClientConnection conn,
                          char *hostname, SilcUInt16 port,
+                         SilcAuthMethod auth_method,
                          SilcGetAuthMeth completion, void *context);
 
   /* Verifies received public key. The `conn_type' indicates which entity
-     (server, client etc.) has sent the public key. If user decides to trust
-     the application may save the key as trusted public key for later
-     use. The `completion' must be called after the public key has been
-     verified. */
+     (server or client) has sent the public key. If user decides to trust
+     the key the application may save the key as trusted public key for
+     later use. The `completion' must be called after the public key has
+     been verified. */
   void (*verify_public_key)(SilcClient client, SilcClientConnection conn,
                            SilcConnectionType conn_type,
                            SilcPublicKey public_key,
@@ -632,12 +644,6 @@ typedef struct {
      in the callbacks to protect application specific data. */
   SilcBool threads;
 
-  /* Connection authentication method request timeout. If server does not
-     reply back the current authentication method when we've requested it
-     in this time interval we'll assume the reply will not come at all.
-     If set to zero, the default value (2 seconds) will be used. */
-  unsigned int connauth_request_secs;
-
   /* Nickname format string. This can be used to order the client library
      to save the nicknames in the library in a certain format. Since
      nicknames are not unique in SILC it is possible to have multiple same
@@ -929,6 +935,7 @@ typedef struct {
  *    silc_client_connect_to_server(SilcClient client,
  *                                  SilcClientConnectionParams *params,
  *                                  SilcPublicKey public_key,
+ *                                  SilcPrivateKey private_key,
  *                                  char *remote_host, int port,
  *                                  SilcClientConnectCallback callback,
  *                                  void *context);
@@ -971,6 +978,7 @@ silc_client_connect_to_server(SilcClient client,
  *    silc_client_connect_to_client(SilcClient client,
  *                                  SilcClientConnectionParams *params,
  *                                  SilcPublicKey public_key,
+ *                                  SilcPrivateKey private_key,
  *                                  char *remote_host, int port,
  *                                  SilcClientConnectCallback callback,
  *                                  void *context);
@@ -1632,10 +1640,10 @@ SilcBool silc_client_del_channel_private_key(SilcClient client,
  * DESCRIPTION
  *
  *    Returns list of private keys associated to the `channel'.  The caller
- *    must free the returned list.  The pointers in the list may be
- *    used to delete the specific key by giving the pointer as argument to the
- *    function silc_client_del_channel_private_key.  Each entry in the list
- *    is SilcChannelPrivateKey.
+ *    must free the returned list with silc_dlist_uninit.  The pointers in
+ *    the list may be used to delete the specific key by giving the pointer
+ *    as argument to the function silc_client_del_channel_private_key.  Each
+ *    entry in the list is SilcChannelPrivateKey.
  *
  ***/
 SilcDList silc_client_list_channel_private_keys(SilcClient client,
@@ -1854,56 +1862,6 @@ void silc_client_set_away_message(SilcClient client,
                                  SilcClientConnection conn,
                                  char *message);
 
-/****f* silcclient/SilcClientAPI/SilcConnectionAuthRequest
- *
- * SYNOPSIS
- *
- *    typedef void (*SilcConnectionAuthRequest)(SilcClient client,
- *                                              SilcClientConnection conn,
- *                                              SilcAuthMethod auth_meth,
- *                                              void *context);
- *
- * DESCRIPTION
- *
- *    Connection authentication method request callback. This is called
- *    by the client library after it has received the authentication method
- *    that the application requested by calling the function
- *    silc_client_request_authentication_method.
- *
- ***/
-typedef void (*SilcConnectionAuthRequest)(SilcClient client,
-                                         SilcClientConnection conn,
-                                         SilcAuthMethod auth_meth,
-                                         void *context);
-
-/****f* silcclient/SilcClientAPI/silc_client_request_authentication_method
- *
- * SYNOPSIS
- *
- *    void
- *    silc_client_request_authentication_method(SilcClient client,
- *                                              SilcClientConnection conn,
- *                                              SilcConnectionAuthRequest
- *                                                callback,
- *                                              void *context);
- *
- * DESCRIPTION
- *
- *    This function can be used to request the current authentication method
- *    from the server. This may be called when connecting to the server
- *    and the client library requests the authentication data from the
- *    application. If the application does not know the current authentication
- *    method it can request it from the server using this function.
- *    The `callback' with `context' will be called after the server has
- *    replied back with the current authentication method.
- *
- ***/
-void
-silc_client_request_authentication_method(SilcClient client,
-                                         SilcClientConnection conn,
-                                         SilcConnectionAuthRequest callback,
-                                         void *context);
-
 /****d* silcclient/SilcClientAPI/SilcClientMonitorStatus
  *
  * NAME