int conn_tls_start(xmpp_conn_t * const conn) { int rc; if (conn->tls_disabled) { conn->tls = NULL; rc = -ENOSYS; } else { conn->tls = tls_new(conn->ctx, conn->sock); rc = conn->tls == NULL ? -ENOMEM : 0; } if (conn->tls != NULL) { if (tls_start(conn->tls)) { conn->secured = 1; conn_prepare_reset(conn, auth_handle_open); } else { rc = tls_error(conn->tls); conn->error = rc; tls_free(conn->tls); conn->tls = NULL; conn->tls_failed = 1; } } if (rc != 0) xmpp_debug(conn->ctx, "conn", "Couldn't start TLS! error %d", rc); return rc; }
static int _handle_proceedtls_default(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { char *name; name = xmpp_stanza_get_name(stanza); xmpp_debug(conn->ctx, "xmpp", "handle proceedtls called for %s", name); if (strcmp(name, "proceed") == 0) { xmpp_debug(conn->ctx, "xmpp", "proceeding with TLS"); conn->tls = tls_new(conn->ctx, conn->sock); if (!tls_start(conn->tls)) { xmpp_debug(conn->ctx, "xmpp", "Couldn't start TLS! error %d", tls_error(conn->tls)); tls_free(conn->tls); conn->tls = NULL; conn->tls_failed = 1; /* failed tls spoils the connection, so disconnect */ xmpp_disconnect(conn); } else { conn->secured = 1; conn_prepare_reset(conn, auth_handle_open); conn_open_stream(conn); } } return 0; }
int conn_tls_start(xmpp_conn_t * const conn) { int rc; if (conn->tls_disabled) { conn->tls = NULL; rc = XMPP_EINVOP; } else { conn->tls = tls_new(conn); rc = conn->tls == NULL ? XMPP_EMEM : 0; } if (conn->tls != NULL) { if (tls_start(conn->tls)) { conn->secured = 1; } else { rc = XMPP_EINT; conn->error = tls_error(conn->tls); tls_free(conn->tls); conn->tls = NULL; conn->tls_failed = 1; } } if (rc != 0) { xmpp_debug(conn->ctx, "conn", "Couldn't start TLS! " "error %d tls_error %d", rc, conn->error); } return rc; }
static int start_tls(void *user) { if (!in_tls && use_tls) { memset(&tls, 0, sizeof(tls)); tls.recv = tcp_recv; tls.send = tcp_send; if (tls_start(&tls)) return -1; in_tls = 1; } return 0; }
static int start_tls(void *user) { struct xmpp *xmpp = (struct xmpp *)user; if (!in_tls) { memset(&tls, 0, sizeof(tls)); tls.user = xmpp->io_context; tls.recv = tcp_recv; tls.send = tcp_send; if (tls_start(&tls)) { fprintf(stderr, "err: TLS start failure\n"); return -1; } in_tls = 1; } return 0; }
int tls_read(tls_t *tls, void * const buff, const size_t len) { int bytes; /* first, if we've got some ready data, put that in the buffer */ if (tls->readybufferpos < tls->readybufferlen) { if (len < tls->readybufferlen - tls->readybufferpos) { bytes = len; } else { bytes = tls->readybufferlen - tls->readybufferpos; } memcpy(buff, tls->readybuffer + tls->readybufferpos, bytes); if (len < tls->readybufferlen - tls->readybufferpos) { tls->readybufferpos += bytes; return bytes; } else { unsigned char *newbuff = buff; int read; tls->readybufferpos += bytes; newbuff += bytes; read = tls_read(tls, newbuff, len - bytes); if (read == -1) { if (tls_is_recoverable(tls->lasterror)) { return bytes; } return -1; } return bytes + read; } } /* next, top up our recv buffer */ bytes = sock_read(tls->sock, tls->recvbuffer + tls->recvbufferpos, tls->recvbuffermaxlen - tls->recvbufferpos); if (bytes == 0) { tls->lasterror = WSAECONNRESET; return -1; } if (bytes == -1) { if (!tls_is_recoverable(sock_error())) { tls->lasterror = sock_error(); return -1; } } if (bytes > 0) { tls->recvbufferpos += bytes; } /* next, try to decrypt the recv buffer */ if (tls->recvbufferpos > 0) { SecBufferDesc sbddec; SecBuffer sbdec[4]; int ret; memset(&sbddec, 0, sizeof(sbddec)); sbddec.ulVersion = SECBUFFER_VERSION; sbddec.cBuffers = 4; sbddec.pBuffers = sbdec; memset(&(sbdec[0]), 0, sizeof(sbdec[0])); sbdec[0].BufferType = SECBUFFER_DATA; sbdec[0].pvBuffer = tls->recvbuffer; sbdec[0].cbBuffer = tls->recvbufferpos; memset(&(sbdec[1]), 0, sizeof(sbdec[1])); sbdec[1].BufferType = SECBUFFER_EMPTY; memset(&(sbdec[2]), 0, sizeof(sbdec[2])); sbdec[2].BufferType = SECBUFFER_EMPTY; memset(&(sbdec[3]), 0, sizeof(sbdec[3])); sbdec[3].BufferType = SECBUFFER_EMPTY; ret = tls->sft->DecryptMessage(&(tls->hctxt), &sbddec, 0, NULL); if (ret == SEC_E_OK) { memcpy(tls->readybuffer, sbdec[1].pvBuffer, sbdec[1].cbBuffer); tls->readybufferpos = 0; tls->readybufferlen = sbdec[1].cbBuffer; /* have we got some data left over? If so, copy it to the start * of the recv buffer */ if (sbdec[3].BufferType == SECBUFFER_EXTRA) { memcpy(tls->recvbuffer, sbdec[3].pvBuffer, sbdec[3].cbBuffer); tls->recvbufferpos = sbdec[3].cbBuffer; } else { tls->recvbufferpos = 0; } return tls_read(tls, buff, len); } else if (ret == SEC_E_INCOMPLETE_MESSAGE) { tls->lasterror = SEC_E_INCOMPLETE_MESSAGE; return -1; } else if (ret == SEC_I_RENEGOTIATE) { ret = tls_start(tls); if (!ret) { return -1; } /* fake an incomplete message so we're called again */ tls->lasterror = SEC_E_INCOMPLETE_MESSAGE; return -1; } /* something bad happened, so we bail */ tls->lasterror = ret; return -1; } tls->lasterror = SEC_E_INCOMPLETE_MESSAGE; return -1; }