00001 #!node
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 var cluster = require('cluster');
00014 var numCPUs = require("os").cpus().length;
00015 var fs = require('fs');
00016 var path_module = require('path');
00017 var child_process = require('child_process');
00018
00019 var util = require('util');
00020 var log_file = fs.createWriteStream('/tmp/xdaqproxy.' + process.env["USER"] + '.log', { flags: 'a' });
00021 var log_stdout = process.stdout;
00022
00023 var getversion = function () {
00024 console.log("Getting Server Version");
00025 if (fs.existsSync("./version.txt")) {
00026 console.log("Reading Server Version from File");
00027 return "" + fs.readFileSync("./version.txt");
00028 }
00029 else {
00030 child_process.exec("git describe --tags", function (error, stdout, stderr) {
00031 version = stdout.trim() + "-Git";
00032 child_process.exec("git status --porcelain", function (error, stdout) {
00033 if (stdout.length > 0) {
00034 version += "*";
00035 }
00036 });
00037 });
00038 }
00039 }
00040 var version = getversion();
00041
00042 var config = {
00043 listenhost: "localhost",
00044 listenport: 8080,
00045 xdaqhost: "localhost",
00046 xdaqport: 2015
00047 };
00048 function loadConfig() {
00049 if (fs.existsSync("xdaq_config.json")) {
00050 config = JSON.parse(fs.readFileSync("xdaq_config.json"));
00051 } else {
00052 fs.writeFileSync("xdaq_config.json", JSON.stringify(config));
00053 }
00054
00055 if (config.hostname === "localhost" && cluster.isMaster) {
00056 console.log("Listening only on localhost. To listen on a different address, set \"hostname\" in config.json.\nUse \"0.0.0.0\" to listen on all interfaces.");
00057 }
00058 }
00059
00060 loadConfig();
00061
00062 console.log = function (d) {
00063 log_file.write(util.format(d) + '\n');
00064 log_stdout.write(util.format(d) + '\n');
00065 };
00066
00067 function LoadCerts(path) {
00068 var output = [];
00069 var files = fs.readdirSync(path);
00070 for (var i = 0; i < files.length; i++) {
00071 if (files[i].search(".pem") > 0 || files[i].search(".crt") > 0) {
00072 output.push(fs.readFileSync(path + "/" + files[i]));
00073 }
00074 }
00075 return output;
00076 }
00077
00078 function GetCILogonCRL(path) {
00079
00080 var file = fs.createWriteStream(path_module.join(path, "cilogon-basic.r0"));
00081 http.get("http://crl-cilogon.ncsa-security.net/cilogon-basic.r0", function (res) { res.pipe(file); });
00082 var file2 = fs.createWriteStream(path_module.join(path, "cilogon-basic.crl"));
00083 http.get("http://crl-cilogon.ncsa-security.net/cilogon-basic.crl", function (res) { res.pipe(file2); });
00084 }
00085
00086 function LoadCRLs(path) {
00087 GetCILogonCRL(path);
00088 var output = [];
00089 var files = fs.readdirSync(path);
00090 for (var i = 0; i < files.length; i++) {
00091 if (files[i].search(".r0") > 0 || files[i].search(".crl") > 0) {
00092 output.push(fs.readFileSync(path + "/" + files[i]));
00093 }
00094 }
00095 return output;
00096 }
00097
00098
00099
00100 if (cluster.isMaster) {
00101
00102
00103 for (var i = 0; i < numCPUs; i++) {
00104
00105 var worker = cluster.fork();
00106 }
00107
00108
00109 cluster.on("exit", function () {
00110 var newWorker = cluster.fork();
00111 });
00112 } else {
00113
00114 var https = require('https');
00115 var http = require('http');
00116 var url = require('url');
00117
00118 console.log("Setting up options");
00119 var options = {
00120 key: fs.readFileSync('./certs/server.key'),
00121 cert: fs.readFileSync('./certs/server.crt'),
00122 ca: LoadCerts("./certs/certificates"),
00123 crl: LoadCRLs("./certs/certificates"),
00124 requestCert: true,
00125 rejectUnauthorized: false
00126 };
00127 var authlist = " " + fs.readFileSync("./certs/authorized_users");
00128 console.log("Done setting up options");
00129
00130
00131 var server = https.createServer(options, function (req, res) {
00132 var clientCertificate = req.connection.getPeerCertificate();
00133 var useremail = "";
00134 if (req.client.authorized) {
00135
00136
00137
00138
00139
00140 var username = clientCertificate.subject.CN[0];
00141 useremail = clientCertificate.subjectaltname.substr(6);
00142 if (authlist.search(username) > 0 || authlist.search(useremail) > 0) {
00143 console.log("User: " + username + " (" + useremail + ")");
00144 }
00145 }
00146
00147 if (req.url.search(/lid=\d+$/) > 0) {
00148 req.url = req.url + "/";
00149 }
00150
00151 var thisurl = url.parse(req.url, true);
00152 console.log("Request path: " + thisurl.pathname);
00153 if (useremail.length > 0 && thisurl.pathname !== "/") {
00154 thisurl.query.httpsUser = useremail;
00155 }
00156 var pathname = url.format(thisurl);
00157 console.log("Adjusted path: " + pathname);
00158
00159 var reqOptions = {
00160 host: config.xdaqhost,
00161 port: config.xdaqport,
00162 method: req.method,
00163 headers: req.headers,
00164 path: pathname
00165 }
00166 console.log("Request options: " + JSON.stringify(reqOptions));
00167 var xreq = http.request(reqOptions, function (xres) {
00168 if (xres.statusCode >= 300 && xres.statusCode < 400 && xres.headers.location) {
00169 console.log("Redirect detected. Going to " + xres.headers.location);
00170 var redirUri = url.parse(xres.headers.location + "/");
00171 redirUri.hostname = config.listenhost;
00172 redirUri.port = config.listenport;
00173 redirUri.host = config.listenhost + ":" + config.listenport;
00174 redirUri.protocol = "https:";
00175 var redirUrl = url.format(redirUri);
00176 console.log("Redirect url adjusted to " + redirUrl);
00177 res.writeHead(xres.statusCode, { 'location': redirUrl });
00178 res.end();
00179 } else {
00180
00181 xres.pipe(res);
00182 }
00183 });
00184
00185 req.pipe(xreq);
00186
00187 });
00188
00189 console.log("Listening on https://" + config.listenhost + ":" + config.listenport);
00190 server.listen(config.listenport, config.listenhost);
00191 }