diff options
| author | Linus Nordberg <linus@nordu.net> | 2012-04-26 10:18:33 +0200 | 
|---|---|---|
| committer | Linus Nordberg <linus@nordu.net> | 2012-04-26 10:18:33 +0200 | 
| commit | 6e6672cffd42def79813dbf7f1588d2ce219ca79 (patch) | |
| tree | 6c408c2806ed8336373a14eb10b2f47ab3645fec | |
| parent | c1f196080a7cb867afd3dee50e2910899cbf5f46 (diff) | |
Implement cert verification.
NOTE: Not used yet.
| -rw-r--r-- | lib/rsp_tlscommon.c | 119 | ||||
| -rw-r--r-- | lib/rsp_tlscommon.h | 5 | ||||
| -rw-r--r-- | lib/tls.c | 78 | ||||
| -rw-r--r-- | lib/tls.h | 1 | 
4 files changed, 85 insertions, 118 deletions
| diff --git a/lib/rsp_tlscommon.c b/lib/rsp_tlscommon.c index 75aa891..abc395e 100644 --- a/lib/rsp_tlscommon.c +++ b/lib/rsp_tlscommon.c @@ -11,7 +11,6 @@  #endif  #include <sys/types.h> -#if defined(RADPROT_TLS) || defined(RADPROT_DTLS)  #include <signal.h>  #include <sys/socket.h>  #include <netinet/in.h> @@ -353,7 +352,7 @@ X509 *verifytlscert(SSL *ssl) {      return cert;  } -static int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) { +int subjectaltnameaddr(X509 *cert, int family, const struct in6_addr *addr) {      int loc, i, l, n, r = 0;      char *v;      X509_EXTENSION *ex; @@ -389,7 +388,7 @@ static int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) {      return r;  } -static int subjectaltnameregexp(X509 *cert, int type, char *exact,  regex_t *regex) { +int subjectaltnameregexp(X509 *cert, int type, const char *exact,  const regex_t *regex) {      int loc, i, l, n, r = 0;      char *s, *v;      X509_EXTENSION *ex; @@ -442,7 +441,7 @@ static int subjectaltnameregexp(X509 *cert, int type, char *exact,  regex_t *reg      return r;  } -static int cnregexp(X509 *cert, char *exact, regex_t *regex) { +int cnregexp(X509 *cert, const char *exact, const regex_t *regex) {      int loc, l;      char *v, *s;      X509_NAME *nm; @@ -545,118 +544,6 @@ int verifyconfcert(X509 *cert, struct clsrvconf *conf) {      return 1;  } -#if 0 -int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { -    struct tls *conf; -    long int expiry = LONG_MIN; - -    debug(DBG_DBG, "conftls_cb called for %s", block); - -    conf = malloc(sizeof(struct tls)); -    if (!conf) { -	debug(DBG_ERR, "conftls_cb: malloc failed"); -	return 0; -    } -    memset(conf, 0, sizeof(struct tls)); - -    if (!getgenericconfig(cf, block, -			  "CACertificateFile", CONF_STR, &conf->cacertfile, -			  "CACertificatePath", CONF_STR, &conf->cacertpath, -			  "CertificateFile", CONF_STR, &conf->certfile, -			  "CertificateKeyFile", CONF_STR, &conf->certkeyfile, -			  "CertificateKeyPassword", CONF_STR, &conf->certkeypwd, -			  "CacheExpiry", CONF_LINT, &expiry, -			  "CRLCheck", CONF_BLN, &conf->crlcheck, -			  "PolicyOID", CONF_MSTR, &conf->policyoids, -			  NULL -	    )) { -	debug(DBG_ERR, "conftls_cb: configuration error in block %s", val); -	goto errexit; -    } -    if (!conf->certfile || !conf->certkeyfile) { -	debug(DBG_ERR, "conftls_cb: TLSCertificateFile and TLSCertificateKeyFile must be specified in block %s", val); -	goto errexit; -    } -    if (!conf->cacertfile && !conf->cacertpath) { -	debug(DBG_ERR, "conftls_cb: CA Certificate file or path need to be specified in block %s", val); -	goto errexit; -    } -    if (expiry != LONG_MIN) { -	if (expiry < 0) { -	    debug(DBG_ERR, "error in block %s, value of option CacheExpiry is %ld, may not be negative", val, expiry); -	    goto errexit; -	} -	conf->cacheexpiry = expiry; -    } - -    conf->name = stringcopy(val, 0); -    if (!conf->name) { -	debug(DBG_ERR, "conftls_cb: malloc failed"); -	goto errexit; -    } - -    if (!tlsconfs) -	tlsconfs = hash_create(); -    if (!hash_insert(tlsconfs, val, strlen(val), conf)) { -	debug(DBG_ERR, "conftls_cb: malloc failed"); -	goto errexit; -    } -    if (!tlsgetctx(RAD_TLS, conf)) -	debug(DBG_ERR, "conftls_cb: error creating ctx for TLS block %s", val); -    debug(DBG_DBG, "conftls_cb: added TLS block %s", val); -    return 1; - -errexit: -    free(conf->cacertfile); -    free(conf->cacertpath); -    free(conf->certfile); -    free(conf->certkeyfile); -    free(conf->certkeypwd); -    freegconfmstr(conf->policyoids); -    free(conf); -    return 0; -} -#endif - -int addmatchcertattr(struct clsrvconf *conf) { -    char *v; -    regex_t **r; - -    if (!strncasecmp(conf->matchcertattr, "CN:/", 4)) { -	r = &conf->certcnregex; -	v = conf->matchcertattr + 4; -    } else if (!strncasecmp(conf->matchcertattr, "SubjectAltName:URI:/", 20)) { -	r = &conf->certuriregex; -	v = conf->matchcertattr + 20; -    } else -	return 0; -    if (!*v) -	return 0; -    /* regexp, remove optional trailing / if present */ -    if (v[strlen(v) - 1] == '/') -	v[strlen(v) - 1] = '\0'; -    if (!*v) -	return 0; - -    *r = malloc(sizeof(regex_t)); -    if (!*r) { -	debug(DBG_ERR, "malloc failed"); -	return 0; -    } -    if (regcomp(*r, v, REG_EXTENDED | REG_ICASE | REG_NOSUB)) { -	free(*r); -	*r = NULL; -	debug(DBG_ERR, "failed to compile regular expression %s", v); -	return 0; -    } -    return 1; -} -#else -/* Just to makes file non-empty, should rather avoid compiling this file when not needed */ -static void tlsdummy() { -} -#endif -  /* Local Variables: */  /* c-file-style: "stroustrup" */  /* End: */ diff --git a/lib/rsp_tlscommon.h b/lib/rsp_tlscommon.h index 6819cd0..0470aa7 100644 --- a/lib/rsp_tlscommon.h +++ b/lib/rsp_tlscommon.h @@ -34,9 +34,10 @@ void ssl_init();  struct tls *tlsgettls(char *alt1, char *alt2);  SSL_CTX *tlsgetctx(uint8_t type, struct tls *t);  X509 *verifytlscert(SSL *ssl); +int subjectaltnameaddr(X509 *cert, int family, const struct in6_addr *addr); +int subjectaltnameregexp(X509 *cert, int type, const char *exact,  const regex_t *regex); +int cnregexp(X509 *cert, const char *exact, const regex_t *regex);  int verifyconfcert(X509 *cert, struct clsrvconf *conf); -int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val); -int addmatchcertattr(struct clsrvconf *conf);  #endif  #if defined (__cplusplus) @@ -9,6 +9,7 @@  #include <openssl/ssl.h>  #include <openssl/err.h>  #include <openssl/bn.h> +#include <openssl/x509v3.h>  #include <radsec/radsec.h>  #include <radsec/radsec-impl.h> @@ -155,3 +156,80 @@ rs_tls_init (struct rs_connection *conn)    rs_free (ctx, tlsconf);    return RSE_OK;  } + +/* draft-ietf-radext-radsec-11.txt + +       *  Certificate validation MUST include the verification rules as +          per [RFC5280]. + +       *  Implementations SHOULD indicate their acceptable Certification +          Authorities as per section 7.4.4 (server side) and x.y.z +          ["Trusted CA Indication"] (client side) of [RFC5246] (see +          Section 3.2) + +       *  Implementations SHOULD allow to configure a list of acceptable +          certificates, identified via certificate fingerprint.  When a +          fingerprint configured, the fingerprint is prepended with an +          ASCII label identifying the hash function followed by a colon. +          Implementations MUST support SHA-1 as the hash algorithm and +          use the ASCII label "sha-1" to identify the SHA-1 algorithm. +          The length of a SHA-1 hash is 20 bytes and the length of the +          corresponding fingerprint string is 65 characters.  An example +          certificate fingerprint is: sha- +          1:E1:2D:53:2B:7C:6B:8A:29:A2:76:C8:64:36:0B:08:4B:7A:F1:9E:9D + +       *  Peer validation always includes a check on whether the locally +          configured expected DNS name or IP address of the server that +          is contacted matches its presented certificate.  DNS names and +          IP addresses can be contained in the Common Name (CN) or +          subjectAltName entries.  For verification, only one of these +          entries is to be considered.  The following precedence +          applies: for DNS name validation, subjectAltName:DNS has +          precedence over CN; for IP address validation, subjectAltName: +          iPAddr has precedence over CN. + +       *  Implementations SHOULD allow to configure a set of acceptable +          values for subjectAltName:URI. + */ +int +tls_verify_cert (struct rs_connection *conn) +{ +  int err = 0; +  int success = 0; +  X509 *peer_cert = NULL; +  struct in6_addr addr; +  const char *hostname = NULL; + +  assert (conn->active_peer->conn == conn); +  assert (conn->active_peer->hostname != NULL); +  hostname = conn->active_peer->hostname; + +  /* verifytlscert() performs basic verification as described by +     OpenSSL VERIFY(1), i.e. verification of the certificate chain.  */ +  peer_cert = verifytlscert (conn->tls_ssl); +  if (peer_cert == NULL) +    { +      err = rs_err_conn_push (conn, RSE_SSLERR, +                              "basic certificate validation failed"); +      goto out; +    } + +  if (inet_pton(AF_INET, hostname, &addr)) +    success = (subjectaltnameaddr (peer_cert, AF_INET, &addr) == 1); +  else if (inet_pton(AF_INET6, hostname, &addr)) +    success = (subjectaltnameaddr (peer_cert, AF_INET6, &addr) == 1); +  else +    success = (subjectaltnameregexp (peer_cert, GEN_DNS, hostname, NULL) == 1); + +  if (!success) +    success = (cnregexp(peer_cert, hostname, NULL) == 1); + +  if (!success) +    err = rs_err_conn_push (conn, RSE_CERT, "server certificate doesn't " +                            "match configured hostname \"%s\"", hostname); + + out: +  if (peer_cert != NULL) +    X509_free (peer_cert); +  return err; +} @@ -6,6 +6,7 @@ extern "C" {  #endif  int rs_tls_init (struct rs_connection *conn); +int tls_verify_cert (struct rs_connection *conn);  #if defined (__cplusplus)  } | 
