pool/stratum/user.cpp
2018-05-02 14:10:39 +02:00

214 lines
6.5 KiB
C++

#include "stratum.h"
// sql injection security, unwanted chars
void db_check_user_input(char* input)
{
char *p = NULL;
if (input && input[0]) {
p = strpbrk(input, " \"'\\");
if(p) *p = '\0';
}
}
void db_check_coin_symbol(YAAMP_DB *db, char* symbol)
{
if (!symbol) return;
size_t len = strlen(symbol);
if (len >= 2 && len <= 12) {
#ifdef NO_EXCHANGE
db_query(db, "SELECT symbol FROM coins WHERE installed AND algo='%s' AND symbol='%s'", g_stratum_algo, symbol);
#else
db_query(db, "SELECT symbol FROM coins WHERE installed AND (symbol='%s' OR symbol2='%s')", symbol, symbol);
#endif
MYSQL_RES *result = mysql_store_result(&db->mysql);
*symbol = '\0';
if (!result) return;
MYSQL_ROW row = mysql_fetch_row(result);
if (row) {
strcpy(symbol, row[0]);
}
mysql_free_result(result);
} else {
*symbol = '\0';
}
}
void db_add_user(YAAMP_DB *db, YAAMP_CLIENT *client)
{
db_clean_string(db, client->username);
db_clean_string(db, client->password);
db_clean_string(db, client->version);
db_clean_string(db, client->notify_id);
db_clean_string(db, client->worker);
char symbol[16] = { 0 };
char *p = strstr(client->password, "c=");
if(!p) p = strstr(client->password, "s=");
if(p) strncpy(symbol, p+2, 15);
p = strchr(symbol, ',');
if(p) *p = '\0';
bool guest = false;
int gift = -1;
#ifdef ALLOW_CUSTOM_DONATIONS
// donation percent
p = strstr(client->password, "g=");
if(p) gift = atoi(p+2);
if(gift > 100) gift = 100;
#endif
db_check_user_input(client->username);
if(strlen(client->username) < MIN_ADDRESS_LEN) {
// allow benchmark / test / donate usernames
if (!strcmp(client->username, "benchmark") || !strcmp(client->username, "donate") || !strcmp(client->username, "test")) {
guest = true;
if (g_list_coind.first) {
CLI li = g_list_coind.first;
YAAMP_COIND *coind = (YAAMP_COIND *)li->data;
if (!strlen(client->worker)) strcpy(client->worker, client->username);
strcpy(client->username, coind->wallet);
if (!strcmp(client->username, "benchmark")) strcat(client->password, ",stats");
if (!strcmp(client->username, "donate")) gift = 100;
}
}
if (!guest) {
debuglog("Invalid user address '%s'\n", client->username);
return;
}
}
// debuglog("user %s %s gives %d %\n", client->username, symbol, gift);
db_query(db, "SELECT id, is_locked, logtraffic, coinid, donation FROM accounts WHERE username='%s'", client->username);
MYSQL_RES *result = mysql_store_result(&db->mysql);
if(!result) return;
MYSQL_ROW row = mysql_fetch_row(result);
if(row)
{
if(row[1] && atoi(row[1])) client->userid = -1;
else client->userid = atoi(row[0]);
client->logtraffic = row[2] && atoi(row[2]);
client->coinid = row[3] ? atoi(row[3]) : 0;
if (gift == -1) gift = row[4] ? atoi(row[4]) : 0; // keep current
}
mysql_free_result(result);
db_check_user_input(symbol);
db_check_coin_symbol(db, symbol);
if (gift < 0) gift = 0;
client->donation = gift;
if(client->userid == -1)
return;
else if(client->userid == 0 && strlen(client->username) >= MIN_ADDRESS_LEN)
{
db_query(db, "INSERT INTO accounts (username, coinsymbol, balance, donation, hostaddr) values ('%s', '%s', 0, %d, '%s')",
client->username, symbol, gift, client->sock->ip);
client->userid = (int)mysql_insert_id(&db->mysql);
}
else {
db_query(db, "UPDATE accounts SET coinsymbol='%s', swap_time=%u, donation=%d, hostaddr='%s' WHERE id=%d AND balance = 0"
" AND (SELECT COUNT(id) FROM payouts WHERE account_id=%d AND tx IS NULL) = 0" // failed balance
" AND (SELECT pending FROM balanceuser WHERE userid=%d ORDER by time DESC LIMIT 1) = 0" // pending balance
, symbol, (uint) time(NULL), gift, client->sock->ip, client->userid, client->userid, client->userid);
if (mysql_affected_rows(&db->mysql) > 0 && strlen(symbol)) {
debuglog("%s: %s coinsymbol set to %s ip %s uid (%d)\n",
g_current_algo->name, client->username, symbol, client->sock->ip, client->userid);
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
void db_clear_worker(YAAMP_DB *db, YAAMP_CLIENT *client)
{
if(!client->workerid)
return;
db_query(db, "DELETE FROM workers WHERE id=%d", client->workerid);
client->workerid = 0;
}
void db_add_worker(YAAMP_DB *db, YAAMP_CLIENT *client)
{
char password[128] = { 0 };
char version[128] = { 0 };
char worker[128] = { 0 };
int now = time(NULL);
db_clear_worker(db, client);
db_check_user_input(client->username);
db_check_user_input(client->version);
db_check_user_input(client->password);
db_check_user_input(client->worker);
// strip for recent mysql defaults (error if fields are too long)
if (strlen(client->password) > 64)
clientlog(client, "password too long truncated: %s", client->password);
if (strlen(client->version) > 64)
clientlog(client, "version too long truncated: %s", client->version);
if (strlen(client->worker) > 64)
clientlog(client, "worker too long truncated: %s", client->worker);
strncpy(password, client->password, 64);
strncpy(version, client->version, 64);
strncpy(worker, client->worker, 64);
db_query(db, "INSERT INTO workers (userid, ip, name, difficulty, version, password, worker, algo, time, pid) "\
"VALUES (%d, '%s', '%s', %f, '%s', '%s', '%s', '%s', %d, %d)",
client->userid, client->sock->ip, client->username, client->difficulty_actual,
version, password, worker, g_stratum_algo, now, getpid());
client->workerid = (int)mysql_insert_id(&db->mysql);
}
void db_update_workers(YAAMP_DB *db)
{
g_list_client.Enter();
for(CLI li = g_list_client.first; li; li = li->next)
{
YAAMP_CLIENT *client = (YAAMP_CLIENT *)li->data;
if(client->deleted) continue;
if(!client->workerid) continue;
if(client->speed < 0.00001)
{
clientlog(client, "speed %f", client->speed);
shutdown(client->sock->sock, SHUT_RDWR);
db_clear_worker(db, client);
object_delete(client);
continue;
}
client->speed *= 0.8;
if(client->difficulty_written == client->difficulty_actual) continue;
db_query(db, "UPDATE workers SET difficulty=%f, subscribe=%d WHERE id=%d",
client->difficulty_actual, client->extranonce_subscribe, client->workerid);
client->difficulty_written = client->difficulty_actual;
}
//client_sort();
g_list_client.Leave();
}
void db_init_user_coinid(YAAMP_DB *db, YAAMP_CLIENT *client)
{
if (!client->userid)
return;
if (!client->coinid)
db_query(db, "UPDATE accounts SET coinid=NULL WHERE id=%d", client->userid);
else
db_query(db, "UPDATE accounts SET coinid=%d WHERE id=%d AND IFNULL(coinid,0) = 0",
client->coinid, client->userid);
}