Imported gnutls based branch.
[tinc] / src / net_setup.c
index 3695e18..58d80da 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: net_setup.c,v 1.1.2.40 2003/07/29 22:59:00 guus Exp $
+    $Id: net_setup.c,v 1.1.2.50 2003/12/20 21:25:17 guus Exp $
 */
 
 #include "system.h"
 
-#include <openssl/pem.h>
-#include <openssl/rsa.h>
-#include <openssl/rand.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gcrypt.h>
 
 #include "avl_tree.h"
 #include "conf.h"
@@ -44,6 +44,7 @@
 
 char *myport;
 
+#if 0
 bool read_rsa_public_key(connection_t *c)
 {
        FILE *fp;
@@ -144,52 +145,62 @@ bool read_rsa_public_key(connection_t *c)
 
        return false;
 }
+#endif
 
-bool read_rsa_private_key(void)
+bool setup_credentials(void)
 {
-       FILE *fp;
-       char *fname, *key;
+       char *trust = NULL, *crl = NULL;
+       char *key = NULL, *cert = NULL;
+       int result;
 
        cp();
 
-       if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) {
-               myself->connection->rsa_key = RSA_new();
-//             RSA_blinding_on(myself->connection->rsa_key, NULL);
-               BN_hex2bn(&myself->connection->rsa_key->d, key);
-               BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
-               free(key);
-               return true;
-       }
-
-       if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
-               asprintf(&fname, "%s/rsa_key.priv", confbase);
-
-       if(is_safe_path(fname)) {
-               fp = fopen(fname, "r");
+       gnutls_certificate_allocate_credentials(&myself->connection->credentials);
 
-               if(!fp) {
-                       logger(LOG_ERR, _("Error reading RSA private key file `%s': %s"),
-                                  fname, strerror(errno));
-                       free(fname);
+       if(get_config_string(lookup_config(config_tree, "TrustFile"), &trust)) {
+               result = gnutls_certificate_set_x509_trust_file(myself->connection->credentials, trust, GNUTLS_X509_FMT_PEM);
+               if(result < 0) {
+                       logger(LOG_ERR, _("Error reading trust file '%s': %s"), trust, gnutls_strerror(result));
+                       free(trust);
                        return false;
                }
+               free(trust);
+       }
 
-               free(fname);
-               myself->connection->rsa_key =
-                       PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
-               fclose(fp);
-
-               if(!myself->connection->rsa_key) {
-                       logger(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"),
-                                  fname, strerror(errno));
+       if(get_config_string(lookup_config(config_tree, "CRLFile"), &crl)) {
+               result = gnutls_certificate_set_x509_crl_file(myself->connection->credentials, crl, GNUTLS_X509_FMT_PEM);
+               if(result) {
+                       logger(LOG_ERR, _("Error reading CRL file '%s': %s"), crl, gnutls_strerror(result));
+                       free(crl);
                        return false;
                }
+               free(crl);
+       }
 
-               return true;
+       if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &key))
+               asprintf(&key, "%s/rsa_key.priv", confbase);
+
+       if(!get_config_string(lookup_config(config_tree, "CertificateFile"), &cert))
+               asprintf(&cert, "%s/hosts/%s", confbase, myself->name);
+
+       
+       gnutls_certificate_set_x509_trust_file(myself->connection->credentials, cert, GNUTLS_X509_FMT_PEM);
+       logger(LOG_DEBUG, _("JOEHOE"));
+       gnutls_certificate_set_verify_flags(myself->connection->credentials, GNUTLS_VERIFY_DISABLE_CA_SIGN);
+       
+       result = gnutls_certificate_set_x509_key_file(myself->connection->credentials, cert, key, GNUTLS_X509_FMT_PEM);
+
+       if(result) {
+               logger(LOG_ERR, _("Error reading credentials from %s and %s: %s"), cert, key, gnutls_strerror(result));
+               free(key);
+               free(cert);
+               return false;
        }
 
-       free(fname);
-       return false;
+       free(key);
+       free(cert);
+       
+       return true;
 }
 
 /*
@@ -202,9 +213,9 @@ bool setup_myself(void)
        char *name, *hostname, *mode, *afname, *cipher, *digest;
        char *address = NULL;
        char *envp[5];
-       struct addrinfo hint, *ai, *aip;
+       struct addrinfo *ai, *aip, hint = {0};
        bool choice;
-       int i, err;
+       int i, err, result;
 
        cp();
 
@@ -232,7 +243,7 @@ bool setup_myself(void)
        myself->name = name;
        myself->connection->name = xstrdup(name);
 
-       if(!read_rsa_private_key())
+       if(!setup_credentials())
                return false;
 
        if(!read_connection_config(myself->connection)) {
@@ -240,11 +251,7 @@ bool setup_myself(void)
                return false;
        }
 
-       if(!read_rsa_public_key(myself->connection))
-               return false;
-
-       if(!get_config_string
-          (lookup_config(myself->connection->config_tree, "Port"), &myport))
+       if(!get_config_string (lookup_config(myself->connection->config_tree, "Port"), &myport))
                asprintf(&myport, "655");
 
        /* Read in all the subnets specified in the host configuration file */
@@ -262,25 +269,26 @@ bool setup_myself(void)
 
        /* Check some options */
 
-       if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice))
-               if(choice)
-                       myself->options |= OPTION_INDIRECT;
+       if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice)
+               myself->options |= OPTION_INDIRECT;
+
+       if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice)
+               myself->options |= OPTION_TCPONLY;
 
-       if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice))
-               if(choice)
-                       myself->options |= OPTION_TCPONLY;
+       if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice) && choice)
+               myself->options |= OPTION_INDIRECT;
 
-       if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice))
-               if(choice)
-                       myself->options |= OPTION_INDIRECT;
+       if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice) && choice)
+               myself->options |= OPTION_TCPONLY;
 
-       if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice))
-               if(choice)
-                       myself->options |= OPTION_TCPONLY;
+       if(get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice) && choice)
+               myself->options |= OPTION_PMTU_DISCOVERY;
 
        if(myself->options & OPTION_TCPONLY)
                myself->options |= OPTION_INDIRECT;
 
+       get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
+
        if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) {
                if(!strcasecmp(mode, "router"))
                        routing_mode = RMODE_ROUTER;
@@ -306,7 +314,7 @@ bool setup_myself(void)
        if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
                macexpire = 600;
 
-       if(get_config_int(lookup_config(myself->connection->config_tree, "MaxTimeout"), &maxtimeout)) {
+       if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
                if(maxtimeout <= 0) {
                        logger(LOG_ERR, _("Bogus maximum timeout!"));
                        return false;
@@ -332,12 +340,11 @@ bool setup_myself(void)
 
        /* Generate packet encryption key */
 
-       if(get_config_string
-          (lookup_config(myself->connection->config_tree, "Cipher"), &cipher)) {
+       if(get_config_string (lookup_config(myself->connection->config_tree, "Cipher"), &cipher)) {
                if(!strcasecmp(cipher, "none")) {
-                       myself->cipher = NULL;
+                       myself->cipher = GCRY_CIPHER_NONE;
                } else {
-                       myself->cipher = EVP_get_cipherbyname(cipher);
+                       myself->cipher = gcry_cipher_map_name(cipher);
 
                        if(!myself->cipher) {
                                logger(LOG_ERR, _("Unrecognized cipher type!"));
@@ -345,36 +352,44 @@ bool setup_myself(void)
                        }
                }
        } else
-               myself->cipher = EVP_bf_cbc();
+               myself->cipher = GCRY_CIPHER_AES;
 
-       if(myself->cipher)
-               myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
-       else
-               myself->keylength = 1;
+       if(myself->cipher) {
+               result = gcry_cipher_open(&myself->cipher_ctx, myself->cipher, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_SECURE);
 
-       myself->connection->outcipher = EVP_bf_ofb();
+               if(result) {
+                       logger(LOG_ERR, _("Error during initialisation of cipher for %s (%s): %s"),
+                                       myself->name, myself->hostname, gcry_strerror(result));
+                       return false;
+               }
+
+       }
 
-       myself->key = (char *) xmalloc(myself->keylength);
-       RAND_pseudo_bytes(myself->key, myself->keylength);
+       if(myself->cipher) {
+               myself->cipherkeylen = gcry_cipher_get_algo_keylen(myself->cipher);
+               myself->cipherblklen = gcry_cipher_get_algo_blklen(myself->cipher);
+       } else {
+               myself->cipherkeylen = 1;
+       }
+
+       logger(LOG_DEBUG, _("Key %s len %d"), gcry_cipher_algo_name(myself->cipher), myself->cipherkeylen);
+       myself->cipherkey = xmalloc(myself->cipherkeylen);
+       gcry_randomize(myself->cipherkey, myself->cipherkeylen, GCRY_STRONG_RANDOM);
+       if(myself->cipher)
+               gcry_cipher_setkey(myself->cipher_ctx, myself->cipherkey, myself->cipherkeylen);
 
        if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
                keylifetime = 3600;
 
        keyexpires = now + keylifetime;
        
-       if(myself->cipher) {
-               EVP_CIPHER_CTX_init(&packet_ctx);
-               EVP_DecryptInit_ex(&packet_ctx, myself->cipher, NULL, myself->key, myself->key + myself->cipher->key_len);
-       }
-
        /* Check if we want to use message authentication codes... */
 
-       if(get_config_string
-          (lookup_config(myself->connection->config_tree, "Digest"), &digest)) {
+       if(get_config_string (lookup_config(myself->connection->config_tree, "Digest"), &digest)) {
                if(!strcasecmp(digest, "none")) {
-                       myself->digest = NULL;
+                       myself->digest = GCRY_MD_NONE;
                } else {
-                       myself->digest = EVP_get_digestbyname(digest);
+                       myself->digest = gcry_md_map_name(digest);
 
                        if(!myself->digest) {
                                logger(LOG_ERR, _("Unrecognized digest type!"));
@@ -382,14 +397,34 @@ bool setup_myself(void)
                        }
                }
        } else
-               myself->digest = EVP_sha1();
+               myself->digest = GCRY_MD_SHA1;
+
+
+       if(myself->digest) {
+               result = gcry_md_open(&myself->digest_ctx, myself->digest, GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC);
+
+               if(result) {
+                       logger(LOG_ERR, _("Error during initialisation of digest for %s (%s): %s"),
+                                       myself->name, myself->hostname, gcry_strerror(result));
+                       return false;
+               }
+
+       }
 
-       myself->connection->outdigest = EVP_sha1();
+       if(myself->digest) {
+               myself->digestlen = gcry_md_get_algo_dlen(myself->digest);
+       } else {
+               myself->digestlen = 1;
+       }
 
-       if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"),
-               &myself->maclength)) {
+       myself->digestkey = xmalloc(myself->digestlen);
+       gcry_randomize(myself->digestkey, myself->digestlen, GCRY_STRONG_RANDOM);
+       if(myself->digest)
+               gcry_md_setkey(myself->digest_ctx, myself->digestkey, myself->digestlen);
+
+       if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength)) {
                if(myself->digest) {
-                       if(myself->maclength > myself->digest->md_size) {
+                       if(myself->maclength > myself->digestlen) {
                                logger(LOG_ERR, _("MAC length exceeds size of digest!"));
                                return false;
                        } else if(myself->maclength < 0) {
@@ -400,8 +435,6 @@ bool setup_myself(void)
        } else
                myself->maclength = 4;
 
-       myself->connection->outmaclength = 0;
-
        /* Compression */
 
        if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"),
@@ -413,8 +446,6 @@ bool setup_myself(void)
        } else
                myself->compression = 0;
 
-       myself->connection->outcompression = 0;
-
        /* Done */
 
        myself->nexthop = myself;
@@ -446,12 +477,10 @@ bool setup_myself(void)
 
        get_config_string(lookup_config(config_tree, "BindToAddress"), &address);
 
-       hint = (struct addrinfo) {
-               .ai_family = addressfamily,
-               .ai_socktype = SOCK_STREAM,
-               .ai_protocol = IPPROTO_TCP,
-               .ai_flags = AI_PASSIVE,
-       };
+       hint.ai_family = addressfamily;
+       hint.ai_socktype = SOCK_STREAM;
+       hint.ai_protocol = IPPROTO_TCP;
+       hint.ai_flags = AI_PASSIVE;
 
        err = getaddrinfo(address, myport, &hint, &ai);
 
@@ -543,7 +572,7 @@ void close_network_connections(void)
 
        for(node = connection_tree->head; node; node = next) {
                next = node->next;
-               c = (connection_t *) node->data;
+               c = node->data;
 
                if(c->outgoing)
                        free(c->outgoing->name), free(c->outgoing), c->outgoing = NULL;