Exemplo n.º 1
0
char *nussl_ssl_readable_dname(const nussl_ssl_dname * name)
{
	int n, flag = 0;
	nussl_buffer *dump = nussl_buffer_create();
	const ASN1_OBJECT *const cname = OBJ_nid2obj(NID_commonName),
	    *const email = OBJ_nid2obj(NID_pkcs9_emailAddress);

	for (n = X509_NAME_entry_count(name->dn); n > 0; n--) {
		X509_NAME_ENTRY *ent =
		    X509_NAME_get_entry(name->dn, n - 1);

		/* Skip commonName or emailAddress except if there is no other
		 * attribute in dname. */
		if ((OBJ_cmp(ent->object, cname)
		     && OBJ_cmp(ent->object, email)) || (!flag
							 && n == 1)) {
			if (flag++)
				nussl_buffer_append(dump, ", ", 2);

			if (append_dirstring(dump, ent->value))
				nussl_buffer_czappend(dump, "???");
		}
	}

	return nussl_buffer_finish(dump);
}
Exemplo n.º 2
0
char *ne_ssl_readable_dname(const ne_ssl_dname *name)
{
    gnutls_x509_dn_t dn;
    int ret, rdn = 0, flag = 0;
    ne_buffer *buf;
    gnutls_x509_ava_st val;

#ifdef HAVE_NEW_DN_API
    dn = name->dn;
#else
    if (name->subject)
        ret = gnutls_x509_crt_get_subject(name->cert, &dn);
    else
        ret = gnutls_x509_crt_get_issuer(name->cert, &dn);
    
    if (ret)
        return ne_strdup(_("[unprintable]"));
#endif /* HAVE_NEW_DN_API */

    buf = ne_buffer_create();
    
    /* Find the highest rdn... */
    while (gnutls_x509_dn_get_rdn_ava(dn, rdn++, 0, &val) == 0)
        ;        

    /* ..then iterate back to the first: */
    while (--rdn >= 0) {
        int ava = 0;

        /* Iterate through all AVAs for multivalued AVAs; better than
         * ne_openssl can do! */
        do {
            ret = gnutls_x509_dn_get_rdn_ava(dn, rdn, ava, &val);

            /* If the *only* attribute to append is the common name or
             * email address, use it; otherwise skip those
             * attributes. */
            if (ret == 0 && val.value.size > 0
                && ((!CMPOID(&val, OID_emailAddress)
                     && !CMPOID(&val, OID_commonName))
                    || (buf->used == 1 && rdn == 0))) {
                flag = 1;
                if (buf->used > 1) ne_buffer_append(buf, ", ", 2);

                append_dirstring(buf, &val.value, val.value_tag);
            }
            
            ava++;
        } while (ret == 0);
    }

    return ne_buffer_finish(buf);
}
Exemplo n.º 3
0
/* Check certificate identity.  Returns zero if identity matches; 1 if
 * identity does not match, or <0 if the certificate had no identity.
 * If 'identity' is non-NULL, store the malloc-allocated identity in
 * *identity.  Logic specified by RFC 2818 and RFC 3280. */
static int check_identity(const ne_uri *server, X509 *cert, char **identity)
{
    STACK_OF(GENERAL_NAME) *names;
    int match = 0, found = 0;
    const char *hostname;
    
    hostname = server ? server->host : "";

    names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
    if (names) {
	int n;

        /* subjectAltName contains a sequence of GeneralNames */
	for (n = 0; n < sk_GENERAL_NAME_num(names) && !match; n++) {
	    GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, n);
	    
            /* handle dNSName and iPAddress name extensions only. */
	    if (nm->type == GEN_DNS) {
		char *name = dup_ia5string(nm->d.ia5);
                if (identity && !found) *identity = ne_strdup(name);
		match = ne__ssl_match_hostname(name, strlen(name), hostname);
		free(name);
		found = 1;
            } 
            else if (nm->type == GEN_IPADD) {
                /* compare IP address with server IP address. */
                ne_inet_addr *ia;
                if (nm->d.ip->length == 4)
                    ia = ne_iaddr_make(ne_iaddr_ipv4, nm->d.ip->data);
                else if (nm->d.ip->length == 16)
                    ia = ne_iaddr_make(ne_iaddr_ipv6, nm->d.ip->data);
                else
                    ia = NULL;
                /* ne_iaddr_make returns NULL if address type is unsupported */
                if (ia != NULL) { /* address type was supported. */
                    char buf[128];

                    match = strcmp(hostname, 
                                   ne_iaddr_print(ia, buf, sizeof buf)) == 0;
                    found = 1;
                    ne_iaddr_free(ia);
                } else {
                    NE_DEBUG(NE_DBG_SSL, "iPAddress name with unsupported "
                             "address type (length %d), skipped.\n",
                             nm->d.ip->length);
                }
            } 
            else if (nm->type == GEN_URI) {
                char *name = dup_ia5string(nm->d.ia5);
                ne_uri uri;

                if (ne_uri_parse(name, &uri) == 0 && uri.host && uri.scheme) {
                    ne_uri tmp;

                    if (identity && !found) *identity = ne_strdup(name);
                    found = 1;

                    if (server) {
                        /* For comparison purposes, all that matters is
                         * host, scheme and port; ignore the rest. */
                        memset(&tmp, 0, sizeof tmp);
                        tmp.host = uri.host;
                        tmp.scheme = uri.scheme;
                        tmp.port = uri.port;
                        
                        match = ne_uri_cmp(server, &tmp) == 0;
                    }
                }

                ne_uri_free(&uri);
                free(name);
            }
	}
        /* free the whole stack. */
        sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
    }
    
    /* Check against the commonName if no DNS alt. names were found,
     * as per RFC3280. */
    if (!found) {
	X509_NAME *subj = X509_get_subject_name(cert);
	X509_NAME_ENTRY *entry;
	ne_buffer *cname = ne_buffer_ncreate(30);
	int idx = -1, lastidx;

	/* find the most specific commonName attribute. */
	do {
	    lastidx = idx;
	    idx = X509_NAME_get_index_by_NID(subj, NID_commonName, lastidx);
	} while (idx >= 0);
	
	if (lastidx < 0) {
            /* no commonName attributes at all. */
            ne_buffer_destroy(cname);
	    return -1;
        }

	/* extract the string from the entry */
        entry = X509_NAME_get_entry(subj, lastidx);
        if (append_dirstring(cname, X509_NAME_ENTRY_get_data(entry))) {
            ne_buffer_destroy(cname);
            return -1;
        }
        if (identity) *identity = ne_strdup(cname->data);
        match = ne__ssl_match_hostname(cname->data, cname->used - 1, hostname);
        ne_buffer_destroy(cname);
    }

    NE_DEBUG(NE_DBG_SSL, "Identity match for '%s': %s\n", hostname, 
             match ? "good" : "bad");
    return match ? 0 : 1;
}
Exemplo n.º 4
0
/* static int check_identity(const nussl_uri *server, X509 *cert, char **identity) */
static int check_identity(const char *expected_hostname, X509 * cert, char **identity)
{
	STACK_OF(GENERAL_NAME) * names;
	int match = 0, found = 0;
	char *found_hostname = NULL;

/*     hostname = server ? server->host : ""; */

	names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
	/* if expected_hostname is NULL, do not check subjectAltName,
	 * we are only looking for the CN
	 */
	if (names && expected_hostname != NULL) {
		int n;

		/* subjectAltName contains a sequence of GeneralNames */
		for (n = 0; n < sk_GENERAL_NAME_num(names) && !match; n++) {
			GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, n);

			/* handle dNSName and iPAddress name extensions only. */
			if (nm->type == GEN_DNS) {
				found_hostname = dup_ia5string(nm->d.ia5);
				match = match_hostname(found_hostname, expected_hostname);
				if (match) {
					found = 1;
					if (identity)
						*identity = nussl_strdup(found_hostname);
				}
			}
			else
			if (nm->type == GEN_IPADD) {
				/* compare IP address with server IP address. */
				nussl_inet_addr *ia;
				if (nm->d.ip->length == 4)
					ia = nussl_iaddr_make(nussl_iaddr_ipv4, nm->d.ip->data);
				else if (nm->d.ip->length == 16)
					ia = nussl_iaddr_make(nussl_iaddr_ipv6, nm->d.ip->data);
				else
					ia = NULL;
				/* nussl_iaddr_make returns NULL if address type is unsupported */
/*                 if (ia != NULL) { /\* address type was supported. *\/ */
/*                     char buf[128]; */

/*                     match = strcmp(hostname,  */
/*                                    nussl_iaddr_print(ia, buf, sizeof buf)) == 0; */
/*                     found = 1; */
/*                     nussl_iaddr_free(ia); */
/*                 } else { */
/*                     NUSSL_DEBUG(NUSSL_DBG_SSL, "iPAddress name with unsupported " */
/*                              "address type (length %d), skipped.\n", */
/*                              nm->d.ip->length); */
/*                 } */
			}
/*             else if (nm->type == GEN_URI) { */
/*                 char *name = dup_ia5string(nm->d.ia5); */
/*                 nussl_uri uri; */

/*                 if (nussl_uri_parse(name, &uri) == 0 && uri.host && uri.scheme) { */
/*                     nussl_uri tmp; */

/*                     if (identity && !found) *identity = nussl_strdup(name); */
/*                     found = 1; */

/*                     if (server) { */
/*                         /\* For comparison purposes, all that matters is */
/*                          * host, scheme and port; ignore the rest. *\/ */
/*                         memset(&tmp, 0, sizeof tmp); */
/*                         tmp.host = uri.host; */
/*                         tmp.scheme = uri.scheme; */
/*                         tmp.port = uri.port; */

/*                         match = nussl_uri_cmp(server, &tmp) == 0; */
/*                     } */
/*                 } */

/*                 nussl_uri_free(&uri); */
/*                 nussl_free(name); */
/*             } */
		}
	}

	/* free the whole stack. */
	if (names)
		sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);

	/* Check against the commonName if no DNS alt. names were found,
	 * as per RFC3280. */
	if (!found) {
		X509_NAME *subj = X509_get_subject_name(cert);
		X509_NAME_ENTRY *entry;
		nussl_buffer *cname = nussl_buffer_ncreate(30);
		int idx = -1, lastidx;

		/* find the most specific commonName attribute. */
		do {
			lastidx = idx;
			idx = X509_NAME_get_index_by_NID(subj,
						       NID_commonName,
						       lastidx);
		} while (idx >= 0);

		/* check commonName attribute if present */
		if (lastidx >= 0) {
			/* extract the string from the entry */
			entry = X509_NAME_get_entry(subj, lastidx);
			if (append_dirstring(cname, X509_NAME_ENTRY_get_data(entry))) {
				nussl_buffer_destroy(cname);
				return -1;
			}

			found_hostname = nussl_strdup(cname->data);
			if (expected_hostname != NULL)
				match = match_hostname(found_hostname, expected_hostname);
		}
		nussl_buffer_destroy(cname);
	}

	if (found_hostname == NULL)
		return 1;

	/*NUSSL_DEBUG(NUSSL_DBG_SSL, "Identity match for '%s' (identity: %s): %s\n",
			expected_hostname, found_hostname,
			match ? "good" : "bad");*/
	if (identity != NULL)
		*identity = nussl_strdup(found_hostname);
	nussl_free(found_hostname);
	return match ? 0 : 1;
}