2017-01-30 101 views
1

我在Linux上使用OpenSSL 1.0.0-fips。我遇到的問題是SSL_connect()正在返回-1,而SSL_get_error()正在返回SSL_ERROR_WANT_READ。然後我把文件描述符放入select()timeval結構設置爲10秒,select()剛剛超時。使用OpenSSL BIO的非阻塞I/O

我解僱了Wireshark,我看到「Client Hello」出來,我看到ServerHello回到客戶端,但它從未在select()中「醒來」。它只是超時。

我的問題是:

  1. 我必須使用BIO_new_socket()創建BIO對象,然後用SSL_set_bio()的BIO對象分配給我的SSL對象? SSL_set_fd()的手冊頁說它會自動創建一個BIO對象,這似乎意味着SSL_set_bio()是一種無用的函數,你永遠不需要調用它。

  2. 讓我們假設我們使用SSL_set_fd()並分配一個阻塞的連接的TCP文件描述符。假設我們稍後使用fcntl()將該文件描述符更改爲非阻塞。這是否會破壞SSL對象(或底層的BIO對象)?

+0

您應該可能會顯示一些代碼,包括如何設置上下文。異步I/O和非阻塞套接字給人們帶來了相當多的麻煩,因爲庫不太適應。查看['apps/ocsp.c'](https://github.com/openssl/openssl/blob/master/apps/ocsp.c)的源代碼,瞭解OpenSSL如何實現它。我似乎想起正常的上下文是在阻塞模式下設置的,然後使用底層套接字切換到非阻塞模式。搜索調用「BIO_get_fd」和「select」的代碼。 AFAIK,它是自我記錄代碼中非阻塞I/O的唯一例子:) – jww

+1

我沒有發佈代碼,因爲我實現的C++ SSL Socket類的整個連接函數非常大。但是,我發現我的問題。我忘記將1添加到select()的maxfd參數。 –

回答

1

1)我一定要創建一個使用BIO_new_socket(),然後 一個BIO對象使用SSL_set_bio的BIO對象分配給我的SSL對象()? SSL_set_fd()的頁面 表示它會自動創建一個BIO對象 ,這似乎意味着SSL_set_bio()是一種無用的 函數,您無需真正調用該函數。

如果默認BIO對象是足以滿足您的需求,那麼你就不必手動創建和安裝自己的BIO對象。 SSL_set_bio()調用是爲了防止您想創建/使用與SSL_set_bio()代表您創建的默認對象不同的BIO對象。

2)讓我們說我們使用SSL_set_fd()並分配一個連接的TCP文件 阻塞描述符。假設我們稍後使用fcntl()將該文件描述符更改爲非阻塞。這是否會破壞SSL 對象(或底層的BIO對象)?

是的,我相信它會打破。非阻塞OpenSSL的調用模式與阻塞OpenSSL的調用模式非常不同,我不相信您可以隨時在一種模式中來回切換。也就是說,我沒有自己嘗試過,所以我可能是錯的,但我認爲要安全起見(並保持一致),您應該選擇預先決定是否要使用阻塞或非阻塞I/O並在連接期間堅持使用它。

特別是,這句話從該名男子頁:

的BIO,因此SSL引擎繼承FD的行爲。

...建議SSL設置調用將檢查fd的狀態,並根據fd的阻塞/非阻塞狀態在BIO和SSL對象內設置私有變量。如果你「落後於OpenSSL的後面」並改變fd的行爲,那麼OpenSSL的例程不會期望這樣做,並且很可能會做錯誤的事情並且不能正常工作。

+0

因此,我在我的C++ SSL Socket類中編寫的連接函數使用SSL_set_fd()將文件描述符分配給SSL對象,然後使用fnctl()將文件描述符設置爲非阻塞,並且它工作得很好。我甚至可以將其切換回阻塞狀態,並且SSL層的行爲方式我期望它的行爲。所以,這些文檔似乎是誤導性的,或者它可能只是運氣好像它正在按我希望的方式工作。 –