summaryrefslogtreecommitdiff
path: root/src/pluto/keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/keys.c')
-rw-r--r--src/pluto/keys.c2249
1 files changed, 1080 insertions, 1169 deletions
diff --git a/src/pluto/keys.c b/src/pluto/keys.c
index 1aed7a63f..6dfbd6732 100644
--- a/src/pluto/keys.c
+++ b/src/pluto/keys.c
@@ -10,8 +10,6 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
- *
- * RCSID $Id: keys.c 3738 2008-04-02 19:04:45Z andreas $
*/
#include <stddef.h>
@@ -25,33 +23,34 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
+#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
#include <sys/queue.h>
#include <glob.h>
#ifndef GLOB_ABORTED
-# define GLOB_ABORTED GLOB_ABEND /* fix for old versions */
+# define GLOB_ABORTED GLOB_ABEND /* fix for old versions */
#endif
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <library.h>
+#include <asn1/asn1.h>
#include "constants.h"
#include "defs.h"
-#include "mp_defs.h"
#include "id.h"
#include "x509.h"
-#include "pgp.h"
+#include "pgpcert.h"
#include "certs.h"
#include "smartcard.h"
#include "connections.h"
#include "state.h"
#include "lex.h"
#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
+#include "adns.h" /* needs <resolv.h> */
+#include "dnskey.h" /* needs keys.h and adns.h */
#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
+#include "whack.h" /* for RC_LOG_SERIOUS */
#include "timer.h"
#include "fetch.h"
#include "xauth.h"
@@ -61,77 +60,34 @@ const char *shared_secrets_file = SHARED_SECRETS_FILE;
typedef struct id_list id_list_t;
struct id_list {
- struct id id;
- id_list_t *next;
+ struct id id;
+ id_list_t *next;
};
typedef struct secret secret_t;
struct secret {
- id_list_t *ids;
- enum PrivateKeyKind kind;
- union {
- chunk_t preshared_secret;
- RSA_private_key_t RSA_private_key;
- xauth_t xauth_secret;
- smartcard_t *smartcard;
- } u;
- secret_t *next;
+ id_list_t *ids;
+ enum PrivateKeyKind kind;
+ union {
+ chunk_t preshared_secret;
+ xauth_t xauth_secret;
+ private_key_t *private_key;
+ smartcard_t *smartcard;
+ } u;
+ secret_t *next;
};
-static pubkey_t*
-allocate_RSA_public_key(const cert_t cert)
-{
- pubkey_t *pk = alloc_thing(pubkey_t, "pubkey");
- chunk_t e = empty_chunk, n = empty_chunk;
-
- switch (cert.type)
- {
- case CERT_PGP:
- e = cert.u.pgp->publicExponent;
- n = cert.u.pgp->modulus;
- break;
- case CERT_X509_SIGNATURE:
- e = cert.u.x509->publicExponent;
- n = cert.u.x509->modulus;
- break;
- default:
- plog("RSA public key allocation error");
- }
-
- init_RSA_public_key(&pk->u.rsa, e, n);
- DBG(DBG_RAW,
- RSA_show_public_key(&pk->u.rsa)
- )
-
- pk->alg = PUBKEY_ALG_RSA;
- pk->id = empty_id;
- pk->issuer = empty_chunk;
- pk->serial = empty_chunk;
-
- return pk;
-}
-
/*
* free a public key struct
*/
-static void
-free_public_key(pubkey_t *pk)
+static void free_public_key(pubkey_t *pk)
{
- free_id_content(&pk->id);
- freeanychunk(pk->issuer);
- freeanychunk(pk->serial);
-
- /* algorithm-specific freeing */
- switch (pk->alg)
- {
- case PUBKEY_ALG_RSA:
- free_RSA_public_content(&pk->u.rsa);
- break;
- default:
- bad_case(pk->alg);
- }
- pfree(pk);
+ DESTROY_IF(pk->public_key);
+ free_id_content(&pk->id);
+ free(pk->issuer.ptr);
+ free(pk->serial.ptr);
+ free(pk);
}
secret_t *secrets = NULL;
@@ -140,227 +96,215 @@ secret_t *secrets = NULL;
* me and the peer. We match the Id (if none, the IP address).
* Failure is indicated by a NULL.
*/
-static const secret_t *
-get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym)
+static const secret_t* get_secret(const struct connection *c,
+ enum PrivateKeyKind kind, bool asym)
{
- enum { /* bits */
- match_default = 01,
- match_him = 02,
- match_me = 04
- };
-
- unsigned int best_match = 0;
- secret_t *best = NULL;
- secret_t *s;
- const struct id *my_id = &c->spd.this.id
- , *his_id = &c->spd.that.id;
- struct id rw_id;
-
- /* is there a certificate assigned to this connection? */
- if (kind == PPK_RSA && c->spd.this.cert.type != CERT_NONE)
- {
- pubkey_t *my_public_key = allocate_RSA_public_key(c->spd.this.cert);
-
- for (s = secrets; s != NULL; s = s->next)
+ enum { /* bits */
+ match_default = 0x01,
+ match_him = 0x02,
+ match_me = 0x04
+ };
+
+ unsigned int best_match = 0;
+ secret_t *best = NULL;
+ secret_t *s;
+ const struct id *my_id = &c->spd.this.id
+ , *his_id = &c->spd.that.id;
+ struct id rw_id;
+
+ /* is there a certificate assigned to this connection? */
+ if (kind == PPK_PUBKEY && c->spd.this.cert.type != CERT_NONE)
{
- if (s->kind == kind &&
- same_RSA_public_key(&s->u.RSA_private_key.pub, &my_public_key->u.rsa))
- {
- best = s;
- break; /* we have found the private key - no sense in searching further */
- }
- }
- free_public_key(my_public_key);
- return best;
- }
-
- if (his_id_was_instantiated(c))
- {
- /* roadwarrior: replace him with 0.0.0.0 */
- rw_id.kind = c->spd.that.id.kind;
- rw_id.name = empty_chunk;
- happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
- his_id = &rw_id;
- }
- else if (kind == PPK_PSK
- && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK))
- && ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_NONE) ||
- (c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id))))
- {
- /* roadwarrior: replace him with 0.0.0.0 */
- rw_id.kind = ID_IPV4_ADDR;
- happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
- his_id = &rw_id;
- }
-
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == kind)
- {
- unsigned int match = 0;
+ public_key_t *pub_key = cert_get_public_key(c->spd.this.cert);
- if (s->ids == NULL)
- {
- /* a default (signified by lack of ids):
- * accept if no more specific match found
- */
- match = match_default;
- }
- else
- {
- /* check if both ends match ids */
- id_list_t *i;
-
- for (i = s->ids; i != NULL; i = i->next)
+ for (s = secrets; s != NULL; s = s->next)
{
- if (same_id(my_id, &i->id))
- match |= match_me;
-
- if (same_id(his_id, &i->id))
- match |= match_him;
+ if (s->kind == kind &&
+ s->u.private_key->belongs_to(s->u.private_key, pub_key))
+ {
+ best = s;
+ break; /* we have found the private key - no sense in searching further */
+ }
}
+ return best;
+ }
- /* If our end matched the only id in the list,
- * default to matching any peer.
- * A more specific match will trump this.
- */
- if (match == match_me
- && s->ids->next == NULL)
- match |= match_default;
- }
-
- switch (match)
- {
- case match_me:
- /* if this is an asymmetric (eg. public key) system,
- * allow this-side-only match to count, even if
- * there are other ids in the list.
- */
- if (!asym)
- break;
- /* FALLTHROUGH */
- case match_default: /* default all */
- case match_me | match_default: /* default peer */
- case match_me | match_him: /* explicit */
- if (match == best_match)
- {
- /* two good matches are equally good:
- * do they agree?
- */
- bool same = FALSE;
-
- switch (kind)
- {
- case PPK_PSK:
- same = s->u.preshared_secret.len == best->u.preshared_secret.len
- && memcmp(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len) == 0;
- break;
- case PPK_RSA:
- /* Dirty trick: since we have code to compare
- * RSA public keys, but not private keys, we
- * make the assumption that equal public keys
- * mean equal private keys. This ought to work.
- */
- same = same_RSA_public_key(&s->u.RSA_private_key.pub
- , &best->u.RSA_private_key.pub);
- break;
- default:
- bad_case(kind);
- }
- if (!same)
- {
- loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with distinct secrets match endpoints:"
- " first secret used");
- best = s; /* list is backwards: take latest in list */
- }
- }
- else if (match > best_match)
+ if (his_id_was_instantiated(c))
+ {
+ /* roadwarrior: replace him with 0.0.0.0 */
+ rw_id.kind = c->spd.that.id.kind;
+ rw_id.name = chunk_empty;
+ happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
+ his_id = &rw_id;
+ }
+ else if (kind == PPK_PSK
+ && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK))
+ && ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_ANY) ||
+ (c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id))))
+ {
+ /* roadwarrior: replace him with 0.0.0.0 */
+ rw_id.kind = ID_IPV4_ADDR;
+ happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
+ his_id = &rw_id;
+ }
+
+ for (s = secrets; s != NULL; s = s->next)
+ {
+ if (s->kind == kind)
{
- /* this is the best match so far */
- best_match = match;
- best = s;
+ unsigned int match = 0;
+
+ if (s->ids == NULL)
+ {
+ /* a default (signified by lack of ids):
+ * accept if no more specific match found
+ */
+ match = match_default;
+ }
+ else
+ {
+ /* check if both ends match ids */
+ id_list_t *i;
+
+ for (i = s->ids; i != NULL; i = i->next)
+ {
+ if (same_id(my_id, &i->id))
+ {
+ match |= match_me;
+ }
+ if (same_id(his_id, &i->id))
+ {
+ match |= match_him;
+ }
+ }
+
+ /* If our end matched the only id in the list,
+ * default to matching any peer.
+ * A more specific match will trump this.
+ */
+ if (match == match_me && s->ids->next == NULL)
+ {
+ match |= match_default;
+ }
+ }
+
+ switch (match)
+ {
+ case match_me:
+ /* if this is an asymmetric (eg. public key) system,
+ * allow this-side-only match to count, even if
+ * there are other ids in the list.
+ */
+ if (!asym)
+ {
+ break;
+ }
+ /* FALLTHROUGH */
+ case match_default: /* default all */
+ case match_me | match_default: /* default peer */
+ case match_me | match_him: /* explicit */
+ if (match == best_match)
+ {
+ /* two good matches are equally good:
+ * do they agree?
+ */
+ bool same = FALSE;
+
+ switch (kind)
+ {
+ case PPK_PSK:
+ same = s->u.preshared_secret.len == best->u.preshared_secret.len
+ && memeq(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len);
+ break;
+ case PPK_PUBKEY:
+ same = s->u.private_key->equals(s->u.private_key, best->u.private_key);
+ break;
+ default:
+ bad_case(kind);
+ }
+ if (!same)
+ {
+ loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with distinct secrets match endpoints:"
+ " first secret used");
+ best = s; /* list is backwards: take latest in list */
+ }
+ }
+ else if (match > best_match)
+ {
+ /* this is the best match so far */
+ best_match = match;
+ best = s;
+ }
+ }
}
- }
}
- }
- return best;
+ return best;
}
/* find the appropriate preshared key (see get_secret).
* Failure is indicated by a NULL pointer.
* Note: the result is not to be freed by the caller.
*/
-const chunk_t *
-get_preshared_secret(const struct connection *c)
+const chunk_t* get_preshared_secret(const struct connection *c)
{
- const secret_t *s = get_secret(c, PPK_PSK, FALSE);
+ const secret_t *s = get_secret(c, PPK_PSK, FALSE);
- DBG(DBG_PRIVATE,
- if (s == NULL)
- DBG_log("no Preshared Key Found");
- else
- DBG_dump_chunk("Preshared Key", s->u.preshared_secret);
- )
- return s == NULL? NULL : &s->u.preshared_secret;
+ DBG(DBG_PRIVATE,
+ if (s == NULL)
+ DBG_log("no Preshared Key Found");
+ else
+ DBG_dump_chunk("Preshared Key", s->u.preshared_secret);
+ )
+ return s == NULL? NULL : &s->u.preshared_secret;
}
-/* check the existence of an RSA private key matching an RSA public
- * key contained in an X.509 or OpenPGP certificate
+/* check the existence of a private key matching a public key contained
+ * in an X.509 or OpenPGP certificate
*/
-bool
-has_private_key(cert_t cert)
+bool has_private_key(cert_t cert)
{
- secret_t *s;
- bool has_key = FALSE;
- pubkey_t *pubkey = allocate_RSA_public_key(cert);
-
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == PPK_RSA &&
- same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa))
+ secret_t *s;
+ bool has_key = FALSE;
+ public_key_t *pub_key = cert_get_public_key(cert);
+
+ for (s = secrets; s != NULL; s = s->next)
{
- has_key = TRUE;
- break;
+ if (s->kind == PPK_PUBKEY &&
+ s->u.private_key->belongs_to(s->u.private_key, pub_key))
+ {
+ has_key = TRUE;
+ break;
+ }
}
- }
- free_public_key(pubkey);
- return has_key;
+ return has_key;
}
/*
- * get the matching RSA private key belonging to a given X.509 certificate
+ * get the matching private key belonging to a given X.509 certificate
*/
-const RSA_private_key_t*
-get_x509_private_key(const x509cert_t *cert)
+private_key_t* get_x509_private_key(const x509cert_t *cert)
{
- secret_t *s;
- const RSA_private_key_t *pri = NULL;
- const cert_t c = {CERT_X509_SIGNATURE, {(x509cert_t*)cert}};
-
- pubkey_t *pubkey = allocate_RSA_public_key(c);
+ secret_t *s;
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == PPK_RSA &&
- same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa))
+ for (s = secrets; s != NULL; s = s->next)
{
- pri = &s->u.RSA_private_key;
- break;
+ if (s->kind == PPK_PUBKEY &&
+ s->u.private_key->belongs_to(s->u.private_key, cert->public_key))
+ {
+ return s->u.private_key;
+ }
}
- }
- free_public_key(pubkey);
- return pri;
+ return NULL;
}
-/* find the appropriate RSA private key (see get_secret).
+/* find the appropriate private key (see get_secret).
* Failure is indicated by a NULL pointer.
*/
-const RSA_private_key_t *
-get_RSA_private_key(const struct connection *c)
+private_key_t* get_private_key(const struct connection *c)
{
- const secret_t *s = get_secret(c, PPK_RSA, TRUE);
+ const secret_t *s = get_secret(c, PPK_PUBKEY, TRUE);
- return s == NULL? NULL : &s->u.RSA_private_key;
+ return s == NULL? NULL : s->u.private_key;
}
/* digest a secrets file
@@ -403,1100 +347,1071 @@ get_RSA_private_key(const struct connection *c)
*/
/* parse PSK from file */
-static err_t
-process_psk_secret(chunk_t *psk)
+static err_t process_psk_secret(chunk_t *psk)
{
- err_t ugh = NULL;
-
- if (*tok == '"' || *tok == '\'')
- {
- clonetochunk(*psk, tok+1, flp->cur - tok - 2, "PSK");
- (void) shift();
- }
- else
- {
- char buf[BUF_LEN]; /* limit on size of binary representation of key */
- size_t sz;
-
- ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz
- , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
- if (ugh != NULL)
+ err_t ugh = NULL;
+
+ if (*tok == '"' || *tok == '\'')
{
- /* ttodata didn't like PSK data */
- ugh = builddiag("PSK data malformed (%s): %s", ugh, tok);
+ chunk_t secret = { tok + 1, flp->cur - tok -2 };
+
+ *psk = chunk_clone(secret);
+ (void) shift();
}
else
{
- clonetochunk(*psk, buf, sz, "PSK");
- (void) shift();
+ char buf[BUF_LEN]; /* limit on size of binary representation of key */
+ size_t sz;
+
+ ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz
+ , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
+ if (ugh != NULL)
+ {
+ /* ttodata didn't like PSK data */
+ ugh = builddiag("PSK data malformed (%s): %s", ugh, tok);
+ }
+ else
+ {
+ chunk_t secret = { buf, sz };
+ *psk = chunk_clone(secret);
+ (void) shift();
+ }
}
- }
- return ugh;
+ return ugh;
}
-/* Parse fields of RSA private key.
- * A braced list of keyword and value pairs.
- * At the moment, each field is required, in order.
- * The fields come from BIND 8.2's representation
+typedef enum rsa_private_key_part_t rsa_private_key_part_t;
+
+enum rsa_private_key_part_t {
+ RSA_PART_MODULUS = 0,
+ RSA_PART_PUBLIC_EXPONENT = 1,
+ RSA_PART_PRIVATE_EXPONENT = 2,
+ RSA_PART_PRIME1 = 3,
+ RSA_PART_PRIME2 = 4,
+ RSA_PART_EXPONENT1 = 5,
+ RSA_PART_EXPONENT2 = 6,
+ RSA_PART_COEFFICIENT = 7
+};
+
+const char *rsa_private_key_part_names[] = {
+ "Modulus",
+ "PublicExponent",
+ "PrivateExponent",
+ "Prime1",
+ "Prime2",
+ "Exponent1",
+ "Exponent2",
+ "Coefficient"
+};
+
+/**
+ * Parse fields of an RSA private key in BIND 8.2's representation
+ * consistiong of a braced list of keyword and value pairs in required order.
+ * Conversion into ASN.1 DER encoded PKCS#1 representation.
*/
-static err_t
-process_rsa_secret(RSA_private_key_t *rsak)
+static err_t process_rsa_secret(private_key_t **key)
{
- char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */
- const struct fld *p;
-
- /* save bytes of Modulus and PublicExponent for keyid calculation */
- unsigned char ebytes[sizeof(buf)];
- unsigned char *eb_next = ebytes;
- chunk_t pub_bytes[2];
- chunk_t *pb_next = &pub_bytes[0];
-
- for (p = RSA_private_field; p < &RSA_private_field[RSA_PRIVATE_FIELD_ELEMENTS]; p++)
- {
- size_t sz;
+ chunk_t asn1_chunk[countof(rsa_private_key_part_names)];
+ chunk_t pkcs1_chunk;
+ u_char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */
+ rsa_private_key_part_t part, p;
+ size_t sz, len = 0;
err_t ugh;
- if (!shift())
+ for (part = RSA_PART_MODULUS; part <= RSA_PART_COEFFICIENT; part++)
{
- return "premature end of RSA key";
+ chunk_t rsa_private_key_part;
+ const char *keyword = rsa_private_key_part_names[part];
+
+ if (!shift())
+ {
+ ugh = "premature end of RSA key";
+ goto end;
+ }
+ if (!tokeqword(keyword))
+ {
+ ugh = builddiag("%s keyword not found where expected in RSA key"
+ , keyword);
+ goto end;
+ }
+ if (!(shift() && (!tokeq(":") || shift()))) /* ignore optional ":" */
+ {
+ ugh = "premature end of RSA key";
+ goto end;
+ }
+ ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz,
+ diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
+ if (ugh)
+ {
+ ugh = builddiag("RSA data malformed (%s): %s", ugh, tok);
+ part++;
+ goto end;
+ }
+ rsa_private_key_part = chunk_create(buf, sz);
+ asn1_chunk[part] = asn1_integer("c", rsa_private_key_part);
+ len += asn1_chunk[part].len;
}
- else if (!tokeqword(p->name))
+
+ /* We require an (indented) '}' and the end of the record.
+ * We break down the test so that the diagnostic will be more helpful.
+ * Some people don't seem to wish to indent the brace!
+ */
+ if (!shift() || !tokeq("}"))
{
- return builddiag("%s keyword not found where expected in RSA key"
- , p->name);
+ ugh = "malformed end of RSA private key -- indented '}' required";
+ goto end;
}
- else if (!(shift()
- && (!tokeq(":") || shift()))) /* ignore optional ":" */
+ if (shift())
{
- return "premature end of RSA key";
+ ugh = "malformed end of RSA private key -- unexpected token after '}'";
+ goto end;
}
- else if (NULL != (ugh = ttodatav(tok, flp->cur - tok
- , 0, buf, sizeof(buf), &sz, diag_space, sizeof(diag_space)
- , TTODATAV_SPACECOUNTS)))
+
+ pkcs1_chunk = asn1_wrap(ASN1_SEQUENCE, "ccccccccc",
+ ASN1_INTEGER_0,
+ asn1_chunk[RSA_PART_MODULUS],
+ asn1_chunk[RSA_PART_PUBLIC_EXPONENT],
+ asn1_chunk[RSA_PART_PRIVATE_EXPONENT],
+ asn1_chunk[RSA_PART_PRIME1],
+ asn1_chunk[RSA_PART_PRIME2],
+ asn1_chunk[RSA_PART_EXPONENT1],
+ asn1_chunk[RSA_PART_EXPONENT2],
+ asn1_chunk[RSA_PART_COEFFICIENT]);
+
+ *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_ASN1_DER, pkcs1_chunk,
+ BUILD_END);
+ free(pkcs1_chunk.ptr);
+ if (*key == NULL)
{
- /* in RSA key, ttodata didn't like */
- return builddiag("RSA data malformed (%s): %s", ugh, tok);
+ ugh = "parsing of RSA private key failed";
}
- else
+
+end:
+ /* clean up and return */
+ for (p = RSA_PART_MODULUS ; p < part; p++)
{
- MP_INT *n = (MP_INT *) ((char *)rsak + p->offset);
-
- n_to_mpz(n, buf, sz);
- if (pb_next < &pub_bytes[elemsof(pub_bytes)])
- {
- if (eb_next - ebytes + sz > sizeof(ebytes))
- return "public key takes too many bytes";
-
- setchunk(*pb_next, eb_next, sz);
- memcpy(eb_next, buf, sz);
- eb_next += sz;
- pb_next++;
- }
-#if 0 /* debugging info that compromises security */
- {
- size_t sz = mpz_sizeinbase(n, 16);
- char buf[RSA_MAX_OCTETS * 2 + 2]; /* ought to be big enough */
-
- passert(sz <= sizeof(buf));
- mpz_get_str(buf, 16, n);
-
- loglog(RC_LOG_SERIOUS, "%s: %s", p->name, buf);
- }
-#endif
+ free(asn1_chunk[p].ptr);
}
- }
-
- /* We require an (indented) '}' and the end of the record.
- * We break down the test so that the diagnostic will be
- * more helpful. Some people don't seem to wish to indent
- * the brace!
- */
- if (!shift() || !tokeq("}"))
- {
- return "malformed end of RSA private key -- indented '}' required";
- }
- else if (shift())
- {
- return "malformed end of RSA private key -- unexpected token after '}'";
- }
- else
- {
- unsigned bits = mpz_sizeinbase(&rsak->pub.n, 2);
-
- rsak->pub.k = (bits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
- rsak->pub.keyid[0] = '\0'; /* in case of splitkeytoid failure */
- splitkeytoid(pub_bytes[1].ptr, pub_bytes[1].len
- , pub_bytes[0].ptr, pub_bytes[0].len
- , rsak->pub.keyid, sizeof(rsak->pub.keyid));
- return RSA_private_key_sanity(rsak);
- }
+ return ugh;
}
-/* process rsa key file protected with optional passphrase which can either be
+/**
+ * process a key file protected with optional passphrase which can either be
* read from ipsec.secrets or prompted for by using whack
*/
-static err_t
-process_rsa_keyfile(RSA_private_key_t *rsak, int whackfd)
+static err_t process_keyfile(private_key_t **key, key_type_t type, int whackfd)
{
- char filename[BUF_LEN];
- prompt_pass_t pass;
-
- memset(filename,'\0', BUF_LEN);
- memset(pass.secret,'\0', sizeof(pass.secret));
- pass.prompt = FALSE;
- pass.fd = whackfd;
+ char filename[BUF_LEN];
+ prompt_pass_t pass;
- /* we expect the filename of a PKCS#1 private key file */
+ memset(filename,'\0', BUF_LEN);
+ memset(pass.secret,'\0', sizeof(pass.secret));
+ pass.prompt = FALSE;
+ pass.fd = whackfd;
- if (*tok == '"' || *tok == '\'') /* quoted filename */
- memcpy(filename, tok+1, flp->cur - tok - 2);
- else
- memcpy(filename, tok, flp->cur - tok);
+ /* we expect the filename of a PKCS#1 private key file */
- if (shift())
- {
- /* we expect an appended passphrase or passphrase prompt*/
- if (tokeqword("%prompt"))
- {
- if (pass.fd == NULL_FD)
- return "RSA private key file -- enter passphrase using 'ipsec secrets'";
- pass.prompt = TRUE;
- }
+ if (*tok == '"' || *tok == '\'') /* quoted filename */
+ memcpy(filename, tok+1, flp->cur - tok - 2);
else
+ memcpy(filename, tok, flp->cur - tok);
+
+ if (shift())
{
- char *passphrase = tok;
- size_t len = flp->cur - passphrase;
-
- if (*tok == '"' || *tok == '\'') /* quoted passphrase */
- {
- passphrase++;
- len -= 2;
- }
- if (len > PROMPT_PASS_LEN)
- return "RSA private key file -- passphrase exceeds 64 characters";
-
- memcpy(pass.secret, passphrase, len);
+ /* we expect an appended passphrase or passphrase prompt*/
+ if (tokeqword("%prompt"))
+ {
+ if (pass.fd == NULL_FD)
+ {
+ return "Private key file -- enter passphrase using 'ipsec secrets'";
+ }
+ pass.prompt = TRUE;
+ }
+ else
+ {
+ char *passphrase = tok;
+ size_t len = flp->cur - passphrase;
+
+ if (*tok == '"' || *tok == '\'') /* quoted passphrase */
+ {
+ passphrase++;
+ len -= 2;
+ }
+ if (len > PROMPT_PASS_LEN)
+ {
+ return "Private key file -- passphrase exceeds 64 characters";
+ }
+ memcpy(pass.secret, passphrase, len);
+ }
+ if (shift())
+ {
+ return "Private key file -- unexpected token after passphrase";
+ }
}
- if (shift())
- return "RSA private key file -- unexpected token after passphrase";
- }
- return load_rsa_private_key(filename, &pass, rsak);
+ *key = load_private_key(filename, &pass, type);
+
+ return key ? NULL : "Private key file -- could not be loaded";
}
-/*
- * process xauth secret read from ipsec.secrets
+/**
+ * Process xauth secret read from ipsec.secrets
*/
-static err_t
-process_xauth(secret_t *s)
+static err_t process_xauth(secret_t *s)
{
- chunk_t user_name;
-
- s->kind = PPK_XAUTH;
-
- if (!shift())
- return "missing xauth user name";
- if (*tok == '"' || *tok == '\'') /* quoted user name */
- {
- user_name.ptr = tok + 1;
- user_name.len = flp->cur - tok - 2;
- }
- else
- {
- user_name.ptr = tok;
- user_name.len = flp->cur - tok;
- }
- plog(" loaded xauth credentials of user '%.*s'"
- , user_name.len
- , user_name.ptr);
- clonetochunk(s->u.xauth_secret.user_name
- , user_name.ptr, user_name.len, "xauth user name");
-
- if (!shift())
- return "missing xauth user password";
- return process_psk_secret(&s->u.xauth_secret.user_password);
+ chunk_t user_name;
+
+ s->kind = PPK_XAUTH;
+
+ if (!shift())
+ return "missing xauth user name";
+ if (*tok == '"' || *tok == '\'') /* quoted user name */
+ {
+ user_name.ptr = tok + 1;
+ user_name.len = flp->cur - tok - 2;
+ }
+ else
+ {
+ user_name.ptr = tok;
+ user_name.len = flp->cur - tok;
+ }
+ plog(" loaded xauth credentials of user '%.*s'"
+ , user_name.len
+ , user_name.ptr);
+ s->u.xauth_secret.user_name = chunk_clone(user_name);
+
+ if (!shift())
+ return "missing xauth user password";
+ return process_psk_secret(&s->u.xauth_secret.user_password);
}
-/* get XAUTH secret from chained secrets lists
+/**
+ * Get XAUTH secret from chained secrets lists
* only one entry is currently supported
*/
-static bool
-xauth_get_secret(xauth_t *xauth_secret)
+static bool xauth_get_secret(xauth_t *xauth_secret)
{
- secret_t *s;
- bool found = FALSE;
+ secret_t *s;
+ bool found = FALSE;
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == PPK_XAUTH)
+ for (s = secrets; s != NULL; s = s->next)
{
- if (found)
- {
- plog("found multiple xauth secrets - first selected");
- }
- else
- {
- found = TRUE;
- *xauth_secret = s->u.xauth_secret;
- }
+ if (s->kind == PPK_XAUTH)
+ {
+ if (found)
+ {
+ plog("found multiple xauth secrets - first selected");
+ }
+ else
+ {
+ found = TRUE;
+ *xauth_secret = s->u.xauth_secret;
+ }
+ }
}
- }
- return found;
+ return found;
}
-/*
+/**
* find a matching secret
*/
-static bool
-xauth_verify_secret(const xauth_peer_t *peer, const xauth_t *xauth_secret)
+static bool xauth_verify_secret(const xauth_peer_t *peer,
+ const xauth_t *xauth_secret)
{
- bool found = FALSE;
- secret_t *s;
+ bool found = FALSE;
+ secret_t *s;
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == PPK_XAUTH)
+ for (s = secrets; s != NULL; s = s->next)
{
- if (!same_chunk(xauth_secret->user_name, s->u.xauth_secret.user_name))
- continue;
- found = TRUE;
- if (same_chunk(xauth_secret->user_password, s->u.xauth_secret.user_password))
- return TRUE;
+ if (s->kind == PPK_XAUTH)
+ {
+ if (!chunk_equals(xauth_secret->user_name, s->u.xauth_secret.user_name))
+ {
+ continue;
+ }
+ found = TRUE;
+ if (chunk_equals(xauth_secret->user_password, s->u.xauth_secret.user_password))
+ {
+ return TRUE;
+ }
+ }
}
- }
- plog("xauth user '%.*s' %s"
- , xauth_secret->user_name.len, xauth_secret->user_name.ptr
- , found? "sent wrong password":"not found");
- return FALSE;
+ plog("xauth user '%.*s' %s"
+ , xauth_secret->user_name.len, xauth_secret->user_name.ptr
+ , found? "sent wrong password":"not found");
+ return FALSE;
}
-/*
+/**
* the global xauth_module struct is defined here
*/
xauth_module_t xauth_module;
-/*
- * assign the default xauth functions to any null function pointers
+/**
+ * Assign the default xauth functions to any null function pointers
*/
-void
-xauth_defaults(void)
+void xauth_defaults(void)
{
- if (xauth_module.get_secret == NULL)
- {
- DBG(DBG_CONTROL,
- DBG_log("xauth module: using default get_secret() function")
- )
- xauth_module.get_secret = xauth_get_secret;
- }
- if (xauth_module.verify_secret == NULL)
- {
- DBG(DBG_CONTROL,
- DBG_log("xauth module: using default verify_secret() function")
- )
- xauth_module.verify_secret = xauth_verify_secret;
- }
+ if (xauth_module.get_secret == NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("xauth module: using default get_secret() function")
+ )
+ xauth_module.get_secret = xauth_get_secret;
+ }
+ if (xauth_module.verify_secret == NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("xauth module: using default verify_secret() function")
+ )
+ xauth_module.verify_secret = xauth_verify_secret;
+ }
};
-/*
- * process pin read from ipsec.secrets or prompted for it using whack
+/**
+ * Process pin read from ipsec.secrets or prompted for it using whack
*/
-static err_t
-process_pin(secret_t *s, int whackfd)
+static err_t process_pin(secret_t *s, int whackfd)
{
- smartcard_t *sc;
- const char *pin_status = "no pin";
-
- s->kind = PPK_PIN;
-
- /* looking for the smartcard keyword */
- if (!shift() || strncmp(tok, SCX_TOKEN, strlen(SCX_TOKEN)) != 0)
- return "PIN keyword must be followed by %smartcard<reader>:<id>";
-
- sc = scx_add(scx_parse_number_slot_id(tok + strlen(SCX_TOKEN)));
- s->u.smartcard = sc;
- scx_share(sc);
- if (sc->pin.ptr != NULL)
- {
- scx_release_context(sc);
- scx_free_pin(&sc->pin);
- }
- sc->valid = FALSE;
-
- if (!shift())
- return "PIN statement must be terminated either by <pin code>, %pinpad or %prompt";
-
- if (tokeqword("%prompt"))
- {
- shift();
- /* if whackfd exists, whack will be used to prompt for a pin */
- if (whackfd != NULL_FD)
- pin_status = scx_get_pin(sc, whackfd) ? "valid pin" : "invalid pin";
+ smartcard_t *sc;
+ const char *pin_status = "no pin";
+
+ s->kind = PPK_PIN;
+
+ /* looking for the smartcard keyword */
+ if (!shift() || strncmp(tok, SCX_TOKEN, strlen(SCX_TOKEN)) != 0)
+ return "PIN keyword must be followed by %smartcard<reader>:<id>";
+
+ sc = scx_add(scx_parse_number_slot_id(tok + strlen(SCX_TOKEN)));
+ s->u.smartcard = sc;
+ scx_share(sc);
+ if (sc->pin.ptr != NULL)
+ {
+ scx_release_context(sc);
+ scx_free_pin(&sc->pin);
+ }
+ sc->valid = FALSE;
+
+ if (!shift())
+ return "PIN statement must be terminated either by <pin code>, %pinpad or %prompt";
+
+ if (tokeqword("%prompt"))
+ {
+ shift();
+ /* if whackfd exists, whack will be used to prompt for a pin */
+ if (whackfd != NULL_FD)
+ pin_status = scx_get_pin(sc, whackfd) ? "valid pin" : "invalid pin";
+ else
+ pin_status = "pin entry via prompt";
+ }
+ else if (tokeqword("%pinpad"))
+ {
+ chunk_t empty_pin = { "", 0 };
+
+ shift();
+
+ /* pin will be entered via pin pad during verification */
+ sc->pin = chunk_clone(empty_pin);
+ sc->pinpad = TRUE;
+ sc->valid = TRUE;
+ pin_status = "pin entry via pad";
+ if (pkcs11_keep_state)
+ {
+ scx_verify_pin(sc);
+ }
+ }
else
- pin_status = "pin entry via prompt";
- }
- else if (tokeqword("%pinpad"))
- {
- shift();
- /* pin will be entered via pin pad during verification */
- clonetochunk(sc->pin, "", 0, "empty pin");
- sc->pinpad = TRUE;
- sc->valid = TRUE;
- pin_status = "pin entry via pad";
- if (pkcs11_keep_state)
- scx_verify_pin(sc);
- }
- else
- {
- /* we read the pin directly from ipsec.secrets */
- err_t ugh = process_psk_secret(&sc->pin);
- if (ugh != NULL)
- return ugh;
- /* verify the pin */
- pin_status = scx_verify_pin(sc) ? "valid PIN" : "invalid PIN";
- }
+ {
+ /* we read the pin directly from ipsec.secrets */
+ err_t ugh = process_psk_secret(&sc->pin);
+ if (ugh != NULL)
+ return ugh;
+ /* verify the pin */
+ pin_status = scx_verify_pin(sc) ? "valid PIN" : "invalid PIN";
+ }
#ifdef SMARTCARD
- {
- char buf[BUF_LEN];
+ {
+ char buf[BUF_LEN];
- if (sc->any_slot)
- snprintf(buf, BUF_LEN, "any slot");
- else
- snprintf(buf, BUF_LEN, "slot: %lu", sc->slot);
+ if (sc->any_slot)
+ snprintf(buf, BUF_LEN, "any slot");
+ else
+ snprintf(buf, BUF_LEN, "slot: %lu", sc->slot);
- plog(" %s for #%d (%s, id: %s)"
- , pin_status, sc->number, scx_print_slot(sc, ""), sc->id);
- }
+ plog(" %s for #%d (%s, id: %s)"
+ , pin_status, sc->number, scx_print_slot(sc, ""), sc->id);
+ }
#else
- plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
+ plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
#endif
- return NULL;
+ return NULL;
}
-static void
-log_psk(secret_t *s)
+static void log_psk(secret_t *s)
{
- int n = 0;
- char buf[BUF_LEN];
- id_list_t *id_list = s->ids;
-
- if (id_list == NULL)
- {
- n = snprintf(buf, BUF_LEN, "%%any");
- }
- else
- {
- do
+ int n = 0;
+ char buf[BUF_LEN];
+ id_list_t *id_list = s->ids;
+
+ if (id_list == NULL)
{
- n += idtoa(&id_list->id, buf + n, BUF_LEN - n);
- if (n >= BUF_LEN)
- {
- n = BUF_LEN - 1;
- break;
- }
- else if (n < BUF_LEN - 1)
- {
- n += snprintf(buf + n, BUF_LEN - n, " ");
- }
- id_list = id_list->next;
+ n = snprintf(buf, BUF_LEN, "%%any");
}
- while (id_list);
- }
- plog(" loaded shared key for %.*s", n, buf);
+ else
+ {
+ do
+ {
+ n += idtoa(&id_list->id, buf + n, BUF_LEN - n);
+ if (n >= BUF_LEN)
+ {
+ n = BUF_LEN - 1;
+ break;
+ }
+ else if (n < BUF_LEN - 1)
+ {
+ n += snprintf(buf + n, BUF_LEN - n, " ");
+ }
+ id_list = id_list->next;
+ }
+ while (id_list);
+ }
+ plog(" loaded shared key for %.*s", n, buf);
}
-static void
-process_secret(secret_t *s, int whackfd)
+static void process_secret(secret_t *s, int whackfd)
{
- err_t ugh = NULL;
-
- s->kind = PPK_PSK; /* default */
- if (*tok == '"' || *tok == '\'')
- {
- /* old PSK format: just a string */
- log_psk(s);
- ugh = process_psk_secret(&s->u.preshared_secret);
- }
- else if (tokeqword("psk"))
- {
- /* preshared key: quoted string or ttodata format */
- log_psk(s);
- ugh = !shift()? "unexpected end of record in PSK"
- : process_psk_secret(&s->u.preshared_secret);
- }
- else if (tokeqword("rsa"))
- {
- /* RSA key: the fun begins.
- * A braced list of keyword and value pairs.
- */
- s->kind = PPK_RSA;
- if (!shift())
+ err_t ugh = NULL;
+
+ s->kind = PPK_PSK; /* default */
+ if (*tok == '"' || *tok == '\'')
+ {
+ /* old PSK format: just a string */
+ log_psk(s);
+ ugh = process_psk_secret(&s->u.preshared_secret);
+ }
+ else if (tokeqword("psk"))
+ {
+ /* preshared key: quoted string or ttodata format */
+ log_psk(s);
+ ugh = !shift()? "unexpected end of record in PSK"
+ : process_psk_secret(&s->u.preshared_secret);
+ }
+ else if (tokeqword("rsa"))
+ {
+ /* RSA key: the fun begins.
+ * A braced list of keyword and value pairs.
+ */
+ s->kind = PPK_PUBKEY;
+ if (!shift())
+ {
+ ugh = "bad RSA key syntax";
+ }
+ else if (tokeq("{"))
+ {
+ ugh = process_rsa_secret(&s->u.private_key);
+ }
+ else
+ {
+ ugh = process_keyfile(&s->u.private_key, KEY_RSA, whackfd);
+ }
+ }
+ else if (tokeqword("ecdsa"))
+ {
+ s->kind = PPK_PUBKEY;
+ if (!shift())
+ {
+ ugh = "bad ECDSA key syntax";
+ }
+ else
+ {
+ ugh = process_keyfile(&s->u.private_key, KEY_ECDSA, whackfd);
+ }
+ }
+ else if (tokeqword("xauth"))
{
- ugh = "bad RSA key syntax";
+ ugh = process_xauth(s);
}
- else if (tokeq("{"))
+ else if (tokeqword("pin"))
{
- ugh = process_rsa_secret(&s->u.RSA_private_key);
+ ugh = process_pin(s, whackfd);
}
else
{
- ugh = process_rsa_keyfile(&s->u.RSA_private_key, whackfd);
+ ugh = builddiag("unrecognized key format: %s", tok);
}
- }
- else if (tokeqword("xauth"))
- {
- ugh = process_xauth(s);
- }
- else if (tokeqword("pin"))
- {
- ugh = process_pin(s, whackfd);
- }
- else
- {
- ugh = builddiag("unrecognized key format: %s", tok);
- }
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s"
- , flp->filename, flp->lino, ugh);
- pfree(s);
- }
- else if (flushline("expected record boundary in key"))
- {
- /* gauntlet has been run: install new secret */
- lock_certs_and_keys("process_secret");
- s->next = secrets;
- secrets = s;
- unlock_certs_and_keys("process_secrets");
- }
-}
-
-static void process_secrets_file(const char *file_pat, int whackfd); /* forward declaration */
-
-static void
-process_secret_records(int whackfd)
-{
- /* read records from ipsec.secrets and load them into our table */
- for (;;)
- {
- (void)flushline(NULL); /* silently ditch leftovers, if any */
- if (flp->bdry == B_file)
- break;
-
- flp->bdry = B_none; /* eat the Record Boundary */
- (void)shift(); /* get real first token */
- if (tokeqword("include"))
+ if (ugh != NULL)
{
- /* an include directive */
- char fn[MAX_TOK_LEN]; /* space for filename (I hope) */
- char *p = fn;
- char *end_prefix = strrchr(flp->filename, '/');
-
- if (!shift())
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of include directive"
- , flp->filename, flp->lino);
- continue; /* abandon this record */
- }
-
- /* if path is relative and including file's pathname has
- * a non-empty dirname, prefix this path with that dirname.
- */
- if (tok[0] != '/' && end_prefix != NULL)
- {
- size_t pl = end_prefix - flp->filename + 1;
-
- /* "clamp" length to prevent problems now;
- * will be rediscovered and reported later.
- */
- if (pl > sizeof(fn))
- pl = sizeof(fn);
- memcpy(fn, flp->filename, pl);
- p += pl;
- }
- if (flp->cur - tok >= &fn[sizeof(fn)] - p)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: include pathname too long"
- , flp->filename, flp->lino);
- continue; /* abandon this record */
- }
- strcpy(p, tok);
- (void) shift(); /* move to Record Boundary, we hope */
- if (flushline("ignoring malformed INCLUDE -- expected Record Boundary after filename"))
- {
- process_secrets_file(fn, whackfd);
- tok = NULL; /* correct, but probably redundant */
- }
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s"
+ , flp->filename, flp->lino, ugh);
+ free(s);
}
- else
+ else if (flushline("expected record boundary in key"))
{
- /* expecting a list of indices and then the key info */
- secret_t *s = alloc_thing(secret_t, "secret");
+ /* gauntlet has been run: install new secret */
+ lock_certs_and_keys("process_secret");
+ s->next = secrets;
+ secrets = s;
+ unlock_certs_and_keys("process_secrets");
+ }
+}
- s->ids = NULL;
- s->kind = PPK_PSK; /* default */
- setchunk(s->u.preshared_secret, NULL, 0);
- s->next = NULL;
+static void process_secrets_file(const char *file_pat, int whackfd); /* forward declaration */
- for (;;)
- {
- if (tok[0] == '"' || tok[0] == '\'')
+static void process_secret_records(int whackfd)
+{
+ /* read records from ipsec.secrets and load them into our table */
+ for (;;)
+ {
+ (void)flushline(NULL); /* silently ditch leftovers, if any */
+ if (flp->bdry == B_file)
{
- /* found key part */
- process_secret(s, whackfd);
- break;
+ break;
}
- else if (tokeq(":"))
+ flp->bdry = B_none; /* eat the Record Boundary */
+ (void)shift(); /* get real first token */
+
+ if (tokeqword("include"))
{
- /* found key part */
- shift(); /* discard explicit separator */
- process_secret(s, whackfd);
- break;
+ /* an include directive */
+ char fn[MAX_TOK_LEN]; /* space for filename (I hope) */
+ char *p = fn;
+ char *end_prefix = strrchr(flp->filename, '/');
+
+ if (!shift())
+ {
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of include directive"
+ , flp->filename, flp->lino);
+ continue; /* abandon this record */
+ }
+
+ /* if path is relative and including file's pathname has
+ * a non-empty dirname, prefix this path with that dirname.
+ */
+ if (tok[0] != '/' && end_prefix != NULL)
+ {
+ size_t pl = end_prefix - flp->filename + 1;
+
+ /* "clamp" length to prevent problems now;
+ * will be rediscovered and reported later.
+ */
+ if (pl > sizeof(fn))
+ {
+ pl = sizeof(fn);
+ }
+ memcpy(fn, flp->filename, pl);
+ p += pl;
+ }
+ if (flp->cur - tok >= &fn[sizeof(fn)] - p)
+ {
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: include pathname too long"
+ , flp->filename, flp->lino);
+ continue; /* abandon this record */
+ }
+ strcpy(p, tok);
+ (void) shift(); /* move to Record Boundary, we hope */
+ if (flushline("ignoring malformed INCLUDE -- expected Record Boundary after filename"))
+ {
+ process_secrets_file(fn, whackfd);
+ tok = NULL; /* correct, but probably redundant */
+ }
}
else
{
- /* an id
- * See RFC2407 IPsec Domain of Interpretation 4.6.2
- */
- struct id id;
- err_t ugh;
-
- if (tokeq("%any"))
- {
- id = empty_id;
- id.kind = ID_IPV4_ADDR;
- ugh = anyaddr(AF_INET, &id.ip_addr);
- }
- else if (tokeq("%any6"))
- {
- id = empty_id;
- id.kind = ID_IPV6_ADDR;
- ugh = anyaddr(AF_INET6, &id.ip_addr);
- }
- else
- {
- ugh = atoid(tok, &id, FALSE);
- }
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS
- , "ERROR \"%s\" line %d: index \"%s\" %s"
- , flp->filename, flp->lino, tok, ugh);
- }
- else
- {
- id_list_t *i = alloc_thing(id_list_t
- , "id_list");
-
- i->id = id;
- unshare_id_content(&i->id);
- i->next = s->ids;
- s->ids = i;
- /* DBG_log("id type %d: %s %.*s", i->kind, ip_str(&i->ip_addr), (int)i->name.len, i->name.ptr); */
- }
- if (!shift())
- {
- /* unexpected Record Boundary or EOF */
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of id list"
- , flp->filename, flp->lino);
- break;
- }
+ /* expecting a list of indices and then the key info */
+ secret_t *s = malloc_thing(secret_t);
+
+ zero(s);
+ s->ids = NULL;
+ s->kind = PPK_PSK; /* default */
+ s->u.preshared_secret = chunk_empty;
+ s->next = NULL;
+
+ for (;;)
+ {
+ if (tok[0] == '"' || tok[0] == '\'')
+ {
+ /* found key part */
+ process_secret(s, whackfd);
+ break;
+ }
+ else if (tokeq(":"))
+ {
+ /* found key part */
+ shift(); /* discard explicit separator */
+ process_secret(s, whackfd);
+ break;
+ }
+ else
+ {
+ /* an id
+ * See RFC2407 IPsec Domain of Interpretation 4.6.2
+ */
+ struct id id;
+ err_t ugh;
+
+ if (tokeq("%any"))
+ {
+ id = empty_id;
+ id.kind = ID_IPV4_ADDR;
+ ugh = anyaddr(AF_INET, &id.ip_addr);
+ }
+ else if (tokeq("%any6"))
+ {
+ id = empty_id;
+ id.kind = ID_IPV6_ADDR;
+ ugh = anyaddr(AF_INET6, &id.ip_addr);
+ }
+ else
+ {
+ ugh = atoid(tok, &id, FALSE);
+ }
+
+ if (ugh != NULL)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "ERROR \"%s\" line %d: index \"%s\" %s"
+ , flp->filename, flp->lino, tok, ugh);
+ }
+ else
+ {
+ id_list_t *i = malloc_thing(id_list_t);
+
+ i->id = id;
+ unshare_id_content(&i->id);
+ i->next = s->ids;
+ s->ids = i;
+ /* DBG_log("id type %d: %s %.*s", i->kind, ip_str(&i->ip_addr), (int)i->name.len, i->name.ptr); */
+ }
+ if (!shift())
+ {
+ /* unexpected Record Boundary or EOF */
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of id list"
+ , flp->filename, flp->lino);
+ break;
+ }
+ }
+ }
}
- }
}
- }
}
-static int
-globugh(const char *epath, int eerrno)
+static int globugh(const char *epath, int eerrno)
{
- log_errno_routine(eerrno, "problem with secrets file \"%s\"", epath);
- return 1; /* stop glob */
+ log_errno_routine(eerrno, "problem with secrets file \"%s\"", epath);
+ return 1; /* stop glob */
}
-static void
-process_secrets_file(const char *file_pat, int whackfd)
+static void process_secrets_file(const char *file_pat, int whackfd)
{
- struct file_lex_position pos;
- char **fnp;
- glob_t globbuf;
-
- pos.depth = flp == NULL? 0 : flp->depth + 1;
+ struct file_lex_position pos;
+ char **fnp;
+ glob_t globbuf;
- if (pos.depth > 10)
- {
- loglog(RC_LOG_SERIOUS, "preshared secrets file \"%s\" nested too deeply", file_pat);
- return;
- }
+ pos.depth = flp == NULL? 0 : flp->depth + 1;
- /* do globbing */
- {
- int r = glob(file_pat, GLOB_ERR, globugh, &globbuf);
+ if (pos.depth > 10)
+ {
+ loglog(RC_LOG_SERIOUS, "preshared secrets file \"%s\" nested too deeply", file_pat);
+ return;
+ }
- if (r != 0)
+ /* do globbing */
{
- switch (r)
- {
- case GLOB_NOSPACE:
- loglog(RC_LOG_SERIOUS, "out of space processing secrets filename \"%s\"", file_pat);
- break;
- case GLOB_ABORTED:
- break; /* already logged */
- case GLOB_NOMATCH:
- loglog(RC_LOG_SERIOUS, "no secrets filename matched \"%s\"", file_pat);
- break;
- default:
- loglog(RC_LOG_SERIOUS, "unknown glob error %d", r);
- break;
- }
- globfree(&globbuf);
- return;
+ int r = glob(file_pat, GLOB_ERR, globugh, &globbuf);
+
+ if (r != 0)
+ {
+ switch (r)
+ {
+ case GLOB_NOSPACE:
+ loglog(RC_LOG_SERIOUS, "out of space processing secrets filename \"%s\"", file_pat);
+ break;
+ case GLOB_ABORTED:
+ break; /* already logged */
+ case GLOB_NOMATCH:
+ loglog(RC_LOG_SERIOUS, "no secrets filename matched \"%s\"", file_pat);
+ break;
+ default:
+ loglog(RC_LOG_SERIOUS, "unknown glob error %d", r);
+ break;
+ }
+ globfree(&globbuf);
+ return;
+ }
}
- }
- /* for each file... */
- for (fnp = globbuf.gl_pathv; *fnp != NULL; fnp++)
- {
- if (lexopen(&pos, *fnp, FALSE))
+ /* for each file... */
+ for (fnp = globbuf.gl_pathv; *fnp != NULL; fnp++)
{
- plog("loading secrets from \"%s\"", *fnp);
- (void) flushline("file starts with indentation (continuation notation)");
- process_secret_records(whackfd);
- lexclose();
+ if (lexopen(&pos, *fnp, FALSE))
+ {
+ plog("loading secrets from \"%s\"", *fnp);
+ (void) flushline("file starts with indentation (continuation notation)");
+ process_secret_records(whackfd);
+ lexclose();
+ }
}
- }
- globfree(&globbuf);
+ globfree(&globbuf);
}
-void
-free_preshared_secrets(void)
+void free_preshared_secrets(void)
{
- lock_certs_and_keys("free_preshared_secrets");
+ lock_certs_and_keys("free_preshared_secrets");
- if (secrets != NULL)
- {
- secret_t *s, *ns;
+ if (secrets != NULL)
+ {
+ secret_t *s, *ns;
- plog("forgetting secrets");
+ plog("forgetting secrets");
- for (s = secrets; s != NULL; s = ns)
- {
- id_list_t *i, *ni;
-
- ns = s->next; /* grab before freeing s */
- for (i = s->ids; i != NULL; i = ni)
- {
- ni = i->next; /* grab before freeing i */
- free_id_content(&i->id);
- pfree(i);
- }
- switch (s->kind)
- {
- case PPK_PSK:
- pfree(s->u.preshared_secret.ptr);
- break;
- case PPK_RSA:
- free_RSA_private_content(&s->u.RSA_private_key);
- break;
- case PPK_XAUTH:
- pfree(s->u.xauth_secret.user_name.ptr);
- pfree(s->u.xauth_secret.user_password.ptr);
- break;
- case PPK_PIN:
- scx_release(s->u.smartcard);
- break;
- default:
- bad_case(s->kind);
- }
- pfree(s);
+ for (s = secrets; s != NULL; s = ns)
+ {
+ id_list_t *i, *ni;
+
+ ns = s->next; /* grab before freeing s */
+ for (i = s->ids; i != NULL; i = ni)
+ {
+ ni = i->next; /* grab before freeing i */
+ free_id_content(&i->id);
+ free(i);
+ }
+ switch (s->kind)
+ {
+ case PPK_PSK:
+ free(s->u.preshared_secret.ptr);
+ break;
+ case PPK_PUBKEY:
+ DESTROY_IF(s->u.private_key);
+ break;
+ case PPK_XAUTH:
+ free(s->u.xauth_secret.user_name.ptr);
+ free(s->u.xauth_secret.user_password.ptr);
+ break;
+ case PPK_PIN:
+ scx_release(s->u.smartcard);
+ break;
+ default:
+ bad_case(s->kind);
+ }
+ free(s);
+ }
+ secrets = NULL;
}
- secrets = NULL;
- }
- unlock_certs_and_keys("free_preshard_secrets");
+ unlock_certs_and_keys("free_preshard_secrets");
}
-void
-load_preshared_secrets(int whackfd)
+void load_preshared_secrets(int whackfd)
{
- free_preshared_secrets();
- (void) process_secrets_file(shared_secrets_file, whackfd);
+ free_preshared_secrets();
+ (void) process_secrets_file(shared_secrets_file, whackfd);
}
/* public key machinery
* Note: caller must set dns_auth_level.
*/
-pubkey_t *
-public_key_from_rsa(const RSA_public_key_t *k)
+pubkey_t* public_key_from_rsa(public_key_t *key)
{
- pubkey_t *p = alloc_thing(pubkey_t, "pubkey");
-
- p->id = empty_id; /* don't know, doesn't matter */
- p->issuer = empty_chunk;
- p->serial = empty_chunk;
- p->alg = PUBKEY_ALG_RSA;
-
- memcpy(p->u.rsa.keyid, k->keyid, sizeof(p->u.rsa.keyid));
- p->u.rsa.k = k->k;
- mpz_init_set(&p->u.rsa.e, &k->e);
- mpz_init_set(&p->u.rsa.n, &k->n);
-
- /* note that we return a 1 reference count upon creation:
- * invariant: recount > 0.
- */
- p->refcnt = 1;
- time(&p->installed_time);
- return p;
+ pubkey_t *p = malloc_thing(pubkey_t);
+
+ zero(p);
+ p->id = empty_id; /* don't know, doesn't matter */
+ p->issuer = chunk_empty;
+ p->serial = chunk_empty;
+ p->public_key = key;
+
+ /* note that we return a 1 reference count upon creation:
+ * invariant: recount > 0.
+ */
+ p->refcnt = 1;
+ time(&p->installed_time);
+ return p;
}
/* Free a public key record.
* As a convenience, this returns a pointer to next.
*/
-pubkey_list_t *
-free_public_keyentry(pubkey_list_t *p)
+pubkey_list_t* free_public_keyentry(pubkey_list_t *p)
{
- pubkey_list_t *nxt = p->next;
+ pubkey_list_t *nxt = p->next;
- if (p->key != NULL)
- unreference_key(&p->key);
- pfree(p);
- return nxt;
+ if (p->key != NULL)
+ {
+ unreference_key(&p->key);
+ }
+ free(p);
+ return nxt;
}
-void
-free_public_keys(pubkey_list_t **keys)
+void free_public_keys(pubkey_list_t **keys)
{
- while (*keys != NULL)
- *keys = free_public_keyentry(*keys);
+ while (*keys != NULL)
+ {
+ *keys = free_public_keyentry(*keys);
+ }
}
/* root of chained public key list */
-pubkey_list_t *pubkeys = NULL; /* keys from ipsec.conf */
+pubkey_list_t *pubkeys = NULL; /* keys from ipsec.conf */
-void
-free_remembered_public_keys(void)
+void free_remembered_public_keys(void)
{
- free_public_keys(&pubkeys);
+ free_public_keys(&pubkeys);
}
-/* transfer public keys from *keys list to front of pubkeys list */
-void
-transfer_to_public_keys(struct gw_info *gateways_from_dns
+/**
+ * Transfer public keys from *keys list to front of pubkeys list
+ */
+void transfer_to_public_keys(struct gw_info *gateways_from_dns
#ifdef USE_KEYRR
, pubkey_list_t **keys
#endif /* USE_KEYRR */
)
{
- {
- struct gw_info *gwp;
-
- for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next)
{
- pubkey_list_t *pl = alloc_thing(pubkey_list_t, "from TXT");
+ struct gw_info *gwp;
- pl->key = gwp->key; /* note: this is a transfer */
- gwp->key = NULL; /* really, it is! */
- pl->next = pubkeys;
- pubkeys = pl;
+ for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
+ pubkey_list_t *pl = malloc_thing(pubkey_list_t);
+
+ pl->key = gwp->key; /* note: this is a transfer */
+ gwp->key = NULL; /* really, it is! */
+ pl->next = pubkeys;
+ pubkeys = pl;
+ }
}
- }
#ifdef USE_KEYRR
- {
- pubkey_list_t **pp = keys;
-
- while (*pp != NULL)
- pp = &(*pp)->next;
- *pp = pubkeys;
- pubkeys = *keys;
- *keys = NULL;
- }
+ {
+ pubkey_list_t **pp = keys;
+
+ while (*pp != NULL)
+ {
+ pp = &(*pp)->next;
+ }
+ *pp = pubkeys;
+ pubkeys = *keys;
+ *keys = NULL;
+ }
#endif /* USE_KEYRR */
}
-/* decode of RSA pubkey chunk
- * - format specified in RFC 2537 RSA/MD5 Keys and SIGs in the DNS
- * - exponent length in bytes (1 or 3 octets)
- * + 1 byte if in [1, 255]
- * + otherwise 0x00 followed by 2 bytes of length
- * - exponent
- * - modulus
- */
-err_t
-unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey)
-{
- chunk_t exp;
- chunk_t mod;
-
- if (pubkey->len < 3)
- return "RSA public key blob way to short"; /* not even room for length! */
-
- if (pubkey->ptr[0] != 0x00)
- {
- setchunk(exp, pubkey->ptr + 1, pubkey->ptr[0]);
- }
- else
- {
- setchunk(exp, pubkey->ptr + 3
- , (pubkey->ptr[1] << BITS_PER_BYTE) + pubkey->ptr[2]);
- }
-
- if (pubkey->len - (exp.ptr - pubkey->ptr) < exp.len + RSA_MIN_OCTETS_RFC)
- return "RSA public key blob too short";
-
- mod.ptr = exp.ptr + exp.len;
- mod.len = &pubkey->ptr[pubkey->len] - mod.ptr;
-
- if (mod.len < RSA_MIN_OCTETS)
- return RSA_MIN_OCTETS_UGH;
-
- if (mod.len > RSA_MAX_OCTETS)
- return RSA_MAX_OCTETS_UGH;
-
- init_RSA_public_key(rsa, exp, mod);
- rsa->k = mpz_sizeinbase(&rsa->n, 2); /* size in bits, for a start */
- rsa->k = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE; /* now octets */
- DBG(DBG_RAW,
- RSA_show_public_key(rsa)
- )
-
- if (rsa->k != mod.len)
- {
- mpz_clear(&rsa->e);
- mpz_clear(&rsa->n);
- return "RSA modulus shorter than specified";
- }
-
- return NULL;
-}
-static void
-install_public_key(pubkey_t *pk, pubkey_list_t **head)
+static void install_public_key(pubkey_t *pk, pubkey_list_t **head)
{
- pubkey_list_t *p = alloc_thing(pubkey_list_t, "pubkey entry");
+ pubkey_list_t *p = malloc_thing(pubkey_list_t);
- unshare_id_content(&pk->id);
+ unshare_id_content(&pk->id);
- /* copy issuer dn */
- if (pk->issuer.ptr != NULL)
- pk->issuer.ptr = clone_bytes(pk->issuer.ptr, pk->issuer.len, "issuer dn");
+ /* copy issuer dn */
+ pk->issuer = chunk_clone(pk->issuer);
- /* copy serial number */
- if (pk->serial.ptr != NULL)
- pk->serial.ptr = clone_bytes(pk->serial.ptr, pk->serial.len, "serialNumber");
+ /* copy serial number */
+ pk->serial = chunk_clone(pk->serial);
- /* store the time the public key was installed */
- time(&pk->installed_time);
+ /* store the time the public key was installed */
+ time(&pk->installed_time);
- /* install new key at front */
- p->key = reference_key(pk);
- p->next = *head;
- *head = p;
+ /* install new key at front */
+ p->key = reference_key(pk);
+ p->next = *head;
+ *head = p;
}
-
-void
-delete_public_keys(const struct id *id, enum pubkey_alg alg
-, chunk_t issuer, chunk_t serial)
+void delete_public_keys(const struct id *id, key_type_t type,
+ chunk_t issuer, chunk_t serial)
{
- pubkey_list_t **pp, *p;
- pubkey_t *pk;
-
- for (pp = &pubkeys; (p = *pp) != NULL; )
- {
- pk = p->key;
-
- if (same_id(id, &pk->id) && pk->alg == alg
- && (issuer.ptr == NULL || pk->issuer.ptr == NULL
- || same_dn(issuer, pk->issuer))
- && same_serial(serial, pk->serial))
- *pp = free_public_keyentry(p);
- else
- pp = &p->next;
- }
+ pubkey_list_t **pp, *p;
+ pubkey_t *pk;
+ key_type_t pk_type;
+
+ for (pp = &pubkeys; (p = *pp) != NULL; )
+ {
+ pk = p->key;
+ pk_type = pk->public_key->get_type(pk->public_key);
+
+ if (same_id(id, &pk->id) && pk_type == type
+ && (issuer.ptr == NULL || pk->issuer.ptr == NULL
+ || same_dn(issuer, pk->issuer))
+ && same_serial(serial, pk->serial))
+ {
+ *pp = free_public_keyentry(p);
+ }
+ else
+ {
+ pp = &p->next;
+ }
+ }
}
-pubkey_t *
-reference_key(pubkey_t *pk)
+pubkey_t* reference_key(pubkey_t *pk)
{
- pk->refcnt++;
- return pk;
+ pk->refcnt++;
+ return pk;
}
void
unreference_key(pubkey_t **pkp)
{
- pubkey_t *pk = *pkp;
- char b[BUF_LEN];
+ pubkey_t *pk = *pkp;
+ char b[BUF_LEN];
- if (pk == NULL)
- return;
+ if (pk == NULL)
+ {
+ return;
+ }
- /* print stuff */
- DBG(DBG_CONTROLMORE,
- idtoa(&pk->id, b, sizeof(b));
- DBG_log("unreference key: %p %s cnt %d--", pk, b, pk->refcnt)
- )
+ /* print stuff */
+ DBG(DBG_CONTROLMORE,
+ idtoa(&pk->id, b, sizeof(b));
+ DBG_log("unreference key: %p %s cnt %d--", pk, b, pk->refcnt)
+ )
- /* cancel out the pointer */
- *pkp = NULL;
+ /* cancel out the pointer */
+ *pkp = NULL;
- passert(pk->refcnt != 0);
- pk->refcnt--;
- if (pk->refcnt == 0)
- free_public_key(pk);
+ passert(pk->refcnt != 0);
+ pk->refcnt--;
+ if (pk->refcnt == 0)
+ {
+ free_public_key(pk);
+ }
}
-err_t
-add_public_key(const struct id *id
-, enum dns_auth_level dns_auth_level
-, enum pubkey_alg alg
-, const chunk_t *key
-, pubkey_list_t **head)
+bool add_public_key(const struct id *id, enum dns_auth_level dns_auth_level,
+ enum pubkey_alg alg, chunk_t rfc3110_key,
+ pubkey_list_t **head)
{
- pubkey_t *pk = alloc_thing(pubkey_t, "pubkey");
+ public_key_t *key = NULL;
+ pubkey_t *pk;
- /* first: algorithm-specific decoding of key chunk */
- switch (alg)
- {
- case PUBKEY_ALG_RSA:
+ /* first: algorithm-specific decoding of key chunk */
+ switch (alg)
{
- err_t ugh = unpack_RSA_public_key(&pk->u.rsa, key);
-
- if (ugh != NULL)
- {
- pfree(pk);
- return ugh;
- }
+ case PUBKEY_ALG_RSA:
+ key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+ BUILD_BLOB_RFC_3110, rfc3110_key,
+ BUILD_END);
+ if (key == NULL)
+ {
+ return FALSE;
+ }
+ break;
+ default:
+ bad_case(alg);
}
- break;
- default:
- bad_case(alg);
- }
-
- pk->id = *id;
- pk->dns_auth_level = dns_auth_level;
- pk->alg = alg;
- pk->until_time = UNDEFINED_TIME;
- pk->issuer = empty_chunk;
- pk->serial = empty_chunk;
-
- install_public_key(pk, head);
- return NULL;
+
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = key;
+ pk->id = *id;
+ pk->dns_auth_level = dns_auth_level;
+ pk->until_time = UNDEFINED_TIME;
+ pk->issuer = chunk_empty;
+ pk->serial = chunk_empty;
+ install_public_key(pk, head);
+ return TRUE;
}
/* extract id and public key from x.509 certificate and
* insert it into a pubkeyrec
*/
-void
-add_x509_public_key(x509cert_t *cert , time_t until
- , enum dns_auth_level dns_auth_level)
+void add_x509_public_key(x509cert_t *cert , time_t until,
+ enum dns_auth_level dns_auth_level)
{
- generalName_t *gn;
- pubkey_t *pk;
- cert_t c = { CERT_X509_SIGNATURE, {cert} };
-
- /* we support RSA only */
- if (cert->subjectPublicKeyAlgorithm != PUBKEY_ALG_RSA)
- return;
-
- /* ID type: ID_DER_ASN1_DN (X.509 subject field) */
- pk = allocate_RSA_public_key(c);
- pk->id.kind = ID_DER_ASN1_DN;
- pk->id.name = cert->subject;
- pk->dns_auth_level = dns_auth_level;
- pk->until_time = until;
- pk->issuer = cert->issuer;
- pk->serial = cert->serialNumber;
- delete_public_keys(&pk->id, pk->alg, pk->issuer, pk->serial);
- install_public_key(pk, &pubkeys);
-
- gn = cert->subjectAltName;
-
- while (gn != NULL) /* insert all subjectAltNames */
- {
- struct id id = empty_id;
-
- gntoid(&id, gn);
- if (id.kind != ID_NONE)
+ generalName_t *gn;
+ pubkey_t *pk;
+ key_type_t pk_type;
+
+ /* ID type: ID_DER_ASN1_DN (X.509 subject field) */
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = cert->public_key->get_ref(cert->public_key);
+ pk->id.kind = ID_DER_ASN1_DN;
+ pk->id.name = cert->subject;
+ pk->dns_auth_level = dns_auth_level;
+ pk->until_time = until;
+ pk->issuer = cert->issuer;
+ pk->serial = cert->serialNumber;
+ pk_type = pk->public_key->get_type(pk->public_key);
+ delete_public_keys(&pk->id, pk_type, pk->issuer, pk->serial);
+ install_public_key(pk, &pubkeys);
+
+ gn = cert->subjectAltName;
+
+ while (gn != NULL) /* insert all subjectAltNames */
{
- pk = allocate_RSA_public_key(c);
- pk->id = id;
- pk->dns_auth_level = dns_auth_level;
- pk->until_time = until;
- pk->issuer = cert->issuer;
- pk->serial = cert->serialNumber;
- delete_public_keys(&pk->id, pk->alg, pk->issuer, pk->serial);
- install_public_key(pk, &pubkeys);
+ struct id id = empty_id;
+
+ gntoid(&id, gn);
+ if (id.kind != ID_ANY)
+ {
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = cert->public_key->get_ref(cert->public_key);
+ pk->id = id;
+ pk->dns_auth_level = dns_auth_level;
+ pk->until_time = until;
+ pk->issuer = cert->issuer;
+ pk->serial = cert->serialNumber;
+ delete_public_keys(&pk->id, pk_type, pk->issuer, pk->serial);
+ install_public_key(pk, &pubkeys);
+ }
+ gn = gn->next;
}
- gn = gn->next;
- }
}
/* extract id and public key from OpenPGP certificate and
* insert it into a pubkeyrec
*/
-void
-add_pgp_public_key(pgpcert_t *cert , time_t until
- , enum dns_auth_level dns_auth_level)
+void add_pgp_public_key(pgpcert_t *cert , time_t until,
+ enum dns_auth_level dns_auth_level)
{
- pubkey_t *pk;
- cert_t c;
-
- c.type = CERT_PGP;
- c.u.pgp = cert;
-
- /* we support RSA only */
- if (cert->pubkeyAlg != PUBKEY_ALG_RSA)
- {
- plog(" RSA public keys supported only");
- return;
- }
-
- pk = allocate_RSA_public_key(c);
- pk->id.kind = ID_KEY_ID;
- pk->id.name.ptr = cert->fingerprint;
- pk->id.name.len = PGP_FINGERPRINT_SIZE;
- pk->dns_auth_level = dns_auth_level;
- pk->until_time = until;
- delete_public_keys(&pk->id, pk->alg, empty_chunk, empty_chunk);
- install_public_key(pk, &pubkeys);
+ pubkey_t *pk;
+ key_type_t pk_type;
+
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = cert->public_key->get_ref(cert->public_key);
+ pk->id.kind = ID_KEY_ID;
+ pk->id.name = cert->fingerprint->get_encoding(cert->fingerprint);
+ pk->dns_auth_level = dns_auth_level;
+ pk->until_time = until;
+ pk_type = pk->public_key->get_type(pk->public_key);
+ delete_public_keys(&pk->id, pk_type, chunk_empty, chunk_empty);
+ install_public_key(pk, &pubkeys);
}
/* when a X.509 certificate gets revoked, all instances of
* the corresponding public key must be removed
*/
-void
-remove_x509_public_key(const x509cert_t *cert)
+void remove_x509_public_key(const x509cert_t *cert)
{
- const cert_t c = {CERT_X509_SIGNATURE, {(x509cert_t*)cert}};
- pubkey_list_t *p, **pp;
- pubkey_t *revoked_pk;
+ public_key_t *revoked_key = cert->public_key;
+ pubkey_list_t *p, **pp;
- revoked_pk = allocate_RSA_public_key(c);
- p = pubkeys;
- pp = &pubkeys;
+ p = pubkeys;
+ pp = &pubkeys;
- while(p != NULL)
- {
- if (same_RSA_public_key(&p->key->u.rsa, &revoked_pk->u.rsa))
- {
- /* remove p from list and free memory */
- *pp = free_public_keyentry(p);
- loglog(RC_LOG_SERIOUS,
- "invalid RSA public key deleted");
- }
- else
+ while(p != NULL)
{
- pp = &p->next;
+ if (revoked_key->equals(revoked_key, p->key->public_key))
+ {
+ /* remove p from list and free memory */
+ *pp = free_public_keyentry(p);
+ loglog(RC_LOG_SERIOUS, "invalid public key deleted");
+ }
+ else
+ {
+ pp = &p->next;
+ }
+ p =*pp;
}
- p =*pp;
- }
- free_public_key(revoked_pk);
}
/*
@@ -1504,45 +1419,41 @@ remove_x509_public_key(const x509cert_t *cert)
*/
void list_public_keys(bool utc)
{
- pubkey_list_t *p = pubkeys;
-
- if (p != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of Public Keys:");
- whack_log(RC_COMMENT, " ");
- }
+ pubkey_list_t *p = pubkeys;
- while (p != NULL)
- {
- pubkey_t *key = p->key;
+ if (p != NULL)
+ {
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of Public Keys:");
+ whack_log(RC_COMMENT, " ");
+ }
- if (key->alg == PUBKEY_ALG_RSA)
+ while (p != NULL)
{
- char buf[BUF_LEN];
- char expires_buf[TIMETOA_BUF];
-
- idtoa(&key->id, buf, BUF_LEN);
- strcpy(expires_buf, timetoa(&key->until_time, utc));
- whack_log(RC_COMMENT, "%s, %4d RSA Key %s, until %s %s",
-
- timetoa(&key->installed_time, utc), 8*key->u.rsa.k, key->u.rsa.keyid,
- expires_buf,
- check_expiry(key->until_time, PUBKEY_WARNING_INTERVAL, TRUE));
- whack_log(RC_COMMENT," %s '%s'",
- enum_show(&ident_names, key->id.kind), buf);
- if (key->issuer.len > 0)
- {
- dntoa(buf, BUF_LEN, key->issuer);
- whack_log(RC_COMMENT," issuer: '%s'", buf);
- }
- if (key->serial.len > 0)
- {
- datatot(key->serial.ptr, key->serial.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT," serial: %s", buf);
- }
+ pubkey_t *key = p->key;
+ public_key_t *public = key->public_key;
+ identification_t *keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
+ char buf[BUF_LEN];
+
+ idtoa(&key->id, buf, BUF_LEN);
+ whack_log(RC_COMMENT,"%T, '%s'", &key->installed_time, utc, buf);
+ whack_log(RC_COMMENT, " pubkey: %N %4d bits, until %T %s",
+ key_type_names, public->get_type(public),
+ public->get_keysize(public) * BITS_PER_BYTE,
+ &key->until_time, utc,
+ check_expiry(key->until_time, PUBKEY_WARNING_INTERVAL, TRUE));
+ whack_log(RC_COMMENT," keyid: %Y", keyid);
+ if (key->issuer.len > 0)
+ {
+ dntoa(buf, BUF_LEN, key->issuer);
+ whack_log(RC_COMMENT," issuer: '%s'", buf);
+ }
+ if (key->serial.len > 0)
+ {
+ datatot(key->serial.ptr, key->serial.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT," serial: %s", buf);
+ }
+ p = p->next;
}
- p = p->next;
- }
}