https
express server läuft jetzt mit https
This commit is contained in:
		
							
								
								
									
										51
									
								
								express-server/node_modules/greenlock/lib/community.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								express-server/node_modules/greenlock/lib/community.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
function addCommunityMember(opts) {
 | 
			
		||||
  // { name, version, email, domains, action, communityMember, telemetry }
 | 
			
		||||
  setTimeout(function () {
 | 
			
		||||
    var https = require('https');
 | 
			
		||||
    var req = https.request({
 | 
			
		||||
      hostname: 'api.ppl.family'
 | 
			
		||||
    , port: 443
 | 
			
		||||
    , path: '/api/ppl.family/public/list'
 | 
			
		||||
    , method: 'POST'
 | 
			
		||||
    , headers: {
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      }
 | 
			
		||||
    }, function (err, resp) {
 | 
			
		||||
      if (err) { return; }
 | 
			
		||||
      resp.on('data', function () {});
 | 
			
		||||
    });
 | 
			
		||||
    var os = require('os');
 | 
			
		||||
    var data = {
 | 
			
		||||
      address: opts.email
 | 
			
		||||
      // greenlock-security is transactional and security only
 | 
			
		||||
    , list: opts.communityMember ? (opts.name + '@ppl.family') : 'greenlock-security@ppl.family'
 | 
			
		||||
    , action: opts.action // reg | renew
 | 
			
		||||
    , package: opts.name
 | 
			
		||||
      // hashed for privacy, but so we can still get some telemetry and inform users
 | 
			
		||||
      // if abnormal things are happening (like several registrations for the same domain each day)
 | 
			
		||||
    , domain: (opts.domains||[]).map(function (d) {
 | 
			
		||||
        return require('crypto').createHash('sha1').update(d).digest('base64')
 | 
			
		||||
          .replace(/\//g, '_').replace(/\+/g, '-').replace(/=/g, '');
 | 
			
		||||
      }).join(',')
 | 
			
		||||
    };
 | 
			
		||||
    if (false !== opts.telemetry) {
 | 
			
		||||
      data.arch = process.arch || os.arch();
 | 
			
		||||
      data.platform = process.platform || os.platform();
 | 
			
		||||
      data.release = os.release();
 | 
			
		||||
      data.version = opts.version;
 | 
			
		||||
      data.node = process.version;
 | 
			
		||||
    }
 | 
			
		||||
    req.write(JSON.stringify(data, 2, null));
 | 
			
		||||
    req.end();
 | 
			
		||||
  }, 50);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.add = addCommunityMember;
 | 
			
		||||
 | 
			
		||||
if (require.main === module) {
 | 
			
		||||
  //addCommunityMember('greenlock-express.js', 'reg', 'coolaj86+test42@gmail.com', ['coolaj86.com'], true);
 | 
			
		||||
  //addCommunityMember('greenlock.js', 'reg', 'coolaj86+test37@gmail.com', ['oneal.im'], false);
 | 
			
		||||
  //addCommunityMember('greenlock.js', 'reg', 'coolaj86+test11@gmail.com', ['ppl.family'], true);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										459
									
								
								express-server/node_modules/greenlock/lib/core.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										459
									
								
								express-server/node_modules/greenlock/lib/core.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,459 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var PromiseA;
 | 
			
		||||
try {
 | 
			
		||||
  PromiseA = require('bluebird');
 | 
			
		||||
} catch(e) {
 | 
			
		||||
  PromiseA = global.Promise;
 | 
			
		||||
}
 | 
			
		||||
var util = require('util');
 | 
			
		||||
function promisifyAll(obj) {
 | 
			
		||||
  var aobj = {};
 | 
			
		||||
  Object.keys(obj).forEach(function (key) {
 | 
			
		||||
    if ('function' === typeof obj[key]) {
 | 
			
		||||
      aobj[key] = obj[key];
 | 
			
		||||
      aobj[key + 'Async'] = util.promisify(obj[key]);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  return aobj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _log(debug) {
 | 
			
		||||
  if (debug) {
 | 
			
		||||
    var args = Array.prototype.slice.call(arguments);
 | 
			
		||||
    args.shift();
 | 
			
		||||
    args.unshift("[greenlock/lib/core.js]");
 | 
			
		||||
    console.log.apply(console, args);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.create = function (gl) {
 | 
			
		||||
  var utils = require('./utils');
 | 
			
		||||
  var RSA = promisifyAll(require('rsa-compat').RSA);
 | 
			
		||||
  var log = gl.log || _log; // allow custom log
 | 
			
		||||
  var pendingRegistrations = {};
 | 
			
		||||
 | 
			
		||||
  var core = {
 | 
			
		||||
    //
 | 
			
		||||
    // Helpers
 | 
			
		||||
    //
 | 
			
		||||
    getAcmeUrlsAsync: function (args) {
 | 
			
		||||
      var now = Date.now();
 | 
			
		||||
 | 
			
		||||
      // TODO check response header on request for cache time
 | 
			
		||||
      if ((now - gl._ipc.acmeUrlsUpdatedAt) < 10 * 60 * 1000) {
 | 
			
		||||
        return PromiseA.resolve(gl._ipc.acmeUrls);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return gl.acme.getAcmeUrlsAsync(args.server).then(function (data) {
 | 
			
		||||
        gl._ipc.acmeUrlsUpdatedAt = Date.now();
 | 
			
		||||
        gl._ipc.acmeUrls = data;
 | 
			
		||||
 | 
			
		||||
        return gl._ipc.acmeUrls;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // The Main Enchilada
 | 
			
		||||
    //
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // Accounts
 | 
			
		||||
    //
 | 
			
		||||
  , accounts: {
 | 
			
		||||
      // Accounts
 | 
			
		||||
      registerAsync: function (args) {
 | 
			
		||||
        var err;
 | 
			
		||||
        var copy = utils.merge(args, gl);
 | 
			
		||||
        var disagreeTos;
 | 
			
		||||
        args = utils.tplCopy(copy);
 | 
			
		||||
 | 
			
		||||
        disagreeTos = (!args.agreeTos && 'undefined' !== typeof args.agreeTos);
 | 
			
		||||
        if (!args.email || disagreeTos || (parseInt(args.rsaKeySize, 10) < 2048)) {
 | 
			
		||||
          err = new Error(
 | 
			
		||||
            "In order to register an account both 'email' and 'agreeTos' must be present"
 | 
			
		||||
              + " and 'rsaKeySize' must be 2048 or greater."
 | 
			
		||||
          );
 | 
			
		||||
          err.code = 'E_ARGS';
 | 
			
		||||
          return PromiseA.reject(err);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return utils.testEmail(args.email).then(function () {
 | 
			
		||||
          var promise = gl.store.accounts.checkKeypairAsync(args).then(function (keypair) {
 | 
			
		||||
            if (keypair) {
 | 
			
		||||
              return RSA.import(keypair);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (args.accountKeypair) {
 | 
			
		||||
              return gl.store.accounts.setKeypairAsync(args, RSA.import(args.accountKeypair));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var keypairOpts = { bitlen: args.rsaKeySize, exp: 65537, public: true, pem: true };
 | 
			
		||||
            return RSA.generateKeypairAsync(keypairOpts).then(function (keypair) {
 | 
			
		||||
              keypair.privateKeyPem = RSA.exportPrivatePem(keypair);
 | 
			
		||||
              keypair.publicKeyPem = RSA.exportPublicPem(keypair);
 | 
			
		||||
              keypair.privateKeyJwk = RSA.exportPrivateJwk(keypair);
 | 
			
		||||
              return gl.store.accounts.setKeypairAsync(args, keypair);
 | 
			
		||||
            });
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          return promise.then(function (keypair) {
 | 
			
		||||
            // Note: the ACME urls are always fetched fresh on purpose
 | 
			
		||||
            // TODO is this the right place for this?
 | 
			
		||||
            return core.getAcmeUrlsAsync(args).then(function (urls) {
 | 
			
		||||
              args._acmeUrls = urls;
 | 
			
		||||
 | 
			
		||||
              return gl.acme.registerNewAccountAsync({
 | 
			
		||||
                email: args.email
 | 
			
		||||
              , newRegUrl: args._acmeUrls.newReg
 | 
			
		||||
              , newAuthzUrl: args._acmeUrls.newAuthz
 | 
			
		||||
              , agreeToTerms: function (tosUrl, agreeCb) {
 | 
			
		||||
                  if (true === args.agreeTos || tosUrl === args.agreeTos || tosUrl === gl.agreeToTerms) {
 | 
			
		||||
                    agreeCb(null, tosUrl);
 | 
			
		||||
                    return;
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  // args.email = email;      // already there
 | 
			
		||||
                  // args.domains = domains   // already there
 | 
			
		||||
                  args.tosUrl = tosUrl;
 | 
			
		||||
                  gl.agreeToTerms(args, agreeCb);
 | 
			
		||||
                }
 | 
			
		||||
              , accountKeypair: keypair
 | 
			
		||||
 | 
			
		||||
              , debug: gl.debug || args.debug
 | 
			
		||||
              }).then(function (receipt) {
 | 
			
		||||
                var reg = {
 | 
			
		||||
                  keypair: keypair
 | 
			
		||||
                , receipt: receipt
 | 
			
		||||
                , email: args.email
 | 
			
		||||
                , newRegUrl: args._acmeUrls.newReg
 | 
			
		||||
                , newAuthzUrl: args._acmeUrls.newAuthz
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                // TODO move templating of arguments to right here?
 | 
			
		||||
                return gl.store.accounts.setAsync(args, reg).then(function (account) {
 | 
			
		||||
                  // should now have account.id and account.accountId
 | 
			
		||||
                  args.account = account;
 | 
			
		||||
                  args.accountId = account.id;
 | 
			
		||||
                  return account;
 | 
			
		||||
                });
 | 
			
		||||
              });
 | 
			
		||||
            });
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Accounts
 | 
			
		||||
    , getAsync: function (args) {
 | 
			
		||||
        return core.accounts.checkAsync(args).then(function (account) {
 | 
			
		||||
          if (account) {
 | 
			
		||||
            return account;
 | 
			
		||||
          } else {
 | 
			
		||||
            return core.accounts.registerAsync(args);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Accounts
 | 
			
		||||
    , checkAsync: function (args) {
 | 
			
		||||
        var requiredArgs = ['accountId', 'email', 'domains', 'domain'];
 | 
			
		||||
        if (!requiredArgs.some(function (key) { return -1 !== Object.keys(args).indexOf(key); })) {
 | 
			
		||||
          return PromiseA.reject(new Error(
 | 
			
		||||
            "In order to register or retrieve an account one of '" + requiredArgs.join("', '") + "' must be present"
 | 
			
		||||
          ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var copy = utils.merge(args, gl);
 | 
			
		||||
        args = utils.tplCopy(copy);
 | 
			
		||||
 | 
			
		||||
        return gl.store.accounts.checkAsync(args).then(function (account) {
 | 
			
		||||
 | 
			
		||||
          if (!account) {
 | 
			
		||||
            return null;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          args.account = account;
 | 
			
		||||
          args.accountId = account.id;
 | 
			
		||||
 | 
			
		||||
          return account;
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  , certificates: {
 | 
			
		||||
      // Certificates
 | 
			
		||||
      registerAsync: function (args) {
 | 
			
		||||
        var err;
 | 
			
		||||
        var challengeDefaults = gl['_challengeOpts_' + (args.challengeType || gl.challengeType)] || {};
 | 
			
		||||
        var copy = utils.merge(args, challengeDefaults || {});
 | 
			
		||||
        copy = utils.merge(copy, gl);
 | 
			
		||||
        args = utils.tplCopy(copy);
 | 
			
		||||
 | 
			
		||||
        if (!Array.isArray(args.domains)) {
 | 
			
		||||
          return PromiseA.reject(new Error('args.domains should be an array of domains'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!(args.domains.length && args.domains.every(utils.isValidDomain))) {
 | 
			
		||||
          // NOTE: this library can't assume to handle the http loopback
 | 
			
		||||
          // (or dns-01 validation may be used)
 | 
			
		||||
          // so we do not check dns records or attempt a loopback here
 | 
			
		||||
          err = new Error("invalid domain name(s): '" + args.domains + "'");
 | 
			
		||||
          err.code = "INVALID_DOMAIN";
 | 
			
		||||
          return PromiseA.reject(err);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If a previous request to (re)register a certificate is already underway we need
 | 
			
		||||
        // to return the same promise created before rather than registering things twice.
 | 
			
		||||
        // I'm not 100% sure how to properly handle the case where someone registers domain
 | 
			
		||||
        // lists with some but not all elements common, nor am I sure that's even a case that
 | 
			
		||||
        // is allowed to happen anyway. But for now we act like the list is completely the
 | 
			
		||||
        // same if any elements are the same.
 | 
			
		||||
        var promise;
 | 
			
		||||
        args.domains.some(function (name) {
 | 
			
		||||
          if (pendingRegistrations.hasOwnProperty(name)) {
 | 
			
		||||
            promise = pendingRegistrations[name];
 | 
			
		||||
            return true;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        if (promise) {
 | 
			
		||||
          return promise;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        promise = core.certificates._runRegistration(args);
 | 
			
		||||
 | 
			
		||||
        // Now that the registration is actually underway we need to make sure any subsequent
 | 
			
		||||
        // registration attempts return the same promise until it is completed (but not after
 | 
			
		||||
        // it is completed).
 | 
			
		||||
        args.domains.forEach(function (name) {
 | 
			
		||||
          pendingRegistrations[name] = promise;
 | 
			
		||||
        });
 | 
			
		||||
        function clearPending() {
 | 
			
		||||
          args.domains.forEach(function (name) {
 | 
			
		||||
            delete pendingRegistrations[name];
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
        promise.then(clearPending, clearPending);
 | 
			
		||||
 | 
			
		||||
        return promise;
 | 
			
		||||
      }
 | 
			
		||||
    , _runRegistration: function (args) {
 | 
			
		||||
        // TODO renewal cb
 | 
			
		||||
        // accountId and or email
 | 
			
		||||
        return core.accounts.getAsync(args).then(function (account) {
 | 
			
		||||
          args.account = account;
 | 
			
		||||
 | 
			
		||||
          var promise = gl.store.certificates.checkKeypairAsync(args).then(function (keypair) {
 | 
			
		||||
            if (keypair) {
 | 
			
		||||
              return RSA.import(keypair);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (args.domainKeypair) {
 | 
			
		||||
              return gl.store.certificates.setKeypairAsync(args, RSA.import(args.domainKeypair));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var keypairOpts = { bitlen: args.rsaKeySize, exp: 65537, public: true, pem: true };
 | 
			
		||||
            return RSA.generateKeypairAsync(keypairOpts).then(function (keypair) {
 | 
			
		||||
              keypair.privateKeyPem = RSA.exportPrivatePem(keypair);
 | 
			
		||||
              keypair.publicKeyPem = RSA.exportPublicPem(keypair);
 | 
			
		||||
              keypair.privateKeyJwk = RSA.exportPrivateJwk(keypair);
 | 
			
		||||
              return gl.store.certificates.setKeypairAsync(args, keypair);
 | 
			
		||||
            });
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          return promise.then(function (domainKeypair) {
 | 
			
		||||
            args.domainKeypair = domainKeypair;
 | 
			
		||||
            //args.registration = domainKey;
 | 
			
		||||
 | 
			
		||||
            // Note: the ACME urls are always fetched fresh on purpose
 | 
			
		||||
            // TODO is this the right place for this?
 | 
			
		||||
            return core.getAcmeUrlsAsync(args).then(function (urls) {
 | 
			
		||||
              args._acmeUrls = urls;
 | 
			
		||||
 | 
			
		||||
              var certReq = {
 | 
			
		||||
                debug: args.debug || gl.debug
 | 
			
		||||
 | 
			
		||||
              , newAuthzUrl: args._acmeUrls.newAuthz
 | 
			
		||||
              , newCertUrl: args._acmeUrls.newCert
 | 
			
		||||
 | 
			
		||||
              , accountKeypair: RSA.import(account.keypair)
 | 
			
		||||
              , domainKeypair: domainKeypair
 | 
			
		||||
              , domains: args.domains
 | 
			
		||||
              , challengeType: args.challengeType
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
              //
 | 
			
		||||
              // IMPORTANT
 | 
			
		||||
              //
 | 
			
		||||
              // setChallenge and removeChallenge are handed defaults
 | 
			
		||||
              // instead of args because getChallenge does not have
 | 
			
		||||
              // access to args
 | 
			
		||||
              // (args is per-request, defaults is per instance)
 | 
			
		||||
              //
 | 
			
		||||
              // Each of these fires individually for each domain,
 | 
			
		||||
              // even though the certificate on the whole may have many domains
 | 
			
		||||
              //
 | 
			
		||||
              certReq.setChallenge = function (domain, key, value, done) {
 | 
			
		||||
                log(args.debug, "setChallenge called for '" + domain + "'");
 | 
			
		||||
                var copy = utils.merge({ domains: [domain] }, args);
 | 
			
		||||
                copy = utils.merge(copy, gl);
 | 
			
		||||
                utils.tplCopy(copy);
 | 
			
		||||
 | 
			
		||||
                // TODO need to save challengeType
 | 
			
		||||
                gl.challenges[args.challengeType].set(copy, domain, key, value, done);
 | 
			
		||||
              };
 | 
			
		||||
              certReq.removeChallenge = function (domain, key, done) {
 | 
			
		||||
                log(args.debug, "removeChallenge called for '" + domain + "'");
 | 
			
		||||
                var copy = utils.merge({ domains: [domain] }, gl);
 | 
			
		||||
                utils.tplCopy(copy);
 | 
			
		||||
 | 
			
		||||
                gl.challenges[args.challengeType].remove(copy, domain, key, done);
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
              log(args.debug, 'calling greenlock.acme.getCertificateAsync', certReq.domains);
 | 
			
		||||
 | 
			
		||||
              return gl.acme.getCertificateAsync(certReq).then(utils.attachCertInfo);
 | 
			
		||||
            });
 | 
			
		||||
          }).then(function (results) {
 | 
			
		||||
            // { cert, chain, privkey /*TODO, subject, altnames, issuedAt, expiresAt */ }
 | 
			
		||||
 | 
			
		||||
            // args.certs.privkey = RSA.exportPrivatePem(options.domainKeypair);
 | 
			
		||||
            args.certs = results;
 | 
			
		||||
            // args.pems is deprecated
 | 
			
		||||
            args.pems = results;
 | 
			
		||||
            return gl.store.certificates.setAsync(args).then(function () {
 | 
			
		||||
              return results;
 | 
			
		||||
            });
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      // Certificates
 | 
			
		||||
    , renewAsync: function (args, certs) {
 | 
			
		||||
        var renewableAt = core.certificates._getRenewableAt(args, certs);
 | 
			
		||||
        var err;
 | 
			
		||||
        //var halfLife = (certs.expiresAt - certs.issuedAt) / 2;
 | 
			
		||||
        //var renewable = (Date.now() - certs.issuedAt) > halfLife;
 | 
			
		||||
 | 
			
		||||
        log(args.debug, "(Renew) Expires At", new Date(certs.expiresAt).toISOString());
 | 
			
		||||
        log(args.debug, "(Renew) Renewable At", new Date(renewableAt).toISOString());
 | 
			
		||||
 | 
			
		||||
        if (!args.duplicate && Date.now() < renewableAt) {
 | 
			
		||||
          err = new Error(
 | 
			
		||||
              "[ERROR] Certificate issued at '"
 | 
			
		||||
            + new Date(certs.issuedAt).toISOString() + "' and expires at '"
 | 
			
		||||
            + new Date(certs.expiresAt).toISOString() + "'. Ignoring renewal attempt until '"
 | 
			
		||||
            + new Date(renewableAt).toISOString() + "'. Set { duplicate: true } to force."
 | 
			
		||||
          );
 | 
			
		||||
          err.code = 'E_NOT_RENEWABLE';
 | 
			
		||||
          return PromiseA.reject(err);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Either the cert has entered its renewal period
 | 
			
		||||
        // or we're forcing a refresh via 'dupliate: true'
 | 
			
		||||
        log(args.debug, "Renewing!");
 | 
			
		||||
 | 
			
		||||
        if (!args.domains || !args.domains.length) {
 | 
			
		||||
          args.domains = args.servernames || [certs.subject].concat(certs.altnames);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return core.certificates.registerAsync(args);
 | 
			
		||||
      }
 | 
			
		||||
      // Certificates
 | 
			
		||||
    , _isRenewable: function (args, certs) {
 | 
			
		||||
        var renewableAt = core.certificates._getRenewableAt(args, certs);
 | 
			
		||||
 | 
			
		||||
        log(args.debug, "Check Expires At", new Date(certs.expiresAt).toISOString());
 | 
			
		||||
        log(args.debug, "Check Renewable At", new Date(renewableAt).toISOString());
 | 
			
		||||
 | 
			
		||||
        if (args.duplicate || Date.now() >= renewableAt) {
 | 
			
		||||
          log(args.debug, "certificates are renewable");
 | 
			
		||||
          return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    , _getRenewableAt: function (args, certs) {
 | 
			
		||||
        return certs.expiresAt - (args.renewWithin || gl.renewWithin);
 | 
			
		||||
      }
 | 
			
		||||
    , checkAsync: function (args) {
 | 
			
		||||
        var copy = utils.merge(args, gl);
 | 
			
		||||
        utils.tplCopy(copy);
 | 
			
		||||
 | 
			
		||||
        // returns pems
 | 
			
		||||
        return gl.store.certificates.checkAsync(copy).then(function (cert) {
 | 
			
		||||
          if (cert) {
 | 
			
		||||
            log(args.debug, 'checkAsync found existing certificates');
 | 
			
		||||
            return utils.attachCertInfo(cert);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          log(args.debug, 'checkAsync failed to find certificates');
 | 
			
		||||
          return null;
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      // Certificates
 | 
			
		||||
    , getAsync: function (args) {
 | 
			
		||||
        var copy = utils.merge(args, gl);
 | 
			
		||||
        args = utils.tplCopy(copy);
 | 
			
		||||
 | 
			
		||||
        return core.certificates.checkAsync(args).then(function (certs) {
 | 
			
		||||
          if (!certs) {
 | 
			
		||||
            // There is no cert available
 | 
			
		||||
            if (false !== args.securityUpdates && !args._communityMemberAdded) {
 | 
			
		||||
              try {
 | 
			
		||||
                // We will notify all greenlock users of mandatory and security updates
 | 
			
		||||
                // We'll keep track of versions and os so we can make sure things work well
 | 
			
		||||
                // { name, version, email, domains, action, communityMember, telemetry }
 | 
			
		||||
                require('./community').add({
 | 
			
		||||
                  name: args._communityPackage
 | 
			
		||||
                , version: args._communityPackageVersion
 | 
			
		||||
                , email: args.email
 | 
			
		||||
                , domains: args.domains || args.servernames
 | 
			
		||||
                , action: 'reg'
 | 
			
		||||
                , communityMember: args.communityMember
 | 
			
		||||
                , telemetry: args.telemetry
 | 
			
		||||
                });
 | 
			
		||||
              } catch(e) { /* ignore */ }
 | 
			
		||||
              args._communityMemberAdded = true;
 | 
			
		||||
            }
 | 
			
		||||
            return core.certificates.registerAsync(args);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (core.certificates._isRenewable(args, certs)) {
 | 
			
		||||
            // it's time to renew the available cert
 | 
			
		||||
            if (false !== args.securityUpdates && !args._communityMemberAdded) {
 | 
			
		||||
              try {
 | 
			
		||||
                // We will notify all greenlock users of mandatory and security updates
 | 
			
		||||
                // We'll keep track of versions and os so we can make sure things work well
 | 
			
		||||
                // { name, version, email, domains, action, communityMember, telemetry }
 | 
			
		||||
                require('./community').add({
 | 
			
		||||
                  name: args._communityPackage
 | 
			
		||||
                , version: args._communityPackageVersion
 | 
			
		||||
                , email: args.email
 | 
			
		||||
                , domains: args.domains || args.servernames
 | 
			
		||||
                , action: 'renew'
 | 
			
		||||
                , communityMember: args.communityMember
 | 
			
		||||
                , telemetry: args.telemetry
 | 
			
		||||
                });
 | 
			
		||||
              } catch(e) { /* ignore */ }
 | 
			
		||||
              args._communityMemberAdded = true;
 | 
			
		||||
            }
 | 
			
		||||
            certs.renewing = core.certificates.renewAsync(args, certs);
 | 
			
		||||
            if (args.waitForRenewal) {
 | 
			
		||||
              return certs.renewing;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // return existing unexpired (although potentially stale) certificates when available
 | 
			
		||||
          // there will be an additional .renewing property if the certs are being asynchronously renewed
 | 
			
		||||
          return certs;
 | 
			
		||||
        }).then(function (results) {
 | 
			
		||||
          // returns pems
 | 
			
		||||
          return results;
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return core;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										68
									
								
								express-server/node_modules/greenlock/lib/middleware.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								express-server/node_modules/greenlock/lib/middleware.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var utils = require('./utils');
 | 
			
		||||
 | 
			
		||||
function _log(debug) {
 | 
			
		||||
  if (debug) {
 | 
			
		||||
    var args = Array.prototype.slice.call(arguments);
 | 
			
		||||
    args.shift();
 | 
			
		||||
    args.unshift("[greenlock/lib/middleware.js]");
 | 
			
		||||
    console.log.apply(console, args);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.create = function (gl) {
 | 
			
		||||
  if (!gl.challenges['http-01'] || !gl.challenges['http-01'].get) {
 | 
			
		||||
    throw new Error("middleware requires challenge plugin with get method");
 | 
			
		||||
  }
 | 
			
		||||
  var log = gl.log || _log;
 | 
			
		||||
 | 
			
		||||
  log(gl.debug, "created middleware");
 | 
			
		||||
  return function (_app) {
 | 
			
		||||
    if (_app && 'function' !== typeof _app) {
 | 
			
		||||
      throw new Error("use greenlock.middleware() or greenlock.middleware(function (req, res) {})");
 | 
			
		||||
    }
 | 
			
		||||
    var prefix = gl.acmeChallengePrefix || '/.well-known/acme-challenge/';
 | 
			
		||||
 | 
			
		||||
    return function (req, res, next) {
 | 
			
		||||
      if (0 !== req.url.indexOf(prefix)) {
 | 
			
		||||
        log(gl.debug, "no match, skipping middleware");
 | 
			
		||||
        if ('function' === typeof _app) {
 | 
			
		||||
          _app(req, res, next);
 | 
			
		||||
        }
 | 
			
		||||
        else if ('function' === typeof next) {
 | 
			
		||||
          next();
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          res.statusCode = 500;
 | 
			
		||||
          res.end("[500] Developer Error: app.use('/', greenlock.middleware()) or greenlock.middleware(app)");
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      log(gl.debug, "this must be tinder, 'cuz it's a match!");
 | 
			
		||||
 | 
			
		||||
      var token = req.url.slice(prefix.length);
 | 
			
		||||
      var hostname = req.hostname || (req.headers.host || '').toLowerCase().replace(/:.*/, '');
 | 
			
		||||
 | 
			
		||||
      log(gl.debug, "hostname", hostname, "token", token);
 | 
			
		||||
 | 
			
		||||
      var copy = utils.merge({ domains: [ hostname ] }, gl);
 | 
			
		||||
      copy = utils.tplCopy(copy);
 | 
			
		||||
 | 
			
		||||
      // TODO tpl copy?
 | 
			
		||||
      // TODO need to restore challengeType
 | 
			
		||||
      gl.challenges['http-01'].get(copy, hostname, token, function (err, secret) {
 | 
			
		||||
        if (err || !token) {
 | 
			
		||||
          res.statusCode = 404;
 | 
			
		||||
          res.setHeader('Content-Type', 'application/json; charset=utf-8');
 | 
			
		||||
          res.end('{ "error": { "message": "Error: These aren\'t the tokens you\'re looking for. Move along." } }');
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        res.setHeader('Content-Type', 'text/plain; charset=utf-8');
 | 
			
		||||
        res.end(secret);
 | 
			
		||||
      });
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										127
									
								
								express-server/node_modules/greenlock/lib/utils.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								express-server/node_modules/greenlock/lib/utils.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,127 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var path = require('path');
 | 
			
		||||
var homeRe = new RegExp("^~(\\/|\\\\|\\" + path.sep + ")");
 | 
			
		||||
// very basic check. Allows *.example.com.
 | 
			
		||||
var re = /^(\*\.)?[a-zA-Z0-9\.\-]+$/;
 | 
			
		||||
var punycode = require('punycode');
 | 
			
		||||
var promisify = (require('util').promisify || require('bluebird').promisify);
 | 
			
		||||
var dnsResolveMxAsync = promisify(require('dns').resolveMx);
 | 
			
		||||
 | 
			
		||||
module.exports.attachCertInfo = function (results) {
 | 
			
		||||
  // XXX Note: Parsing the certificate info comes at a great cost (~500kb)
 | 
			
		||||
  var getCertInfo = require('certpem').info;
 | 
			
		||||
  var certInfo = getCertInfo(results.cert);
 | 
			
		||||
 | 
			
		||||
  // subject, altnames, issuedAt, expiresAt
 | 
			
		||||
  Object.keys(certInfo).forEach(function (key) {
 | 
			
		||||
    results[key] = certInfo[key];
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return results;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports.isValidDomain = function (domain) {
 | 
			
		||||
  if (re.test(domain)) {
 | 
			
		||||
    return domain;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  domain = punycode.toASCII(domain);
 | 
			
		||||
 | 
			
		||||
  if (re.test(domain)) {
 | 
			
		||||
    return domain;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return '';
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports.merge = function (/*defaults, args*/) {
 | 
			
		||||
  var allDefaults = Array.prototype.slice.apply(arguments);
 | 
			
		||||
  var args = allDefaults.shift();
 | 
			
		||||
  var copy = {};
 | 
			
		||||
 | 
			
		||||
  allDefaults.forEach(function (defaults) {
 | 
			
		||||
    Object.keys(defaults).forEach(function (key) {
 | 
			
		||||
      copy[key] = defaults[key];
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  Object.keys(args).forEach(function (key) {
 | 
			
		||||
    copy[key] = args[key];
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return copy;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports.tplCopy = function (copy) {
 | 
			
		||||
  var homedir = require('os').homedir();
 | 
			
		||||
  var tplKeys;
 | 
			
		||||
 | 
			
		||||
  copy.hostnameGet = function (copy) {
 | 
			
		||||
    return (copy.domains || [])[0] || copy.domain;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Object.keys(copy).forEach(function (key) {
 | 
			
		||||
    var newName;
 | 
			
		||||
    if (!/Get$/.test(key)) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    newName = key.replace(/Get$/, '');
 | 
			
		||||
    copy[newName] = copy[newName] || copy[key](copy);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  tplKeys = Object.keys(copy);
 | 
			
		||||
  tplKeys.sort(function (a, b) {
 | 
			
		||||
    return b.length - a.length;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  tplKeys.forEach(function (key) {
 | 
			
		||||
    if ('string' !== typeof copy[key]) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    copy[key] = copy[key].replace(homeRe, homedir + path.sep);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  tplKeys.forEach(function (key) {
 | 
			
		||||
    if ('string' !== typeof copy[key]) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tplKeys.forEach(function (tplname) {
 | 
			
		||||
      if (!copy[tplname]) {
 | 
			
		||||
        // what can't be templated now may be templatable later
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      copy[key] = copy[key].replace(':' + tplname, copy[tplname]);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return copy;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports.testEmail = function (email) {
 | 
			
		||||
  var parts = (email||'').split('@');
 | 
			
		||||
  var err;
 | 
			
		||||
 | 
			
		||||
  if (2 !== parts.length || !parts[0] || !parts[1]) {
 | 
			
		||||
    err = new Error("malformed email address '" + email + "'");
 | 
			
		||||
    err.code = 'E_EMAIL';
 | 
			
		||||
    return Promise.reject(err);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return dnsResolveMxAsync(parts[1]).then(function (records) {
 | 
			
		||||
    // records only returns when there is data
 | 
			
		||||
    if (!records.length) {
 | 
			
		||||
      throw new Error("sanity check fail: success, but no MX records returned");
 | 
			
		||||
    }
 | 
			
		||||
    return email;
 | 
			
		||||
  }, function (err) {
 | 
			
		||||
    if ('ENODATA' === err.code) {
 | 
			
		||||
      err = new Error("no MX records found for '" + parts[1] + "'");
 | 
			
		||||
      err.code = 'E_EMAIL';
 | 
			
		||||
      return Promise.reject(err);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user