"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/sshpk/lib/formats/openssh-cert.js" (7 Feb 2017, 7433 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2016 Joyent, Inc.
    2 
    3 module.exports = {
    4     read: read,
    5     verify: verify,
    6     sign: sign,
    7     write: write,
    8 
    9     /* Internal private API */
   10     fromBuffer: fromBuffer,
   11     toBuffer: toBuffer
   12 };
   13 
   14 var assert = require('assert-plus');
   15 var SSHBuffer = require('../ssh-buffer');
   16 var crypto = require('crypto');
   17 var algs = require('../algs');
   18 var Key = require('../key');
   19 var PrivateKey = require('../private-key');
   20 var Identity = require('../identity');
   21 var rfc4253 = require('./rfc4253');
   22 var Signature = require('../signature');
   23 var utils = require('../utils');
   24 var Certificate = require('../certificate');
   25 
   26 function verify(cert, key) {
   27     /*
   28      * We always give an issuerKey, so if our verify() is being called then
   29      * there was no signature. Return false.
   30      */
   31     return (false);
   32 }
   33 
   34 var TYPES = {
   35     'user': 1,
   36     'host': 2
   37 };
   38 Object.keys(TYPES).forEach(function (k) { TYPES[TYPES[k]] = k; });
   39 
   40 var ECDSA_ALGO = /^ecdsa-sha2-([^@-]+)-cert-v01@openssh.com$/;
   41 
   42 function read(buf, options) {
   43     if (Buffer.isBuffer(buf))
   44         buf = buf.toString('ascii');
   45     var parts = buf.trim().split(/[ \t\n]+/g);
   46     if (parts.length < 2 || parts.length > 3)
   47         throw (new Error('Not a valid SSH certificate line'));
   48 
   49     var algo = parts[0];
   50     var data = parts[1];
   51 
   52     data = new Buffer(data, 'base64');
   53     return (fromBuffer(data, algo));
   54 }
   55 
   56 function fromBuffer(data, algo, partial) {
   57     var sshbuf = new SSHBuffer({ buffer: data });
   58     var innerAlgo = sshbuf.readString();
   59     if (algo !== undefined && innerAlgo !== algo)
   60         throw (new Error('SSH certificate algorithm mismatch'));
   61     if (algo === undefined)
   62         algo = innerAlgo;
   63 
   64     var cert = {};
   65     cert.signatures = {};
   66     cert.signatures.openssh = {};
   67 
   68     cert.signatures.openssh.nonce = sshbuf.readBuffer();
   69 
   70     var key = {};
   71     var parts = (key.parts = []);
   72     key.type = getAlg(algo);
   73 
   74     var partCount = algs.info[key.type].parts.length;
   75     while (parts.length < partCount)
   76         parts.push(sshbuf.readPart());
   77     assert.ok(parts.length >= 1, 'key must have at least one part');
   78 
   79     var algInfo = algs.info[key.type];
   80     if (key.type === 'ecdsa') {
   81         var res = ECDSA_ALGO.exec(algo);
   82         assert.ok(res !== null);
   83         assert.strictEqual(res[1], parts[0].data.toString());
   84     }
   85 
   86     for (var i = 0; i < algInfo.parts.length; ++i) {
   87         parts[i].name = algInfo.parts[i];
   88         if (parts[i].name !== 'curve' &&
   89             algInfo.normalize !== false) {
   90             var p = parts[i];
   91             p.data = utils.mpNormalize(p.data);
   92         }
   93     }
   94 
   95     cert.subjectKey = new Key(key);
   96 
   97     cert.serial = sshbuf.readInt64();
   98 
   99     var type = TYPES[sshbuf.readInt()];
  100     assert.string(type, 'valid cert type');
  101 
  102     cert.signatures.openssh.keyId = sshbuf.readString();
  103 
  104     var principals = [];
  105     var pbuf = sshbuf.readBuffer();
  106     var psshbuf = new SSHBuffer({ buffer: pbuf });
  107     while (!psshbuf.atEnd())
  108         principals.push(psshbuf.readString());
  109     if (principals.length === 0)
  110         principals = ['*'];
  111 
  112     cert.subjects = principals.map(function (pr) {
  113         if (type === 'user')
  114             return (Identity.forUser(pr));
  115         else if (type === 'host')
  116             return (Identity.forHost(pr));
  117         throw (new Error('Unknown identity type ' + type));
  118     });
  119 
  120     cert.validFrom = int64ToDate(sshbuf.readInt64());
  121     cert.validUntil = int64ToDate(sshbuf.readInt64());
  122 
  123     cert.signatures.openssh.critical = sshbuf.readBuffer();
  124     cert.signatures.openssh.exts = sshbuf.readBuffer();
  125 
  126     /* reserved */
  127     sshbuf.readBuffer();
  128 
  129     var signingKeyBuf = sshbuf.readBuffer();
  130     cert.issuerKey = rfc4253.read(signingKeyBuf);
  131 
  132     /*
  133      * OpenSSH certs don't give the identity of the issuer, just their
  134      * public key. So, we use an Identity that matches anything. The
  135      * isSignedBy() function will later tell you if the key matches.
  136      */
  137     cert.issuer = Identity.forHost('**');
  138 
  139     var sigBuf = sshbuf.readBuffer();
  140     cert.signatures.openssh.signature =
  141         Signature.parse(sigBuf, cert.issuerKey.type, 'ssh');
  142 
  143     if (partial !== undefined) {
  144         partial.remainder = sshbuf.remainder();
  145         partial.consumed = sshbuf._offset;
  146     }
  147 
  148     return (new Certificate(cert));
  149 }
  150 
  151 function int64ToDate(buf) {
  152     var i = buf.readUInt32BE(0) * 4294967296;
  153     i += buf.readUInt32BE(4);
  154     var d = new Date();
  155     d.setTime(i * 1000);
  156     d.sourceInt64 = buf;
  157     return (d);
  158 }
  159 
  160 function dateToInt64(date) {
  161     if (date.sourceInt64 !== undefined)
  162         return (date.sourceInt64);
  163     var i = Math.round(date.getTime() / 1000);
  164     var upper = Math.floor(i / 4294967296);
  165     var lower = Math.floor(i % 4294967296);
  166     var buf = new Buffer(8);
  167     buf.writeUInt32BE(upper, 0);
  168     buf.writeUInt32BE(lower, 4);
  169     return (buf);
  170 }
  171 
  172 function sign(cert, key) {
  173     if (cert.signatures.openssh === undefined)
  174         cert.signatures.openssh = {};
  175     try {
  176         var blob = toBuffer(cert, true);
  177     } catch (e) {
  178         delete (cert.signatures.openssh);
  179         return (false);
  180     }
  181     var sig = cert.signatures.openssh;
  182     var hashAlgo = undefined;
  183     if (key.type === 'rsa' || key.type === 'dsa')
  184         hashAlgo = 'sha1';
  185     var signer = key.createSign(hashAlgo);
  186     signer.write(blob);
  187     sig.signature = signer.sign();
  188     return (true);
  189 }
  190 
  191 function write(cert, options) {
  192     if (options === undefined)
  193         options = {};
  194 
  195     var blob = toBuffer(cert);
  196     var out = getCertType(cert.subjectKey) + ' ' + blob.toString('base64');
  197     if (options.comment)
  198         out = out + ' ' + options.comment;
  199     return (out);
  200 }
  201 
  202 
  203 function toBuffer(cert, noSig) {
  204     assert.object(cert.signatures.openssh, 'signature for openssh format');
  205     var sig = cert.signatures.openssh;
  206 
  207     if (sig.nonce === undefined)
  208         sig.nonce = crypto.randomBytes(16);
  209     var buf = new SSHBuffer({});
  210     buf.writeString(getCertType(cert.subjectKey));
  211     buf.writeBuffer(sig.nonce);
  212 
  213     var key = cert.subjectKey;
  214     var algInfo = algs.info[key.type];
  215     algInfo.parts.forEach(function (part) {
  216         buf.writePart(key.part[part]);
  217     });
  218 
  219     buf.writeInt64(cert.serial);
  220 
  221     var type = cert.subjects[0].type;
  222     assert.notStrictEqual(type, 'unknown');
  223     cert.subjects.forEach(function (id) {
  224         assert.strictEqual(id.type, type);
  225     });
  226     type = TYPES[type];
  227     buf.writeInt(type);
  228 
  229     if (sig.keyId === undefined) {
  230         sig.keyId = cert.subjects[0].type + '_' +
  231             (cert.subjects[0].uid || cert.subjects[0].hostname);
  232     }
  233     buf.writeString(sig.keyId);
  234 
  235     var sub = new SSHBuffer({});
  236     cert.subjects.forEach(function (id) {
  237         if (type === TYPES.host)
  238             sub.writeString(id.hostname);
  239         else if (type === TYPES.user)
  240             sub.writeString(id.uid);
  241     });
  242     buf.writeBuffer(sub.toBuffer());
  243 
  244     buf.writeInt64(dateToInt64(cert.validFrom));
  245     buf.writeInt64(dateToInt64(cert.validUntil));
  246 
  247     if (sig.critical === undefined)
  248         sig.critical = new Buffer(0);
  249     buf.writeBuffer(sig.critical);
  250 
  251     if (sig.exts === undefined)
  252         sig.exts = new Buffer(0);
  253     buf.writeBuffer(sig.exts);
  254 
  255     /* reserved */
  256     buf.writeBuffer(new Buffer(0));
  257 
  258     sub = rfc4253.write(cert.issuerKey);
  259     buf.writeBuffer(sub);
  260 
  261     if (!noSig)
  262         buf.writeBuffer(sig.signature.toBuffer('ssh'));
  263 
  264     return (buf.toBuffer());
  265 }
  266 
  267 function getAlg(certType) {
  268     if (certType === 'ssh-rsa-cert-v01@openssh.com')
  269         return ('rsa');
  270     if (certType === 'ssh-dss-cert-v01@openssh.com')
  271         return ('dsa');
  272     if (certType.match(ECDSA_ALGO))
  273         return ('ecdsa');
  274     if (certType === 'ssh-ed25519-cert-v01@openssh.com')
  275         return ('ed25519');
  276     throw (new Error('Unsupported cert type ' + certType));
  277 }
  278 
  279 function getCertType(key) {
  280     if (key.type === 'rsa')
  281         return ('ssh-rsa-cert-v01@openssh.com');
  282     if (key.type === 'dsa')
  283         return ('ssh-dss-cert-v01@openssh.com');
  284     if (key.type === 'ecdsa')
  285         return ('ecdsa-sha2-' + key.curve + '-cert-v01@openssh.com');
  286     if (key.type === 'ed25519')
  287         return ('ssh-ed25519-cert-v01@openssh.com');
  288     throw (new Error('Unsupported key type ' + key.type));
  289 }