int init_trace_key(Buf & buf, CryptoContext * ctx, const char * filename, mode_t mode, unsigned char * trace_key) { unsigned char derivator[DERIVATOR_LENGTH]; get_derivator(filename, derivator, DERIVATOR_LENGTH); if (-1 == compute_hmac(trace_key, ctx->crypto_key, derivator)) { return -1; } return buf.open(filename, mode); }
int create_stun_message_integrity(char *msg,unsigned int len,char *key,unsigned int key_len,t_stun_message_integrity *mi) { if (len % 4 != 0) { if (log_1) LOG("create_stun_message_integrity:len not modulo 4\n"); return -1; } if (compute_hmac(mi->hmac,msg,len,key,key_len) < 0) return -1; mi->header.type = MESSAGE_INTEGRITY; mi->header.len = STUN_MESSAGE_INTEGRITY_LEN; return 1; }
// the password is a sha1 based on the username int generate_password(char *username,unsigned int ulen,char *another_key,unsigned int key_len,char **pass,unsigned int *len) { char hmac[STUN_MESSAGE_INTEGRITY_LEN]; char *password; *len = STUN_MESSAGE_INTEGRITY_LEN; password = NULL; password = (char *)malloc(*len); if (password == NULL) return -1; if (compute_hmac((char *)hmac,username,ulen,another_key,key_len) < 0) { free(password); return -2; } memcpy(password,hmac,STUN_MESSAGE_INTEGRITY_LEN); *pass = password; return 1; }
//the algorithm is described in STUN RFC. Based on the ip, port, time,a seed, and the hmac of these we generate a username int generate_username(t_uint32 client_ip,t_uint16 port,char *hmac_key,unsigned int key_len,char **user,unsigned int *len) { int i; t_uint16 r; t_uint16 minutes; char *username; char ulen; time_t t; char hmac[STUN_MESSAGE_INTEGRITY_LEN]; ulen = USERNAME_PREFIX_LEN+2+4+2+STUN_MESSAGE_INTEGRITY_LEN; if (ulen % 4 != 0) return -1; username = NULL; username = (char *)malloc(ulen); if (username ==NULL) return -2; for(i=0;i<USERNAME_PREFIX_LEN;i++) { get_rand16(32,126,&r); username[i] = (char)r; } t = time(0); minutes = t%1200; memcpy(username+USERNAME_PREFIX_LEN,&minutes,2); memcpy(username+USERNAME_PREFIX_LEN+2,&client_ip,4); memcpy(username+USERNAME_PREFIX_LEN+6,&port,2); if (compute_hmac((char *)hmac,username,USERNAME_PREFIX_LEN+8,hmac_key,key_len) < 0) { free(username); return -2; } memcpy(username+USERNAME_PREFIX_LEN+8,hmac,STUN_MESSAGE_INTEGRITY_LEN); *user = username; *len = ulen; return 1; }
//TODO:if the requestul contains USERNAME and MESSAGE_INTEGRITY i should add a MI int create_stun_binding_response(t_stun_message *req,t_stun_message *msg) { t_stun_header header; t_uint128 tid; unsigned int len; t_stun_mapped_address ma; t_stun_source_address sa; t_stun_changed_address ca; t_stun_reflected_from rf; t_uint16 port; t_uint32 address; char *pass; unsigned int plen; t_stun_message n; int adv; memset(msg,0,sizeof(t_stun_message)); if (req == NULL) { if (get_rand128(&tid) < 0) return -1; } else tid = req->header.tid; if (create_stun_header(MSG_TYPE_BINDING_RESPONSE,0,tid,&header) < 0) return -2; msg->header = header; len = 0; //mandatory:mapped_address,source_address,changed_address, port = ntohs(req->original_src.sin.sin_port); memcpy(&address,&(req->original_src.sin.sin_addr),4); address = ntohl(address); if (create_stun_address(MAPPED_ADDRESS,IPv4FAMILY,port,address,&ma) < 0) return -3; msg->u.resp.is_mapped_address = 1; msg->u.resp.mapped_address = ma; //?changed_address si source_address? if (req->u.req.is_change_request) { if (req->u.req.change_request.value & CHANGE_PORT_FLAG) port = ntohs(bind_address_port->su.sin.sin_port); else port = ntohs(bind_address->su.sin.sin_port); if (req->u.req.change_request.value & CHANGE_IP_FLAG) memcpy(&address,&(alternate_address->su.sin.sin_addr),4); else memcpy(&address,&(bind_address->su.sin.sin_addr),4); address = ntohl(address); } else //we have no request to change ip or port { port = ntohs(bind_address->su.sin.sin_port); memcpy(&address,&(bind_address->su.sin.sin_addr),4); address = ntohl(address); } if (create_stun_address(SOURCE_ADDRESS,IPv4FAMILY,port,address,&sa) < 0) return -4; msg->u.resp.is_source_address = 1; msg->u.resp.source_address = sa; port = ntohs(bind_address_port->su.sin.sin_port); memcpy(&address,&(alternate_address->su.sin.sin_addr),4); address = ntohl(address); if (create_stun_address(CHANGED_ADDRESS,IPv4FAMILY,port,address,&ca) < 0) return -5; msg->u.resp.is_changed_address = 1; msg->u.resp.changed_address = ca; /* port = ntohs(bind_address->su.sin.sin_port); memcpy(&address,&(bind_address->su.sin.sin_addr),4); address = ntohl(address); if (create_stun_address(SOURCE_ADDRESS,IPv4FAMILY,port,address,&sa) < 0) return -4; msg->u.resp.is_source_address = 1; msg->u.resp.source_address = sa; */ //PAG11 if (req->u.req.is_response_address) { //we create request_from, if we have a username, because in it we save the inital address of the request pag 11 STUN RFC if (req->u.req.is_username) { //we get from username the address and port of registration if (req->u.req.username.len != USERNAME_PREFIX_LEN+2+4+2+STUN_MESSAGE_INTEGRITY_LEN) return -2; memcpy(&address,(req->u.req.username.value+USERNAME_PREFIX_LEN+2),4); memcpy(&port,(req->u.req.username.value+USERNAME_PREFIX_LEN+6),2); } else { port = ntohs(req->original_src.sin.sin_port); memcpy(&address,&(req->original_src.sin.sin_addr),4); address = ntohl(address); } if (create_stun_address(REFLECTED_FROM,IPv4FAMILY,port,address,&rf) < 0) return -4; msg->u.resp.is_reflected_from = 1; msg->u.resp.reflected_from = rf; } if ((req->u.req.is_username)&&(req->u.req.is_message_integrity)) { //TODO:we add MI pass = NULL; plen = 0; if (obtain_password(req->u.req.username.value,req->u.req.username.len,&pass,&plen)<0) return -5;//internal error if (plen == 0) { //error 430,expired password adv = create_stun_binding_error_response(4,30,STUN_ERROR_430_REASON,STUN_ERROR_430_REASON_LEN,req,&n); adv = format_stun_binding_error_response(&n); adv = udp_send(bind_address,(char *)n.buff,n.buff_len,&(req->original_src)); return -6; } //pag 28:the buffer must be padded with 0 till it dvides with 64 if (compute_hmac(msg->u.resp.message_integrity.hmac,msg->buff,msg->buff_len,pass,plen) < 0) { if (pass) free(pass); return -102;//internal error } msg->u.resp.is_message_integrity = 1; if (pass) free(pass); } return 1; }