add TlsRpcCommand and TlsRawRpcCommand.
These act the same as the !tls versions of this code but they take a PEM encoded certificate chain to be used to verify certificates (ca verified certs could use /etc/ssl/certs.pem) and a parameter to skip cert verification and will use https internally.
This commit is contained in:
parent
606262514b
commit
e43c79c74d
3 changed files with 56 additions and 5 deletions
|
@ -51,7 +51,7 @@ func TestJsonRpcSend(t *testing.T) {
|
||||||
password := "something"
|
password := "something"
|
||||||
server := "invalid"
|
server := "invalid"
|
||||||
var message []byte
|
var message []byte
|
||||||
_, err := jsonRpcSend(user, password, server, message)
|
_, err := jsonRpcSend(user, password, server, message, false, nil, false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Should fail when it cannot connect.")
|
t.Errorf("Should fail when it cannot connect.")
|
||||||
}
|
}
|
||||||
|
|
37
jsonapi.go
37
jsonapi.go
|
@ -872,16 +872,32 @@ func JSONGetMethod(message []byte) (string, error) {
|
||||||
return method, err
|
return method, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TlsRpcCommand takes a message generated from one of the routines above
|
||||||
|
// along with the login/server information and any relavent PEM encoded
|
||||||
|
// certificates chains. It sends the command via https and returns a go struct
|
||||||
|
// with the result.
|
||||||
|
func TlsRpcCommand(user string, password string, server string, message []byte,
|
||||||
|
certificates []byte, skipverify bool) (Reply, error) {
|
||||||
|
return rpcCommand(user, password, server, message, true, certificates,
|
||||||
|
skipverify)
|
||||||
|
}
|
||||||
|
|
||||||
// RpcCommand takes a message generated from one of the routines above
|
// RpcCommand takes a message generated from one of the routines above
|
||||||
// along with the login/server info, sends it, and gets a reply, returning
|
// along with the login/server info, sends it, and gets a reply, returning
|
||||||
// a go struct with the result.
|
// a go struct with the result.
|
||||||
func RpcCommand(user string, password string, server string, message []byte) (Reply, error) {
|
func RpcCommand(user string, password string, server string, message []byte) (Reply, error) {
|
||||||
|
return rpcCommand(user, password, server, message, false, nil, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rpcCommand(user string, password string, server string, message []byte,
|
||||||
|
https bool, certificates []byte, skipverify bool) (Reply, error) {
|
||||||
var result Reply
|
var result Reply
|
||||||
method, err := JSONGetMethod(message)
|
method, err := JSONGetMethod(message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
body, err := RpcRawCommand(user, password, server, message)
|
body, err := rpcRawCommand(user, password, server, message, https,
|
||||||
|
certificates, skipverify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error getting json reply: %v", err)
|
err := fmt.Errorf("Error getting json reply: %v", err)
|
||||||
return result, err
|
return result, err
|
||||||
|
@ -894,10 +910,26 @@ func RpcCommand(user string, password string, server string, message []byte) (Re
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TlsRpcRawCommand takes a message generated from one of the routines above
|
||||||
|
// along with the login,server info and PEM encoded certificate chains for the
|
||||||
|
// server sends it, and gets a reply, returning
|
||||||
|
// the raw []byte response for use with ReadResultCmd.
|
||||||
|
func TlsRpcRawCommand(user string, password string, server string,
|
||||||
|
message []byte, certificates []byte, skipverify bool) ([]byte, error) {
|
||||||
|
return rpcRawCommand(user, password, server, message, true,
|
||||||
|
certificates, skipverify)
|
||||||
|
}
|
||||||
|
|
||||||
// RpcRawCommand takes a message generated from one of the routines above
|
// RpcRawCommand takes a message generated from one of the routines above
|
||||||
// along with the login/server info, sends it, and gets a reply, returning
|
// along with the login/server info, sends it, and gets a reply, returning
|
||||||
// the raw []byte response for use with ReadResultCmd.
|
// the raw []byte response for use with ReadResultCmd.
|
||||||
func RpcRawCommand(user string, password string, server string, message []byte) ([]byte, error) {
|
func RpcRawCommand(user string, password string, server string, message []byte) ([]byte, error) {
|
||||||
|
return rpcRawCommand(user, password, server, message, false, nil, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// rpcRawCommand is a helper function for the above two functions.
|
||||||
|
func rpcRawCommand(user string, password string, server string,
|
||||||
|
message []byte, https bool, certificates []byte, skipverify bool) ([]byte, error) {
|
||||||
var result []byte
|
var result []byte
|
||||||
var msg interface{}
|
var msg interface{}
|
||||||
err := json.Unmarshal(message, &msg)
|
err := json.Unmarshal(message, &msg)
|
||||||
|
@ -905,7 +937,8 @@ func RpcRawCommand(user string, password string, server string, message []byte)
|
||||||
err := fmt.Errorf("Error, message does not appear to be valid json: %v", err)
|
err := fmt.Errorf("Error, message does not appear to be valid json: %v", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
resp, err := jsonRpcSend(user, password, server, message)
|
resp, err := jsonRpcSend(user, password, server, message, https,
|
||||||
|
certificates, skipverify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error sending json message: " + err.Error())
|
err := fmt.Errorf("Error sending json message: " + err.Error())
|
||||||
return result, err
|
return result, err
|
||||||
|
|
22
jsonfxns.go
22
jsonfxns.go
|
@ -6,6 +6,9 @@ package btcjson
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
_ "crypto/sha512"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -32,9 +35,24 @@ func MarshallAndSend(rawReply Reply, w io.Writer) (string, error) {
|
||||||
// and ip/port and then send the supplied message. This uses net/http rather
|
// and ip/port and then send the supplied message. This uses net/http rather
|
||||||
// than net/rpc/jsonrpc since that one doesn't support http connections and is
|
// than net/rpc/jsonrpc since that one doesn't support http connections and is
|
||||||
// therefore useless.
|
// therefore useless.
|
||||||
func jsonRpcSend(user string, password string, server string, message []byte) (*http.Response, error) {
|
func jsonRpcSend(user string, password string, server string, message []byte,
|
||||||
|
https bool, certificates []byte, skipverify bool) (*http.Response, error) {
|
||||||
|
client := &http.Client{}
|
||||||
|
protocol := "http"
|
||||||
|
if https {
|
||||||
|
pool := x509.NewCertPool()
|
||||||
|
pool.AppendCertsFromPEM(certificates)
|
||||||
|
|
||||||
|
config := &tls.Config{
|
||||||
|
InsecureSkipVerify: skipverify,
|
||||||
|
RootCAs: pool,
|
||||||
|
}
|
||||||
|
transport := &http.Transport{TLSClientConfig: config}
|
||||||
|
client.Transport = transport
|
||||||
|
protocol = "https"
|
||||||
|
}
|
||||||
credentials := user + ":" + password
|
credentials := user + ":" + password
|
||||||
resp, err := http.Post("http://"+credentials+"@"+server,
|
resp, err := client.Post(protocol+"://"+credentials+"@"+server,
|
||||||
"application/json", bytes.NewBuffer(message))
|
"application/json", bytes.NewBuffer(message))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// We do not want to log the username/password in the errors.
|
// We do not want to log the username/password in the errors.
|
||||||
|
|
Loading…
Reference in a new issue