Permalink
Browse files

tls: x509 certificate subject parsing fail

Fixes #1568.
  • Loading branch information...
1 parent 43cdbec commit 03918a08944aa9336f6172af0b4f5926b3b0c35b @koichik committed Aug 26, 2011
Showing with 112 additions and 20 deletions.
  1. +4 −4 lib/tls.js
  2. +26 −16 src/node_crypto.cc
  3. +24 −0 test/fixtures/alice.crt
  4. +58 −0 test/simple/test-tls-peer-certificate.js
View
@@ -153,12 +153,12 @@ CryptoStream.prototype.setEncoding = function(encoding) {
};
-// EG '/C=US/ST=CA/L=SF/O=Joyent/OU=Node.js/CN=ca1/emailAddress=ry@clouds.org'
+// Example:
+// C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org
function parseCertString(s) {
var out = {};
- var parts = s.split('/');
- // Note: can always skip the first one.
- for (var i = 1; i < parts.length; i++) {
+ var parts = s.split('\n');
+ for (var i = 0, len = parts.length; i < len; i++) {
var sepIndex = parts[i].indexOf('=');
if (sepIndex > 0) {
var key = parts[i].slice(0, sepIndex);
View
@@ -50,6 +50,11 @@
static const char *PUBLIC_KEY_PFX = "-----BEGIN PUBLIC KEY-----";
static const int PUBLIC_KEY_PFX_LEN = strlen(PUBLIC_KEY_PFX);
+static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
+ | ASN1_STRFLGS_ESC_MSB
+ | XN_FLAG_SEP_MULTILINE
+ | XN_FLAG_FN_SN;
+
namespace node {
namespace crypto {
@@ -1066,27 +1071,31 @@ Handle<Value> Connection::GetPeerCertificate(const Arguments& args) {
Local<Object> info = Object::New();
X509* peer_cert = SSL_get_peer_certificate(ss->ssl_);
if (peer_cert != NULL) {
- char* subject = X509_NAME_oneline(X509_get_subject_name(peer_cert), 0, 0);
- if (subject != NULL) {
- info->Set(subject_symbol, String::New(subject));
- OPENSSL_free(subject);
+ BIO* bio = BIO_new(BIO_s_mem());
+ BUF_MEM* mem;
+ if (X509_NAME_print_ex(bio, X509_get_subject_name(peer_cert), 0,
+ X509_NAME_FLAGS) > 0) {
+ BIO_get_mem_ptr(bio, &mem);
+ info->Set(subject_symbol, String::New(mem->data, mem->length));
}
- char* issuer = X509_NAME_oneline(X509_get_issuer_name(peer_cert), 0, 0);
- if (subject != NULL) {
- info->Set(issuer_symbol, String::New(issuer));
- OPENSSL_free(issuer);
+ (void) BIO_reset(bio);
+
+ if (X509_NAME_print_ex(bio, X509_get_issuer_name(peer_cert), 0,
+ X509_NAME_FLAGS) > 0) {
+ BIO_get_mem_ptr(bio, &mem);
+ info->Set(issuer_symbol, String::New(mem->data, mem->length));
}
- char buf[256];
- BIO* bio = BIO_new(BIO_s_mem());
+ (void) BIO_reset(bio);
+
ASN1_TIME_print(bio, X509_get_notBefore(peer_cert));
- memset(buf, 0, sizeof(buf));
- BIO_read(bio, buf, sizeof(buf) - 1);
- info->Set(valid_from_symbol, String::New(buf));
+ BIO_get_mem_ptr(bio, &mem);
+ info->Set(valid_from_symbol, String::New(mem->data, mem->length));
+ (void) BIO_reset(bio);
+
ASN1_TIME_print(bio, X509_get_notAfter(peer_cert));
- memset(buf, 0, sizeof(buf));
- BIO_read(bio, buf, sizeof(buf) - 1);
+ BIO_get_mem_ptr(bio, &mem);
+ info->Set(valid_to_symbol, String::New(mem->data, mem->length));
BIO_free(bio);
- info->Set(valid_to_symbol, String::New(buf));
unsigned int md_size, i;
unsigned char md[EVP_MAX_MD_SIZE];
@@ -1114,6 +1123,7 @@ Handle<Value> Connection::GetPeerCertificate(const Arguments& args) {
peer_cert, NID_ext_key_usage, NULL, NULL);
if (eku != NULL) {
Local<Array> ext_key_usage = Array::New();
+ char buf[256];
for (int i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
memset(buf, 0, sizeof(buf));
View
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID8DCCAtigAwIBAgIJALmw0zKhqlY1MA0GCSqGSIb3DQEBBQUAMFgxDjAMBgNV
+BAMTBWFsaWNlMUYwRAYDVR0RFD11bmlmb3JtUmVzb3VyY2VJZGVudGlmaWVyOmh0
+dHA6Ly9sb2NhbGhvc3Q6ODAwMC9hbGljZS5mb2FmI21lMB4XDTExMDgyNDA1NTUx
+NFoXDTExMDkyMzA1NTUxNFowWDEOMAwGA1UEAxMFYWxpY2UxRjBEBgNVHREUPXVu
+aWZvcm1SZXNvdXJjZUlkZW50aWZpZXI6aHR0cDovL2xvY2FsaG9zdDo4MDAwL2Fs
+aWNlLmZvYWYjbWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDP4tdk
+6NxAImrf5kpQVpuPvWij97H9ewFwWq0FOGONPD0JURXB89BCnhfC0+IHbTi+dhfB
+DX9HY11NCoJm7juXv0uywv+7Zrlj37Q0RTedADmp237UUATRzmh7E+KZc6tHcZZ8
+rPs+ZnY7TXXsh4JRRc8blTy6aEN7/iYMXhk0mIpzjTha2Gq5OqBLustBkeFnoPQS
+cac6TOWbEkxg80dI5jX/qK901RRwLztrA0QDeWB+HLbkjIErdAlz5pgo1Nu3vQt6
+vLdu7bBYsUa2Y2IaVBNLgmzEiZGwQJMjvbs5tLv8VYBCypb4I4vRJrkG4wWsUimM
++sR7SKHu9FFt2ZdHAgMBAAGjgbwwgbkwHQYDVR0OBBYEFA51eHepg7Tp5bi6Ao5F
+B01/5+GoMIGJBgNVHSMEgYEwf4AUDnV4d6mDtOnluLoCjkUHTX/n4aihXKRaMFgx
+DjAMBgNVBAMTBWFsaWNlMUYwRAYDVR0RFD11bmlmb3JtUmVzb3VyY2VJZGVudGlm
+aWVyOmh0dHA6Ly9sb2NhbGhvc3Q6ODAwMC9hbGljZS5mb2FmI21lggkAubDTMqGq
+VjUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAreudH4Y7R9Vl2GJo
+2xRUEwZiMj/ogomZ7B+IZtcuMIR8X2mzQ30xmPKaCy/fjbueqBroIDdxFeQ4eWZf
+MD3AK/q5lJXwSInDjnn7jE9gNgLdQeCnajV0/QH+eDxIe/Alvx+RuvrDiNOudEs4
+vhqv5zEaL6VEXoWVb4/cghDbynQucSpyOMmGGPYYw2zmg0nNXdQauYWDUZIaDwQ6
+tM/pi2ewYubHPZdwJv5jvxTN3Z7RuuGHM+aLAZSAqSgAi0ml8PYYd2eRzXMaEI0c
+eajcEvVa405aYT6dxuF1qqRDYx14As/R7O5RKCpz7wsxD6ICD/Ynv3GCUGxANQim
+bcCjpg==
+-----END CERTIFICATE-----
@@ -0,0 +1,58 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+if (!process.versions.openssl) {
+ console.error("Skipping because node compiled without OpenSSL.");
+ process.exit(0);
+}
+
+var common = require('../common');
+var assert = require('assert');
+var tls = require('tls');
+var fs = require('fs');
+var util = require('util');
+var join = require('path').join;
+var spawn = require('child_process').spawn;
+
+var options = {
+ key: fs.readFileSync(join(common.fixturesDir, 'agent.key')),
+ cert: fs.readFileSync(join(common.fixturesDir, 'alice.crt'))
+};
+var verified = false;
+
+var server = tls.createServer(options, function(cleartext) {
+ cleartext.end('World');
+});
+server.listen(common.PORT, function() {
+ var socket = tls.connect(common.PORT, function() {
+ var peerCert = socket.getPeerCertificate();
+ common.debug(util.inspect(peerCert));
+ assert.equal(peerCert.subject.subjectAltName,
+ 'uniformResourceIdentifier:http://localhost:8000/alice.foaf#me');
+ verified = true;
+ server.close();
+ });
+ socket.end('Hello');
+});
+
+process.on('exit', function() {
+ assert.ok(verified);
+});

0 comments on commit 03918a0

Please sign in to comment.