summaryrefslogtreecommitdiff
path: root/node_modules/sshpk/lib/identity.js
diff options
context:
space:
mode:
authorLinuxWizard42 <computerwizard@linuxmail.org>2022-10-12 22:54:37 +0300
committerLinuxWizard42 <computerwizard@linuxmail.org>2022-10-12 22:54:37 +0300
commit703e03aba33f234712206769f57717ba7d92d23d (patch)
tree0041f04ccb75bd5379c764e9fe42249fffe75fc3 /node_modules/sshpk/lib/identity.js
parentab6e257e6e9d9a483d7e86f220d8b209a2cd7753 (diff)
downloadFlashRunner-703e03aba33f234712206769f57717ba7d92d23d.tar.gz
FlashRunner-703e03aba33f234712206769f57717ba7d92d23d.tar.zst
Added export_allowed file to make repository visible in cgit
Diffstat (limited to 'node_modules/sshpk/lib/identity.js')
-rw-r--r--node_modules/sshpk/lib/identity.js373
1 files changed, 373 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..7d75b66
--- /dev/null
+++ b/node_modules/sshpk/lib/identity.js
@@ -0,0 +1,373 @@
+// 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');
+var Buffer = require('safer-buffer').Buffer;
+
+/*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.postalCode = '2.5.4.17';
+oids.serialNumber = '2.5.4.5';
+oids.street = '2.5.4.9';
+oids.x500UniqueIdentifier = '2.5.4.45';
+oids.role = '2.5.4.72';
+oids.telephoneNumber = '2.5.4.20';
+oids.description = '2.5.4.13';
+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';
+oids.title = '2.5.4.12';
+oids.gn = '2.5.4.42';
+oids.initials = '2.5.4.43';
+oids.pseudonym = '2.5.4.65';
+oids.emailAddress = '1.2.840.113549.1.9.1';
+
+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) {
+ var n = c.name.toUpperCase();
+ /*JSSTYLED*/
+ n = n.replace(/=/g, '\\=');
+ var v = c.value;
+ /*JSSTYLED*/
+ v = v.replace(/,/g, '\\,');
+ return (n + '=' + v);
+ }).join(', '));
+};
+
+Identity.prototype.get = function (name, asArray) {
+ assert.string(name, 'name');
+ var arr = this.componentLookup[name];
+ if (arr === undefined || arr.length === 0)
+ return (undefined);
+ if (!asArray && arr.length > 1)
+ throw (new Error('Multiple values for attribute ' + name));
+ if (!asArray)
+ return (arr[0].value);
+ return (arr.map(function (c) {
+ return (c.value);
+ }));
+};
+
+Identity.prototype.toArray = function (idx) {
+ return (this.components.map(function (c) {
+ return ({
+ name: c.name,
+ value: c.value
+ });
+ }));
+};
+
+/*
+ * 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 this identity was parsed from a DN, use the ASN.1 types
+ * from the original representation (otherwise this might not
+ * be a full match for the original in some validators).
+ */
+ if (c.asn1type === asn1.Ber.Utf8String ||
+ c.value.match(NOT_IA5)) {
+ var v = Buffer.from(c.value, 'utf8');
+ der.writeBuffer(v, asn1.Ber.Utf8String);
+
+ } else if (c.asn1type === asn1.Ber.IA5String ||
+ c.value.match(NOT_PRINTABLE)) {
+ der.writeString(c.value, asn1.Ber.IA5String);
+
+ } else {
+ var type = asn1.Ber.PrintableString;
+ if (c.asn1type !== undefined)
+ type = c.asn1type;
+ der.writeString(c.value, type);
+ }
+ 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 = [''];
+ var idx = 0;
+ var rem = dn;
+ while (rem.length > 0) {
+ var m;
+ /*JSSTYLED*/
+ if ((m = /^,/.exec(rem)) !== null) {
+ parts[++idx] = '';
+ rem = rem.slice(m[0].length);
+ /*JSSTYLED*/
+ } else if ((m = /^\\,/.exec(rem)) !== null) {
+ parts[idx] += ',';
+ rem = rem.slice(m[0].length);
+ /*JSSTYLED*/
+ } else if ((m = /^\\./.exec(rem)) !== null) {
+ parts[idx] += m[0];
+ rem = rem.slice(m[0].length);
+ /*JSSTYLED*/
+ } else if ((m = /^[^\\,]+/.exec(rem)) !== null) {
+ parts[idx] += m[0];
+ rem = rem.slice(m[0].length);
+ } else {
+ throw (new Error('Failed to parse DN'));
+ }
+ }
+ var cmps = parts.map(function (c) {
+ c = c.trim();
+ var eqPos = c.indexOf('=');
+ while (eqPos > 0 && c.charAt(eqPos - 1) === '\\')
+ eqPos = c.indexOf('=', eqPos + 1);
+ if (eqPos === -1) {
+ throw (new Error('Failed to parse DN'));
+ }
+ /*JSSTYLED*/
+ var name = c.slice(0, eqPos).toLowerCase().replace(/\\=/g, '=');
+ var value = c.slice(eqPos + 1);
+ return ({ name: name, value: value });
+ });
+ return (new Identity({ components: cmps }));
+};
+
+Identity.fromArray = function (components) {
+ assert.arrayOfObject(components, 'components');
+ components.forEach(function (cmp) {
+ assert.object(cmp, 'component');
+ assert.string(cmp.name, 'component.name');
+ if (!Buffer.isBuffer(cmp.value) &&
+ !(typeof (cmp.value) === 'string')) {
+ throw (new Error('Invalid component value'));
+ }
+ });
+ return (new Identity({ components: components }));
+};
+
+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, asn1type: type, 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]);
+};