static int
verify_cert_hostname(X509 *cert, char *hostname) {
  int                   extcount, i, j, ok = 0;
  char                  name[256];
  X509_NAME             *subj;
  const char            *extstr;
  CONF_VALUE            *nval;
  const unsigned char   *data;
  X509_EXTENSION        *ext;
  X509V3_EXT_METHOD     *meth;
  STACK_OF(CONF_VALUE)  *val;

  if ((extcount = X509_get_ext_count(cert)) > 0) {
    for (i = 0;  !ok && i < extcount;  i++) {
      ext = X509_get_ext(cert, i);
      extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
      if (!strcasecmp(extstr, "subjectAltName")) {
        if (!(meth = (X509V3_EXT_METHOD *)X509V3_EXT_get(ext))) break;
        data = ext->value->data;

        val = meth->i2v(meth, meth->d2i(0, &data, ext->value->length), 0);
        for (j = 0;  j < sk_CONF_VALUE_num(val);  j++) {
          nval = sk_CONF_VALUE_value(val, j);
          if (!strcasecmp(nval->name, "DNS") && !strcasecmp(nval->value, hostname)) {
            ok = 1;
            break;
          }
        }
      }
    }
  }

  if (!ok && (subj = X509_get_subject_name(cert)) &&
      X509_NAME_get_text_by_NID(subj, NID_commonName, name, sizeof(name)) > 0) {
    name[sizeof(name) - 1] = '\0';
    if (!strcasecmp(name, hostname)) ok = 1;
  }

  return ok;
}
Exemple #2
0
/* Match a hostname against the contents of a dNSName field of the
   subjectAltName extension, if present. This is the preferred place for a
   certificate to store its domain name, as opposed to in the commonName field.
   It has the advantage that multiple names can be stored, so that one
   certificate can match both "example.com" and "www.example.com".

   If num_checked is not NULL, the number of dNSName fields that were checked
   before returning will be stored in it. This is so you can distinguish between
   the check failing because there were names but none matched, or because there
   were no names to match. */
static int cert_match_dnsname(X509 *cert, const char *hostname,
    unsigned int *num_checked)
{
    X509_EXTENSION *ext;
    STACK_OF(GENERAL_NAME) *gen_names;
    const X509V3_EXT_METHOD *method;
    unsigned char *data;
    int i;

    if (num_checked != NULL)
        *num_checked = 0;

    i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
    if (i < 0)
        return 0;
    /* If there's more than one subjectAltName extension, forget it. */
    if (X509_get_ext_by_NID(cert, NID_subject_alt_name, i) >= 0)
        return 0;
    ext = X509_get_ext(cert, i);

    /* See the function X509V3_EXT_print in the OpenSSL source for this method
       of getting a string value from an extension. */
    method = X509V3_EXT_get(ext);
    if (method == NULL)
        return 0;

    /* We must copy this address into a temporary variable because ASN1_item_d2i
       increments it. We don't want it to corrupt ext->value->data. */
    data = ext->value->data;
    /* Here we rely on the fact that the internal representation (the "i" in
       "i2d") for NID_subject_alt_name is STACK_OF(GENERAL_NAME). Converting it
       to a stack of CONF_VALUE with a i2v method is not satisfactory, because a
       CONF_VALUE doesn't contain the length of the value so you can't know the
       presence of null bytes. */
#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
    if (method->it != NULL) {
        gen_names = (STACK_OF(GENERAL_NAME) *) ASN1_item_d2i(NULL,
            (const unsigned char **) &data,
            ext->value->length, ASN1_ITEM_ptr(method->it));
    } else {
Exemple #3
0
static Str
ssl_check_cert_ident(X509 * x, char *hostname)
{
    int i;
    Str ret = NULL;
    int match_ident = FALSE;
    /*
     * All we need to do here is check that the CN matches.
     *
     * From RFC2818 3.1 Server Identity:
     * If a subjectAltName extension of type dNSName is present, that MUST
     * be used as the identity. Otherwise, the (most specific) Common Name
     * field in the Subject field of the certificate MUST be used. Although
     * the use of the Common Name is existing practice, it is deprecated and
     * Certification Authorities are encouraged to use the dNSName instead.
     */
    i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
    if (i >= 0) {
	X509_EXTENSION *ex;
	STACK_OF(GENERAL_NAME) * alt;

	ex = X509_get_ext(x, i);
	alt = X509V3_EXT_d2i(ex);
	if (alt) {
	    int n;
	    GENERAL_NAME *gn;
	    X509V3_EXT_METHOD *method;
	    Str seen_dnsname = NULL;

	    n = sk_GENERAL_NAME_num(alt);
	    for (i = 0; i < n; i++) {
		gn = sk_GENERAL_NAME_value(alt, i);
		if (gn->type == GEN_DNS) {
		    char *sn = ASN1_STRING_data(gn->d.ia5);
		    int sl = ASN1_STRING_length(gn->d.ia5);

		    if (!seen_dnsname)
			seen_dnsname = Strnew();
		    /* replace \0 to make full string visible to user */
		    if (sl != strlen(sn)) {
			int i;
			for (i = 0; i < sl; ++i) {
			    if (!sn[i])
				sn[i] = '!';
			}
		    }
		    Strcat_m_charp(seen_dnsname, sn, " ", NULL);
		    if (sl == strlen(sn) /* catch \0 in SAN */
			&& ssl_match_cert_ident(sn, sl, hostname))
			break;
		}
	    }
	    method = X509V3_EXT_get(ex);
	    sk_GENERAL_NAME_free(alt);
	    if (i < n)		/* Found a match */
		match_ident = TRUE;
	    else if (seen_dnsname)
		/* FIXME: gettextize? */
		ret = Sprintf("Bad cert ident from %s: dNSName=%s", hostname,
			      seen_dnsname->ptr);
	}
    }

    if (match_ident == FALSE && ret == NULL) {
	X509_NAME *xn;
	char buf[2048];
	int slen;

	xn = X509_get_subject_name(x);

	slen = X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof(buf));
	if ( slen == -1)
	    /* FIXME: gettextize? */
	    ret = Strnew_charp("Unable to get common name from peer cert");
	else if (slen != strlen(buf)
		|| !ssl_match_cert_ident(buf, strlen(buf), hostname)) {
	    /* replace \0 to make full string visible to user */
	    if (slen != strlen(buf)) {
		int i;
		for (i = 0; i < slen; ++i) {
		    if (!buf[i])
			buf[i] = '!';
		}
	    }
	    /* FIXME: gettextize? */
	    ret = Sprintf("Bad cert ident %s from %s", buf, hostname);
	}
	else
	    match_ident = TRUE;
    }
    return ret;
}
Exemple #4
0
su_inline
int tls_post_connection_check(tport_t *self, tls_t *tls)
{
  X509 *cert;
  int extcount;
  int i, j, error;

  if (!tls) return -1;

  cert = SSL_get_peer_certificate(tls->con);
  if (!cert) {
    SU_DEBUG_7(("%s(%p): Peer did not provide X.509 Certificate.\n", 
				__func__, (void *) self));
    if (self->tp_accepted && tls->verify_incoming)
      return X509_V_ERR_CERT_UNTRUSTED;
    else if (!self->tp_accepted && tls->verify_outgoing)
      return X509_V_ERR_CERT_UNTRUSTED;
    else 
      return X509_V_OK;
  }

  tls->subjects = su_strlst_create(tls->home);
  if (!tls->subjects)
    return X509_V_ERR_OUT_OF_MEM;

  extcount = X509_get_ext_count(cert);

  /* Find matching subjectAltName.DNS */
  for (i = 0; i < extcount; i++) {
    X509_EXTENSION *ext;
    char const *name;
#if OPENSSL_VERSION_NUMBER >  0x10000000L
    const X509V3_EXT_METHOD *vp;
#else
    X509V3_EXT_METHOD *vp;
#endif
    STACK_OF(CONF_VALUE) *values;
    CONF_VALUE *value;
    void *d2i;

    ext = X509_get_ext(cert, i);
    name = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));

    if (strcmp(name, "subjectAltName") != 0)
      continue;

    vp = X509V3_EXT_get(ext); if (!vp) continue;
    d2i = X509V3_EXT_d2i(ext);
    values = vp->i2v(vp, d2i, NULL);

    for (j = 0; j < sk_CONF_VALUE_num(values); j++) {
      value = sk_CONF_VALUE_value(values, j);
      if (strcmp(value->name, "DNS") == 0)
        su_strlst_dup_append(tls->subjects, value->value);
      if (strcmp(value->name, "IP") == 0)
        su_strlst_dup_append(tls->subjects, value->value);
      else if (strcmp(value->name, "URI") == 0)
        su_strlst_dup_append(tls->subjects, value->value);
    }
  }

  {
    X509_NAME *subject;
    char name[256];

    subject = X509_get_subject_name(cert);

    if (subject) {
      if (X509_NAME_get_text_by_NID(subject, NID_commonName,
				    name, sizeof name) > 0) {
	usize_t k, N = su_strlst_len(tls->subjects);
	name[(sizeof name) - 1] = '\0';

	for (k = 0; k < N; k++)
	  if (su_casematch(su_strlst_item(tls->subjects, k), name) == 0)
	    break;

	if (k >= N)
	  su_strlst_dup_append(tls->subjects, name);
      }
    }
  }

  X509_free(cert);

  error = SSL_get_verify_result(tls->con);

  if (cert && error == X509_V_OK)
    tls->x509_verified = 1;

  if (tport_log->log_level >= 7) {
    int i, len = su_strlst_len(tls->subjects);
    for (i=0; i < len; i++)
      SU_DEBUG_7(("%s(%p): Peer Certificate Subject %i: %s\n", \
				  __func__, (void *)self, i, su_strlst_item(tls->subjects, i)));
    if (i == 0)
      SU_DEBUG_7(("%s(%p): Peer Certificate provided no usable subjects.\n",
				  __func__, (void *)self));
  }

  /* Verify incoming connections */
  if (self->tp_accepted) {
    if (!tls->verify_incoming)
      return X509_V_OK;

    if (!tls->x509_verified)
      return error;

    if (tls->verify_subj_in) {
      su_strlst_t const *subjects = self->tp_pri->pri_primary->tp_subjects;
      int i, items;

      items = subjects ? su_strlst_len(subjects) : 0;
      if (items == 0)
        return X509_V_OK;

      for (i=0; i < items; i++) {
	if (tport_subject_search(su_strlst_item(subjects, i), tls->subjects))
	  return X509_V_OK;
      }
      SU_DEBUG_3(("%s(%p): Peer Subject Mismatch (incoming connection)\n", \
				  __func__, (void *)self));

      return X509_V_ERR_CERT_UNTRUSTED;
    }
  }
  /* Verify outgoing connections */
  else {
    char const *subject = self->tp_canon;
    if (!tls->verify_outgoing)
      return X509_V_OK;

    if (!tls->x509_verified || !subject)
      return error;

    if (tls->verify_subj_out) {
      if (tport_subject_search(subject, tls->subjects))
        return X509_V_OK; /* Subject match found in verified certificate chain */
      SU_DEBUG_3(("%s(%p): Peer Subject Mismatch (%s)\n", \
				  __func__, (void *)self, subject));

      return X509_V_ERR_CERT_UNTRUSTED;
    }
  }

  return error;
}
Exemple #5
0
/**
 Search for a hostname match in the SubjectAlternativeNames.
*/
uint32_t
check_san (SSL *ssl, const char *hostname)
{
  X509 *cert;
  int extcount, ok = 0;
  /* What an OpenSSL mess ... */
  if (NULL == (cert = SSL_get_peer_certificate(ssl)))
  {
    die ("Getting certificate failed");
  }

  if ((extcount = X509_get_ext_count(cert)) > 0)
  {
    int i;
    for (i = 0; i < extcount; ++i)
    {
      const char *extstr;
      X509_EXTENSION *ext;
      ext = X509_get_ext(cert, i);
      extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));

      if (!strcmp(extstr, "subjectAltName"))
      {

        int j;
        void *extvalstr;
        const unsigned char *tmp;

        STACK_OF(CONF_VALUE) *val;
        CONF_VALUE *nval;
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
        const
#endif
        X509V3_EXT_METHOD *method;

        if (!(method = X509V3_EXT_get(ext)))
        {
          break;
        }

        tmp = ext->value->data;
        if (method->it)
        {
          extvalstr = ASN1_item_d2i(NULL, &tmp, ext->value->length,
                                    ASN1_ITEM_ptr(method->it));
        } else {
          extvalstr = method->d2i(NULL, &tmp, ext->value->length);
        }

        if (!extvalstr)
        {
          break;
        }

        if (method->i2v)
        {
          val = method->i2v(method, extvalstr, NULL);
          for (j = 0; j < sk_CONF_VALUE_num(val); ++j)
          {
            nval = sk_CONF_VALUE_value(val, j);
            if ((!strcasecmp(nval->name, "DNS") &&
                !strcasecmp(nval->value, hostname) ) ||
                (!strcasecmp(nval->name, "iPAddress") &&
                !strcasecmp(nval->value, hostname)))
            {
              verb ("V: subjectAltName matched: %s, type: %s", nval->value, nval->name); // We matched this; so it's safe to print
              ok = 1;
              break;
            }
            // Attempt to match subjectAltName DNS names
            if (!strcasecmp(nval->name, "DNS"))
            {
              ok = check_wildcard_match_rfc2595(hostname, nval->value);
              if (ok)
              {
                break;
              }
            }
            verb_debug ("V: subjectAltName found but not matched: %s, type: %s",
                nval->value, sanitize_string(nval->name));
          }
        }
      } else {
        verb_debug ("V: found non subjectAltName extension");
      }
      if (ok)
      {
        break;
      }
    }
  } else {
    verb_debug ("V: no X509_EXTENSION field(s) found");
  }
  X509_free(cert);
  return ok;
}
Exemple #6
0
//extention to SSL_get_verify_result
int CSSLClient::PostConnectCheck(SSL *ssl, const char *pHost)
{
	X509 *cert;
	X509_NAME *subj;
	char data[256];
	int extcount;
	int ret = 0;

	do 
	{
		if (!(cert = SSL_get_peer_certificate(ssl)) || !pHost)
		{
			break;
		}
		if ((extcount = X509_get_ext_count(cert)) > 0)
		{
			int i;
			for (i = 0; i < extcount; i++)
			{
				const char *extstr;
				X509_EXTENSION *ext;
				ext = X509_get_ext(cert, i);
				extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
				if (!strcmp(extstr, SN_subject_alt_name))
				{
					int j;
					const unsigned char *pData;
					STACK_OF(CONF_VALUE) *val;
					CONF_VALUE *nval;
					const X509V3_EXT_METHOD *pExtMethod;
					if (!(pExtMethod = X509V3_EXT_get(ext)))
					{
						break;
					}
					pData = ext->value->data;
					val = pExtMethod->i2v(pExtMethod, pExtMethod->d2i(NULL, &pData, ext->value->length), NULL);
					for (j = 0; j < sk_CONF_VALUE_num(val); j++)
					{
						nval = sk_CONF_VALUE_value(val, j);
						if (!strcmp(nval->name, "DNS") && !strcmp(nval->value, pHost))
						{
							ret = 1;
							break;
						}
					}
				}
				if (ret)
				{
					break;
				}
			}//end of for(; extentcount; )
		}
		if (!ret && (subj = X509_get_subject_name(cert)) && X509_NAME_get_text_by_NID(subj, NID_commonName, data, 256) > 0)
		{
			data[255] = 0;
			if (strcmp(data, pHost) != 0)
			{
				break;
			}
		}

		X509_free(cert);
		ret = SSL_get_verify_result(ssl);
		return ret;

	} while(0);

	if (cert)
	{
		X509_free(cert);
	}
	return -1;
}
Exemple #7
0
/*
 * Check that the common name matches the host name
 */
static int
check_cert_chain(conn_t * conn, SSL * ssl, ruleset_t * rs)
{
	X509           *peer;
	X509_NAME      *xn;
	static char     subject[1024];
	int             r = FALSE, extc;

	if (SSL_get_verify_result(ssl) != X509_V_OK) {
		LOG(SPOCP_ERR) traceLog(LOG_ERR,"Certificate doesn't verify");
		return FALSE;
	}

	/*
	 * Check the cert chain. The chain length is automatically checked by
	 * OpenSSL when we set the verify depth in the ctx 
	 */

	peer = SSL_get_peer_certificate(ssl);
	if (!peer) {
		LOG(SPOCP_ERR) traceLog(LOG_ERR,"No peer certificate");
		return TRUE;
	}

	/*
	 * check subjectaltname 
	 */

	if ((extc = X509_get_ext_count(peer)) > 0) {
		int             i;

		for (i = 0; r == FALSE && i < extc; i++) {
			X509_EXTENSION *ext;
			const char     *extstr;

			ext = X509_get_ext(peer, i);
			extstr =
			    OBJ_nid2sn(OBJ_obj2nid
				       (X509_EXTENSION_get_object(ext)));

			if (strcmp(extstr, "subjectAltName") == 0) {
				int             j;
				unsigned char  *data;
				STACK_OF(CONF_VALUE) * val;
				CONF_VALUE     *nval;
				X509V3_EXT_METHOD *meth;

				if ((meth = X509V3_EXT_get(ext)) == 0)
					break;

				data = ext->value->data;

				val =
				    meth->i2v(meth,
					      meth->d2i(NULL, &data,
							ext->value->length),
					      NULL);

				for (j = 0;
				     r == FALSE && i < sk_CONF_VALUE_num(val);
				     j++) {
					nval = sk_CONF_VALUE_value(val, j);
					if (strcasecmp(nval->name, "DNS") == 0
					    && strcasecmp(nval->value,
							  conn->sri.
							  hostname)) {
						r = TRUE;
					}
				}
			}
		}
	}

	if (r == FALSE) {
		/*
		 * Check the subject name 
		 */
		xn = X509_get_subject_name(peer);
		X509_NAME_get_text_by_NID(xn, NID_commonName, subject, 1024);
		subject[1023] = '\0';

		traceLog(LOG_DEBUG,"\"%s\" = \"%s\" ?", subject, conn->sri.hostname);
		if (strcasecmp(subject, conn->sri.hostname) == 0) {
			r = TRUE;
		}
	}

	if (r == TRUE) {
		conn->subjectDN =
		    X509_NAME_oneline(X509_get_subject_name(peer), NULL, 0);
		conn->issuerDN =
		    X509_NAME_oneline(X509_get_issuer_name(peer), NULL, 0);
	}

	X509_free(peer);

	return r;
}
Exemple #8
0
static PyObject *
_get_peer_alt_names (X509 *certificate) {

	/* this code follows the procedure outlined in
	   OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print()
	   function to extract the STACK_OF(GENERAL_NAME),
	   then iterates through the stack to add the
	   names. */

	int i, j;
	PyObject *peer_alt_names = Py_None;
	PyObject *v, *t;
	X509_EXTENSION *ext = NULL;
	GENERAL_NAMES *names = NULL;
	GENERAL_NAME *name;
	X509V3_EXT_METHOD *method;
	BIO *biobuf = NULL;
	char buf[2048];
	char *vptr;
	int len;
	const unsigned char *p;

	if (certificate == NULL)
		return peer_alt_names;

	/* get a memory buffer */
	biobuf = BIO_new(BIO_s_mem());

	i = 0;
	while ((i = X509_get_ext_by_NID(
			certificate, NID_subject_alt_name, i)) >= 0) {

		if (peer_alt_names == Py_None) {
                        peer_alt_names = PyList_New(0);
                        if (peer_alt_names == NULL)
				goto fail;
		}

		/* now decode the altName */
		ext = X509_get_ext(certificate, i);
		if(!(method = X509V3_EXT_get(ext))) {
			PyErr_SetString
                          (PySSLErrorObject,
                           ERRSTR("No method for internalizing subjectAltName!"));
			goto fail;
		}

		p = ext->value->data;
		if (method->it)
			names = (GENERAL_NAMES*)
                          (ASN1_item_d2i(NULL,
                                         &p,
                                         ext->value->length,
                                         ASN1_ITEM_ptr(method->it)));
		else
			names = (GENERAL_NAMES*)
                          (method->d2i(NULL,
                                       &p,
                                       ext->value->length));

		for(j = 0; j < sk_GENERAL_NAME_num(names); j++) {

			/* get a rendering of each name in the set of names */

			name = sk_GENERAL_NAME_value(names, j);
			if (name->type == GEN_DIRNAME) {

				/* we special-case DirName as a tuple of
                                   tuples of attributes */

				t = PyTuple_New(2);
				if (t == NULL) {
					goto fail;
				}

				v = PyUnicode_FromString("DirName");
				if (v == NULL) {
					Py_DECREF(t);
					goto fail;
				}
				PyTuple_SET_ITEM(t, 0, v);

				v = _create_tuple_for_X509_NAME (name->d.dirn);
				if (v == NULL) {
					Py_DECREF(t);
					goto fail;
				}
				PyTuple_SET_ITEM(t, 1, v);

			} else {

				/* for everything else, we use the OpenSSL print form */

				(void) BIO_reset(biobuf);
				GENERAL_NAME_print(biobuf, name);
				len = BIO_gets(biobuf, buf, sizeof(buf)-1);
				if (len < 0) {
					_setSSLError(NULL, 0, __FILE__, __LINE__);
					goto fail;
				}
				vptr = strchr(buf, ':');
				if (vptr == NULL)
					goto fail;
				t = PyTuple_New(2);
				if (t == NULL)
					goto fail;
				v = PyUnicode_FromStringAndSize(buf, (vptr - buf));
				if (v == NULL) {
					Py_DECREF(t);
					goto fail;
				}
				PyTuple_SET_ITEM(t, 0, v);
				v = PyUnicode_FromStringAndSize((vptr + 1),
                                                                (len - (vptr - buf + 1)));
				if (v == NULL) {
					Py_DECREF(t);
					goto fail;
				}
				PyTuple_SET_ITEM(t, 1, v);
			}

			/* and add that rendering to the list */

			if (PyList_Append(peer_alt_names, t) < 0) {
				Py_DECREF(t);
				goto fail;
			}
			Py_DECREF(t);
		}
	}
	BIO_free(biobuf);
	if (peer_alt_names != Py_None) {
		v = PyList_AsTuple(peer_alt_names);
		Py_DECREF(peer_alt_names);
		return v;
	} else {
		return peer_alt_names;
	}


  fail:
	if (biobuf != NULL)
		BIO_free(biobuf);

	if (peer_alt_names != Py_None) {
		Py_XDECREF(peer_alt_names);
	}

	return NULL;
}
Exemple #9
0
int protocol_checknameconstraints(const struct peer_s *peer)
{
  struct in_network ncnet, *shnet;
  int i, j, r, ret = 0, valid = 0;
  const unsigned char *p;
  void *ext_str = NULL;
  X509 *cert;
  STACK_OF(X509_EXTENSION) * exts;
  X509_EXTENSION *ext;
  const X509V3_EXT_METHOD *method;
  STACK_OF(GENERAL_SUBTREE) * trees;
  GENERAL_SUBTREE *tree;

  pthread_mutex_lock(&peer->udpsrvsession->dtls_mutex);
  cert = SSL_get_peer_certificate(peer->udpsrvsession->dtls);
  exts = cert->cert_info->extensions;
  for (r = 0; r < peer->shared_networks_len; r++)
    {
      shnet = &peer->shared_networks[r];
      for (i = 0; i < sk_X509_EXTENSION_num(exts); i++)
        {
          ext = sk_X509_EXTENSION_value(exts, i);
          if ((method = X509V3_EXT_get(ext))
              && method->ext_nid == NID_name_constraints)
            {
              p = ext->value->data;
              if (method->it)
                ext_str = ASN1_item_d2i(NULL, &p, ext->value->length,
                                        ASN1_ITEM_ptr(method->it));
              else
                ext_str = method->d2i(NULL, &p, ext->value->length);

              trees = ((NAME_CONSTRAINTS *) ext_str)->permittedSubtrees;
              for (j = 0; j < sk_GENERAL_SUBTREE_num(trees); j++)
                {
                  tree = sk_GENERAL_SUBTREE_value(trees, j);
                  if (tree->base->type == GEN_IPADD)
                    {
                      if (tree->base->d.ip->length == 8)
                        {
                          ncnet.addr.s_addr =
                            *((uint32_t *) tree->base->d.ip->data);
                          ncnet.netmask.s_addr =
                            *((uint32_t *) & tree->base->d.ip->data[4]);
                          if (shnet->netmask.s_addr >= ncnet.netmask.s_addr
                              && (ncnet.addr.s_addr & ncnet.netmask.s_addr)
                              == (shnet->addr.s_addr &
                                  shnet->netmask.s_addr))
                            valid++;
                        }
//else if(tree->base->d.ip->length == 32) //IPv6
//  See openssl/crypto/x509v3/v3_ncons.c:static int print_nc_ipadd()
//} else { //DNS
//  GENERAL_NAME_print(bp, tree->base);
                    }
                }
            }
        }
      if (valid == 0){
        ret = -1;
        break;
      }
      ret += valid;
      valid = 0;
    }
  pthread_mutex_unlock(&peer->udpsrvsession->dtls_mutex);
  return ret;
}
Exemple #10
0
long ipfix_ssl_post_connection_check(SSL *ssl, char *host)
{
    X509      *cert;
    X509_NAME *subj;
    char      data[256];
    int       extcount;
    int       ok = 0;

    /* Checking the return from SSL_get_peer_certificate here is not strictly
     * necessary.
     */
    if (!(cert = SSL_get_peer_certificate(ssl)) || !host)
        goto err_occured;
    if ((extcount = X509_get_ext_count(cert)) > 0)
    {
        int i;

        for (i = 0;  i < extcount;  i++)
        {
            char              *extstr;
            X509_EXTENSION    *ext;

            ext = X509_get_ext(cert, i);
            extstr = (char*) OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));

            if (!strcmp(extstr, "subjectAltName"))
            {
                int                  j;
                const unsigned char  *data;
                STACK_OF(CONF_VALUE) *val;
                CONF_VALUE           *nval;
                X509V3_EXT_METHOD    *meth;
                void                 *ext_str = NULL;

                if (!(meth = X509V3_EXT_get(ext)))
                    break;
                data = ext->value->data;

#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
                if (meth->it)
                  ext_str = ASN1_item_d2i(NULL, &data, ext->value->length,
                                          ASN1_ITEM_ptr(meth->it));
                else
                  ext_str = meth->d2i(NULL, &data, ext->value->length);
#else
                ext_str = meth->d2i(NULL, &data, ext->value->length);
#endif
                val = meth->i2v(meth, ext_str, NULL);
                for (j = 0;  j < sk_CONF_VALUE_num(val);  j++)
                {
                    nval = sk_CONF_VALUE_value(val, j);
                    if (!strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
                    {
                        ok = 1;
                        break;
                    }
                }
            }
            if (ok)
                break;
        }
    }

    if (!ok && (subj = X509_get_subject_name(cert)) &&
        X509_NAME_get_text_by_NID(subj, NID_commonName, data, 256) > 0)
    {
        data[255] = 0;
        if (strcasecmp(data, host) != 0)
            goto err_occured;
    }

    X509_free(cert);
    return SSL_get_verify_result(ssl);

err_occured:
    if (cert)
        X509_free(cert);
    return X509_V_ERR_APPLICATION_VERIFICATION;
}
int
certproc(int netsock, int filesock)
{
	char		*csr, *chain, *url;
	unsigned char	*csrcp, *chaincp;
	size_t		 csrsz, chainsz;
	int		 i, rc, idx, cc;
	enum certop	 op;
	long		 lval;
	X509		*x, *chainx;
	X509_EXTENSION	*ext;
	X509V3_EXT_METHOD *method;
	void		*entries;
	STACK_OF(CONF_VALUE) *val;
	CONF_VALUE	*nval;

	ext = NULL;
	idx = -1;
	method = NULL;
	chain = csr = url = NULL;
	rc = 0;
	x = chainx = NULL;

	/* File-system and sandbox jailing. */

	if ( ! sandbox_before())
		goto out;

	ERR_load_crypto_strings();

	if ( ! dropfs(PATH_VAR_EMPTY))
		goto out;
	else if ( ! dropprivs())
		goto out;
	else if ( ! sandbox_after())
		goto out;

	/* Read what the netproc wants us to do. */

	op = CERT__MAX;
	if (0 == (lval = readop(netsock, COMM_CSR_OP)))
		op = CERT_STOP;
	else if (CERT_REVOKE == lval || CERT_UPDATE == lval)
		op = lval;

	if (CERT_STOP == op) {
		rc = 1;
		goto out;
	} else if (CERT__MAX == op) {
		warnx("unknown operation from netproc");
		goto out;
	}

	/* 
	 * Pass revocation right through to fileproc. 
	 * If the reader is terminated, ignore it.
	 */

	if (CERT_REVOKE == op) {
		if (writeop(filesock, COMM_CHAIN_OP, FILE_REMOVE) >= 0)
			rc = 1;
		goto out;
	}

	/*
	 * Wait until we receive the DER encoded (signed) certificate
	 * from the network process.
	 * Then convert the DER encoding into an X509 certificate.
	 */

	if (NULL == (csr = readbuf(netsock, COMM_CSR, &csrsz)))
		goto out;

	csrcp = (u_char *)csr;
	x = d2i_X509(NULL, (const u_char **)&csrcp, csrsz);
	if (NULL == x) {
		warnx("d2i_X509");
		goto out;
	}

	/*
	 * Extract the CA Issuers from its NID.
	 * TODO: I have no idea what I'm doing.
	 */

	idx = X509_get_ext_by_NID(x, NID_info_access, idx);
	if (idx >= 0 && NULL != (ext = X509_get_ext(x, idx)))
		method = (X509V3_EXT_METHOD *)X509V3_EXT_get(ext);

	entries = X509_get_ext_d2i(x, NID_info_access, 0, 0);
	if (NULL != method && NULL != entries) {
		val = method->i2v(method, entries, 0);
		for (i = 0; i < sk_CONF_VALUE_num(val); i++) {
			nval = sk_CONF_VALUE_value(val, i);
			if (strcmp(nval->name, "CA Issuers - URI"))
				continue;
			url = strdup(nval->value);
			if (NULL == url) {
				warn("strdup");
				goto out;
			}
			break;
		}
	}

	if (NULL == url) {
		warnx("no CA issuer registered with certificate");
		goto out;
	}

	/* Write the CA issuer to the netsock. */

	if (writestr(netsock, COMM_ISSUER, url) <= 0)
		goto out;

	/* Read the full-chain back from the netsock. */

	if (NULL == (chain = readbuf(netsock, COMM_CHAIN, &chainsz)))
		goto out;

	/*
	 * Then check if the chain is PEM-encoded by looking to see if
	 * it begins with the PEM marker.
	 * If so, ship it as-is; otherwise, convert to a PEM encoded
	 * buffer and ship that.
	 * FIXME: if PEM, re-parse it.
	 */

	if (chainsz <= strlen(MARKER) ||
	    strncmp(chain, MARKER, strlen(MARKER))) {
		chaincp = (u_char *)chain;
		chainx = d2i_X509(NULL, 
			(const u_char **)&chaincp, chainsz);
		if (NULL == chainx) {
			warnx("d2i_X509");
			goto out;
		}
		free(chain);
		if (NULL == (chain = x509buf(chainx, &chainsz)))
			goto out;
	} 

	/* Allow reader termination to just push us out. */

	if (0 == (cc = writeop(filesock, COMM_CHAIN_OP, FILE_CREATE)))
		rc = 1;
	if (cc <= 0)
		goto out;
	if (0 == (cc = writebuf(filesock, COMM_CHAIN, chain, chainsz)))
		rc = 1;
	if (cc <= 0)
		goto out;

	/* 
	 * Next, convert the X509 to a buffer and send that. 
	 * Reader failure doesn't change anything.
	 */

	free(chain);
	if (NULL == (chain = x509buf(x, &chainsz)))
		goto out;
	if (writebuf(filesock, COMM_CSR, chain, chainsz) < 0)
		goto out;

	rc = 1;
out:
	close(netsock);
	close(filesock);
	if (NULL != x)
		X509_free(x);
	if (NULL != chainx)
		X509_free(chainx);
	free(csr);
	free(url);
	free(chain);
	ERR_print_errors_fp(stderr);
	ERR_free_strings();
	return(rc);
}