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) {
|
function parseCertString(s) {
|
||||||
var out = {};
|
var out = {};
|
||||||
var parts = s.split('/');
|
var parts = s.split('\n');
|
||||||
// Note: can always skip the first one.
|
for (var i = 0, len = parts.length; i < len; i++) {
|
||||||
for (var i = 1; i < parts.length; i++) {
|
|
||||||
var sepIndex = parts[i].indexOf('=');
|
var sepIndex = parts[i].indexOf('=');
|
||||||
if (sepIndex > 0) {
|
if (sepIndex > 0) {
|
||||||
var key = parts[i].slice(0, sepIndex);
|
var key = parts[i].slice(0, sepIndex);
|
||||||
|
@ -50,6 +50,11 @@
|
|||||||
static const char *PUBLIC_KEY_PFX = "-----BEGIN PUBLIC KEY-----";
|
static const char *PUBLIC_KEY_PFX = "-----BEGIN PUBLIC KEY-----";
|
||||||
static const int PUBLIC_KEY_PFX_LEN = strlen(PUBLIC_KEY_PFX);
|
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 node {
|
||||||
namespace crypto {
|
namespace crypto {
|
||||||
|
|
||||||
@ -1066,27 +1071,31 @@ Handle<Value> Connection::GetPeerCertificate(const Arguments& args) {
|
|||||||
Local<Object> info = Object::New();
|
Local<Object> info = Object::New();
|
||||||
X509* peer_cert = SSL_get_peer_certificate(ss->ssl_);
|
X509* peer_cert = SSL_get_peer_certificate(ss->ssl_);
|
||||||
if (peer_cert != NULL) {
|
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());
|
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));
|
ASN1_TIME_print(bio, X509_get_notBefore(peer_cert));
|
||||||
memset(buf, 0, sizeof(buf));
|
BIO_get_mem_ptr(bio, &mem);
|
||||||
BIO_read(bio, buf, sizeof(buf) - 1);
|
info->Set(valid_from_symbol, String::New(mem->data, mem->length));
|
||||||
info->Set(valid_from_symbol, String::New(buf));
|
(void) BIO_reset(bio);
|
||||||
|
|
||||||
ASN1_TIME_print(bio, X509_get_notAfter(peer_cert));
|
ASN1_TIME_print(bio, X509_get_notAfter(peer_cert));
|
||||||
memset(buf, 0, sizeof(buf));
|
BIO_get_mem_ptr(bio, &mem);
|
||||||
BIO_read(bio, buf, sizeof(buf) - 1);
|
info->Set(valid_to_symbol, String::New(mem->data, mem->length));
|
||||||
BIO_free(bio);
|
BIO_free(bio);
|
||||||
info->Set(valid_to_symbol, String::New(buf));
|
|
||||||
|
|
||||||
unsigned int md_size, i;
|
unsigned int md_size, i;
|
||||||
unsigned char md[EVP_MAX_MD_SIZE];
|
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);
|
peer_cert, NID_ext_key_usage, NULL, NULL);
|
||||||
if (eku != NULL) {
|
if (eku != NULL) {
|
||||||
Local<Array> ext_key_usage = Array::New();
|
Local<Array> ext_key_usage = Array::New();
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
for (int i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
|
for (int i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
|
||||||
memset(buf, 0, sizeof(buf));
|
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