added support for raw RSA public keys to stroke
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 29 Apr 2012 22:31:42 +0000 (00:31 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 29 Apr 2012 22:31:42 +0000 (00:31 +0200)
NEWS
src/libcharon/plugins/stroke/stroke_config.c
src/libcharon/plugins/stroke/stroke_cred.c
src/libcharon/plugins/stroke/stroke_cred.h
src/libcharon/plugins/stroke/stroke_list.c
src/libcharon/plugins/stroke/stroke_socket.c
src/libstrongswan/plugins/pem/pem_builder.c
src/starter/starterstroke.c
src/stroke/stroke_msg.h

diff --git a/NEWS b/NEWS
index 1834344..79e6c89 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,10 @@ strongswan-4.6.3
 - The resolve plugin automatically installs nameservers via resolvconf(8),
   if it is installed, instead of modifying /etc/resolv.conf directly.
 
+- The IKEv2 charon daemon supports now raw RSA public keys in RFC 3110
+  DNSKEY and PKCS#1 file format.
+
+
 strongswan-4.6.2
 ----------------
 
index 5a6c22f..c94c185 100644 (file)
@@ -264,7 +264,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
 {
        identification_t *identity;
        certificate_t *certificate;
-       char *auth, *id, *cert, *ca;
+       char *auth, *id, *pubkey, *cert, *ca;
        stroke_end_t *end, *other_end;
        auth_cfg_t *cfg;
        char eap_buf[32];
@@ -400,6 +400,14 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
        }
        cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
 
+       /* add raw RSA public key */
+       pubkey = end->rsakey;
+       if (pubkey && !streq(pubkey, "") && !streq(pubkey, "%cert"))
+       {
+               certificate = this->cred->load_pubkey(this->cred, KEY_RSA, pubkey,
+                                                                                         identity);
+       }
+
        /* CA constraint */
        if (ca)
        {
index 2b96833..a2a6d6d 100644 (file)
@@ -158,6 +158,78 @@ METHOD(stroke_cred_t, load_peer, certificate_t*,
        return NULL;
 }
 
+METHOD(stroke_cred_t, load_pubkey, certificate_t*,
+       private_stroke_cred_t *this, key_type_t type, char *filename,
+       identification_t *identity)
+{
+       certificate_t *cert;
+       char path[PATH_MAX];
+
+       if (streq(filename, "%dns"))
+       {
+
+       }
+       else if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2))
+       {
+               chunk_t printable_key, rfc3110_key;
+               public_key_t *key;
+
+               printable_key = chunk_create(filename + 2, strlen(filename) - 2);
+               rfc3110_key = strncaseeq(filename, "0x", 2) ?
+                                                                chunk_from_hex(printable_key, NULL) :
+                                                                chunk_from_base64(printable_key, NULL);
+               key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+                                                                BUILD_BLOB_DNSKEY, rfc3110_key,
+                                                                BUILD_END);
+               free(rfc3110_key.ptr);
+               if (key)
+               {
+                       cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+                                                                         CERT_TRUSTED_PUBKEY,
+                                                                         BUILD_PUBLIC_KEY, key,
+                                                                         BUILD_SUBJECT, identity,
+                                                                         BUILD_END);
+                       key->destroy(key);
+                       if (cert)
+                       {
+                               cert = this->creds->add_cert_ref(this->creds, TRUE, cert);
+                               DBG1(DBG_CFG, "  loaded %N public key for \"%Y\"",
+                                        key_type_names, type, identity);
+                               return cert;
+                       }
+               }
+               DBG1(DBG_CFG, "  loading %N public key for \"%Y\" failed",
+                        key_type_names, type, identity);
+       }
+       else
+       {
+               if (*filename == '/')
+               {
+                       snprintf(path, sizeof(path), "%s", filename);
+               }
+               else
+               {
+                       snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename);
+               }
+
+               cert = lib->creds->create(lib->creds,
+                                                                 CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
+                                                                 BUILD_FROM_FILE, path,
+                                                                 BUILD_SUBJECT, identity,
+                                                                 BUILD_END);
+               if (cert)
+               {
+                       cert = this->creds->add_cert_ref(this->creds, TRUE, cert);
+                       DBG1(DBG_CFG, "  loaded %N public key for \"%Y\" from '%s'",
+                                key_type_names, type, identity, filename);
+                       return cert;
+               }
+               DBG1(DBG_CFG, "  loading %N public key for \"%Y\" from '%s' failed",
+                        key_type_names, type, identity, filename);
+       }
+       return NULL;
+}
+
 /**
  * load trusted certificates from a directory
  */
@@ -1098,6 +1170,7 @@ stroke_cred_t *stroke_cred_create()
                        .reread = _reread,
                        .load_ca = _load_ca,
                        .load_peer = _load_peer,
+                       .load_pubkey = _load_pubkey,
                        .add_shared = _add_shared,
                        .cachecrl = _cachecrl,
                        .destroy = _destroy,
index 89b235f..83e6488 100644 (file)
@@ -66,6 +66,17 @@ struct stroke_cred_t {
        certificate_t* (*load_peer)(stroke_cred_t *this, char *filename);
 
        /**
+        * Load a raw public key and serve it through the credential_set.
+        *
+        * @param type                  type of the raw public key (RSA or ECDSA)
+        * @param filename              file to load raw public key from
+        * @param identity              identity of the raw public key owner
+        * @return                              reference to loaded raw public key, or NULL
+        */
+       certificate_t* (*load_pubkey)(stroke_cred_t *this, key_type_t type,
+                                                                 char *filename, identification_t *identity);
+
+       /**
         * Add a shared secret to serve through the credential_set.
         *
         * @param shared                shared key to add, gets owned
index 7ba967a..2cdadff 100644 (file)
@@ -705,6 +705,7 @@ static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
 
        while (enumerator->enumerate(enumerator, (void**)&cert))
        {
+               identification_t *subject = cert->get_subject(cert);
                public_key_t *public = cert->get_public_key(cert);
 
                if (public)
@@ -717,6 +718,10 @@ static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
                        }
                        fprintf(out, "\n");
 
+                       if (subject->get_type(subject) != ID_KEY_ID)
+                       {
+                               fprintf(out, "  subject:   %#Y\n", subject);
+                       }
                        list_public_key(public, out);
                        public->destroy(public);
                }
index d51cdaf..57648fe 100644 (file)
@@ -185,6 +185,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
        pop_string(msg, &end->auth2);
        pop_string(msg, &end->id);
        pop_string(msg, &end->id2);
+       pop_string(msg, &end->rsakey);
        pop_string(msg, &end->cert);
        pop_string(msg, &end->cert2);
        pop_string(msg, &end->ca);
@@ -200,6 +201,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
        DBG2(DBG_CFG, "  %sauth2=%s", label, end->auth2);
        DBG2(DBG_CFG, "  %sid=%s", label, end->id);
        DBG2(DBG_CFG, "  %sid2=%s", label, end->id2);
+       DBG2(DBG_CFG, "  %srsakey=%s", label, end->rsakey);
        DBG2(DBG_CFG, "  %scert=%s", label, end->cert);
        DBG2(DBG_CFG, "  %scert2=%s", label, end->cert2);
        DBG2(DBG_CFG, "  %sca=%s", label, end->ca);
index f05d348..46a5e72 100644 (file)
@@ -355,7 +355,7 @@ static status_t pem_to_bin(chunk_t *blob, bool *pgp)
  * load the credential from a blob
  */
 static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype,
-                                                       x509_flag_t flags)
+                                                       identification_t *subject, x509_flag_t flags)
 {
        void *cred = NULL;
        bool pgp = FALSE;
@@ -381,10 +381,19 @@ static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype,
        {
                subtype = pgp ? CERT_GPG : CERT_X509;
        }
-       cred = lib->creds->create(lib->creds, type, subtype,
+       if (type == CRED_CERTIFICATE && subtype == CERT_TRUSTED_PUBKEY && subject)
+       {
+               cred = lib->creds->create(lib->creds, type, subtype,
+                                                         BUILD_BLOB_ASN1_DER, blob, BUILD_SUBJECT, subject,
+                                                         BUILD_END);
+       }
+       else
+       {
+               cred = lib->creds->create(lib->creds, type, subtype,
                                                          pgp ? BUILD_BLOB_PGP : BUILD_BLOB_ASN1_DER, blob,
                                                          flags ? BUILD_X509_FLAG : BUILD_END,
                                                          flags, BUILD_END);
+       }
        chunk_clear(&blob);
        return cred;
 }
@@ -393,7 +402,7 @@ static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype,
  * load the credential from a file
  */
 static void *load_from_file(char *file, credential_type_t type, int subtype,
-                                                       x509_flag_t flags)
+                                                       identification_t *subject, x509_flag_t flags)
 {
        void *cred = NULL;
        struct stat sb;
@@ -423,7 +432,8 @@ static void *load_from_file(char *file, credential_type_t type, int subtype,
                return NULL;
        }
 
-       cred = load_from_blob(chunk_create(addr, sb.st_size), type, subtype, flags);
+       cred = load_from_blob(chunk_create(addr, sb.st_size), type, subtype,
+                                                                          subject,flags);
 
        munmap(addr, sb.st_size);
        close(fd);
@@ -434,7 +444,7 @@ static void *load_from_file(char *file, credential_type_t type, int subtype,
  * load the credential from a file descriptor
  */
 static void *load_from_fd(int fd, credential_type_t type, int subtype,
-                                                 x509_flag_t flags)
+                                                 identification_t *subject, x509_flag_t flags)
 {
        char buf[8096];
        char *pos = buf;
@@ -460,7 +470,8 @@ static void *load_from_fd(int fd, credential_type_t type, int subtype,
                        return NULL;
                }
        }
-       return load_from_blob(chunk_create(buf, total), type, subtype, flags);
+       return load_from_blob(chunk_create(buf, total), type, subtype,
+                                                 subject, flags);
 }
 
 /**
@@ -471,6 +482,7 @@ static void *pem_load(credential_type_t type, int subtype, va_list args)
        char *file = NULL;
        int fd = -1;
        chunk_t pem = chunk_empty;
+       identification_t *subject;
        int flags = 0;
 
        while (TRUE)
@@ -486,6 +498,9 @@ static void *pem_load(credential_type_t type, int subtype, va_list args)
                        case BUILD_BLOB_PEM:
                                pem = va_arg(args, chunk_t);
                                continue;
+                       case BUILD_SUBJECT:
+                               subject = va_arg(args, identification_t*);
+                               continue;
                        case BUILD_X509_FLAG:
                                flags = va_arg(args, int);
                                continue;
@@ -499,15 +514,15 @@ static void *pem_load(credential_type_t type, int subtype, va_list args)
 
        if (pem.len)
        {
-               return load_from_blob(pem, type, subtype, flags);
+               return load_from_blob(pem, type, subtype, subject, flags);
        }
        if (file)
        {
-               return load_from_file(file, type, subtype, flags);
+               return load_from_file(file, type, subtype, subject, flags);
        }
        if (fd != -1)
        {
-               return load_from_fd(fd, type, subtype, flags);
+               return load_from_fd(fd, type, subtype, subject, flags);
        }
        return NULL;
 }
index e399b1c..ae04c20 100644 (file)
@@ -162,6 +162,7 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
        msg_end->auth2 = push_string(msg, conn_end->auth2);
        msg_end->id = push_string(msg, conn_end->id);
        msg_end->id2 = push_string(msg, conn_end->id2);
+       msg_end->rsakey = push_string(msg, conn_end->rsakey);
        msg_end->cert = push_string(msg, conn_end->cert);
        msg_end->cert2 = push_string(msg, conn_end->cert2);
        msg_end->cert_policy = push_string(msg, conn_end->cert_policy);
index 7a469d3..4341225 100644 (file)
@@ -146,6 +146,7 @@ struct stroke_end_t {
        char *id;
        char *id2;
        char *eap_id;
+       char *rsakey;
        char *cert;
        char *cert2;
        char *ca;