summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton <anton@picapica>2018-12-14 22:41:27 +0400
committerAnton <anton@picapica>2018-12-14 22:41:27 +0400
commit0b6656e30c83a328e2b70c0802584e98b1da0a40 (patch)
tree44000a140f54a26310eb95b3ee24741f40df9955
parent240d089596ff9727ba257e539b88584d6fa6a9f9 (diff)
downloadpica-pica-0b6656e30c83a328e2b70c0802584e98b1da0a40.tar.gz
pica-pica-0b6656e30c83a328e2b70c0802584e98b1da0a40.zip
pica-node: implemented anon DH TLS connection stage, reworked newconns
-rw-r--r--PICA_node.c523
-rw-r--r--PICA_node.h58
-rw-r--r--PICA_nodewait.c20
-rw-r--r--PICA_security.h1
4 files changed, 481 insertions, 121 deletions
diff --git a/PICA_node.c b/PICA_node.c
index 04a5c9c..0113bab 100644
--- a/PICA_node.c
+++ b/PICA_node.c
@@ -61,7 +61,8 @@ char *my_addr;//TEMP CONF FIXME
SOCKET listen_comm_sck;//*
-SSL_CTX* ctx;
+SSL_CTX *ctx;
+SSL_CTX *anon_ctx;
struct newconn newconns[MAX_NEWCONNS];
unsigned int newconns_pos = 0;
@@ -80,9 +81,8 @@ struct nodelink *nodelink_list_end;
unsigned int nodelink_list_count;
-
-char msg_VERDIFFER[4] = {PICA_PROTO_VERDIFFER, PICA_PROTO_VERDIFFER, PICA_PROTO_VER_HIGH, PICA_PROTO_VER_LOW};
-const unsigned int msg_VERDIFFER_len = 4;
+const char msg_INITRESPOK[] = {PICA_PROTO_INITRESPOK, PICA_PROTO_INITRESPOK, 'O', 'K'};
+const char msg_VERDIFFER[] = {PICA_PROTO_VERDIFFER, PICA_PROTO_VERDIFFER, PICA_PROTO_VER_HIGH, PICA_PROTO_VER_LOW};
unsigned int procmsg_INITREQ(unsigned char* buf, unsigned int size, void* ptr);
unsigned int procmsg_CONNID(unsigned char* buf, unsigned int size, void* ptr);
@@ -116,7 +116,8 @@ void cclink_list_delete(struct cclink *l);
void cclink_list_addn2nclr(struct client *clr, const unsigned char *callee_id);
void cclink_setwaitconn(struct cclink *ccl);
void cclink_list_addn2ncle(const unsigned char *caller_id, struct nodelink *caller_node, struct client *cle);
-void cclink_activate(struct cclink *ccl, SOCKET s);
+void cclink_activate(struct cclink *ccl);
+void cclink_setwaitanontlsshutdown(struct cclink *link, struct newconn *nc);
void cclink_attach_remotecle_node(struct cclink *ccl, struct nodelink *callee_node);
void cclink_list_delete_by_client(struct client *cl);
@@ -179,6 +180,26 @@ struct PICA_msginfo _msginfo_newconn[] =
{PICA_PROTO_NODECONNREQ, PICA_MSG_FIXED_SIZE, PICA_PROTO_NODECONNREQ_SIZE, procmsg_NODECONNREQ}
};
+static int process_async_ssl_readwrite(SSL *ssl, int ret)
+{
+ if (ret == 0)
+ return 0;
+
+ if (ret < 0)
+ {
+ switch(SSL_get_error(ssl, ret))
+ {
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_READ:
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
//return 1 for self-signed certificates
@@ -210,6 +231,8 @@ unsigned int procmsg_INITREQ(unsigned char* buf, unsigned int size, void* ptr)
PICA_debug1("received INITREQ");
+ nc->type = NEWCONN_C2N;
+
if (buf[2] == PICA_PROTO_VER_HIGH && buf[3] == PICA_PROTO_VER_LOW)
{
struct client *c;
@@ -217,6 +240,10 @@ unsigned int procmsg_INITREQ(unsigned char* buf, unsigned int size, void* ptr)
if (!c)
return 0;
+ c->state = PICA_CLSTATE_WAITANONTLSSHUTDOWN;
+ nc->iconn.cl = c;
+ nc->state = PICA_NEWCONN_SENDINGOK;
+ /*
newconn_free(nc);
if ((mp = client_wbuf_push(c, PICA_PROTO_INITRESPOK, PICA_PROTO_INITRESPOK_SIZE)))
@@ -225,12 +252,11 @@ unsigned int procmsg_INITREQ(unsigned char* buf, unsigned int size, void* ptr)
mp->tail[1] = 'K';
}
- c->state = PICA_CLSTATE_SENDINGRESP;
+ c->state = PICA_CLSTATE_SENDINGRESP;*/
}///////---------<<<<<<<<<<< new client
else
{
- //// PICA_PROTO_VERDIFFER
- send(nc->sck, msg_VERDIFFER, msg_VERDIFFER_len, 0);
+ nc->state = PICA_NEWCONN_SENDINGREJECT;
if (buf[2] > PICA_PROTO_VER_HIGH || (buf[2] == PICA_PROTO_VER_HIGH && buf[3] > PICA_PROTO_VER_LOW))
{
@@ -240,13 +266,44 @@ unsigned int procmsg_INITREQ(unsigned char* buf, unsigned int size, void* ptr)
{
PICA_info("Client has older protocol version. Disconnecting ...");
}
-
- return 0;
}
return 1;
}
+void cclink_sendcleconnected(struct cclink *link)
+{
+ struct PICA_proto_msg *mp;
+
+ if (link->state == PICA_CCLINK_LOCAL_WAITCONNCLEANONTLSSHUTDOWN)
+ {
+ if((mp = client_wbuf_push(link->p1, PICA_PROTO_FOUND, PICA_PROTO_FOUND_SIZE)))
+ {
+ memcpy(mp->tail, link->callee_id, PICA_ID_SIZE);
+ }
+ else
+ {
+ cclink_list_delete(link);
+ return 0;
+ }
+ }
+
+ if (link->state == PICA_CCLINK_N2NCLE_WAITCONNCLEANONTLSSHUTDOWN)
+ {
+ if((mp = nodelink_wbuf_push(link->caller_node, PICA_PROTO_N2NALLOW, PICA_PROTO_N2NALLOW_SIZE)))
+ {
+ memcpy(mp->tail, link->caller_id, PICA_ID_SIZE);
+ memcpy(mp->tail + PICA_ID_SIZE, link->callee_id, PICA_ID_SIZE);
+ }
+ else
+ {
+ cclink_list_delete(link);
+ return 0;
+ }
+ }
+
+}
+
unsigned int procmsg_CONNID(unsigned char* buf, unsigned int size, void* ptr)
{
struct PICA_proto_msg *mp;
@@ -256,6 +313,8 @@ unsigned int procmsg_CONNID(unsigned char* buf, unsigned int size, void* ptr)
PICA_debug1("received CONNID");
+ nc->type = NEWCONN_C2C;
+
caller_id = buf + 2;
callee_id = buf + 2 + PICA_ID_SIZE;
@@ -296,35 +355,9 @@ unsigned int procmsg_CONNID(unsigned char* buf, unsigned int size, void* ptr)
}
}
- if (link->state == PICA_CCLINK_LOCAL_WAITCONNCLE)
- {
- if((mp = client_wbuf_push(link->p1, PICA_PROTO_FOUND, PICA_PROTO_FOUND_SIZE)))
- {
- memcpy(mp->tail, callee_id, PICA_ID_SIZE);
- }
- else
- {
- cclink_list_delete(link);
- return 0;
- }
- }
-
- if (link->state == PICA_CCLINK_N2NCLE_WAITCONNCLE)
- {
- if((mp = nodelink_wbuf_push(link->caller_node, PICA_PROTO_N2NALLOW, PICA_PROTO_N2NALLOW_SIZE)))
- {
- memcpy(mp->tail, caller_id, PICA_ID_SIZE);
- memcpy(mp->tail + PICA_ID_SIZE, callee_id, PICA_ID_SIZE);
- }
- else
- {
- cclink_list_delete(link);
- return 0;
- }
- }
PICA_debug3("CONNID processed successfully");
- cclink_activate(link, nc->sck);
- newconn_free(nc);
+ cclink_setwaitanontlsshutdown(link, nc);
+
return 1;
}
@@ -335,12 +368,15 @@ unsigned int procmsg_NODECONNREQ(unsigned char* buf, unsigned int size, void* pt
PICA_debug1("received NODECONNREQ");
+ nc->type = NEWCONN_N2N;
+
if (buf[2] == PICA_PROTO_VER_HIGH &&
buf[3] == PICA_PROTO_VER_LOW)
{
////-прием входящего подключения
//--------------------------
- struct nodelink *nl;
+ nc->state = PICA_NEWCONN_SENDINGOK;
+ /*struct nodelink *nl;
nl = nodelink_list_addnew(nc);
newconn_free(nc);
if (!nl)
@@ -350,10 +386,12 @@ unsigned int procmsg_NODECONNREQ(unsigned char* buf, unsigned int size, void* pt
{
mp->tail[0] = 'O';
mp->tail[1] = 'K';
- }
+ }*/
}
else
{
+ nc->state = PICA_NEWCONN_SENDINGREJECT;
+ /*
//// PICA_PROTO_VERDIFFER
send(nc->sck, msg_VERDIFFER, msg_VERDIFFER_len, 0);
@@ -367,7 +405,7 @@ unsigned int procmsg_NODECONNREQ(unsigned char* buf, unsigned int size, void* pt
PICA_info("Node %s has older protocol version. Disconnecting ...", inet_ntoa(nc->addr.sin_addr));
}
- return 0;
+ return 0;*/
}
return 1;
@@ -1286,39 +1324,68 @@ int cclink_allocbufs(struct cclink *ccl)
return 1;
}
-void cclink_activate(struct cclink *ccl, SOCKET s)
+void cclink_setwaitanontlsshutdown(struct cclink *link, struct newconn *nc)
{
- switch(ccl->state)
+ nc->iconn.cc = link;
+ nc->state = PICA_NEWCONN_WAITANONTLSSHUTDOWN;
+
+ switch(link->state)
{
case PICA_CCLINK_LOCAL_WAITCONNCLE:
- ccl->sck_p2 = s;
- ccl->state = PICA_CCLINK_LOCAL_WAITCONNCLR;
+ link->sck_p2 = nc->sck;
+ link->state = PICA_CCLINK_LOCAL_WAITCONNCLEANONTLSSHUTDOWN;
break;
+
case PICA_CCLINK_LOCAL_WAITCONNCLR:
- ccl->sck_p1 = s;
- if (!cclink_allocbufs(ccl))
+ link->sck_p1 = nc->sck;
+
+ if (!cclink_allocbufs(link))
{
- cclink_list_delete(ccl);
+ cclink_list_delete(link);
return;
}
- ccl->state = PICA_CCLINK_LOCAL_ACTIVE;
+ link->state = PICA_CCLINK_LOCAL_WAITCONNCLRANONTLSSHUTDOWN;
break;
+
case PICA_CCLINK_N2NCLR_WAITCONNCLR:
- ccl->sck_p1 = s;
- if (!cclink_allocbufs(ccl))
+ link->sck_p1 = nc->sck;
+
+ if (!cclink_allocbufs(link))
{
- cclink_list_delete(ccl);
+ cclink_list_delete(link);
return;
}
- ccl->state = PICA_CCLINK_N2NCLR_ACTIVE;
+ link->state = PICA_CCLINK_N2NCLR_WAITCONNCLRANONTLSSHUTDOWN;
break;
+
case PICA_CCLINK_N2NCLE_WAITCONNCLE:
- ccl->sck_p2 = s;
- if (!cclink_allocbufs(ccl))
+ link->sck_p2 = nc->sck;
+
+ if (!cclink_allocbufs(link))
{
- cclink_list_delete(ccl);
+ cclink_list_delete(link);
return;
}
+
+ link->state = PICA_CCLINK_N2NCLE_WAITCONNCLEANONTLSSHUTDOWN;
+ break;
+ }
+}
+
+void cclink_activate(struct cclink *ccl)
+{
+ switch(ccl->state)
+ {
+ case PICA_CCLINK_LOCAL_WAITCONNCLEANONTLSSHUTDOWN:
+ ccl->state = PICA_CCLINK_LOCAL_WAITCONNCLR;
+ break;
+ case PICA_CCLINK_LOCAL_WAITCONNCLRANONTLSSHUTDOWN:
+ ccl->state = PICA_CCLINK_LOCAL_ACTIVE;
+ break;
+ case PICA_CCLINK_N2NCLR_WAITCONNCLRANONTLSSHUTDOWN:
+ ccl->state = PICA_CCLINK_N2NCLR_ACTIVE;
+ break;
+ case PICA_CCLINK_N2NCLE_WAITCONNCLEANONTLSSHUTDOWN:
ccl->state = PICA_CCLINK_N2NCLE_ACTIVE;
break;
}
@@ -1330,6 +1397,8 @@ int PICA_node_init()
struct sockaddr_in sd;
int ret;
int flag;
+ FILE *dh_file;
+ DH *dh = NULL;
SSL_load_error_strings();
SSL_library_init();
@@ -1389,22 +1458,39 @@ int PICA_node_init()
//#endif
ctx = SSL_CTX_new(TLSv1_2_method());
+ anon_ctx = SSL_CTX_new(TLSv1_2_method());
- if (!ctx)
+ if (!ctx || !anon_ctx)
PICA_fatal("unable to create SSL_CTX object");
-
ret = SSL_CTX_set_cipher_list(ctx, PICA_TLS_CIPHERLIST);
if (!ret)
PICA_fatal("failed to set cipher list " PICA_TLS_CIPHERLIST);
- ret = SSL_CTX_load_verify_locations(ctx, nodecfg.CA_cert_file, 0);
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
+
+ dh_file = fopen(nodecfg.dh_param_file, "r");
+
+ if (dh_file)
+ {
+ dh = PEM_read_DHparams(dh_file, NULL, NULL, NULL);
+ fclose(dh_file);
+ }
+ else
+ PICA_fatal("Unable to open DH parameters file %", nodecfg.dh_param_file);
+
+ ret = SSL_CTX_set_tmp_dh(anon_ctx, dh);
+
+ if (ret != 1)
+ PICA_fatal("Failed to set DH parameters");
+
+ ret = SSL_CTX_set_cipher_list(anon_ctx, PICA_TLS_ANONDHCIPHERLIST);
if (!ret)
- PICA_fatal("call to SSL_CTX_load_verify_locations failed(). Check if %s exists and is accesible", nodecfg.CA_cert_file);
+ PICA_fatal("failed to set cipher list " PICA_TLS_ANONDHCIPHERLIST);
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
+ newconns_init();
return 1;
}
@@ -1415,8 +1501,31 @@ void newconn_close(struct newconn* nc)
CLOSE(nc->sck);
PICA_debug3("newconn_close(): nc = %p closed socket %i", nc, nc->sck);
- nc->sck = 0;
+ nc->sck = -1;
nc->pos = 0;
+
+ if (nc->iconn.cl && nc->type == NEWCONN_C2N)
+ client_list_delete(nc->iconn.cl);
+
+ if (nc->iconn.cc && nc->type == NEWCONN_C2C)
+ cclink_list_delete(nc->iconn.cc);
+
+ nc->iconn.cl = NULL;
+
+ nc->type = NEWCONN_UNKNOWN;
+}
+
+void newconns_init()
+{
+ int i;
+
+ memset(newconns, 0, sizeof(struct newconn) * MAX_NEWCONNS);
+
+ for (i = 0; i < MAX_NEWCONNS; i++)
+ {
+ newconns[i].sck = -1;
+ newconns[i].type = NEWCONN_UNKNOWN;
+ }
}
//функция ищет свободный элемент в массиве структур newconn и возвращает на него указатель
@@ -1426,7 +1535,7 @@ struct newconn* newconn_add(struct newconn *ncs, int *pos)
{
time_t min;
int min_pos = 0;
- if (*pos < MAX_NEWCONNS && !ncs[*pos].sck)
+ if (*pos < MAX_NEWCONNS && ncs[*pos].sck == -1)
{
goto ret;
}
@@ -1434,7 +1543,7 @@ struct newconn* newconn_add(struct newconn *ncs, int *pos)
{
*pos = 0;
min = ncs->tmst;
- while(ncs[*pos].sck && *pos < MAX_NEWCONNS)
+ while(*pos < MAX_NEWCONNS && ncs[*pos].sck >= 0)
{
if (ncs[*pos].tmst < min)
{
@@ -1449,11 +1558,12 @@ struct newconn* newconn_add(struct newconn *ncs, int *pos)
*pos = min_pos;
SHUTDOWN(ncs[min_pos].sck);
CLOSE(ncs[min_pos].sck);
- PICA_debug2("closed socket %i", ncs[min_pos].sck);
+ PICA_debug2("closed newconn socket %i", ncs[min_pos].sck);
}
}
ret:
+ ncs[*pos].sck = -1;
ncs[*pos].pos = 0;
ncs[*pos].tmst = time(0);
return &ncs[(*pos)++];
@@ -1461,7 +1571,7 @@ ret:
void newconn_free(struct newconn* nc)
{
- nc->sck = 0;
+ nc->sck = -1;
//nc->pos=0; - pos value is being used in processmsgdatastream
}
@@ -1765,6 +1875,7 @@ struct nodelink *nodelink_list_addnew(struct newconn *nc)
nl->sck = nc->sck;
nl->addr = nc->addr;
+ nl->anonssl = nc->anonssl;
nl->r_buf = calloc(1, DEFAULT_BUF_SIZE);
if (!nl->r_buf)
@@ -1914,7 +2025,7 @@ void process_timeouts_newconn()
for (i = 0; i < MAX_NEWCONNS; i++)
{
- if (newconns[i].sck)
+ if (newconns[i].sck >= 0)
{
if (newconns[i].tmst < t)
{
@@ -2113,7 +2224,7 @@ void newconn_set_fds(fd_set *readfds, int *nfds)
int i;
for (i = 0; i < MAX_NEWCONNS; i++)
- if (newconns[i].sck)
+ if (newconns[i].sck >= 0)
set_select_fd(newconns[i].sck, readfds, nfds);
}
@@ -2173,8 +2284,27 @@ void process_listen_read(fd_set *readfds)
{
nc = newconn_add(newconns, &newconns_pos);
+ nc->anonssl = SSL_new(anon_ctx);
+
+ if (!nc->anonssl)
+ {
+ PICA_error("failed to allocate SSL struct");
+ return;
+ }
+
+ if (!SSL_set_fd(nc->anonssl, s))
+ {
+ SSL_free(nc->anonssl);
+ return;
+ }
+
+
nc->sck = s;
nc->addr = addr;
+ nc->state = PICA_NEWCONN_WAITANONTLSACCEPT;
+
+ IOCTLSETNONBLOCKINGSOCKET(s, 1);
+
PICA_debug1("accepted connection from %.16s, new socket %i", inet_ntoa(addr.sin_addr), s);//IPv6
}
else
@@ -2186,28 +2316,208 @@ void process_listen_read(fd_set *readfds)
//IPv6
}
-void process_newconn_read(fd_set *readfds)
+void process_newconn_write()
{
int i, ret;
for (i = 0; i < MAX_NEWCONNS; i++)
- if (newconns[i].sck && FD_ISSET(newconns[i].sck, readfds))
+ if (newconns[i].sck >= 0)
{
- ret = recv(newconns[i].sck, newconns[i].buf + newconns[i].pos, NEWCONN_BUFSIZE - newconns[i].pos, 0);
- if (ret <= 0)
+ switch(newconns[i].state)
{
- //perror("process_newconn_read - recv:");//debug
- newconn_close(newconns + i);
- continue;
+ case PICA_NEWCONN_SENDINGOK:
+ PICA_debug3("sending OK response to newconn on socket %i...\n", newconns[i].sck);
+ ret = SSL_write(newconns[i].anonssl, msg_INITRESPOK, sizeof msg_INITRESPOK);
+
+ if (ret < 0 && process_async_ssl_readwrite(newconns[i].anonssl, ret))
+ break;
+
+ if (ret <= 0)
+ {
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
+ break;
+ }
+
+ if (ret == sizeof msg_INITRESPOK)
+ {
+ if (newconns[i].type == NEWCONN_N2N)
+ {
+ if (!nodelink_list_addnew(&newconns[i]))
+ {
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
+ }
+
+ newconn_free(&newconns[i]);
+ }
+ else
+ newconns[i].state = PICA_NEWCONN_WAITANONTLSSHUTDOWN;
+ }
+ break;
+
+ case PICA_NEWCONN_SENDINGREJECT:
+ PICA_debug3("sending reject response to newconn on socket %i...\n", newconns[i].sck);
+ ret = SSL_write(newconns[i].anonssl, msg_VERDIFFER, sizeof msg_VERDIFFER);
+
+ if (ret < 0 && process_async_ssl_readwrite(newconns[i].anonssl, ret))
+ break;
+
+ if (ret <= 0)
+ {
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
+ break;
+ }
+
+ SSL_shutdown(newconns[i].anonssl);
+ SHUTDOWN(newconns[i].sck);
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
}
- newconns[i].pos += ret;
- if(!PICA_processdatastream(newconns[i].buf, &(newconns[i].pos), newconns + i /*arg*/, _msginfo_newconn, MSGINFO_MSGSNUM(_msginfo_newconn) ))
+ }
+
+}
+
+void process_newconn_read(fd_set *readfds)
+{
+ int i, ret;
+
+ for (i = 0; i < MAX_NEWCONNS; i++)
+ if (newconns[i].sck >= 0 && FD_ISSET(newconns[i].sck, readfds))
+ {
+
+ switch(newconns[i].state)
{
- newconn_close(newconns + i);
+ case PICA_NEWCONN_WAITANONTLSACCEPT:
+ ret = SSL_accept(newconns[i].anonssl);
+
+ if (ret < 0 && process_async_ssl_readwrite(newconns[i].anonssl, ret))
+ break;
+
+ if (ret <= 0)
+ {
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
+ break;
+ }
+ else if (ret == 1)
+ {
+ newconns[i].state = PICA_NEWCONN_WAITREQUEST;
+ }
+
+ case PICA_NEWCONN_WAITREQUEST:
+ ret = SSL_read(newconns[i].anonssl, newconns[i].buf + newconns[i].pos, NEWCONN_BUFSIZE - newconns[i].pos);
+
+ if (ret < 0 && process_async_ssl_readwrite(newconns[i].anonssl, ret))
+ break;
+
+ if (ret <= 0)
+ {
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
+ break;
+ }
+
+ newconns[i].pos += ret;
+
+ if(!PICA_processdatastream(newconns[i].buf, &(newconns[i].pos), newconns + i, _msginfo_newconn, MSGINFO_MSGSNUM(_msginfo_newconn) ))
+ {
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
+ }
+
+ break;
+
+ /*case PICA_NEWCONN_SENDINGOK:
+ PICA_debug3("sending OK response to newconn on socket %i...\n", newconns[i].sck);
+ ret = SSL_write(newconns[i].anonssl, msg_INITRESPOK, sizeof msg_INITRESPOK);
+
+ if (ret < 0 && process_async_ssl_readwrite(newconns[i].anonssl, ret))
+ break;
+
+ if (ret <= 0)
+ {
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
+ break;
+ }
+
+ if (ret == sizeof msg_INITRESPOK)
+ {
+ if (newconns[i].type == NEWCONN_N2N)
+ {
+ if (!nodelink_list_addnew(&newconns[i]))
+ {
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
+ }
+
+ newconn_free(&newconns[i]);
+ }
+ else
+ newconns[i].state = PICA_NEWCONN_WAITANONTLSSHUTDOWN;
+ }*/
+
+ case PICA_NEWCONN_WAITANONTLSSHUTDOWN:
+ PICA_debug3("waiting for anon TLS shutdown on socket %i...\n", newconns[i].sck);
+ ret = SSL_shutdown(newconns[i].anonssl);
+
+ if (ret == 0)
+ break;
+
+ if (ret < 0 && process_async_ssl_readwrite(newconns[i].anonssl, ret))
+ break;
+
+ if (ret < 0)
+ {
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
+ break;
+ }
+
+ //switch state of client or cclink on successful shutdown
+ if (ret == 1)
+ {
+ if (newconns[i].iconn.cl && newconns[i].type == NEWCONN_C2N)
+ {
+ newconns[i].iconn.cl->state = PICA_CLSTATE_TLSNEGOTIATION;
+ newconn_free(&newconns[i]);
+ break;
+ }
+
+ if (newconns[i].iconn.cc && newconns[i].type == NEWCONN_C2C)
+ {
+ cclink_sendcleconnected(newconns[i].iconn.cc);
+ cclink_activate(newconns[i].iconn.cc);
+
+ newconn_free(&newconns[i]);
+ break;
+ }
+ }
+ break;
+
+ /*case PICA_NEWCONN_SENDINGREJECT:
+ ret = SSL_write(newconns[i].anonssl, msg_VERDIFFER, sizeof msg_VERDIFFER);
+
+ if (ret < 0 && process_async_ssl_readwrite(newconns[i].anonssl, ret))
+ break;
+
+ if (ret <= 0)
+ {
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);
+ break;
+ }
+
+ SSL_shutdown(newconns[i].anonssl);
+ SHUTDOWN(newconns[i].sck);
+ SSL_free(newconns[i].anonssl);
+ newconn_close(&newconns[i]);*/
}
- //FD_CLR(newconns[i].sck,readfds);
+
}
}
@@ -2330,15 +2640,9 @@ void process_n2n_read(fd_set *readfds)
{
if (FD_ISSET(nl->sck, readfds))
{
- ret = recv(nl->sck, nl->r_buf + nl->r_pos, nl->buflen_r - nl->r_pos, 0);
+ ret = SSL_read(nl->anonssl, nl->r_buf + nl->r_pos, nl->buflen_r - nl->r_pos);
- if (ret <= 0)
- {
- if (ret < 0)
- PICA_debug3("recv() failed in process_n2n_read(): %s", strerror(errno));
- kill_ptr = nl;
- }
- else
+ if (ret > 0)
{
nl->r_pos += ret;
@@ -2349,6 +2653,14 @@ void process_n2n_read(fd_set *readfds)
if (!nodelink_rbuf_grow(nl))
kill_ptr = nl;
}
+ else
+ {
+ if (ret == 0 || process_async_ssl_readwrite(nl->anonssl, ret) == 0)
+ {
+ PICA_debug3("SSL_read() failed in process_n2n_read()");
+ kill_ptr = nl;
+ }
+ }
}
nl = nl->next;
@@ -2387,6 +2699,9 @@ void process_c2n_write()
if (ret == i_ptr->btw_ssl)
{
+ if (ret < i_ptr->w_pos)
+ memmove(i_ptr->w_buf, i_ptr->w_buf + ret, i_ptr->w_pos - ret); //may be it's better to implement ring buffer here
+
i_ptr->w_pos -= i_ptr->btw_ssl;
i_ptr->btw_ssl = 0;
}
@@ -2401,7 +2716,10 @@ void process_c2n_write()
kill_ptr = i_ptr;
}
break;
- case PICA_CLSTATE_SENDINGRESP:
+ case PICA_CLSTATE_WAITANONTLSSHUTDOWN:
+ // do nothing here, state will be switched by newconn
+ break;
+/* case PICA_CLSTATE_SENDINGRESP:
ret = send(i_ptr->sck_comm, i_ptr->w_buf, i_ptr->w_pos, 0);
if (!ret)
kill_ptr = i_ptr;
@@ -2418,7 +2736,7 @@ void process_c2n_write()
if (!i_ptr->w_pos)
i_ptr->state = PICA_CLSTATE_TLSNEGOTIATION;
- break;
+ break;*/
case PICA_CLSTATE_TLSNEGOTIATION:
i_ptr->w_pos = 0;
ret = SSL_connect(i_ptr->ssl_comm);
@@ -2662,28 +2980,24 @@ void process_n2n_write()
{
if (nl->w_pos > 0)
{
- ret = send(nl->sck, nl->w_buf, nl->w_pos, MSG_NOSIGNAL);
+ if (!nl->btw_ssl)
+ nl->btw_ssl = nl->w_pos;
- if (ret > 0)
+ ret = SSL_write(nl->anonssl, nl->w_buf, nl->btw_ssl);
+
+ if (ret == nl->btw_ssl)
{
if (ret < nl->w_pos)
memmove(nl->w_buf, nl->w_buf + ret, nl->w_pos - ret); //may be it's better to implement ring buffer here
- nl->w_pos -= ret;
+ nl->w_pos -= nl->btw_ssl;
+ nl->btw_ssl = 0;
}
- if (ret < 0)
+
+ if (ret == 0 || ret < 0 && process_async_ssl_readwrite(nl->anonssl, ret) == 0)
{
-#ifdef WIN32
- ret = WSAGetLastError();
- if (!(ret == WSAEWOULDBLOCK || ret == WSAENOBUFS))
- kill_ptr = nl;
-#else
- ret = errno;
- if (!(ret == EAGAIN || ret == ENOBUFS || ret == EINTR))
- kill_ptr = nl;
-#endif
- }
- if (ret == 0)
kill_ptr = nl;
+ }
+
}
nl = nl->next;
@@ -2834,6 +3148,7 @@ int node_loop()
process_c2n_write();
process_c2c_write();
process_n2n_write();
+ process_newconn_write();
process_timeouts();
process_nodewait();
diff --git a/PICA_node.h b/PICA_node.h
index c5fd45e..7d8d19e 100644
--- a/PICA_node.h
+++ b/PICA_node.h
@@ -58,27 +58,38 @@
//#define PICA_DATA_PORT 51915
//#define PICA_NODE_PORT 51916
-#define PICA_CLSTATE_SENDINGRESP 1
+#define PICA_NEWCONN_WAITANONTLSACCEPT 1
+#define PICA_NEWCONN_WAITREQUEST 2
+#define PICA_NEWCONN_SENDINGOK 3
+#define PICA_NEWCONN_SENDINGREJECT 4
+#define PICA_NEWCONN_WAITANONTLSSHUTDOWN 5
+
+#define PICA_CLSTATE_WAITANONTLSSHUTDOWN 1
+//#define PICA_CLSTATE_SENDINGRESP 1
#define PICA_CLSTATE_TLSNEGOTIATION 2
#define PICA_CLSTATE_CONNECTED 3
-//LOCAL - оба клиента подсоединены к одному узлу
-//N2NCLR - к узлу подключен вызывающий клиент
-//N2NCLE - к узлу подключен вызываемый клиент
+//LOCAL - both clients are connected to the same node
+//N2NCLR - caller client is connected to this node
+//N2NCLE - callee client is connected to this node
#define PICA_CCLINK_LOCAL_WAITREP 1
#define PICA_CCLINK_LOCAL_WAITCONNCLE 2
-#define PICA_CCLINK_LOCAL_WAITCONNCLR 3
-#define PICA_CCLINK_LOCAL_ACTIVE 4
+#define PICA_CCLINK_LOCAL_WAITCONNCLEANONTLSSHUTDOWN 3
+#define PICA_CCLINK_LOCAL_WAITCONNCLR 4
+#define PICA_CCLINK_LOCAL_WAITCONNCLRANONTLSSHUTDOWN 5
+#define PICA_CCLINK_LOCAL_ACTIVE 6
-#define PICA_CCLINK_N2NCLR_WAITSEARCH 5
-#define PICA_CCLINK_N2NCLR_WAITREP 6
-#define PICA_CCLINK_N2NCLR_WAITCONNCLR 7
-#define PICA_CCLINK_N2NCLR_ACTIVE 8
+#define PICA_CCLINK_N2NCLR_WAITSEARCH 7
+#define PICA_CCLINK_N2NCLR_WAITREP 8
+#define PICA_CCLINK_N2NCLR_WAITCONNCLR 9
+#define PICA_CCLINK_N2NCLR_WAITCONNCLRANONTLSSHUTDOWN 10
+#define PICA_CCLINK_N2NCLR_ACTIVE 11
-#define PICA_CCLINK_N2NCLE_WAITREP 9
-#define PICA_CCLINK_N2NCLE_WAITCONNCLE 10
-#define PICA_CCLINK_N2NCLE_ACTIVE 11
+#define PICA_CCLINK_N2NCLE_WAITREP 12
+#define PICA_CCLINK_N2NCLE_WAITCONNCLE 13
+#define PICA_CCLINK_N2NCLE_WAITCONNCLEANONTLSSHUTDOWN 14
+#define PICA_CCLINK_N2NCLE_ACTIVE 15
@@ -90,7 +101,6 @@
#define DEFAULT_BUF_SIZE 4096
-
struct nodelink;
struct client
@@ -151,20 +161,36 @@ struct cclink //структура, описывающая соединение
int disconnect_ticking;
};
+enum newconn_type
+{
+ NEWCONN_UNKNOWN,
+ NEWCONN_C2N,
+ NEWCONN_C2C,
+ NEWCONN_N2N
+};
+
struct newconn //структура, описывающая новое подключение (клиента)
{
SOCKET sck;
+ SSL *anonssl;
struct sockaddr_in addr;
time_t tmst;
int pos;
+ int state;
+ enum newconn_type type;
unsigned char buf[NEWCONN_BUFSIZE];
+ union
+ {
+ struct client *cl;
+ struct cclink *cc;
+ } iconn;
};
struct nodelink
{
struct sockaddr_in addr;
SOCKET sck;
- SSL *ssl;
+ SSL *anonssl;
unsigned int addr_type;//тип адреса узла - PICA_PROTO_NEWNODE_IPV4,PICA_PROTE_NEWNODE_IPV6,...
void *node_addr;//указатель на структуру адреса {PICA_nodeaddr_ipv4, PICA_nodeaddr_ipv6,PICA_nodeaddr_dns,..}
@@ -175,6 +201,7 @@ struct nodelink
unsigned int buflen_w;
unsigned int r_pos;
unsigned int w_pos;
+ unsigned int btw_ssl;
struct nodelink *next;
struct nodelink *prev;
@@ -183,5 +210,6 @@ struct nodelink
int disconnect_ticking;
};
+extern SSL_CTX *anon_ctx;
#endif
diff --git a/PICA_nodewait.c b/PICA_nodewait.c
index 6bae525..c2467e1 100644
--- a/PICA_nodewait.c
+++ b/PICA_nodewait.c
@@ -162,6 +162,22 @@ static void *nodewait_connect_thread (void *arg)
}
else
{
+ nw->nc.anonssl = SSL_new(anon_ctx);
+
+ if (!nw->nc.anonssl)
+ {
+ CLOSE(nw->nc.sck);
+ return (void *)0;
+ }
+
+ if (!SSL_set_fd(nw->nc.anonssl, nw->nc.sck) || 1 != SSL_connect(nw->nc.anonssl))
+ {
+ SSL_free(nw->nc.anonssl);
+ CLOSE(nw->nc.sck);
+ ap = ap->ai_next;
+ continue;
+ }
+
break;
}
}
@@ -171,11 +187,11 @@ static void *nodewait_connect_thread (void *arg)
nw->nc.addr = *((struct sockaddr_in*)(ap->ai_addr));
nw->state = PICA_NODEWAIT_CONNECTED;
- return 1;
+ return (void *)1;
}
nw->state = PICA_NODEWAIT_CONNECT_FAILED;
- return 0;
+ return (void *)0;
}
void nodewait_start_resolve(struct PICA_nodeaddr *a)
diff --git a/PICA_security.h b/PICA_security.h
index c928adb..6697e7a 100644
--- a/PICA_security.h
+++ b/PICA_security.h
@@ -23,6 +23,7 @@
#define PICA_RSA_MINKEYSIZE 4096
#define PICA_TLS_CIPHERLIST "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CAMELLIA256-SHA"
+#define PICA_TLS_ANONDHCIPHERLIST "ADH-AES256-GCM-SHA384:ADH-CAMELLIA256-SHA"
#define PICA_OPENSSL_SECURUTY_LEVEL 3
#define PICA_CERTDIGESTALGO "-sha256"
#define PICA_PRIVKEYENCALGO "-aes256"