include_HEADERS = gnutls.h
-EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls_plaintext.h gnutls_cipher.h gnutls_buffers.h gnutls_errors.h gnutls_int.h gnutls_handshake.h
+EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls_plaintext.h gnutls_cipher.h gnutls_buffers.h gnutls_errors.h gnutls_int.h gnutls_handshake.h gnutls_num.h
lib_LTLIBRARIES = libgnutls.la
-libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c gnutls_cipher.c gnutls_buffers.c gnutls_handshake.c
+libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c gnutls_cipher.c gnutls_buffers.c gnutls_handshake.c gnutls_num.c
libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
noinst_PROGRAMS = serv cli
serv_SOURCES = serv.c
#include <netinet/in.h>
#include <arpa/inet.h>
#include <gnutls.h>
+#include <signal.h>
#define SA struct sockaddr
-#define ERR(err,s) if (err==-1) {perror(s);exit(1);}
+#define ERR(err,s) if (err==-1) {perror(s);return(1);}
-int main ()
+int main()
{
- int err;
- int sd;
- struct sockaddr_in sa;
- GNUTLS_STATE state;
- char buffer[100];
-
- sd = socket (AF_INET, SOCK_STREAM, 0); ERR(sd, "socket");
-
- memset (&sa, '\0', sizeof(sa));
- sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = inet_addr ("127.0.0.1");
- sa.sin_port = htons (6666);
-
- err = connect(sd, (SA*) &sa,
- sizeof(sa)); ERR(err, "connect");
-
- gnutls_init(&state, GNUTLS_CLIENT);
- gnutls_handshake( sd, state);
-
- gnutls_recv( sd, state, buffer, 10);
- fprintf(stderr, "Received: %s\n", buffer);
-
-
- close (sd);
- gnutls_deinit(&state);
- return 0;
+ int err, ret;
+ int sd;
+ struct sockaddr_in sa;
+ GNUTLS_STATE state;
+ char buffer[100];
+
+// signal(SIGPIPE, SIG_IGN);
+
+ sd = socket(AF_INET, SOCK_STREAM, 0);
+ ERR(sd, "socket");
+
+ memset(&sa, '\0', sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = inet_addr("127.0.0.1");
+ sa.sin_port = htons(2222);
+
+ err = connect(sd, (SA *) & sa, sizeof(sa));
+ ERR(err, "connect");
+
+ gnutls_init(&state, GNUTLS_CLIENT);
+ ret = gnutls_handshake(sd, state);
+
+ if (ret<0) {
+ fprintf(stderr, "handshake failed(%d)\n", ret);
+ } else {
+ fprintf(stderr, "handshake finished\n");
+ }
+
+ bzero(buffer, sizeof(buffer));
+ ret = gnutls_recv(sd, state, buffer, 5);
+ if (ret<0) {
+ fprintf(stderr, "Received corrupted data(%d)\n", ret);
+ } else {
+ fprintf(stdout, "Received: %s\n", buffer);
+ }
+ gnutls_close(sd, state);
+
+ close(sd);
+ gnutls_deinit(&state);
+ return 0;
}
}
+int gnutls_close(int cd, GNUTLS_STATE state) {
+
+ state->gnutls_internals.valid_connection = VALID_FALSE;
+ return _gnutls_send_alert(cd, state, GNUTLS_WARNING, GNUTLS_CLOSE_NOTIFY);
+
+}
+
ssize_t gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type,
char *data, size_t sizeofdata)
{
}
_gnutls_freeTLSCompressed(gcomp);
-fprintf(stderr, "size: %d\ntype: %d\n", gcipher->length, type);
if (Write(cd, &gcipher->type, sizeof(ContentType)) !=
sizeof(ContentType)) {
state->gnutls_internals.resumable = RESUME_FALSE;
return GNUTLS_E_UNABLE_SEND_DATA;
}
+
if (Write(cd, &gcipher->version.major, 1) != 1) {
state->gnutls_internals.valid_connection =
VALID_FALSE;
state->gnutls_internals.resumable = RESUME_FALSE;
return GNUTLS_E_UNABLE_SEND_DATA;
}
+
if (Write(cd, &gcipher->version.minor, 1) != 1) {
state->gnutls_internals.valid_connection =
VALID_FALSE;
if (state->gnutls_internals.valid_connection == VALID_FALSE)
return GNUTLS_E_INVALID_SESSION;
- while (gnutls_getDataBufferSize(type, state) < sizeofdata) {
+ do {
if (Read(cd, &gcipher.type, sizeof(ContentType)) !=
sizeof(ContentType)) {
- _gnutls_send_alert(cd, state, GNUTLS_FATAL,
- GNUTLS_INTERNAL_ERROR);
+// _gnutls_send_alert(cd, state, GNUTLS_FATAL,
+// GNUTLS_INTERNAL_ERROR);
state->gnutls_internals.valid_connection =
VALID_FALSE;
state->gnutls_internals.resumable = RESUME_FALSE;
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
+
if (Read(cd, &gcipher.version.major, 1) != 1) {
_gnutls_send_alert(cd, state, GNUTLS_FATAL,
GNUTLS_INTERNAL_ERROR);
state->gnutls_internals.resumable = RESUME_FALSE;
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
+
if (Read(cd, &gcipher.version.minor, 1) != 1) {
_gnutls_send_alert(cd, state, GNUTLS_FATAL,
GNUTLS_INTERNAL_ERROR);
state->gnutls_internals.resumable = RESUME_FALSE;
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
+
if (gcipher.version.major != GNUTLS_VERSION_MAJOR
|| gcipher.version.minor != GNUTLS_VERSION_MINOR) {
+
_gnutls_send_alert(cd, state, GNUTLS_FATAL,
GNUTLS_PROTOCOL_VERSION);
state->gnutls_internals.resumable = RESUME_FALSE;
#ifndef WORDS_BIGENDIAN
gcipher.length = byteswap16(gcipher.length);
#endif
+
if (gcipher.length > 18432) { /* 2^14+2048 */
+#ifdef DEBUG
fprintf(stderr, "Received packet with length: %d\n", gcipher.length);
+#endif
_gnutls_send_alert(cd, state, GNUTLS_FATAL,
GNUTLS_RECORD_OVERFLOW);
state->gnutls_internals.valid_connection =
gcipher.fragment = gnutls_malloc(gcipher.length);
/* read ciphertext */
- if (ret=Read(cd, gcipher.fragment, gcipher.length) !=
- gcipher.length) {
+
+ ret=Read(cd, gcipher.fragment, gcipher.length);
+
+ if (ret != gcipher.length) {
+#ifdef DEBUG
fprintf(stderr, "Received packet with length: %d\nExpecting %d\n", ret, gcipher.length);
+#endif
gnutls_free(gcipher.fragment);
- _gnutls_send_alert(cd, state, GNUTLS_FATAL,
- GNUTLS_INTERNAL_ERROR);
+// _gnutls_send_alert(cd, state, GNUTLS_FATAL,
+// GNUTLS_INTERNAL_ERROR);
state->gnutls_internals.valid_connection =
VALID_FALSE;
state->gnutls_internals.resumable = RESUME_FALSE;
return ret;
}
tmplen = gtxt->length;
-fprintf(stderr, "size: %d\ntype: %d\n", tmplen, type);
+
_gnutls_freeTLSPlaintext(gtxt);
- if (gcipher.type == type == GNUTLS_APPLICATION_DATA) {
+ if (gcipher.type == type && type == GNUTLS_APPLICATION_DATA) {
gnutls_insertDataBuffer(state, tmpdata, tmplen);
} else {
switch (gcipher.type) {
case GNUTLS_ALERT:
+#ifdef DEBUG
+ fprintf(stderr, "Alert was received\n");
+#endif
state->gnutls_internals.last_alert =
((Alert *) tmpdata)->description;
}
break;
case GNUTLS_CHANGE_CIPHER_SPEC:
- if (((ChangeCipherSpecType) tmpdata) ==
+ if (type != GNUTLS_CHANGE_CIPHER_SPEC) return GNUTLS_E_UNEXPECTED_PACKET;
+ if (((ChangeCipherSpecType) tmpdata[0]) ==
GNUTLS_TYPE_CHANGE_CIPHER_SPEC
&& tmplen == 1) {
- _gnutls_connection_state_init
+ ret = _gnutls_connection_state_init
(state);
+
} else {
state->gnutls_internals.
valid_connection = VALID_FALSE;
state->gnutls_internals.resumable =
RESUME_FALSE;
- return
+ ret =
GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
+ state->connection_state.read_sequence_number++;
+ return ret;
break;
case GNUTLS_HANDSHAKE:
if (type == GNUTLS_HANDSHAKE) {
- fprintf(stderr, "HANDSHAKE\n");
- ret = _gnutls_recv_hello( cd, state, tmpdata, sizeofdata, NULL, 0);
+ ret = _gnutls_recv_handshake( cd, state, tmpdata, tmplen);
gnutls_free(tmpdata);
+ state->connection_state.read_sequence_number++;
return ret;
}
}
/* Incread sequence number */
state->connection_state.read_sequence_number++;
-
- }
-
+
+ } while (gnutls_getDataBufferSize(type, state) < sizeofdata);
+
+
/* Insert Application data to buffer */
if (gcipher.type == type == GNUTLS_APPLICATION_DATA) {
ret = gnutls_getDataFromBuffer(state, data, sizeofdata);
gnutls_free(tmpdata);
} else {
- if (gcipher.type != type)
+ if (gcipher.type != type) {
return GNUTLS_E_RECEIVED_BAD_MESSAGE;
+#ifdef DEBUG
+ fprintf(stderr, "Received unexpected packet type\n");
+#endif
+ }
/* this is an error because we have messages of fixed
* length */
- if (sizeofdata != tmplen)
+#if 0 /* this is not a fatal error */
+ if (sizeofdata != tmplen) {
return GNUTLS_E_RECEIVED_MORE_DATA;
+#ifdef DEBUG
+ fprintf(stderr, "Received more data than expected\n");
+#endif
+ }
+#endif
memmove(data, tmpdata, sizeofdata);
gnutls_free(tmpdata);
ret = sizeofdata;
int gnutls_deinit(GNUTLS_STATE * state);
ssize_t gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, char* data, size_t sizeofdata);
ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char* data, size_t sizeofdata);
+int gnutls_close(int cd, GNUTLS_STATE state);
int gnutls_handshake(int cd, GNUTLS_STATE state);
#define gnutls_send( x, y, z, w) gnutls_send_int( x, y, GNUTLS_APPLICATION_DATA, z, w)
{
if (type == GNUTLS_APPLICATION_DATA)
return state->gnutls_internals.bufferSize;
- return -1;
+ return 0;
}
int gnutls_getDataFromBuffer(GNUTLS_STATE state, char *data, int length)
#define GNUTLS_E_ALERT_RECEIVED -12
#define GNUTLS_E_RECEIVED_BAD_MESSAGE -13
#define GNUTLS_E_RECEIVED_MORE_DATA -14
+#define GNUTLS_E_UNEXPECTED_PACKET -15
#include "gnutls_cipher.h"
#include "gnutls_buffers.h"
#include "gnutls_handshake.h"
+#include "gnutls_num.h"
+#ifdef DEBUG
+#define ERR(x, y) fprintf(stderr, "GNUTLS Error: %s (%d)\n", x,y)
+#else
+#define ERR(x, y)
+#endif
int SelectSuite( opaque ret[2], char* data, int datalen) {
int x, pos=0, i,j;
int _gnutls_send_handshake(int cd, GNUTLS_STATE state, void* i_data, uint32 i_datasize, HandshakeType type) {
int ret;
- char *data;
+ uint8* data;
uint24 length;
uint32 datasize;
int pos=0;
datasize = byteswap32(i_datasize);
#endif
- length.pint[0] = ((uint8*)&datasize)[1];
- length.pint[1] = ((uint8*)&datasize)[2];
- length.pint[2] = ((uint8*)&datasize)[3];
+ length = uint32touint24( datasize);
+// length.pint[0] = ((uint8*)&datasize)[1];
+// length.pint[1] = ((uint8*)&datasize)[2];
+// length.pint[2] = ((uint8*)&datasize)[3];
- data = gnutls_malloc( i_datasize + 3 + 1);
+ i_datasize += 4;
+ data = gnutls_malloc( i_datasize);
memmove( &data[pos++], &type, 1);
memmove( &data[pos++], &length.pint[0], 1);
memmove( &data[pos++], &length.pint[1], 1);
memmove( &data[pos++], &length.pint[2], 1);
- if (i_datasize > 0) memmove( &data[pos], i_data, i_datasize);
+ if (i_datasize > 0) memmove( &data[pos], i_data, i_datasize-4);
ret = gnutls_send_int( cd, state, GNUTLS_HANDSHAKE, data, i_datasize);
return ret;
}
+int _gnutls_recv_handshake( int cd, GNUTLS_STATE state, void* data, uint32 datasize) {
+ int ret;
+ uint32 length32=0;
+ int pos=0;
+ char *dataptr=data;
+ uint24 num;
+
+ num.pint[0] = dataptr[1];
+ num.pint[1] = dataptr[2];
+ num.pint[2] = dataptr[3];
+ length32 = uint24touint32( num);
+
+#ifndef WORDS_BIGENDIAN
+ length32 = byteswap32(length32);
+#endif
+
+
+ switch(dataptr[0]) {
+ case GNUTLS_CLIENT_HELLO:
+ case GNUTLS_SERVER_HELLO:
+ ret = _gnutls_recv_hello( cd, state, &dataptr[4], length32, NULL, 0);
+ break;
+ }
+
+ return ret;
+}
+
int _gnutls_send_hello_request(int cd, GNUTLS_STATE state) {
return _gnutls_send_handshake( cd, state, NULL, 0, GNUTLS_HELLO_REQUEST);
}
int pos=0;
GNUTLS_CipherSuite* cipher_suites;
CompressionMethod* compression_methods;
- int i, datalen, ret;
+ int i, datalen, ret=0;
uint16 x;
session_id_len = SessionIDLen;
memmove( &data[pos++], &state->gnutls_internals.compression_method, 1);
gcry_free(rand);
- gnutls_free(cipher_suites);
- gnutls_free(compression_methods);
- ret = _gnutls_send_handshake( cd, state, data, datalen, GNUTLS_CLIENT_HELLO);
+ ret = _gnutls_send_handshake( cd, state, data, datalen, GNUTLS_SERVER_HELLO);
gnutls_free(data);
}
}
-/* RECEIVE A HELLO MESSAGE. This should be called from gnutls_recv_int only if a
+/* RECEIVE A HELLO MESSAGE. This should be called from gnutls_recv_handshake only if a
* hello message is expected. It uses the gnutls_internals.current_cipher_suite
* and gnutls_internals.compression_method.
*/
uint16 x, sizeOfSuites;
if (state->security_parameters.entity == GNUTLS_CLIENT) {
-
if (datalen < 38) return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
-
+
if (data[pos++] != GNUTLS_VERSION_MAJOR)
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
+
if (data[pos++] != GNUTLS_VERSION_MINOR)
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
gnutls_free(compression_methods);
} else { /* Server side reading a client hello */
-
if (datalen < 35) return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
if (data[pos++] != GNUTLS_VERSION_MAJOR)
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
+
if (data[pos++] != GNUTLS_VERSION_MINOR)
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
memmove( &z, &data[pos++], 1);
SelectCompMethod( &state->gnutls_internals.compression_method, &data[pos], z);
- gnutls_free(cipher_suites);
- gnutls_free(compression_methods);
}
return ret;
if (state->security_parameters.entity == GNUTLS_CLIENT) {
ret = _gnutls_send_hello( cd, state, NULL, 0);
if (ret<0) {
- fprintf(stderr, "handshake error(%d)\n", ret);
+ ERR("send hello", ret);
return ret;
}
/* receive the server handshake */
ret = gnutls_recv_int( cd, state, GNUTLS_HANDSHAKE, NULL, 0);
if (ret<0) {
- fprintf(stderr, "handshake error(%d)\n", ret);
+ ERR("recv hello", ret);
+ return ret;
+ }
+ ret = gnutls_recv_int( cd, state, GNUTLS_CHANGE_CIPHER_SPEC, NULL, 0);
+ if (ret<0) {
+ ERR("recv ChangeCipherSpec", ret);
return ret;
- }
+ }
ret = _gnutls_send_change_cipher_spec( cd, state);
+ if (ret<0) {
+ ERR("send ChangeCipherSpec", ret);
+ return ret;
+ }
} else { /* SERVER */
-
+
ret = gnutls_recv_int( cd, state, GNUTLS_HANDSHAKE, NULL, 0);
if (ret<0) {
- fprintf(stderr, "handshake error(%d)\n", ret);
+ ERR("recv hello", ret);
return ret;
}
ret = _gnutls_send_hello( cd, state, NULL, 0);
if (ret<0) {
- fprintf(stderr, "handshake error(%d)\n", ret);
+ ERR("send hello", ret);
return ret;
}
ret = _gnutls_send_change_cipher_spec( cd, state);
+ if (ret<0) {
+ ERR("send ChangeCipherSpec", ret);
+ return ret;
+ }
+ ret = gnutls_recv_int( cd, state, GNUTLS_CHANGE_CIPHER_SPEC, NULL, 0);
+ if (ret<0) {
+ ERR("recv ChangeCipherSpec", ret);
+ return ret;
+ }
}
return ret;
int _gnutls_send_hello(int cd, GNUTLS_STATE state, opaque* SessionID, uint8 SessionIDLen);
int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char* data, int datalen, opaque** SessionID, int SessionIDnum);
int gnutls_handshake(int cd, GNUTLS_STATE state);
+int _gnutls_recv_handshake( int cd, GNUTLS_STATE state, void*, uint32);
+#define DEBUG
+
#define svoid void /* for functions that allocate using secure_free */
#define secure_free free
#define secure_malloc malloc
/* functions */
int _gnutls_send_alert( int cd, GNUTLS_STATE state, AlertLevel level, AlertDescription desc);
+int gnutls_close(int cd, GNUTLS_STATE state);
#include "gnutls.h"
#define SA struct sockaddr
-#define ERR(err,s) if(err==-1) {perror(s);exit(1);}
+#define ERR(err,s) if(err==-1) {perror(s);return(1);}
int main()
{
- int err;
- int listen_sd;
- int sd;
+ int err, listen_sd;
+ int sd, ret;
struct sockaddr_in sa_serv;
struct sockaddr_in sa_cli;
int client_len, i;
memset(&sa_serv, '\0', sizeof(sa_serv));
sa_serv.sin_family = AF_INET;
sa_serv.sin_addr.s_addr = INADDR_ANY;
- sa_serv.sin_port = htons(6666); /* Server Port number */
+ sa_serv.sin_port = htons(2222); /* Server Port number */
- err = bind(listen_sd, (SA*) &sa_serv,
- sizeof(sa_serv)); ERR(err, "bind");
+ err = bind(listen_sd, (SA *) & sa_serv, sizeof(sa_serv));
+ ERR(err, "bind");
err = listen(listen_sd, 1024);
ERR(err, "listen");
client_len = sizeof(sa_cli);
for (;;) {
gnutls_init(&state, GNUTLS_SERVER);
- sd =
- accept(listen_sd, (SA*) &sa_cli,
- &client_len);
+ sd = accept(listen_sd, (SA *) & sa_cli, &client_len);
fprintf(stderr, "connection from %s, port %d\n",
-// gnutls_handshake(sd, state);
-// fprintf(stderr, "Handshake was completed\n");
-// gnutls_send(sd, state, "hello\n", 5);
- gnutls_recv(sd, state, buf, 10);
-// fprintf(stderr, "buf: %s\n", bin2hex(buf,100));
- _print_TLSCiphertext( buf);
- fprintf(stderr, "Data was send\n");
+ gnutls_handshake(sd, state);
+ fprintf(stderr, "Handshake was completed\n");
+ ret = gnutls_send(sd, state, "hello\n", 5);
+ fprintf(stderr, "Data was send (%d)\n", ret);
+ gnutls_close(sd, state);
close(sd);
gnutls_deinit(&state);
}