From 5f1931ada11a826733162d0b7f587174416f249f Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Mon, 30 Apr 2012 00:31:42 +0200 Subject: [PATCH] added support for raw RSA public keys to stroke --- NEWS | 4 ++ src/libcharon/plugins/stroke/stroke_config.c | 10 ++- src/libcharon/plugins/stroke/stroke_cred.c | 73 ++++++++++++++++++++ src/libcharon/plugins/stroke/stroke_cred.h | 11 +++ src/libcharon/plugins/stroke/stroke_list.c | 5 ++ src/libcharon/plugins/stroke/stroke_socket.c | 2 + src/libstrongswan/plugins/pem/pem_builder.c | 33 ++++++--- src/starter/starterstroke.c | 1 + src/stroke/stroke_msg.h | 1 + 9 files changed, 130 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 18343444b..79e6c896d 100644 --- 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 ---------------- diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 5a6c22fb3..c94c18595 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -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) { diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index 2b96833fe..a2a6d6d9f 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -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, diff --git a/src/libcharon/plugins/stroke/stroke_cred.h b/src/libcharon/plugins/stroke/stroke_cred.h index 89b235f54..83e648819 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.h +++ b/src/libcharon/plugins/stroke/stroke_cred.h @@ -65,6 +65,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. * diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index 7ba967aba..2cdadff48 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -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); } diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index d51cdafde..57648feb8 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -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); diff --git a/src/libstrongswan/plugins/pem/pem_builder.c b/src/libstrongswan/plugins/pem/pem_builder.c index f05d348ee..46a5e7240 100644 --- a/src/libstrongswan/plugins/pem/pem_builder.c +++ b/src/libstrongswan/plugins/pem/pem_builder.c @@ -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; } diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c index e399b1c04..ae04c20dd 100644 --- a/src/starter/starterstroke.c +++ b/src/starter/starterstroke.c @@ -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); diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h index 7a469d3ac..434122511 100644 --- a/src/stroke/stroke_msg.h +++ b/src/stroke/stroke_msg.h @@ -146,6 +146,7 @@ struct stroke_end_t { char *id; char *id2; char *eap_id; + char *rsakey; char *cert; char *cert2; char *ca;