Пример #1
0
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;    
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
    }
}
Пример #5
0
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;
}
Пример #6
0
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;
}