parent
d8f7a8655f
commit
6f60683802
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
char buf[256];
|
||||
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));
|
||||
}
|
||||
(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));
|
||||
}
|
||||
(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));
|
||||
|
24
test/fixtures/alice.crt
vendored
Normal file
24
test/fixtures/alice.crt
vendored
Normal file
@ -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-----
|
58
test/simple/test-tls-peer-certificate.js
Normal file
58
test/simple/test-tls-peer-certificate.js
Normal file
@ -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);
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user