Fix bugs with large (>16384 bytes) sends with tls.
This commit is contained in:
16
src/event.c
16
src/event.c
@@ -42,7 +42,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
|||||||
int ret;
|
int ret;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
xmpp_send_queue_t *sq, *tsq;
|
xmpp_send_queue_t *sq, *tsq;
|
||||||
size_t towrite;
|
int towrite;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
uint64_t next;
|
uint64_t next;
|
||||||
|
|
||||||
@@ -58,6 +58,19 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if we're running tls, there may be some remaining data waiting to
|
||||||
|
* be sent, so push that out */
|
||||||
|
if (conn->tls) {
|
||||||
|
ret = tls_clear_pending_write(conn->tls);
|
||||||
|
|
||||||
|
if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls))) {
|
||||||
|
/* an error occured */
|
||||||
|
xmpp_debug(ctx, "xmpp", "Send error occured, disconnecting.");
|
||||||
|
conn->error = ECONNABORTED;
|
||||||
|
conn_disconnect(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sq = conn->send_queue_head;
|
sq = conn->send_queue_head;
|
||||||
while (sq) {
|
while (sq) {
|
||||||
towrite = sq->len - sq->written;
|
towrite = sq->len - sq->written;
|
||||||
@@ -74,6 +87,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
|||||||
if (ret >= 0) sq->written += ret;
|
if (ret >= 0) sq->written += ret;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ret = sock_write(conn->sock, &sq->data[sq->written], towrite);
|
ret = sock_write(conn->sock, &sq->data[sq->written], towrite);
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,22 @@ tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock)
|
|||||||
int ret;
|
int ret;
|
||||||
ALG_ID algs[1];
|
ALG_ID algs[1];
|
||||||
|
|
||||||
|
SecPkgCred_SupportedAlgs spc_sa;
|
||||||
|
SecPkgCred_CipherStrengths spc_cs;
|
||||||
|
SecPkgCred_SupportedProtocols spc_sp;
|
||||||
|
|
||||||
|
OSVERSIONINFO osvi;
|
||||||
|
|
||||||
|
memset(&osvi, 0, sizeof(osvi));
|
||||||
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||||
|
|
||||||
|
GetVersionEx(&osvi);
|
||||||
|
|
||||||
|
/* no TLS support on win9x/me, despite what anyone says */
|
||||||
|
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
tls = xmpp_alloc(ctx, sizeof(*tls));
|
tls = xmpp_alloc(ctx, sizeof(*tls));
|
||||||
|
|
||||||
if (!tls) {
|
if (!tls) {
|
||||||
@@ -78,27 +94,33 @@ tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock)
|
|||||||
tls->sock = sock;
|
tls->sock = sock;
|
||||||
|
|
||||||
if (!(tls->hsec32 = LoadLibrary ("secur32.dll"))) {
|
if (!(tls->hsec32 = LoadLibrary ("secur32.dll"))) {
|
||||||
|
tls_free(tls);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pInitSecurityInterface =
|
if (!(pInitSecurityInterface =
|
||||||
(void *)GetProcAddress(tls->hsec32, "InitSecurityInterfaceA"))) {
|
(void *)GetProcAddress(tls->hsec32, "InitSecurityInterfaceA"))) {
|
||||||
FreeLibrary(tls->hsec32);
|
tls_free(tls);
|
||||||
tls->hsec32 = NULL;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls->sft = pInitSecurityInterface();
|
tls->sft = pInitSecurityInterface();
|
||||||
|
|
||||||
if (!tls->sft) {
|
if (!tls->sft) {
|
||||||
tls->sft = NULL;
|
tls_free(tls);
|
||||||
FreeLibrary(tls->hsec32);
|
|
||||||
tls->hsec32 = NULL;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = tls->sft->QuerySecurityPackageInfo(UNISP_NAME, &(tls->spi));
|
ret = tls->sft->QuerySecurityPackageInfo(UNISP_NAME, &(tls->spi));
|
||||||
|
|
||||||
|
if (ret != SEC_E_OK)
|
||||||
|
{
|
||||||
|
tls_free(tls);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmpp_debug(ctx, "TLSS", "QuerySecurityPackageInfo() success");
|
||||||
|
|
||||||
memset(&scred, 0, sizeof(scred));
|
memset(&scred, 0, sizeof(scred));
|
||||||
scred.dwVersion = SCHANNEL_CRED_VERSION;
|
scred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||||
/*scred.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT;*/
|
/*scred.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT;*/
|
||||||
@@ -107,10 +129,42 @@ tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock)
|
|||||||
scred.cSupportedAlgs = 1;
|
scred.cSupportedAlgs = 1;
|
||||||
scred.palgSupportedAlgs = algs;
|
scred.palgSupportedAlgs = algs;
|
||||||
|
|
||||||
tls->sft->AcquireCredentialsHandleA(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND,
|
ret = tls->sft->AcquireCredentialsHandleA(NULL, UNISP_NAME,
|
||||||
NULL, &scred, NULL, NULL, &(tls->hcred), NULL);
|
SECPKG_CRED_OUTBOUND, NULL, &scred, NULL, NULL, &(tls->hcred), NULL);
|
||||||
|
|
||||||
|
if (ret != SEC_E_OK)
|
||||||
|
{
|
||||||
|
tls_free(tls);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmpp_debug(ctx, "TLSS", "AcquireCredentialsHandle() success");
|
||||||
|
|
||||||
tls->init = 1;
|
tls->init = 1;
|
||||||
|
|
||||||
|
/* This bunch of queries should trip up wine until someone fixes
|
||||||
|
* schannel support there */
|
||||||
|
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_ALGS, &spc_sa);
|
||||||
|
if (ret != SEC_E_OK)
|
||||||
|
{
|
||||||
|
tls_free(tls);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_CIPHER_STRENGTHS, &spc_cs);
|
||||||
|
if (ret != SEC_E_OK)
|
||||||
|
{
|
||||||
|
tls_free(tls);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_PROTOCOLS, &spc_sp);
|
||||||
|
if (ret != SEC_E_OK)
|
||||||
|
{
|
||||||
|
tls_free(tls);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return tls;
|
return tls;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,9 +513,8 @@ int tls_read(tls_t *tls, void * const buff, const size_t len)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tls_clear_pending_write(tls_t *tls)
|
int tls_clear_pending_write(tls_t *tls)
|
||||||
{
|
{
|
||||||
/* clear pending writes first */
|
|
||||||
if (tls->sendbufferpos < tls->sendbufferlen)
|
if (tls->sendbufferpos < tls->sendbufferlen)
|
||||||
{
|
{
|
||||||
int bytes;
|
int bytes;
|
||||||
@@ -551,7 +604,7 @@ int tls_write(tls_t *tls, const void * const buff, const size_t len)
|
|||||||
|
|
||||||
ret = tls_clear_pending_write(tls);
|
ret = tls_clear_pending_write(tls);
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1 && !tls_is_recoverable(tls_error(tls))) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,7 +616,7 @@ int tls_write(tls_t *tls, const void * const buff, const size_t len)
|
|||||||
remain = 0;
|
remain = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0 || (ret == -1 && tls_is_recoverable(tls_error(tls)))) {
|
||||||
return sent;
|
return sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user