updates.
[silc.git] / lib / silcclient / client_keyagr.c
index e4a6a25c7ff260e9e54a54bb5fbafef9989de41c..41c6edff3091daadfba0ceda553133799988e920 100644 (file)
@@ -36,12 +36,13 @@ SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start);
 struct SilcClientKeyAgreementStruct {
   SilcClient client;
   SilcClientConnection conn;
-  int fd;                              /* Listening/connection socket */
-  SilcSocketConnection sock;           /* Remote socket connection */
-  SilcClientEntry client_entry;                /* Destination client */
-  SilcKeyAgreementCallback completion; /* Key agreement completion */
-  void *context;                       /* User context */
-  SilcTask timeout;                    /* Timeout task */
+  int fd;                                /* Listening/connection socket */
+  SilcSocketConnection sock;             /* Remote socket connection */
+  SilcClientEntry client_entry;                  /* Destination client */
+  SilcKeyAgreementCallback completion;   /* Key agreement completion */
+  void *context;                         /* User context */
+  SilcTask timeout;                      /* Timeout task */
+  SilcClientKEInternalContext *proto_ctx; /* Key Exchange protocol context */
 };
 
 /* Packet sending function used by the SKE in the key agreement process. */
@@ -151,7 +152,7 @@ SILC_TASK_CALLBACK(silc_client_process_key_agreement)
 
   sock = silc_net_accept_connection(ke->fd);
   if (sock < 0) {
-    client->ops->say(client, conn, 
+    client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
                     "Could not accept key agreement connection: ", 
                     strerror(errno));
     ke->client_entry->ke = NULL;
@@ -179,7 +180,7 @@ SILC_TASK_CALLBACK(silc_client_process_key_agreement)
   /* Perform name and address lookups for the remote host. */
   silc_net_check_host_by_sock(sock, &newsocket->hostname, &newsocket->ip);
   if (!newsocket->hostname && !newsocket->ip) {
-    client->ops->say(client, conn, 
+    client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
                     "Could not resolve the remote IP or hostname");
     ke->client_entry->ke = NULL;
     ke->completion(ke->client, ke->conn, ke->client_entry, 
@@ -201,12 +202,13 @@ SILC_TASK_CALLBACK(silc_client_process_key_agreement)
      sent as context for the protocol. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   proto_ctx->client = client;
-  proto_ctx->sock = newsocket;
+  proto_ctx->sock = silc_socket_dup(newsocket);
   proto_ctx->rng = client->rng;
   proto_ctx->responder = TRUE;
   proto_ctx->context = context;
   proto_ctx->send_packet = silc_client_key_agreement_send_packet;
   proto_ctx->verify = silc_client_protocol_ke_verify_key;
+  ke->proto_ctx = proto_ctx;
 
   /* Prepare the connection for key exchange protocol. We allocate the
      protocol but will not start it yet. The connector will be the
@@ -242,6 +244,8 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
     silc_client_del_socket(ke->client, ke->sock);
     silc_socket_free(ke->sock);
   }
+  if (ke->proto_ctx && ke->proto_ctx->ske)
+    silc_ske_free(ke->proto_ctx->ske);
   ke->client_entry->ke = NULL;
   if (ke->fd)
     silc_task_unregister_by_fd(ke->client->io_queue, ke->fd);
@@ -279,6 +283,10 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
    If remote side decides to ignore the request the `completion' will be
    called after the specified timeout, `timeout_secs'. 
 
+   NOTE: If the `hostname' and the `port' was not provided the `completion'
+   will not be called at all since this does nothing more than sending
+   a packet to the remote host.
+
    NOTE: There can be only one active key agreement for one client entry.
    Before setting new one, the old one must be finished (it is finished
    after calling the completion callback) or the function 
@@ -308,7 +316,7 @@ void silc_client_send_key_agreement(SilcClient client,
     ke->fd = silc_net_create_server(port, hostname);
 
     if (ke->fd < 0) {
-      client->ops->say(client, conn, 
+      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR, 
                       "Cannot create listener on %s on port %d: %s", 
                       hostname, port, strerror(errno));
       completion(client, conn, client_entry, SILC_KEY_AGREEMENT_FAILURE,
@@ -416,13 +424,14 @@ SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start)
   SILC_LOG_DEBUG(("Start"));
 
   /* Check the socket status as it might be in error */
-  getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
+  silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
   if (opt != 0) {
     if (ctx->tries < 2) {
       /* Connection failed but lets try again */
-      client->ops->say(client, conn, "Could not connect to client %s: %s",
+      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                      "Could not connect to client %s: %s",
                       ctx->host, strerror(opt));
-      client->ops->say(client, conn, 
+      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
                       "Connecting to port %d of client %s resumed", 
                       ctx->port, ctx->host);
 
@@ -436,7 +445,8 @@ SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start)
       ctx->tries++;
     } else {
       /* Connection failed and we won't try anymore */
-      client->ops->say(client, conn, "Could not connect to client %s: %s",
+      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                      "Could not connect to client %s: %s",
                       ctx->host, strerror(opt));
       silc_schedule_unset_listen_fd(client->schedule, fd);
       silc_net_close_connection(fd);
@@ -556,12 +566,13 @@ void silc_client_perform_key_agreement_fd(SilcClient client,
      sent as context for the protocol. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   proto_ctx->client = client;
-  proto_ctx->sock = ke->sock;
+  proto_ctx->sock = silc_socket_dup(ke->sock);
   proto_ctx->rng = client->rng;
   proto_ctx->responder = FALSE;
   proto_ctx->context = ke;
   proto_ctx->send_packet = silc_client_key_agreement_send_packet;
   proto_ctx->verify = silc_client_protocol_ke_verify_key;
+  ke->proto_ctx = proto_ctx;
 
   /* Perform key exchange protocol. */
   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,