📄 log_pgsql.c
字号:
#include <config.h>/* PostgreSQL backend, by Cindy Marasco <cindy@getaclue.org> */#ifdef WITH_PGSQL#include "ftpd.h"#include "parser.h"#include "log_pgsql_p.h"#include "log_pgsql.h"#include "messages.h"#include "crypto.h"#ifdef WITH_DMALLOC# include <dmalloc.h>#endifstatic size_t prv_PQescapeString(char * const to, const char * const from, const size_t length){ register const char *source = from; register char *target = to; size_t remaining = length; while (remaining > (size_t) 0U) { switch (*source) { case 0: remaining = (size_t) 1U; break; case '\r': *target++ = '\\'; *target++ = 'r'; break; case '\n': *target++ = '\\'; *target++ = 'n'; break; case '\b': *target++ = '\\'; *target++ = 'b'; break; case '\\': case '\'': case '"': *target++ = '\\'; default: *target++ = *source; } source++; remaining--; } *target = 0; return (size_t) (target - to);}static int pw_pgsql_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_pgsql_escape_string(const char *from){ size_t from_len; size_t to_len; char *to; size_t tolen; if (from == NULL) { return NULL; } from_len = strlen(from); to_len = from_len * 2U + (size_t) 1U; if ((to = malloc(to_len)) == NULL) { return NULL; } tolen = prv_PQescapeString(to, from, from_len); if (tolen >= to_len) { for (;;) { *to++ = 0; } } to[tolen] = 0; return to;}/* * Substitute digraphs for SQL requests. * orig_str is the original string, from the configuration file * 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_pgsql_connect(PGconn ** const id_sql_server){ char *conninfo = NULL; size_t sizeof_conninfo; char *escaped_server = NULL; char *escaped_db = NULL; char *escaped_user = NULL; char *escaped_pw = NULL; int ret = -1; *id_sql_server = NULL; if ((escaped_server = pw_pgsql_escape_string(server)) == NULL || (escaped_db = pw_pgsql_escape_string(db)) == NULL || (escaped_user = pw_pgsql_escape_string(user)) == NULL || (escaped_pw = pw_pgsql_escape_string(pw)) == NULL) { goto bye; } #define PGSQL_CONNECT_FMTSTRING \"host='%s' port='%d' dbname='%s' user='%s' password='%s'" sizeof_conninfo = sizeof PGSQL_CONNECT_FMTSTRING + strlen(escaped_server) + (size_t) 5U + strlen(escaped_db) + strlen(escaped_user) + strlen(escaped_pw); if ((conninfo = malloc(sizeof_conninfo)) == NULL) { goto bye; } if (SNCHECK(snprintf(conninfo, sizeof_conninfo, PGSQL_CONNECT_FMTSTRING, server, port, db, user, pw), sizeof_conninfo)) { goto bye; } if ((*id_sql_server = PQconnectdb(conninfo)) == NULL || PQstatus(*id_sql_server) == CONNECTION_BAD) { free(conninfo); if (server_down == 0) { server_down++; logfile(LOG_ERR, MSG_SQL_DOWN); } goto bye; } server_down = 0; ret = 0; bye: free(conninfo); free(escaped_server); free(escaped_db); free(escaped_user); free(escaped_pw); return ret;}static int pw_pgsql_simplequery(PGconn * const id_sql_server, const char * const query){ PGresult *result; if ((result = PQexec(id_sql_server, query)) == NULL) { return -1; } if (PQresultStatus(result) != PGRES_COMMAND_OK) { PQclear(result); return -1; } PQclear(result); return 0;}static char *pw_pgsql_getquery(PGconn * 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){ PGresult *qresult = NULL; size_t length; char *answer = NULL; char query[PGSQL_MAX_REQUEST_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 ((qresult = PQexec(id_sql_server, query)) == NULL) { logfile(LOG_WARNING, MSG_SQL_WRONG_PARMS " : [%s]", query); goto bye; } if (PQresultStatus(qresult) != PGRES_TUPLES_OK || PQnfields(qresult) != 1 || PQntuples(qresult) != 1 || PQgetisnull(qresult, 0, 0)) { goto bye; } if ((length = (size_t) PQgetlength(qresult, 0, 0) + (size_t) 1U) <= (size_t) 1U || (answer = malloc(length)) == NULL) { goto bye; } strncpy(answer, PQgetvalue(qresult, 0, 0), length - (size_t) 1U); answer[length - (size_t) 1U] = 0; bye: if (qresult != NULL) { PQclear(qresult); } return answer; }void pw_pgsql_check(AuthResult * const result, const char *account, const char *password, const struct sockaddr_storage * const sa, const struct sockaddr_storage * const peer){ PGconn *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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -