Add "cert" option for rpc server's self-signed SSL certificate

When minerd is used across the internet, the server's rpc userpass
travel unexcrypted, allowing anyone en route to copy them and
empty the server's wallet. Using https: would prevent this
but minerd's SSL connection fails on self-signed certificates.

This change adds a "-cert file" option (cert:"file" in minerd.conf)
to tell minerd the filename of the server's self-signed certificate.
This commit is contained in:
Martin Guy 2013-06-08 15:56:28 +02:00
parent 3c4eb509a5
commit b6f26e1acc
3 changed files with 17 additions and 7 deletions

View file

@ -130,6 +130,7 @@ static enum sha256_algos opt_algo = ALGO_SCRYPT;
static int opt_n_threads; static int opt_n_threads;
static int num_processors; static int num_processors;
static char *rpc_url; static char *rpc_url;
static char *rpc_cert;
static char *rpc_userpass; static char *rpc_userpass;
static char *rpc_user, *rpc_pass; static char *rpc_user, *rpc_pass;
char *opt_proxy; char *opt_proxy;
@ -163,6 +164,7 @@ Options:\n\
scrypt scrypt(1024, 1, 1) (default)\n\ scrypt scrypt(1024, 1, 1) (default)\n\
sha256d SHA-256d\n\ sha256d SHA-256d\n\
-o, --url=URL URL of mining server (default: " DEF_RPC_URL ")\n\ -o, --url=URL URL of mining server (default: " DEF_RPC_URL ")\n\
-C, --cert=FILE certificate for mining server using ssl\n\
-O, --userpass=U:P username:password pair for mining server\n\ -O, --userpass=U:P username:password pair for mining server\n\
-u, --user=USERNAME username for mining server\n\ -u, --user=USERNAME username for mining server\n\
-p, --pass=PASSWORD password for mining server\n\ -p, --pass=PASSWORD password for mining server\n\
@ -200,7 +202,7 @@ static char const short_options[] =
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
"S" "S"
#endif #endif
"a:c:Dhp:Px:qr:R:s:t:T:o:u:O:V"; "a:C:c:Dhp:Px:qr:R:s:t:T:o:u:O:V";
static struct option const options[] = { static struct option const options[] = {
{ "algo", 1, NULL, 'a' }, { "algo", 1, NULL, 'a' },
@ -208,6 +210,7 @@ static struct option const options[] = {
{ "background", 0, NULL, 'B' }, { "background", 0, NULL, 'B' },
#endif #endif
{ "benchmark", 0, NULL, 1005 }, { "benchmark", 0, NULL, 1005 },
{ "cert", 1, NULL, 'C' },
{ "config", 1, NULL, 'c' }, { "config", 1, NULL, 'c' },
{ "debug", 0, NULL, 'D' }, { "debug", 0, NULL, 'D' },
{ "help", 0, NULL, 'h' }, { "help", 0, NULL, 'h' },
@ -317,7 +320,7 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
hexstr); hexstr);
/* issue JSON-RPC request */ /* issue JSON-RPC request */
val = json_rpc_call(curl, rpc_url, rpc_userpass, s, false, false, NULL); val = json_rpc_call(curl, rpc_url, rpc_cert, rpc_userpass, s, false, false, NULL);
if (unlikely(!val)) { if (unlikely(!val)) {
applog(LOG_ERR, "submit_upstream_work json_rpc_call failed"); applog(LOG_ERR, "submit_upstream_work json_rpc_call failed");
goto out; goto out;
@ -367,7 +370,7 @@ static bool get_upstream_work(CURL *curl, struct work *work)
struct timeval tv_start, tv_end, diff; struct timeval tv_start, tv_end, diff;
gettimeofday(&tv_start, NULL); gettimeofday(&tv_start, NULL);
val = json_rpc_call(curl, rpc_url, rpc_userpass, rpc_req, val = json_rpc_call(curl, rpc_url, rpc_cert, rpc_userpass, rpc_req,
want_longpoll, false, NULL); want_longpoll, false, NULL);
gettimeofday(&tv_end, NULL); gettimeofday(&tv_end, NULL);
@ -740,7 +743,7 @@ start:
json_t *val, *soval; json_t *val, *soval;
int err; int err;
val = json_rpc_call(curl, lp_url, rpc_userpass, rpc_req, val = json_rpc_call(curl, lp_url, rpc_cert, rpc_userpass, rpc_req,
false, true, &err); false, true, &err);
if (likely(val)) { if (likely(val)) {
applog(LOG_INFO, "LONGPOLL detected new block"); applog(LOG_INFO, "LONGPOLL detected new block");
@ -818,6 +821,11 @@ static void parse_arg (int key, char *arg)
case 'B': case 'B':
opt_background = true; opt_background = true;
break; break;
case 'C':
free(rpc_cert);
rpc_cert = strdup(arg);
break;
case 'c': { case 'c': {
json_error_t err; json_error_t err;
if (opt_config) if (opt_config)

View file

@ -164,8 +164,8 @@ extern int longpoll_thr_id;
extern struct work_restart *work_restart; extern struct work_restart *work_restart;
extern void applog(int prio, const char *fmt, ...); extern void applog(int prio, const char *fmt, ...);
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, extern json_t *json_rpc_call(CURL *curl, const char *url, const char *cert,
const char *rpc_req, bool, bool, int *); const char *userpass, const char *rpc_req, bool, bool, int *);
extern char *bin2hex(const unsigned char *p, size_t len); extern char *bin2hex(const unsigned char *p, size_t len);
extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len); extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
extern int timeval_subtract(struct timeval *result, struct timeval *x, extern int timeval_subtract(struct timeval *result, struct timeval *x,

4
util.c
View file

@ -285,7 +285,7 @@ static int json_rpc_call_lp_cb(void *userdata, curl_socket_t fd,
} }
#endif #endif
json_t *json_rpc_call(CURL *curl, const char *url, json_t *json_rpc_call(CURL *curl, const char *url, const char *cert,
const char *userpass, const char *rpc_req, const char *userpass, const char *rpc_req,
bool longpoll_scan, bool longpoll, int *curl_err) bool longpoll_scan, bool longpoll, int *curl_err)
{ {
@ -306,6 +306,8 @@ json_t *json_rpc_call(CURL *curl, const char *url,
if (opt_protocol) if (opt_protocol)
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_URL, url);
if (cert != NULL)
curl_easy_setopt(curl, CURLOPT_CAINFO, cert);
curl_easy_setopt(curl, CURLOPT_ENCODING, ""); curl_easy_setopt(curl, CURLOPT_ENCODING, "");
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);