📄 log_mysql.c
字号:
#include <config.h>#ifdef WITH_MYSQL# include "ftpd.h"# include "parser.h"# include "log_mysql_p.h"# include "log_mysql.h"# include "messages.h"# include "crypto.h"# ifdef WITH_DMALLOC# include <dmalloc.h># endifstatic int pw_mysql_validate_name(const char *name){ if (name == NULL || *name == 0) { return -1; } do { if ((*name >= 'a' && *name <= 'z') || (*name >= 'A' && *name <= 'Z') || (*name >= '0' && *name <= '9') || *name == ' ' || *name == '-' || *name == '_' || *name == '\'' || *name == '.' || *name == ':' || *name == '@') { /* God bless the Perl 'unless' keyword */ } else { return -1; } name++; } while (*name != 0); return 0;}static char *pw_mysql_escape_string(MYSQL * const id_sql_server, const char *from){ size_t from_len; size_t to_len; char *to; unsigned long tolen; unsigned int t; unsigned char t1, t2; if (from == NULL) { return NULL; } from_len = strlen(from); to_len = from_len * 2U + (size_t) 1U; if ((to = malloc(to_len + 2U)) == NULL) { return NULL; } t = zrand(); t1 = t & 0xff; t2 = (t >> 8) & 0xff; to[to_len] = (char) t1; to[to_len + 1] = (char) t2; /* * I really hate giving a buffer without any size to a 3rd party function. * The "to" buffer is allocated on the heap, not on the stack, if * mysql_real_escape_string() is buggy, the stack shouldn't be already * smashed at this point, but data from other malloc can be corrupted and * bad things can happen. It make sense to wipe this area as soon as * possible instead of doing anything with the heap. We'll end up with * a segmentation violation, but without any possible exploit. */#ifdef HAVE_MYSQL_REAL_ESCAPE_STRING tolen = mysql_real_escape_string(id_sql_server, to, from, from_len);#else /* MySQL 3.22.x and earlier are obsolete. Better use 3.23.x or 4.x */ tolen = mysql_escape_string(to, from, from_len); #endif if (tolen >= to_len || (unsigned char) to[to_len] != t1 || (unsigned char) to[to_len + 1] != t2) { for (;;) { *to++ = 0; } } to[tolen] = 0; return to;}/* * Substitute digraphs for SQL requests. * orig_str is the original string, full of \L, \I, \P, \R and \D. * query is a buffer to handle the result. * query_len is the size of the buffer. * returns the buffer @ if successful, NULL otherwise. -frank. */static char *sqlsubst(const char *orig_str, char * const query, size_t query_len, const char * const user, const char * const ip, const char * const port, const char * const peer_ip, const char * const decimal_ip){ char *query_pnt = query; const char *orig_str_scan = orig_str; const size_t user_len = (user == NULL ? (size_t) 0U : strlen(user)); const size_t ip_len = (ip == NULL ? (size_t) 0U : strlen(ip)); const size_t port_len = (port == NULL ? (size_t) 0U : strlen(port)); const size_t peer_ip_len = (peer_ip == NULL ? (size_t) 0U : strlen(peer_ip)); const size_t decimal_ip_len = (decimal_ip == NULL ? (size_t) 0U : strlen(decimal_ip)); while (*orig_str_scan != 0) { if (*orig_str_scan == '\\' && orig_str_scan[1] != 0) { orig_str_scan++; switch(tolower((unsigned char) *orig_str_scan)) { case 'l' : if (user_len >= query_len) { return NULL; } if (user_len <= (size_t) 0U) { goto nextone; } memcpy(query_pnt, user, user_len); query_pnt += user_len; query_len -= user_len; goto nextone; case 'i' : if (ip_len >= query_len) { return NULL; } if (ip_len <= (size_t) 0U) { goto nextone; } memcpy(query_pnt, ip, ip_len); query_pnt += ip_len; query_len -= ip_len; goto nextone; case 'p' : if (port_len >= query_len) { return NULL; } if (port_len <= (size_t) 0U) { goto nextone; } memcpy(query_pnt, port, port_len); query_pnt += port_len; query_len -= port_len; goto nextone; case 'r' : if (peer_ip_len >= query_len) { return NULL; } if (peer_ip_len <= (size_t) 0U) { goto nextone; } memcpy(query_pnt, peer_ip, peer_ip_len); query_pnt += peer_ip_len; query_len -= peer_ip_len; goto nextone; case 'd' : if (decimal_ip_len >= query_len) { return NULL; } if (decimal_ip_len <= (size_t) 0U) { goto nextone; } memcpy(query_pnt, decimal_ip, decimal_ip_len); query_pnt += decimal_ip_len; query_len -= decimal_ip_len; goto nextone; default : if (--query_len <= (size_t) 0U) { return NULL; } *query_pnt++ = '\\'; } } if (ISCTRLCODE(*orig_str_scan)) { goto nextone; } if (--query_len <= (size_t) 0U) { return NULL; } *query_pnt++ = *orig_str_scan; nextone: orig_str_scan++; } *query_pnt = 0; return query;}static int pw_mysql_connect(MYSQL ** const id_sql_server){ *id_sql_server = NULL; if ((*id_sql_server = mysql_init(NULL)) == NULL) { down: if (server_down == 0) { server_down++; logfile(LOG_ERR, MSG_SQL_DOWN); } return -1; } if (mysql_real_connect(*id_sql_server, server, user, pw, db, port, socket_path, 0) == NULL) { goto down; } if (mysql_ping(*id_sql_server) != 0) { goto down; } server_down = 0; return 0;}static int pw_mysql_simplequery(MYSQL * const id_sql_server, const char * const query){ if (mysql_real_query(id_sql_server, query, strlen(query)) != 0) { return -1; } return 0;}static char *pw_mysql_getquery(MYSQL * const id_sql_server, const char * const orig_query, const char * const account, const char * const ip, const char * const port, const char * const peer_ip, const char * const decimal_ip){ char query[MYSQL_MAX_REQUEST_LENGTH]; MYSQL_RES *qresult = NULL; unsigned long *lengths; char *answer = NULL; MYSQL_ROW row; size_t length; if (orig_query == NULL || *orig_query == 0) { goto bye; } if (sqlsubst(orig_query, query, sizeof query, account, ip, port, peer_ip, decimal_ip) == NULL) { goto bye; } if (mysql_real_query(id_sql_server, query, strlen(query)) != 0) { logfile(LOG_WARNING, MSG_SQL_WRONG_PARMS " : [%s]", query); goto bye; } if (mysql_field_count(id_sql_server) != 1) { goto bye; } if ((qresult = mysql_store_result(id_sql_server)) == NULL) { goto bye; } if (mysql_num_rows(qresult) != 1) { goto bye; } if ((row = mysql_fetch_row(qresult)) == NULL || row[0] == NULL) { goto bye; } lengths = mysql_fetch_lengths(qresult); if (lengths == NULL || (length = (size_t) lengths[0] + (size_t) 1U) <= (size_t) 1U) { goto bye; } if ((answer = malloc(length)) == NULL) { goto bye; } strncpy(answer, row[0], length - (size_t) 1U); answer[length - (size_t) 1U] = 0; bye: if (qresult != NULL) { mysql_free_result(qresult); } return answer; }void pw_mysql_check(AuthResult * const result, const char *account, const char *password, const struct sockaddr_storage * const sa, const struct sockaddr_storage * const peer){ MYSQL *id_sql_server = NULL; const char *spwd = NULL; /* stored password */ const char *uid = sql_default_uid; /* stored system login/uid */ const char *gid = sql_default_gid; /* stored system group/gid */ const char *dir = NULL; /* stored home directory */#ifdef QUOTAS const char *sqta_fs = NULL; /* stored quota files */ const char *sqta_sz = NULL; /* stored quota size */#endif #ifdef RATIOS const char *ratio_ul = NULL; /* stored ratio UL */ const char *ratio_dl = NULL; /* stored ratio DL */#endif #ifdef THROTTLING const char *bandwidth_ul = NULL; /* stored bandwidth UL */ const char *bandwidth_dl = NULL; /* stored bandwidth DL */#endif char *escaped_account = NULL; char *escaped_ip = NULL; char *escaped_port = NULL; char *escaped_peer_ip = NULL; char *escaped_decimal_ip = NULL; int committed = 1; int crypto_crypt = 0, crypto_mysql = 0, crypto_md5 = 0, crypto_plain = 0; unsigned long decimal_ip_num = 0UL; char decimal_ip[42]; char hbuf[NI_MAXHOST]; char pbuf[NI_MAXSERV]; char phbuf[NI_MAXHOST]; result->auth_ok = 0; if (pw_mysql_validate_name(account) != 0) { goto bye; } if (getnameinfo((const struct sockaddr *) sa, STORAGE_LEN(*sa), hbuf, sizeof hbuf, pbuf, sizeof pbuf,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -