diff options
| author | Arman Shah <[email protected]> | 2018-02-19 23:50:04 -0800 |
|---|---|---|
| committer | Arman Shah <[email protected]> | 2018-02-19 23:50:04 -0800 |
| commit | ae34dcfd3823a609ba7182f2d6eda593be876f7d (patch) | |
| tree | b9d7f2884c4999349418cbdc4f9ab46d113e0afd /node_modules/sshpk/lib/identity.js | |
| parent | Initial commit (diff) | |
| download | launcher-ae34dcfd3823a609ba7182f2d6eda593be876f7d.tar.xz launcher-ae34dcfd3823a609ba7182f2d6eda593be876f7d.zip | |
add base files
Diffstat (limited to 'node_modules/sshpk/lib/identity.js')
| -rw-r--r-- | node_modules/sshpk/lib/identity.js | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/node_modules/sshpk/lib/identity.js b/node_modules/sshpk/lib/identity.js new file mode 100644 index 0000000..5e9021f --- /dev/null +++ b/node_modules/sshpk/lib/identity.js @@ -0,0 +1,277 @@ +// Copyright 2017 Joyent, Inc. + +module.exports = Identity; + +var assert = require('assert-plus'); +var algs = require('./algs'); +var crypto = require('crypto'); +var Fingerprint = require('./fingerprint'); +var Signature = require('./signature'); +var errs = require('./errors'); +var util = require('util'); +var utils = require('./utils'); +var asn1 = require('asn1'); + +/*JSSTYLED*/ +var DNS_NAME_RE = /^([*]|[a-z0-9][a-z0-9\-]{0,62})(?:\.([*]|[a-z0-9][a-z0-9\-]{0,62}))*$/i; + +var oids = {}; +oids.cn = '2.5.4.3'; +oids.o = '2.5.4.10'; +oids.ou = '2.5.4.11'; +oids.l = '2.5.4.7'; +oids.s = '2.5.4.8'; +oids.c = '2.5.4.6'; +oids.sn = '2.5.4.4'; +oids.dc = '0.9.2342.19200300.100.1.25'; +oids.uid = '0.9.2342.19200300.100.1.1'; +oids.mail = '0.9.2342.19200300.100.1.3'; + +var unoids = {}; +Object.keys(oids).forEach(function (k) { + unoids[oids[k]] = k; +}); + +function Identity(opts) { + var self = this; + assert.object(opts, 'options'); + assert.arrayOfObject(opts.components, 'options.components'); + this.components = opts.components; + this.componentLookup = {}; + this.components.forEach(function (c) { + if (c.name && !c.oid) + c.oid = oids[c.name]; + if (c.oid && !c.name) + c.name = unoids[c.oid]; + if (self.componentLookup[c.name] === undefined) + self.componentLookup[c.name] = []; + self.componentLookup[c.name].push(c); + }); + if (this.componentLookup.cn && this.componentLookup.cn.length > 0) { + this.cn = this.componentLookup.cn[0].value; + } + assert.optionalString(opts.type, 'options.type'); + if (opts.type === undefined) { + if (this.components.length === 1 && + this.componentLookup.cn && + this.componentLookup.cn.length === 1 && + this.componentLookup.cn[0].value.match(DNS_NAME_RE)) { + this.type = 'host'; + this.hostname = this.componentLookup.cn[0].value; + + } else if (this.componentLookup.dc && + this.components.length === this.componentLookup.dc.length) { + this.type = 'host'; + this.hostname = this.componentLookup.dc.map( + function (c) { + return (c.value); + }).join('.'); + + } else if (this.componentLookup.uid && + this.components.length === + this.componentLookup.uid.length) { + this.type = 'user'; + this.uid = this.componentLookup.uid[0].value; + + } else if (this.componentLookup.cn && + this.componentLookup.cn.length === 1 && + this.componentLookup.cn[0].value.match(DNS_NAME_RE)) { + this.type = 'host'; + this.hostname = this.componentLookup.cn[0].value; + + } else if (this.componentLookup.uid && + this.componentLookup.uid.length === 1) { + this.type = 'user'; + this.uid = this.componentLookup.uid[0].value; + + } else if (this.componentLookup.mail && + this.componentLookup.mail.length === 1) { + this.type = 'email'; + this.email = this.componentLookup.mail[0].value; + + } else if (this.componentLookup.cn && + this.componentLookup.cn.length === 1) { + this.type = 'user'; + this.uid = this.componentLookup.cn[0].value; + + } else { + this.type = 'unknown'; + } + } else { + this.type = opts.type; + if (this.type === 'host') + this.hostname = opts.hostname; + else if (this.type === 'user') + this.uid = opts.uid; + else if (this.type === 'email') + this.email = opts.email; + else + throw (new Error('Unknown type ' + this.type)); + } +} + +Identity.prototype.toString = function () { + return (this.components.map(function (c) { + return (c.name.toUpperCase() + '=' + c.value); + }).join(', ')); +}; + +/* + * These are from X.680 -- PrintableString allowed chars are in section 37.4 + * table 8. Spec for IA5Strings is "1,6 + SPACE + DEL" where 1 refers to + * ISO IR #001 (standard ASCII control characters) and 6 refers to ISO IR #006 + * (the basic ASCII character set). + */ +/* JSSTYLED */ +var NOT_PRINTABLE = /[^a-zA-Z0-9 '(),+.\/:=?-]/; +/* JSSTYLED */ +var NOT_IA5 = /[^\x00-\x7f]/; + +Identity.prototype.toAsn1 = function (der, tag) { + der.startSequence(tag); + this.components.forEach(function (c) { + der.startSequence(asn1.Ber.Constructor | asn1.Ber.Set); + der.startSequence(); + der.writeOID(c.oid); + /* + * If we fit in a PrintableString, use that. Otherwise use an + * IA5String or UTF8String. + */ + if (c.value.match(NOT_IA5)) { + var v = new Buffer(c.value, 'utf8'); + der.writeBuffer(v, asn1.Ber.Utf8String); + } else if (c.value.match(NOT_PRINTABLE)) { + der.writeString(c.value, asn1.Ber.IA5String); + } else { + der.writeString(c.value, asn1.Ber.PrintableString); + } + der.endSequence(); + der.endSequence(); + }); + der.endSequence(); +}; + +function globMatch(a, b) { + if (a === '**' || b === '**') + return (true); + var aParts = a.split('.'); + var bParts = b.split('.'); + if (aParts.length !== bParts.length) + return (false); + for (var i = 0; i < aParts.length; ++i) { + if (aParts[i] === '*' || bParts[i] === '*') + continue; + if (aParts[i] !== bParts[i]) + return (false); + } + return (true); +} + +Identity.prototype.equals = function (other) { + if (!Identity.isIdentity(other, [1, 0])) + return (false); + if (other.components.length !== this.components.length) + return (false); + for (var i = 0; i < this.components.length; ++i) { + if (this.components[i].oid !== other.components[i].oid) + return (false); + if (!globMatch(this.components[i].value, + other.components[i].value)) { + return (false); + } + } + return (true); +}; + +Identity.forHost = function (hostname) { + assert.string(hostname, 'hostname'); + return (new Identity({ + type: 'host', + hostname: hostname, + components: [ { name: 'cn', value: hostname } ] + })); +}; + +Identity.forUser = function (uid) { + assert.string(uid, 'uid'); + return (new Identity({ + type: 'user', + uid: uid, + components: [ { name: 'uid', value: uid } ] + })); +}; + +Identity.forEmail = function (email) { + assert.string(email, 'email'); + return (new Identity({ + type: 'email', + email: email, + components: [ { name: 'mail', value: email } ] + })); +}; + +Identity.parseDN = function (dn) { + assert.string(dn, 'dn'); + var parts = dn.split(','); + var cmps = parts.map(function (c) { + c = c.trim(); + var eqPos = c.indexOf('='); + var name = c.slice(0, eqPos).toLowerCase(); + var value = c.slice(eqPos + 1); + return ({ name: name, value: value }); + }); + return (new Identity({ components: cmps })); +}; + +Identity.parseAsn1 = function (der, top) { + var components = []; + der.readSequence(top); + var end = der.offset + der.length; + while (der.offset < end) { + der.readSequence(asn1.Ber.Constructor | asn1.Ber.Set); + var after = der.offset + der.length; + der.readSequence(); + var oid = der.readOID(); + var type = der.peek(); + var value; + switch (type) { + case asn1.Ber.PrintableString: + case asn1.Ber.IA5String: + case asn1.Ber.OctetString: + case asn1.Ber.T61String: + value = der.readString(type); + break; + case asn1.Ber.Utf8String: + value = der.readString(type, true); + value = value.toString('utf8'); + break; + case asn1.Ber.CharacterString: + case asn1.Ber.BMPString: + value = der.readString(type, true); + value = value.toString('utf16le'); + break; + default: + throw (new Error('Unknown asn1 type ' + type)); + } + components.push({ oid: oid, value: value }); + der._offset = after; + } + der._offset = end; + return (new Identity({ + components: components + })); +}; + +Identity.isIdentity = function (obj, ver) { + return (utils.isCompatible(obj, Identity, ver)); +}; + +/* + * API versions for Identity: + * [1,0] -- initial ver + */ +Identity.prototype._sshpkApiVersion = [1, 0]; + +Identity._oldVersionDetect = function (obj) { + return ([1, 0]); +}; |