static char *
ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_stream_ssl_conf_t  *scf = conf;
    ngx_str_t  *value;
    if (scf->passwords != NGX_CONF_UNSET_PTR)
    {
        return "is duplicate";
    }
    value = cf->args->elts;
    scf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
    if (scf->passwords == NULL)
    {
        return NGX_CONF_ERROR;
    }
    return NGX_CONF_OK;
}
static char *
ngx_rtmp_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_rtmp_ssl_srv_conf_t *prev = parent;
    ngx_rtmp_ssl_srv_conf_t *conf = child;

    ngx_pool_cleanup_t  *cln;
    ngx_array_t         *passwords = NULL;

    conf->ssl.log = cf->log;

    if (!conf->enable) {
        return NGX_CONF_OK;
    }

    ngx_conf_merge_str_value(conf->certificate, prev->certificate, "");
    if (conf->certificate.len == 0) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Missing ssl_certificate");
        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, "");
    if (conf->certificate_key.len == 0) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Missing ssl_certificate_key");
        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
                                 NGX_CONF_BITMASK_SET
                                 |NGX_RTMPS_DEFAULT_PROTOCOLS);

    ngx_conf_merge_str_value(conf->password_file, prev->password_file, "");

    ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");

    ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
                             NGX_RTMPS_DEFAULT_ECDH_CURVE);

    ngx_conf_merge_str_value(conf->ciphers, prev->ciphers,
                             NGX_RTMPS_DEFAULT_CIPHERS);

    ngx_conf_merge_value(conf->prefer_server_ciphers,
                         prev->prefer_server_ciphers, 0);

    if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    cln = ngx_pool_cleanup_add(cf->pool, 0);
    if (cln == NULL) {
        return NGX_CONF_ERROR;
    }

    cln->handler = ngx_ssl_cleanup_ctx;
    cln->data = &conf->ssl;

    if (conf->password_file.len > 0) {
        passwords = ngx_ssl_read_password_file(cf, &conf->password_file);
        if (passwords == NULL) {
            return NGX_CONF_ERROR;
        }
    }

    if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
                            &conf->certificate_key, passwords)
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    if (SSL_CTX_set_cipher_list(conf->ssl.ctx,
                                (const char *) conf->ciphers.data)
        == 0)
    {
        ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
                      "SSL_CTX_set_cipher_list(%V) failed", &conf->ciphers);
        return NGX_CONF_ERROR;
    }

    if (conf->prefer_server_ciphers) {
        SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
    }

    if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);

    return NGX_CONF_OK;
}