⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stun_common.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 2 页
字号:
  return attr->enc_buf.size;}int stun_encode_buffer(stun_attr_t *attr) {  stun_buffer_t *a;  a = (stun_buffer_t *)attr->pattr;  assert(a->size < 65536);  if (stun_encode_type_len(attr, (uint16_t)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) {    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 the message integrity based on given  * STUN password 'pwd'. The received content should be * in msg->enc_buf. */int stun_validate_message_integrity(stun_msg_t *msg, stun_buffer_t *pwd){#if defined(HAVE_OPENSSL)  int padded_len, len;  unsigned int dig_len;  unsigned char dig[20]; /* received sha1 digest */  unsigned char *padded_text;#endif  /* password NULL so shared-secret not established and      messege integrity checks can be skipped */  if (pwd->data == NULL)    return 0;  /* otherwise the check must match */#if defined(HAVE_OPENSSL)  /* 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;#else /* HAVE_OPENSSL */  return -1;#endif}void debug_print(stun_buffer_t *buf) {  unsigned 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) {  stun_attr_t *p, *p2;  /* clearing header */  memset(&msg->stun_hdr, 0, sizeof msg->stun_hdr);  /* 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_attr_t **a, *b;  stun_encode_message(msg, pwd);  err = su_sendto(s, msg->enc_buf.data, msg->enc_buf.size, 0, 		  to_addr, SU_SOCKADDR_SIZE(to_addr));  free(msg->enc_buf.data), msg->enc_buf.data = NULL;  msg->enc_buf.size = 0;  for (a = &msg->stun_attr; *a;) {    if ((*a)->pattr)      free((*a)->pattr), (*a)->pattr = NULL;    if ((*a)->enc_buf.data)      free((*a)->enc_buf.data), (*a)->enc_buf.data = NULL;    b = *a;    b = b->next;    free(*a);    *a = NULL;    *a = b;  }  if (err > 0) {    su_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 z = -1, len, buf_len = 0;  unsigned char *buf;  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 */    len = 0;    for (attr = msg->stun_attr; attr ; attr = attr->next) {      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);	break;      case CHANGE_REQUEST:#ifdef USE_TURN      case TURN_LIFETIME:      case TURN_MAGIC_COOKIE:      case TURN_BANDWIDTH:#endif	z = stun_encode_uint32(attr);	break;      case USERNAME:      case PASSWORD:#ifdef USE_TURN      case TURN_REALM:      case TURN_NONCE:      case TURN_DATA:#endif	z = stun_encode_buffer(attr);	break;      case MESSAGE_INTEGRITY:	msg_int = attr;	z = 24;	break;      case ERROR_CODE:	z = stun_encode_error_code(attr);      default:	break;      }      if(z < 0) return z;      len += z;    }    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 */    set16(buf, 0, msg->stun_hdr.msg_type);    set16(buf, 2, msg->stun_hdr.msg_len);    memcpy(buf + 4, msg->stun_hdr.tran_id, STUN_TID_BYTES);    len = 20;    /* 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, (void *)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, (void *)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;  size_t 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 + 1);  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";  case STUN_A_ALTERNATE_SERVER:  case STUN_A_ALTERNATE_SERVER_DEP:     return "ALTERNATE-SERVER";  case STUN_A_REALM: return "REALM";  case STUN_A_NONCE: return "NONCE";  case STUN_A_XOR_MAPPED_ADDRESS: return "XOR-MAPPED-ADDRESS";#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 + -