Compare commits
5 Commits
generic-se
...
tls-secure
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06cb1459f1 | ||
|
|
82f372fa49 | ||
|
|
9ddc881102 | ||
|
|
f6ef50d134 | ||
|
|
bd87653c76 |
@@ -102,6 +102,7 @@ EXTRA_DIST = \
|
|||||||
jni/Android.mk \
|
jni/Android.mk \
|
||||||
jni/Application.mk \
|
jni/Application.mk \
|
||||||
src/tls_schannel.c \
|
src/tls_schannel.c \
|
||||||
|
src/tls_securetransport.c \
|
||||||
tests/res_query_dump.c
|
tests/res_query_dump.c
|
||||||
|
|
||||||
if TLS_WITH_GNUTLS
|
if TLS_WITH_GNUTLS
|
||||||
|
|||||||
252
src/tls_securetransport.c
Normal file
252
src/tls_securetransport.c
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
// Secure Transport implementation of TLS by Christopher A. Taylor (2013)
|
||||||
|
|
||||||
|
#include <Security/Security.h>
|
||||||
|
#include <Security/SecureTransport.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <CommonCrypto/CommonDigest.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "tls.h"
|
||||||
|
#include "sock.h"
|
||||||
|
|
||||||
|
struct _tls {
|
||||||
|
xmpp_ctx_t *ctx;
|
||||||
|
sock_t sock;
|
||||||
|
|
||||||
|
SSLContextRef sslctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
void tls_initialize(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void tls_shutdown(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
char *tls_id_on_xmppaddr(xmpp_conn_t *conn, unsigned int n)
|
||||||
|
{
|
||||||
|
UNUSED(n);
|
||||||
|
/* always fail */
|
||||||
|
xmpp_error(conn->ctx, "tls", "Client-Authentication not implemented");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int tls_id_on_xmppaddr_num(xmpp_conn_t *conn)
|
||||||
|
{
|
||||||
|
/* always fail */
|
||||||
|
xmpp_error(conn->ctx, "tls", "Client-Authentication not implemented");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSStatus MySSLReadFunction(SSLConnectionRef connection, void *data, size_t *dataLength) {
|
||||||
|
size_t bytesToGo = *dataLength;
|
||||||
|
size_t initLen = bytesToGo;
|
||||||
|
UInt8 *currData = (UInt8 *)data;
|
||||||
|
/*int sock = *(int *)connection;*/
|
||||||
|
tls_t *connssl = (tls_t *)connection;
|
||||||
|
int sock = connssl->sock;
|
||||||
|
OSStatus rtn = noErr;
|
||||||
|
size_t bytesRead;
|
||||||
|
ssize_t rrtn;
|
||||||
|
int theErr;
|
||||||
|
|
||||||
|
*dataLength = 0;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
bytesRead = 0;
|
||||||
|
rrtn = read(sock, currData, bytesToGo);
|
||||||
|
if(rrtn <= 0) {
|
||||||
|
/* this is guesswork... */
|
||||||
|
theErr = errno;
|
||||||
|
if(rrtn == 0) { /* EOF = server hung up */
|
||||||
|
/* the framework will turn this into errSSLClosedNoNotify */
|
||||||
|
rtn = errSSLClosedGraceful;
|
||||||
|
}
|
||||||
|
else /* do the switch */
|
||||||
|
switch(theErr) {
|
||||||
|
case ENOENT:
|
||||||
|
/* connection closed */
|
||||||
|
rtn = errSSLClosedGraceful;
|
||||||
|
break;
|
||||||
|
case ECONNRESET:
|
||||||
|
rtn = errSSLClosedAbort;
|
||||||
|
break;
|
||||||
|
case EAGAIN:
|
||||||
|
rtn = errSSLWouldBlock;
|
||||||
|
//connssl->ssl_direction = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rtn = errSSLClosedAbort;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bytesRead = rrtn;
|
||||||
|
}
|
||||||
|
bytesToGo -= bytesRead;
|
||||||
|
currData += bytesRead;
|
||||||
|
|
||||||
|
if(bytesToGo == 0) {
|
||||||
|
/* filled buffer with incoming data, done */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*dataLength = initLen - bytesToGo;
|
||||||
|
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSStatus MySSLWriteFunction(SSLConnectionRef connection, const void *data, size_t *dataLength) {
|
||||||
|
size_t bytesSent = 0;
|
||||||
|
/*int sock = *(int *)connection;*/
|
||||||
|
tls_t *connssl = (tls_t *)connection;
|
||||||
|
int sock = connssl->sock;
|
||||||
|
ssize_t length;
|
||||||
|
size_t dataLen = *dataLength;
|
||||||
|
const UInt8 *dataPtr = (UInt8 *)data;
|
||||||
|
OSStatus ortn;
|
||||||
|
int theErr;
|
||||||
|
|
||||||
|
*dataLength = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
length = write(sock,
|
||||||
|
(char*)dataPtr + bytesSent,
|
||||||
|
dataLen - bytesSent);
|
||||||
|
} while((length > 0) &&
|
||||||
|
( (bytesSent += length) < dataLen) );
|
||||||
|
|
||||||
|
if(length <= 0) {
|
||||||
|
theErr = errno;
|
||||||
|
if(theErr == EAGAIN) {
|
||||||
|
ortn = errSSLWouldBlock;
|
||||||
|
//connssl->ssl_direction = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ortn = errSSLClosedAbort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ortn = noErr;
|
||||||
|
}
|
||||||
|
*dataLength = bytesSent;
|
||||||
|
return ortn;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls_t *tls_new(xmpp_conn_t *conn)
|
||||||
|
{
|
||||||
|
tls_t *tls = xmpp_alloc(conn->ctx, sizeof(tls_t));
|
||||||
|
|
||||||
|
if (tls) {
|
||||||
|
tls->ctx = conn->ctx;
|
||||||
|
tls->sock = conn->sock;
|
||||||
|
tls->sslctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
|
||||||
|
|
||||||
|
SSLSetIOFuncs(tls->sslctx, MySSLReadFunction, MySSLWriteFunction);
|
||||||
|
|
||||||
|
SSLSetConnection(tls->sslctx, tls);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tls;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tls_free(tls_t *tls)
|
||||||
|
{
|
||||||
|
CFRelease(tls->sslctx);
|
||||||
|
|
||||||
|
xmpp_free(tls->ctx, tls);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_set_credentials(tls_t *tls, const char *cafilename)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Not implemented in OpenSSL version so we should not need it either.
|
||||||
|
But if we want to do it here's a place to start:
|
||||||
|
|
||||||
|
FILE * ret = fopen(cafilename, options);
|
||||||
|
void *data = malloc(bytes);
|
||||||
|
fread(data, 1, bytes, ret);
|
||||||
|
fclose(ret);
|
||||||
|
NSData *myCertData = [NSData dataWithBytesNoCopy:data length:bytes]; <- requires -ObjC compile option?
|
||||||
|
|
||||||
|
SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, myCertData);
|
||||||
|
CFArrayRef certRefs = CFArrayCreate(kCFAllocatorDefault, (const void **)&cert, 1, NULL);
|
||||||
|
|
||||||
|
SSLSetCertificate(tls->sslctx, certRefs);
|
||||||
|
*/
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_start(tls_t *tls)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Since we're non-blocking, loop the connect call until it
|
||||||
|
succeeds or fails */
|
||||||
|
do {
|
||||||
|
ret = SSLHandshake(tls->sslctx);
|
||||||
|
} while (ret == errSSLWouldBlock);
|
||||||
|
|
||||||
|
return ret < 0 ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_stop(tls_t *tls)
|
||||||
|
{
|
||||||
|
SSLClose(tls->sslctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_is_recoverable(int error)
|
||||||
|
{
|
||||||
|
switch (error) {
|
||||||
|
case errSSLWouldBlock:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_error(tls_t *tls)
|
||||||
|
{
|
||||||
|
/* todo: some kind of error polling/dump */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_pending(tls_t *tls)
|
||||||
|
{
|
||||||
|
size_t buffer;
|
||||||
|
|
||||||
|
if (SSLGetBufferedReadSize(tls->sslctx, &buffer) < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_read(tls_t *tls, void * const buff, const size_t len)
|
||||||
|
{
|
||||||
|
size_t processed;
|
||||||
|
|
||||||
|
SSLRead(tls->sslctx, buff, len, &processed);
|
||||||
|
|
||||||
|
return processed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_write(tls_t *tls, const void * const buff, const size_t len)
|
||||||
|
{
|
||||||
|
size_t processed;
|
||||||
|
|
||||||
|
SSLWrite(tls->sslctx, buff, len, &processed);
|
||||||
|
|
||||||
|
return processed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_clear_pending_write(tls_t *tls)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user