diff options
author | Andrew Bartlett <abartlet@samba.org> | 2012-07-18 15:28:50 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2012-07-18 11:23:55 +0200 |
commit | d0d05f8474ed1882d373f042aba2c0209247678a (patch) | |
tree | 88b39ca2b2519743559f3dae1d66278fecc1d124 /source4/lib/tls | |
parent | 02a356ea775a3ba589cb50af3c861ab86aaffa0b (diff) | |
download | samba-d0d05f8474ed1882d373f042aba2c0209247678a.tar.gz samba-d0d05f8474ed1882d373f042aba2c0209247678a.tar.bz2 samba-d0d05f8474ed1882d373f042aba2c0209247678a.zip |
s4-lib/tls: Try socket_send() multiple times to send partial packets
This works around an artificial limitation in socket_wrapper that breaks
some versions of GnuTLS when we return a short write.
Instead, keep pushing until the OS will not take it.
The correct solution will be to use tls_tstream, but the client code
for this is not yet tested and needs the ldap client layer changed
to use it.
Andrew Bartlett
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Wed Jul 18 11:23:55 CEST 2012 on sn-devel-104
Diffstat (limited to 'source4/lib/tls')
-rw-r--r-- | source4/lib/tls/tls.c | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c index 7bf2ff8e43..db6d1eb5de 100644 --- a/source4/lib/tls/tls.c +++ b/source4/lib/tls/tls.c @@ -152,7 +152,7 @@ static ssize_t tls_push(gnutls_transport_ptr ptr, const void *buf, size_t size) { struct tls_context *tls = talloc_get_type(ptr, struct tls_context); NTSTATUS status; - size_t nwritten; + size_t nwritten, total_nwritten = 0; DATA_BLOB b; if (!tls->tls_enabled) { @@ -162,19 +162,32 @@ static ssize_t tls_push(gnutls_transport_ptr ptr, const void *buf, size_t size) b.data = discard_const(buf); b.length = size; - status = socket_send(tls->socket, &b, &nwritten); - if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { - errno = EAGAIN; - return -1; - } - if (!NT_STATUS_IS_OK(status)) { - TEVENT_FD_WRITEABLE(tls->fde); - return -1; - } - if (size != nwritten) { + /* Cope with socket_wrapper 1500 byte chunking for PCAP */ + do { + status = socket_send(tls->socket, &b, &nwritten); + + if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { + errno = EAGAIN; + return -1; + } + if (!NT_STATUS_IS_OK(status)) { + TEVENT_FD_WRITEABLE(tls->fde); + return -1; + } + + total_nwritten += nwritten; + + if (size == nwritten) { + break; + } + + b.data += nwritten; + b.length -= nwritten; + TEVENT_FD_WRITEABLE(tls->fde); - } - return nwritten; + } while (b.length); + + return total_nwritten; } /* |