parent
36417a5657
commit
1ac9e7d201
23
Makefile
23
Makefile
@ -2,19 +2,40 @@ MOCHA=./node_modules/.bin/mocha
|
||||
BOX=test/testnet-box
|
||||
|
||||
test:
|
||||
$(MAKE) test-ssl-no
|
||||
sleep 15
|
||||
$(MAKE) clean
|
||||
$(MAKE) test-ssl
|
||||
|
||||
test-ssl-no:
|
||||
$(MAKE) start
|
||||
sleep 15
|
||||
$(MAKE) run-test
|
||||
$(MAKE) stop
|
||||
|
||||
test-ssl:
|
||||
$(MAKE) start-ssl
|
||||
sleep 15
|
||||
$(MAKE) run-test-ssl
|
||||
$(MAKE) stop-ssl
|
||||
|
||||
start:
|
||||
$(MAKE) -C $(BOX) start
|
||||
|
||||
start-ssl:
|
||||
$(MAKE) -C $(BOX) start B1_FLAGS=-rpcssl=1 B2_FLAGS=-rpcssl=1
|
||||
|
||||
stop:
|
||||
$(MAKE) -C $(BOX) stop
|
||||
|
||||
stop-ssl:
|
||||
$(MAKE) -C $(BOX) stop B1_FLAGS=-rpcssl=1 B2_FLAGS=-rpcssl=1
|
||||
|
||||
run-test:
|
||||
$(MOCHA)
|
||||
$(MOCHA) --invert --grep SSL
|
||||
|
||||
run-test-ssl:
|
||||
$(MOCHA) --grep SSL
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(BOX) clean
|
||||
|
||||
30
Readme.md
30
Readme.md
@ -16,12 +16,6 @@ object, or you may call the API directly using the `cmd` method.
|
||||
|
||||
### Create client
|
||||
```js
|
||||
var bitcoin = require('bitcoin');
|
||||
var client = new bitcoin.Client('localhost', 8332, 'username', 'password');
|
||||
```
|
||||
|
||||
### Create client with single object
|
||||
```js
|
||||
var client = new bitcoin.Client({
|
||||
host: 'localhost',
|
||||
port: 8332,
|
||||
@ -62,3 +56,27 @@ client.cmd(batch, function(err, address) {
|
||||
console.log('Address:', address);
|
||||
});
|
||||
```
|
||||
|
||||
## SSL
|
||||
See [Enabling SSL on original client](https://en.bitcoin.it/wiki/Enabling_SSL_on_original_client_daemon).
|
||||
|
||||
If you're using this to connect to bitcoind across a network it is highly
|
||||
recommended to use SSL, otherwise an attacker may interecept your RPC credentials
|
||||
resulting in theft of your Bitcoins.
|
||||
|
||||
When enabling `ssl` by setting the configuration option to `true`, the `sslStrict`
|
||||
option will also be enabled by default. It is highly recommended to specify the
|
||||
CA as well to ensure you are not connecting to an attacker's bitcoind attempting
|
||||
to impersonate your own bitcoind.
|
||||
|
||||
```js
|
||||
var client = new bitcoin.Client({
|
||||
host: 'localhost',
|
||||
port: 8332,
|
||||
user: 'username',
|
||||
pass: 'password',
|
||||
ssl: true
|
||||
sslStrict: true,
|
||||
sslCa: fs.readFileSync(__dirname + '/myca.cert')
|
||||
});
|
||||
```
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
var rpc = require('../jsonrpc');
|
||||
var rpc = require('../jsonrpc'),
|
||||
deprecate = require('deprecate');
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// jsonrpc wrappers
|
||||
@ -69,16 +70,32 @@ var bitcoinAPI = {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Client
|
||||
// Either pass in 4 arguments, or a single object with host, port, user, pass
|
||||
// Pass in an object with host, port, user, pass
|
||||
//===----------------------------------------------------------------------===//
|
||||
function Client() {
|
||||
var args = [].slice.call(arguments);
|
||||
this.host = args[0].host || args[0];
|
||||
this.port = args[0].port || args[1];
|
||||
this.user = args[0].user || args[2];
|
||||
this.pass = args[0].pass || args[3];
|
||||
|
||||
if (args.length > 1) {
|
||||
deprecate('calling bitcoin.Client with more than one argument is deprecated');
|
||||
this.host = args[0];
|
||||
this.port = args[1];
|
||||
this.user = args[2];
|
||||
this.pass = args[3];
|
||||
this.ssl = false;
|
||||
this.sslStrict = false;
|
||||
this.sslCa = null;
|
||||
} else {
|
||||
this.host = args[0].host;
|
||||
this.port = args[0].port;
|
||||
this.user = args[0].user;
|
||||
this.pass = args[0].pass;
|
||||
this.ssl = args[0].ssl ? true : false;
|
||||
this.sslStrict = (typeof args[0].sslStrict === 'undefined' || args[0].sslStrict);
|
||||
this.sslCa = args[0].sslCa;
|
||||
}
|
||||
|
||||
this.rpc = new rpc.Client(this.port, this.host, this.user, this.pass);
|
||||
this.rpc = new rpc.Client(this.port, this.host, this.user, this.pass,
|
||||
this.ssl, this.sslStrict, this.sslCa);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,10 +1,16 @@
|
||||
var http = require('http');
|
||||
var http = require('http'),
|
||||
https = require('https');
|
||||
|
||||
var Client = function(port, host, user, password) {
|
||||
var Client = function(port, host, user, password, ssl, sslStrict, sslCa) {
|
||||
this.port = port;
|
||||
this.host = host;
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
|
||||
this.ssl = ssl ? true : false;
|
||||
this.sslStrict = sslStrict ? true : false;
|
||||
this.http = this.ssl ? https : http;
|
||||
this.sslCa = sslCa;
|
||||
};
|
||||
|
||||
Client.prototype.call = function(method, params, callback, errback, path) {
|
||||
@ -42,8 +48,17 @@ Client.prototype.call = function(method, params, callback, errback, path) {
|
||||
headers: {
|
||||
'Host': this.host,
|
||||
'Content-Length': requestJSON.length
|
||||
}
|
||||
},
|
||||
agent: false
|
||||
};
|
||||
|
||||
if (this.ssl && this.sslStrict) {
|
||||
requestOptions.rejectUnauthorized = true;
|
||||
}
|
||||
|
||||
if (this.ssl && this.sslCa) {
|
||||
requestOptions.ca = this.sslCa;
|
||||
}
|
||||
|
||||
// use HTTP auth if user and password set
|
||||
if (this.user && this.password) {
|
||||
@ -51,7 +66,7 @@ Client.prototype.call = function(method, params, callback, errback, path) {
|
||||
}
|
||||
|
||||
// Now we'll make a request to the server
|
||||
var request = http.request(requestOptions);
|
||||
var request = this.http.request(requestOptions);
|
||||
|
||||
request.on('error', errback);
|
||||
|
||||
|
||||
@ -11,9 +11,12 @@
|
||||
"contributors": [
|
||||
"Sean Lavine <sean@eternalrise.com>"
|
||||
],
|
||||
"dependencies": {},
|
||||
"dependencies": {
|
||||
"deprecate": "~0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "~1.8.1"
|
||||
"mocha": "~1.8.1",
|
||||
"clone": "~0.1.6"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
var assert = require('assert'),
|
||||
bitcoin = require('../lib/bitcoin'),
|
||||
config = require('./config');
|
||||
config = require('./config'),
|
||||
deprecate = require('deprecate');
|
||||
|
||||
// hide deprecation warnings
|
||||
deprecate.silence = true;
|
||||
|
||||
var test = {
|
||||
account: 'test'
|
||||
|
||||
56
test/ssl.js
Normal file
56
test/ssl.js
Normal file
@ -0,0 +1,56 @@
|
||||
var assert = require('assert'),
|
||||
fs = require('fs'),
|
||||
clone = require('clone'),
|
||||
bitcoin = require('../lib/bitcoin'),
|
||||
config = require('./config');
|
||||
|
||||
var getInfo = function(opts, cb) {
|
||||
var client = new bitcoin.Client(opts);
|
||||
client.getInfo(cb);
|
||||
};
|
||||
|
||||
describe('Client SSL', function() {
|
||||
it('use sslStrict by default', function(done) {
|
||||
var opts = clone(config);
|
||||
opts.ssl = true;
|
||||
getInfo(opts, function(err, info) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.equal(err.message, 'DEPTH_ZERO_SELF_SIGNED_CERT');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('strictSSL should fail with self-signed certificate', function(done) {
|
||||
var opts = clone(config);
|
||||
opts.ssl = true;
|
||||
opts.sslStrict = true;
|
||||
getInfo(opts, function(err, info) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.equal(err.message, 'DEPTH_ZERO_SELF_SIGNED_CERT');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('self-signed certificate with sslStrict false', function(done) {
|
||||
var opts = clone(config);
|
||||
opts.ssl = true;
|
||||
opts.sslStrict = false;
|
||||
getInfo(opts, function(err, info) {
|
||||
assert.ifError(err);
|
||||
assert.ok(info);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('self-signed certificate with sslStrict and CA specified', function(done) {
|
||||
var opts = clone(config);
|
||||
opts.ssl = true;
|
||||
opts.sslCa = fs.readFileSync(__dirname + '/testnet-box/1/testnet3/server.cert');
|
||||
getInfo(opts, function(err, info) {
|
||||
assert.ifError(err);
|
||||
assert.ok(info);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user