http: have json rpc use server api key.

This commit is contained in:
Christopher Jeffrey 2016-07-30 20:39:13 -07:00
parent 18ddcc49c5
commit bf63691fd2
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
6 changed files with 52 additions and 47 deletions

View File

@ -54,5 +54,4 @@ listen: true
# http-host: 0.0.0.0
# api-key: 74b4147957813b62cc8987f2b711ddb31f8cb46dcbf71502033da66053c8780a
# wallet-auth: true
# rpc-user: admin
# rpc-password: bcoin
# no-auth: false

View File

@ -167,8 +167,7 @@ config.parseData = function parseData(data) {
options.httpHost = str(data.httphost);
options.apiKey = str(data.apikey);
options.walletAuth = bool(data.walletauth);
options.rpcUser = str(data.rpcuser);
options.rpcPassword = str(data.rpcpassword);
options.noAuth = bool(data.noauth);
return options;
};

View File

@ -145,8 +145,7 @@ function Fullnode(options) {
host: this.options.httpHost || '0.0.0.0',
apiKey: this.options.apiKey,
walletAuth: this.options.walletAuth,
rpcUser: this.options.rpcUser,
rpcPassword: this.options.rpcPassword
noAuth: this.options.noAuth
});
}

View File

@ -326,7 +326,7 @@ RPC.prototype.disconnectnode = function disconnectnode(args, callback) {
var node, peer;
if (args.help || args.length !== 1)
return callback(new Error('disconnectnode "node" '));
return callback(new Error('disconnectnode "node"'));
node = String(args[0]);
node = IP.normalize(node);
@ -475,6 +475,7 @@ RPC.prototype.clearbanned = function clearbanned(args, callback) {
if (args.help || args.length !== 0)
return callback(new Error('clearbanned'));
this.pool.peers.ignored = {};
this.pool.peers.misbehaving = {};
callback(null, null);
@ -488,13 +489,13 @@ RPC.prototype._deployment = function _deployment(id, version, status) {
status: status,
found: status ? this.network.block.majorityWindow : 0,
required: this.network.block.majorityEnforceUpgrade,
window: this.network.block.majorityWindow,
window: this.network.block.majorityWindow
},
reject: {
status: status,
found: status ? this.network.block.majorityWindow : 0,
required: this.network.block.majorityRejectOutdated,
winodw: this.network.block.majorityWindow,
window: this.network.block.majorityWindow
}
};
};

View File

@ -49,16 +49,8 @@ function HTTPServer(options) {
this.logger = options.logger || this.node.logger;
this.loaded = false;
this.apiKey = options.apiKey;
this.rpcUser = options.rpcUser;
this.rpcPassword = options.rpcPassword;
this.rpc = null;
if (!this.rpcUser)
this.rpcUser = 'admin';
if (!this.rpcPassword)
this.rpcPassword = bcoin.ec.random(20).toString('hex');
if (this.apiKey) {
if (typeof this.apiKey === 'string') {
assert(utils.isHex(this.apiKey), 'API key must be a hex string.');
@ -66,8 +58,13 @@ function HTTPServer(options) {
}
assert(Buffer.isBuffer(this.apiKey));
assert(this.apiKey.length === 32, 'API key must be 32 bytes.');
} else {
this.apiKey = bcoin.ec.random(32);
}
if (options.noAuth)
this.apiKey = null;
options.sockets = true;
this.server = new HTTPBase(options);
@ -140,6 +137,11 @@ HTTPServer.prototype._init = function _init() {
if (req.method === 'POST'
&& req.pathname === '/') {
if (self.apiKey) {
assert(utils.isHex(req.password), 'API key must be a hex string.');
assert(req.password.length === 64, 'API key must be 32 bytes.');
req.password = new Buffer(req.password, 'hex');
}
return next();
}
@ -299,38 +301,40 @@ HTTPServer.prototype._init = function _init() {
// JSON RPC
this.post('/', function(req, res, next, send) {
if (req.body.method && req.body.params) {
if (self.rpcUser) {
if (!textCmp(req.username, self.rpcUser)
|| !textCmp(req.password, self.rpcPassword)) {
res.setHeader('WWW-Authenticate', 'Basic realm="rpc"');
send(401, { error: 'Bad auth.' });
return;
}
}
if (!(req.body.method && req.body.params))
return next(new Error('Method not found.'));
if (!self.rpc) {
RPC = require('./rpc');
self.rpc = new RPC(self.node);
}
return self.rpc.execute(req.body, function(err, json) {
if (err) {
return send(400, {
result: null,
error: err.message,
id: req.body.id
});
}
send(200, {
result: json,
error: null,
if (self.apiKey) {
if (!utils.ccmp(req.password, self.apiKey)) {
res.setHeader('WWW-Authenticate', 'Basic realm="rpc"');
send(401, {
result: null,
error: 'Bad auth.',
id: req.body.id
});
});
return;
}
}
next(new Error('Method not found.'));
if (!self.rpc) {
RPC = require('./rpc');
self.rpc = new RPC(self.node);
}
self.rpc.execute(req.body, function(err, json) {
if (err) {
return send(400, {
result: null,
error: err.message,
id: req.body.id
});
}
send(200, {
result: json,
error: null,
id: req.body.id
});
});
});
this.get('/', function(req, res, next, send) {
@ -1017,7 +1021,11 @@ HTTPServer.prototype._initIO = function _initIO() {
*/
HTTPServer.prototype.open = function open(callback) {
this.logger.info('RPC credentials: %s:%s', this.rpcUser, this.rpcPassword);
if (this.apiKey)
this.logger.info('API key: %s', this.apiKey.toString('hex'));
else
this.logger.warning('WARNING: Your http server is open to the world.');
this.server.open(callback);
};

View File

@ -84,8 +84,7 @@ function SPVNode(options) {
host: this.options.httpHost || '0.0.0.0',
apiKey: this.options.apiKey,
walletAuth: this.options.walletAuth,
rpcUser: this.options.rpcUser,
rpcPassword: this.options.rpcPassword
noAuth: this.options.noAuth
});
}