Fix bugs with large (>16384 bytes) sends with tls.

This commit is contained in:
James Canete
2008-05-14 21:09:31 +00:00
parent 77e3b1be77
commit ce235002c5
2 changed files with 80 additions and 13 deletions

View File

@@ -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);

View File

@@ -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;
} }