Skip to content

Commit 8cd07bb

Browse files
committed
TLS: handle cert chains
1 parent 43bc1d7 commit 8cd07bb

1 file changed

Lines changed: 124 additions & 46 deletions

File tree

src/node_crypto.cc

Lines changed: 124 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,72 @@ Handle<Value> SecureContext::SetKey(const Arguments& args) {
185185
}
186186

187187

188+
// Read a file that contains our certificate in "PEM" format,
189+
// possibly followed by a sequence of CA certificates that should be
190+
// sent to the peer in the Certificate message.
191+
//
192+
// Taken from OpenSSL - editted for style.
193+
int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, BIO *in) {
194+
int ret = 0;
195+
X509 *x = NULL;
196+
197+
x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
198+
199+
if (x == NULL) {
200+
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
201+
goto end;
202+
}
203+
204+
ret = SSL_CTX_use_certificate(ctx, x);
205+
206+
if (ERR_peek_error() != 0) {
207+
// Key/certificate mismatch doesn't imply ret==0 ...
208+
ret = 0;
209+
}
210+
211+
if (ret) {
212+
// If we could set up our certificate, now proceed to
213+
// the CA certificates.
214+
X509 *ca;
215+
int r;
216+
unsigned long err;
217+
218+
if (ctx->extra_certs != NULL) {
219+
sk_X509_pop_free(ctx->extra_certs, X509_free);
220+
ctx->extra_certs = NULL;
221+
}
222+
223+
while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
224+
r = SSL_CTX_add_extra_chain_cert(ctx, ca);
225+
226+
if (!r) {
227+
X509_free(ca);
228+
ret = 0;
229+
goto end;
230+
}
231+
// Note that we must not free r if it was successfully
232+
// added to the chain (while we must free the main
233+
// certificate, since its reference count is increased
234+
// by SSL_CTX_use_certificate).
235+
}
236+
237+
// When the while loop ends, it's usually just EOF.
238+
err = ERR_peek_last_error();
239+
if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
240+
ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
241+
ERR_clear_error();
242+
} else {
243+
// some real error
244+
ret = 0;
245+
}
246+
}
247+
248+
end:
249+
if (x != NULL) X509_free(x);
250+
return ret;
251+
}
252+
253+
188254
Handle<Value> SecureContext::SetCert(const Arguments& args) {
189255
HandleScope scope;
190256

@@ -195,11 +261,23 @@ Handle<Value> SecureContext::SetCert(const Arguments& args) {
195261
String::New("Bad parameter")));
196262
}
197263

198-
X509* x509 = LoadX509(args[0]);
199-
if (!x509) return False();
264+
BIO* bio = LoadBIO(args[0]);
265+
if (!bio) return False();
200266

201-
SSL_CTX_use_certificate(sc->ctx_, x509);
202-
X509_free(x509);
267+
int rv = SSL_CTX_use_certificate_chain(sc->ctx_, bio);
268+
269+
BIO_free(bio);
270+
271+
if (!rv) {
272+
unsigned long err = ERR_get_error();
273+
if (!err) {
274+
return ThrowException(Exception::Error(
275+
String::New("SSL_CTX_use_certificate_chain")));
276+
}
277+
char string[120];
278+
ERR_error_string(err, string);
279+
return ThrowException(Exception::Error(String::New(string)));
280+
}
203281

204282
return True();
205283
}
@@ -1233,9 +1311,9 @@ class Cipher : public ObjectWrap {
12331311
EVP_CIPHER_CTX_init(&ctx);
12341312
EVP_CipherInit(&ctx,cipher,(unsigned char *)key,(unsigned char *)iv, true);
12351313
if (!EVP_CIPHER_CTX_set_key_length(&ctx,key_len)) {
1236-
fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
1237-
EVP_CIPHER_CTX_cleanup(&ctx);
1238-
return false;
1314+
fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
1315+
EVP_CIPHER_CTX_cleanup(&ctx);
1316+
return false;
12391317
}
12401318
initialised_ = true;
12411319
return true;
@@ -1253,15 +1331,15 @@ class Cipher : public ObjectWrap {
12531331
return false;
12541332
}
12551333
if (EVP_CIPHER_iv_length(cipher)!=iv_len) {
1256-
fprintf(stderr, "node-crypto : Invalid IV length %d\n", iv_len);
1334+
fprintf(stderr, "node-crypto : Invalid IV length %d\n", iv_len);
12571335
return false;
12581336
}
12591337
EVP_CIPHER_CTX_init(&ctx);
12601338
EVP_CipherInit(&ctx,cipher,(unsigned char *)key,(unsigned char *)iv, true);
12611339
if (!EVP_CIPHER_CTX_set_key_length(&ctx,key_len)) {
1262-
fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
1263-
EVP_CIPHER_CTX_cleanup(&ctx);
1264-
return false;
1340+
fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
1341+
EVP_CIPHER_CTX_cleanup(&ctx);
1342+
return false;
12651343
}
12661344
initialised_ = true;
12671345
return true;
@@ -1336,7 +1414,7 @@ class Cipher : public ObjectWrap {
13361414

13371415
static Handle<Value> CipherInitIv(const Arguments& args) {
13381416
Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());
1339-
1417+
13401418
HandleScope scope;
13411419

13421420
cipher->incomplete_base64=NULL;
@@ -1368,7 +1446,7 @@ class Cipher : public ObjectWrap {
13681446
assert(iv_written == iv_len);
13691447

13701448
String::Utf8Value cipherType(args[0]->ToString());
1371-
1449+
13721450
bool r = cipher->CipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len);
13731451

13741452
delete [] key_buf;
@@ -1421,19 +1499,19 @@ class Cipher : public ObjectWrap {
14211499
if (out_len==0) {
14221500
outString=String::New("");
14231501
} else {
1424-
if (args.Length() <= 2 || !args[2]->IsString()) {
1425-
// Binary
1426-
outString = Encode(out, out_len, BINARY);
1427-
} else {
1428-
char* out_hexdigest;
1429-
int out_hex_len;
1430-
String::Utf8Value encoding(args[2]->ToString());
1431-
if (strcasecmp(*encoding, "hex") == 0) {
1432-
// Hex encoding
1433-
HexEncode(out, out_len, &out_hexdigest, &out_hex_len);
1434-
outString = Encode(out_hexdigest, out_hex_len, BINARY);
1435-
delete [] out_hexdigest;
1436-
} else if (strcasecmp(*encoding, "base64") == 0) {
1502+
if (args.Length() <= 2 || !args[2]->IsString()) {
1503+
// Binary
1504+
outString = Encode(out, out_len, BINARY);
1505+
} else {
1506+
char* out_hexdigest;
1507+
int out_hex_len;
1508+
String::Utf8Value encoding(args[2]->ToString());
1509+
if (strcasecmp(*encoding, "hex") == 0) {
1510+
// Hex encoding
1511+
HexEncode(out, out_len, &out_hexdigest, &out_hex_len);
1512+
outString = Encode(out_hexdigest, out_hex_len, BINARY);
1513+
delete [] out_hexdigest;
1514+
} else if (strcasecmp(*encoding, "base64") == 0) {
14371515
// Base64 encoding
14381516
// Check to see if we need to add in previous base64 overhang
14391517
if (cipher->incomplete_base64!=NULL){
@@ -1460,16 +1538,16 @@ class Cipher : public ObjectWrap {
14601538
out[out_len]=0;
14611539
}
14621540

1463-
base64(out, out_len, &out_hexdigest, &out_hex_len);
1464-
outString = Encode(out_hexdigest, out_hex_len, BINARY);
1465-
delete [] out_hexdigest;
1466-
} else if (strcasecmp(*encoding, "binary") == 0) {
1467-
outString = Encode(out, out_len, BINARY);
1468-
} else {
1541+
base64(out, out_len, &out_hexdigest, &out_hex_len);
1542+
outString = Encode(out_hexdigest, out_hex_len, BINARY);
1543+
delete [] out_hexdigest;
1544+
} else if (strcasecmp(*encoding, "binary") == 0) {
1545+
outString = Encode(out, out_len, BINARY);
1546+
} else {
14691547
fprintf(stderr, "node-crypto : Cipher .update encoding "
14701548
"can be binary, hex or base64\n");
1471-
}
1472-
}
1549+
}
1550+
}
14731551
}
14741552

14751553
if (out) delete [] out;
@@ -1585,9 +1663,9 @@ class Decipher : public ObjectWrap {
15851663
(unsigned char *)(iv),
15861664
false);
15871665
if (!EVP_CIPHER_CTX_set_key_length(&ctx,key_len)) {
1588-
fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
1589-
EVP_CIPHER_CTX_cleanup(&ctx);
1590-
return false;
1666+
fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
1667+
EVP_CIPHER_CTX_cleanup(&ctx);
1668+
return false;
15911669
}
15921670
initialised_ = true;
15931671
return true;
@@ -1605,7 +1683,7 @@ class Decipher : public ObjectWrap {
16051683
return false;
16061684
}
16071685
if (EVP_CIPHER_iv_length(cipher_) != iv_len) {
1608-
fprintf(stderr, "node-crypto : Invalid IV length %d\n", iv_len);
1686+
fprintf(stderr, "node-crypto : Invalid IV length %d\n", iv_len);
16091687
return false;
16101688
}
16111689
EVP_CIPHER_CTX_init(&ctx);
@@ -1615,9 +1693,9 @@ class Decipher : public ObjectWrap {
16151693
(unsigned char *)(iv),
16161694
false);
16171695
if (!EVP_CIPHER_CTX_set_key_length(&ctx,key_len)) {
1618-
fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
1619-
EVP_CIPHER_CTX_cleanup(&ctx);
1620-
return false;
1696+
fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
1697+
EVP_CIPHER_CTX_cleanup(&ctx);
1698+
return false;
16211699
}
16221700
initialised_ = true;
16231701
return true;
@@ -1659,7 +1737,7 @@ class Decipher : public ObjectWrap {
16591737

16601738
static Handle<Value> DecipherInit(const Arguments& args) {
16611739
Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
1662-
1740+
16631741
HandleScope scope;
16641742

16651743
cipher->incomplete_utf8=NULL;
@@ -1682,7 +1760,7 @@ class Decipher : public ObjectWrap {
16821760
assert(key_written == key_len);
16831761

16841762
String::Utf8Value cipherType(args[0]->ToString());
1685-
1763+
16861764
bool r = cipher->DecipherInit(*cipherType, key_buf,key_len);
16871765

16881766
delete [] key_buf;
@@ -1696,7 +1774,7 @@ class Decipher : public ObjectWrap {
16961774

16971775
static Handle<Value> DecipherInitIv(const Arguments& args) {
16981776
Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
1699-
1777+
17001778
HandleScope scope;
17011779

17021780
cipher->incomplete_utf8=NULL;
@@ -1730,7 +1808,7 @@ class Decipher : public ObjectWrap {
17301808
assert(iv_written == iv_len);
17311809

17321810
String::Utf8Value cipherType(args[0]->ToString());
1733-
1811+
17341812
bool r = cipher->DecipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len);
17351813

17361814
delete [] key_buf;
@@ -2087,7 +2165,7 @@ class Hmac : public ObjectWrap {
20872165
}
20882166

20892167
int r;
2090-
2168+
20912169
if( Buffer::HasInstance(args[0])) {
20922170
Local<Object> buffer_obj = args[0]->ToObject();
20932171
char *buffer_data = Buffer::Data(buffer_obj);

0 commit comments

Comments
 (0)