diff options
| author | me_desk <me_desk@fb96df88-216d-11de-830c-f3023f12d8ac> | 2015-03-09 23:41:26 +0000 |
|---|---|---|
| committer | Anton <anton@picapica> | 2015-03-10 03:42:49 +0400 |
| commit | 94587f893a83cf505d655169b6b45b24345a8aa9 (patch) | |
| tree | c3ffbe93f3719977e5df5cb4a3e88719dd048287 | |
| parent | c6f557b7259ee8c8b5d71706abd3ac9b6db0bff8 (diff) | |
| download | pica-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-x | PICA_client.c | 264 | ||||
| -rwxr-xr-x | PICA_client.h | 60 |
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 |
