/* * add_fingerprint() * - msg: response buffer * * The function add_fingerprint ensures adding fingerprint attribute into * response buffer. * * Return value: 0 if there is no environment error * -1 if there is some enviroment error such as insufficiency * of memory */ int add_fingerprint(struct stun_buffer* msg) { struct stun_attr attr; USHORT_T attr_type_size; attr_type_size = sizeof(struct stun_attr); attr.type = htons(FINGERPRINT_ATTR); attr.len = htons(SHA_DIGEST_LENGTH); if (msg->empty < (SHA_DIGEST_LENGTH + attr_type_size)) { if (reallock_buffer(msg, SHA_DIGEST_LENGTH + attr_type_size) != 0) { return FATAL_ERROR; } } memcpy(&msg->buf.s[msg->buf.len], (void *) &attr, attr_type_size); msg->buf.len += attr_type_size; msg->empty -= attr_type_size; if (SHA1((UCHAR_T *)msg->buf.s, msg->buf.len-attr_type_size, (UCHAR_T *) &msg->buf.s[msg->buf.len]) == 0) { LOG(L_ERR, "ERROR: STUN: SHA-1 algorithm failed.\n"); return FATAL_ERROR; } msg->buf.len += SHA_DIGEST_LENGTH; msg->empty -= SHA_DIGEST_LENGTH; return 0; }
/* * buf_copy() * - msg: buffer where the data will be copy to * - source: source data buffer * - len: number of bytes that should be copied * * The function buf_copy copies "len" bytes from source into msg buffer * * Return value: 0 if there is no environment error * -1 if there is some enviroment error such as insufficiency * of memory */ static int buf_copy(struct stun_buffer* msg, void* source, UINT_T len) { if (msg->empty < len) { if (reallock_buffer(msg, len) != 0) { return FATAL_ERROR; } } memcpy(&msg->buf.s[msg->buf.len], source, len); msg->buf.len += len; msg->empty -= len; return 0; }
/* * add_error_code() * - res: response representation * - error_code: value of error type * * The function add_error_code ensures copy of link list of unknown * attributes into response buffer. * * Return value: 0 if there is no environment error * -1 if there is some enviroment error such as insufficiency * of memory */ static int add_error_code(struct stun_msg* res, USHORT_T error_code) { struct stun_attr attr; USHORT_T orig_len; USHORT_T two_bytes; int text_pad; char err[2]; orig_len = res->msg.buf.len; text_pad = 0; /* the type and length will be copy as last one because of unknown length*/ if (res->msg.buf.len < sizeof(struct stun_attr)) { if (reallock_buffer(&res->msg, sizeof(struct stun_attr)) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: add_error_code: failed to reallocate buffer\n"); #endif return FATAL_ERROR; } } res->msg.buf.len += sizeof(struct stun_attr); res->msg.empty -= sizeof(struct stun_attr); /* first two bytes are empty */ two_bytes = 0x0000; if (buf_copy(&res->msg, (void *) &two_bytes, sizeof(USHORT_T)) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: add_error_code: failed to copy buffer\n"); #endif return FATAL_ERROR; } err[0] = error_code / 100; err[1] = error_code % 100; if (buf_copy(&res->msg, (void *) err, sizeof(UCHAR_T)*2) != 0) { return FATAL_ERROR; } switch (error_code) { case TRY_ALTERNATE_ERR: text_pad = copy_str_to_buffer(res, TRY_ALTERNATE_TXT, PAD4); break; case BAD_REQUEST_ERR: text_pad = copy_str_to_buffer(res, BAD_REQUEST_TXT, PAD4); break; case UNAUTHORIZED_ERR: text_pad = copy_str_to_buffer(res, UNAUTHORIZED_TXT, PAD4); break; case UNKNOWN_ATTRIBUTE_ERR: text_pad = copy_str_to_buffer(res, UNKNOWN_ATTRIBUTE_TXT, PAD4); break; case STALE_CREDENTIALS_ERR: text_pad = copy_str_to_buffer(res, STALE_CREDENTIALS_TXT, PAD4); break; case INTEGRITY_CHECK_ERR: text_pad = copy_str_to_buffer(res, INTEGRITY_CHECK_TXT, PAD4); break; case MISSING_USERNAME_ERR: text_pad = copy_str_to_buffer(res, MISSING_USERNAME_TXT, PAD4); break; case USE_TLS_ERR: text_pad = copy_str_to_buffer(res, USE_TLS_TXT, PAD4); break; case MISSING_REALM_ERR: text_pad = copy_str_to_buffer(res, MISSING_REALM_TXT, PAD4); break; case MISSING_NONCE_ERR: text_pad = copy_str_to_buffer(res, MISSING_NONCE_TXT, PAD4); break; case UNKNOWN_USERNAME_ERR: text_pad = copy_str_to_buffer(res, UNKNOWN_USERNAME_TXT, PAD4); break; case STALE_NONCE_ERR: text_pad = copy_str_to_buffer(res, STALE_NONCE_TXT, PAD4); break; case SERVER_ERROR_ERR: text_pad = copy_str_to_buffer(res, SERVER_ERROR_TXT, PAD4); break; case GLOBAL_FAILURE_ERR: text_pad = copy_str_to_buffer(res, GLOBAL_FAILURE_TXT, PAD4); break; default: LOG(L_ERR, "ERROR: STUN: Unknown error code.\n"); break; } if (text_pad < 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: add_error_code: text_pad is negative\n"); #endif goto error; } attr.type = htons(ERROR_CODE_ATTR); /* count length of "value" field -> without type and lehgth field */ attr.len = htons(res->msg.buf.len - orig_len - text_pad - sizeof(struct stun_attr)); memcpy(&res->msg.buf.s[orig_len], (void *)&attr, sizeof(struct stun_attr)); return 0; error: return FATAL_ERROR; }