From 255f83d5109d7ddeab1c9a343292f2cfbcf10651 Mon Sep 17 00:00:00 2001 From: me_desk Date: Wed, 21 Aug 2013 12:57:33 +0000 Subject: changed client library code for handling new 224bit client id git-svn-id: svn://localhost/project_picapica/trunk@262 fb96df88-216d-11de-830c-f3023f12d8ac --- PICA_client.c | 148 ++++++++++++++++++++++++++++++++++----------------------- PICA_client.h | 36 +++++++------- PICA_msgproc.c | 2 +- PICA_msgproc.h | 2 +- 4 files changed, 110 insertions(+), 78 deletions(-) diff --git a/PICA_client.c b/PICA_client.c index ef8c638..8d31e50 100755 --- a/PICA_client.c +++ b/PICA_client.c @@ -67,7 +67,7 @@ struct PICA_msginfo c2n_init_messages[] = { //buf[size - 1] = 0; //return(strlen(buf)); //} - +/* //функция возвращает номер клиента id в бинарном виде, извлекая его из строки, //которая возвращается функцией X509_NAME_oneline и представляет собой DN из сертификата клиента static int get_id_fromsubjstr(char* DN_str,unsigned int* id) @@ -97,41 +97,56 @@ if (tmp1==tmp2) *tmp2='#'; return 1; } +*/ +int get_id_from_X509(X509 *x, unsigned char *id) +{ +unsigned char *der = NULL; +int len; + +len = i2d_X509(x, &der); - int PICA_get_id_from_cert(const char *cert_file, unsigned int *p_id) - { - char *DN_str; - X509 *x; - FILE *f; +if (len <= 0) +{ + return 0; +} - f=fopen(cert_file,"r"); +SHA224(der, len, id); - if (!f) - { - perror(cert_file); - return 0; - } +OPENSSL_free(der); + +return 1; +} + +int PICA_get_id_from_cert_file(const char *cert_file, unsigned char *id) +{ +X509 *x; +FILE *f; - x=PEM_read_X509(f,0,0,0); - fclose(f); +f=fopen(cert_file,"r"); - DN_str=X509_NAME_oneline(X509_get_subject_name(x), 0, 0); +if (!f) +{ + perror(cert_file); + return 0; +} - if (!get_id_fromsubjstr(DN_str,p_id)) - { - OPENSSL_free(DN_str); - return 0; - } - //printf("my id is %u\n",*p_id);//debug - //puts(DN_str);//debug +x=PEM_read_X509(f,0,0,0); +fclose(f); - OPENSSL_free(DN_str); - return 1; - } +if (!x) +{ + return 0; +} +return get_id_from_X509(x, id); +} +static int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) +{ //return 1 for self-signed certificates + return preverify_ok; +} -static int add_chaninfo(struct PICA_conninfo *ci,struct PICA_chaninfo **chn,unsigned int uid,int is_outgoing) +static int add_chaninfo(struct PICA_conninfo *ci, struct PICA_chaninfo **chn, const unsigned char *peer_id, int is_outgoing) { struct PICA_chaninfo *chnl,*ipt; @@ -140,9 +155,9 @@ chnl=*chn=(struct PICA_chaninfo*)calloc(sizeof(struct PICA_chaninfo),1); if (!chnl) return 0;//ERR_CHECK -chnl->conn=ci; -chnl->outgoing=is_outgoing; -chnl->peer_id=uid; +chnl->conn = ci; +chnl->outgoing = is_outgoing; +memcpy(chnl->peer_id, peer_id, PICA_ID_SIZE); chnl->timestamp = time(0); @@ -194,14 +209,13 @@ if (mp) { if (chnl->outgoing) { - *(unsigned int*)(mp->tail) = chnl->conn->id;//вызвывающий - *(unsigned int*)(mp->tail + 4) = chnl->peer_id;//вызываемый + memcpy(mp->tail, chnl->conn->id, PICA_ID_SIZE);//вызвывающий + memcpy(mp->tail + PICA_ID_SIZE, chnl->peer_id, PICA_ID_SIZE);//вызываемый } else { - //puts("callee CONNID");//debug - *(unsigned int*)(mp->tail) = chnl->peer_id;//вызвывающий - *(unsigned int*)(mp->tail + 4) = chnl->conn->id;//вызываемый + memcpy(mp->tail, chnl->peer_id, PICA_ID_SIZE);//вызвывающий + memcpy(mp->tail + PICA_ID_SIZE, chnl->conn->id, PICA_ID_SIZE);//вызываемый } } else @@ -209,7 +223,7 @@ else err_ret=PICA_ERRNOMEM; goto error_ret; } -//ret=send(chnl->sck_data,buf,PICA_PROTO_CONNID_SIZE,0); + do { err_ret = PICA_write_c2c(chnl); @@ -236,7 +250,9 @@ if (!ret) goto error_ret_; } -SSL_set_verify(chnl->ssl, SSL_VERIFY_PEER,0); +SSL_set_verify(chnl->ssl, SSL_VERIFY_PEER, verify_callback); +SSL_set_verify_depth(chnl->ssl, 1);//peer certificate and one CA + if (chnl->outgoing) ret=SSL_connect(chnl->ssl); @@ -263,6 +279,22 @@ if (!chnl->peer_cert) goto error_ret_; } +{ +unsigned char temp_id[PICA_ID_SIZE]; + +if (get_id_from_X509(chnl->peer_cert, temp_id) == 0) + { + err_ret=PICA_ERRNOPEERCERT; + goto error_ret_; + } + +if (memcmp(temp_id, chnl->peer_id, PICA_ID_SIZE) != 0) + { + err_ret=PICA_ERRINVPEERCERT; + goto error_ret_; + } +} +/* DN_str=X509_NAME_oneline(X509_get_subject_name(chnl->peer_cert), 0, 0); if (!DN_str) @@ -279,7 +311,9 @@ if (!get_id_fromsubjstr(DN_str,&tmp_uid) || tmp_uid!=chnl->peer_id) } //puts(DN_str);//debug -OPENSSL_free(DN_str); +OPENSSL_free(DN_str);*/ + + { BIO *mem = BIO_new(BIO_s_mem()); @@ -339,9 +373,10 @@ static unsigned int procmsg_CONNREQINC(unsigned char* buf,unsigned int nb,void* int ret; struct PICA_conninfo *ci=(struct PICA_conninfo *)p; struct PICA_proto_msg *mp; +unsigned char *peer_id = buf + 2; - if (callbacks.accept_cb(*(unsigned int*)(buf+2))) + if (callbacks.accept_cb(peer_id)) { struct PICA_chaninfo *_chnl; @@ -349,12 +384,12 @@ struct PICA_proto_msg *mp; if (mp) { - *(unsigned int*)(mp->tail) = *(unsigned int*)(buf+2); + memcpy(mp->tail, peer_id, PICA_ID_SIZE); } else return 0; - ret = add_chaninfo( ci, &_chnl, *(unsigned int*)(buf+2), 0); + ret = add_chaninfo( ci, &_chnl, peer_id, 0); if (!ret) return 0; //ERR_CHECK - кончилась память @@ -378,11 +413,11 @@ struct PICA_proto_msg *mp; } else { - mp = c2n_writebuf_push( ci, PICA_PROTO_CONNDENY, PICA_PROTO_CONNDENY_SIZE); + mp = c2n_writebuf_push(ci, PICA_PROTO_CONNDENY, PICA_PROTO_CONNDENY_SIZE); if (mp) { - *(unsigned int*)(mp->tail) = *(unsigned int*)(buf+2); + memcpy(mp->tail, peer_id, PICA_ID_SIZE); } else return 0;//ERR_CHECK @@ -394,19 +429,20 @@ static unsigned int procmsg_NOTFOUND(unsigned char* buf,unsigned int nb,void* p) { struct PICA_conninfo *ci=(struct PICA_conninfo *)p; struct PICA_chaninfo *ipt,*rq=0; +unsigned char *peer_id = buf + 2; //puts("procmsg_NOTFOUND");//debug ipt=ci->chan_list_end; while(ipt) { - if (ipt->peer_id==*(unsigned int*)(buf+2)) + if (memcmp(ipt->peer_id, peer_id, PICA_ID_SIZE) == 0) { rq=ipt; break; } ipt=ipt->prev; - } + } if (!rq) return 0;// ERR_CHECK -левое сообщение, такой запрос не посылался @@ -416,7 +452,7 @@ PICA_close_channel(rq); //puts("procmsg_NOTFOUND_chkp1");//debug -callbacks.notfound_cb(*(unsigned int*)(buf+2)); +callbacks.notfound_cb(peer_id); return 1; } @@ -424,12 +460,13 @@ static unsigned int procmsg_FOUND(unsigned char* buf,unsigned int nb,void* p) { struct PICA_conninfo *ci=(struct PICA_conninfo *)p; struct PICA_chaninfo *ipt,*rq=0; +unsigned char *peer_id = buf + 2; int ret; ipt=ci->chan_list_end; while(ipt) { - if (ipt->peer_id==*(unsigned int*)(buf+2)) + if (memcmp(ipt->peer_id, peer_id, PICA_ID_SIZE) == 0) { rq=ipt; break; @@ -698,7 +735,7 @@ if (!cid->ctx) goto error_ret_2; } -if (!PICA_get_id_from_cert(cert_file, &cid->id)) +if (!PICA_get_id_from_cert(cert_file, cid->id)) { ret_err=PICA_ERRINVCERT; goto error_ret_3; @@ -707,7 +744,7 @@ if (!PICA_get_id_from_cert(cert_file, &cid->id)) 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_userdata(cid->ctx,cid->id); } ret=SSL_CTX_use_certificate_file(cid->ctx,cert_file,SSL_FILETYPE_PEM); @@ -894,20 +931,15 @@ return ret_err; //создает ИСХОДЯЩИЙ логический зашифрованный канал связи с указанным собеседником, если тот доступен // в данный момент. - -int PICA_create_channel(struct PICA_conninfo *ci,unsigned int uid,struct PICA_chaninfo **chn) +int PICA_create_channel(struct PICA_conninfo *ci,const unsigned char *peer_id,struct PICA_chaninfo **chn) { struct PICA_proto_msg *mp; struct PICA_chaninfo *chnl; -char* DN_str; -unsigned char buf[12]; -int ret,err_ret; if (!(ci && chn)) return PICA_ERRINVARG; - -if (!add_chaninfo(ci,chn,uid,1)) +if (!add_chaninfo(ci, chn, peer_id, PICA_CHANNEL_OUTGOING)) return PICA_ERRNOMEM; chnl=*chn; @@ -916,17 +948,13 @@ mp = c2n_writebuf_push( ci, PICA_PROTO_CONNREQOUTG, PICA_PROTO_CONNREQOUTG_SIZE) if (mp) { - *(unsigned int*)(mp->tail)=uid; + memcpy(mp->tail, peer_id, PICA_ID_SIZE); } else return PICA_ERRNOMEM; return PICA_OK; - -//сделать нормальную обработку ошибок - со стековой последовательностью деинициализирующих процедур (!!??) -// в этой функции и в предыдущей - } int PICA_read(struct PICA_conninfo *ci,int timeout) diff --git a/PICA_client.h b/PICA_client.h index d98a607..b71e8bf 100755 --- a/PICA_client.h +++ b/PICA_client.h @@ -36,6 +36,7 @@ typedef unsigned __int16 uint16_t; #include #include #include +#include #ifdef PICA_MULTITHREADED @@ -83,6 +84,11 @@ typedef unsigned __int16 uint16_t; #define PICA_CHAN_ACTIVATE_TIMEOUT 30 +#define PICA_ID_SIZE SHA224_DIGEST_LENGTH + +#define PICA_CHANNEL_INCOMING 0 +#define PICA_CHANNEL_OUTGOING 1 + struct PICA_conninfo; struct PICA_chaninfo; @@ -90,13 +96,11 @@ struct PICA_conninfo { //#warning "sockaddr!" struct sockaddr_in srv_addr; // sockaddr !! -unsigned int id; +unsigned char id[PICA_ID_SIZE]; //SHA224 hash of user's certificate in DER format SSL_CTX* ctx; SOCKET sck_comm; SSL* ssl_comm; -//сертификат клиента -// unsigned char r_buf[128]; -// unsigned int r_pos; + int state; @@ -116,7 +120,7 @@ unsigned char node_ver_major, node_ver_minor; struct PICA_chaninfo { struct PICA_conninfo *conn;//соединение с сервером, через которое установлен данный логический канал связи -unsigned int peer_id;//номер собеседника +unsigned char peer_id[PICA_ID_SIZE]; SOCKET sck_data; SSL *ssl; int outgoing;//1 если создание канала инициировано локальным клиентом, 0 - если собеседником @@ -138,24 +142,24 @@ time_t timestamp; struct PICA_client_callbacks { //получение сообщения. -void (*newmsg_cb)(unsigned int peer_id,char* msgbuf,unsigned int nb,int type); +void (*newmsg_cb)(const unsigned char *peer_id,char* msgbuf,unsigned int nb,int type); //получение подтверждения о доставке сообщения -void (*msgok_cb)(unsigned int peer_id); +void (*msgok_cb)(const unsigned char *peer_id); //создание канала с собеседником -void (*channel_established_cb)(unsigned int peer_id); +void (*channel_established_cb)(const unsigned char *peer_id); //создать канал не удалось -void (*channel_failed)(unsigned int peer_id); +void (*channel_failed)(const unsigned char *peer_id); //входящий запрос на создание канала от пользователя с номером caller_id //возвращаемое значение: 0 - отклонить запрос, ненулевое значение - принять запрос -int (*accept_cb)(unsigned int caller_id); +int (*accept_cb)(const unsigned char *caller_id); //запрошенный пользователь не найден, в оффлайне или отказался от общения -void (*notfound_cb)(unsigned int callee_id); +void (*notfound_cb)(const unsigned char *callee_id); // -void (*channel_closed_cb)(unsigned int peer_id, int reason); +void (*channel_closed_cb)(const unsigned char *peer_id, int reason); void (*nodelist_cb)(int type, void *addr_bin, const char *addr_str, unsigned int port); //сертификат собеседника в формате PEM. Функция должна сравнить предъявленный сертификат с сохранённым (если есть) и вернуть 1 при успешной проверке, 0 - при неуспешной -int (*peer_cert_verify_cb)(unsigned int peer_id, const char *cert_pem, unsigned int nb); +int (*peer_cert_verify_cb)(const unsigned char *peer_id, const char *cert_pem, unsigned int nb); }; @@ -164,7 +168,8 @@ int (*peer_cert_verify_cb)(unsigned int peer_id, const char *cert_pem, unsigned extern "C" { #endif -int PICA_get_id_from_cert(const char *cert_file, unsigned int *p_id); +//read certificate from cert_file in PEM format, store id in buffer pointed by id +int PICA_get_id_from_cert(const char *cert_file, unsigned char *id); int PICA_client_init(struct PICA_client_callbacks *clcbs); int PICA_new_connection @@ -173,11 +178,10 @@ int PICA_new_connection const char *CA_file, const char *cert_file, const char *pkey_file, - //const char* password, int (*password_cb)(char *buf, int size, int rwflag, void *userdata), struct PICA_conninfo **ci); -int PICA_create_channel(struct PICA_conninfo *ci,unsigned int uid,struct PICA_chaninfo **chn); +int PICA_create_channel(struct PICA_conninfo *ci,const unsigned char *peer_id,struct PICA_chaninfo **chn); int PICA_read_c2n(struct PICA_conninfo *ci); int PICA_read(struct PICA_conninfo *ci,int timeout); diff --git a/PICA_msgproc.c b/PICA_msgproc.c index 78987c6..1564af7 100755 --- a/PICA_msgproc.c +++ b/PICA_msgproc.c @@ -60,7 +60,7 @@ for (i=0;i