📄 ssl.c
字号:
{ int result; SSL_CTX *ctx; SSL *ssl; SSL_CIPHER *cipher; int algbits; int retry = 10; ctx = conn->context; if (! ctx) { ERR(("missing SSL context\n")); return -1; } ssl = conn->sock; if (! ssl) { ssl = SSL_new(ctx); conn->sock = ssl; } if (! ssl) { closesocket(fd); conn->fd = -1; ERR(("can't allocate ssl\n")); return -1; } SSL_set_fd(ssl, fd); SSL_set_app_data(ssl, conn); SSL_set_tmp_rsa_callback(ssl, ssl_get_temporary_RSA_key); /* set non-blocking i/o */#ifndef WIN32 { int flags; flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, O_NONBLOCK|flags); }#endif while (retry-- >= 0 && ! SSL_is_init_finished(ssl)) { fd_set read_mask; struct timeval timeout; timeout.tv_sec = 30; timeout.tv_usec = 0; FD_ZERO(&read_mask); FD_SET(fd, &read_mask); result = select(fd + 1, &read_mask, 0, 0, &timeout); if (result < 0 && (errno == EINTR || errno == EAGAIN)) continue; if (result <= 0) { ERR(("select timeout %d err:%d\n", result, errno)); } if (result > 0) {#ifdef THREADS result = SSL_accept(ssl);#else pthread_mutex_lock(conn->ssl_lock); result = SSL_accept(ssl); pthread_mutex_unlock(conn->ssl_lock);#endif } if (result > 0) { } else if (SSL_get_error(ssl, result) == SSL_ERROR_WANT_READ) continue; else if (result < 0) { ERR(("can't accept ssl %d response %d\n", result, SSL_get_error(ssl, result))); ERR_print_errors_fp(stderr); conn->sock = 0; conn->fd = -1; ssl_safe_free(fd, ssl); closesocket(fd); return -1; } } conn->fd = fd; cipher = SSL_get_current_cipher(ssl); if (cipher) { conn->ssl_cipher = (void *) SSL_CIPHER_get_name(cipher); conn->ssl_bits = SSL_CIPHER_get_bits(cipher, &algbits); } return 0;}static intssl_read(connection_t *conn, char *buf, int len){ fd_set read_mask; struct timeval timeout; int fd; int ms; SSL *ssl; int result; int retry = 100; int ssl_error = 0; int timeout_chunk = 5; int timeout_count; if (conn->fd < 0) return -1; if (! conn) return -1; fd = conn->fd; ms = conn->timeout; if (ms <= 0) timeout_count = (30 + timeout_chunk - 1) / timeout_chunk; else timeout_count = (ms / 1000 + timeout_chunk - 1) / timeout_chunk; if (timeout_count <= 0) timeout_count = 1; if (fd < 0) return -1; if (! conn->is_init) { conn->is_init = 1; if (ssl_open(conn, conn->fd) < 0) { conn->ops->close(conn); return -1; } } ssl = conn->sock; if (! ssl) return -1; while (retry-- > 0) { ssl_error = 0; result = SSL_read(ssl, buf, len); if (result >= 0) return result; else if ((ssl_error = SSL_get_error(ssl, result)) == SSL_ERROR_WANT_READ) { /* wait for data */ } else { /* fprintf(stderr, "disconnect from ssl error %d\n", ssl_error); */ return DISCONNECT_EXN; } do { FD_ZERO(&read_mask); FD_SET(fd, &read_mask); timeout.tv_sec = timeout_chunk; timeout.tv_usec = 0; result = select(fd + 1, &read_mask, 0, 0, &timeout); } while (result < 0 && (errno == EINTR || errno == EAGAIN) && retry-- > 0); if (result == 0 && --timeout_count <= 0) return TIMEOUT_EXN; else if (result < 0) return exception_status(conn, errno); } return exception_status(conn, errno);}static intssl_write(connection_t *conn, char *buf, int len){ SSL *ssl = conn->sock; fd_set write_mask; struct timeval timeout; int fd; int ms; int result; int retry = 100; if (! conn) return -1; if (conn->fd < 0) return -1; fd = conn->fd; if (! conn->is_init) { conn->is_init = 1; if (ssl_open(conn, conn->fd) < 0) { conn->ops->close(conn); return -1; } } ssl = conn->sock; result = SSL_write(ssl, buf, len); if (result > 0) return result; while (retry-- > 0) { ms = conn->timeout; FD_ZERO(&write_mask); FD_SET(fd, &write_mask); if (ms <= 0) { timeout.tv_sec = 30; timeout.tv_usec = 0; } else { timeout.tv_sec = ms / 1000; timeout.tv_usec = ms % 1000 * 1000; } result = select(fd + 1, 0, &write_mask, 0, &timeout); if (result > 0) { } else if (result == 0) { conn->ops->close(conn); return TIMEOUT_EXN; } else if (errno == EINTR || errno == EAGAIN) continue; else return exception_status(conn, errno); result = SSL_write(ssl, buf, len); if (result >= 0) return result; else continue; } return exception_status(conn, errno);}static intssl_close(connection_t *conn){ int fd; SSL *ssl; if (! conn) return 0; fd = conn->fd; conn->fd = -1; ssl = conn->sock; conn->sock = 0; ssl_safe_free(fd, ssl); if (fd > 0) closesocket(fd); conn_close(conn); return 0;}static voidssl_free(connection_t *conn){ SSL *ssl = conn->sock; conn->sock = 0; if (ssl) { pthread_mutex_lock(conn->ssl_lock); ssl_safe_free(-1, ssl); pthread_mutex_unlock(conn->ssl_lock); } std_free(conn);}/** * Sets certificate chain stuff. */static intset_certificate_chain(SSL_CTX *ctx, ssl_config_t *config){ /* Not sure how this is supposed to work. */}intssl_create(server_socket_t *ss, ssl_config_t *config){ ss->ssl_config = config; ss->verify_client = config->verify_client; ss->context = ssl_create_context(config); ss->accept = ssl_accept; return 1;}static intssl_read_client_certificate(connection_t *conn, char *buffer, int length){ BIO *bio; int n; X509 *cert; if (! conn) return -1; if (! conn->is_init) { conn->is_init = 1; if (ssl_open(conn, conn->fd) < 0) { conn->ops->close(conn); return -1; } } cert = SSL_get_peer_certificate(conn->sock); if (! cert) return -1; if ((bio = BIO_new(BIO_s_mem())) == NULL) return -1; PEM_write_bio_X509(bio, cert); n = BIO_pending(bio); if (n <= length) n = BIO_read(bio, buffer, n); BIO_free(bio); return n;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -