Do some random sanity checking for stratum message parsing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
diff --git a/util.c b/util.c
index 756b77d..6401bb8 100644
--- a/util.c
+++ b/util.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2013 Con Kolivas
+ * Copyright 2011-2014 Con Kolivas
* Copyright 2010 Jeff Garzik
*
* This program is free software; you can redistribute it and/or modify it
@@ -720,6 +720,34 @@ bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
return ret;
}
+static bool _valid_hex(char *s, const char *file, const char *func, const int line)
+{
+ bool ret = false;
+ int i, len;
+
+ if (unlikely(!s)) {
+ applog(LOG_ERR, "Null string passed to valid_hex from"IN_FMT_FFL, file, func, line);
+ return ret;
+ }
+ len = strlen(s);
+ if (unlikely(!len)) {
+ applog(LOG_ERR, "Zero length string passed to valid_hex from"IN_FMT_FFL, file, func, line);
+ return ret;
+ }
+ for (i = 0; i < len; i++) {
+ unsigned char idx = s[i];
+
+ if (unlikely(hex2bin_tbl[idx] < 0)) {
+ applog(LOG_ERR, "Invalid char %x passed to valid_hex from"IN_FMT_FFL, idx, file, func, line);
+ return ret;
+ }
+ }
+ ret = true;
+ return ret;
+}
+
+#define valid_hex(s) _valid_hex(s, __FILE__, __func__, __LINE__)
+
static const int b58tobin_tbl[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -1375,7 +1403,7 @@ bool extract_sockaddr(char *url, char **sockaddr_url, char **sockaddr_port)
if (url_len < 1)
return false;
- sprintf(url_address, "%.*s", url_len, url_begin);
+ snprintf(url_address, 254, "%.*s", url_len, url_begin);
if (port_len) {
char *slash;
@@ -1685,14 +1713,13 @@ static bool parse_notify(struct pool *pool, json_t *val)
ntime = __json_array_string(val, 7);
clean = json_is_true(json_array_get(val, 8));
- if (!job_id || !prev_hash || !coinbase1 || !coinbase2 || !bbversion || !nbit || !ntime) {
+ if (!valid_hex(job_id) || !valid_hex(prev_hash) || !valid_hex(coinbase1) ||
+ !valid_hex(coinbase2) || !valid_hex(bbversion) || !valid_hex(nbit) ||
+ !valid_hex(ntime)) {
/* Annoying but we must not leak memory */
- if (job_id)
- free(job_id);
- if (coinbase1)
- free(coinbase1);
- if (coinbase2)
- free(coinbase2);
+ free(job_id);
+ free(coinbase1);
+ free(coinbase2);
goto out;
}
@@ -1880,7 +1907,7 @@ static bool parse_reconnect(struct pool *pool, json_t *val)
if (!port)
port = pool->stratum_port;
- sprintf(address, "%s:%s", url, port);
+ snprintf(address, 254, "%s:%s", url, port);
if (!extract_sockaddr(address, &sockaddr_url, &stratum_port))
return false;
@@ -2551,14 +2578,14 @@ resend:
if (!sessionid)
applog(LOG_DEBUG, "Failed to get sessionid in initiate_stratum");
nonce1 = json_array_string(res_val, 1);
- if (!nonce1) {
- applog(LOG_INFO, "Failed to get nonce1 in initiate_stratum");
+ if (!valid_hex(nonce1)) {
+ applog(LOG_INFO, "Failed to get valid nonce1 in initiate_stratum");
free(sessionid);
goto out;
}
n2size = json_integer_value(json_array_get(res_val, 2));
- if (!n2size) {
- applog(LOG_INFO, "Failed to get n2size in initiate_stratum");
+ if (n2size < 2 || n2size > 16) {
+ applog(LOG_INFO, "Failed to get valid n2size in initiate_stratum");
free(sessionid);
free(nonce1);
goto out;