Added OpenSSL support.
Added win32-specific srv lookup support. Extend session timeout to 15 seconds.
This commit is contained in:
88
src/auth.c
88
src/auth.c
@@ -27,10 +27,11 @@
|
||||
/* FIXME: these should be configurable */
|
||||
#define FEATURES_TIMEOUT 2000 /* 2 seconds */
|
||||
#define BIND_TIMEOUT 2000 /* 2 seconds */
|
||||
#define SESSION_TIMEOUT 2000 /* 2 seconds */
|
||||
#define SESSION_TIMEOUT 15000 /* 15 seconds */
|
||||
#define LEGACY_TIMEOUT 2000 /* 2 seconds */
|
||||
|
||||
static void _auth(xmpp_conn_t * const conn);
|
||||
static void _handle_open_tls(xmpp_conn_t * const conn);
|
||||
static void _handle_open_sasl(xmpp_conn_t * const conn);
|
||||
static int _handle_missing_legacy(xmpp_conn_t * const conn,
|
||||
void * const userdata);
|
||||
@@ -89,8 +90,13 @@ static int _handle_error(xmpp_conn_t * const conn,
|
||||
if (conn->stream_error) {
|
||||
child = xmpp_stanza_get_children(stanza);
|
||||
do {
|
||||
if (child && strcmp(xmpp_stanza_get_ns(child),
|
||||
XMPP_NS_STREAMS_IETF) == 0) {
|
||||
char *ns = NULL;
|
||||
|
||||
if (child) {
|
||||
ns = xmpp_stanza_get_ns(child);
|
||||
}
|
||||
|
||||
if (ns && strcmp(ns, XMPP_NS_STREAMS_IETF) == 0) {
|
||||
name = xmpp_stanza_get_name(child);
|
||||
if (strcmp(name, "text") == 0) {
|
||||
if (conn->stream_error->text)
|
||||
@@ -203,7 +209,7 @@ static int _handle_features(xmpp_conn_t * const conn,
|
||||
/* TODO: Implement TLS */
|
||||
|
||||
_auth(conn);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -222,6 +228,36 @@ static char *_get_authid(xmpp_conn_t * const conn)
|
||||
return authid;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
parser_prepare_reset(conn, _handle_open_tls);
|
||||
|
||||
conn->tls = tls_new(conn->ctx, conn->sock);
|
||||
|
||||
if (!tls_start(conn->tls))
|
||||
{
|
||||
xmpp_debug(conn->ctx, "xmpp", "Couldn't start TLS!");
|
||||
}
|
||||
else
|
||||
{
|
||||
conn_open_stream(conn);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int _handle_digestmd5_default(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
@@ -393,6 +429,20 @@ static int _handle_plain(xmpp_conn_t * const conn,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmpp_stanza_t *_make_starttls(xmpp_conn_t * const conn)
|
||||
{
|
||||
xmpp_stanza_t *starttls;
|
||||
|
||||
/* build start stanza */
|
||||
starttls = xmpp_stanza_new(conn->ctx);
|
||||
if (starttls) {
|
||||
xmpp_stanza_set_name(starttls, "starttls");
|
||||
xmpp_stanza_set_ns(starttls, XMPP_NS_TLS);
|
||||
}
|
||||
|
||||
return starttls;
|
||||
}
|
||||
|
||||
static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t * const conn,
|
||||
const char * const mechanism)
|
||||
{
|
||||
@@ -418,7 +468,25 @@ static void _auth(xmpp_conn_t * const conn)
|
||||
xmpp_stanza_t *auth, *authdata, *query, *child, *iq;
|
||||
char *str, *authid;
|
||||
|
||||
if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
|
||||
if (conn->tls_support)
|
||||
{
|
||||
auth = _make_starttls(conn);
|
||||
|
||||
if (!auth) {
|
||||
disconnect_mem_error(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
handler_add(conn, _handle_proceedtls_default,
|
||||
XMPP_NS_TLS, NULL, NULL, NULL);
|
||||
|
||||
xmpp_send(conn, auth);
|
||||
xmpp_stanza_release(auth);
|
||||
|
||||
/* TLS was tried, unset flag */
|
||||
conn->tls_support = 0;
|
||||
}
|
||||
else if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
|
||||
auth = _make_sasl_auth(conn, "DIGEST-MD5");
|
||||
if (!auth) {
|
||||
disconnect_mem_error(conn);
|
||||
@@ -592,6 +660,16 @@ void auth_handle_open(xmpp_conn_t * const conn)
|
||||
FEATURES_TIMEOUT, NULL);
|
||||
}
|
||||
|
||||
/* called when stream:stream tag received after TLS connection */
|
||||
static void _handle_open_tls(xmpp_conn_t * const conn)
|
||||
{
|
||||
xmpp_debug(conn->ctx, "xmpp", "TLS successful, proceeding with SASL");
|
||||
|
||||
/* go straight to SASL auth */
|
||||
_auth(conn);
|
||||
}
|
||||
|
||||
|
||||
/* called when stream:stream tag received after SASL auth */
|
||||
static void _handle_open_sasl(xmpp_conn_t * const conn)
|
||||
{
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "strophe.h"
|
||||
#include "sock.h"
|
||||
#include "tls.h"
|
||||
#include "hash.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -157,6 +158,7 @@ struct _xmpp_conn_t {
|
||||
int error;
|
||||
xmpp_stream_error_t *stream_error;
|
||||
sock_t sock;
|
||||
tls_t *tls;
|
||||
|
||||
int tls_support;
|
||||
int sasl_support; /* if true, field is a bitfield of supported
|
||||
|
||||
15
src/conn.c
15
src/conn.c
@@ -41,6 +41,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx)
|
||||
|
||||
conn->type = XMPP_UNKNOWN;
|
||||
conn->sock = -1;
|
||||
conn->tls = NULL;
|
||||
conn->timeout_stamp = 0;
|
||||
conn->error = 0;
|
||||
conn->stream_error = NULL;
|
||||
@@ -241,6 +242,9 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
|
||||
xmpp_conn_handler callback,
|
||||
void * const userdata)
|
||||
{
|
||||
char connectdomain[2048];
|
||||
int connectport;
|
||||
|
||||
conn->type = XMPP_CLIENT;
|
||||
|
||||
if (domain) {
|
||||
@@ -250,8 +254,8 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
|
||||
}
|
||||
if (!conn->domain) return -1;
|
||||
|
||||
/* TODO: look up SRV record for actual host and port */
|
||||
conn->sock = sock_connect(conn->domain, 5222);
|
||||
sock_srv_lookup("xmpp-client", "tcp", conn->domain, connectdomain, 2048, &connectport);
|
||||
conn->sock = sock_connect(connectdomain, connectport);
|
||||
if (conn->sock < 0) return -1;
|
||||
|
||||
/* setup handler */
|
||||
@@ -265,7 +269,7 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
|
||||
|
||||
conn->state = XMPP_STATE_CONNECTING;
|
||||
conn->timeout_stamp = time_stamp();
|
||||
xmpp_debug(conn->ctx, "xmpp", "attempting to connect to %s", conn->domain);
|
||||
xmpp_debug(conn->ctx, "xmpp", "attempting to connect to %s", connectdomain);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -285,6 +289,11 @@ void conn_disconnect(xmpp_conn_t * const conn)
|
||||
{
|
||||
xmpp_debug(conn->ctx, "xmpp", "Closing socket.");
|
||||
conn->state = XMPP_STATE_DISCONNECTED;
|
||||
if (conn->tls) {
|
||||
tls_stop(conn->tls);
|
||||
tls_free(conn->tls);
|
||||
conn->tls = NULL;
|
||||
}
|
||||
sock_close(conn->sock);
|
||||
|
||||
/* fire off connection handler */
|
||||
|
||||
@@ -26,11 +26,13 @@
|
||||
void xmpp_initialize(void)
|
||||
{
|
||||
sock_initialize();
|
||||
tls_initialize();
|
||||
}
|
||||
|
||||
void xmpp_shutdown(void)
|
||||
{
|
||||
sock_shutdown();
|
||||
tls_shutdown();
|
||||
}
|
||||
|
||||
/** version **/
|
||||
|
||||
59
src/event.c
59
src/event.c
@@ -61,16 +61,31 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
||||
sq = conn->send_queue_head;
|
||||
while (sq) {
|
||||
towrite = sq->len - sq->written;
|
||||
ret = sock_write(conn->sock, &sq->data[sq->written], towrite);
|
||||
|
||||
if (ret < 0 && !sock_is_recoverable(sock_error())) {
|
||||
/* an error occured */
|
||||
conn->error = sock_error();
|
||||
break;
|
||||
} else if (ret < towrite) {
|
||||
/* not all data could be sent now */
|
||||
if (ret >= 0) sq->written += ret;
|
||||
break;
|
||||
if (conn->tls) {
|
||||
ret = tls_write(conn->tls, &sq->data[sq->written], towrite);
|
||||
|
||||
if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls))) {
|
||||
/* an error occured */
|
||||
conn->error = tls_error(conn->tls);
|
||||
break;
|
||||
} else if (ret < towrite) {
|
||||
/* not all data could be sent now */
|
||||
if (ret >= 0) sq->written += ret;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ret = sock_write(conn->sock, &sq->data[sq->written], towrite);
|
||||
|
||||
if (ret < 0 && !sock_is_recoverable(sock_error())) {
|
||||
/* an error occured */
|
||||
conn->error = sock_error();
|
||||
break;
|
||||
} else if (ret < towrite) {
|
||||
/* not all data could be sent now */
|
||||
if (ret >= 0) sq->written += ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* all data for this queue item written, delete and move on */
|
||||
@@ -161,7 +176,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
||||
|
||||
/* no events happened */
|
||||
if (ret == 0) return;
|
||||
|
||||
|
||||
/* process events */
|
||||
connitem = ctx->connlist;
|
||||
while (connitem) {
|
||||
@@ -191,7 +206,12 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
||||
break;
|
||||
case XMPP_STATE_CONNECTED:
|
||||
if (FD_ISSET(conn->sock, &rfds)) {
|
||||
ret = sock_read(conn->sock, buf, 4096);
|
||||
if (conn->tls) {
|
||||
ret = tls_read(conn->tls, buf, 4096);
|
||||
} else {
|
||||
ret = sock_read(conn->sock, buf, 4096);
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
ret = XML_Parse(conn->parser, buf, ret, 0);
|
||||
if (!ret) {
|
||||
@@ -201,10 +221,19 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
||||
conn_disconnect(conn);
|
||||
}
|
||||
} else {
|
||||
/* return of 0 means socket closed by server */
|
||||
xmpp_debug(ctx, "xmpp", "Socket closed by remote host.");
|
||||
conn->error = ECONNRESET;
|
||||
conn_disconnect(conn);
|
||||
if (conn->tls) {
|
||||
if (!tls_is_recoverable(tls_error(conn->tls)))
|
||||
{
|
||||
xmpp_debug(ctx, "xmpp", "Unrecoverable TLS error.");
|
||||
conn->error = tls_error(conn->tls);
|
||||
conn_disconnect(conn);
|
||||
}
|
||||
} else {
|
||||
/* return of 0 means socket closed by server */
|
||||
xmpp_debug(ctx, "xmpp", "Socket closed by remote host.");
|
||||
conn->error = ECONNRESET;
|
||||
conn_disconnect(conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
52
src/sock.c
52
src/sock.c
@@ -19,6 +19,7 @@
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windns.h>
|
||||
#define snprintf _snprintf
|
||||
#else
|
||||
#include <errno.h>
|
||||
@@ -163,3 +164,54 @@ int sock_connect_error(const sock_t sock)
|
||||
if (ret < 0) return ret;
|
||||
return error;
|
||||
}
|
||||
|
||||
void sock_srv_lookup(const char *service, const char *proto, const char *domain, char *resulttarget, int resulttargetlength, int *resultport)
|
||||
{
|
||||
int set = 0;
|
||||
char fulldomain[2048];
|
||||
|
||||
snprintf(fulldomain, 2048, "_%s._%s.%s", service, proto, domain);
|
||||
#ifdef _WIN32
|
||||
{
|
||||
HINSTANCE hdnsapi = NULL;
|
||||
|
||||
DNS_STATUS (WINAPI * pDnsQuery_A)(PCSTR, WORD, DWORD, PIP4_ARRAY, PDNS_RECORD*, PVOID*);
|
||||
void (WINAPI * pDnsRecordListFree)(PDNS_RECORD, DNS_FREE_TYPE);
|
||||
|
||||
if (hdnsapi = LoadLibrary("dnsapi.dll")) {
|
||||
pDnsQuery_A = GetProcAddress(hdnsapi, "DnsQuery_A");
|
||||
pDnsRecordListFree = GetProcAddress(hdnsapi, "DnsRecordListFree");
|
||||
|
||||
if (pDnsQuery_A && pDnsRecordListFree) {
|
||||
PDNS_RECORD dnsrecords = NULL;
|
||||
|
||||
if (pDnsQuery_A(fulldomain, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &dnsrecords, NULL) == 0) {
|
||||
PDNS_RECORD current = dnsrecords;
|
||||
|
||||
while (current) {
|
||||
if (current->wType == DNS_TYPE_SRV) {
|
||||
snprintf(resulttarget, resulttargetlength, current->Data.Srv.pNameTarget);
|
||||
*resultport = current->Data.Srv.wPort;
|
||||
set = 1;
|
||||
|
||||
current = NULL;
|
||||
} else {
|
||||
current = current->pNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pDnsRecordListFree(dnsrecords, DnsFreeRecordList);
|
||||
}
|
||||
/*UnloadLibrary(hdnsapi);*/
|
||||
}
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
if (!set)
|
||||
{
|
||||
snprintf(resulttarget, resulttargetlength, domain);
|
||||
*resultport = 5222;
|
||||
}
|
||||
}
|
||||
@@ -40,4 +40,8 @@ int sock_is_recoverable(const int error);
|
||||
/* checks for an error after connect, return 0 if connect successful */
|
||||
int sock_connect_error(const sock_t sock);
|
||||
|
||||
void sock_srv_lookup(const char *service, const char *proto,
|
||||
const char *domain, char *resulttarget,
|
||||
int resulttargetlength, int *resultport);
|
||||
|
||||
#endif /* __LIBSTROPHE_SOCK_H__ */
|
||||
|
||||
41
src/stanza.c
41
src/stanza.c
@@ -335,6 +335,47 @@ int xmpp_stanza_set_attributes(xmpp_stanza_t * const stanza,
|
||||
return XMPP_EOK;
|
||||
}
|
||||
|
||||
int xmpp_stanza_get_attribute_count(xmpp_stanza_t * const stanza)
|
||||
{
|
||||
if (stanza->attributes == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hash_num_keys(stanza->attributes);
|
||||
}
|
||||
|
||||
int xmpp_stanza_get_attributes(xmpp_stanza_t * const stanza,
|
||||
char **attr, int attrlen)
|
||||
{
|
||||
hash_iterator_t *iter;
|
||||
char *key;
|
||||
int num = 0;
|
||||
|
||||
if (stanza->attributes == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
iter = hash_iter_new(stanza->attributes);
|
||||
while ((key = hash_iter_next(iter)) != NULL && attrlen) {
|
||||
attr[num++] = key;
|
||||
attrlen--;
|
||||
if (attrlen == 0) {
|
||||
hash_iter_release(iter);
|
||||
return num;
|
||||
}
|
||||
attr[num++] = hash_get(stanza->attributes, key);
|
||||
attrlen--;
|
||||
if (attrlen == 0) {
|
||||
hash_iter_release(iter);
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
hash_iter_release(iter);
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
|
||||
const char * const key,
|
||||
const char * const value)
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#ifndef __LIBSTROPHE_TLS_H__
|
||||
#define __LIBSTROPHE_TLS_H__
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include "common.h"
|
||||
#include "sock.h"
|
||||
|
||||
|
||||
223
src/tls_openssl.c
Normal file
223
src/tls_openssl.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/* tls.c
|
||||
** libstrophe XMPP client library -- TLS abstraction openssl impl.
|
||||
**
|
||||
** Copyright (C) 2005 OGG, LCC. All rights reserved.
|
||||
**
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
*/
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/applink.c>
|
||||
|
||||
#include "common.h"
|
||||
#include "tls.h"
|
||||
#include "sock.h"
|
||||
|
||||
struct _tls {
|
||||
xmpp_ctx_t *ctx;
|
||||
sock_t sock;
|
||||
SSL_CTX *ssl_ctx;
|
||||
SSL *ssl;
|
||||
int lasterror;
|
||||
};
|
||||
|
||||
void tls_initialize(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
RAND_screen ();
|
||||
#else
|
||||
{
|
||||
char filename[512];
|
||||
char *file;
|
||||
|
||||
filename[0] = '\0';
|
||||
file = RAND_file_name(filename, 512);
|
||||
|
||||
if (file && strlen(file) != 0) {
|
||||
RAND_load_file(filename, /*It's over */9000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
SSL_library_init();
|
||||
SSL_load_error_strings();
|
||||
return;
|
||||
}
|
||||
|
||||
void tls_shutdown(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void tls_logerror(tls_t *tls)
|
||||
{
|
||||
char *texterror = NULL;
|
||||
|
||||
switch(tls->lasterror) {
|
||||
case SSL_ERROR_NONE:
|
||||
texterror = "No error.";
|
||||
break;
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
texterror = "Connection closed.";
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
texterror = "Data waiting to read.";
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
texterror = "Data waiting to write.";
|
||||
break;
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
texterror = "Not yet connected.";
|
||||
break;
|
||||
case SSL_ERROR_WANT_ACCEPT:
|
||||
texterror = "Not yet accepted.";
|
||||
break;
|
||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||
texterror = "No certification.";
|
||||
break;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
texterror = "I/O error.";
|
||||
break;
|
||||
case SSL_ERROR_SSL:
|
||||
texterror = "SSL library internal error";
|
||||
break;
|
||||
default:
|
||||
texterror = "Unknown error";
|
||||
break;
|
||||
}
|
||||
|
||||
xmpp_debug(tls->ctx, "xmpp", "SSL error: %s", texterror);
|
||||
}
|
||||
|
||||
tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock)
|
||||
{
|
||||
tls_t *tls = xmpp_alloc(ctx, sizeof(*tls));
|
||||
|
||||
if (tls) {
|
||||
int ret;
|
||||
memset(tls, 0, sizeof(*tls));
|
||||
|
||||
tls->ctx = ctx;
|
||||
tls->sock = sock;
|
||||
tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
|
||||
SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL);
|
||||
SSL_CTX_set_mode (tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||
SSL_CTX_set_verify (tls->ssl_ctx, SSL_VERIFY_NONE, NULL);
|
||||
|
||||
tls->ssl = SSL_new(tls->ssl_ctx);
|
||||
|
||||
ret = SSL_set_fd(tls->ssl, sock);
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
tls_error(tls);
|
||||
tls_free(tls);
|
||||
tls = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return tls;
|
||||
}
|
||||
|
||||
void tls_free(tls_t *tls)
|
||||
{
|
||||
SSL_CTX_free(tls->ssl_ctx);
|
||||
xmpp_free(tls->ctx, tls);
|
||||
return;
|
||||
}
|
||||
|
||||
int tls_set_credentials(tls_t *tls, const char *cafilename)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tls_start(tls_t *tls)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
/* Since we're non-blocking, loop the connect call until it
|
||||
succeeds or fails */
|
||||
while (ret == -1) {
|
||||
ret = SSL_connect(tls->ssl);
|
||||
|
||||
/* wait for something to happen on the sock before looping back */
|
||||
if (ret == -1) {
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1000;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(tls->sock, &fds);
|
||||
|
||||
select(tls->sock + 1, &fds, &fds, NULL, &tv);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
tls_logerror(tls);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int tls_stop(tls_t *tls)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = SSL_shutdown(tls->ssl);
|
||||
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
tls_logerror(tls);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_error(tls_t *tls)
|
||||
{
|
||||
return tls->lasterror;
|
||||
}
|
||||
|
||||
int tls_is_recoverable(int error)
|
||||
{
|
||||
return (error == SSL_ERROR_NONE || error == SSL_ERROR_WANT_READ
|
||||
|| error == SSL_ERROR_WANT_WRITE
|
||||
|| error == SSL_ERROR_WANT_CONNECT
|
||||
|| error == SSL_ERROR_WANT_ACCEPT);
|
||||
}
|
||||
|
||||
int tls_read(tls_t *tls, void * const buff, const size_t len)
|
||||
{
|
||||
int ret = SSL_read(tls->ssl, buff, len);
|
||||
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
tls_logerror(tls);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tls_write(tls_t *tls, const void * const buff, const size_t len)
|
||||
{
|
||||
int ret = SSL_write(tls->ssl, buff, len);
|
||||
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
tls_logerror(tls);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user