|
|
@ -145,11 +145,89 @@ PayPro.prototype.x509Verify = function() { |
|
|
|
// Handle Cert Extensions
|
|
|
|
// http://tools.ietf.org/html/rfc5280#section-4.2
|
|
|
|
//
|
|
|
|
var extensions = rfc5280.parseExtensions(c.tbsCertificate, { partial: false }); |
|
|
|
var extensions = rfc5280.decodeExtensions(c, { partial: false }); |
|
|
|
var extensionsVerified = !extensions.unknown.filter(function(ext) { |
|
|
|
return ext.critical; |
|
|
|
}).length; |
|
|
|
|
|
|
|
// Object.keys(extensions).forEach(function(key) {
|
|
|
|
// if (extensions[key].execute) {
|
|
|
|
// c = extensions[key].execute(c);
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
|
|
|
|
if (extensions.subjectDirectoryAttributes) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.subjectKeyIdentifier) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.keyUsage) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.subjectAlternativeName) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.issuerAlternativeName) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.basicConstraints) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.nameConstraints) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.CRLDistributionPoints) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.certificatePolicies) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.policyMappings) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.authorityKeyIdentifier) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.policyConstraints) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.extendedKeyUsage) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.freshestCRL) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.inhibitanyPolicy) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.unknownExtension) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.authorityInformationAccess) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
if (extensions.subjectInformationAccess) { |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
//
|
|
|
|
// Verify current certificate signature
|
|
|
|
//
|
|
|
@ -861,8 +939,8 @@ rfc5280.extensions = { |
|
|
|
// VERY IMPORTANT, especially is cA (basic constraints) is true (it is)
|
|
|
|
15: { |
|
|
|
name: 'Key Usage', |
|
|
|
parse: function(data, decoded, ext) { |
|
|
|
data = data[0]; |
|
|
|
parse: function(decoded, cert, ext, edata) { |
|
|
|
var data = decoded.data[0]; |
|
|
|
return { |
|
|
|
digitalSignature: !!((data >> 0) & 1), |
|
|
|
nonRepudiation: !!((data >> 1) & 1), |
|
|
@ -876,6 +954,9 @@ rfc5280.extensions = { |
|
|
|
encipherOnly: !!((data >> 7) & 1), |
|
|
|
decipherOnly: !!((data >> 8) & 1) |
|
|
|
}; |
|
|
|
}, |
|
|
|
execute: function(cert) { |
|
|
|
return cert; |
|
|
|
} |
|
|
|
}, |
|
|
|
32: 'Certificate Policies', |
|
|
@ -887,7 +968,35 @@ rfc5280.extensions = { |
|
|
|
30: 'Name Constraints', |
|
|
|
36: 'Policy Constraints', |
|
|
|
37: 'Extended Key Usage', |
|
|
|
31: 'CRL Distribution Points', |
|
|
|
31: { |
|
|
|
name: 'CRL Distribution Points', |
|
|
|
parse: function(decoded, cert, ext, edata) { |
|
|
|
// XXX Find the bitstr: ReasonFlags
|
|
|
|
console.log('###########################'); |
|
|
|
console.log(decoded); |
|
|
|
console.log(cert); |
|
|
|
console.log(ext); |
|
|
|
console.log(edata); |
|
|
|
console.log('###########################'); |
|
|
|
// XXX Find the bitstr: ReasonFlags
|
|
|
|
// var data = CRLDistributionPoints.DistributionPoint.reasons;
|
|
|
|
// return {
|
|
|
|
// unused: !!((data >> 0) & 1),
|
|
|
|
// keyCompromise: !!((data >> 1) & 1),
|
|
|
|
// cACompromise: !!((data >> 2) & 1),
|
|
|
|
// affiliationChanged: !!((data >> 3) & 1),
|
|
|
|
// superseded: !!((data >> 4) & 1),
|
|
|
|
// cessationOfOperation: !!((data >> 5) & 1),
|
|
|
|
// certificateHold: !!((data >> 6) & 1),
|
|
|
|
// privilegeWithdrawn: !!((data >> 7) & 1),
|
|
|
|
// aACompromise: !!((data >> 8) & 1)
|
|
|
|
// };
|
|
|
|
return decoded; |
|
|
|
}, |
|
|
|
execute: function(cert) { |
|
|
|
return cert; |
|
|
|
} |
|
|
|
}, |
|
|
|
54: 'Inhibit anyPolicy', |
|
|
|
46: 'Freshest CRL', |
|
|
|
// Unknown Extension (not documented anywhere, probably non-standard)
|
|
|
@ -906,7 +1015,7 @@ rfc5280.extensions = { |
|
|
|
Object.keys(rfc5280.extensions).forEach(function(typeName) { |
|
|
|
var type = rfc5280.extensions[typeName]; |
|
|
|
Object.keys(type).forEach(function(suffix) { |
|
|
|
var id, prop, schemaName, schema, parse; |
|
|
|
var id, prop, schemaName, schema, parse, execute; |
|
|
|
|
|
|
|
if (suffix === 'prefix') |
|
|
|
return; |
|
|
@ -918,6 +1027,7 @@ Object.keys(rfc5280.extensions).forEach(function(typeName) { |
|
|
|
var obj = name; |
|
|
|
name = obj.name; |
|
|
|
parse = obj.parse; |
|
|
|
execute = obj.execute; |
|
|
|
} |
|
|
|
|
|
|
|
id = prefix.concat(suffix).join('.'); |
|
|
@ -941,16 +1051,24 @@ Object.keys(rfc5280.extensions).forEach(function(typeName) { |
|
|
|
prop: prop, |
|
|
|
schemaName: schemaName, |
|
|
|
schema: schema, |
|
|
|
parse: parse |
|
|
|
parse: parse, |
|
|
|
execute: execute |
|
|
|
}; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
rfc5280.parseExtensions = function(tbsCertificate, options) { |
|
|
|
var edata, eid, ext, decoded, data; |
|
|
|
rfc5280.decodeExtensions = function(cert, options) { |
|
|
|
var tbsCertificate = cert.tbsCertificate; |
|
|
|
|
|
|
|
if (!tbsCertificate) { |
|
|
|
tbsCertificate = cert; |
|
|
|
cert = null; |
|
|
|
} |
|
|
|
|
|
|
|
var edata, eid, ext, decoded, errors, data; |
|
|
|
|
|
|
|
var output = {}; |
|
|
|
var unknown = 0; |
|
|
|
output.unknown = []; |
|
|
|
|
|
|
|
for (var i = 0; i < tbsCertificate.extensions.length; i++) { |
|
|
|
edata = tbsCertificate.extensions[i]; |
|
|
@ -960,19 +1078,42 @@ rfc5280.parseExtensions = function(tbsCertificate, options) { |
|
|
|
// Parse Extension
|
|
|
|
decoded = ext.schema.decode(edata.extnValue, 'der', options); |
|
|
|
|
|
|
|
if (options.partial && decoded.result) { |
|
|
|
errors = decoded.errors; |
|
|
|
decoded = decoded.result; |
|
|
|
if (Array.isArray(decoded)) { |
|
|
|
decoded = decoded.map(function(decoded) { |
|
|
|
decoded.errors.forEach(function(error) { |
|
|
|
errors.push(error); |
|
|
|
}); |
|
|
|
return decoded.result; |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// If the Extension needs extra parsing (i.e. bitstrs)
|
|
|
|
data = ext.parse |
|
|
|
? ext.parse(decoded.data, decoded, ext) |
|
|
|
? ext.parse(decoded, cert, ext, edata) |
|
|
|
: decoded; |
|
|
|
|
|
|
|
// Tack on some useful info
|
|
|
|
|
|
|
|
// Comment for debugging:
|
|
|
|
// data._edata = edata;
|
|
|
|
// data._ext = ext;
|
|
|
|
|
|
|
|
// data.edata = edata;
|
|
|
|
// data.ext = ext;
|
|
|
|
data.errors = errors; |
|
|
|
if (ext.parse) { |
|
|
|
data._decoded = decoded; |
|
|
|
data.decoded = decoded; |
|
|
|
} |
|
|
|
|
|
|
|
// Execute Behavior for Cert
|
|
|
|
if (ext.execute) { |
|
|
|
data.execute = ext.execute; |
|
|
|
} |
|
|
|
|
|
|
|
// Add errors for partial: true
|
|
|
|
if (options.partial && errors) { |
|
|
|
data.errors = errors; |
|
|
|
} |
|
|
|
|
|
|
|
// Add our decoded extension to the output
|
|
|
@ -987,7 +1128,8 @@ rfc5280.parseExtensions = function(tbsCertificate, options) { |
|
|
|
print(data); |
|
|
|
} else { |
|
|
|
// Add unknown extension:
|
|
|
|
output['Unkown_' + unknown] = edata; |
|
|
|
output.unknown.push(edata); |
|
|
|
output['unkown_' + (output.unknown.length - 1)] = edata; |
|
|
|
|
|
|
|
// XXX Debug
|
|
|
|
print('Unknown extension: %s', eid); |
|
|
|