diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2013-11-28 20:21:18 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2013-11-28 20:21:18 +0000 |
commit | 80934ed5126d3e0fd0ccafc16f70c897fc7bea82 (patch) | |
tree | 0c35f0bb84f27304e0cc8401e00bff3ce21bb0c6 /sbin | |
parent | 7fc50327b95cb08f5b4b12dea8c86347298fa0f9 (diff) |
support raw pubkey authentication w/o x509 certificates;
mostly by Michael Cardell Widerkrantz, reyk@ and mikeb@; ok mike@
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/iked/ca.c | 193 | ||||
-rw-r--r-- | sbin/iked/iked.h | 4 | ||||
-rw-r--r-- | sbin/iked/ikev2.c | 116 | ||||
-rw-r--r-- | sbin/iked/ikev2_pld.c | 20 | ||||
-rw-r--r-- | sbin/iked/parse.y | 71 |
5 files changed, 305 insertions, 99 deletions
diff --git a/sbin/iked/ca.c b/sbin/iked/ca.c index b22614bcdc7..a36ab7cd52c 100644 --- a/sbin/iked/ca.c +++ b/sbin/iked/ca.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ca.c,v 1.23 2013/11/14 12:38:20 markus Exp $ */ +/* $OpenBSD: ca.c,v 1.24 2013/11/28 20:21:17 markus Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -64,7 +64,8 @@ struct ibuf * ca_x509_serialize(X509 *); int ca_x509_subjectaltname_cmp(X509 *, struct iked_static_id *); int ca_x509_subjectaltname(X509 *cert, struct iked_id *); -int ca_key_serialize(EVP_PKEY *, struct iked_id *); +int ca_privkey_serialize(EVP_PKEY *, struct iked_id *); +int ca_pubkey_serialize(EVP_PKEY *, struct iked_id *); int ca_dispatch_parent(int, struct privsep_proc *, struct imsg *); int ca_dispatch_ikev1(int, struct privsep_proc *, struct imsg *); int ca_dispatch_ikev2(int, struct privsep_proc *, struct imsg *); @@ -83,6 +84,7 @@ struct ca_store { X509_LOOKUP *ca_certlookup; struct iked_id ca_privkey; + struct iked_id ca_pubkey; }; pid_t @@ -98,6 +100,7 @@ caproc(struct privsep *ps, struct privsep_proc *p) if ((store = calloc(1, sizeof(*store))) == NULL) fatal("ca: failed to allocate cert store"); + /* Read private key */ if ((fp = fopen(IKED_PRIVKEY, "r")) == NULL) fatal("ca: failed to open private key"); @@ -105,8 +108,12 @@ caproc(struct privsep *ps, struct privsep_proc *p) fatalx("ca: failed to read private key"); fclose(fp); - if (ca_key_serialize(key, &store->ca_privkey) != 0) + if (ca_privkey_serialize(key, &store->ca_privkey) != 0) fatalx("ca: failed to serialize private key"); + if (ca_pubkey_serialize(key, &store->ca_pubkey) != 0) + fatalx("ca: failed to serialize public key"); + + EVP_PKEY_free(key); return (proc_run(ps, p, procs, nitems(procs), ca_reset, store)); } @@ -390,40 +397,50 @@ ca_getreq(struct iked *env, struct imsg *imsg) return (-1); memcpy(&sh, ptr + sizeof(id), sizeof(sh)); memcpy(&type, ptr + sizeof(id) + sizeof(sh), sizeof(u_int8_t)); - if (type != IKEV2_CERT_X509_CERT) - return (-1); - - for (n = 1; i < len; n++, i += SHA_DIGEST_LENGTH) { - if ((ca = ca_by_subjectpubkey(store->ca_cas, - ptr + i, SHA_DIGEST_LENGTH)) == NULL) { - log_debug("%s: CA %d not found", __func__, n); - print_hex(ptr, i, SHA_DIGEST_LENGTH); - continue; - } - log_debug("%s: found CA %s", __func__, ca->name); + switch (type) { + case IKEV2_CERT_RSA_KEY: + if (store->ca_pubkey.id_type != type || + (buf = store->ca_pubkey.id_buf) == NULL) + return (-1); - if ((cert = ca_by_issuer(store->ca_certs, - X509_get_subject_name(ca), &id)) != NULL) { - /* XXX should we re-validate our own cert here? */ - break; - } + log_debug("%s: using local public key of type %s", __func__, + print_map(type, ikev2_cert_map)); + break; + case IKEV2_CERT_X509_CERT: + for (n = 1; i < len; n++, i += SHA_DIGEST_LENGTH) { + if ((ca = ca_by_subjectpubkey(store->ca_cas, ptr + i, + SHA_DIGEST_LENGTH)) == NULL) + continue; - log_debug("%s: no valid certificate for this CA", __func__); - } - if (ca == NULL || cert == NULL) { - log_warnx("%s: no valid local certificate found", __func__); - type = IKEV2_CERT_NONE; - ca_setcert(env, &sh, NULL, type, NULL, 0, PROC_IKEV2); - return (0); - } + log_debug("%s: found CA %s", __func__, ca->name); - log_debug("%s: found local certificate %s", __func__, cert->name); + if ((cert = ca_by_issuer(store->ca_certs, + X509_get_subject_name(ca), &id)) != NULL) { + /* XXX + * should we re-validate our own cert here? + */ + break; + } + } + if (ca == NULL || cert == NULL) { + log_warnx("%s: no valid local certificate found", + __func__); + type = IKEV2_CERT_NONE; + ca_setcert(env, &sh, NULL, type, NULL, 0, PROC_IKEV2); + return (0); + } + log_debug("%s: found local certificate %s", __func__, + cert->name); - if ((buf = ca_x509_serialize(cert)) == NULL) + if ((buf = ca_x509_serialize(cert)) == NULL) + return (-1); + break; + default: + log_warnx("%s: unknown cert type requested", __func__); return (-1); + } - type = IKEV2_CERT_X509_CERT; ca_setcert(env, &sh, NULL, type, ibuf_data(buf), ibuf_size(buf), PROC_IKEV2); @@ -492,17 +509,16 @@ ca_getauth(struct iked *env, struct imsg *imsg) int ca_reload(struct iked *env) { - struct ca_store *store = env->sc_priv; - DIR *dir; - struct dirent *entry; + struct ca_store *store = env->sc_priv; + u_int8_t md[EVP_MAX_MD_SIZE]; char file[PATH_MAX]; + struct iovec iov[2]; + struct dirent *entry; STACK_OF(X509_OBJECT) *h; X509_OBJECT *xo; X509 *x509; - int i, len; - u_int8_t md[EVP_MAX_MD_SIZE]; - struct iovec iov[2]; - int iovcnt = 2; + DIR *dir; + int i, len, iovcnt = 2; /* * Load CAs @@ -637,6 +653,17 @@ ca_reload(struct iked *env) (void)ca_validate_cert(env, NULL, x509, 0); } + if (!env->sc_certreqtype) + env->sc_certreqtype = store->ca_pubkey.id_type; + + log_debug("%s: local cert type %s", __func__, + print_map(env->sc_certreqtype, ikev2_cert_map)); + + iov[0].iov_base = &env->sc_certreqtype; + iov[0].iov_len = sizeof(env->sc_certreqtype); + (void)proc_composev_imsg(env, PROC_IKEV2, IMSG_CERTREQ, -1, + iov, iovcnt); + return (0); } @@ -748,11 +775,54 @@ ca_x509_serialize(X509 *x509) } int -ca_key_serialize(EVP_PKEY *key, struct iked_id *id) +ca_pubkey_serialize(EVP_PKEY *key, struct iked_id *id) { - int len; + RSA *rsa; + BIO *out = NULL; u_int8_t *d; + int len = 0; + int ret = -1; + + switch (key->type) { + case EVP_PKEY_RSA: + id->id_type = 0; + id->id_offset = 0; + ibuf_release(id->id_buf); + + if ((rsa = EVP_PKEY_get1_RSA(key)) == NULL) + goto done; + if ((out = BIO_new(BIO_s_mem())) == NULL) + goto done; + if (!i2d_RSAPublicKey_bio(out, rsa)) + goto done; + + len = BIO_get_mem_data(out, &d); + if ((id->id_buf = ibuf_new(d, len)) == NULL) + goto done; + + id->id_type = IKEV2_CERT_RSA_KEY; + break; + default: + log_debug("%s: unsupported key type %d", __func__, key->type); + return (-1); + } + + log_debug("%s: type %s length %d", __func__, + print_map(id->id_type, ikev2_cert_map), len); + + ret = 0; + done: + if (out != NULL) + BIO_free(out); + return (ret); +} + +int +ca_privkey_serialize(EVP_PKEY *key, struct iked_id *id) +{ RSA *rsa; + u_int8_t *d; + int len = 0; switch (key->type) { case EVP_PKEY_RSA: @@ -780,6 +850,9 @@ ca_key_serialize(EVP_PKEY *key, struct iked_id *id) return (-1); } + log_debug("%s: type %s length %d", __func__, + print_map(id->id_type, ikev2_cert_map), len); + return (0); } @@ -817,7 +890,7 @@ ca_validate_pubkey(struct iked *env, struct iked_static_id *id, void *data, size_t len) { BIO *rawcert = NULL; - RSA *rsa = NULL; + RSA *peerrsa = NULL, *localrsa = NULL; EVP_PKEY *peerkey = NULL, *localkey = NULL; int ret = -1; FILE *fp = NULL; @@ -855,32 +928,44 @@ ca_validate_pubkey(struct iked *env, struct iked_static_id *id, if ((rawcert = BIO_new_mem_buf(data, len)) == NULL) goto done; - if ((rsa = d2i_RSAPublicKey_bio(rawcert, NULL)) == NULL) + if ((peerrsa = d2i_RSAPublicKey_bio(rawcert, NULL)) == NULL) goto sslerr; if ((peerkey = EVP_PKEY_new()) == NULL) goto sslerr; - if (!EVP_PKEY_set1_RSA(peerkey, rsa)) + if (!EVP_PKEY_set1_RSA(peerkey, peerrsa)) goto sslerr; } lc_string(idstr); if (strlcpy(file, IKED_PUBKEY_DIR, sizeof(file)) >= sizeof(file) || - strlcpy(file, idstr, sizeof(file)) >= sizeof(file)) + strlcat(file, idstr, sizeof(file)) >= sizeof(file)) goto done; - log_debug("%s: looking up %s", __func__, file); - if ((fp = fopen(file, "r")) == NULL) goto done; - localkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL); - fclose(fp); + if (localkey == NULL) { + /* reading PKCS #8 failed, try PEM */ + rewind(fp); + localrsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL); + fclose(fp); + if (localrsa == NULL) + goto sslerr; + if ((localkey = EVP_PKEY_new()) == NULL) + goto sslerr; + if (!EVP_PKEY_set1_RSA(localkey, localrsa)) + goto sslerr; + } else { + fclose(fp); + } if (localkey == NULL) goto sslerr; if (!EVP_PKEY_cmp(peerkey, localkey)) goto done; + log_debug("%s: valid public key in file %s", __func__, file); + ret = 0; sslerr: if (ret != 0) @@ -889,8 +974,12 @@ ca_validate_pubkey(struct iked *env, struct iked_static_id *id, ibuf_release(idp.id_buf); if (peerkey != NULL) EVP_PKEY_free(peerkey); - if (rsa != NULL) - RSA_free(rsa); + if (localkey != NULL) + EVP_PKEY_free(localkey); + if (peerrsa != NULL) + RSA_free(peerrsa); + if (localrsa != NULL) + RSA_free(localrsa); if (rawcert != NULL) BIO_free(rawcert); @@ -931,7 +1020,7 @@ ca_validate_cert(struct iked *env, struct iked_static_id *id, if (id != NULL) { if ((ret = ca_validate_pubkey(env, id, X509_get_pubkey(cert), 0)) == 0) { - errstr = "public key found, ok"; + errstr = "in public key file, ok"; goto done; } @@ -984,11 +1073,11 @@ ca_validate_cert(struct iked *env, struct iked_static_id *id, /* Success */ ret = 0; + errstr = "ok"; done: if (cert != NULL) - log_debug("%s: %s %.100s", __func__, cert->name, - ret == 0 ? "ok" : errstr); + log_debug("%s: %s %.100s", __func__, cert->name, errstr); if (idname != NULL) X509_NAME_free(idname); diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h index d23ab9a5734..a1297ba649f 100644 --- a/sbin/iked/iked.h +++ b/sbin/iked/iked.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iked.h,v 1.58 2013/11/21 17:46:17 millert Exp $ */ +/* $OpenBSD: iked.h,v 1.59 2013/11/28 20:21:17 markus Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -241,6 +241,8 @@ struct iked_policy { int pol_refcnt; + u_int8_t pol_certreqtype; + int pol_af; u_int8_t pol_saproto; u_int pol_ipproto; diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c index 02e14621072..466cc3c716c 100644 --- a/sbin/iked/ikev2.c +++ b/sbin/iked/ikev2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2.c,v 1.83 2013/06/13 09:11:51 reyk Exp $ */ +/* $OpenBSD: ikev2.c,v 1.84 2013/11/28 20:21:17 markus Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -97,6 +97,8 @@ ssize_t ikev2_add_transform(struct ibuf *, u_int8_t, u_int8_t, u_int16_t, u_int16_t); ssize_t ikev2_add_ts(struct ibuf *, struct ikev2_payload **, ssize_t, struct iked_sa *, int); +ssize_t ikev2_add_certreq(struct ibuf *, struct ikev2_payload **, ssize_t, + struct ibuf *, u_int8_t); ssize_t ikev2_add_ts_payload(struct ibuf *, u_int, struct iked_sa *); int ikev2_add_data(struct ibuf *, void *, size_t); int ikev2_add_buf(struct ibuf *buf, struct ibuf *); @@ -192,6 +194,7 @@ ikev2_dispatch_cert(int fd, struct privsep_proc *p, struct imsg *imsg) u_int8_t *ptr; size_t len; struct iked_id *id = NULL; + int ignore = 0; switch (imsg->hdr.type) { case IMSG_CERTREQ: @@ -206,8 +209,9 @@ ikev2_dispatch_cert(int fd, struct privsep_proc *p, struct imsg *imsg) env->sc_certreq = ibuf_new(ptr, IMSG_DATA_SIZE(imsg) - sizeof(type)); - log_debug("%s: updated local CERTREQ signatures length %d", - __func__, ibuf_length(env->sc_certreq)); + log_debug("%s: updated local CERTREQ type %s length %d", + __func__, print_map(type, ikev2_cert_map), + ibuf_length(env->sc_certreq)); break; case IMSG_CERTVALID: @@ -240,6 +244,21 @@ ikev2_dispatch_cert(int fd, struct privsep_proc *p, struct imsg *imsg) break; } + /* + * Ignore the message if we already got a valid certificate. + * This might happen if the peer sent multiple CERTREQs. + */ + if (sa->sa_stateflags & IKED_REQ_CERT || + type == IKEV2_CERT_NONE) + ignore = 1; + + log_debug("%s: cert type %s length %d, %s", __func__, + print_map(type, ikev2_cert_map), len, + ignore ? "ignored" : "ok"); + + if (ignore) + break; + if (sh.sh_initiator) id = &sa->sa_icert; else @@ -250,18 +269,12 @@ ikev2_dispatch_cert(int fd, struct privsep_proc *p, struct imsg *imsg) ibuf_release(id->id_buf); id->id_buf = NULL; - if (type != IKEV2_CERT_NONE) { - if (len <= 0 || - (id->id_buf = ibuf_new(ptr, len)) == NULL) { - log_debug("%s: failed to get cert payload", - __func__); - break; - } + if (len <= 0 || (id->id_buf = ibuf_new(ptr, len)) == NULL) { + log_debug("%s: failed to get cert payload", + __func__); + break; } - - log_debug("%s: cert type %d length %d", __func__, - id->id_type, ibuf_length(id->id_buf)); - + sa_stateflags(sa, IKED_REQ_CERT); if (ikev2_ike_auth(env, sa, NULL) != 0) @@ -921,21 +934,15 @@ ikev2_init_ike_auth(struct iked *env, struct iked_sa *sa) goto done; len = ibuf_size(certid->id_buf) + sizeof(*cert); - if (env->sc_certreqtype) { - if (ikev2_next_payload(pld, len, - IKEV2_PAYLOAD_CERTREQ) == -1) - goto done; + /* CERTREQ payload(s) */ + if ((len = ikev2_add_certreq(e, &pld, + len, env->sc_certreq, env->sc_certreqtype)) == -1) + goto done; - /* CERTREQ payload */ - if ((pld = ikev2_add_payload(e)) == NULL) - goto done; - if ((cert = ibuf_advance(e, sizeof(*cert))) == NULL) - goto done; - cert->cert_type = env->sc_certreqtype; - if (ikev2_add_buf(e, env->sc_certreq) == -1) - goto done; - len = ibuf_size(env->sc_certreq) + sizeof(*cert); - } + if (env->sc_certreqtype != pol->pol_certreqtype && + (len = ikev2_add_certreq(e, &pld, + len, NULL, pol->pol_certreqtype)) == -1) + goto done; } if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_AUTH) == -1) @@ -1261,6 +1268,41 @@ ikev2_add_ts(struct ibuf *e, struct ikev2_payload **pld, ssize_t len, return (len); } + +ssize_t +ikev2_add_certreq(struct ibuf *e, struct ikev2_payload **pld, ssize_t len, + struct ibuf *certreq, u_int8_t type) +{ + struct ikev2_cert *cert; + + if (type == IKEV2_CERT_NONE) + return (len); + + if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_CERTREQ) == -1) + return (-1); + + /* CERTREQ payload */ + if ((*pld = ikev2_add_payload(e)) == NULL) + return (-1); + + if ((cert = ibuf_advance(e, sizeof(*cert))) == NULL) + return (-1); + + cert->cert_type = type; + len = sizeof(*cert); + + if (certreq != NULL && cert->cert_type == IKEV2_CERT_X509_CERT) { + if (ikev2_add_buf(e, certreq) == -1) + return (-1); + len += ibuf_size(certreq); + } + + log_debug("%s: type %s length %d", __func__, + print_map(type, ikev2_cert_map), len); + + return (len); +} + int ikev2_next_payload(struct ikev2_payload *pld, size_t length, u_int8_t nextpayload) @@ -1737,7 +1779,6 @@ ikev2_resp_ike_sa_init(struct iked *env, struct iked_message *msg) struct iked_message resp; struct ike_header *hdr; struct ikev2_payload *pld; - struct ikev2_cert *cert; struct ikev2_keyexchange *ke; struct ikev2_notify *n; struct iked_sa *sa = msg->msg_sa; @@ -1838,19 +1879,16 @@ ikev2_resp_ike_sa_init(struct iked *env, struct iked_message *msg) len += sizeof(*n); } - if (env->sc_certreqtype && (sa->sa_statevalid & IKED_REQ_CERT)) { - if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_CERTREQ) == -1) + if (sa->sa_statevalid & IKED_REQ_CERT) { + /* CERTREQ payload(s) */ + if ((len = ikev2_add_certreq(buf, &pld, + len, env->sc_certreq, env->sc_certreqtype)) == -1) goto done; - /* CERTREQ payload */ - if ((pld = ikev2_add_payload(buf)) == NULL) - goto done; - if ((cert = ibuf_advance(buf, sizeof(*cert))) == NULL) - goto done; - cert->cert_type = env->sc_certreqtype; - if (ikev2_add_buf(buf, env->sc_certreq) == -1) + if (env->sc_certreqtype != sa->sa_policy->pol_certreqtype && + (len = ikev2_add_certreq(buf, &pld, + len, NULL, sa->sa_policy->pol_certreqtype)) == -1) goto done; - len = ibuf_size(env->sc_certreq) + sizeof(*cert); } if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE) == -1) diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c index 96654f067eb..75b78bfc1fe 100644 --- a/sbin/iked/ikev2_pld.c +++ b/sbin/iked/ikev2_pld.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_pld.c,v 1.31 2013/03/21 04:30:14 deraadt Exp $ */ +/* $OpenBSD: ikev2_pld.c,v 1.32 2013/11/28 20:21:17 markus Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -526,7 +526,7 @@ ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld, struct iked_sa *sa = msg->msg_sa; struct ikev2_cert cert; u_int8_t *buf; - size_t len; + ssize_t len; u_int8_t *msgbuf = ibuf_data(msg->msg_data); memcpy(&cert, msgbuf + offset, sizeof(cert)); @@ -535,16 +535,24 @@ ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld, buf = msgbuf + offset; len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cert); - log_debug("%s: type %s signatures length %d", + log_debug("%s: type %s length %d", __func__, print_map(cert.cert_type, ikev2_cert_map), len); + + if (len < 0) { + log_debug("%s: invalid certificate request length", __func__); + return (-1); + } + print_hex(buf, 0, len); if (!ikev2_msg_frompeer(msg)) return (0); - if (!len || (len % SHA_DIGEST_LENGTH) != 0) { - log_debug("%s: invalid certificate request", __func__); - return (-1); + if (cert.cert_type == IKEV2_CERT_X509_CERT) { + if (!len || (len % SHA_DIGEST_LENGTH) != 0) { + log_debug("%s: invalid certificate request", __func__); + return (-1); + } } if (msg->msg_sa == NULL) diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y index b9dd157c62e..932eb9aa072 100644 --- a/sbin/iked/parse.y +++ b/sbin/iked/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.32 2013/11/25 13:12:23 benno Exp $ */ +/* $OpenBSD: parse.y,v 1.33 2013/11/28 20:21:17 markus Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -63,6 +63,7 @@ static struct file { struct file *pushfile(const char *, int); int popfile(void); int check_file_secrecy(int, const char *); +int check_pubkey(char *, int ); int yyparse(void); int yylex(void); int yyerror(const char *, ...); @@ -1625,6 +1626,48 @@ get_id_type(char *string) return (IKEV2_ID_FQDN); } +int +check_pubkey(char *idstr, int type) +{ + char keyfile[MAXPATHLEN]; + FILE *fp = NULL; + const char *suffix = NULL; + + switch (type) { + case IKEV2_ID_IPV4: + suffix = "ipv4"; + break; + case IKEV2_ID_IPV6: + suffix = "ipv6"; + break; + case IKEV2_ID_FQDN: + suffix = "fqdn"; + break; + case IKEV2_ID_UFQDN: + suffix = "ufqdn"; + break; + default: + /* Unspecified ID or public key not supported for this type */ + return (-1); + } + + lc_string(idstr); + if ((size_t)snprintf(keyfile, sizeof(keyfile), + IKED_CA IKED_PUBKEY_DIR "%s/%s", suffix, + idstr) >= sizeof(keyfile)) { + log_warnx("%s: public key path is too long", __func__); + return (-1); + } + + if ((fp = fopen(keyfile, "r")) == NULL) + return (-1); + fclose(fp); + + log_debug("%s: found public key file %s", __func__, keyfile); + + return (0); +} + struct ipsec_addr_wrap * host(const char *s) { @@ -2323,6 +2366,8 @@ create_ike(char *name, int af, u_int8_t ipproto, struct ipsec_hosts *hosts, struct iked_auth *authtype, struct ipsec_filters *filter, struct ipsec_addr_wrap *ikecfg) { + char idstr[IKED_ID_SIZE]; + u_int idtype = IKEV2_ID_NONE; struct ipsec_addr_wrap *ipa, *ipb; struct iked_policy pol; struct iked_proposal prop[2]; @@ -2334,8 +2379,10 @@ create_ike(char *name, int af, u_int8_t ipproto, struct ipsec_hosts *hosts, bzero(&pol, sizeof(pol)); bzero(&prop, sizeof(prop)); + bzero(idstr, sizeof(idstr)); pol.pol_id = ++policy_id; + pol.pol_certreqtype = env->sc_certreqtype; pol.pol_af = af; pol.pol_saproto = saproto; pol.pol_ipproto = ipproto; @@ -2559,6 +2606,28 @@ create_ike(char *name, int af, u_int8_t ipproto, struct ipsec_hosts *hosts, cfg->cfg.address.addr_af = ipa->af; } + if (dstid) { + strlcpy(idstr, dstid, sizeof(idstr)); + idtype = pol.pol_peerid.id_type; + } else if (!pol.pol_peer.addr_net) { + print_host(&pol.pol_peer.addr, idstr, sizeof(idstr)); + switch (pol.pol_peer.addr.ss_family) { + case AF_INET: + idtype = IKEV2_ID_IPV4; + break; + case AF_INET6: + idtype = IKEV2_ID_IPV6; + break; + default: + log_warnx("%s: unknown address family", __func__); + break; + } + } + + /* Check if we have a raw public key for this peer */ + if (check_pubkey(idstr, idtype) != -1) + pol.pol_certreqtype = IKEV2_CERT_RSA_KEY; + config_setpolicy(env, &pol, PROC_IKEV2); rules++; |