Replace SSL_write().

This commit is contained in:
Jim Hague 2018-11-15 15:00:19 +00:00
parent e7453522d5
commit 09019bee75
3 changed files with 60 additions and 19 deletions

View File

@ -404,6 +404,39 @@ getdns_return_t _getdns_tls_connection_read(_getdns_tls_connection* conn, uint8_
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_connection_write(_getdns_tls_connection* conn, uint8_t* buf, size_t to_write, size_t* written)
{
int swritten;
if (!conn || !conn->ssl || !written)
return -GETDNS_RETURN_INVALID_PARAMETER;
ERR_clear_error();
swritten = SSL_write(conn->ssl, buf, to_write);
if (swritten <= 0) {
switch(SSL_get_error(conn->ssl, swritten)) {
case SSL_ERROR_WANT_READ:
/* SSL_write will not do partial writes, because
* SSL_MODE_ENABLE_PARTIAL_WRITE is not default,
* but the write could fail because of renegotiation.
* In that case SSL_get_error() will return
* SSL_ERROR_WANT_READ or, SSL_ERROR_WANT_WRITE.
* Return for retry in such cases.
*/
return GETDNS_RETURN_TLS_WANT_READ;
case SSL_ERROR_WANT_WRITE:
return GETDNS_RETURN_TLS_WANT_WRITE;
default:
return GETDNS_RETURN_GENERIC_ERROR;
}
}
*written = swritten;
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_session_free(_getdns_tls_session* s)
{
if (!s || !s->ssl)

View File

@ -120,6 +120,21 @@ getdns_return_t _getdns_tls_connection_is_session_reused(_getdns_tls_connection*
*/
getdns_return_t _getdns_tls_connection_read(_getdns_tls_connection* conn, uint8_t* buf, size_t to_read, size_t* read);
/**
* Write to TLS.
*
* @param conn the connection.
* @param buf the buffer to write from.
* @param to_write the number of bytes to write.
* @param written the number of bytes written.
* @return GETDNS_RETURN_GOOD if some bytes were read.
* @return GETDNS_RETURN_INVALID_PARAMETER if conn is null or has no SSL.
* @return GETDNS_RETURN_TLS_WANT_READ if handshake isn't finished.
* @return GETDNS_RETURN_TLS_WANT_WRITE if the write needs to be retried.
* @return GETDNS_RETURN_GENERIC_ERROR if write failed.
*/
getdns_return_t _getdns_tls_connection_write(_getdns_tls_connection* conn, uint8_t* buf, size_t to_write, size_t* written);
getdns_return_t _getdns_tls_session_free(_getdns_tls_session* s);
getdns_return_t _getdns_tls_get_api_information(getdns_dict* dict);

View File

@ -1359,10 +1359,10 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
getdns_network_req *netreq)
{
size_t pkt_len;
ssize_t written;
size_t written;
uint16_t query_id;
intptr_t query_id_intptr;
SSL* tls_obj = upstream->tls_obj->ssl;
_getdns_tls_connection* tls_obj = upstream->tls_obj;
uint16_t padding_sz;
int q = tls_connected(upstream);
@ -1437,7 +1437,6 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
* Lets see how much of it we can write */
/* TODO[TLS]: Handle error cases, partial writes, renegotiation etc. */
ERR_clear_error();
#if INTERCEPT_COM_DS
/* Intercept and do not sent out COM DS queries. For debugging
* purposes only. Never commit with this turned on.
@ -1454,22 +1453,16 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
written = pkt_len + 2;
} else
#endif
written = SSL_write(tls_obj, netreq->query - 2, pkt_len + 2);
if (written <= 0) {
/* SSL_write will not do partial writes, because
* SSL_MODE_ENABLE_PARTIAL_WRITE is not default,
* but the write could fail because of renegotiation.
* In that case SSL_get_error() will return
* SSL_ERROR_WANT_READ or, SSL_ERROR_WANT_WRITE.
* Return for retry in such cases.
*/
switch (SSL_get_error(tls_obj, written)) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
return STUB_TCP_RETRY;
default:
return STUB_TCP_ERROR;
}
switch ((int)_getdns_tls_connection_write(tls_obj, netreq->query - 2, pkt_len + 2, &written)) {
case GETDNS_RETURN_GOOD:
break;
case GETDNS_RETURN_TLS_WANT_READ:
case GETDNS_RETURN_TLS_WANT_WRITE:
return STUB_TCP_RETRY;
default:
return STUB_TCP_ERROR;
}
/* We were able to write everything! Start reading. */
return (int) query_id;