static const char *uptime(void) { #ifdef __FreeBSD__ struct timeval boottime; time_t now; int mib[2]; size_t size; time_t u; static char buf[1025]; (void)time(&now); mib[0] = CTL_KERN; mib[1] = KERN_BOOTTIME; size = sizeof(boottime); if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0) { u = now - boottime.tv_sec; if (u > 60) u += 30; if (SNCHECK(snprintf(buf, sizeof buf, "%lu days, %lu:%02lu:%02lu", u / 86400UL, u / 3600UL % 24UL, u / 60UL % 60UL, u % 60UL), sizeof buf)) { _exit(EXIT_FAILURE); } } return buf; #else int f; ssize_t r; unsigned long u; static char buf[1025]; if ((f = open("/proc/uptime", O_RDONLY)) == -1) { return "?"; } while ((r = read(f, buf, sizeof buf - 1U)) < (ssize_t) 0 && errno == EINTR); if (r <= (ssize_t) 0) { close(f); return "?"; } close(f); u = strtoul(buf, NULL, 10); if (SNCHECK(snprintf(buf, sizeof buf, "%lu days, %lu:%02lu:%02lu", u / 86400UL, u / 3600UL % 24UL, u / 60UL % 60UL, u % 60UL), sizeof buf)) { _exit(EXIT_FAILURE); } return buf; #endif }
static LDAPMessage *pw_ldap_uid_search(LDAP * const ld, const char *uid, char *attrs[]) { char *alloca_filter; size_t uid_size; size_t filter_size; int rc; LDAPMessage *res; if (uid == NULL || *uid == 0) { return NULL; } uid_size = strlen(uid); if (uid_size > MAX_LDAP_UID_LENGTH) { return NULL; } filter_size = strlen(ldap_filter) + uid_size + (size_t) 1U; if ((alloca_filter = ALLOCA(filter_size)) == NULL) { return NULL; } if (SNCHECK(snprintf(alloca_filter, filter_size, ldap_filter, uid), filter_size)) { ALLOCA_FREE(alloca_filter); return NULL; } rc = ldap_search_s(ld, base, LDAP_SCOPE_SUBTREE, alloca_filter, attrs, 0, &res); ALLOCA_FREE(alloca_filter); if (rc != LDAP_SUCCESS) { return NULL; } return res; }
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='******' password='******'" 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 altlog_writexfer_w3c(const int upload, const char * const filename, const off_t size, const double duration) { /* * <date> <time> <ip> "[]sent" <file> "226" <user> * date time c-ip cs-method cs-uri-stem sc-status cs-username */ struct tm *tm; struct tm gmt; const char *host_ = *host != 0 ? host : "-"; const char *account_ = *account != 0 ? account : "-"; char *alloca_line; char *quoted_filename; time_t now; size_t line_size; (void) duration; if ((now = time(NULL)) == (time_t) -1 || (tm = localtime(&now)) == NULL || tm->tm_mon > 11 || tm->tm_mon < 0) { return -1; } gmt = *gmtime(&now); if ((quoted_filename = urlencode(filename)) == NULL) { return -1; } line_size = (sizeof "13-04-1975 12:34:56 " - 1U) + strlen(host_) + 1U + (sizeof "[]created" - 1U) + 1U + strlen(quoted_filename) + 1U + (sizeof "226" - 1U) + strlen(account_) + 1U + 42U + 1U /* \n */ + 1U; if ((alloca_line = ALLOCA(line_size)) == NULL) { return -1; } if (!SNCHECK(snprintf(alloca_line, line_size, "%d-%02d-%02d %02d:%02d:%02d %s []%s %s 226 %s %llu\n", gmt.tm_year + 1900, gmt.tm_mon + 1, gmt.tm_mday, gmt.tm_hour, gmt.tm_min, gmt.tm_sec, host_, (upload != 0 ? "created" : "sent"), quoted_filename, account, (unsigned long long) size), line_size)) { altlog_write(alloca_line); } if (quoted_filename != filename) { free(quoted_filename); } ALLOCA_FREE(alloca_line); return 0; }
static void newenv_uo(const char * const var, const unsigned int val) { size_t s; char *v; s = strlen(var) + (size_t) 8U; if ((v = malloc(s)) == NULL) { return; } if (SNCHECK(snprintf(v, s, "%s=%o", var, val), s)) { free(v); return; } putenv(v); }
static void newenv_str(const char * const var, const char * const str) { size_t s; char *v; if (str == NULL || *str == 0) { return; } s = strlen(var) + strlen(str) + (size_t) 2U; if ((v = malloc(s)) == NULL) { return; } if (SNCHECK(snprintf(v, s, "%s=%s", var, str), s)) { free(v); return; } putenv(v); }
static char *checkvirtual(char *path) { static char buf[PATH_MAX + 1]; char *path_pnt; if (path == NULL || *path == '/' || (path_pnt = strstr(path, ":/")) == NULL) { return path; } *path_pnt = 0; if (SNCHECK(snprintf(buf, sizeof buf, VHOST_PATH "/%s%s", path, path_pnt + 1), sizeof buf)) { /* Better avoid processing than risking a security flaw */ return NULL; } return buf; }
void ftpwho_unlinksbfile(const pid_t pid) { size_t sbfile_size; char *sbfile; sbfile_size = sizeof SCOREBOARD_PATH - 1U + 1U + sizeof SCOREBOARD_PREFIX - 1U + 8U + 1U; if ((sbfile = ALLOCA(sbfile_size)) == NULL) { return; } if (SNCHECK(snprintf(sbfile, sbfile_size, SCOREBOARD_PATH "/" SCOREBOARD_PREFIX "%08lu", (unsigned long) pid), sbfile_size)) { ALLOCA_FREE(sbfile); return; } (void) unlink(sbfile); ALLOCA_FREE(sbfile); }
static int altlog_writexfer_stats(const int upload, const char * const filename, const off_t size, const double duration) { /* * <date> <start.pid> <user> <ip> <u/d> <size> <duration> <file> */ const char *host_ = *host != 0 ? host : "-"; const char *account_ = *account != 0 ? account : "-"; char *alloca_line; size_t line_size; line_size = 16U /* now */ + 1U + 16U /* start */ + 1U /* . */ + 16U /* pid */ + 1U + strlen(account_) + 1U + strlen(host_) + 1U + 1U /* U/D */ + 1U + 20U /* size */ + 1U + 16U /* duration */ + strlen(filename) + 1U /* \n */ + 1U; if ((alloca_line = ALLOCA(line_size)) == NULL) { return -1; } if (!SNCHECK(snprintf(alloca_line, line_size, "%llu %llx.%lx %s %s %c %llu %lu %s\n", (unsigned long long) time(NULL), (unsigned long long) session_start_time, (unsigned long) getpid(), account_, host_, upload != 0 ? 'U' : 'D', (unsigned long long) size, (unsigned long) (duration + 0.5), filename), line_size)) { altlog_write(alloca_line); } ALLOCA_FREE(alloca_line); return 0; }
static void updatepidfile(void) { char buf[42]; size_t buf_len; int fd; if (SNCHECK(snprintf(buf, sizeof buf, "%lu\n", (unsigned long) getpid()), sizeof buf)) { return; } if (unlink(uploadscript_pid_file) != 0 && errno != ENOENT) { return; } if ((fd = open(uploadscript_pid_file, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, (mode_t) 0644)) == -1) { return; } buf_len = strlen(buf); if (safe_write(fd, buf, buf_len, -1) != (ssize_t) buf_len) { (void) ftruncate(fd, (off_t) 0); } close(fd); }
int altlog_write_w3c_header(void) { time_t now; struct tm *tm; struct tm gmt; char *alloca_line; size_t line_size; if ((now = time(NULL)) == (time_t) -1 || (tm = localtime(&now)) == NULL || tm->tm_mon > 11 || tm->tm_mon < 0) { return -1; } gmt = *gmtime(&now); line_size = sizeof "#Date: 001975-04-13 12:34:56\n"; /* be year-999999 compliant :) */ if ((alloca_line = ALLOCA(line_size)) == NULL) { return -1; } altlog_write("#Software: Pure-FTPd " VERSION "\n"); altlog_write("#Version: 1.0\n"); if (!SNCHECK(snprintf(alloca_line, line_size, "#Date: %04d-%02d-%02d %02d:%02d:%02d\n", gmt.tm_year + 1900, gmt.tm_mon + 1, gmt.tm_mday, gmt.tm_hour, gmt.tm_min, gmt.tm_sec), line_size)) { altlog_write(alloca_line); } altlog_write("#Fields: date time c-ip cs-method cs-uri-stem sc-status cs-username sc-bytes\n"); ALLOCA_FREE(alloca_line); return 0; }
static int altlog_writexfer_xferlog(const int upload, const char * const filename, const off_t size, const double duration) { char date[sizeof "Mon Apr 13 12:34:56 1975"]; struct tm *tm; char *alloca_line; const char *host_ = *host != 0 ? host : "-"; const char *account_ = *account != 0 ? account : "-"; char *quoted_filename; size_t filename_idx; time_t now; size_t line_size; size_t filename_size; char c; if ((now = time(NULL)) == (time_t) -1 || (tm = localtime(&now)) == NULL || tm->tm_mon > 11 || tm->tm_mon < 0 || tm->tm_wday > 6 || tm->tm_wday < 0) { return -1; } if (SNCHECK(snprintf(date, sizeof date, "%s %s %02d %02d:%02d:%02d %d", week_days[tm->tm_wday], months[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_year + 1900), sizeof date)) { return -1; } if ((filename_idx = strlen(filename)) <= (size_t) 0U) { return -1; } filename_size = filename_idx + (size_t) 1U; if ((quoted_filename = ALLOCA(filename_size)) == NULL) { return -1; } quoted_filename[filename_idx] = 0; do { filename_idx--; c = filename[filename_idx]; if (isspace((unsigned char) c) || ISCTRLCODE(c)) { c = '_'; } quoted_filename[filename_idx] = c; } while (filename_idx > (size_t) 0U); line_size = (sizeof date - 1U) + (sizeof " " - 1U) + (size_t) 16U /* duration */ + (sizeof " " - 1U) + strlen(host_) + (sizeof " " - 1U) + (size_t) 20U /* size */ + (sizeof " " - 1U) + (filename_size - 1U) + (sizeof " " - 1U) + (size_t) 1U /* type */ + (sizeof " _ " - 1U) + (size_t) 1U /* direction */ + (sizeof " " - 1U) + (size_t) 1U /* anonymous */ + (sizeof " " - 1U) + strlen(account_) + (sizeof " ftp 1 * c\n" - 1U) + (size_t) 1U; if ((alloca_line = ALLOCA(line_size)) == NULL) { ALLOCA_FREE(quoted_filename); return -1; } if (!SNCHECK(snprintf(alloca_line, line_size, "%s %lu %s %llu %s %c _ %c %c %s ftp 1 * c\n", date, (unsigned long) (duration + 0.5), host_, (unsigned long long) size, quoted_filename, type == 1 ? 'a' : 'b', upload != 0 ? 'i' : 'o', loggedin != 0 ? 'r' : 'a', account_), line_size)) { altlog_write(alloca_line); } ALLOCA_FREE(quoted_filename); ALLOCA_FREE(alloca_line); return 0; }
static int altlog_writexfer_clf(const int upload, const char * const filename, const off_t size) { char date[sizeof "13/Apr/1975:12:34:56 +0100"]; struct tm *tm; char *alloca_line; const char *host_ = *host != 0 ? host : "-"; const char *account_ = *account != 0 ? account : "-"; char *quoted_filename; time_t now; long diff; int sign; size_t line_size; if ((now = time(NULL)) == (time_t) -1 || (tm = localtime(&now)) == NULL || tm->tm_mon > 11 || tm->tm_mon < 0) { return -1; } # ifdef HAVE_STRUCT_TM_TM_GMTOFF diff = -(tm->tm_gmtoff) / 60L; # elif defined(HAVE_SCALAR_TIMEZONE) diff = -(timezone) / 60L; # else { struct tm gmt; struct tm *t; int days, hours, minutes; gmt = *gmtime(&now); t = localtime(&now); days = t->tm_yday - gmt.tm_yday; hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) + t->tm_hour - gmt.tm_hour); minutes = hours * 60 + t->tm_min - gmt.tm_min; diff = -minutes; } # endif if (diff > 0L) { sign = '+'; } else { sign = '-'; diff = -diff; } if (SNCHECK(snprintf(date, sizeof date, "%02d/%s/%d:%02d:%02d:%02d %c%02ld%02ld", tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, sign, diff / 60L, diff % 60L), sizeof date)) { return -1; } if ((quoted_filename = urlencode(filename)) == NULL) { return -1; } line_size = strlen(host_) + (sizeof " - " - 1U) + strlen(account_) + (sizeof " [" - 1U) + (sizeof date - 1U) + (sizeof "] \"" - 1U) + 3U /* GET / PUT */ + (sizeof " " - 1U) + strlen(quoted_filename) + (sizeof "\" 200 18446744073709551616\n" - 1U) + 1U; if ((alloca_line = ALLOCA(line_size)) == NULL) { return -1; } if (!SNCHECK(snprintf(alloca_line, line_size, "%s - %s [%s] \"%s %s\" 200 %llu\n", host_, account_, date, upload == 0 ? "GET" : "PUT", quoted_filename, (unsigned long long) size), line_size)) { altlog_write(alloca_line); } if (quoted_filename != filename) { free(quoted_filename); } ALLOCA_FREE(alloca_line); return 0; }
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 */ 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; char *scrambled_password = NULL; int committed = 1; int crypto_crypt = 0, crypto_plain = 0, crypto_md5 = 0, crypto_md5sha1 = 0; /* TRICK */ 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_pgsql_validate_name(account) != 0) { goto bye; } if (getnameinfo((const struct sockaddr *) sa, STORAGE_LEN(*sa), hbuf, sizeof hbuf, pbuf, sizeof pbuf, NI_NUMERICHOST | NI_NUMERICSERV) != 0 || getnameinfo((const struct sockaddr *) peer, STORAGE_LEN(*peer), phbuf, sizeof phbuf, NULL, (size_t) 0U, NI_NUMERICHOST) != 0) { goto bye; } *decimal_ip = 0; //if (STORAGE_FAMILY(*peer) == AF_INET) { const unsigned char *decimal_ip_raw = (const unsigned char *) &(STORAGE_SIN_ADDR(*peer)); decimal_ip_num = (decimal_ip_raw[0] << 24) | (decimal_ip_raw[1] << 16) | (decimal_ip_raw[2] << 8) | decimal_ip_raw[3]; if (SNCHECK(snprintf(decimal_ip, sizeof decimal_ip, "%lu", decimal_ip_num), sizeof decimal_ip)) { goto bye; } //} if (pw_pgsql_connect(&id_sql_server) != 0) { goto bye; } if ((escaped_account = pw_pgsql_escape_string(account)) == NULL) { goto bye; } if ((escaped_ip = pw_pgsql_escape_string(hbuf)) == NULL) { goto bye; } if ((escaped_port = pw_pgsql_escape_string(pbuf)) == NULL) { goto bye; } if ((escaped_peer_ip = pw_pgsql_escape_string(phbuf)) == NULL) { goto bye; } if ((escaped_decimal_ip = pw_pgsql_escape_string(decimal_ip)) == NULL) { goto bye; } if (pw_pgsql_simplequery(id_sql_server, PGSQL_TRANSACTION_START) == 0) { committed = 0; } /*logfile(LOG_WARNING, "START AUTH 2 [%s]", sqlreq_getpw); */ if ((spwd = pw_pgsql_getquery(id_sql_server, sqlreq_getpw, escaped_account, escaped_ip, escaped_port, escaped_peer_ip, escaped_decimal_ip)) == NULL) { goto bye; } /*logfile(LOG_WARNING, "START AUTH 3 [%s]", sqlreq_getuid);*/ if (uid == NULL) { uid = pw_pgsql_getquery(id_sql_server, sqlreq_getuid, escaped_account, escaped_ip, escaped_port, escaped_peer_ip, escaped_decimal_ip); } if (uid == NULL) { goto bye; } /*logfile(LOG_WARNING, "START AUTH 4 [%s]", sqlreq_getgid);*/ if (gid == NULL) { gid = pw_pgsql_getquery(id_sql_server, sqlreq_getgid, escaped_account, escaped_ip, escaped_port, escaped_peer_ip, escaped_decimal_ip); } if (gid == NULL) { goto bye; } /*logfile(LOG_WARNING, "START AUTH 5 [%s]", sqlreq_getdir);*/ if ((dir = pw_pgsql_getquery(id_sql_server, sqlreq_getdir, escaped_account, escaped_ip, escaped_port, escaped_peer_ip, escaped_decimal_ip)) == NULL) { goto bye; } result->auth_ok--; /* -1 */ if (strcasecmp(crypto, PASSWD_SQL_ANY) == 0) { crypto_crypt++; crypto_md5++; } else if (strcasecmp(crypto, PASSWD_SQL_CRYPT) == 0) { crypto_crypt++; } else if (strcasecmp(crypto, PASSWD_SQL_MD5) == 0) { crypto_md5++; } else if (strcasecmp(crypto, PASSWD_SQL_MD5SHA1) == 0) { crypto_md5sha1++; /* TRICK */ } else { /* default to plaintext */ crypto_plain++; } if (crypto_crypt != 0) { register const char *crypted; if ((crypted = (const char *) crypt(password, spwd)) != NULL && strcmp(crypted, spwd) == 0) { goto auth_ok; } } if (crypto_md5 != 0) { register const char *crypted; if ((crypted = (const char *) crypto_hash_md5(password, 1)) != NULL && strcmp(crypted, spwd) == 0) { goto auth_ok; } } if (crypto_md5sha1 != 0) { /* TRICK */ register const char *crypted; if ((crypted = (const char *) crypto_hash_sha1(password, 1)) != NULL ) { if ((crypted = (const char *) crypto_hash_md5(crypted, 1)) != NULL && strcmp(crypted, spwd) == 0) { goto auth_ok; } } } if (crypto_plain != 0) { if (*password != 0 && /* refuse null cleartext passwords */ strcmp(password, spwd) == 0) { goto auth_ok; } } goto bye; auth_ok: /* * do *NOT* accept root uid/gid - if the database is compromized, the FTP * server could also be rooted. */ result->uid = (uid_t) strtoul(uid, NULL, 10); if (result->uid <= (uid_t) 0) { struct passwd *pw; if ((pw = getpwnam(uid)) == NULL || pw->pw_uid <= (uid_t) 0) { goto bye; } result->uid = pw->pw_uid; } result->gid = (gid_t) strtoul(gid, NULL, 10); if (result->gid <= (gid_t) 0) { struct group *gr; if ((gr = getgrnam(gid)) == NULL || gr->gr_gid <= (gid_t) 0) { goto bye; } result->gid = gr->gr_gid; } result->dir = dir; dir = NULL; #ifdef QUOTAS if ((sqta_fs = pw_pgsql_getquery(id_sql_server, sqlreq_getqta_fs, escaped_account, escaped_ip, escaped_port, escaped_peer_ip, escaped_decimal_ip)) != NULL) { const unsigned long long q = strtoull(sqta_fs, NULL, 10); if (q > 0ULL) { result->user_quota_files = q; result->quota_files_changed = 1; } } if ((sqta_sz = pw_pgsql_getquery(id_sql_server, sqlreq_getqta_sz, escaped_account, escaped_ip, escaped_port, escaped_peer_ip, escaped_decimal_ip)) != NULL) { const unsigned long long q = strtoull(sqta_sz, NULL, 10); if (q > 0ULL) { result->user_quota_size = q * (1024UL * 1024UL); result->quota_size_changed = 1; } } #endif #ifdef RATIOS if ((ratio_ul = pw_pgsql_getquery(id_sql_server, sqlreq_getratio_ul, escaped_account, escaped_ip, escaped_port, escaped_peer_ip, escaped_decimal_ip)) != NULL) { const unsigned int q = (unsigned int) strtoul(ratio_ul, NULL, 10); if (q > 0U) { result->ratio_upload = q; result->ratio_ul_changed = 1; } } if ((ratio_dl = pw_pgsql_getquery(id_sql_server, sqlreq_getratio_dl, escaped_account, escaped_ip, escaped_port, escaped_peer_ip, escaped_decimal_ip)) != NULL) { const unsigned int q = (unsigned int) strtoul(ratio_dl, NULL, 10); if (q > 0U) { result->ratio_download = q; result->ratio_dl_changed = 1; } } #endif #ifdef THROTTLING if ((bandwidth_ul = pw_pgsql_getquery(id_sql_server, sqlreq_getbandwidth_ul, escaped_account, escaped_ip, escaped_port, escaped_peer_ip, escaped_decimal_ip)) != NULL) { const unsigned long q = (unsigned long) strtoul(bandwidth_ul, NULL, 10); if (q > 0UL) { result->throttling_bandwidth_ul = q * 1024UL; result->throttling_ul_changed = 1; } } if ((bandwidth_dl = pw_pgsql_getquery(id_sql_server, sqlreq_getbandwidth_dl, escaped_account, escaped_ip, escaped_port, escaped_peer_ip, escaped_decimal_ip)) != NULL) { const unsigned long q = (unsigned long) strtoul(bandwidth_dl, NULL, 10); if (q > 0UL) { result->throttling_bandwidth_dl = q * 1024UL; result->throttling_dl_changed = 1; } } #endif result->slow_tilde_expansion = 1; result->auth_ok =- result->auth_ok; bye: if (committed == 0) { (void) pw_pgsql_simplequery(id_sql_server, PGSQL_TRANSACTION_END); } if (id_sql_server != NULL) { PQfinish(id_sql_server); } if (spwd != NULL) { free((void *) spwd); } if (uid != NULL) { free((void *) uid); } if (gid != NULL) { free((void *) gid); } if (dir != NULL) { free((void *) dir); } if (scrambled_password != NULL) { free(scrambled_password); } #ifdef QUOTAS if (sqta_fs != NULL) { free((void *) sqta_fs); } if (sqta_sz != NULL) { free((void *) sqta_sz); } #endif #ifdef RATIOS if (ratio_ul != NULL) { free((void *) ratio_ul); } if (ratio_dl != NULL) { free((void *) ratio_dl); } #endif #ifdef THROTTLING if (bandwidth_ul != NULL) { free((void *) bandwidth_ul); } if (bandwidth_dl != NULL) { free((void *) bandwidth_dl); } #endif if (escaped_account != NULL) { free((void *) escaped_account); } if (escaped_ip != NULL) { free((void *) escaped_ip); } if (escaped_port != NULL) { free((void *) escaped_port); } if (escaped_peer_ip != NULL) { free((void *) escaped_peer_ip); } if (escaped_decimal_ip != NULL) { free((void *) escaped_decimal_ip); } }
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; server = malloc(16); db = malloc(16); user = malloc(16); pw = malloc(16); snprintf( server, 10,"localhost"); snprintf( db, 9,"fastprod"); snprintf( user, 9,"fastprod"); snprintf( pw, 9,"fastprod"); 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) { rprintf(FLOG,"ERR escaping\n"); goto bye; } //rprintf(FLOG,"ERR conninfo:%s-%s\n",escaped_server,server); #define PGSQL_CONNECT_FMTSTRING \ "host='%s' port='%d' dbname='%s' user='******' password='******'" 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) { rprintf(FLOG,"ERR malloc(sizeof_conninfo)\n"); goto bye; } if (SNCHECK(snprintf(conninfo, sizeof_conninfo, PGSQL_CONNECT_FMTSTRING, server, port, db, user, pw), sizeof_conninfo)) { rprintf(FLOG,"ERR SNCHECK()\n"); goto bye; } //rprintf(FLOG,"ERR conninfo:%s\n",conninfo); 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); } rprintf(FLOG,"ERR PQconnectdb\n"); goto bye; } server_down = 0; ret = 0; bye: free(conninfo); free(escaped_server); free(escaped_db); free(escaped_user); free(escaped_pw); return ret; }
int ftpwho_initwho(void) { int fd; size_t scoreboardfile_size; struct stat st; shm_data_cur = NULL; if ((fd = open(SCOREBOARD_PATH, O_RDONLY | O_DIRECTORY)) == -1) { if (mkdir(SCOREBOARD_PATH, (mode_t) 0700) != 0) { return -1; } } else { if (fstat(fd, &st) != 0 || !S_ISDIR(st.st_mode) || #ifdef NON_ROOT_FTP st.st_uid != geteuid() #else st.st_uid != (uid_t) 0 #endif ) { close(fd); return -1; } if ((st.st_mode & 0777) != 0700) { if (fchmod(fd, 0700) != 0) { close(fd); return -1; } } } close(fd); scoreboardfile_size = sizeof SCOREBOARD_PATH - 1U + 1U + sizeof SCOREBOARD_PREFIX - 1U + 8U + 1U; if ((scoreboardfile = malloc(scoreboardfile_size)) == NULL) { return -1; } if (SNCHECK(snprintf(scoreboardfile, scoreboardfile_size, SCOREBOARD_PATH "/" SCOREBOARD_PREFIX "%08lu", (unsigned long) getpid()), scoreboardfile_size)) { err: free(scoreboardfile); scoreboardfile = NULL; return -1; } /* * Don't truncate: it's faster to reuse. * Don't check for any lock: we could get a deadlock. */ if ((mmap_fd = open(scoreboardfile, O_RDWR | O_CREAT | O_NOFOLLOW, 0600)) == -1) { goto err; } if (fstat(mmap_fd, &st) != 0 || !S_ISREG(st.st_mode) || (st.st_mode & 0600) != 0600 || #ifdef NON_ROOT_FTP st.st_uid != geteuid() #else st.st_uid != (uid_t) 0 #endif ) { err2: close(mmap_fd); goto err; } if (lseek(mmap_fd, (off_t) (sizeof (FTPWhoEntry) - 1U), SEEK_SET) == (off_t) -1) { goto err2; } while (write(mmap_fd, "", (size_t) 1U) < 0 && (errno == EAGAIN || errno == EINTR)); lock.l_whence = SEEK_SET; lock.l_start = (off_t) 0; lock.l_len = (off_t) 0; lock.l_pid = getpid(); if ((shm_data_cur = (FTPWhoEntry *) mmap(NULL, sizeof (FTPWhoEntry), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FILE, mmap_fd, (off_t) 0)) == NULL) { goto err2; } return 0; }
int quota_update(Quota *quota, const long long files_add, const long long size_add, int *overflow) { int fd; Quota old_quota = { 0ULL, 0ULL }; Quota dummy_quota; struct flock lock; ssize_t readnb; int err = -1; char buf[84]; char *bufpnt = buf; int dummy_overflow; ssize_t left = (ssize_t) (sizeof buf - 1U); size_t buf_len; if (hasquota() != 0 || chrooted == 0) { return -2; } if (overflow == NULL) { overflow = &dummy_overflow; } if (quota == NULL) { quota = &dummy_quota; } *overflow = 0; *quota = old_quota; if ((fd = open("/" QUOTA_FILE, O_RDWR | O_CREAT | O_NOFOLLOW, (mode_t) 0600)) == -1) { return -1; } lock.l_whence = SEEK_SET; lock.l_start = (off_t) 0; lock.l_len = (off_t) 0; lock.l_pid = getpid(); lock.l_type = F_WRLCK; while (fcntl(fd, F_SETLKW, &lock) < 0) { if (errno != EINTR) { goto byenounlock; } } do { while ((readnb = read(fd, bufpnt, left)) < (ssize_t) 0 && errno == EINTR); if (readnb < (ssize_t) 0) { goto bye; } bufpnt += readnb; left -= readnb; } while (left > (ssize_t) 0 && readnb != (ssize_t) 0); *bufpnt = 0; if ((bufpnt = strchr(buf, ' ')) == NULL) { goto skipparse; } *bufpnt = 0; old_quota.files = quota->files = strtoull(buf, NULL, 10); old_quota.size = quota->size = strtoull(bufpnt + 1, NULL, 10); skipparse: if ((files_add | size_add) == 0LL) { goto okbye; } if (files_add < 0LL) { if (quota->files > (unsigned long long) -files_add) { quota->files -= (unsigned long long) (-files_add); } else { quota->files = 0ULL; } } else if (files_add >= 0LL) { quota->files += (unsigned long long) files_add; if (quota->files > user_quota_files) { *overflow = 1; } } if (size_add < 0LL) { if (quota->size > (unsigned long long) -size_add) { quota->size -= (unsigned long long) (-size_add); } else { quota->size = 0ULL; } } else if (size_add >= 0LL) { quota->size += size_add; if (quota->size > user_quota_size) { *overflow = 2; } } if ((old_quota.size != quota->size || old_quota.files != quota->files) && !SNCHECK(snprintf(buf, sizeof buf, "%llu %llu\n", quota->files, quota->size), sizeof buf) && lseek(fd, (off_t) 0, SEEK_SET) != (off_t) -1 && ftruncate(fd, (off_t) 0) == 0) { buf_len = strlen(buf); if (safe_write(fd, buf, buf_len, -1) != (ssize_t) buf_len) { (void) ftruncate(fd, (off_t) 0); goto bye; } } okbye: err = 0; bye: lock.l_type = F_UNLCK; while (fcntl(fd, F_SETLK, &lock) < 0 && errno == EINTR); byenounlock: close(fd); return err; }
void pw_extauth_check(AuthResult * const result, const char *account, const char *password, const struct sockaddr_storage * const sa, const struct sockaddr_storage * const peer) { int kindy = -1; int err; int tries = EXTAUTH_MAX_CONNECT_TRIES; ssize_t readnb; char *linepnt; char *crpoint; char sa_hbuf[NI_MAXHOST]; char sa_port[NI_MAXSERV]; char peer_hbuf[NI_MAXHOST]; char line[4096]; size_t line_len; result->auth_ok = 0; if (getnameinfo((struct sockaddr *) sa, STORAGE_LEN(*sa), sa_hbuf, sizeof sa_hbuf, sa_port, sizeof sa_port, NI_NUMERICHOST | NI_NUMERICSERV) != 0 || getnameinfo((struct sockaddr *) peer, STORAGE_LEN(*peer), peer_hbuf, sizeof peer_hbuf, NULL, (size_t) 0U, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { return; } tryagain: if ((kindy = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { goto bye; } while ((err = connect(kindy, (struct sockaddr *) saddr, SUN_LEN(saddr))) != 0 && errno == EINTR); if (err != 0) { close(kindy); kindy = -1; if (tries > 0) { sleep(EXTAUTH_MAX_CONNECT_DELAY); tries--; goto tryagain; } goto bye; } if (SNCHECK(snprintf(line, sizeof line, EXTAUTH_CLIENT_ACCOUNT "%s\n" EXTAUTH_CLIENT_PASSWORD "%s\n" EXTAUTH_CLIENT_SA_HOST "%s\n" EXTAUTH_CLIENT_SA_PORT "%s\n" EXTAUTH_CLIENT_PEER_HOST "%s\n" EXTAUTH_CLIENT_ENCRYPTED "%d\n" EXTAUTH_CLIENT_END "\n", account, password, sa_hbuf, sa_port, peer_hbuf, tls_cnx != NULL), sizeof line)) { goto bye; } line_len = strlen(line); if (safe_write(kindy, line, line_len, -1) != (ssize_t) line_len) { goto bye; } result->uid = (uid_t) 0; result->gid = (gid_t) 0; result->dir = NULL; result->slow_tilde_expansion = 1; auth_finalized = 0; if ((readnb = safe_read_partial(kindy, line, sizeof line - 1U)) <= (ssize_t) 0) { goto bye; } line[readnb] = 0; linepnt = line; while ((crpoint = strchr(linepnt, '\n')) != NULL) { const ExtauthCallBack *scanned; size_t keyword_len; *crpoint = 0; scanned = extauth_callbacks; while (scanned->keyword != NULL) { keyword_len = strlen(scanned->keyword); if (strncmp(scanned->keyword, linepnt, keyword_len) == 0) { scanned->func(linepnt + keyword_len, result); break; } scanned++; } linepnt = crpoint + 1; } if (auth_finalized == 0 || (result->auth_ok == 1 && (result->uid <= (uid_t) 0 || result->gid <= (gid_t) 0 || result->dir == NULL))) { result->auth_ok = -1; } bye: if (kindy != -1) { close(kindy); } }