Code coverage report for lib/_tls_common.js

Statements: 91.75% (89 / 97)      Branches: 90% (63 / 70)      Functions: 100% (4 / 4)      Lines: 92.31% (84 / 91)      Ignored: none     

All files » lib/ » _tls_common.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173    94 94     94   94 94   94 410       410 1   409   409 32   377       403     94     94 410   410 410 116   410   402       402 56 52 60     4     346     402 149 1 2   148               402 149 1 2   2     2     148 3   145         400 268   132   400 398 2 1   400   399 6         6       399 116     399 10 10   10 3   10 10 8   10 8   2         393 252 252     393     94 36     36 36 1   36 36 15 15     15 30     30     30     36        
(function () { 'use strict';
 
const constants = require('constants');
const tls = require('tls');
 
// Lazily loaded
var crypto = null;
 
const binding = process.binding('crypto');
const NativeSecureContext = binding.SecureContext;
 
function SecureContext(secureProtocol, flags, context) {
  Iif (!(this instanceof SecureContext)) {
    return new SecureContext(secureProtocol, flags, context);
  }
 
  if (context) {
    this.context = context;
  } else {
    this.context = new NativeSecureContext();
 
    if (secureProtocol) {
      this.context.init(secureProtocol);
    } else {
      this.context.init();
    }
  }
 
  if (flags) this.context.setOptions(flags);
}
 
exports.SecureContext = SecureContext;
 
 
exports.createSecureContext = function createSecureContext(options, context) {
  if (!options) options = {};
 
  var secureOptions = options.secureOptions;
  if (options.honorCipherOrder)
    secureOptions |= constants.SSL_OP_CIPHER_SERVER_PREFERENCE;
 
  var c = new SecureContext(options.secureProtocol, secureOptions, context);
 
  Iif (context) return c;
 
  // NOTE: It's important to add CA before the cert to be able to load
  // cert's issuer in C++ code.
  if (options.ca) {
    if (Array.isArray(options.ca)) {
      for (var i = 0, len = options.ca.length; i < len; i++) {
        c.context.addCACert(options.ca[i]);
      }
    } else {
      c.context.addCACert(options.ca);
    }
  } else {
    c.context.addRootCerts();
  }
 
  if (options.cert) {
    if (Array.isArray(options.cert)) {
      for (var i = 0; i < options.cert.length; i++)
        c.context.setCert(options.cert[i]);
    } else {
      c.context.setCert(options.cert);
    }
  }
 
  // NOTE: It is important to set the key after the cert.
  // `ssl_set_pkey` returns `0` when the key does not much the cert, but
  // `ssl_set_cert` returns `1` and nullifies the key in the SSL structure
  // which leads to the crash later on.
  if (options.key) {
    if (Array.isArray(options.key)) {
      for (var i = 0; i < options.key.length; i++) {
        var key = options.key[i];
 
        Iif (key.passphrase)
          c.context.setKey(key.pem, key.passphrase);
        else
          c.context.setKey(key);
      }
    } else {
      if (options.passphrase) {
        c.context.setKey(options.key, options.passphrase);
      } else {
        c.context.setKey(options.key);
      }
    }
  }
 
  if (options.ciphers)
    c.context.setCiphers(options.ciphers);
  else
    c.context.setCiphers(tls.DEFAULT_CIPHERS);
 
  if (options.ecdhCurve === undefined)
    c.context.setECDHCurve(tls.DEFAULT_ECDH_CURVE);
  else if (options.ecdhCurve)
    c.context.setECDHCurve(options.ecdhCurve);
 
  if (options.dhparam) c.context.setDHParam(options.dhparam);
 
  if (options.crl) {
    Iif (Array.isArray(options.crl)) {
      for (var i = 0, len = options.crl.length; i < len; i++) {
        c.context.addCRL(options.crl[i]);
      }
    } else {
      c.context.addCRL(options.crl);
    }
  }
 
  if (options.sessionIdContext) {
    c.context.setSessionIdContext(options.sessionIdContext);
  }
 
  if (options.pfx) {
    var pfx = options.pfx;
    var passphrase = options.passphrase;
 
    if (!crypto)
      crypto = require('crypto');
 
    pfx = crypto._toBuf(pfx);
    if (passphrase)
      passphrase = crypto._toBuf(passphrase);
 
    if (passphrase) {
      c.context.loadPKCS12(pfx, passphrase);
    } else {
      c.context.loadPKCS12(pfx);
    }
  }
 
  // Do not keep read/write buffers in free list
  if (options.singleUse) {
    c.singleUse = true;
    c.context.setFreeListLength(0);
  }
 
  return c;
};
 
exports.translatePeerCertificate = function translatePeerCertificate(c) {
  Iif (!c)
    return null;
 
  if (c.issuer) c.issuer = tls.parseCertString(c.issuer);
  if (c.issuerCertificate && c.issuerCertificate !== c) {
    c.issuerCertificate = translatePeerCertificate(c.issuerCertificate);
  }
  if (c.subject) c.subject = tls.parseCertString(c.subject);
  if (c.infoAccess) {
    var info = c.infoAccess;
    c.infoAccess = {};
 
    // XXX: More key validation?
    info.replace(/([^\n:]*):([^\n]*)(?:\n|$)/g, function(all, key, val) {
      Iif (key === '__proto__')
        return;
 
      Iif (c.infoAccess.hasOwnProperty(key))
        c.infoAccess[key].push(val);
      else
        c.infoAccess[key] = [val];
    });
  }
  return c;
};
 
}());