// This function taken from openvpn-2.2.1 and tidied up a bit. static int setenv_x509(X509_NAME *x509, const char *type) { int i, n; int fn_nid; ASN1_OBJECT *fn; ASN1_STRING *val; X509_NAME_ENTRY *ent; const char *objbuf; uint8_t *buf; char *name_expand; size_t name_expand_size; n=X509_NAME_entry_count (x509); for(i=0; i<n; ++i) { if(!(ent=X509_NAME_get_entry (x509, i)) || !(fn=X509_NAME_ENTRY_get_object(ent)) || !(val=X509_NAME_ENTRY_get_data(ent)) || (fn_nid=OBJ_obj2nid(fn))==NID_undef || !(objbuf=OBJ_nid2sn(fn_nid))) continue; buf=(uint8_t *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */ if(ASN1_STRING_to_UTF8(&buf, val)<=0) continue; name_expand_size=64+strlen(objbuf); if(!(name_expand=(char *)malloc_w(name_expand_size, __func__))) return -1; snprintf(name_expand, name_expand_size, "X509_%s_%s", type, objbuf); sanitise(name_expand); sanitise((char*)buf); setenv(name_expand, (char*)buf, 1); free (name_expand); OPENSSL_free (buf); } return 0; }
static PyObject * get_subject (certificate_x509 *self, PyObject *args) { if (!PyArg_ParseTuple (args, "")) { return NULL; } X509_NAME *name = X509_get_subject_name (self->x509); int entries = X509_NAME_entry_count (name); int i; PyObject *dict = PyDict_New (); for (i = 0; i < entries; i++) { X509_NAME_ENTRY *entry = X509_NAME_get_entry (name, i); ASN1_OBJECT *obj = X509_NAME_ENTRY_get_object (entry); ASN1_STRING *data = X509_NAME_ENTRY_get_data (entry); PyObject *key = PyString_FromString (OBJ_nid2sn (OBJ_obj2nid (obj))); PyObject *value = PyString_FromString ((const char *) ASN1_STRING_data (data)); PyDict_SetItem (dict, key, value); Py_DECREF (key); Py_DECREF (value); } return dict; }
static char *lookup_ssl_cert_dn(X509_NAME *xsname, int dnidx) { char *result; X509_NAME_ENTRY *xsne; int i, j, n, idx = 0; result = NULL; for (i = 0; info_cert_dn_rec[i].fid != 0; i++) { if (info_cert_dn_rec[i].fid == dnidx) { for (j = 0; j < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *) (xsname->entries)); j++) { xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *) (xsname->entries), j); n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); if (n == info_cert_dn_rec[i].nid && idx-- == 0) { result = malloc(xsne->value->length + 1); memcpy(result, xsne->value->data, xsne->value->length); result[xsne->value->length] = '\0'; #if APR_CHARSET_EBCDIC ap_xlate_proto_from_ascii(result, xsne->value->length); #endif /* APR_CHARSET_EBCDIC */ break; } } break; } } return result; }
/* * Given a X509_NAME object and a name identifier, set the corresponding * attribute to the given string. Used by the setattr function. * * Arguments: name - The X509_NAME object * nid - The name identifier * value - The string to set * Returns: 0 for success, -1 on failure */ static int set_name_by_nid(X509_NAME *name, int nid, char *utf8string) { X509_NAME_ENTRY *ne; int i, entry_count, temp_nid; /* If there's an old entry for this NID, remove it */ entry_count = X509_NAME_entry_count(name); for (i = 0; i < entry_count; i++) { ne = X509_NAME_get_entry(name, i); temp_nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne)); if (temp_nid == nid) { ne = X509_NAME_delete_entry(name, i); X509_NAME_ENTRY_free(ne); break; } } /* Add the new entry */ if (!X509_NAME_add_entry_by_NID(name, nid, MBSTRING_UTF8, (unsigned char *)utf8string, -1, -1, 0)) { exception_from_error_queue(crypto_Error); return -1; } return 0; }
static int openssl_push_xname_entry(lua_State* L, X509_NAME_ENTRY* ne) { ASN1_OBJECT* object = X509_NAME_ENTRY_get_object(ne); lua_newtable(L); openssl_push_asn1object(L, object); PUSH_ASN1_STRING(L, X509_NAME_ENTRY_get_data(ne)); lua_settable(L, -3); return 1; }
/* * Equivalent of X509_NAME_oneline that respects encoding * * This function converts X509_NAME structure to the text variable * converting all textual data into current database encoding. * * Parameter: X509_NAME *name X509_NAME structure to be converted * * Returns: text datum which contains string representation of * X509_NAME */ static Datum X509_NAME_to_text(X509_NAME *name) { BIO *membuf = BIO_new(BIO_s_mem()); int i, nid, count = X509_NAME_entry_count(name); X509_NAME_ENTRY *e; ASN1_STRING *v; const char *field_name; size_t size; char nullterm; char *sp; char *dp; text *result; if (membuf == NULL) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("could not create OpenSSL BIO structure"))); (void) BIO_set_close(membuf, BIO_CLOSE); for (i = 0; i < count; i++) { e = X509_NAME_get_entry(name, i); nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e)); if (nid == NID_undef) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not get NID for ASN1_OBJECT object"))); v = X509_NAME_ENTRY_get_data(e); field_name = OBJ_nid2sn(nid); if (field_name == NULL) field_name = OBJ_nid2ln(nid); if (field_name == NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not convert NID %d to an ASN1_OBJECT structure", nid))); BIO_printf(membuf, "/%s=", field_name); ASN1_STRING_print_ex(membuf, v, ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB) | ASN1_STRFLGS_UTF8_CONVERT)); } /* ensure null termination of the BIO's content */ nullterm = '\0'; BIO_write(membuf, &nullterm, 1); size = BIO_get_mem_data(membuf, &sp); dp = pg_any_to_server(sp, size - 1, PG_UTF8); result = cstring_to_text(dp); if (dp != sp) pfree(dp); if (BIO_free(membuf) != 1) elog(ERROR, "could not free OpenSSL BIO structure"); PG_RETURN_TEXT_P(result); }
/* * Equivalent of X509_NAME_oneline that respects encoding * * This function converts X509_NAME structure to the text variable * converting all textual data into current database encoding. * * Parameter: X509_NAME *name X509_NAME structure to be converted * * Returns: text datum which contains string representation of * X509_NAME */ Datum X509_NAME_to_text(X509_NAME *name) { BIO *membuf = BIO_new(BIO_s_mem()); int i, nid, count = X509_NAME_entry_count(name); X509_NAME_ENTRY *e; ASN1_STRING *v; const char *field_name; size_t size, outlen; char *sp; char *dp; text *result; (void) BIO_set_close(membuf, BIO_CLOSE); for (i = 0; i < count; i++) { e = X509_NAME_get_entry(name, i); nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e)); v = X509_NAME_ENTRY_get_data(e); field_name = OBJ_nid2sn(nid); if (!field_name) field_name = OBJ_nid2ln(nid); BIO_printf(membuf, "/%s=", field_name); ASN1_STRING_print_ex(membuf, v, ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB) | ASN1_STRFLGS_UTF8_CONVERT)); } i = 0; BIO_write(membuf, &i, 1); size = BIO_get_mem_data(membuf, &sp); dp = (char *) pg_do_encoding_conversion((unsigned char *) sp, size - 1, PG_UTF8, GetDatabaseEncoding()); BIO_free(membuf); outlen = strlen(dp); result = palloc(VARHDRSZ + outlen); memcpy(VARDATA(result), dp, outlen); /* * pg_do_encoding_conversion has annoying habit of returning source * pointer */ if (dp != sp) pfree(dp); VARATT_SIZEP(result) = outlen + VARHDRSZ; PG_RETURN_TEXT_P(result); }
IoObject *IoCertificate_nameToObject(IoObject *self, X509_NAME *xname) { IoObject *map = IoObject_new(IoObject_state(self)); int i; for(i = 0; i < X509_NAME_entry_count(xname); i++) { X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i); const char *key = (const char *)OBJ_nid2ln(OBJ_obj2nid(X509_NAME_ENTRY_get_object(entry))); const char *value = (const char *)ASN1_STRING_data(X509_NAME_ENTRY_get_data(entry)); IoObject_setSlot_to_(map, IOSYMBOL(key), IoSeq_newWithCString_(IoObject_state(self), value)); } return map; }
/* * Save X509 fields to environment, using the naming convention: * * X509_{cert_depth}_{name}={value} */ void x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *peer_cert) { int i, n; int fn_nid; ASN1_OBJECT *fn; ASN1_STRING *val; X509_NAME_ENTRY *ent; const char *objbuf; unsigned char *buf; char *name_expand; size_t name_expand_size; X509_NAME *x509 = X509_get_subject_name (peer_cert); n = X509_NAME_entry_count (x509); for (i = 0; i < n; ++i) { ent = X509_NAME_get_entry (x509, i); if (!ent) continue; fn = X509_NAME_ENTRY_get_object (ent); if (!fn) continue; val = X509_NAME_ENTRY_get_data (ent); if (!val) continue; fn_nid = OBJ_obj2nid (fn); if (fn_nid == NID_undef) continue; objbuf = OBJ_nid2sn (fn_nid); if (!objbuf) continue; buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */ if (ASN1_STRING_to_UTF8 (&buf, val) <= 0) continue; name_expand_size = 64 + strlen (objbuf); name_expand = (char *) malloc (name_expand_size); check_malloc_return (name_expand); openvpn_snprintf (name_expand, name_expand_size, "X509_%d_%s", cert_depth, objbuf); string_mod (name_expand, CC_PRINT, CC_CRLF, '_'); string_mod ((char*)buf, CC_PRINT, CC_CRLF, '_'); setenv_str (es, name_expand, (char*)buf); free (name_expand); OPENSSL_free (buf); } }
/* * Equivalent of X509_NAME_oneline that respects encoding * * This function converts X509_NAME structure to the text variable * converting all textual data into current database encoding. * * Parameter: X509_NAME *name X509_NAME structure to be converted * * Returns: text datum which contains string representation of * X509_NAME */ datum_t X509_NAME_to_text(X509_NAME *name) { BIO *membuf = BIO_new(BIO_s_mem()); int i, nid, count = X509_NAME_entry_count(name); X509_NAME_ENTRY *e; ASN1_STRING *v; const char *field_name; size_t size; char nullterm; char *sp; char *dp; text *result; (void) BIO_set_close(membuf, BIO_CLOSE); for (i = 0; i < count; i++) { e = X509_NAME_get_entry(name, i); nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e)); v = X509_NAME_ENTRY_get_data(e); field_name = OBJ_nid2sn(nid); if (!field_name) field_name = OBJ_nid2ln(nid); BIO_printf(membuf, "/%s=", field_name); ASN1_STRING_print_ex(membuf, v, ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB) | ASN1_STRFLGS_UTF8_CONVERT)); } /* ensure null termination of the BIO's content */ nullterm = '\0'; BIO_write(membuf, &nullterm, 1); size = BIO_get_mem_data(membuf, &sp); dp = (char *) pg_do_encoding_conversion((unsigned char *) sp, size - 1, PG_UTF8, get_db_encoding()); result = cstring_to_text(dp); if (dp != sp) pfree(dp); BIO_free(membuf); RET_TEXT_P(result); }
/*** get index by give asn1_object or nid @function delete_entry @tparam integer location which name entry to delete @treturn[1] asn1_object object that delete name entry @treturn[1] asn1_string value that delete name entry @treturn[2] nil delete nothing */ static int openssl_xname_delete_entry(lua_State*L) { X509_NAME* xn = CHECK_OBJECT(1, X509_NAME, "openssl.x509_name"); int loc = luaL_checkint(L, 2); X509_NAME_ENTRY *xe = X509_NAME_delete_entry(xn, loc); if (xe) { openssl_push_asn1object(L, X509_NAME_ENTRY_get_object(xe)); PUSH_ASN1_STRING(L, X509_NAME_ENTRY_get_data(xe)); X509_NAME_ENTRY_free(xe); return 2; } else lua_pushnil(L); return 1; };
static int openssl_push_xname_entry(lua_State* L, X509_NAME_ENTRY* ne, int obj) { ASN1_OBJECT* object = X509_NAME_ENTRY_get_object(ne); ASN1_STRING* value = X509_NAME_ENTRY_get_data(ne); lua_newtable(L); if(obj) { openssl_push_asn1object(L, object); PUSH_ASN1_STRING(L, value); } else { lua_pushstring(L, OBJ_nid2sn(OBJ_obj2nid(object))); lua_pushlstring(L, (const char*)ASN1_STRING_get0_data(value), ASN1_STRING_length(value)); } lua_settable(L, -3); return 1; }
/* * Convert an X509 subject name to a cstring. * */ static char * X509_NAME_to_cstring(X509_NAME *name) { BIO *membuf = BIO_new(BIO_s_mem()); int i, nid, count = X509_NAME_entry_count(name); X509_NAME_ENTRY *e; ASN1_STRING *v; const char *field_name; size_t size; char nullterm; char *sp; char *dp; char *result; (void) BIO_set_close(membuf, BIO_CLOSE); for (i = 0; i < count; i++) { e = X509_NAME_get_entry(name, i); nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e)); v = X509_NAME_ENTRY_get_data(e); field_name = OBJ_nid2sn(nid); if (!field_name) field_name = OBJ_nid2ln(nid); BIO_printf(membuf, "/%s=", field_name); ASN1_STRING_print_ex(membuf, v, ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB) | ASN1_STRFLGS_UTF8_CONVERT)); } /* ensure null termination of the BIO's content */ nullterm = '\0'; BIO_write(membuf, &nullterm, 1); size = BIO_get_mem_data(membuf, &sp); dp = pg_any_to_server(sp, size - 1, PG_UTF8); result = pstrdup(dp); if (dp != sp) pfree(dp); BIO_free(membuf); return result; }
static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, const char *var) { const char *ptr; char *result; X509_NAME_ENTRY *xsne; int i, j, n, idx = 0, raw = 0; apr_size_t varlen; ptr = ap_strrchr_c(var, '_'); if (ptr && ptr > var && strcmp(ptr + 1, "RAW") == 0) { var = apr_pstrmemdup(p, var, ptr - var); raw = 1; } /* if an _N suffix is used, find the Nth attribute of given name */ ptr = ap_strchr_c(var, '_'); if (ptr != NULL && strspn(ptr + 1, "0123456789") == strlen(ptr + 1)) { idx = atoi(ptr + 1); varlen = ptr - var; } else { varlen = strlen(var); } result = NULL; for (i = 0; ssl_var_lookup_ssl_cert_dn_rec[i].name != NULL; i++) { if (strEQn(var, ssl_var_lookup_ssl_cert_dn_rec[i].name, varlen) && strlen(ssl_var_lookup_ssl_cert_dn_rec[i].name) == varlen) { for (j = 0; j < X509_NAME_entry_count(xsname); j++) { xsne = X509_NAME_get_entry(xsname, j); n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); if (n == ssl_var_lookup_ssl_cert_dn_rec[i].nid && idx-- == 0) { result = modssl_X509_NAME_ENTRY_to_string(p, xsne, raw); break; } } break; } } return result; }
static PyObject* nassl_X509_NAME_ENTRY_get_data(nassl_X509_NAME_ENTRY_Object *self) { unsigned int nameDataSize = 0, objectDataSize = 0, nameUtf8Size = 0; ASN1_STRING *nameData = NULL; ASN1_OBJECT *objectData = NULL; unsigned char *nameDataTxt = NULL; unsigned char *objectDataTxt = NULL; PyObject* res = NULL; nameData = X509_NAME_ENTRY_get_data(self->x509NameEntry); nameDataSize = ASN1_STRING_length(nameData); // Extract the text representation of the field's name objectData = X509_NAME_ENTRY_get_object(self->x509NameEntry); objectDataSize = OBJ_obj2txt(NULL, 0, objectData, 0) + 1; objectDataTxt = PyMem_Malloc(objectDataSize); if (objectDataTxt == NULL) { return PyErr_NoMemory(); } OBJ_obj2txt((char *)objectDataTxt, objectDataSize, objectData, 0); nameUtf8Size = ASN1_STRING_to_UTF8(&nameDataTxt, nameData); // Are we extracting the Common Name ? if (strncmp((char *)objectDataTxt, "commonName", strlen("commonName")) == 0) { if (nameDataSize != nameUtf8Size) { // TODO: Unit test for that // Embedded null character in the Common Name ? Get out PyMem_Free(objectDataTxt); PyErr_SetString(PyExc_NotImplementedError, "ASN1 string length does not match C string length. Embedded null character ?"); return NULL; } } PyMem_Free(objectDataTxt); res = PyString_FromStringAndSize((const char*) nameDataTxt, nameDataSize); return res; }
MONO_API int mono_btls_x509_name_get_entry_oid (MonoBtlsX509Name *name, int index, char *buffer, int size) { X509_NAME_ENTRY *entry; ASN1_OBJECT *obj; if (index >= X509_NAME_entry_count (name->name)) return 0; entry = X509_NAME_get_entry (name->name, index); if (!entry) return 0; obj = X509_NAME_ENTRY_get_object (entry); if (!obj) return 0; return OBJ_obj2txt (buffer, size, obj, 1); }
static PyObject * crypto_X509Name_get_components(crypto_X509NameObj *self, PyObject *args) { int n, i; X509_NAME *name = self->x509_name; PyObject *list; if (!PyArg_ParseTuple(args, ":get_components")) return NULL; n = X509_NAME_entry_count(name); list = PyList_New(n); for (i = 0; i < n; i++) { X509_NAME_ENTRY *ent; ASN1_OBJECT *fname; ASN1_STRING *fval; int nid; int l; unsigned char *str; PyObject *tuple; ent = X509_NAME_get_entry(name, i); fname = X509_NAME_ENTRY_get_object(ent); fval = X509_NAME_ENTRY_get_data(ent); l = ASN1_STRING_length(fval); str = ASN1_STRING_data(fval); nid = OBJ_obj2nid(fname); /* printf("fname is %s len=%d str=%s\n", OBJ_nid2sn(nid), l, str); */ tuple = PyTuple_New(2); PyTuple_SetItem(tuple, 0, PyBytes_FromString(OBJ_nid2sn(nid))); PyTuple_SetItem(tuple, 1, PyBytes_FromStringAndSize((char *)str, l)); PyList_SetItem(list, i, tuple); } return list; }
MONO_API MonoBtlsX509NameEntryType mono_btls_x509_name_get_entry_type (MonoBtlsX509Name *name, int index) { X509_NAME_ENTRY *entry; ASN1_OBJECT *obj; if (index >= X509_NAME_entry_count (name->name)) return -1; entry = X509_NAME_get_entry (name->name, index); if (!entry) return -1; obj = X509_NAME_ENTRY_get_object (entry); if (!obj) return -1; return nid2mono (OBJ_obj2nid (obj)); }
static char *__apn_ssl_cert_entry_string(X509_NAME *name) { char subject_entry_buffer[__APN_X509_ENTRY_BUF_SIZE] = {0}; int entry_count = X509_NAME_entry_count(name); for (int i = 0; i < entry_count; i++) { X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); ASN1_OBJECT *entry_object = X509_NAME_ENTRY_get_object(entry); const char *entry_name = OBJ_nid2sn(OBJ_obj2nid(entry_object)); const unsigned char *entry_value = ASN1_STRING_data(X509_NAME_ENTRY_get_data(entry)); apn_strcat(subject_entry_buffer, entry_name, __APN_X509_ENTRY_BUF_SIZE, strlen(entry_name)); apn_strcat(subject_entry_buffer, "=", __APN_X509_ENTRY_BUF_SIZE, 1); apn_strcat(subject_entry_buffer, (const char *)entry_value, __APN_X509_ENTRY_BUF_SIZE, strlen((const char *)entry_value)); if(i + 1 < entry_count) { apn_strcat(subject_entry_buffer, ", ", __APN_X509_ENTRY_BUF_SIZE, 2); } } return apn_strndup(subject_entry_buffer, strlen(subject_entry_buffer)); }
static void openssl_setenv_X509_add_entries(liVRequest *vr, X509 *x509, const gchar *prefix, guint prefix_len) { guint i, j; GString *k = vr->wrk->tmp_str; X509_NAME *xn = X509_get_subject_name(x509); X509_NAME_ENTRY *xe; const char * xobjsn; g_string_truncate(k, 0); g_string_append_len(k, prefix, prefix_len); for (i = 0, j = X509_NAME_entry_count(xn); i < j; ++i) { if (!(xe = X509_NAME_get_entry(xn, i)) || !(xobjsn = OBJ_nid2sn(OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe))))) continue; g_string_truncate(k, prefix_len); g_string_append(k, xobjsn); li_environment_set(&vr->env, GSTR_LEN(k), (const gchar *)xe->value->data, xe->value->length); } }
// generate an LLSD from a certificate name (issuer or subject name). // the name will be strings indexed by the 'long form' LLSD cert_name_from_X509_NAME(X509_NAME* name) { LLSD result = LLSD::emptyMap(); int name_entries = X509_NAME_entry_count(name); for (int entry_index=0; entry_index < name_entries; entry_index++) { char buffer[32]; X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, entry_index); std::string name_value = std::string((const char*)M_ASN1_STRING_data(X509_NAME_ENTRY_get_data(entry)), M_ASN1_STRING_length(X509_NAME_ENTRY_get_data(entry))); ASN1_OBJECT* name_obj = X509_NAME_ENTRY_get_object(entry); OBJ_obj2txt(buffer, sizeof(buffer), name_obj, 0); std::string obj_buffer_str = std::string(buffer); result[obj_buffer_str] = name_value; } return result; }
MONO_API int mono_btls_x509_name_get_entry_oid_data (MonoBtlsX509Name *name, int index, const void **data) { X509_NAME_ENTRY *entry; ASN1_OBJECT *obj; if (index >= X509_NAME_entry_count (name->name)) return -1; entry = X509_NAME_get_entry (name->name, index); if (!entry) return -1; obj = X509_NAME_ENTRY_get_object (entry); if (!obj) return -1; *data = obj->data; return obj->length; }
static void x509_print_info (X509 *x509crt) { int i, n; int fn_nid; ASN1_OBJECT *fn; ASN1_STRING *val; X509_NAME *x509_name; X509_NAME_ENTRY *ent; const char *objbuf; unsigned char *buf; x509_name = X509_get_subject_name (x509crt); n = X509_NAME_entry_count (x509_name); for (i = 0; i < n; ++i) { ent = X509_NAME_get_entry (x509_name, i); if (!ent) continue; fn = X509_NAME_ENTRY_get_object (ent); if (!fn) continue; val = X509_NAME_ENTRY_get_data (ent); if (!val) continue; fn_nid = OBJ_obj2nid (fn); if (fn_nid == NID_undef) continue; objbuf = OBJ_nid2sn (fn_nid); if (!objbuf) continue; buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */ if (ASN1_STRING_to_UTF8 (&buf, val) <= 0) continue; printf("X509 %s: %s\n", objbuf, (char *)buf); OPENSSL_free (buf); } }
/** * Retrive the general names from the object. */ static int push_x509_name(lua_State* L, X509_NAME *name) { int i; int n_entries; ASN1_OBJECT *object; X509_NAME_ENTRY *entry; lua_newtable(L); n_entries = X509_NAME_entry_count(name); for (i = 0; i < n_entries; i++) { entry = X509_NAME_get_entry(name, i); object = X509_NAME_ENTRY_get_object(entry); lua_newtable(L); push_asn1_objname(L, object, 1); lua_setfield(L, -2, "oid"); push_asn1_objname(L, object, 0); lua_setfield(L, -2, "name"); push_asn1_string(L, X509_NAME_ENTRY_get_data(entry)); lua_setfield(L, -2, "value"); lua_rawseti(L, -2, i+1); } return 1; }
static PyObject* nassl_X509_NAME_ENTRY_get_object(nassl_X509_NAME_ENTRY_Object *self) { unsigned int objectDataSize = 0; ASN1_OBJECT *objectData = NULL; char *objectDataTxt = NULL; PyObject* res = NULL; objectData = X509_NAME_ENTRY_get_object(self->x509NameEntry); objectDataSize = OBJ_obj2txt(NULL, 0, objectData, 0) + 1; objectDataTxt = (char *) PyMem_Malloc(objectDataSize); if (objectDataTxt == NULL) { return PyErr_NoMemory(); } // Extract the text representation OBJ_obj2txt(objectDataTxt, objectDataSize, objectData, 0); res = PyString_FromStringAndSize(objectDataTxt, objectDataSize - 1); PyMem_Free(objectDataTxt); return res; }
static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n, int indent, unsigned long flags) { int i, prev = -1, orflags, cnt; int fn_opt, fn_nid; ASN1_OBJECT *fn; ASN1_STRING *val; X509_NAME_ENTRY *ent; char objtmp[80]; const char *objbuf; int outlen, len; char *sep_dn, *sep_mv, *sep_eq; int sep_dn_len, sep_mv_len, sep_eq_len; if (indent < 0) indent = 0; outlen = indent; if (!do_indent(io_ch, arg, indent)) return -1; switch (flags & XN_FLAG_SEP_MASK) { case XN_FLAG_SEP_MULTILINE: sep_dn = "\n"; sep_dn_len = 1; sep_mv = " + "; sep_mv_len = 3; break; case XN_FLAG_SEP_COMMA_PLUS: sep_dn = ","; sep_dn_len = 1; sep_mv = "+"; sep_mv_len = 1; indent = 0; break; case XN_FLAG_SEP_CPLUS_SPC: sep_dn = ", "; sep_dn_len = 2; sep_mv = " + "; sep_mv_len = 3; indent = 0; break; case XN_FLAG_SEP_SPLUS_SPC: sep_dn = "; "; sep_dn_len = 2; sep_mv = " + "; sep_mv_len = 3; indent = 0; break; default: return -1; } if (flags & XN_FLAG_SPC_EQ) { sep_eq = " = "; sep_eq_len = 3; } else { sep_eq = "="; sep_eq_len = 1; } fn_opt = flags & XN_FLAG_FN_MASK; cnt = X509_NAME_entry_count(n); for (i = 0; i < cnt; i++) { if (flags & XN_FLAG_DN_REV) ent = X509_NAME_get_entry(n, cnt - i - 1); else ent = X509_NAME_get_entry(n, i); if (prev != -1) { if (prev == ent->set) { if (!io_ch(arg, sep_mv, sep_mv_len)) return -1; outlen += sep_mv_len; } else { if (!io_ch(arg, sep_dn, sep_dn_len)) return -1; outlen += sep_dn_len; if (!do_indent(io_ch, arg, indent)) return -1; outlen += indent; } } prev = ent->set; fn = X509_NAME_ENTRY_get_object(ent); val = X509_NAME_ENTRY_get_data(ent); fn_nid = OBJ_obj2nid(fn); if (fn_opt != XN_FLAG_FN_NONE) { int objlen, fld_len; if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) { OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1); fld_len = 0; /* XXX: what should this be? */ objbuf = objtmp; } else { if (fn_opt == XN_FLAG_FN_SN) { fld_len = FN_WIDTH_SN; objbuf = OBJ_nid2sn(fn_nid); } else if (fn_opt == XN_FLAG_FN_LN) { fld_len = FN_WIDTH_LN; objbuf = OBJ_nid2ln(fn_nid); } else { fld_len = 0; /* XXX: what should this be? */ objbuf = ""; } } objlen = strlen(objbuf); if (!io_ch(arg, objbuf, objlen)) return -1; if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { if (!do_indent(io_ch, arg, fld_len - objlen)) return -1; outlen += fld_len - objlen; } if (!io_ch(arg, sep_eq, sep_eq_len)) return -1; outlen += objlen + sep_eq_len; } /* * If the field name is unknown then fix up the DER dump flag. We * might want to limit this further so it will DER dump on anything * other than a few 'standard' fields. */ if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) orflags = ASN1_STRFLGS_DUMP_ALL; else orflags = 0; len = do_print_ex(io_ch, arg, flags | orflags, val); if (len < 0) return -1; outlen += len; } return outlen; }
static void https_add_ssl_entries(connection *con) { X509 *xs; X509_NAME *xn; X509_NAME_ENTRY *xe; int i, nentries; if ( SSL_get_verify_result(con->ssl) != X509_V_OK || !(xs = SSL_get_peer_certificate(con->ssl)) ) { return; } xn = X509_get_subject_name(xs); for (i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) { int xobjnid; const char * xobjsn; data_string *envds; if (!(xe = X509_NAME_get_entry(xn, i))) { continue; } xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe)); xobjsn = OBJ_nid2sn(xobjnid); if (!xobjsn) { continue; } if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { envds = data_string_init(); } buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_S_DN_")); buffer_append_string(envds->key, xobjsn); buffer_copy_string_len( envds->value, (const char *)xe->value->data, xe->value->length ); /* pick one of the exported values as "authed user", for example * ssl.verifyclient.username = "******" or "SSL_CLIENT_S_DN_emailAddress" */ if (buffer_is_equal(con->conf.ssl_verifyclient_username, envds->key)) { buffer_copy_string_buffer(con->authed_user, envds->value); } array_insert_unique(con->environment, (data_unset *)envds); } if (con->conf.ssl_verifyclient_export_cert) { BIO *bio; if (NULL != (bio = BIO_new(BIO_s_mem()))) { data_string *envds; int n; PEM_write_bio_X509(bio, xs); n = BIO_pending(bio); if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { envds = data_string_init(); } buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_CERT")); buffer_prepare_copy(envds->value, n+1); BIO_read(bio, envds->value->ptr, n); BIO_free(bio); envds->value->ptr[n] = '\0'; envds->value->used = n+1; array_insert_unique(con->environment, (data_unset *)envds); } } X509_free(xs); }
/* Function: GetX509NameInfo Used by System.Security.Cryptography.X509Certificates' OpenSslX509CertificateReader as the entire implementation of X509Certificate2.GetNameInfo. Return values: NULL if the certificate is invalid or no name information could be found, otherwise a pointer to a memory-backed BIO structure which contains the answer to the GetNameInfo query */ BIO* GetX509NameInfo( X509* x509, int nameType, int forIssuer) { static const char szOidUpn[] = "1.3.6.1.4.1.311.20.2.3"; if (!x509 || !x509->cert_info || nameType < NAME_TYPE_SIMPLE || nameType > NAME_TYPE_URL) { return NULL; } // Algorithm behaviors (pseudocode). When forIssuer is true, replace "Subject" with "Issuer" and // SAN (Subject Alternative Names) with IAN (Issuer Alternative Names). // // SimpleName: Subject[CN] ?? Subject[OU] ?? Subject[O] ?? Subject[E] ?? Subject.Rdns.FirstOrDefault() ?? SAN.Entries.FirstOrDefault(type == GEN_EMAIL); // EmailName: SAN.Entries.FirstOrDefault(type == GEN_EMAIL) ?? Subject[E]; // UpnName: SAN.Entries.FirsOrDefaultt(type == GEN_OTHER && entry.AsOther().OID == szOidUpn).AsOther().Value; // DnsName: SAN.Entries.FirstOrDefault(type == GEN_DNS) ?? Subject[CN]; // DnsFromAlternativeName: SAN.Entries.FirstOrDefault(type == GEN_DNS); // UrlName: SAN.Entries.FirstOrDefault(type == GEN_URI); if (nameType == NAME_TYPE_SIMPLE) { X509_NAME* name = forIssuer ? x509->cert_info->issuer : x509->cert_info->subject; if (name) { ASN1_STRING* cn = NULL; ASN1_STRING* ou = NULL; ASN1_STRING* o = NULL; ASN1_STRING* e = NULL; ASN1_STRING* firstRdn = NULL; // Walk the list backwards because it is stored in stack order for (int i = X509_NAME_entry_count(name) - 1; i >= 0; --i) { X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, i); if (!entry) { continue; } ASN1_OBJECT* oid = X509_NAME_ENTRY_get_object(entry); ASN1_STRING* str = X509_NAME_ENTRY_get_data(entry); if (!oid || !str) { continue; } int nid = OBJ_obj2nid(oid); if (nid == NID_commonName) { // CN wins, so no need to keep looking. cn = str; break; } else if (nid == NID_organizationalUnitName) { ou = str; } else if (nid == NID_organizationName) { o = str; } else if (nid == NID_pkcs9_emailAddress) { e = str; } else if (!firstRdn) { firstRdn = str; } } ASN1_STRING* answer = cn; // If there was no CN, but there was something, then perform fallbacks. if (!answer && firstRdn) { answer = ou; if (!answer) { answer = o; } if (!answer) { answer = e; } if (!answer) { answer = firstRdn; } } if (answer) { BIO* b = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(b, answer, 0); return b; } } } if (nameType == NAME_TYPE_SIMPLE || nameType == NAME_TYPE_DNS || nameType == NAME_TYPE_DNSALT || nameType == NAME_TYPE_EMAIL || nameType == NAME_TYPE_UPN || nameType == NAME_TYPE_URL) { int expectedType = -1; switch (nameType) { case NAME_TYPE_DNS: case NAME_TYPE_DNSALT: expectedType = GEN_DNS; break; case NAME_TYPE_SIMPLE: case NAME_TYPE_EMAIL: expectedType = GEN_EMAIL; break; case NAME_TYPE_UPN: expectedType = GEN_OTHERNAME; break; case NAME_TYPE_URL: expectedType = GEN_URI; break; } STACK_OF(GENERAL_NAME)* altNames = X509_get_ext_d2i(x509, forIssuer ? NID_issuer_alt_name : NID_subject_alt_name, NULL, NULL); if (altNames) { int i; for (i = 0; i < sk_GENERAL_NAME_num(altNames); ++i) { GENERAL_NAME* altName = sk_GENERAL_NAME_value(altNames, i); if (altName && altName->type == expectedType) { ASN1_STRING* str = NULL; switch (nameType) { case NAME_TYPE_DNS: case NAME_TYPE_DNSALT: str = altName->d.dNSName; break; case NAME_TYPE_SIMPLE: case NAME_TYPE_EMAIL: str = altName->d.rfc822Name; break; case NAME_TYPE_URL: str = altName->d.uniformResourceIdentifier; break; case NAME_TYPE_UPN: { OTHERNAME* value = altName->d.otherName; if (value) { // Enough more padding than szOidUpn that a \0 won't accidentally align char localOid[sizeof(szOidUpn) + 3]; int cchLocalOid = 1 + OBJ_obj2txt(localOid, sizeof(localOid), value->type_id, 1); if (sizeof(szOidUpn) == cchLocalOid && 0 == strncmp(localOid, szOidUpn, sizeof(szOidUpn))) { //OTHERNAME->ASN1_TYPE->union.field str = value->value->value.asn1_string; } } break; } } if (str) { BIO* b = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(b, str, 0); sk_GENERAL_NAME_free(altNames); return b; } } } sk_GENERAL_NAME_free(altNames); } } if (nameType == NAME_TYPE_EMAIL || nameType == NAME_TYPE_DNS) { X509_NAME* name = forIssuer ? x509->cert_info->issuer : x509->cert_info->subject; int expectedNid = NID_undef; switch (nameType) { case NAME_TYPE_EMAIL: expectedNid = NID_pkcs9_emailAddress; break; case NAME_TYPE_DNS: expectedNid = NID_commonName; break; } if (name) { // Walk the list backwards because it is stored in stack order for (int i = X509_NAME_entry_count(name) - 1; i >= 0; --i) { X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, i); if (!entry) { continue; } ASN1_OBJECT* oid = X509_NAME_ENTRY_get_object(entry); ASN1_STRING* str = X509_NAME_ENTRY_get_data(entry); if (!oid || !str) { continue; } int nid = OBJ_obj2nid(oid); if (nid == expectedNid) { BIO* b = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(b, str, 0); return b; } } } } return NULL; }
static int verifypeer(const struct tls_info *info, SSL *ssl) { X509 *x=NULL; X509_NAME *subj=NULL; int nentries, j; char domain[256]; char *p; char errmsg[1000]; if (!info->peer_verify_domain) return (1); if (info->isserver) { x=SSL_get_peer_certificate(ssl); if (x) subj=X509_get_subject_name(x); } else { STACK_OF(X509) *peer_cert_chain=SSL_get_peer_cert_chain(ssl); if (peer_cert_chain && peer_cert_chain->stack.num > 0) { X509 *xx=(X509 *)peer_cert_chain->stack.data[0]; if (xx) subj=X509_get_subject_name(xx); } } nentries=0; if (subj) nentries=X509_NAME_entry_count(subj); domain[0]=0; for (j=0; j<nentries; j++) { const char *obj_name; X509_NAME_ENTRY *e; ASN1_OBJECT *o; ASN1_STRING *d; int dlen; unsigned char *ddata; e=X509_NAME_get_entry(subj, j); if (!e) continue; o=X509_NAME_ENTRY_get_object(e); d=X509_NAME_ENTRY_get_data(e); if (!o || !d) continue; obj_name=OBJ_nid2sn(OBJ_obj2nid(o)); dlen=ASN1_STRING_length(d); ddata=ASN1_STRING_data(d); if (strcasecmp(obj_name, "CN") == 0) { if (dlen >= sizeof(domain)-1) dlen=sizeof(domain)-1; memcpy(domain, ddata, dlen); domain[dlen]=0; } } if (x) X509_free(x); p=domain; if (*p == '*') { int pl, l; pl=strlen(++p); l=strlen(info->peer_verify_domain); if (*p == '.' && pl <= l && strcasecmp(info->peer_verify_domain+l-pl, p) == 0) return (1); } else if (strcasecmp(info->peer_verify_domain, p) == 0) return (1); strcpy(errmsg, "couriertls: Mismatched SSL certificate: CN="); strcat(errmsg, domain); strcat(errmsg, " (expected "); strncat(errmsg, info->peer_verify_domain, 256); strcat(errmsg, ")"); (*info->tls_err_msg)(errmsg, info->app_data); return (0); }
void add_assoc_name_entry(lua_State*L, char * key, X509_NAME * name, int shortname) /* {{{ */ { int i, j = -1, last = -1, obj_cnt = 0; char *sname; int nid; X509_NAME_ENTRY * ne; ASN1_STRING * str = NULL; ASN1_OBJECT * obj; char* p; lua_newtable(L); p=X509_NAME_oneline(name,NULL,0); lua_pushstring(L, p); lua_rawseti(L, -2, 0); OPENSSL_free(p); for (i = 0; i < X509_NAME_entry_count(name); i++) { unsigned char *to_add; int to_add_len; int tindex = 0; //int utf8 = 0; ne = X509_NAME_get_entry(name, i); obj = X509_NAME_ENTRY_get_object(ne); nid = OBJ_obj2nid(obj); obj_cnt = 0; if (shortname) { sname = (char *) OBJ_nid2sn(nid); } else { sname = (char *) OBJ_nid2ln(nid); } lua_newtable(L); last = -1; for (;;) { j = X509_NAME_get_index_by_OBJ(name, obj, last); if (j < 0) { if (last != -1) break; } else { obj_cnt++; ne = X509_NAME_get_entry(name, j); str = X509_NAME_ENTRY_get_data(ne); /* Some Certificate not stardand if (ASN1_STRING_type(str) != V_ASN1_UTF8STRING) { to_add_len = ASN1_STRING_to_UTF8(&to_add, str); } */ to_add = ASN1_STRING_data(str); to_add_len = ASN1_STRING_length(str); tindex++; lua_pushlstring(L,(char *)to_add, to_add_len); lua_rawseti(L,-2,tindex); } last = j; } i = last; if (obj_cnt > 1) { lua_setfield(L,-2,sname); } else { lua_pop(L,1); if (obj_cnt && str && to_add_len > -1) { lua_pushlstring(L,(char *)to_add, to_add_len); lua_setfield(L,-2, sname); } } } if (key != NULL) { lua_setfield(L,-2,key); } }