mirror of
				https://git.coolaj86.com/coolaj86/telebit.js.git
				synced 2025-11-04 02:32:47 +00:00 
			
		
		
		
	handle pairing request via API
This commit is contained in:
		
							parent
							
								
									a763ead434
								
							
						
					
					
						commit
						99b891fd99
					
				@ -14,6 +14,7 @@ var recase = require('recase').create({});
 | 
			
		||||
var camelCopy = recase.camelCopy.bind(recase);
 | 
			
		||||
//var snakeCopy = recase.snakeCopy.bind(recase);
 | 
			
		||||
 | 
			
		||||
var urequest = require('@coolaj86/urequest');
 | 
			
		||||
var common = require('../lib/cli-common.js');
 | 
			
		||||
 | 
			
		||||
var argv = process.argv.slice(2);
 | 
			
		||||
@ -141,7 +142,7 @@ function askForConfig(answers, mainCb) {
 | 
			
		||||
        if (!relay) { relay = 'telebit.cloud'; }
 | 
			
		||||
        relay = relay.trim();
 | 
			
		||||
        var urlstr = common.parseUrl(relay) + common.apiDirectory;
 | 
			
		||||
        common.urequest({ url: urlstr, json: true }, function (err, resp, body) {
 | 
			
		||||
        urequest({ url: urlstr, json: true }, function (err, resp, body) {
 | 
			
		||||
          if (err) {
 | 
			
		||||
            console.error("[Network Error] Failed to retrieve '" + urlstr + "'");
 | 
			
		||||
            console.error(err);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										173
									
								
								bin/telebitd.js
									
									
									
									
									
								
							
							
						
						
									
										173
									
								
								bin/telebitd.js
									
									
									
									
									
								
							@ -512,75 +512,9 @@ function connectTunnel() {
 | 
			
		||||
  state.sortingHat = state.config.sortingHat;
 | 
			
		||||
 | 
			
		||||
  // TODO sortingHat.print(); ?
 | 
			
		||||
 | 
			
		||||
  if (state.config.email && !state.token) {
 | 
			
		||||
    console.info();
 | 
			
		||||
    console.info('====================================');
 | 
			
		||||
    console.info('=           HEY! LISTEN!           =');
 | 
			
		||||
    console.info('====================================');
 | 
			
		||||
    console.info('=                                  =');
 | 
			
		||||
    console.info('= 1. Open your email               =');
 | 
			
		||||
    console.info('=                                  =');
 | 
			
		||||
    console.info('= 2. Click the magic login link    =');
 | 
			
		||||
    console.info('=    Login Code (if needed): 0000  ='.replace('0000', state.otp));
 | 
			
		||||
    console.info('=                                  =');
 | 
			
		||||
    console.info('= 3. Check back here for deets     =');
 | 
			
		||||
    console.info('=                                  =');
 | 
			
		||||
    console.info('=                                  =');
 | 
			
		||||
    console.info('====================================');
 | 
			
		||||
    console.info();
 | 
			
		||||
  }
 | 
			
		||||
  // TODO Check undefined vs false for greenlock config
 | 
			
		||||
  var remote = require('../');
 | 
			
		||||
  state.handlers = {
 | 
			
		||||
    grant: function (grants) {
 | 
			
		||||
      console.info("");
 | 
			
		||||
      console.info("Connect to your device by any of the following means:");
 | 
			
		||||
      console.info("");
 | 
			
		||||
      grants.forEach(function (arr) {
 | 
			
		||||
        if ('https' === arr[0]) {
 | 
			
		||||
          if (!state.servernames[arr[1]]) {
 | 
			
		||||
            state.servernames[arr[1]] = {};
 | 
			
		||||
          }
 | 
			
		||||
        } else if ('tcp' === arr[0]) {
 | 
			
		||||
          if (!state.ports[arr[2]]) {
 | 
			
		||||
            state.ports[arr[2]] = {};
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ('ssh+https' === arr[0]) {
 | 
			
		||||
          console.info("SSH+HTTPS");
 | 
			
		||||
        } else if ('ssh' === arr[0]) {
 | 
			
		||||
          console.info("SSH");
 | 
			
		||||
        } else if ('tcp' === arr[0]) {
 | 
			
		||||
          console.info("TCP");
 | 
			
		||||
        } else if ('https' === arr[0]) {
 | 
			
		||||
          console.info("HTTPS");
 | 
			
		||||
        }
 | 
			
		||||
        console.info('\t' + arr[0] + '://' + arr[1] + (arr[2] ? (':' + arr[2]) : ''));
 | 
			
		||||
        if ('ssh+https' === arr[0]) {
 | 
			
		||||
          console.info("\tex: ssh -o ProxyCommand='openssl s_client -connect %h:%p -servername %h -quiet' " + arr[1] + " -p 443\n");
 | 
			
		||||
        } else if ('ssh' === arr[0]) {
 | 
			
		||||
          console.info("\tex: ssh " + arr[1] + " -p " + arr[2] + "\n");
 | 
			
		||||
        } else if ('tcp' === arr[0]) {
 | 
			
		||||
          console.info("\tex: netcat " + arr[1] + " " + arr[2] + "\n");
 | 
			
		||||
        } else if ('https' === arr[0]) {
 | 
			
		||||
          console.info("\tex: curl https://" + arr[1] + "\n");
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  , access_token: function (opts) {
 | 
			
		||||
      state.token = opts.jwt;
 | 
			
		||||
      state.config.token = opts.jwt;
 | 
			
		||||
      console.info("Updating '" + tokenpath + "' with new token:");
 | 
			
		||||
      try {
 | 
			
		||||
        require('fs').writeFileSync(tokenpath, opts.jwt);
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        console.error("Token not saved:");
 | 
			
		||||
        console.error(e);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  console.log();
 | 
			
		||||
  state.greenlockConfig = {
 | 
			
		||||
    version: state.greenlockConf.version || 'draft-11'
 | 
			
		||||
@ -696,31 +630,122 @@ function rawTunnel(cb) {
 | 
			
		||||
    , os_arch: os.arch()
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (state.config.email && !state.token) {
 | 
			
		||||
      console.info();
 | 
			
		||||
      console.info('====================================');
 | 
			
		||||
      console.info('=           HEY! LISTEN!           =');
 | 
			
		||||
      console.info('====================================');
 | 
			
		||||
      console.info('=                                  =');
 | 
			
		||||
      console.info('= 1. Open your email               =');
 | 
			
		||||
      console.info('=                                  =');
 | 
			
		||||
      console.info('= 2. Click the magic login link    =');
 | 
			
		||||
      console.info('=    Login Code (if needed): 0000  ='.replace('0000', state.otp));
 | 
			
		||||
      console.info('=                                  =');
 | 
			
		||||
      console.info('= 3. Check back here for deets     =');
 | 
			
		||||
      console.info('=                                  =');
 | 
			
		||||
      console.info('=                                  =');
 | 
			
		||||
      console.info('====================================');
 | 
			
		||||
      console.info();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (err || !body || !body.pair_request) {
 | 
			
		||||
      cb(null, connectTunnel());
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO do auth stuff
 | 
			
		||||
    var pairRequest = url.resolve('https://' + body.api_host.replace(/:hostname/g, state.relayHostname), body.pair_request.pathname);
 | 
			
		||||
    var pairRequestUrl = url.resolve('https://' + body.api_host.replace(/:hostname/g, state.relayHostname), body.pair_request.pathname);
 | 
			
		||||
    var req = {
 | 
			
		||||
      url: pairRequest
 | 
			
		||||
      url: pairRequestUrl
 | 
			
		||||
    , method: body.pair_request.method
 | 
			
		||||
    , json: state._auth
 | 
			
		||||
    };
 | 
			
		||||
    console.log('[telebitd.js] req');
 | 
			
		||||
    console.log(req);
 | 
			
		||||
    urequest(req, function (err, resp, body) {
 | 
			
		||||
        if (err) { console.error('[telebitd.js] pair request', err); }
 | 
			
		||||
 | 
			
		||||
    function gotoNext(req) {
 | 
			
		||||
      urequest(req, function (err, resp, body) {
 | 
			
		||||
        if (err) { console.error('[telebitd.js] pair request', err); return; }
 | 
			
		||||
 | 
			
		||||
        console.log('\nToken Request Body:');
 | 
			
		||||
        console.log(resp.headers);
 | 
			
		||||
        console.log(body);
 | 
			
		||||
        // TODO poll for token
 | 
			
		||||
        //cb(null, connectTunnel());
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
        console.info('Device Pair Code: 0000'.replace('0000', state.otp));
 | 
			
		||||
 | 
			
		||||
        // pending, try again
 | 
			
		||||
        if (resp.headers.location) {
 | 
			
		||||
          setTimeout(gotoNext, 2 * 1000, { url: resp.headers.location, json: true });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ('ready' !== body.status) {
 | 
			
		||||
          console.error("\n[error] neither ready nor pending...");
 | 
			
		||||
          console.error(body);
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        state.token = body.access_token;
 | 
			
		||||
        state.config.token = state.token;
 | 
			
		||||
        state.handlers.access_token({ jwt: state.token });
 | 
			
		||||
        cb(null, connectTunnel());
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gotoNext(req);
 | 
			
		||||
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
state.handlers = {
 | 
			
		||||
  grant: function (grants) {
 | 
			
		||||
    console.info("");
 | 
			
		||||
    console.info("Connect to your device by any of the following means:");
 | 
			
		||||
    console.info("");
 | 
			
		||||
    grants.forEach(function (arr) {
 | 
			
		||||
      if ('https' === arr[0]) {
 | 
			
		||||
        if (!state.servernames[arr[1]]) {
 | 
			
		||||
          state.servernames[arr[1]] = {};
 | 
			
		||||
        }
 | 
			
		||||
      } else if ('tcp' === arr[0]) {
 | 
			
		||||
        if (!state.ports[arr[2]]) {
 | 
			
		||||
          state.ports[arr[2]] = {};
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if ('ssh+https' === arr[0]) {
 | 
			
		||||
        console.info("SSH+HTTPS");
 | 
			
		||||
      } else if ('ssh' === arr[0]) {
 | 
			
		||||
        console.info("SSH");
 | 
			
		||||
      } else if ('tcp' === arr[0]) {
 | 
			
		||||
        console.info("TCP");
 | 
			
		||||
      } else if ('https' === arr[0]) {
 | 
			
		||||
        console.info("HTTPS");
 | 
			
		||||
      }
 | 
			
		||||
      console.info('\t' + arr[0] + '://' + arr[1] + (arr[2] ? (':' + arr[2]) : ''));
 | 
			
		||||
      if ('ssh+https' === arr[0]) {
 | 
			
		||||
        console.info("\tex: ssh -o ProxyCommand='openssl s_client -connect %h:%p -servername %h -quiet' " + arr[1] + " -p 443\n");
 | 
			
		||||
      } else if ('ssh' === arr[0]) {
 | 
			
		||||
        console.info("\tex: ssh " + arr[1] + " -p " + arr[2] + "\n");
 | 
			
		||||
      } else if ('tcp' === arr[0]) {
 | 
			
		||||
        console.info("\tex: netcat " + arr[1] + " " + arr[2] + "\n");
 | 
			
		||||
      } else if ('https' === arr[0]) {
 | 
			
		||||
        console.info("\tex: curl https://" + arr[1] + "\n");
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
, access_token: function (opts) {
 | 
			
		||||
    state.token = opts.jwt;
 | 
			
		||||
    state.config.token = opts.jwt;
 | 
			
		||||
    console.info("Updating '" + tokenpath + "' with new token:");
 | 
			
		||||
    try {
 | 
			
		||||
      require('fs').writeFileSync(tokenpath, opts.jwt);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      console.error("Token not saved:");
 | 
			
		||||
      console.error(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
require('fs').readFile(confpath, 'utf8', parseConfig);
 | 
			
		||||
 | 
			
		||||
}());
 | 
			
		||||
 | 
			
		||||
@ -52,7 +52,8 @@ common.parseHostname = function (hostname) {
 | 
			
		||||
common.apiDirectory = '_apis/telebit.cloud/index.json';
 | 
			
		||||
 | 
			
		||||
function leftpad(i, n, c) {
 | 
			
		||||
  while (i.toString().length < (n || 4)) {
 | 
			
		||||
  i = i.toString();
 | 
			
		||||
  while (i.length < (n || 4)) {
 | 
			
		||||
    i = (c || '0') + i;
 | 
			
		||||
  }
 | 
			
		||||
  return i;
 | 
			
		||||
@ -61,57 +62,6 @@ common.otp = function getOtp() {
 | 
			
		||||
  return leftpad(Math.round(Math.random() * 9999), 4, '0');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
common.urequest = function (opts, cb) {
 | 
			
		||||
  var https = require('https');
 | 
			
		||||
  // request.js behavior:
 | 
			
		||||
  // encoding: null + json ? unknown
 | 
			
		||||
  // json => attempt to parse, fail silently
 | 
			
		||||
  // encoding => buffer.toString(encoding)
 | 
			
		||||
  // null === encoding => Buffer.concat(buffers)
 | 
			
		||||
  https.get(opts.url, function (resp) {
 | 
			
		||||
    var encoding = opts.encoding;
 | 
			
		||||
    if (null === encoding) {
 | 
			
		||||
      resp._body = [];
 | 
			
		||||
    } else {
 | 
			
		||||
      resp.body = '';
 | 
			
		||||
    }
 | 
			
		||||
    if (!resp.headers['content-length'] || 0 === parseInt(resp.headers['content-length'], 10)) {
 | 
			
		||||
      cb(resp);
 | 
			
		||||
    }
 | 
			
		||||
    resp._bodyLength = 0;
 | 
			
		||||
    resp.on('data', function (chunk) {
 | 
			
		||||
      if ('string' === typeof resp.body) {
 | 
			
		||||
        resp.body += chunk.toString(encoding);
 | 
			
		||||
      } else {
 | 
			
		||||
        resp._body.push(chunk);
 | 
			
		||||
        resp._bodyLength += chunk.length;
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    resp.on('end', function () {
 | 
			
		||||
      if ('string' !== typeof resp.body) {
 | 
			
		||||
        if (1 === resp._body.length) {
 | 
			
		||||
          resp.body = resp._body[0];
 | 
			
		||||
        } else {
 | 
			
		||||
          resp.body = Buffer.concat(resp._body, resp._bodyLength);
 | 
			
		||||
        }
 | 
			
		||||
        resp._body = null;
 | 
			
		||||
      }
 | 
			
		||||
      if (opts.json && 'string' === typeof resp.body) {
 | 
			
		||||
        // TODO I would parse based on Content-Type
 | 
			
		||||
        // but request.js doesn't do that.
 | 
			
		||||
        try {
 | 
			
		||||
          resp.body = JSON.parse(resp.body);
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
          // ignore
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      cb(null, resp, resp.body);
 | 
			
		||||
    });
 | 
			
		||||
  }).on('error', function (e) {
 | 
			
		||||
    cb(e);
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
try {
 | 
			
		||||
  mkdirp.sync(path.join(__dirname, '..', 'var', 'log'));
 | 
			
		||||
  mkdirp.sync(path.join(__dirname, '..', 'var', 'run'));
 | 
			
		||||
 | 
			
		||||
@ -4,8 +4,8 @@
 | 
			
		||||
  "description": "Break out of localhost. Connect to any device from anywhere over any tcp port or securely in a browser. A secure tunnel. A poor man's reverse VPN.",
 | 
			
		||||
  "main": "lib/remote.js",
 | 
			
		||||
  "bin": {
 | 
			
		||||
    "telebit": "bin/telebit.js"
 | 
			
		||||
  , "telebitd": "bin/telebitd.js"
 | 
			
		||||
    "telebit": "bin/telebit.js",
 | 
			
		||||
    "telebitd": "bin/telebitd.js"
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "test": "echo \"Error: no test specified\" && exit 1"
 | 
			
		||||
@ -48,6 +48,7 @@
 | 
			
		||||
  },
 | 
			
		||||
  "homepage": "https://git.coolaj86.com/coolaj86/telebit.js#readme",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@coolaj86/urequest": "^1.1.1",
 | 
			
		||||
    "bluebird": "^3.5.1",
 | 
			
		||||
    "commander": "^2.9.0",
 | 
			
		||||
    "finalhandler": "^1.1.1",
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,9 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var email = 'jon@example.com';
 | 
			
		||||
var pin = Math.round(Math.random() * 999999).toString().padStart(6, '0'); // '321654'
 | 
			
		||||
 | 
			
		||||
console.log('Pair Code:', pin);
 | 
			
		||||
 | 
			
		||||
var urequest = require('@coolaj86/urequest');
 | 
			
		||||
var req =  {
 | 
			
		||||
@ -11,8 +14,8 @@ var req =  {
 | 
			
		||||
	  subject: email
 | 
			
		||||
	, subject_scheme: 'mailto'
 | 
			
		||||
	, scope: ''
 | 
			
		||||
	, otp: '321654'
 | 
			
		||||
	, hostname: "Jon's Macbook Pro"
 | 
			
		||||
	, otp: pin
 | 
			
		||||
	, hostname: "User's Macbook Pro"
 | 
			
		||||
	, os_type: 'Linux'
 | 
			
		||||
	, os_platform: 'linux'
 | 
			
		||||
  , os_release: '4.4.0-116-generic'
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user