📄 stun_common.c
字号:
memcpy(attr->enc_buf.data+8, reason, attr->enc_buf.size - 4); return attr->enc_buf.size;}int stun_encode_buffer(stun_attr_t *attr) { stun_buffer_t *a; a = (stun_buffer_t *)attr->pattr; if (stun_encode_type_len(attr, a->size) < 0) { return -1; } memcpy(attr->enc_buf.data+4, a->data, a->size); return attr->enc_buf.size;}#if defined(HAVE_OPENSSL)int stun_encode_message_integrity(stun_attr_t *attr, unsigned char *buf, int len, stun_buffer_t *pwd) { int padded_len; unsigned int dig_len; unsigned char *padded_text = NULL; void *sha1_hmac; if (stun_encode_type_len(attr, 20) < 0) { return -1; } /* zero padding */ if (len % 64 == 0) { void *sha_hmac; padded_len = len + (64 - (len % 64)); padded_text = (unsigned char *) malloc(padded_len); memcpy(padded_text, buf, len); memset(padded_text + len, 0, padded_len - len); sha1_hmac = HMAC(EVP_sha1(), pwd->data, pwd->size, padded_text, padded_len, NULL, &dig_len); } else { sha1_hmac = HMAC(EVP_sha1(), pwd->data, pwd->size, buf, len, NULL, &dig_len); } assert(dig_len == 20); memcpy(attr->enc_buf.data + 4, sha1_hmac, 20); free(padded_text); return attr->enc_buf.size;}#elseint stun_encode_message_integrity(stun_attr_t *attr, unsigned char *buf, int len, stun_buffer_t *pwd) { return 0;}#endif /* HAVE_OPENSSL *//** this function allocates the enc_buf, fills in type, length */int stun_encode_type_len(stun_attr_t *attr, uint16_t len) { uint16_t tmp; attr->enc_buf.data = (unsigned char *) malloc(len + 4); memset(attr->enc_buf.data, 0, len + 4); tmp = htons(attr->attr_type); memcpy(attr->enc_buf.data, &tmp, 2); tmp = htons(len); memcpy(attr->enc_buf.data + 2, &tmp, 2); attr->enc_buf.size = len + 4; return 0;}/** validate message integrity based on pwd * received content is in msg->enc_buf */#if defined(HAVE_OPENSSL)int stun_validate_message_integrity(stun_msg_t *msg, stun_buffer_t *pwd){ int padded_len, len; unsigned int dig_len; unsigned char dig[20]; /* received sha1 digest */ unsigned char *padded_text; if (pwd->data == NULL) return 0; /* message integrity not received */ if (stun_get_attr(msg->stun_attr, MESSAGE_INTEGRITY) == NULL) { SU_DEBUG_5(("%s: error: message integrity missing.\n", __func__)); return -1; } /* zero padding */ len = msg->enc_buf.size - 24; padded_len = len + (len % 64 == 0 ? 0 : 64 - (len % 64)); padded_text = (unsigned char *) malloc(padded_len); memset(padded_text, 0, padded_len); memcpy(padded_text, msg->enc_buf.data, len); memcpy(dig, HMAC(EVP_sha1(), pwd->data, pwd->size, padded_text, padded_len, NULL, &dig_len), 20); if (memcmp(dig, msg->enc_buf.data + msg->enc_buf.size - 20, 20) != 0) { /* does not match, but try the test server's password */ if (memcmp(msg->enc_buf.data+msg->enc_buf.size-20, "hmac-not-implemented", 20) != 0) { SU_DEBUG_5(("%s: error: message digest problem.\n", __func__)); return -1; } } else { SU_DEBUG_5(("%s: message integrity validated.\n", __func__)); } free(padded_text); return 0;}#elseint stun_validate_message_integrity(stun_msg_t *msg, stun_buffer_t *pwd){ return -1;}#endif /* HAVE_OPENSSL */void debug_print(stun_buffer_t *buf) { int i; for(i = 0; i < buf->size/4; i++) { SU_DEBUG_9(("%02x %02x %02x %02x\n", *(buf->data + i*4), *(buf->data + i*4 +1), *(buf->data + i*4 +2), *(buf->data + i*4 +3))); if (i == 4) SU_DEBUG_9(("---------------------\n")); } SU_DEBUG_9(("\n"));}int stun_init_message(stun_msg_t *msg) { msg->stun_hdr.msg_type = 0; msg->stun_hdr.msg_len = 0; msg->stun_attr = NULL; stun_init_buffer(&msg->enc_buf); return 0;}int stun_free_message(stun_msg_t *msg) { int i; stun_attr_t *p, *p2; /* clearing header */ msg->stun_hdr.msg_type = 0; msg->stun_hdr.msg_len = 0; for(i=0; i<8; i++) msg->stun_hdr.tran_id[i] = 0; /* clearing attr */ p = msg->stun_attr; while(p) { if(p->pattr) { switch(p->attr_type) { case USERNAME: case PASSWORD:#ifdef USE_TURN case TURN_DATA: case TURN_NONCE:#endif stun_free_buffer(p->pattr); break; default: free(p->pattr); } } stun_free_buffer(&p->enc_buf); p2 = p->next; free(p); p = p2; } msg->stun_attr = NULL; /* clearing buffer */ stun_free_buffer(&msg->enc_buf); return 0;}int stun_send_message(su_socket_t s, su_sockaddr_t *to_addr, stun_msg_t *msg, stun_buffer_t *pwd) { int err; char ipaddr[SU_ADDRSIZE + 2]; stun_encode_message(msg, pwd); err = sendto(s, msg->enc_buf.data, msg->enc_buf.size, 0, (struct sockaddr *)to_addr, sizeof(struct sockaddr_in)); if (err > 0) { inet_ntop(to_addr->su_family, SU_ADDR(to_addr), ipaddr, sizeof(ipaddr)); SU_DEBUG_5(("%s: message sent to %s:%u\n", __func__, ipaddr, ntohs(to_addr->su_port))); debug_print(&msg->enc_buf); } else STUN_ERROR(errno, sendto); return err;} /** send a STUN message. * This will convert the stun_msg_t to the binary format based on the * spec */int stun_encode_message(stun_msg_t *msg, stun_buffer_t *pwd) { int i, z, len, buf_len = 0; unsigned char *buf; uint16_t tmp16; stun_attr_t *attr, *msg_int=NULL; if(msg->enc_buf.data == NULL) { /* convert msg to binary format */ /* convert attributes to binary format for transmission */ attr = msg->stun_attr; len = 0; while(attr) { switch(attr->attr_type) { case RESPONSE_ADDRESS: case MAPPED_ADDRESS: case SOURCE_ADDRESS: case CHANGED_ADDRESS: case REFLECTED_FROM: #ifdef USE_TURN case TURN_ALTERNATE_SERVER: case TURN_DESTINATION_ADDRESS: case TURN_SOURCE_ADDRESS:#endif z = stun_encode_address(attr); if(z < 0) return z; len += z; break; case CHANGE_REQUEST:#ifdef USE_TURN case TURN_LIFETIME: case TURN_MAGIC_COOKIE: case TURN_BANDWIDTH:#endif z = stun_encode_uint32(attr); if(z < 0) return z; len += z; break; case USERNAME: case PASSWORD:#ifdef USE_TURN case TURN_REALM: case TURN_NONCE: case TURN_DATA:#endif z = stun_encode_buffer(attr); if(z < 0) return z; len += z; break; case MESSAGE_INTEGRITY: msg_int = attr; len += 24; /* postpone encoding to 2nd round */ break; case ERROR_CODE: z = stun_encode_error_code(attr); if(z < 0) return z; len += z; default: break; } attr = attr->next; } msg->stun_hdr.msg_len = len; buf_len = 20+msg->stun_hdr.msg_len; buf = (unsigned char *)malloc(buf_len); /* convert to binary format for transmission */ len = 0; tmp16 = htons(msg->stun_hdr.msg_type); memcpy(buf, (unsigned char *)&tmp16, 2); len+=2; tmp16 = htons(msg->stun_hdr.msg_len); memcpy(buf+len, (unsigned char *)&tmp16, 2); len+=2; for(i=0; i<8; i++) { tmp16 = htons(msg->stun_hdr.tran_id[i]); memcpy(buf+len, (unsigned char *)&tmp16, 2); len+=2; } /* attaching encoded attributes */ attr = msg->stun_attr; while(attr) { /* attach only if enc_buf is not null */ if(attr->enc_buf.data && attr->attr_type != MESSAGE_INTEGRITY) { memcpy(buf+len, (unsigned char *)attr->enc_buf.data, attr->enc_buf.size); len += attr->enc_buf.size; } attr = attr->next; } if(msg_int) { /* compute message integrity */ if(stun_encode_message_integrity(msg_int, buf, len, pwd)!=24) { free(buf); return -1; } memcpy(buf+len, (unsigned char *)msg_int->enc_buf.data, msg_int->enc_buf.size); } /* save binary buffer for future reference */ if (msg->enc_buf.data) free(msg->enc_buf.data); msg->enc_buf.data = buf; msg->enc_buf.size = buf_len; } return 0;}#include <sofia-sip/su.h>#include <sofia-sip/su_debug.h>#include <sofia-sip/su_localinfo.h>char *stun_determine_ip_address(int family){ char *local_ip_address; su_localinfo_t *li = NULL, hints[1] = {{ LI_CANONNAME|LI_NUMERIC }}; int error, address_size; struct sockaddr_in *sa = NULL; su_sockaddr_t *temp; hints->li_family = family; hints->li_canonname = getenv("HOSTADDRESS"); if ((error = su_getlocalinfo(hints, &li)) < 0) { SU_DEBUG_5(("%s: stun_determine_ip_address, su_getlocalinfo: %s\n", __func__, su_gli_strerror(error))); return NULL; } temp = li->li_addr; sa = &temp->su_sin; address_size = strlen(inet_ntoa(sa->sin_addr)); local_ip_address = malloc(address_size); strcpy(local_ip_address, (char *) inet_ntoa(sa->sin_addr)); /* otherwise? */ su_freelocalinfo(li); return local_ip_address;}const char *stun_attr_phrase(uint16_t type){ switch(type) { case MAPPED_ADDRESS: return "MAPPED-ADDRESS"; case RESPONSE_ADDRESS: return "RESPONSE-ADDRESS"; case CHANGE_REQUEST: return "CHANGE-REQUEST"; case SOURCE_ADDRESS: return "SOURCE-ADDRESS"; case CHANGED_ADDRESS: return "CHANGED-ADDRESS"; case USERNAME: return "USERNAME"; case PASSWORD: return "PASSWORD"; case MESSAGE_INTEGRITY: return "MESSAGE-INTEGRITY"; case ERROR_CODE: return "ERROR-CODE"; case UNKNOWN_ATTRIBUTES: return "UNKNOWN-ATTRIBUTES"; case REFLECTED_FROM: return "REFLECTED-FROM";#ifdef USE_TURN case TURN_REALM: return "REALM"; case TURN_LIFETIME: return "LIFETIME"; case TURN_ALTERNATE_SERVER: return "ALTERNATE_SERVER"; case TURN_MAGIC_COOKIE: return "MAGIC_COOKIE"; case TURN_BANDWIDTH: return "BANDWIDTH"; case TURN_DESTINATION_ADDRESS: return "DESTINATION_ADDRESS"; case TURN_SOURCE_ADDRESS: return "SOURCE_ADDRESS"; case TURN_DATA: return "DATA"; case TURN_NONCE: return "NONCE";#endif default: return "Attribute undefined"; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -