<commit_before> /* 
 * File:   wbt_http.c
 * Author: Fcten
 *
 * Created on 2014年10月24日, 下午3:30
 */

#include "wbt_module.h"
#include "wbt_log.h"
#include "wbt_connection.h"
#include "wbt_config.h"
#include "wbt_ssl.h"

wbt_module_t wbt_module_ssl = {
    wbt_string("ssl"),
    wbt_ssl_init,
    wbt_ssl_exit,
    wbt_ssl_on_conn,
    NULL,
    NULL,
    wbt_ssl_on_close
};

SSL_CTX* ctx;

int wbt_ssl_ecdh_curve();

wbt_status wbt_ssl_init() {
    if( !wbt_conf.secure ) {
        return WBT_OK;
    }
    
    SSL_load_error_strings();     /*为打印调试信息作准备*/
    OpenSSL_add_ssl_algorithms(); /*初始化*/
    
    ctx = SSL_CTX_new(TLSv1_2_server_method());
    if (!ctx) {
        wbt_log_add("SSL_CTX_new failed\n");
        return WBT_ERROR;
    }
    
    // 设置为要求强制校验对方（客户端）证书SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT
    SSL_CTX_set_verify(ctx,SSL_VERIFY_NONE,NULL); /*验证与否SSL_VERIFY_PEER*/ 
    // SSL_CTX_load_verify_locations(ctx,CACERT,NULL);  /*若验证,则放置CA证书*/
    
    if (SSL_CTX_use_certificate_file(ctx, wbt_stdstr(&wbt_conf.secure_crt), SSL_FILETYPE_PEM) <= 0) {
        wbt_log_add("SSL_CTX_use_certificate_file failed\n");
        return WBT_ERROR;
    }
 
    if (SSL_CTX_use_PrivateKey_file(ctx, wbt_stdstr(&wbt_conf.secure_key), SSL_FILETYPE_PEM) <= 0) {
        wbt_log_add("SSL_CTX_use_PrivateKey_file failed\n");
        return WBT_ERROR;
    }
   
    if (!SSL_CTX_check_private_key(ctx)) {
        wbt_log_add("SSL_CTX_check_private_key failed\n");
        return WBT_ERROR;
    }
 
    if ( SSL_CTX_set_cipher_list(ctx,"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!CBC:!EDH:!kEDH:!PSK:!SRP:!kECDH") <= 0 ) {
        wbt_log_add("SSL_CTX_set_cipher_list failed\n");
        return WBT_ERROR;
    }
    
    SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
    
    if( wbt_ssl_ecdh_curve() != WBT_OK ) {
        return WBT_ERROR;
    }
    
    return WBT_OK;
}

wbt_status wbt_ssl_exit() {
    if( !wbt_conf.secure ) {
        return WBT_OK;
    }

    SSL_CTX_free (ctx);
    
    return WBT_OK;
}

wbt_status wbt_ssl_handshake(wbt_event_t *ev) {
    int n = SSL_do_handshake(ev->ssl);
    if( n == 1 ) {
        /*打印所有加密算法的信息(可选)*/ 
        printf ("SSL connection using %s\n", SSL_get_cipher (ev->ssl));

        ev->trigger = wbt_on_recv;
        ev->events = EPOLLIN | EPOLLET;
        ev->time_out = cur_mtime + WBT_CONN_TIMEOUT;

        if(wbt_event_mod(ev) != WBT_OK) {
            return WBT_ERROR;
        }
        
        return WBT_OK;
    }
    
    int err = SSL_get_error(ev->ssl, n);

    wbt_log_debug("SSL_get_error: %d", err);
    wbt_log_debug("Error: %s", ERR_reason_error_string(ERR_get_error()));

    if( err == SSL_ERROR_WANT_READ ) {
        ev->trigger = wbt_ssl_handshake;
        ev->events = EPOLLIN | EPOLLET;
        ev->time_out = cur_mtime + WBT_CONN_TIMEOUT;

        if(wbt_event_mod(ev) != WBT_OK) {
            return WBT_ERROR;
        }
        
        return WBT_OK;
    } else if( err == SSL_ERROR_WANT_WRITE ) {
        ev->trigger = wbt_ssl_handshake;
        ev->events = EPOLLOUT | EPOLLET;
        ev->time_out = cur_mtime + WBT_CONN_TIMEOUT;

        if(wbt_event_mod(ev) != WBT_OK) {
            return WBT_ERROR;
        }
        
        return WBT_OK;
    }
    
    // 握手异常，可能客户端在握手期间关闭了连接
    wbt_conn_close(ev);

    return WBT_OK;
}

wbt_status wbt_ssl_on_conn( wbt_event_t * ev ) {
    if( !wbt_conf.secure ) {
        return WBT_OK;
    }

    ev->ssl = SSL_new (ctx);
    if(!ev->ssl) {
        wbt_log_add("SSL_new failed\n");
        return WBT_ERROR;
    }

    if( SSL_set_fd (ev->ssl, ev->fd) == 0 ) {
        wbt_log_add("SSL_set_fd failed\n");
        return WBT_ERROR;
    }
    
    SSL_set_accept_state(ev->ssl);<commit_msg>Bugfix: 遇到 SSL_ERROR_SYSCALL 错误时应当继续等待事件<commit_after> /* 
 * File:   wbt_http.c
 * Author: Fcten
 *
 * Created on 2014年10月24日, 下午3:30
 */

#include "wbt_module.h"
#include "wbt_log.h"
#include "wbt_connection.h"
#include "wbt_config.h"
#include "wbt_ssl.h"

wbt_module_t wbt_module_ssl = {
    wbt_string("ssl"),
    wbt_ssl_init,
    wbt_ssl_exit,
    wbt_ssl_on_conn,
    NULL,
    NULL,
    wbt_ssl_on_close
};

SSL_CTX* ctx;

int wbt_ssl_ecdh_curve();

wbt_status wbt_ssl_init() {
    if( !wbt_conf.secure ) {
        return WBT_OK;
    }
    
    SSL_load_error_strings();     /*为打印调试信息作准备*/
    OpenSSL_add_ssl_algorithms(); /*初始化*/
    
    ctx = SSL_CTX_new(TLSv1_2_server_method());
    if (!ctx) {
        wbt_log_add("SSL_CTX_new failed\n");
        return WBT_ERROR;
    }
    
    // 设置为要求强制校验对方（客户端）证书SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT
    SSL_CTX_set_verify(ctx,SSL_VERIFY_NONE,NULL); /*验证与否SSL_VERIFY_PEER*/ 
    // SSL_CTX_load_verify_locations(ctx,CACERT,NULL);  /*若验证,则放置CA证书*/
    
    if (SSL_CTX_use_certificate_file(ctx, wbt_stdstr(&wbt_conf.secure_crt), SSL_FILETYPE_PEM) <= 0) {
        wbt_log_add("SSL_CTX_use_certificate_file failed\n");
        return WBT_ERROR;
    }
 
    if (SSL_CTX_use_PrivateKey_file(ctx, wbt_stdstr(&wbt_conf.secure_key), SSL_FILETYPE_PEM) <= 0) {
        wbt_log_add("SSL_CTX_use_PrivateKey_file failed\n");
        return WBT_ERROR;
    }
   
    if (!SSL_CTX_check_private_key(ctx)) {
        wbt_log_add("SSL_CTX_check_private_key failed\n");
        return WBT_ERROR;
    }
 
    if ( SSL_CTX_set_cipher_list(ctx,"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!CBC:!EDH:!kEDH:!PSK:!SRP:!kECDH") <= 0 ) {
        wbt_log_add("SSL_CTX_set_cipher_list failed\n");
        return WBT_ERROR;
    }
    
    SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
    
    if( wbt_ssl_ecdh_curve() != WBT_OK ) {
        return WBT_ERROR;
    }
    
    return WBT_OK;
}

wbt_status wbt_ssl_exit() {
    if( !wbt_conf.secure ) {
        return WBT_OK;
    }

    SSL_CTX_free (ctx);
    
    return WBT_OK;
}

wbt_status wbt_ssl_handshake(wbt_event_t *ev) {
    int n = SSL_do_handshake(ev->ssl);
    if( n == 1 ) {
        /*打印所有加密算法的信息(可选)*/ 
        printf ("SSL connection using %s\n", SSL_get_cipher (ev->ssl));

        ev->trigger = wbt_on_recv;
        ev->events = EPOLLIN | EPOLLET;
        ev->time_out = cur_mtime + WBT_CONN_TIMEOUT;

        if(wbt_event_mod(ev) != WBT_OK) {
            return WBT_ERROR;
        }
        
        return WBT_OK;
    }
    
    int err = SSL_get_error(ev->ssl, n);

    wbt_log_debug("SSL_get_error: %d", err);
    wbt_log_debug("Error: %s", ERR_reason_error_string(ERR_get_error()));

    if( err == SSL_ERROR_WANT_READ ) {
        ev->trigger = wbt_ssl_handshake;
        ev->events = EPOLLIN | EPOLLET;
        ev->time_out = cur_mtime + WBT_CONN_TIMEOUT;

        if(wbt_event_mod(ev) != WBT_OK) {
            return WBT_ERROR;
        }
        
        return WBT_OK;
    } else if( err == SSL_ERROR_WANT_WRITE ) {
        ev->trigger = wbt_ssl_handshake;
        ev->events = EPOLLOUT | EPOLLET;
        ev->time_out = cur_mtime + WBT_CONN_TIMEOUT;

        if(wbt_event_mod(ev) != WBT_OK) {
            return WBT_ERROR;
        }
        
        return WBT_OK;
    } else if( err == SSL_ERROR_SYSCALL ) {
        return WBT_OK;
    }
    
    // 握手异常，可能客户端在握手期间关闭了连接
    wbt_conn_close(ev);

    return WBT_OK;
}

wbt_status wbt_ssl_on_conn( wbt_event_t * ev ) {
    if( !wbt_conf.secure ) {
        return WBT_OK;
    }

    ev->ssl = SSL_new (ctx);
    if(!ev->ssl) {
        wbt_log_add("SSL_new failed\n");
        return WBT_ERROR;
    }

    if( SSL_set_fd (ev->ssl, ev->fd) == 0 ) {
        wbt_log_add("SSL_set_fd failed\n");
        return WBT_ERROR;
    }
    
    SSL_set_accept_state(ev->ssl);
{'fraction_non_alphanumeric': 0.12787849093581577, 'fraction_numerical': 0.018618324350808426, 'mean_word_length': 2.741979835013749, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3266020', 'n_tokens_mistral': 3741, 'n_tokens_neox': 3599, 'n_words': 430}