📄 ssl.c
字号:
SSL_free(p_ssl); p_sess->p_data_ssl = NULL; } return success;}intssl_accept(struct vsf_session* p_sess, int fd){ /* SECURITY: data SSL connections don't have any auth on them as part of the * protocol. If a client sends an unfortunately optional client cert then * we can check for a match between the control and data connections. */ SSL* p_ssl; int reused; if (p_sess->p_data_ssl != NULL) { die("p_data_ssl should be NULL."); } p_ssl = get_ssl(p_sess, fd); if (p_ssl == NULL) { return 0; } p_sess->p_data_ssl = p_ssl; setup_bio_callbacks(p_ssl); reused = SSL_session_reused(p_ssl); if (tunable_require_ssl_reuse && !reused) { str_alloc_text(&debug_str, "No SSL session reuse on data channel."); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); ssl_data_close(p_sess); return 0; } if (str_getlen(&p_sess->control_cert_digest) > 0) { static struct mystr data_cert_digest; if (!ssl_cert_digest(p_ssl, p_sess, &data_cert_digest)) { str_alloc_text(&debug_str, "Missing cert on data channel."); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); ssl_data_close(p_sess); return 0; } if (str_strcmp(&p_sess->control_cert_digest, &data_cert_digest)) { str_alloc_text(&debug_str, "DIFFERENT cert on data channel."); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); ssl_data_close(p_sess); return 0; } if (tunable_debug_ssl) { str_alloc_text(&debug_str, "Matching cert on data channel."); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } } return 1;}voidssl_comm_channel_init(struct vsf_session* p_sess){ if (p_sess->ssl_consumer_fd != -1) { bug("ssl_consumer_fd active"); } if (p_sess->ssl_slave_fd != -1) { bug("ssl_slave_fd active"); } const struct vsf_sysutil_socketpair_retval retval = vsf_sysutil_unix_stream_socketpair(); p_sess->ssl_consumer_fd = retval.socket_one; p_sess->ssl_slave_fd = retval.socket_two;}voidssl_comm_channel_set_consumer_context(struct vsf_session* p_sess){ if (p_sess->ssl_slave_fd == -1) { bug("ssl_slave_fd already closed"); } vsf_sysutil_close(p_sess->ssl_slave_fd); p_sess->ssl_slave_fd = -1;}voidssl_comm_channel_set_producer_context(struct vsf_session* p_sess){ if (p_sess->ssl_consumer_fd == -1) { bug("ssl_consumer_fd already closed"); } vsf_sysutil_close(p_sess->ssl_consumer_fd); p_sess->ssl_consumer_fd = -1;}static SSL*get_ssl(struct vsf_session* p_sess, int fd){ SSL* p_ssl = SSL_new(p_sess->p_ssl_ctx); if (p_ssl == NULL) { if (tunable_debug_ssl) { str_alloc_text(&debug_str, "SSL_new failed"); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } return NULL; } if (!SSL_set_fd(p_ssl, fd)) { if (tunable_debug_ssl) { str_alloc_text(&debug_str, "SSL_set_fd failed"); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } SSL_free(p_ssl); return NULL; } if (SSL_accept(p_ssl) != 1) { const char* p_err = get_ssl_error(); if (tunable_debug_ssl) { str_alloc_text(&debug_str, "SSL_accept failed: "); str_append_text(&debug_str, p_err); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } /* The RFC is quite clear that we can just close the control channel * here. */ die(p_err); } if (tunable_debug_ssl) { const char* p_ssl_version = SSL_get_cipher_version(p_ssl); SSL_CIPHER* p_ssl_cipher = SSL_get_current_cipher(p_ssl); const char* p_cipher_name = SSL_CIPHER_get_name(p_ssl_cipher); X509* p_ssl_cert = SSL_get_peer_certificate(p_ssl); int reused = SSL_session_reused(p_ssl); str_alloc_text(&debug_str, "SSL version: "); str_append_text(&debug_str, p_ssl_version); str_append_text(&debug_str, ", SSL cipher: "); str_append_text(&debug_str, p_cipher_name); if (reused) { str_append_text(&debug_str, ", reused"); } else { str_append_text(&debug_str, ", not reused"); } if (p_ssl_cert != NULL) { str_append_text(&debug_str, ", CERT PRESENTED"); X509_free(p_ssl_cert); } else { str_append_text(&debug_str, ", no cert"); } vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } return p_ssl;}static intssl_session_init(struct vsf_session* p_sess){ SSL* p_ssl = get_ssl(p_sess, VSFTP_COMMAND_FD); if (p_ssl == NULL) { return 0; } p_sess->p_control_ssl = p_ssl; (void) ssl_cert_digest(p_ssl, p_sess, &p_sess->control_cert_digest); setup_bio_callbacks(p_ssl); return 1;}static intssl_cert_digest(SSL* p_ssl, struct vsf_session* p_sess, struct mystr* p_str){ X509* p_cert = SSL_get_peer_certificate(p_ssl); unsigned int num_bytes = 0; if (p_cert == NULL) { return 0; } str_reserve(p_str, EVP_MAX_MD_SIZE); str_empty(p_str); str_rpad(p_str, EVP_MAX_MD_SIZE); if (!X509_digest(p_cert, EVP_sha256(), (unsigned char*) str_getbuf(p_str), &num_bytes)) { die("X509_digest failed"); } X509_free(p_cert); if (tunable_debug_ssl) { unsigned int i; str_alloc_text(&debug_str, "Cert digest:"); for (i = 0; i < num_bytes; ++i) { str_append_char(&debug_str, ' '); str_append_ulong( &debug_str, (unsigned long) (unsigned char) str_get_char_at(p_str, i)); } vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } str_trunc(p_str, num_bytes); return 1;}static char*get_ssl_error(){ SSL_load_error_strings(); return ERR_error_string(ERR_get_error(), NULL);}static void setup_bio_callbacks(SSL* p_ssl){ BIO* p_bio = SSL_get_rbio(p_ssl); BIO_set_callback(p_bio, bio_callback); p_bio = SSL_get_wbio(p_ssl); BIO_set_callback(p_bio, bio_callback);}static longbio_callback( BIO* p_bio, int oper, const char* p_arg, int argi, long argl, long ret){ int retval = 0; int fd = 0; (void) p_arg; (void) argi; (void) argl; if (oper == (BIO_CB_READ | BIO_CB_RETURN) || oper == (BIO_CB_WRITE | BIO_CB_RETURN)) { retval = (int) ret; fd = BIO_get_fd(p_bio, NULL); } vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, fd); return ret;}static intssl_verify_callback(int verify_ok, X509_STORE_CTX* p_ctx){ (void) p_ctx; if (tunable_validate_cert) { return verify_ok; } return 1;}voidssl_add_entropy(struct vsf_session* p_sess){ /* Although each child does seem to have its different pool of entropy, I * don't trust the interaction of OpenSSL's opaque RAND API and fork(). So * throw a bit more in (only works on systems with /dev/urandom for now). */ int ret = RAND_load_file("/dev/urandom", 16); if (ret != 16) { str_alloc_text(&debug_str, "Couldn't add extra OpenSSL entropy: "); str_append_ulong(&debug_str, (unsigned long) ret); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); }}#else /* VSF_BUILD_SSL */voidssl_init(struct vsf_session* p_sess){ (void) p_sess; die("SSL: ssl_enable is set but SSL support not compiled in");}voidssl_control_handshake(struct vsf_session* p_sess){ (void) p_sess;}voidhandle_auth(struct vsf_session* p_sess){ (void) p_sess;}voidhandle_pbsz(struct vsf_session* p_sess){ (void) p_sess;}voidhandle_prot(struct vsf_session* p_sess){ (void) p_sess;}intssl_read(struct vsf_session* p_sess, void* p_ssl, char* p_buf, unsigned int len){ (void) p_sess; (void) p_ssl; (void) p_buf; (void) len; return -1;}intssl_peek(struct vsf_session* p_sess, void* p_ssl, char* p_buf, unsigned int len){ (void) p_sess; (void) p_ssl; (void) p_buf; (void) len; return -1;}intssl_write(void* p_ssl, const char* p_buf, unsigned int len){ (void) p_ssl; (void) p_buf; (void) len; return -1;}intssl_write_str(void* p_ssl, const struct mystr* p_str){ (void) p_ssl; (void) p_str; return -1;}intssl_accept(struct vsf_session* p_sess, int fd){ (void) p_sess; (void) fd; return -1;}intssl_data_close(struct vsf_session* p_sess){ (void) p_sess; return 1;}voidssl_comm_channel_init(struct vsf_session* p_sess){ (void) p_sess;}voidssl_comm_channel_set_consumer_context(struct vsf_session* p_sess){ (void) p_sess;}voidssl_comm_channel_set_producer_context(struct vsf_session* p_sess){ (void) p_sess;}voidssl_add_entropy(struct vsf_session* p_sess){ (void) p_sess;}intssl_read_into_str(struct vsf_session* p_sess, void* p_ssl, struct mystr* p_str){ (void) p_sess; (void) p_ssl; (void) p_str; return -1;}#endif /* VSF_BUILD_SSL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -