summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorme_desk <me_desk@fb96df88-216d-11de-830c-f3023f12d8ac>2015-03-09 23:41:26 +0000
committerAnton <anton@picapica>2015-03-10 03:42:49 +0400
commit94587f893a83cf505d655169b6b45b24345a8aa9 (patch)
treec3ffbe93f3719977e5df5cb4a3e88719dd048287
parentc6f557b7259ee8c8b5d71706abd3ac9b6db0bff8 (diff)
downloadpica-pica-94587f893a83cf505d655169b6b45b24345a8aa9.tar.gz
pica-pica-94587f893a83cf505d655169b6b45b24345a8aa9.zip
new structs PICA_acc - represents account credentials, certificate file and private key and PICA_listener - represents port opened on client for accepting incoming direct p2p (client-to-client, bypassing node) connections; new functions for handling PICA_acc and PICA_listener, moved part of code from PICA_new_connection() to PICA_open_acc()
git-svn-id: svn://localhost/project_picapica/trunk@341 fb96df88-216d-11de-830c-f3023f12d8ac
-rwxr-xr-xPICA_client.c264
-rwxr-xr-xPICA_client.h60
2 files changed, 232 insertions, 92 deletions
diff --git a/PICA_client.c b/PICA_client.c
index c30f283..4b6f3a9 100755
--- a/PICA_client.c
+++ b/PICA_client.c
@@ -46,6 +46,7 @@ static unsigned int procmsg_ACCEPTEDFILE(unsigned char*,unsigned int,void*);
static unsigned int procmsg_DENIEDFILE(unsigned char*,unsigned int,void*);
static unsigned int procmsg_FILEFRAGMENT(unsigned char*,unsigned int,void*);
static unsigned int procmsg_FILECONTROL(unsigned char*,unsigned int,void*);
+static unsigned int procmsg_INITRESP_c2c(unsigned char*,unsigned int,void*);
static struct PICA_proto_msg* c2n_writebuf_push(struct PICA_c2n *ci, unsigned int msgid, unsigned int size);
static struct PICA_proto_msg* c2c_writebuf_push(struct PICA_c2c *chn, unsigned int msgid, unsigned int size);
@@ -70,10 +71,14 @@ const struct PICA_msginfo c2c_messages[] = {
};
struct PICA_msginfo c2n_init_messages[] = {
- {PICA_PROTO_INITRESPOK, PICA_MSG_FIXED_SIZE, PICA_PROTO_INITRESPOK_SIZE, procmsg_INITRESP},
- {PICA_PROTO_VERDIFFER, PICA_MSG_FIXED_SIZE, PICA_PROTO_VERDIFFER_SIZE, procmsg_INITRESP}
+ {PICA_PROTO_INITRESPOK, PICA_MSG_FIXED_SIZE, PICA_PROTO_INITRESPOK_SIZE, procmsg_INITRESP},
+ {PICA_PROTO_VERDIFFER, PICA_MSG_FIXED_SIZE, PICA_PROTO_VERDIFFER_SIZE, procmsg_INITRESP}
};
+struct PICA_msginfo c2c_init_messages[] = {
+ {PICA_PROTO_INITRESPOK, PICA_MSG_FIXED_SIZE, PICA_PROTO_INITRESPOK_SIZE, procmsg_INITRESP_c2c},
+ {PICA_PROTO_VERDIFFER, PICA_MSG_FIXED_SIZE, PICA_PROTO_VERDIFFER_SIZE, procmsg_INITRESP_c2c}
+};
// static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata)
//{
@@ -206,6 +211,8 @@ chnl->conn = ci;
chnl->outgoing = is_outgoing;
memcpy(chnl->peer_id, peer_id, PICA_ID_SIZE);
+chnl->acc = ci->acc;
+
chnl->timestamp = time(0);
chnl->sck_data = -1;//prevent closing stdin when closing non-active connection
@@ -243,7 +250,7 @@ struct sockaddr_in addr=chnl->conn->srv_addr;
addr.sin_port = htons(ntohs(addr.sin_port));
ret=connect( chnl->sck_data, (struct sockaddr*)&addr, sizeof(struct sockaddr_in));
-
+/////////////////state_
if (ret==SOCKET_ERROR)
{
err_ret=PICA_ERRSOCK;
@@ -256,13 +263,13 @@ if (mp)
{
if (chnl->outgoing)
{
- memcpy(mp->tail, chnl->conn->id, PICA_ID_SIZE);//вызвывающий
+ memcpy(mp->tail, chnl->acc->id, PICA_ID_SIZE);//вызвывающий
memcpy(mp->tail + PICA_ID_SIZE, chnl->peer_id, PICA_ID_SIZE);//вызываемый
}
else
{
memcpy(mp->tail, chnl->peer_id, PICA_ID_SIZE);//вызвывающий
- memcpy(mp->tail + PICA_ID_SIZE, chnl->conn->id, PICA_ID_SIZE);//вызываемый
+ memcpy(mp->tail + PICA_ID_SIZE, chnl->acc->id, PICA_ID_SIZE);//вызываемый
}
}
else
@@ -279,7 +286,7 @@ do
}
while( chnl->write_pos > 0);
-chnl->ssl=SSL_new(chnl->conn->ctx);
+chnl->ssl=SSL_new(chnl->acc->ctx);
if (!chnl->ssl)
{
@@ -305,7 +312,7 @@ if (chnl->outgoing)
ret=SSL_connect(chnl->ssl);
else
ret=SSL_accept(chnl->ssl);
-
+/////////////////state_
//printf("verify result:%i\n",(int)SSL_get_verify_result(chnl->ssl));//debug
if (ret!=1)
@@ -398,6 +405,10 @@ PICA_close_channel(chnl);
return err_ret;
}
+static unsigned int procmsg_INITRESP_c2c(unsigned char* buf, unsigned int nb,void* p)
+{
+}
+
static unsigned int procmsg_INITRESP(unsigned char* buf, unsigned int nb,void* p)
{
struct PICA_c2n *ci=(struct PICA_c2n *)p;
@@ -987,61 +998,67 @@ signal(SIGPIPE, SIG_IGN);
return 1;
}
-/*адрес сервера, сертификат клиента и закрытый ключ*/
+static int check_pkey_passphrase(const char *pkey_file,
+ int (*password_cb)(char *buf, int size, int rwflag, void *userdata),
+ void *userdata)
+{
+RSA *rsa;
+FILE *f;
-//Осуществляет подключение к серверу по указанному адресу.
-//Аргументы:
-//nodeaddr - адрес узла
-//port - номер порта, в нативном для хост-машины порядке байт
-//CA_file - имя файла, содержащего корневой сертификат в формате PEM
-//cert_file - имя файла, содержащего сертфикат клиента в формате PEM
-//pkey_file - имя файла, содержащего приватный ключ в формате PEM
-//password_cb - callback-функция, запрашивающая пароль к приватному ключу, см. man 3 SSL_CTX_set_default_passwd_cb;в userdata передается указатель на id
-//ci -указатель на указатель на структуру PICA_c2n, который будет проинициализирован при успешном выполнении функции
-//Память, выделенная под структуру, освобождается при вызове PICA_close_connection
-//Возвращаемое значение - код завершения
-//PICA_OK - успешное завершение функции
-//....
-int PICA_new_connection(const char *nodeaddr,
- unsigned int port,
- const char *CA_file,
- const char *cert_file,
- const char *pkey_file,
- const char *dh_param_file,
- int (*password_cb)(char *buf, int size, int rwflag, void *userdata),
- struct PICA_c2n **ci)
+f = fopen(pkey_file, "r");
+
+if (!f)
+ return PICA_ERRINVPKEYFILE;
+
+rsa = PEM_read_RSAPrivateKey(f, NULL, password_cb, userdata);
+
+fclose(f);
+
+if (!rsa)
+ {
+ unsigned long int e = ERR_get_error();
+
+ // 0x6065064 is an OpenSSL error code corresponding to decryption failure
+ if (e == 0x6065064 || strcmp("bad decrypt", ERR_reason_error_string(e)) == 0)
+ return PICA_ERRINVPKEYPASSPHRASE;
+
+ return PICA_ERRINVPKEYFILE;
+ }
+
+RSA_free(rsa);
+
+return PICA_OK;
+}
+
+int PICA_open_acc(const char *cert_file,
+ const char *pkey_file,
+ const char *dh_param_file,
+ int (*password_cb)(char *buf, int size, int rwflag, void *userdata),
+ struct PICA_acc **acc)
{
int ret,ret_err;
-struct PICA_c2n *cid;
-struct sockaddr_in a;
DH *dh = NULL;
FILE *dh_file = NULL;
+struct PICA_acc *a = NULL;
-if (!(nodeaddr && CA_file && cert_file && pkey_file && ci))
- return PICA_ERRINVARG;
+if (!(cert_file && pkey_file && dh_param_file && acc))
+ return PICA_ERRINVARG;
+a = *acc = (struct PICA_acc*)calloc(sizeof(struct PICA_acc), 1);//(1)
-cid=*ci=(struct PICA_c2n*)calloc(sizeof(struct PICA_c2n),1);//(1)
-if (!cid)
- return PICA_ERRNOMEM;
+if (!a)
+ return PICA_ERRNOMEM;
-cid->read_buf = calloc(PICA_CONNREADBUFSIZE, 1);//(2)
-if (!cid->read_buf)
+a->ctx = SSL_CTX_new(TLSv1_2_method());//(2)
+
+if (!a->ctx)
{
- ret_err = PICA_ERRNOMEM;
+ ret_err=PICA_ERRSSL;
goto error_ret_1;
}
-cid->ctx=SSL_CTX_new(TLSv1_2_method());//(3)
-
-if (!cid->ctx)
- {
- ret_err=PICA_ERRSSL;
- goto error_ret_2;
- }
-
dh_file = fopen(dh_param_file, "r");
if (dh_file)
@@ -1050,45 +1067,56 @@ if (dh_file)
fclose(dh_file);
}
-if (1 != SSL_CTX_set_tmp_dh(cid->ctx, dh))
+if (1 != SSL_CTX_set_tmp_dh(a->ctx, dh))
{
ret_err = PICA_ERRSSL;
goto error_ret_2;
}
-DH_free (dh);
+DH_free(dh);
-if (!PICA_get_id_from_cert_file(cert_file, cid->id))
+if (!PICA_get_id_from_cert_file(cert_file, a->id))
{
- ret_err=PICA_ERRINVCERT;
- goto error_ret_3;
+ ret_err = PICA_ERRINVCERT;
+ goto error_ret_2;
+ }
+
+ret = check_pkey_passphrase(pkey_file, password_cb, a->id);
+
+if (ret != PICA_OK)
+ {
+ ret_err = ret;
+ goto error_ret_2;
}
+
////<<
if (password_cb)
{
- SSL_CTX_set_default_passwd_cb(cid->ctx, password_cb);
- SSL_CTX_set_default_passwd_cb_userdata(cid->ctx,cid->id);
+ SSL_CTX_set_default_passwd_cb(a->ctx, password_cb);
+ SSL_CTX_set_default_passwd_cb_userdata(a->ctx, a->id);
}
-ret=SSL_CTX_use_certificate_file(cid->ctx,cert_file,SSL_FILETYPE_PEM);
-if (ret!=1)
- {//ERR_CHECK
- ret_err=PICA_ERRSSL;
- goto error_ret_3;
- }
-ret=SSL_CTX_use_PrivateKey_file(cid->ctx,pkey_file,SSL_FILETYPE_PEM);
-if (ret!=1)
- {//ERR_CHECK
- ret_err=PICA_ERRSSL;
- goto error_ret_3;
+ret = SSL_CTX_use_certificate_file(a->ctx, cert_file, SSL_FILETYPE_PEM);
+
+if (ret != 1)
+ {
+ ret_err=PICA_ERRSSL;
+ goto error_ret_2;
+ }
+
+ret = SSL_CTX_use_PrivateKey_file(a->ctx, pkey_file, SSL_FILETYPE_PEM);
+if (ret != 1)
+ {
+ ret_err = PICA_ERRSSL;
+ goto error_ret_2;
}
////<<
-ret=SSL_CTX_load_verify_locations(cid->ctx,CA_file,0/*"trustedCA/"*/);
+//ret=SSL_CTX_load_verify_locations(cid->ctx,CA_file,0/*"trustedCA/"*/);
//printf("loadverifylocations ret=%i\n",ret);//debug
-SSL_CTX_set_client_CA_list(cid->ctx,SSL_load_client_CA_file(CA_file));
+//SSL_CTX_set_client_CA_list(cid->ctx,SSL_load_client_CA_file(CA_file));
-ret = SSL_CTX_set_cipher_list(cid->ctx,"DHE-RSA-CAMELLIA256-SHA"/*:DHE-RSA-AES256-SHA256"*/);
+ret = SSL_CTX_set_cipher_list(a->ctx,"DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CAMELLIA256-SHA");
if (ret != 1)
{
@@ -1096,13 +1124,66 @@ if (ret != 1)
goto error_ret_2;
}
+return PICA_OK;
+
+error_ret_2: //(2)
+SSL_CTX_free(a->ctx);
+
+error_ret_1: //(1)
+free(a);
+*acc = 0;
+
+return ret_err;
+}
+
+/*адрес сервера, сертификат клиента и закрытый ключ*/
+
+//Осуществляет подключение к серверу по указанному адресу.
+//Аргументы:
+//nodeaddr - адрес узла
+//port - номер порта, в нативном для хост-машины порядке байт
+//CA_file - имя файла, содержащего корневой сертификат в формате PEM
+//cert_file - имя файла, содержащего сертфикат клиента в формате PEM
+//pkey_file - имя файла, содержащего приватный ключ в формате PEM
+//password_cb - callback-функция, запрашивающая пароль к приватному ключу, см. man 3 SSL_CTX_set_default_passwd_cb;в userdata передается указатель на id
+//ci -указатель на указатель на структуру PICA_c2n, который будет проинициализирован при успешном выполнении функции
+//Память, выделенная под структуру, освобождается при вызове PICA_close_connection
+//Возвращаемое значение - код завершения
+//PICA_OK - успешное завершение функции
+//....
+
+int PICA_new_connection(const struct PICA_acc *acc, const char *nodeaddr,
+ unsigned int port,
+ struct PICA_c2n **ci)
+{
+int ret,ret_err;
+struct PICA_c2n *cid;
+struct sockaddr_in a;
+
+
+if (!(nodeaddr && acc && port && ci))
+ return PICA_ERRINVARG;
+
+
+cid=*ci=(struct PICA_c2n*)calloc(sizeof(struct PICA_c2n),1);//(1)
+if (!cid)
+ return PICA_ERRNOMEM;
-cid->ssl_comm=SSL_new(cid->ctx);//(4)
+cid->acc = acc;
+
+cid->read_buf = calloc(PICA_CONNREADBUFSIZE, 1);//(2)
+if (!cid->read_buf)
+ {
+ ret_err = PICA_ERRNOMEM;
+ goto error_ret_1;
+ }
+
+cid->ssl_comm=SSL_new(acc->ctx);//(3)
if (!cid->ssl_comm)
{
ret_err=PICA_ERRSSL;
- goto error_ret_3;
+ goto error_ret_2;
}
@@ -1144,18 +1225,18 @@ cid->sck_comm=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//(5)
if (cid->sck_comm==SOCKET_ERROR)
{
ret_err=PICA_ERRSOCK;
- goto error_ret_4;
+ goto error_ret_3;
}
cid->state = PICA_CONNSTATE_CONNECTING;
ret=connect(cid->sck_comm,(struct sockaddr*)&a,sizeof(struct sockaddr_in));
-
+/////////////////state_
if (ret==SOCKET_ERROR)
{
ret_err=PICA_ERRSOCK;
- goto error_ret_5;
+ goto error_ret_4;
}
@@ -1172,10 +1253,12 @@ if (mp)
else
{
ret_err = PICA_ERRNOMEM;
- goto error_ret_5;
+ goto error_ret_4;
}
}
+cid->state = PICA_CONNSTATE_WAITINGREP;
+
do
{
ret = PICA_write_c2n(cid);
@@ -1204,7 +1287,7 @@ if (cid->init_resp_ok != 1)
else
ret_err = PICA_ERRPROTOOLD;
}
- goto error_ret_5;
+ goto error_ret_4;
}
//printf("6\n");//debug
@@ -1214,13 +1297,14 @@ ret=SSL_set_fd(cid->ssl_comm,cid->sck_comm);
//printf("SSL_set_fd=%i\n",ret);
ret=SSL_accept(cid->ssl_comm);
-
+/////////////////state_
+cid->state = PICA_CONNSTATE_WAITINGTLS;
if (ret!=1)
{
//printf("SSL_accept ret=%i\n SSL_get_error=%i\n",ret,SSL_get_error(cid->ssl_comm,ret));//debug
//ERR_CHECK
ret_err=PICA_ERRSSL;
- goto error_ret_5;
+ goto error_ret_4;
}
cid->state = PICA_CONNSTATE_CONNECTED;//<<<!!!
@@ -1244,15 +1328,12 @@ IOCTLSETNONBLOCKINGSOCKET(cid->sck_comm, &arg);
return PICA_OK;
-error_ret_5: //(5)
+error_ret_4: //(4)
SHUTDOWN(cid->sck_comm);
CLOSE(cid->sck_comm);
-error_ret_4: //(4)
- SSL_free(cid->ssl_comm);
-
error_ret_3: //(3)
- SSL_CTX_free(cid->ctx);
+ SSL_free(cid->ssl_comm);
error_ret_2: //(2)
free(cid->read_buf);
@@ -1268,7 +1349,7 @@ return ret_err;
//создает ИСХОДЯЩИЙ логический зашифрованный канал связи с указанным собеседником, если тот доступен
// в данный момент.
-int PICA_create_channel(struct PICA_c2n *ci,const unsigned char *peer_id,struct PICA_c2c **chn)
+int PICA_create_channel(struct PICA_c2n *ci,const unsigned char *peer_id, struct PICA_listener *l,struct PICA_c2c **chn)
{
struct PICA_proto_msg *mp;
struct PICA_c2c *chnl;
@@ -1294,6 +1375,11 @@ mp = c2n_writebuf_push( ci, PICA_PROTO_CONNREQOUTG, PICA_PROTO_CONNREQOUTG_SIZE)
return PICA_OK;
}
+int PICA_event_loop(struct PICA_c2n **connections, struct PICA_listener **listeners)
+{
+
+}
+
int PICA_read(struct PICA_c2n *ci,int timeout)
{
fd_set fds;
@@ -1614,6 +1700,11 @@ int PICA_read_c2n(struct PICA_c2n *ci)
{
int ret;
+switch(ci->state)
+{
+//<<<
+}
+
//ret=SSL_read(ci->ssl_comm, ci->read_buf + ci->read_pos, PICA_CONNREADBUFSIZE - ci->read_pos);
if (PICA_CONNSTATE_CONNECTING == ci->state)
ret = PICA_read_socket(ci->sck_comm, ci->read_buf, &ci->read_pos, PICA_CONNREADBUFSIZE);
@@ -2006,7 +2097,7 @@ SSL_shutdown(cid->ssl_comm);
SSL_free(cid->ssl_comm);
SHUTDOWN(cid->sck_comm);
CLOSE(cid->sck_comm);
-SSL_CTX_free(cid->ctx);
+
free(cid->read_buf);
if (cid->write_buf)
@@ -2015,6 +2106,11 @@ if (cid->write_buf)
free(cid);
}
+void PICA_close_acc(struct PICA_acc *a)
+{
+SSL_CTX_free(a->ctx);
+}
+
#ifdef WIN32
const char *PICA_inet_ntop(int af, const void *src, char *dst, size_t size)
{
diff --git a/PICA_client.h b/PICA_client.h
index cbd3ed8..bf4a2de 100755
--- a/PICA_client.h
+++ b/PICA_client.h
@@ -87,6 +87,9 @@ typedef unsigned __int64 uint64_t;
#define PICA_ERRFILEOPEN -20
#define PICA_ERRFILEIO -21
+#define PICA_ERRINVPKEYPASSPHRASE -22
+#define PICA_ERRINVPKEYFILE -23
+
//#define PICA_CHNMSGBUFLEN 104
#define PICA_CHANREADBUFSIZE 65536
@@ -96,7 +99,10 @@ typedef unsigned __int64 uint64_t;
#define PICA_FILEFRAGMENTSIZE 16384 //max size of TLS record
#define PICA_CHANSTATE_ACTIVE 13
+
#define PICA_CONNSTATE_CONNECTING 17
+#define PICA_CONNSTATE_WAITINGREP 18
+#define PICA_CONNSTATE_WAITINGTLS 21
#define PICA_CONNSTATE_CONNECTED 19
#define PICA_CHANSENDFILESTATE_IDLE 0
@@ -118,12 +124,19 @@ typedef unsigned __int64 uint64_t;
struct PICA_c2n;
struct PICA_c2c;
+struct PICA_acc
+{
+unsigned char id[PICA_ID_SIZE]; //SHA224 hash of user's certificate in DER format
+SSL_CTX* ctx;
+};
+
struct PICA_c2n
{
+struct PICA_acc *acc;
//#warning "sockaddr!"
struct sockaddr_in srv_addr; // sockaddr !!
-unsigned char id[PICA_ID_SIZE]; //SHA224 hash of user's certificate in DER format
-SSL_CTX* ctx;
+//unsigned char id[PICA_ID_SIZE]; //SHA224 hash of user's certificate in DER format
+//SSL_CTX* ctx;
SOCKET sck_comm;
SSL* ssl_comm;
@@ -146,6 +159,7 @@ unsigned char node_ver_major, node_ver_minor;
struct PICA_c2c
{
+struct PICA_acc *acc;
struct PICA_c2n *conn;//соединение с сервером, через которое установлен данный логический канал связи
unsigned char peer_id[PICA_ID_SIZE];
SOCKET sck_data;
@@ -176,6 +190,19 @@ uint64_t recvfile_pos;
FILE *recvfile_stream;
};
+struct PICA_listener
+{
+struct PICA_acc *acc;
+SOCKET sck_listener;
+
+int public_port;
+int local_port;
+
+in_addr_t public_addr_ipv4;
+const char *public_addr_dns;
+
+};
+
struct PICA_client_callbacks
{
//получение сообщения.
@@ -224,21 +251,37 @@ int PICA_get_id_from_cert_string(const char *cert_pem, unsigned char *id);
int PICA_client_init(struct PICA_client_callbacks *clcbs);
int PICA_new_connection
- (const char *nodeaddr,
- unsigned int port,
- const char *CA_file,
+ (const struct PICA_acc *acc,
+ const char *nodeaddr,
+ unsigned int port,
+/* const char *CA_file,
const char *cert_file,
const char *pkey_file,
const char *dh_param_file,
- int (*password_cb)(char *buf, int size, int rwflag, void *userdata),
+ int (*password_cb)(char *buf, int size, int rwflag, void *userdata), //move callback to PICA_client_callbacks? */
struct PICA_c2n **ci);
-int PICA_create_channel(struct PICA_c2n *ci,const unsigned char *peer_id,struct PICA_c2c **chn);
+int PICA_create_channel(struct PICA_c2n *ci,const unsigned char *peer_id, struct PICA_listener *l,struct PICA_c2c **chn);
+
+int PICA_new_listener(const char *public_addr, int public_port, int local_port, struct PICA_listener **l);
+
+
+// <<<////
+int PICA_open_acc(const char *cert_file,
+ const char *pkey_file,
+ const char *dh_param_file,
+ int (*password_cb)(char *buf, int size, int rwflag, void *userdata),
+ struct PICA_acc **acc);
+// <<<////
+
int PICA_read_c2n(struct PICA_c2n *ci);
int PICA_read(struct PICA_c2n *ci,int timeout);
int PICA_write(struct PICA_c2n *ci);
+//connections, listeners - NULL-terminated arrays of pointers to appropriate structures
+int PICA_event_loop(struct PICA_c2n **connections, struct PICA_listener **listeners);
+
int PICA_send_msg(struct PICA_c2c *chn, char *buf,unsigned int len);
int PICA_read_msg(struct PICA_c2c *chn,char *buf,unsigned int *n);
@@ -253,7 +296,8 @@ int PICA_cancel_file(struct PICA_c2c *chan, int sending);
void PICA_close_channel(struct PICA_c2c *chn);
void PICA_close_connection(struct PICA_c2n *cid);
-
+void PICA_close_listener(struct PICA_listener *l);
+void PICA_close_acc(struct PICA_acc *a);
#ifdef __cplusplus
}
#endif