Added support for auto-passphrase authentication from the config
[silc.git] / lib / silcclient / client.c
index f54fd256815f69a781a7e50cff38f44d00399ee8..e5ad7feda4699575e5cf7b9bfd1316316bbc64b0 100644 (file)
@@ -103,8 +103,8 @@ int silc_client_init(SilcClient client)
   SILC_LOG_DEBUG(("Initializing client"));
 
   /* Initialize hash functions for client to use */
-  silc_hash_alloc("md5", &client->internal->md5hash);
-  silc_hash_alloc("sha1", &client->internal->sha1hash);
+  silc_hash_alloc("md5", &client->md5hash);
+  silc_hash_alloc("sha1", &client->sha1hash);
 
   /* Initialize none cipher */
   silc_cipher_alloc("none", &client->internal->none_cipher);
@@ -386,12 +386,14 @@ static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
 
   SILC_LOG_DEBUG(("Start"));
 
-  /* XXX We should most likely use the resolved host name instead of the
-     one user provided for us. */
-  silc_free(conn->sock->hostname);
-  conn->sock->hostname = strdup(conn->remote_host);
+  if (conn->sock->hostname) {
+    silc_free(conn->remote_host);
+    conn->remote_host = strdup(conn->sock->hostname);
+  } else {
+    conn->sock->hostname = strdup(conn->remote_host);
+  }
   if (!conn->sock->ip)
-    conn->sock->ip = strdup(conn->remote_host);
+    conn->sock->ip = strdup(conn->sock->hostname);
   conn->sock->port = conn->remote_port;
 
   /* Allocate internal Key Exchange context. This is sent to the
@@ -459,8 +461,8 @@ void silc_client_start_key_exchange(SilcClient client,
                          conn, client->schedule);
 }
 
-/* Callback called when error has occurred during connecting to the server.
-   The `connect' client operation will be called. */
+/* Callback called when error has occurred during connecting (KE) to
+   the server.  The `connect' client operation will be called. */
 
 SILC_TASK_CALLBACK(silc_client_connect_failure)
 {
@@ -475,6 +477,20 @@ SILC_TASK_CALLBACK(silc_client_connect_failure)
   silc_free(ctx);
 }
 
+/* Callback called when error has occurred during connecting (auth) to
+   the server.  The `connect' client operation will be called. */
+
+SILC_TASK_CALLBACK(silc_client_connect_failure_auth)
+{
+  SilcClientConnAuthInternalContext *ctx =
+    (SilcClientConnAuthInternalContext *)context;
+  SilcClient client = (SilcClient)ctx->client;
+
+  client->internal->ops->connect(client, ctx->sock->user_data, 
+                                SILC_CLIENT_CONN_ERROR);
+  silc_free(ctx);
+}
+
 /* Start of the connection to the remote server. This is called after
    succesful TCP/IP connection has been established to the remote host. */
 
@@ -591,6 +607,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
   silc_protocol_free(protocol);
   if (ctx->packet)
     silc_packet_context_free(ctx->packet);
+  ctx->packet = NULL;
   silc_free(ctx);
   sock->protocol = NULL;
 
@@ -623,7 +640,21 @@ void silc_client_resolve_auth_method(bool success,
 
   proto_ctx->auth_meth = auth_meth;
 
-  if (auth_data && auth_data_len) {
+  if (success && auth_data && auth_data_len) {
+
+    /* Passphrase must be UTF-8 encoded, if it isn't encode it */
+    if (auth_meth == SILC_AUTH_PASSWORD && 
+       !silc_utf8_valid(auth_data, auth_data_len)) {
+      int payload_len = 0;
+      unsigned char *autf8 = NULL;
+      payload_len = silc_utf8_encoded_len(auth_data, auth_data_len, 
+                                         SILC_STRING_ASCII);
+      autf8 = silc_calloc(payload_len, sizeof(*autf8));
+      auth_data_len = silc_utf8_encode(auth_data, auth_data_len, 
+                                      SILC_STRING_ASCII, autf8, payload_len);
+      auth_data = autf8;
+    }
+
     proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
     proto_ctx->auth_data_len = auth_data_len;
   }
@@ -759,7 +790,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
 
   /* Notify application of failure */
   silc_schedule_task_add(client->schedule, ctx->sock->sock,
-                        silc_client_connect_failure, ctx,
+                        silc_client_connect_failure_auth, ctx,
                         0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
 
@@ -958,13 +989,15 @@ void silc_client_packet_parse_type(SilcClient client,
   SilcBuffer buffer = packet->buffer;
   SilcPacketType type = packet->type;
 
-  SILC_LOG_DEBUG(("Parsing packet type %d", type));
+  SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type)));
 
   /* Parse the packet type */
   switch(type) {
+
   case SILC_PACKET_DISCONNECT:
     silc_client_disconnected_by_server(client, sock, buffer);
     break;
+
   case SILC_PACKET_SUCCESS:
     /*
      * Success received for something. For now we can have only
@@ -974,6 +1007,7 @@ void silc_client_packet_parse_type(SilcClient client,
     if (sock->protocol)
       silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
     break;
+
   case SILC_PACKET_FAILURE:
     /*
      * Failure received for some protocol. Set the protocol state to 
@@ -982,6 +1016,7 @@ void silc_client_packet_parse_type(SilcClient client,
      */
     silc_client_process_failure(client, sock, packet);
     break;
+
   case SILC_PACKET_REJECT:
     break;
 
@@ -1005,6 +1040,7 @@ void silc_client_packet_parse_type(SilcClient client,
      */
     silc_client_channel_message(client, sock, packet);
     break;
+
   case SILC_PACKET_CHANNEL_KEY:
     /*
      * Received key for a channel. By receiving this key the client will be
@@ -1020,12 +1056,21 @@ void silc_client_packet_parse_type(SilcClient client,
      */
     silc_client_private_message(client, sock, packet);
     break;
+
   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
     /*
      * Received private message key
      */
     break;
 
+  case SILC_PACKET_COMMAND:
+    /*
+     * Received command packet, a special case since normally client
+     * does not receive commands.
+     */
+    silc_client_command_process(client, sock, packet);
+    break;
+
   case SILC_PACKET_COMMAND_REPLY:
     /*
      * Recived reply for a command
@@ -1092,6 +1137,7 @@ void silc_client_packet_parse_type(SilcClient client,
                      "protocol active, packet dropped."));
     }
     break;
+
   case SILC_PACKET_KEY_EXCHANGE_2:
     if (sock->protocol && sock->protocol->protocol && 
        (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||