updates.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 4 Sep 2001 11:52:09 +0000 (11:52 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 4 Sep 2001 11:52:09 +0000 (11:52 +0000)
26 files changed:
CHANGES
TODO
apps/irssi/src/fe-common/core/fe-common-core.c
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/client_ops.h
apps/irssi/src/silc/core/clientutil.c
apps/silcd/packet_receive.c
apps/silcd/protocol.c
apps/silcd/server.c
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h
configure.in.pre
doc/draft-riikonen-silc-ke-auth-04.nroff
doc/example_silcd.conf
lib/silcclient/client.c
lib/silcclient/client.h
lib/silcclient/client_keyagr.c
lib/silcclient/protocol.c
lib/silcclient/silcapi.h
lib/silccrypt/rsa.c
lib/silcmath/silcprimegen.c
lib/silcutil/silcmemory.c
lib/silcutil/silcnet.h
lib/silcutil/unix/silcunixnet.c
lib/silcutil/win32/silcwin32net.c
prepare

diff --git a/CHANGES b/CHANGES
index 1f3ac68090e59c40aa85aa55d4460bd3659a2b6b..839d642492ccc40b5c4231d38575721fe1c63e8a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,40 @@
+Tue Sep  4 12:39:17 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
+
+       * Changed the get_auth_methdod client operation to be asynchronous.
+         It can be async if the application resolves the authentication
+         method from the server during the negotiation.  Added new
+         SilcGetAuthMeth completion callback that the application will
+         call after resolving the authentication method.
+
+         Added function silc_client_request_authentication_method that
+         the application can use to resolve the authentication method
+         from the server.  Added also SilcConnectionAuthRequest callback
+         that the library will call after the server has replied.  The
+         application can call this function if it does not know the
+         current authentication method.
+
+         Affected files are lib/silcclient/client.c and 
+         lib/silcclient/silcapi.h.
+
+       * The Irssi SILC client now automatically resolves the authentication
+         method incase any configuration information is not present (and
+         currently there never is).  The affected file is
+         irssi/src/silc/core/client_ops.c.
+
+       * Fixed public key authentication from the client library.
+         Affected file lib/silcclient/protocol.c.  Changed also the
+         protocol specification about the public key authentication in
+         the connection authentication protocol.  The actual data to be
+         signed is now computed with a hash function before signing.
+
+       * Fixed the public key authentication from the server as well.
+         Affected file silcd/protocol.c.
+
+       * Removed the mlock()'s from the memory allocation routines.
+         Affected file lib/silcutil/silcmemory.c.  The ./configure does
+         not check anymore for the mlock().  Affected file is
+         configure.in.pre.
+
 Mon Sep  3 20:09:59 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed the lib/silcmath/mpi/mpi.h to always use 32-bit data
@@ -8,6 +45,16 @@ Mon Sep  3 20:09:59 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
        * Do not check for threads at all on BSD systems.  Affected
          file configure.in.pre.
 
+       * Removed -n and -h options from the Irssi SILC Client since
+         they are not used in silc.
+
+       * Fixed the prime generation to assure that the first digit
+         of the generated random number is not zero since our conversion
+         routines does not like number strings that starts with zero
+         digit.  If zero digit is seen the random number is regenerated.
+         This caused some corrupted RSA keys when the zero first digit
+         was met.  Affected file lib/silcmath/silcprimegen.c.
+
 Sun Sep  2 17:17:24 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed WIN32 configuration in the ./configure script.
diff --git a/TODO b/TODO
index a2bdc1cdd608cf9cbdddb68026f658a6196c4c4c..ce43e4d3592ca7b18bd753198153a23ab37b72e8 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,15 +1,6 @@
 TODO/bugs in Irssi SILC client
 ==============================
 
- o If the configuration for a server connection does not exist then 
-   resolve the authentication method always from the server.  Otherwise
-   password and/or public key auth with server does not work since it
-   now assumes that config exists or NONE is used.
-
- o -n and -c options does not work.
-
- o Switching servers while on channel is supposed to crash the client?
-
  o Add local command to switch the channel's private key when channel has
    several private keys.  Currently sending channel messages with many
    keys is not possible because changing the key is not possible by the
@@ -88,9 +79,6 @@ TODO/bugs In SILC Libraries
 
  o Some ./prepare problems with latest autoconf and automake.
 
- o Remove the mlock() stuff from the lib/silcutil/silcmemory.c, they
-   are redundant.
-
  o Compression routines are missing.  The protocol supports packet
    compression thus it must be implemented.  SILC Comp API must be
    defined.  zlib package is already included into the lib dir (in CVS,
index 8cfb3a85d0eede745bde7653935fa5f7ac2ccd7b..248369057f595da7264b12081a421e29f223eecb 100644 (file)
@@ -123,8 +123,10 @@ void fe_common_core_init(void)
                { "password", 'w', POPT_ARG_STRING, &autocon_password, 0, "Autoconnect password", "SERVER" },
                { "port", 'p', POPT_ARG_INT, &autocon_port, 0, "Autoconnect port", "PORT" },
                { "noconnect", '!', POPT_ARG_NONE, &no_autoconnect, 0, "Disable autoconnecting", NULL },
+               /*
                { "nick", 'n', POPT_ARG_STRING, &cmdline_nick, 0, "Specify nick to use", NULL },
                { "hostname", 'h', POPT_ARG_STRING, &cmdline_hostname, 0, "Specify host name to use", NULL },
+               */
                { NULL, '\0', 0, NULL }
        };
 
index 6da1a80b81a9f9fef5d5b2b4180f9d100690cf76..9247a3c4f484b5305855ee17e89e36c8b34cc047 100644 (file)
@@ -961,7 +961,7 @@ void ask_passphrase_completion(const char *passphrase, void *context)
 }
 
 void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
-                               SilcAskPassphrase completion, void *context)
+                        SilcAskPassphrase completion, void *context)
 {
   AskPassphrase p = silc_calloc(1, sizeof(*p));
   p->completion = completion;
@@ -971,34 +971,69 @@ void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
                          "Passphrase: ", ENTRY_REDIRECT_FLAG_HIDDEN, p);
 }
 
+typedef struct {
+  SilcGetAuthMeth completion;
+  void *context;
+} *InternalGetAuthMethod;
+
+/* Callback called when we've received the authentication method information
+   from the server after we've requested it. This will get the authentication
+   data from the user if needed. */
+
+static void silc_get_auth_method_callback(SilcClient client,
+                                         SilcClientConnection conn,
+                                         SilcAuthMethod auth_meth,
+                                         void *context)
+{
+  InternalGetAuthMethod internal = (InternalGetAuthMethod)context;
+
+  switch (auth_meth) {
+  case SILC_AUTH_NONE:
+    /* No authentication required. */
+    (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+    break;
+  case SILC_AUTH_PASSWORD:
+    /* Do not ask the passphrase from user, the library will ask it if
+       we do not provide it here. */
+    (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+    break;
+  case SILC_AUTH_PUBLIC_KEY:
+    /* Do not get the authentication data now, the library will generate
+       it using our default key, if we do not provide it here. */
+    /* XXX In the future when we support multiple local keys and multiple
+       local certificates we will need to ask from user which one to use. */
+    (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+    break;
+  }
+
+  silc_free(internal);
+}
+
 /* Find authentication method and authentication data by hostname and
    port. The hostname may be IP address as well. The found authentication
    method and authentication data is returned to `auth_meth', `auth_data'
    and `auth_data_len'. The function returns TRUE if authentication method
    is found and FALSE if not. `conn' may be NULL. */
 
-int silc_get_auth_method(SilcClient client, SilcClientConnection conn,
-                        char *hostname, uint16 port,
-                        SilcProtocolAuthMeth *auth_meth,
-                        unsigned char **auth_data,
-                        uint32 *auth_data_len)
+void silc_get_auth_method(SilcClient client, SilcClientConnection conn,
+                         char *hostname, uint16 port,
+                         SilcGetAuthMeth completion, void *context)
 {
-  bool ret = TRUE;
-  SILC_SERVER_REC *server = conn ? conn->context : NULL;
+  InternalGetAuthMethod internal;
 
   /* XXX must resolve from configuration whether this connection has
      any specific authentication data */
 
-  *auth_meth = SILC_AUTH_NONE;
-  *auth_data = NULL;
-  *auth_data_len = 0;
-
-  if (ret == FALSE) {
-    printformat_module("fe-common/silc", server, NULL,
-                      MSGLEVEL_MODES, SILCTXT_AUTH_METH_UNRESOLVED);
-  }
+  /* If we do not have this connection configured by the user in a
+     configuration file then resolve the authentication method from the
+     server for this session. */
+  internal = silc_calloc(1, sizeof(*internal));
+  internal->completion = completion;
+  internal->context = context;
 
-  return ret;
+  silc_client_request_authentication_method(client, conn, 
+                                           silc_get_auth_method_callback,
+                                           internal);
 }
 
 /* Notifies application that failure packet was received.  This is called
index 620e72f89ddf5fb412c6b9a4436abc73a4f87726..38ccf656eb66cc421d23f69464cc14339b58e41e 100644 (file)
@@ -47,11 +47,9 @@ void silc_verify_public_key(SilcClient client, SilcClientConnection conn,
                            SilcSocketType conn_type, unsigned char *pk, 
                            uint32 pk_len, SilcSKEPKType pk_type,
                            SilcVerifyPublicKey completion, void *context);
-int silc_get_auth_method(SilcClient client, SilcClientConnection conn,
-                        char *hostname, uint16 port,
-                        SilcProtocolAuthMeth *auth_meth,
-                        unsigned char **auth_data,
-                        uint32 *auth_data_len);
+void silc_get_auth_method(SilcClient client, SilcClientConnection conn,
+                         char *hostname, uint16 port,
+                         SilcGetAuthMeth completion, void *context);
 void silc_failure(SilcClient client, SilcClientConnection conn, 
                  SilcProtocol protocol, void *failure);
 int silc_key_agreement(SilcClient client, SilcClientConnection conn,
index 463969670987bcd3850d10655285e069e134555f..6b19cc6f18e2a857e4592398e66562b886299a20 100644 (file)
@@ -537,6 +537,10 @@ int silc_client_load_keys(SilcClient client)
                                  SILC_PKCS_FILE_BIN) == FALSE)
       return FALSE;
 
+  silc_pkcs_alloc(client->public_key->name, &client->pkcs);
+  silc_pkcs_public_key_set(client->pkcs, client->public_key);
+  silc_pkcs_private_key_set(client->pkcs, client->private_key);
+
   return TRUE;
 }
 
index ba3c9cd7d42da6e582cc8f0720fe36407dc8782b..d88d05464e5872f1742d0306c381ced3d65272ac 100644 (file)
@@ -2135,7 +2135,7 @@ void silc_server_key_agreement(SilcServer server,
    actually be received at anytime but usually it is used only during
    the connection authentication phase. Now, protocol says that this packet
    can come from client or server, however, we support only this coming
-   from client and expect that server's always knows what authentication
+   from client and expect that server always knows what authentication
    method to use. */
 
 void silc_server_connection_auth_request(SilcServer server,
@@ -2144,7 +2144,7 @@ void silc_server_connection_auth_request(SilcServer server,
 {
   SilcServerConfigSectionClientConnection *client = NULL;
   uint16 conn_type;
-  int ret;
+  int ret, port;
   SilcAuthMethod auth_meth;
 
   SILC_LOG_DEBUG(("Start"));
@@ -2165,13 +2165,14 @@ void silc_server_connection_auth_request(SilcServer server,
 
   /* Get the authentication method for the client */
   auth_meth = SILC_AUTH_NONE;
+  port = server->sockets[server->sock]->port; /* Listenning port */
   client = silc_server_config_find_client_conn(server->config,
                                               sock->ip,
-                                              sock->port);
+                                              port);
   if (!client)
     client = silc_server_config_find_client_conn(server->config,
                                                 sock->hostname,
-                                                sock->port);
+                                                port);
   if (client)
     auth_meth = client->auth_meth;
          
index 543687a5f3f244195000096b2b152269a8012c79..53b31d9727f476cbbc81a7b41ad62131db3d6c2e 100644 (file)
@@ -712,7 +712,8 @@ silc_server_public_key_authentication(SilcServer server,
                     SILC_STR_END);
 
   /* Verify signature */
-  if (silc_pkcs_verify(pkcs, sign, sign_len, auth->data, auth->len)) {
+  if (silc_pkcs_verify_with_hash(pkcs, ske->prop->hash, sign, sign_len, 
+                                auth->data, auth->len)) {
     silc_pkcs_free(pkcs);
     silc_buffer_free(auth);
     return TRUE;
@@ -725,7 +726,6 @@ silc_server_public_key_authentication(SilcServer server,
 
 static int
 silc_server_get_public_key_auth(SilcServer server,
-                               SilcPublicKey pub_key,
                                unsigned char *auth_data,
                                uint32 *auth_data_len,
                                SilcSKE ske)
@@ -734,14 +734,7 @@ silc_server_get_public_key_auth(SilcServer server,
   SilcPKCS pkcs;
   SilcBuffer auth;
 
-  if (!pub_key)
-    return FALSE;
-
-  silc_pkcs_alloc(pub_key->name, &pkcs);
-  if (!silc_pkcs_public_key_set(pkcs, pub_key)) {
-    silc_pkcs_free(pkcs);
-    return FALSE;
-  }
+  pkcs = server->pkcs;
 
   /* Make the authentication data. Protocol says it is HASH plus
      KE Start Payload. */
@@ -754,13 +747,12 @@ silc_server_get_public_key_auth(SilcServer server,
                                          ske->start_payload_copy->len),
                     SILC_STR_END);
 
-  if (silc_pkcs_sign(pkcs, auth->data, auth->len, auth_data, auth_data_len)) {
-    silc_pkcs_free(pkcs);
+  if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data, 
+                              auth->len, auth_data, auth_data_len)) {
     silc_buffer_free(auth);
     return TRUE;
   }
 
-  silc_pkcs_free(pkcs);
   silc_buffer_free(auth);
   return FALSE;
 }
@@ -1081,8 +1073,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
            unsigned char sign[1024];
 
            /* Public key authentication */
-           silc_server_get_public_key_auth(server, ctx->auth_data,
-                                           sign, &auth_data_len,
+           silc_server_get_public_key_auth(server, sign, &auth_data_len,
                                            ctx->ske);
            auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
            memcpy(auth_data, sign, auth_data_len);
@@ -1545,7 +1536,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
     if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
       /* Error in protocol */
       protocol->state = SILC_PROTOCOL_STATE_ERROR;
-      silc_protocol_execute(protocol, server->schedule, 0, 0);
+      silc_protocol_execute(protocol, server->schedule, 0, 300000);
       return;
     }
 
index b65af7d6514377b9f7d0123326faabf28eb05fca..9047fa072da57f3fd3e853bbdc2e4fbc3e04afb7 100644 (file)
@@ -84,6 +84,9 @@ void silc_server_free(SilcServer server)
     if (server->rng)
       silc_rng_free(server->rng);
 
+    if (server->pkcs)
+      silc_pkcs_free(server->pkcs);
+
 #ifdef SILC_SIM
     while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
       silc_dlist_del(server->sim, sim);
@@ -115,6 +118,7 @@ int silc_server_init(SilcServer server)
   SilcServerID *id;
   SilcServerEntry id_entry;
   SilcIDListPurge purge;
+  SilcServerConfigSectionListenPort *listen;
 
   SILC_LOG_DEBUG(("Initializing server"));
   assert(server);
@@ -166,22 +170,27 @@ int silc_server_init(SilcServer server)
   /* Initialize none cipher */
   silc_cipher_alloc("none", &server->none_cipher);
 
-  /* Create a listening server. Note that our server can listen on
-     multiple ports. All listeners are created here and now. */
-  /* XXX Still check this whether to use server_info or listen_port. */
+  /* Allocate PKCS context for local public and private keys */
+  silc_pkcs_alloc(server->public_key->name, &server->pkcs);
+  silc_pkcs_public_key_set(server->pkcs, server->public_key);
+  silc_pkcs_private_key_set(server->pkcs, server->private_key);
+
+  /* Create a listening server. Note that our server can listen on multiple
+     ports. All listeners are created here and now. */
   sock_count = 0;
-  while(server->config->listen_port) {
+  listen = server->config->listen_port;
+  while(listen) {
     int tmp;
 
     tmp = silc_net_create_server(server->config->listen_port->port,
-                                server->config->listen_port->host);
+                                server->config->listen_port->listener_ip);
     if (tmp < 0)
       goto err0;
 
     sock = silc_realloc(sock, (sizeof(int *) * (sock_count + 1)));
     sock[sock_count] = tmp;
-    server->config->listen_port = server->config->listen_port->next;
     sock_count++;
+    listen = listen->next;
   }
 
   /* Initialize ID caches */
@@ -522,7 +531,8 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
                 sconn->remote_host, sconn->remote_port));
 
   /* Connect to remote host */
-  sock = silc_net_create_connection(sconn->remote_port, 
+  sock = silc_net_create_connection(server->config->listen_port->local_ip,
+                                   sconn->remote_port, 
                                    sconn->remote_host);
   if (sock < 0) {
     SILC_LOG_ERROR(("Could not connect to router"));
index 894d4fd34df8ce43fbe625034c0a426143f6b4dd..8b1f516170047f5ee925a150fdfb2c712ab3f0b3 100644 (file)
@@ -557,13 +557,13 @@ int silc_server_config_parse_lines(SilcServerConfig config,
 
       SILC_SERVER_CONFIG_LIST_ALLOC(config->listen_port);
 
-      /* Get host */
-      ret = silc_config_get_token(line, &config->listen_port->host);
+      /* Get local IP */
+      ret = silc_config_get_token(line, &config->listen_port->local_ip);
       if (ret < 0)
        break;
 
-      /* Get remote IP */
-      ret = silc_config_get_token(line, &config->listen_port->remote_ip);
+      /* Get listener IP */
+      ret = silc_config_get_token(line, &config->listen_port->listener_ip);
       if (ret < 0)
        break;
 
index f6612d4d76df4a62f3633305229ede744e6c21a0..c9e1d2a646fb3fce873a7ce77a68dccd49628f62 100644 (file)
@@ -56,8 +56,8 @@ typedef struct {
 
 /* Holds all the ports the server is listenning on */
 typedef struct SilcServerConfigSectionListenPortStruct {
-  char *host;
-  char *remote_ip;
+  char *local_ip;
+  char *listener_ip;
   uint16 port;
   struct SilcServerConfigSectionListenPortStruct *next;
   struct SilcServerConfigSectionListenPortStruct *prev;
@@ -66,8 +66,8 @@ typedef struct SilcServerConfigSectionListenPortStruct {
 /* Holds server's execution identity, or the user and group which
    to change from root when server starts */
 typedef struct {
- char *user;
- char *group;
 char *user;
 char *group;
 } SilcServerConfigSectionIdentity;
 
 /* Holds all the configured log files. */
index 7ba342c853fcda7bcb28af51f86d1ce5d77ca730..e131273120f5e9d41b8e436609b9eac188da9fc5 100644 (file)
@@ -291,7 +291,6 @@ AC_CHECK_FUNCS(gethostname gethostbyaddr getservbyname getservbyport)
 AC_CHECK_FUNCS(select listen bind shutdown close connect)
 AC_CHECK_FUNCS(fcntl setsockopt)
 AC_CHECK_FUNCS(getopt_long time)
-AC_CHECK_FUNCS(mlock munlock)
 AC_CHECK_FUNCS(chmod stat fstat getenv putenv strerror ctime gettimeofday)
 AC_CHECK_FUNCS(getpid getgid getsid getpgid getpgrp getuid)
 AC_CHECK_FUNCS(strchr strstr strcpy strncpy memcpy memset memmove)
index 1ad23bdba97c2cfd09222b6236996dcc55f147c2..479ea7ded0f3b45e99105e2e553d5e6b362771dc 100644 (file)
@@ -872,10 +872,10 @@ to have plaintext passphrase.  See the section 3.2.1 Passphrase
 Authentication for more information.
 
 If authentication method is public key authentication the authentication
-data is signature of the hash value HASH plus Key Exchange Start Payload,
-established by the SILC Key Exchange protocol.  This signature MUST then
-be verified by the server.  See the section 3.2.2 Public Key
-Authentication for more information.
+data is a signature of the hash value of hash HASH plus Key Exchange
+Start Payload, established by the SILC Key Exchange protocol.  This
+signature MUST then be verified by the server.  See the section 3.2.2
+Public Key Authentication for more information.
 
 The connecting client of this protocol MUST wait after successful execution
 of this protocol for the SILC_PACKET_NEW_ID packet where it will receive
@@ -969,8 +969,16 @@ which the server has received earlier in SKE protocol.
 The signature is computed using the private key of the sender by signing
 the HASH value provided by the SKE protocol previously, and the Key
 Exchange Start Payload from SKE protocol that was sent to the server.
-The server MUST verify the data, thus it must keep the HASH and the
-Key Exchange Start Payload saved during SKE and authentication protocols.
+These are concatenated and hash function is used to compute a hash value
+which is then signed.
+
+  auth_hash = hash(HASH | Key Exchange Start Payload);
+  signature = sign(auth_hash);
+
+The hash() function used to compute the value is the hash function negotiated
+in the SKE protocol.  The server MUST verify the data, thus it must keep
+the HASH and the Key Exchange Start Payload saved during SKE and
+authentication protocols.
 
 If the verified signature matches the sent signature, the authentication
 were successful and SILC_PACKET_SUCCESS is sent.  If it failed the protocol
index 89e7c6c657ce05ba674dda10a318f1b5ae6a645b..e34d43317c1ef571980233dc45de7aeed549f9f3 100644 (file)
@@ -84,7 +84,7 @@ lassi.kuo.fi.ssh.com:10.2.1.6:Kuopio, Finland:706
 #
 # Listenning ports.
 #
-# Format: <local IP/UNIX socket path>:<remote IP>:<port>
+# Format: <local IP>:<Listener IP>:<port>
 #
 [ListenPort]
 10.2.1.6:10.2.1.6:706
index 02288635a09430bf86f33ccca7fbcbe52fed550f..aebaebe65134b8749b1739326a5df644981c9e51 100644 (file)
@@ -34,6 +34,10 @@ static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
 static void silc_client_packet_parse_type(SilcClient client, 
                                          SilcSocketConnection sock,
                                          SilcPacketContext *packet);
+void silc_client_resolve_auth_method(bool success,
+                                    SilcProtocolAuthMeth auth_meth,
+                                    const unsigned char *auth_data,
+                                    uint32 auth_data_len, void *context);
 
 /* Allocates new client object. This has to be done before client may
    work. After calling this one must call silc_client_init to initialize
@@ -59,6 +63,9 @@ SilcClient silc_client_alloc(SilcClientOperations *ops,
   if (!new_client->params->rekey_secs)
     new_client->params->rekey_secs = 3600;
 
+  if (!new_client->params->connauth_request_secs)
+    new_client->params->connauth_request_secs = 2;
+
   return new_client;
 }
 
@@ -247,7 +254,7 @@ silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
   /* XXX In the future we should give up this non-blocking connect all
      together and use threads instead. */
   /* Create connection to server asynchronously */
-  sock = silc_net_create_connection_async(ctx->port, ctx->host);
+  sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
   if (sock < 0)
     return -1;
 
@@ -482,13 +489,6 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
   proto_ctx->dest_id_type = ctx->dest_id_type;
   proto_ctx->dest_id = ctx->dest_id;
 
-  /* Resolve the authentication method to be used in this connection */
-  if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
-                                   sock->port, &proto_ctx->auth_meth,
-                                   &proto_ctx->auth_data, 
-                                   &proto_ctx->auth_data_len))
-    proto_ctx->auth_meth = SILC_AUTH_NONE;
-
   /* Free old protocol as it is finished now */
   silc_protocol_free(protocol);
   if (ctx->packet)
@@ -496,13 +496,46 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
   silc_free(ctx);
   sock->protocol = NULL;
 
+  /* Resolve the authentication method to be used in this connection. The
+     completion callback is called after the application has resolved
+     the authentication method. */
+  client->ops->get_auth_method(client, sock->user_data, sock->hostname,
+                              sock->port, silc_client_resolve_auth_method,
+                              proto_ctx);
+}
+
+/* Authentication method resolving callback. Application calls this function
+   after we've called the client->ops->get_auth_method client operation
+   to resolve the authentication method. We will continue the executiong
+   of the protocol in this function. */
+
+void silc_client_resolve_auth_method(bool success,
+                                    SilcProtocolAuthMeth auth_meth,
+                                    const unsigned char *auth_data,
+                                    uint32 auth_data_len, void *context)
+{
+  SilcClientConnAuthInternalContext *proto_ctx =
+    (SilcClientConnAuthInternalContext *)context;
+  SilcClient client = (SilcClient)proto_ctx->client;
+
+  if (!success)
+    auth_meth = SILC_AUTH_NONE;
+
+  proto_ctx->auth_meth = auth_meth;
+
+  if (auth_data && auth_data_len) {
+    proto_ctx->auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
+    memcpy(proto_ctx->auth_data, auth_data, auth_data_len);
+    proto_ctx->auth_data_len = auth_data_len;
+  }
+
   /* Allocate the authenteication protocol and execute it. */
   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
-                     &sock->protocol, (void *)proto_ctx, 
+                     &proto_ctx->sock->protocol, (void *)proto_ctx, 
                      silc_client_connect_to_server_final);
 
   /* Execute the protocol */
-  silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
+  silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
 }
 
 /* Finalizes the connection to the remote SILC server. This is called
@@ -571,9 +604,9 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
   conn->rekey->timeout = client->params->rekey_secs;
   conn->rekey->context = (void *)client;
   silc_schedule_task_add(client->schedule, conn->sock->sock, 
-                    silc_client_rekey_callback,
-                    (void *)conn->sock, conn->rekey->timeout, 0,
-                    SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+                        silc_client_rekey_callback,
+                        (void *)conn->sock, conn->rekey->timeout, 0,
+                        SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 
   silc_protocol_free(protocol);
   if (ctx->auth_data)
@@ -788,10 +821,10 @@ void silc_client_packet_parse(SilcPacketParserContext *parser_context)
 
   /* Parse the packet */
   silc_schedule_task_add(client->schedule, parser_context->sock->sock, 
-                    silc_client_packet_parse_real,
-                    (void *)parser_context, 0, 1, 
-                    SILC_TASK_TIMEOUT,
-                    SILC_TASK_PRI_NORMAL);
+                        silc_client_packet_parse_real,
+                        (void *)parser_context, 0, 1, 
+                        SILC_TASK_TIMEOUT,
+                        SILC_TASK_PRI_NORMAL);
 }
 
 /* Parses the packet type and calls what ever routines the packet type
@@ -1045,6 +1078,15 @@ void silc_client_packet_parse_type(SilcClient client,
     }
     break;
 
+  case SILC_PACKET_CONNECTION_AUTH_REQUEST:
+    /*
+     * Reveived reply to our connection authentication method request
+     * packet. This is used to resolve the authentication method for the
+     * current session from the server if the client does not know it.
+     */
+    silc_client_connection_auth_request(client, sock, packet);
+    break;
+
   default:
     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
     break;
@@ -1515,9 +1557,9 @@ SILC_TASK_CALLBACK(silc_client_rekey_callback)
 
   /* Re-register re-key timeout */
   silc_schedule_task_add(client->schedule, sock->sock, 
-                    silc_client_rekey_callback,
-                    context, conn->rekey->timeout, 0,
-                    SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+                        silc_client_rekey_callback,
+                        context, conn->rekey->timeout, 0,
+                        SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
 
 /* The final callback for the REKEY protocol. This will actually take the
@@ -1558,3 +1600,107 @@ SILC_TASK_CALLBACK(silc_client_rekey_final)
   silc_socket_free(ctx->sock);
   silc_free(ctx);
 }
+
+/* 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,
+                                        SilcSocketConnection sock,
+                                        SilcPacketContext *packet)
+{
+  SilcClientConnection conn = (SilcClientConnection)sock->user_data;
+  uint16 conn_type, auth_meth;
+  int ret;
+
+  /* If we haven't send our request then ignore this one. */
+  if (!conn->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->connauth->callback)
+    (*conn->connauth->callback)(client, conn, auth_meth,
+                               conn->connauth->context);
+
+  silc_schedule_task_del(client->schedule, conn->connauth->timeout);
+
+  silc_free(conn->connauth);
+  conn->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->connauth)
+    return;
+
+  /* Call the request callback to notify application */
+  if (conn->connauth->callback)
+    (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
+                               conn->connauth->context);
+
+  silc_free(conn->connauth);
+  conn->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;
+
+  connauth = silc_calloc(1, sizeof(*connauth));
+  connauth->callback = callback;
+  connauth->context = context;
+
+  if (conn->connauth)
+    silc_free(conn->connauth);
+
+  conn->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->params->connauth_request_secs, 0,
+                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+}
index f78135f53a79528c1cb178d18f2de33b21af1162..c0e33228f361bfea6594835f8ffac6e18587efe3 100644 (file)
@@ -44,6 +44,15 @@ typedef struct {
   void *context;
 } *SilcClientRekey;
 
+/* 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;
+
 /* Connection structure used in client to associate all the important
    connection specific data to this structure. */
 struct SilcClientConnectionStruct {
@@ -121,6 +130,9 @@ struct SilcClientConnectionStruct {
   /* Re-key context */
   SilcClientRekey rekey;
 
+  /* Authentication request context. */
+  SilcClientConnAuthRequest connauth;
+
   /* Pointer back to the SilcClient. This object is passed to the application
      and the actual client object is accesible through this pointer. */
   SilcClient client;
@@ -295,5 +307,8 @@ void silc_client_notify_by_server(SilcClient client,
 void silc_client_private_message(SilcClient client, 
                                 SilcSocketConnection sock, 
                                 SilcPacketContext *packet);
+void silc_client_connection_auth_request(SilcClient client,
+                                        SilcSocketConnection sock,
+                                        SilcPacketContext *packet);
 
 #endif
index 78337cfe503b416c529910f99b7bf04e819b2632..b23f6550698659d32e7dac01fdd08d8cda3a849d 100644 (file)
@@ -366,7 +366,7 @@ silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
   int sock;
 
   /* Create connection to server asynchronously */
-  sock = silc_net_create_connection_async(ctx->port, ctx->host);
+  sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
   if (sock < 0)
     return -1;
 
index 5ba28db6e17e507543753da37c5ec0e8539636e6..8460ad8fccd0df61fb4f5c315c8086d459cc7eda 100644 (file)
@@ -544,7 +544,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
 
 static int
 silc_client_get_public_key_auth(SilcClient client,
-                               char *filepath,
+                               SilcClientConnection conn,
                                unsigned char *auth_data,
                                uint32 *auth_data_len,
                                SilcSKE ske)
@@ -552,18 +552,9 @@ silc_client_get_public_key_auth(SilcClient client,
   int len;
   SilcPKCS pkcs;
   SilcBuffer auth;
-  SilcPublicKey pub_key;
 
-  if (!silc_pkcs_load_public_key(filepath,&pub_key, SILC_PKCS_FILE_PEM))
-    if (!silc_pkcs_load_public_key(filepath, &pub_key, SILC_PKCS_FILE_BIN))
-      return FALSE;
-
-  silc_pkcs_alloc(pub_key->name, &pkcs);
-  if (!silc_pkcs_public_key_set(pkcs, pub_key)) {
-    silc_pkcs_free(pkcs);
-    silc_pkcs_public_key_free(pub_key);
-    return FALSE;
-  }
+  /* Use our default key */
+  pkcs = client->pkcs;
 
   /* Make the authentication data. Protocol says it is HASH plus
      KE Start Payload. */
@@ -576,16 +567,13 @@ silc_client_get_public_key_auth(SilcClient client,
                                          ske->start_payload_copy->len),
                     SILC_STR_END);
 
-  if (silc_pkcs_sign(pkcs, auth->data, auth->len, auth_data, auth_data_len)) {
-    silc_pkcs_free(pkcs);
+  if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data, 
+                              auth->len, auth_data, auth_data_len)) {
     silc_buffer_free(auth);
-    silc_pkcs_public_key_free(pub_key);
     return TRUE;
   }
 
-  silc_pkcs_free(pkcs);
   silc_buffer_free(auth);
-  silc_pkcs_public_key_free(pub_key);
   return FALSE;
 }
 
@@ -619,11 +607,6 @@ silc_client_conn_auth_continue(unsigned char *auth_data,
                          SILC_PACKET_CONNECTION_AUTH,
                          NULL, 0, NULL, NULL,
                          packet->data, packet->len, TRUE);
-
-  if (auth_data) {
-    memset(auth_data, 0, auth_data_len);
-    silc_free(auth_data);
-  }
   silc_buffer_free(packet);
       
   /* Next state is end of protocol */
@@ -652,6 +635,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
        */
       unsigned char *auth_data = NULL;
       uint32 auth_data_len = 0;
+      unsigned char sign[1024];
 
       switch(ctx->auth_meth) {
       case SILC_AUTH_NONE:
@@ -676,17 +660,17 @@ SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
        break;
 
       case SILC_AUTH_PUBLIC_KEY:
-       {
-         unsigned char sign[1024];
-
+       if (!ctx->auth_data) {
          /* Public key authentication */
-         silc_client_get_public_key_auth(client, ctx->auth_data,
-                                         sign, &auth_data_len, 
+         silc_client_get_public_key_auth(client, conn, sign, &auth_data_len, 
                                          ctx->ske);
-         auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
-         memcpy(auth_data, sign, auth_data_len);
-         break;
+         auth_data = sign;
+       } else {
+         auth_data = ctx->auth_data;
+         auth_data_len = ctx->auth_data_len;
        }
+       
+       break;
       }
 
       silc_client_conn_auth_continue(auth_data,
index 1dec749bb7b95c954173cb5f59854fdc679ee4e3..157d658ad66cf6e5eb41fed9a4dd64e457bca4a8 100644 (file)
@@ -166,6 +166,32 @@ typedef void (*SilcAskPassphrase)(unsigned char *passphrase,
  ***/
 typedef void (*SilcVerifyPublicKey)(bool success, void *context);
 
+/****f* silcclient/SilcClientAPI/SilcGetAuthMeth
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcGetAuthMeth)(bool success, 
+ *                                    SilcProtocolAuthMeth auth_meth,
+ *                                    const unsigned char *auth_data,
+ *                                    uint32 auth_data_len, void *context);
+ * 
+ * DESCRIPTION
+ *
+ *    Authentication method resolving callback. This is called by the
+ *    application to return the resolved authentication method. 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'
+ *    are the resolved authentication data. The `context' is the libary's
+ *    context sent to the get_auth_method client operation.
+ *
+ ***/
+typedef void (*SilcGetAuthMeth)(bool success, 
+                               SilcProtocolAuthMeth auth_meth,
+                               const unsigned char *auth_data,
+                               uint32 auth_data_len, void *context);
+
 /****d* silcclient/SilcClientAPI/SilcClientMessageType
  *
  * NAME
@@ -277,15 +303,13 @@ typedef struct {
   void (*disconnect)(SilcClient client, SilcClientConnection conn);
 
   /* Find authentication method and authentication data by hostname and
-     port. The hostname may be IP address as well. The found authentication
-     method and authentication data is returned to `auth_meth', `auth_data'
-     and `auth_data_len'. The function returns TRUE if authentication method
-     is found and FALSE if not. `conn' may be NULL. */
-  int (*get_auth_method)(SilcClient client, SilcClientConnection conn,
-                        char *hostname, uint16 port,
-                        SilcProtocolAuthMeth *auth_meth,
-                        unsigned char **auth_data,
-                        uint32 *auth_data_len);
+     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. */
+  void (*get_auth_method)(SilcClient client, SilcClientConnection conn,
+                         char *hostname, uint16 port,
+                         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
@@ -351,6 +375,12 @@ typedef struct {
   /* Rekey timeout in seconds. The client will perform rekey in this
      time interval. If set to zero, the default value will be used. */
   unsigned int rekey_secs;
+
+  /* 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;
 } SilcClientParams;
 /***/
 
@@ -1600,4 +1630,55 @@ 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);
+
 #endif
index 79d88cd2d7b0fd2227e0fa7711da9ea1244a4496..66aea06a875c825b232e6f1af6c0bec6f99af2ba 100644 (file)
@@ -77,6 +77,7 @@ SILC_PKCS_API_INIT(rsa)
 {
   uint32 prime_bits = keylen / 2;
   SilcMPInt p, q;
+  bool found = FALSE;
 
   printf("Generating RSA Public and Private keys, might take a while...\n");
 
@@ -84,16 +85,17 @@ SILC_PKCS_API_INIT(rsa)
   silc_mp_init(&q);
 
   /* Find p and q */
- retry_primes:
-  printf("Finding p: ");
-  silc_math_gen_prime(&p, prime_bits, TRUE);
-  
-  printf("\nFinding q: ");
-  silc_math_gen_prime(&q, prime_bits, TRUE);
-  
-  if ((silc_mp_cmp(&p, &q)) == 0) {
-    printf("\nFound equal primes, not good, retrying...\n");
-    goto retry_primes;
+  while (!found) {
+    printf("Finding p: ");
+    silc_math_gen_prime(&p, prime_bits, TRUE);
+    
+    printf("\nFinding q: ");
+    silc_math_gen_prime(&q, prime_bits, TRUE);
+
+    if ((silc_mp_cmp(&p, &q)) == 0)
+      printf("\nFound equal primes, not good, retrying...\n");
+    else
+      found = TRUE;
   }
 
   /* If p is smaller than q, switch them */
@@ -480,7 +482,7 @@ void rsa_generate_keys(RsaKey *key, uint32 bits,
   /* Set the primes */
   silc_mp_set(&key->p, p);
   silc_mp_set(&key->q, q);
-  
+
   /* Compute modulus, n = p * q */
   silc_mp_mul(&key->n, &key->p, &key->q);
   
index bc5edf29a298052e1428bc6a9cb17305dee38f48..27ed090d0357e76da2c998183549a293f773f8a0 100644 (file)
@@ -197,7 +197,7 @@ static uint32 primetable[] =
 
 bool silc_math_gen_prime(SilcMPInt *prime, uint32 bits, bool verbose)
 {
-  unsigned char *numbuf;
+  unsigned char *numbuf = NULL;
   uint32 i, b, k;
   uint32 *spmods;
   SilcMPInt r, base, tmp, tmp2, oprime;
@@ -212,13 +212,20 @@ bool silc_math_gen_prime(SilcMPInt *prime, uint32 bits, bool verbose)
 
   SILC_LOG_DEBUG(("Generating new prime"));
 
-  /* Get random number */
-  numbuf = silc_rng_global_get_rn_string((bits / 8));
-  if (!numbuf)
-    return FALSE;
+  /* Get random number and assure that the first digit is not zero since
+     our conversion routines does not like the first digit being zero. */
+  do {
+    if (numbuf) {
+      memset(numbuf, 0, (bits / 8));
+      silc_free(numbuf);
+    }
+    numbuf = silc_rng_global_get_rn_string((bits / 8));
+    if (!numbuf)
+      return FALSE;
+  } while (numbuf[0] == '0');
 
   /* Convert into MP and set the size */
-  silc_mp_set_str(prime, numbuf, 16);
+  silc_mp_set_str(prime, numbuf, 16);  
   silc_mp_mod_2exp(prime, prime, bits);
 
   /* Empty buffer */
index 61cd6efcee93439e6e97e49b0ce9312e6c2119bf..2df6fee495f03ea02a595f6942c3f63f2603b6e8 100644 (file)
 void *silc_malloc(size_t size)
 {
   void *addr;
-#ifdef HAVE_MLOCK
   addr = malloc(size);
   assert(addr != NULL);
-  mlock(addr, size);
   return addr;
-#else
-  addr = malloc(size);
-  assert(addr != NULL);
-  return addr;
-#endif
 }
 
 void *silc_calloc(size_t items, size_t size)
 {
   void *addr;
-#ifdef HAVE_MLOCK
   addr = calloc(items, size);
   assert(addr != NULL);
-  mlock(addr, size);
   return addr;
-#else
-  addr = calloc(items, size);
-  assert(addr != NULL);
-  return addr;
-#endif
 }
 
 void *silc_realloc(void *ptr, size_t size)
 {
   void *addr;
-#ifdef HAVE_MLOCK
-  addr = realloc(ptr, size);
-  assert(addr != NULL);
-  mlock(addr, size);
-  return addr;
-#else
   addr = realloc(ptr, size);
   assert(addr != NULL);
   return addr;
-#endif
 }
 
 void silc_free(void *ptr)
index 9bdee55403d99e2c0437c18301442dedef75dd2d..4c966eab54b9ad9eea621b2c4b5f0517a6ca7f09 100644 (file)
@@ -72,32 +72,41 @@ void silc_net_close_server(int sock);
  *
  * SYNOPSIS
  *
- *    int silc_net_create_connection(int port, char *host);
+ *    int silc_net_create_connection(const char *local_ip, int port, 
+ *                                   const char *host);
  *
  * DESCRIPTION
  *
  *    Creates a connection (TCP/IP) to a remote host. Returns the connection
  *    socket or -1 on error. This blocks the process while trying to create
- *    the connection.
+ *    the connection. If the `local_ip' is not NULL then this will bind
+ *    the `local_ip' address to a port before creating the connection.  If
+ *    it is NULL then this will directly create the connection.
  *
  ***/
-int silc_net_create_connection(int port, char *host);
+int silc_net_create_connection(const char *localhost, int port, 
+                              const char *host);
 
 /****f* silcutil/SilcNetAPI/silc_net_create_connection_async
  *
  * SYNOPSIS
  *
- *    int silc_net_create_connection_async(int port, char *host);
+ *    int silc_net_create_connection_async(const char *local_ip, int port, 
+ *                                         const char *host);
  *
  * DESCRIPTION
  *
  *    Creates a connection (TCP/IP) to a remote host. Returns the connection
  *    socket or -1 on error. This creates non-blocking socket hence the
  *    connection returns directly. To get the result of the connect() one
- *    must select() the socket and read the result after it's ready.
+ *    must select() the socket and read the result after it's ready. If the
+ *    `local_ip' is not NULL then this will bind the `local_ip' address to
+ *    a port before creating the connection.  If it is NULL then this will
+ *    directly create the connection.
  *
  ***/
-int silc_net_create_connection_async(int port, char *host);
+int silc_net_create_connection_async(const char *local_ip, int port, 
+                                    const char *host);
 
 /****f* silcutil/SilcNetAPI/silc_net_close_connection
  *
index 2849e3f7c436b68af1f478a84c6c87fd737d3237..5268d5540172eb8d7cf908c2acfea2f8c0f83e64 100644 (file)
@@ -37,7 +37,7 @@ int silc_net_create_server(int port, char *ip_addr)
   SILC_LOG_DEBUG(("Creating a new server listener"));
 
   /* Create the socket */
-  sock = socket(PF_INET, SOCK_STREAM, 0);
+  sock = socket(AF_INET, SOCK_STREAM, 0);
   if (sock < 0) {
     SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
     return -1;
@@ -52,7 +52,7 @@ int silc_net_create_server(int port, char *ip_addr)
 
   /* Set the socket information for bind() */
   memset(&server, 0, sizeof(server));
-  server.sin_family = PF_INET;
+  server.sin_family = AF_INET;
   if (port)
     server.sin_port = htons(port);
 
@@ -98,7 +98,8 @@ void silc_net_close_server(int sock)
    socket or -1 on error. This blocks the process while trying to create
    the connection. */
 
-int silc_net_create_connection(int port, char *host)
+int silc_net_create_connection(const char *local_ip, int port, 
+                              const char *host)
 {
   int sock, rval;
   struct hostent *dest;
@@ -117,16 +118,38 @@ int silc_net_create_connection(int port, char *host)
   /* Set socket information */
   memset(&desthost, 0, sizeof(desthost));
   desthost.sin_port = htons(port);
-  desthost.sin_family = PF_INET;
+  desthost.sin_family = AF_INET;
   memcpy(&desthost.sin_addr, dest->h_addr_list[0], sizeof(desthost.sin_addr));
 
   /* Create the connection socket */
-  sock = socket(PF_INET, SOCK_STREAM, 0);
+  sock = socket(AF_INET, SOCK_STREAM, 0);
   if (sock < 0) {
     SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
     return -1;
   }
 
+  /* Bind to the local address if provided */
+  if (local_ip) {
+    struct sockaddr_in local;
+    int local_len = sizeof(local.sin_addr);
+
+    /* Set the socket information for bind() */
+    memset(&local, 0, sizeof(local));
+    local.sin_family = AF_INET;
+
+    /* Convert IP address to network byte order */
+    silc_net_addr2bin(local_ip, (unsigned char *)&local.sin_addr.s_addr, 
+                     local_len);
+
+    /* Bind the local socket */
+    rval = bind(sock, (struct sockaddr *)&local, sizeof(local));
+    if (rval < 0) {
+      SILC_LOG_ERROR(("Cannot connect to remote host: "
+                     "cannot bind socket: %s", strerror(errno)));
+      return -1;
+    }
+  }
+
   /* Connect to the host */
   rval = connect(sock, (struct sockaddr *)&desthost, sizeof(desthost));
   if (rval < 0) {
@@ -152,7 +175,8 @@ int silc_net_create_connection(int port, char *host)
    connection returns directly. To get the result of the connect() one
    must select() the socket and read the result after it's ready. */
 
-int silc_net_create_connection_async(int port, char *host)
+int silc_net_create_connection_async(const char *local_ip, int port, 
+                                    const char *host)
 {
   int sock, rval;
   struct hostent *dest;
@@ -172,16 +196,38 @@ int silc_net_create_connection_async(int port, char *host)
   /* Set socket information */
   memset(&desthost, 0, sizeof(desthost));
   desthost.sin_port = htons(port);
-  desthost.sin_family = PF_INET;
+  desthost.sin_family = AF_INET;
   memcpy(&desthost.sin_addr, dest->h_addr_list[0], sizeof(desthost.sin_addr));
 
   /* Create the connection socket */
-  sock = socket(PF_INET, SOCK_STREAM, 0);
+  sock = socket(AF_INET, SOCK_STREAM, 0);
   if (sock < 0) {
     SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
     return -1;
   }
 
+  /* Bind to the local address if provided */
+  if (local_ip) {
+    struct sockaddr_in local;
+    int local_len = sizeof(local.sin_addr);
+
+    /* Set the socket information for bind() */
+    memset(&local, 0, sizeof(local));
+    local.sin_family = AF_INET;
+
+    /* Convert IP address to network byte order */
+    silc_net_addr2bin(local_ip, (unsigned char *)&local.sin_addr.s_addr, 
+                     local_len);
+
+    /* Bind the local socket */
+    rval = bind(sock, (struct sockaddr *)&local, sizeof(local));
+    if (rval < 0) {
+      SILC_LOG_ERROR(("Cannot connect to remote host: "
+                     "cannot bind socket: %s", strerror(errno)));
+      return -1;
+    }
+  }
+
   /* Set the socket to non-blocking mode */
   silc_net_set_socket_nonblock(sock);
 
index 142a502e9b9f89f8698733b1712247a18ce00b51..e4ffc6aa8e3b7bb2f0b1ae3c5364aa1b7b7fe446 100644 (file)
@@ -99,7 +99,8 @@ void silc_net_close_server(int sock)
    socket or -1 on error. This blocks the process while trying to create
    the connection. */
 
-int silc_net_create_connection(int port, char *host)
+int silc_net_create_connection(const char *local_ip, int port, 
+                              const char *host)
 {
   SOCKET sock;
   int rval, err;
@@ -155,7 +156,8 @@ int silc_net_create_connection(int port, char *host)
    connection returns directly. To get the result of the connect() one
    must select() the socket and read the result after it's ready. */
 
-int silc_net_create_connection_async(int port, char *host)
+int silc_net_create_connection_async(const char *local_ip, int port, 
+                                    const char *host)
 {
   SOCKET sock;
   int rval, err;
diff --git a/prepare b/prepare
index b00d1778947ee621cdd1e720a8b917561cb58f28..b9a8b856609df025c658bcfad605a7456ddbeb53 100755 (executable)
--- a/prepare
+++ b/prepare
@@ -2,7 +2,7 @@
 #
 #  prepare
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
 #  Copyright (C) 2000 - 2001 Pekka Riikonen
 #
@@ -60,7 +60,7 @@ if test "$dist_version" = ""; then
   dist_version=$version
 fi
 
-echo "Preparing $distribution distribution version $version"
+echo "Preparing $distribution distribution version $version (package $dist_version)"
 
 #
 # Go though the subdirs and create the Makefile.ams from the