Browse Source

tls: fix encoding in certificate-related functions

Strings are treated as UTF8 instead of one-byte strings when
names are processed and when OpenSSL's ..._print functions are used.

This commit fixes simple/test-tls-peer-certificate-encoding test.

fix #8366
v0.11.14-release
Adam Lippai 10 years ago
committed by Fedor Indutny
parent
commit
11d57a535c
  1. 23
      src/node_crypto.cc
  2. 31
      test/fixtures/keys/Makefile
  3. 16
      test/fixtures/keys/agent5-cert.pem
  4. 12
      test/fixtures/keys/agent5-csr.pem
  5. 15
      test/fixtures/keys/agent5-key.pem
  6. 21
      test/fixtures/keys/agent5.cnf
  7. 2
      test/fixtures/keys/ca2-cert.srl
  8. 62
      test/simple/test-tls-peer-certificate-encoding.js

23
src/node_crypto.cc

@ -69,7 +69,7 @@ static const char CERTIFICATE_PFX[] = "-----BEGIN CERTIFICATE-----";
static const int CERTIFICATE_PFX_LEN = sizeof(CERTIFICATE_PFX) - 1;
static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
| ASN1_STRFLGS_ESC_MSB
| ASN1_STRFLGS_UTF8_CONVERT
| XN_FLAG_SEP_MULTILINE
| XN_FLAG_FN_SN;
@ -1130,7 +1130,8 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
X509_NAME_FLAGS) > 0) {
BIO_get_mem_ptr(bio, &mem);
info->Set(env->subject_string(),
OneByteString(env->isolate(), mem->data, mem->length));
String::NewFromUtf8(env->isolate(), mem->data,
String::kNormalString, mem->length));
}
(void) BIO_reset(bio);
@ -1138,7 +1139,8 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
if (X509_NAME_print_ex(bio, issuer_name, 0, X509_NAME_FLAGS) > 0) {
BIO_get_mem_ptr(bio, &mem);
info->Set(env->issuer_string(),
OneByteString(env->isolate(), mem->data, mem->length));
String::NewFromUtf8(env->isolate(), mem->data,
String::kNormalString, mem->length));
}
(void) BIO_reset(bio);
@ -1162,7 +1164,8 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
BIO_get_mem_ptr(bio, &mem);
info->Set(keys[i],
OneByteString(env->isolate(), mem->data, mem->length));
String::NewFromUtf8(env->isolate(), mem->data,
String::kNormalString, mem->length));
(void) BIO_reset(bio);
}
@ -1176,13 +1179,15 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
BN_print(bio, rsa->n);
BIO_get_mem_ptr(bio, &mem);
info->Set(env->modulus_string(),
OneByteString(env->isolate(), mem->data, mem->length));
String::NewFromUtf8(env->isolate(), mem->data,
String::kNormalString, mem->length));
(void) BIO_reset(bio);
BN_print(bio, rsa->e);
BIO_get_mem_ptr(bio, &mem);
info->Set(env->exponent_string(),
OneByteString(env->isolate(), mem->data, mem->length));
String::NewFromUtf8(env->isolate(), mem->data,
String::kNormalString, mem->length));
(void) BIO_reset(bio);
}
@ -1198,13 +1203,15 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
ASN1_TIME_print(bio, X509_get_notBefore(cert));
BIO_get_mem_ptr(bio, &mem);
info->Set(env->valid_from_string(),
OneByteString(env->isolate(), mem->data, mem->length));
String::NewFromUtf8(env->isolate(), mem->data,
String::kNormalString, mem->length));
(void) BIO_reset(bio);
ASN1_TIME_print(bio, X509_get_notAfter(cert));
BIO_get_mem_ptr(bio, &mem);
info->Set(env->valid_to_string(),
OneByteString(env->isolate(), mem->data, mem->length));
String::NewFromUtf8(env->isolate(), mem->data,
String::kNormalString, mem->length));
BIO_free_all(bio);
unsigned int md_size, i;

31
test/fixtures/keys/Makefile

@ -1,4 +1,4 @@
all: agent1-cert.pem agent2-cert.pem agent3-cert.pem agent4-cert.pem ca2-crl.pem ec-cert.pem dh512.pem dh1024.pem dh2048.pem
all: agent1-cert.pem agent2-cert.pem agent3-cert.pem agent4-cert.pem agent5-cert.pem ca2-crl.pem ec-cert.pem dh512.pem dh1024.pem dh2048.pem
#
@ -132,6 +132,31 @@ ca2-crl.pem: ca2-key.pem ca2-cert.pem ca2.cnf
-out ca2-crl.pem \
-passin 'pass:password'
#
# agent5 is signed by ca2 (client cert)
#
agent5-key.pem:
openssl genrsa -out agent5-key.pem 1024
agent5-csr.pem: agent5.cnf agent5-key.pem
openssl req -new -config agent5.cnf -key agent5-key.pem -out agent5-csr.pem
agent5-cert.pem: agent5-csr.pem ca2-cert.pem ca2-key.pem
openssl x509 -req \
-days 9999 \
-passin "pass:password" \
-in agent5-csr.pem \
-CA ca2-cert.pem \
-CAkey ca2-key.pem \
-CAcreateserial \
-extfile agent5.cnf \
-extensions ext_key_usage \
-out agent5-cert.pem
agent5-verify: agent5-cert.pem ca2-cert.pem
openssl verify -CAfile ca2-cert.pem agent5-cert.pem
ec-key.pem:
openssl ecparam -genkey -out ec-key.pem -name prime256v1
@ -157,7 +182,7 @@ dh2048.pem:
clean:
rm -f *.pem *.srl ca2-database.txt ca2-serial
test: agent1-verify agent2-verify agent3-verify agent4-verify
test: agent1-verify agent2-verify agent3-verify agent4-verify agent5-verify
.PHONY: all clean test agent1-verify agent2-verify agent3-verify agent4-verify
.PHONY: all clean test agent1-verify agent2-verify agent3-verify agent4-verify agent5-verify

16
test/fixtures/keys/agent5-cert.pem

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICgzCCAeygAwIBAgIJAO6+LOUhGhL4MA0GCSqGSIb3DQEBBQUAMHoxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJDQTELMAkGA1UEBxMCU0YxDzANBgNVBAoTBkpveWVu
dDEQMA4GA1UECxMHTm9kZS5qczEMMAoGA1UEAxMDY2EyMSAwHgYJKoZIhvcNAQkB
FhFyeUB0aW55Y2xvdWRzLm9yZzAeFw0xNDA5MTMyMjM0MThaFw00MjAxMjgyMjM0
MThaMHQxCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDERMA8GA1UECgwI
VHJlc29yaXQxFjAUBgNVBAMMDcOBZMOhbSBMaXBwYWkxJzAlBgkqhkiG9w0BCQEW
GGFkYW0ubGlwcGFpQHRyZXNvcml0LmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEAtrYJnvw24liDRWrfRDp/aBRwAK3xoaJ99YBCj7U8955GJvsoN21q6ZiD
gT+/7K+HA5gxLXTngrSCTzbk8qfGTD+Gco5WoOK7ubm5R4ePlGrT+yCMaUQBKzX7
3s3f0rxuAI5F2qCtIJAS/K6Nk3v6C60DyK/rudnY/+d8dFQf2gECAwEAAaMXMBUw
EwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAC+QBFRXhCWq3
BLogUKBPl9TWeu13aPkhMFo29ZZB4G2KCoKWUgHZyJ3Q/Dx40QA+PCrqmKxNHyUx
oEzol97MwB8Q4puv4BC3m8Zkgu/7z7CFH5LMh/shIjDT+kveGFUscqPzjHykeBhP
2/4042bED6KYhNw+f3DlN+Y1mBYKEuk=
-----END CERTIFICATE-----

12
test/fixtures/keys/agent5-csr.pem

@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIB2TCCAUICAQAwdDELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MREw
DwYDVQQKDAhUcmVzb3JpdDEWMBQGA1UEAwwNw4Fkw6FtIExpcHBhaTEnMCUGCSqG
SIb3DQEJARYYYWRhbS5saXBwYWlAdHJlc29yaXQuY29tMIGfMA0GCSqGSIb3DQEB
AQUAA4GNADCBiQKBgQC2tgme/DbiWINFat9EOn9oFHAArfGhon31gEKPtTz3nkYm
+yg3bWrpmIOBP7/sr4cDmDEtdOeCtIJPNuTyp8ZMP4Zyjlag4ru5ublHh4+UatP7
IIxpRAErNfvezd/SvG4AjkXaoK0gkBL8ro2Te/oLrQPIr+u52dj/53x0VB/aAQID
AQABoCUwIwYJKoZIhvcNAQkHMRYMFEEgY2hhbGxlbmdlIHBhc3N3b3JkMA0GCSqG
SIb3DQEBBQUAA4GBAAoVh5wdSi58RJrwy4xaXeZwrRUeCEfNf66AhAr16fa7AxMZ
7XCMGVYTCcPxsFaagYptWYigYOP3vC89i1dm29PjUwRvyTvkSQ+o/8Cjs+BESeG2
HrmK7b7xQjXCUwUXfHW7bnqVsTXcX1QfSztWKZANgETITD0MsGjh6Cdv+6ze
-----END CERTIFICATE REQUEST-----

15
test/fixtures/keys/agent5-key.pem

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC2tgme/DbiWINFat9EOn9oFHAArfGhon31gEKPtTz3nkYm+yg3
bWrpmIOBP7/sr4cDmDEtdOeCtIJPNuTyp8ZMP4Zyjlag4ru5ublHh4+UatP7IIxp
RAErNfvezd/SvG4AjkXaoK0gkBL8ro2Te/oLrQPIr+u52dj/53x0VB/aAQIDAQAB
AoGAbB+X2/THifT1YhwXmenAQdhuW4iUSKG/RowrV53aQXLxctoId5yRu0Ec+Vy/
eBJ7pJ3o5EydQFUQFE6Y+BxfFPogncoTu7U8I5S38aBDaL5teX8DzaDqLvcqU7GF
s+nOACcCErQ2BcpasTkKBFzzrpJtAes2jVzpsfa48JZtc70CQQDe0uUtlKR7tatL
sugU7OfRoeV1c/tHWp/5HODY0ZeMYvbNw6SqebKeBts26rJNGn4b4LgJs/TTT3qz
ux6a0ex3AkEA0eo22zaBVjZcygfIfEW9tyfGT1eHgfE/DHcaPHekwgwltoo2gEkU
hzWy7n09MTkM2Zw6RBz6yvbdJ80/T8UjRwJBALfPJPqauazLSgjiBozseLb3ZD+l
c02DNp/a8KgrDWbjZFCM6VMvnOa7JS6CIJ92ET2R/H8UkguWbtPAshhovzUCQQC8
uU8SbQGBKiToOnEkUWtMhMUFRlN9HxEpOtdqr8J/933cjIyNb6a2HTA+vHhMjdcg
uhWkcU2FNscEZsJaDIo3AkAOnbQTW1w4WjkV92B+EH6dQfS3wdCFVDUYM+POcwfQ
7HNtjmk1XeMTkGLlyinyFe2nARfXXzMmyRYP8o2m9uCf
-----END RSA PRIVATE KEY-----

21
test/fixtures/keys/agent5.cnf

@ -0,0 +1,21 @@
[ req ]
string_mask = utf8only
utf8 = yes
default_bits = 1024
days = 999
distinguished_name = req_distinguished_name
attributes = req_attributes
prompt = no
[ req_distinguished_name ]
C = HU
L = Budapest
O = Tresorit
CN = Ádám Lippai
emailAddress = adam.lippai@tresorit.com
[ req_attributes ]
challengePassword = A challenge password
[ ext_key_usage ]
extendedKeyUsage = clientAuth

2
test/fixtures/keys/ca2-cert.srl

@ -1 +1 @@
EEBE2CE5211A12F7
EEBE2CE5211A12F8

62
test/simple/test-tls-peer-certificate-encoding.js

@ -0,0 +1,62 @@
// 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, 'keys', 'agent5-key.pem')),
cert: fs.readFileSync(join(common.fixturesDir, 'keys', 'agent5-cert.pem')),
ca: [ fs.readFileSync(join(common.fixturesDir, 'keys', 'ca2-cert.pem')) ]
};
var verified = false;
var server = tls.createServer(options, function(cleartext) {
cleartext.end('World');
});
server.listen(common.PORT, function() {
var socket = tls.connect({
port: common.PORT,
rejectUnauthorized: false
}, function() {
var peerCert = socket.getPeerCertificate();
common.debug(util.inspect(peerCert));
assert.equal(peerCert.subject.CN, 'Ádám Lippai');
verified = true;
server.close();
});
socket.end('Hello');
});
process.on('exit', function() {
assert.ok(verified);
});
Loading…
Cancel
Save