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