void pw_extauth_parse(const char * const file) { size_t file_len; if (file == NULL || (file_len = strlen(file)) <= (size_t) 0U) { return; } if ((saddr = malloc(sizeof(*saddr) + file_len + (size_t) 1U)) == NULL) { die_mem(); } memcpy(saddr->sun_path, file, file_len + (size_t) 1U); saddr->sun_family = AF_UNIX; }
int init_aliases(void) { FILE *fp; char alias[MAXALIASLEN + 1U]; char dir[PATH_MAX + 1U]; if ((fp = fopen(ALIASES_FILE, "r")) == NULL) { return 0; } while (fgets(alias, sizeof alias, fp) != NULL) { if (*alias == '#' || *alias == '\n' || *alias == 0) { continue; } { char * const z = alias + strlen(alias) - 1U; if (*z != '\n') { goto bad; } *z = 0; } do { if (fgets(dir, sizeof dir, fp) == NULL || *dir == 0) { goto bad; } { char * const z = dir + strlen(dir) - 1U; if (*z == '\n') { *z = 0; } } } while (*dir == '#' || *dir == 0); if (head == NULL) { if ((head = tail = malloc(sizeof *head)) == NULL || (tail->alias = strdup(alias)) == NULL || (tail->dir = strdup(dir)) == NULL) { die_mem(); } tail->next = NULL; } else { DirAlias *curr; if ((curr = malloc(sizeof *curr)) == NULL || (curr->alias = strdup(alias)) == NULL || (curr->dir = strdup(dir)) == NULL) { die_mem(); } tail->next = curr; tail = curr; } } fclose(fp); aliases_up++; return 0; bad: fclose(fp); logfile(LOG_ERR, MSG_ALIASES_BROKEN_FILE " [" ALIASES_FILE "]"); return -1; }
static struct passwd *pw_ldap_getpwnam(const char *name, AuthResult * const result) { static struct passwd pwret; LDAP *ld; LDAPMessage *res; char *attrs[] = { /* OpenLDAP forgot a 'const' ... */ LDAP_HOMEDIRECTORY, LDAP_UIDNUMBER, LDAP_FTPUID, LDAP_GIDNUMBER, LDAP_FTPGID, LDAP_USERPASSWORD, LDAP_LOGINSHELL, LDAP_FTPSTATUS, # ifdef QUOTAS LDAP_QUOTAFILES, LDAP_QUOTAMBYTES, # endif # ifdef RATIOS LDAP_DOWNLOADRATIO, LDAP_UPLOADRATIO, # endif #ifdef THROTTLING LDAP_DOWNLOADBANDWIDTH, LDAP_UPLOADBANDWIDTH, #endif NULL }; const char *pw_uid_s = NULL; const char *pw_gid_s = NULL; const char *pw_passwd_ldap = NULL; const char *pw_enabled = NULL; #ifdef QUOTAS const char *quota_files = NULL; const char *quota_mbytes = NULL; #endif #ifdef RATIOS const char *ratio_ul = NULL; const char *ratio_dl = NULL; #endif #ifdef THROTTLING const char *bandwidth_ul = NULL; const char *bandwidth_dl = NULL; #endif memset(&pwret, 0, sizeof pwret); pwret.pw_name = pwret.pw_passwd = pwret.pw_gecos = pwret.pw_dir = pwret.pw_shell = NULL; pwret.pw_uid = (uid_t) 0; pwret.pw_gid = (gid_t) 0; if (pw_ldap_validate_name(name) != 0) { return NULL; } if ((ld = pw_ldap_connect(binddn, pwd)) == NULL) { return NULL; } attrs[0] = ldap_homedirectory; if ((res = pw_ldap_uid_search(ld, name, attrs)) == NULL) { goto error; } pw_ldap_getpwnam_freefields(&pwret); pwret.pw_name = (char *) name; pw_enabled = pw_ldap_getvalue(ld, res, LDAP_FTPSTATUS); if (pw_enabled != NULL && strcasecmp(pw_enabled, "enabled") != 0 && strcasecmp(pw_enabled, "TRUE") != 0) { goto error; } free((void *) pw_enabled); pw_enabled = NULL; #ifdef QUOTAS if ((quota_files = pw_ldap_getvalue(ld, res, LDAP_QUOTAFILES)) != NULL) { const unsigned long long q = strtoull(quota_files, NULL, 10); if (q > 0ULL) { result->user_quota_files = q; result->quota_files_changed = 1; } } if ((quota_mbytes = pw_ldap_getvalue(ld, res, LDAP_QUOTAMBYTES)) != NULL) { const unsigned long long q = strtoull(quota_mbytes, NULL, 10); if (q > 0ULL) { result->user_quota_size = q * (1024UL * 1024UL); result->quota_size_changed = 1; } } #endif #ifdef RATIOS if ((ratio_dl = pw_ldap_getvalue(ld, res, LDAP_DOWNLOADRATIO)) != NULL) { const unsigned int q = strtoul(ratio_dl, NULL, 10); if (q > 0U) { result->ratio_download = q; result->ratio_dl_changed = 1; } } if ((ratio_ul = pw_ldap_getvalue(ld, res, LDAP_UPLOADRATIO)) != NULL) { const unsigned int q = strtoul(ratio_ul, NULL, 10); if (q > 0U) { result->ratio_upload = q; result->ratio_ul_changed = 1; } } #endif #ifdef THROTTLING if ((bandwidth_dl = pw_ldap_getvalue(ld, res, LDAP_DOWNLOADBANDWIDTH)) != 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; } } if ((bandwidth_ul = pw_ldap_getvalue(ld, res, LDAP_UPLOADBANDWIDTH)) != 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; } } #endif if (use_ldap_bind_method == 0) { if ((pw_passwd_ldap = pw_ldap_getvalue(ld, res, LDAP_USERPASSWORD)) == NULL) { /* The LDAP userPassword is empty, this happens when binding to LDAP without sufficient privileges. */ logfile(LOG_WARNING, MSG_WARN_LDAP_USERPASS_EMPTY); goto error; } pwret.pw_passwd = strdup(pw_passwd_ldap); free((void *) pw_passwd_ldap); pw_passwd_ldap = NULL; } else { pwret.pw_passwd = strdup(""); } if (pwret.pw_passwd == NULL) { logfile(LOG_ERR, MSG_OUT_OF_MEMORY); goto error; } /* only force the uid if default_uid has been set */ if (!force_default_uid && default_uid > 0) { if ((pw_uid_s = pw_ldap_getvalue(ld, res, LDAP_FTPUID)) == NULL || *pw_uid_s == 0 || (pwret.pw_uid = (uid_t) strtoul(pw_uid_s, NULL, 10)) <= (uid_t) 0) { free((void *) pw_uid_s); pw_uid_s = NULL; if ((pw_uid_s = pw_ldap_getvalue(ld, res, LDAP_UIDNUMBER)) == NULL || *pw_uid_s == 0 || (pwret.pw_uid = (uid_t) strtoul(pw_uid_s, NULL, 10)) <= (uid_t) 0) { pwret.pw_uid = default_uid; } } } else { pwret.pw_uid = default_uid; } free((void *) pw_uid_s); pw_uid_s = NULL; /* only force the gid if default_gid has been set */ if (!force_default_gid && default_gid > 0) { if ((pw_gid_s = pw_ldap_getvalue(ld, res, LDAP_FTPGID)) == NULL || *pw_gid_s == 0 || (pwret.pw_gid = (gid_t) strtoul(pw_gid_s, NULL, 10)) <= (gid_t) 0) { free((void *) pw_gid_s); pw_gid_s = NULL; if ((pw_gid_s = pw_ldap_getvalue(ld, res, LDAP_GIDNUMBER)) == NULL || *pw_gid_s == 0 || (pwret.pw_gid = (gid_t) strtoul(pw_gid_s, NULL, 10)) <= (gid_t) 0) { pwret.pw_gid = default_gid; } } } else { pwret.pw_gid = default_gid; } free((void *) pw_gid_s); pw_gid_s = NULL; if ((pwret.pw_dir = pw_ldap_getvalue(ld, res, ldap_homedirectory)) == NULL || *pwret.pw_dir == 0) { if (ldap_default_home_directory == NULL || *ldap_default_home_directory == 0) { goto error; } if ((pwret.pw_dir = strdup(ldap_default_home_directory)) == NULL) { die_mem(); } } if ((pwret.pw_shell = pw_ldap_getvalue(ld, res, LDAP_LOGINSHELL)) == NULL) { pwret.pw_shell = strdup(DEFAULT_SHELL); } result->backend_data = ldap_get_dn(ld, res); ldap_msgfree(res); ldap_unbind(ld); return &pwret; error: if (res != NULL) { ldap_msgfree(res); } ldap_unbind(ld); pw_ldap_getpwnam_freefields(&pwret); free((void *) pw_uid_s); free((void *) pw_gid_s); free((void *) pw_passwd_ldap); free((void *) pw_enabled); #ifdef QUOTAS free((void *) quota_files); free((void *) quota_mbytes); #endif #ifdef RATIOS free((void *) ratio_ul); free((void *) ratio_dl); #endif #ifdef THROTTLING free((void *) bandwidth_ul); free((void *) bandwidth_dl); #endif return NULL; }
void pw_ldap_parse(const char * const file) { if (generic_parser(file, ldap_config_keywords) != 0) { illegal_config: die(421, LOG_ERR, MSG_CONF_ERR ": " MSG_ILLEGAL_CONFIG_FILE_LDAP ": %s" , file == NULL ? "-" : file); } if (ldap_scheme == NULL) { if ((ldap_scheme = strdup(LDAP_DEFAULT_SCHEME)) == NULL) { die_mem(); } } if (ldap_host == NULL) { if ((ldap_host = strdup(LDAP_DEFAULT_SERVER)) == NULL) { die_mem(); } } if (port_s == NULL) { port = LDAP_DEFAULT_PORT; } else { port = atoi(port_s); if (port <= 0 || port > 65535) { port = LDAP_DEFAULT_PORT; } free(port_s); port_s = NULL; } if (ldap_filter == NULL) { if ((ldap_filter = strdup(LDAP_DEFAULT_FILTER)) == NULL) { die_mem(); } } { char *t; if (strchr(ldap_filter, '%') != NULL) { goto illegal_config; } if ((t = strchr(ldap_filter, '\\')) != NULL) { if (t[1] != 'L') { goto illegal_config; } *t++ = '%'; *t = 's'; } } if (ldap_homedirectory == NULL) { if ((ldap_homedirectory = strdup(LDAP_HOMEDIRECTORY)) == NULL) { die_mem(); } } if (ldap_version_s != NULL) { ldap_version = atoi(ldap_version_s); free(ldap_version_s); ldap_version_s = NULL; } else { ldap_version = LDAP_DEFAULT_VERSION; } if (default_uid_s != NULL) { default_uid = (uid_t) strtoul(default_uid_s, NULL, 10); free(default_uid_s); default_uid_s = NULL; } if (default_gid_s != NULL) { default_gid = (gid_t) strtoul(default_gid_s, NULL, 10); free(default_gid_s); default_gid_s = NULL; } if (force_default_uid_s != NULL) { if (strcasecmp(force_default_uid_s, "True") == 0) { force_default_uid = 1; } free(force_default_uid_s); force_default_uid_s = NULL; } if (force_default_gid_s != NULL) { if (strcasecmp(force_default_gid_s, "True") == 0) { force_default_gid = 1; } free(force_default_gid_s); force_default_gid_s = NULL; } use_tls = 0; if (use_tls_s != NULL) { if (strcasecmp(use_tls_s, "True") == 0) { use_tls = 1; } free(use_tls_s); use_tls_s = NULL; } /* Build ldap URI string */ ldap_uri = NULL; { const size_t sizeof_ldap_uri = strlen(ldap_scheme) + sizeof URI_SCHEME_SEPARATOR - 1U + sizeof URI_AUTHORITY_LEADER - 1U + strlen(ldap_host) + sizeof URI_PORT_LEADER - 1U + 5U + /* string representation of port; 5 digits at most */ 1U; /* null byte */ if ((ldap_uri = malloc(sizeof_ldap_uri)) == NULL) { die_mem(); } snprintf(ldap_uri, sizeof_ldap_uri, "%s%s%s%s%s%d", ldap_scheme, URI_SCHEME_SEPARATOR, URI_AUTHORITY_LEADER, ldap_host, URI_PORT_LEADER, port); } /* Default to auth method bind, but for backward compatibility, if a binddn * is supplied, default to password checking. */ if (binddn == NULL) { use_ldap_bind_method = 1; } else { use_ldap_bind_method = 0; } if (ldap_auth_method_s != NULL) { if (strcasecmp(ldap_auth_method_s, "bind") == 0) { use_ldap_bind_method = 1; } else if (strcasecmp(ldap_auth_method_s, "password") == 0) { use_ldap_bind_method = 0; } else { die(421, LOG_ERR, MSG_LDAP_INVALID_AUTH_METHOD); } free(ldap_auth_method_s); ldap_auth_method_s = NULL; } if (base == NULL) { die(421, LOG_ERR, MSG_LDAP_MISSING_BASE); } if (binddn == NULL) { pwd = NULL; } }
static int ssl_servername_cb(SSL *cnx, int *al, void *arg) { CertResult result; const char *sni_name; (void) al; (void) arg; if ((sni_name = SSL_get_servername(cnx, TLSEXT_NAMETYPE_host_name)) == NULL || *sni_name == 0 || validate_sni_name(sni_name) != 0) { return SSL_TLSEXT_ERR_NOACK; } logfile(LOG_INFO, "SNI: [%s]", sni_name); if (chrooted != 0 || loggedin != 0) { return SSL_TLSEXT_ERR_NOACK; } if (use_extcert == 0) { return SSL_TLSEXT_ERR_OK; } memset(&result, 0, sizeof result); tls_extcert_get(&result, sni_name); if (result.cert_ok != 1) { die(400, LOG_ERR, "Cert handler not ready"); } if (result.action == CERT_ACTION_DENY) { die(400, LOG_INFO, MSG_LOGOUT); } if (result.action == CERT_ACTION_DEFAULT) { return SSL_TLSEXT_ERR_OK; } if (result.cert_file == NULL) { if (result.action == CERT_ACTION_STRICT) { die(400, LOG_ERR, "Missing certificate"); } else { return SSL_TLSEXT_ERR_OK; } } if (result.key_file == NULL) { result.key_file = result.cert_file; } SSL_CTX_free(tls_ctx); tls_ctx = NULL; if (tls_create_new_context(result.cert_file, result.key_file) != 0) { if (result.action != CERT_ACTION_FALLBACK) { die(400, LOG_ERR, "Invalid certificate"); } if (tls_create_new_context(cert_file, key_file) != 0) { die(400, LOG_ERR, "SSL error"); } } if ((client_sni_name = strdup(sni_name)) == NULL) { die_mem(); } if (tls_cnx != NULL) { const long ctx_options = SSL_CTX_get_options(tls_ctx); SSL_set_SSL_CTX(tls_cnx, tls_ctx); # ifdef SSL_CTRL_CLEAR_OPTIONS SSL_clear_options(tls_cnx, SSL_get_options(tls_cnx) & ~ctx_options); # endif SSL_set_options(tls_cnx, ctx_options); } if (tls_data_cnx != NULL) { const long ctx_options = SSL_CTX_get_options(tls_ctx); SSL_set_SSL_CTX(tls_data_cnx, tls_ctx); # ifdef SSL_CTRL_CLEAR_OPTIONS SSL_clear_options(tls_data_cnx, SSL_get_options(tls_cnx) & ~ctx_options); # endif SSL_set_options(tls_data_cnx, ctx_options); } return SSL_TLSEXT_ERR_OK; }
static int tls_load_dhparams_default(void) { # ifdef HAVE_DH_GET_2048_256 DH *dh; if ((dh = DH_get_2048_256()) == NULL) { die_mem(); } # else # if BN_BITS2 == 64 static const BN_ULONG dh2048_256_p[] = { 0xDB094AE91E1A1597ULL, 0x693877FAD7EF09CAULL, 0x6116D2276E11715FULL, 0xA4B54330C198AF12ULL, 0x75F26375D7014103ULL, 0xC3A3960A54E710C3ULL, 0xDED4010ABD0BE621ULL, 0xC0B857F689962856ULL, 0xB3CA3F7971506026ULL, 0x1CCACB83E6B486F6ULL, 0x67E144E514056425ULL, 0xF6A167B5A41825D9ULL, 0x3AD8347796524D8EULL, 0xF13C6D9A51BFA4ABULL, 0x2D52526735488A0EULL, 0xB63ACAE1CAA6B790ULL, 0x4FDB70C581B23F76ULL, 0xBC39A0BF12307F5CULL, 0xB941F54EB1E59BB8ULL, 0x6C5BFC11D45F9088ULL, 0x22E0B1EF4275BF7BULL, 0x91F9E6725B4758C0ULL, 0x5A8A9D306BCF67EDULL, 0x209E0C6497517ABDULL, 0x3BF4296D830E9A7CULL, 0x16C3D91134096FAAULL, 0xFAF7DF4561B2AA30ULL, 0xE00DF8F1D61957D4ULL, 0x5D2CEED4435E3B00ULL, 0x8CEEF608660DD0F2ULL, 0xFFBBD19C65195999ULL, 0x87A8E61DB4B6663CULL }; static const BN_ULONG dh2048_256_g[] = { 0x664B4C0F6CC41659ULL, 0x5E2327CFEF98C582ULL, 0xD647D148D4795451ULL, 0x2F63078490F00EF8ULL, 0x184B523D1DB246C3ULL, 0xC7891428CDC67EB6ULL, 0x7FD028370DF92B52ULL, 0xB3353BBB64E0EC37ULL, 0xECD06E1557CD0915ULL, 0xB7D2BBD2DF016199ULL, 0xC8484B1E052588B9ULL, 0xDB2A3B7313D3FE14ULL, 0xD052B985D182EA0AULL, 0xA4BD1BFFE83B9C80ULL, 0xDFC967C1FB3F2E55ULL, 0xB5045AF2767164E1ULL, 0x1D14348F6F2F9193ULL, 0x64E67982428EBC83ULL, 0x8AC376D282D6ED38ULL, 0x777DE62AAAB8A862ULL, 0xDDF463E5E9EC144BULL, 0x0196F931C77A57F2ULL, 0xA55AE31341000A65ULL, 0x901228F8C28CBB18ULL, 0xBC3773BF7E8C6F62ULL, 0xBE3A6C1B0C6B47B1ULL, 0xFF4FED4AAC0BB555ULL, 0x10DBC15077BE463FULL, 0x07F4793A1A0BA125ULL, 0x4CA7B18F21EF2054ULL, 0x2E77506660EDBD48ULL, 0x3FB32C9B73134D0BULL }; static const BN_ULONG dh2048_256_q[] = { 0xA308B0FE64F5FBD3ULL, 0x99B1A47D1EB3750BULL, 0xB447997640129DA2ULL, 0x8CF83642A709A097ULL }; # elif BN_BITS2 == 32 static const BN_ULONG dh2048_256_p[] = { 0x1E1A1597, 0xDB094AE9, 0xD7EF09CA, 0x693877FA, 0x6E11715F, 0x6116D227, 0xC198AF12, 0xA4B54330, 0xD7014103, 0x75F26375, 0x54E710C3, 0xC3A3960A, 0xBD0BE621, 0xDED4010A, 0x89962856, 0xC0B857F6, 0x71506026, 0xB3CA3F79, 0xE6B486F6, 0x1CCACB83, 0x14056425, 0x67E144E5, 0xA41825D9, 0xF6A167B5, 0x96524D8E, 0x3AD83477, 0x51BFA4AB, 0xF13C6D9A, 0x35488A0E, 0x2D525267, 0xCAA6B790, 0xB63ACAE1, 0x81B23F76, 0x4FDB70C5, 0x12307F5C, 0xBC39A0BF, 0xB1E59BB8, 0xB941F54E, 0xD45F9088, 0x6C5BFC11, 0x4275BF7B, 0x22E0B1EF, 0x5B4758C0, 0x91F9E672, 0x6BCF67ED, 0x5A8A9D30, 0x97517ABD, 0x209E0C64, 0x830E9A7C, 0x3BF4296D, 0x34096FAA, 0x16C3D911, 0x61B2AA30, 0xFAF7DF45, 0xD61957D4, 0xE00DF8F1, 0x435E3B00, 0x5D2CEED4, 0x660DD0F2, 0x8CEEF608, 0x65195999, 0xFFBBD19C, 0xB4B6663C, 0x87A8E61D }; static const BN_ULONG dh2048_256_g[] = { 0x6CC41659, 0x664B4C0F, 0xEF98C582, 0x5E2327CF, 0xD4795451, 0xD647D148, 0x90F00EF8, 0x2F630784, 0x1DB246C3, 0x184B523D, 0xCDC67EB6, 0xC7891428, 0x0DF92B52, 0x7FD02837, 0x64E0EC37, 0xB3353BBB, 0x57CD0915, 0xECD06E15, 0xDF016199, 0xB7D2BBD2, 0x052588B9, 0xC8484B1E, 0x13D3FE14, 0xDB2A3B73, 0xD182EA0A, 0xD052B985, 0xE83B9C80, 0xA4BD1BFF, 0xFB3F2E55, 0xDFC967C1, 0x767164E1, 0xB5045AF2, 0x6F2F9193, 0x1D14348F, 0x428EBC83, 0x64E67982, 0x82D6ED38, 0x8AC376D2, 0xAAB8A862, 0x777DE62A, 0xE9EC144B, 0xDDF463E5, 0xC77A57F2, 0x0196F931, 0x41000A65, 0xA55AE313, 0xC28CBB18, 0x901228F8, 0x7E8C6F62, 0xBC3773BF, 0x0C6B47B1, 0xBE3A6C1B, 0xAC0BB555, 0xFF4FED4A, 0x77BE463F, 0x10DBC150, 0x1A0BA125, 0x07F4793A, 0x21EF2054, 0x4CA7B18F, 0x60EDBD48, 0x2E775066, 0x73134D0B, 0x3FB32C9B }; static const BN_ULONG dh2048_256_q[] = { 0x64F5FBD3, 0xA308B0FE, 0x1EB3750B, 0x99B1A47D, 0x40129DA2, 0xB4479976, 0xA709A097, 0x8CF83642 }; # else # error "unsupported BN_BITS2" # endif static const BIGNUM p = { (BN_ULONG *) dh2048_256_p, sizeof(dh2048_256_p) / sizeof(BN_ULONG), sizeof(dh2048_256_p) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA }; static const BIGNUM g = { (BN_ULONG *) dh2048_256_g, sizeof(dh2048_256_g) / sizeof(BN_ULONG), sizeof(dh2048_256_g) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA }; static const BIGNUM q = { (BN_ULONG *) dh2048_256_q, sizeof(dh2048_256_q) / sizeof(BN_ULONG), sizeof(dh2048_256_q) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA }; DH *dh; if ((dh = DH_new()) == NULL) { die_mem(); } dh->p = BN_dup(&p); dh->g = BN_dup(&g); dh->q = BN_dup(&q); if (dh->p == NULL || dh->g == NULL || dh->q == NULL) { DH_free(dh); die_mem(); } # endif SSL_CTX_set_tmp_dh(tls_ctx, dh); DH_free(dh); # ifdef SSL_OP_SINGLE_DH_USE SSL_CTX_set_options(tls_ctx, SSL_OP_SINGLE_DH_USE); # endif return 0; }