anyproxy/lib/certMgr.js

151 lines
5.4 KiB
JavaScript
Raw Normal View History

2014-08-11 16:43:14 +08:00
var exec = require('child_process').exec,
2014-08-13 11:51:39 +08:00
spawn = require('child_process').spawn,
2014-08-11 16:43:14 +08:00
path = require("path"),
fs = require("fs"),
os = require("os"),
2014-08-13 11:51:39 +08:00
color = require('colorful'),
2014-08-14 10:59:49 +08:00
readline = require('readline'),
2014-09-06 09:50:49 +08:00
util = require('./util'),
logUtil = require("./log"),
2014-08-13 17:30:16 +08:00
asyncTask = require("async-task-mgr");
2014-08-11 16:43:14 +08:00
2014-12-08 17:13:41 +08:00
//TODO : unstable in windows
2014-09-06 09:50:49 +08:00
var certDir = path.join(util.getUserHome(),"/.anyproxy_certs/"),
cmdDir = path.join(__dirname,"..","./cert/"),
cmd_genRoot = path.join(cmdDir,"./gen-rootCA"),
cmd_genCert = path.join(cmdDir,"./gen-cer"),
createCertTaskMgr = new asyncTask();
2014-08-11 16:43:14 +08:00
2014-09-12 10:28:39 +08:00
if(!fs.existsSync(certDir)){
2014-11-13 10:05:56 +08:00
try{
fs.mkdirSync(certDir,0777); //may fail in windows
}catch(e){
logUtil.printLog("===========", logUtil.T_ERR);
logUtil.printLog("failed to create cert dir ,please create one by yourself - " + certDir, logUtil.T_ERR);
logUtil.printLog("this error will not block main thread unless you use https-related features in anyproxy", logUtil.T_ERR);
logUtil.printLog("===========", logUtil.T_ERR);
2014-11-13 10:05:56 +08:00
}
2014-08-11 16:43:14 +08:00
}
function getCertificate(hostname,certCallback){
2014-08-11 16:43:14 +08:00
var keyFile = path.join(certDir , "__hostname.key".replace(/__hostname/,hostname) ),
crtFile = path.join(certDir , "__hostname.crt".replace(/__hostname/,hostname) );
createCertTaskMgr.addTask(hostname,function(callback){
if(!fs.existsSync(keyFile) || !fs.existsSync(crtFile)){
2014-08-13 17:30:16 +08:00
createCert(hostname,function(err){
if(err){
callback(err);
}else{
callback(null , fs.readFileSync(keyFile) , fs.readFileSync(crtFile));
}
2014-08-13 17:30:16 +08:00
});
}else{
callback(null , fs.readFileSync(keyFile) , fs.readFileSync(crtFile));
}
},function(err,keyContent,crtContent){
if(!err){
certCallback(null ,keyContent,crtContent);
}else{
certCallback(err);
}
});
2014-08-11 16:43:14 +08:00
}
function createCert(hostname,callback){
2014-08-13 11:51:39 +08:00
checkRootCA();
2014-08-11 16:43:14 +08:00
2014-09-12 10:28:39 +08:00
var cmd = cmd_genCert + " __host __path".replace(/__host/,hostname).replace(/__path/,certDir);
exec(cmd,{ cwd : certDir },function(err,stdout,stderr){
2014-08-11 16:43:14 +08:00
if(err){
callback && callback(new Error("error when generating certificate"),null);
}else{
2014-08-13 11:51:39 +08:00
var tipText = "certificate created for __HOST".replace(/__HOST/,hostname);
logUtil.printLog(color.yellow(color.bold("[internal https]")) + color.yellow(tipText)) ;
2014-08-11 16:43:14 +08:00
callback(null);
}
});
}
function clearCerts(cb){
exec("rm *.key *.csr *.crt",{cwd : certDir},cb);
}
2014-08-14 10:59:49 +08:00
function isRootCAFileExists(){
2014-09-12 10:28:39 +08:00
var crtFile = path.join(certDir,"rootCA.crt"),
keyFile = path.join(certDir,"rootCA.key");
2014-08-14 10:59:49 +08:00
return (fs.existsSync(crtFile) && fs.existsSync(keyFile));
}
2014-08-13 11:51:39 +08:00
2014-08-14 10:59:49 +08:00
function checkRootCA(){
if(!isRootCAFileExists() || true){
logUtil.printLog(color.red("can not find rootCA.crt or rootCA.key"), logUtil.T_ERR);
logUtil.printLog(color.red("you may generate one by the following methods"), logUtil.T_ERR);
logUtil.printLog(color.red("\twhen using globally : anyproxy --root"), logUtil.T_ERR);
logUtil.printLog(color.red("\twhen using as a module : require(\"anyproxy\").generateRootCA();"), logUtil.T_ERR);
logUtil.printLog(color.red("\tmore info : https://github.com/alibaba/anyproxy/wiki/How-to-config-https-proxy"), logUtil.T_ERR);
2014-08-14 10:59:49 +08:00
process.exit(0);
2014-08-13 11:51:39 +08:00
}
}
function generateRootCA(){
2014-08-14 10:59:49 +08:00
if(isRootCAFileExists()){
logUtil.printLog(color.yellow("rootCA exists at " + certDir));
2014-08-14 10:59:49 +08:00
var rl = readline.createInterface({
2014-09-12 10:28:39 +08:00
input : process.stdin,
2014-08-14 10:59:49 +08:00
output: process.stdout
});
rl.question("do you really want to generate a new one ?)(yes/NO)", function(answer) {
if(/yes/i.test(answer)){
startGenerating();
}else{
logUtil.printLog("will not generate a new one");
2014-08-13 11:51:39 +08:00
process.exit(0);
2014-08-14 10:59:49 +08:00
}
rl.close();
});
}else{
startGenerating();
}
function startGenerating(){
2014-09-12 10:28:39 +08:00
//clear old certs
clearCerts(function(){
logUtil.printLog(color.green("temp certs cleared"));
2014-09-12 10:28:39 +08:00
var spawnSteam = spawn(cmd_genRoot,['.'],{cwd:certDir,stdio: 'inherit'});
spawnSteam.on('close', function (code) {
if(code == 0){
logUtil.printLog(color.green("rootCA generated"));
logUtil.printLog(color.green(color.bold("please trust the rootCA.crt in " + certDir)));
logUtil.printLog(color.green(color.bold("or you may get it via anyproxy webinterface")));
2014-09-12 10:28:39 +08:00
}else{
logUtil.printLog(color.red("fail to generate root CA"),logUtil.T_ERR);
2014-09-12 10:28:39 +08:00
}
process.exit(0);
2014-09-12 10:28:39 +08:00
});
2014-08-14 10:59:49 +08:00
});
}
2014-08-13 11:51:39 +08:00
}
function getRootCAFilePath(){
if(isRootCAFileExists()){
return path.join(certDir,"rootCA.crt");
}else{
return "";
}
}
module.exports.getRootCAFilePath = getRootCAFilePath;
2014-08-14 10:59:49 +08:00
module.exports.generateRootCA = generateRootCA;
module.exports.getCertificate = getCertificate;
module.exports.createCert = createCert;
module.exports.clearCerts = clearCerts;
module.exports.isRootCAFileExists = isRootCAFileExists;