static int check_oauth(void) { const char server_name[33] = "blackdow.carleon.gov"; size_t i_hmacs,i_shas,i_encs; const char long_term_password[33] = "HGkj32KJGiuy098sdfaqbNjOiaz71923"; size_t ltp_output_length=0; const char* base64encoded_ltp = base64_encode((const unsigned char *)long_term_password, strlen(long_term_password), <p_output_length); const char mac_key[33] = "ZksjpweoixXmvn67534m"; const size_t mac_key_length=strlen(mac_key); const uint64_t token_timestamp = (uint64_t)(92470300704768LL); const uint32_t token_lifetime = 3600; const char kid[33] = "2783466234"; const turn_time_t key_timestamp = 1234567890; const turn_time_t key_lifetime = 3600; const char aead_nonce[OAUTH_AEAD_NONCE_SIZE+1] = "h4j3k2l2n4b5"; for (i_hmacs = 0; hmacs[i_hmacs]; ++i_hmacs) { for (i_shas = 0; shas[i_shas]; ++i_shas) { for (i_encs = 0; encs[i_encs]; ++i_encs) { printf("oauth token %s:%s:%s:",hmacs[i_hmacs],shas[i_shas],encs[i_encs]); if(print_extra) printf("\n"); oauth_token ot; ot.enc_block.key_length = (uint16_t)mac_key_length; STRCPY(ot.enc_block.mac_key,mac_key); ot.enc_block.timestamp = token_timestamp; ot.enc_block.lifetime = token_lifetime; oauth_token dot; ns_bzero((&dot),sizeof(dot)); oauth_key key; ns_bzero(&key,sizeof(key)); { oauth_key_data okd; ns_bzero(&okd,sizeof(okd)); { oauth_key_data_raw okdr; ns_bzero(&okdr,sizeof(okdr)); STRCPY(okdr.kid,kid); STRCPY(okdr.ikm_key,base64encoded_ltp); STRCPY(okdr.as_rs_alg, encs[i_encs]); STRCPY(okdr.auth_alg, hmacs[i_hmacs]); STRCPY(okdr.hkdf_hash_func, shas[i_shas]); okdr.timestamp = key_timestamp; okdr.lifetime = key_lifetime; convert_oauth_key_data_raw(&okdr, &okd); char err_msg[1025] = "\0"; size_t err_msg_size = sizeof(err_msg) - 1; if (convert_oauth_key_data(&okd, &key, err_msg, err_msg_size) < 0) { fprintf(stderr, "%s\n", err_msg); return -1; } } } if(print_extra) { print_field5769("AS-RS",key.as_rs_key,key.as_rs_key_size); print_field5769("AUTH",key.auth_key,key.auth_key_size); } { encoded_oauth_token etoken; ns_bzero(&etoken,sizeof(etoken)); if (encode_oauth_token((const u08bits *) server_name, &etoken, &key, &ot, (const u08bits*)aead_nonce) < 0) { fprintf(stderr, "%s: cannot encode oauth token\n", __FUNCTION__); return -1; } if(print_extra) { print_field5769("encoded token",etoken.token,etoken.size); } if (decode_oauth_token((const u08bits *) server_name, &etoken, &key, &dot) < 0) { fprintf(stderr, "%s: cannot decode oauth token\n", __FUNCTION__); return -1; } } if (strcmp((char*) ot.enc_block.mac_key, (char*) dot.enc_block.mac_key)) { fprintf(stderr, "%s: wrong mac key: %s, must be %s\n", __FUNCTION__, (char*) dot.enc_block.mac_key, (char*) ot.enc_block.mac_key); return -1; } if (ot.enc_block.key_length != dot.enc_block.key_length) { fprintf(stderr, "%s: wrong key length: %d, must be %d\n", __FUNCTION__, (int) dot.enc_block.key_length, (int) ot.enc_block.key_length); return -1; } if (ot.enc_block.timestamp != dot.enc_block.timestamp) { fprintf(stderr, "%s: wrong timestamp: %llu, must be %llu\n", __FUNCTION__, (unsigned long long) dot.enc_block.timestamp, (unsigned long long) ot.enc_block.timestamp); return -1; } if (ot.enc_block.lifetime != dot.enc_block.lifetime) { fprintf(stderr, "%s: wrong lifetime: %lu, must be %lu\n", __FUNCTION__, (unsigned long) dot.enc_block.lifetime, (unsigned long) ot.enc_block.lifetime); return -1; } printf("OK\n"); } } } return 0; }
/* * Password retrieval */ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) { int ret = -1; if(max_session_time) *max_session_time = 0; if(in_oauth && out_oauth && usname && usname[0]) { stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(nbh), ioa_network_buffer_get_size(nbh), STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN); if(sar) { int len = stun_attr_get_len(sar); const u08bits *value = stun_attr_get_value(sar); *out_oauth = 1; if(len>0 && value) { const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->get_oauth_key) { oauth_key_data_raw rawKey; ns_bzero(&rawKey,sizeof(rawKey)); int gres = (*(dbd->get_oauth_key))(usname,&rawKey); if(gres<0) return ret; if(!rawKey.kid[0]) return ret; if(rawKey.lifetime) { if(!turn_time_before(turn_time(),(turn_time_t)(rawKey.timestamp + rawKey.lifetime+OAUTH_TIME_DELTA))) { return ret; } } oauth_key_data okd; ns_bzero(&okd,sizeof(okd)); convert_oauth_key_data_raw(&rawKey, &okd); char err_msg[1025] = "\0"; size_t err_msg_size = sizeof(err_msg) - 1; oauth_key okey; ns_bzero(&okey,sizeof(okey)); if (convert_oauth_key_data(&okd, &okey, err_msg, err_msg_size) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s\n", err_msg); return -1; } oauth_token dot; ns_bzero((&dot),sizeof(dot)); encoded_oauth_token etoken; ns_bzero(&etoken,sizeof(etoken)); if((size_t)len > sizeof(etoken.token)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Encoded oAuth token is too large\n"); return -1; } ns_bcopy(value,etoken.token,(size_t)len); etoken.size = (size_t)len; const char* server_name = (char*)turn_params.oauth_server_name; if(!(server_name && server_name[0])) { server_name = (char*)realm; if(!(server_name && server_name[0])) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot determine oAuth server name"); return -1; } } if (decode_oauth_token((const u08bits *) server_name, &etoken,&okey, &dot) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot decode oauth token\n"); return -1; } switch(dot.enc_block.key_length) { case SHA1SIZEBYTES: if(turn_params.shatype != SHATYPE_SHA1) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(1): %d\n",(int)dot.enc_block.key_length); return -1; } break; case SHA256SIZEBYTES: if(turn_params.shatype != SHATYPE_SHA256) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(2): %d\n",(int)dot.enc_block.key_length); return -1; } break; case SHA384SIZEBYTES: if(turn_params.shatype != SHATYPE_SHA384) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length); return -1; } break; case SHA512SIZEBYTES: if(turn_params.shatype != SHATYPE_SHA512) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length); return -1; } break; default: TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length); return -1; }; password_t pwdtmp; if(stun_check_message_integrity_by_key_str(TURN_CREDENTIALS_LONG_TERM, ioa_network_buffer_data(nbh), ioa_network_buffer_get_size(nbh), dot.enc_block.mac_key, pwdtmp, turn_params.shatype,NULL)>0) { turn_time_t lifetime = (turn_time_t)(dot.enc_block.lifetime); if(lifetime) { turn_time_t ts = (turn_time_t)(dot.enc_block.timestamp >> 16); turn_time_t to = ts + lifetime + OAUTH_TIME_DELTA; turn_time_t ct = turn_time(); if(!turn_time_before(ct,to)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "oAuth token is too old\n"); return -1; } if(max_session_time) { *max_session_time = to - ct; } } ns_bcopy(dot.enc_block.mac_key,key,dot.enc_block.key_length); ret = 0; } } }
/* * Password retrieval */ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) { /* Decode certificate */ struct certificate cert; memset(&cert, 0, sizeof cert); unsigned char const *secret_key = (unsigned char *)turn_params.secret_key; unsigned char const *iv = (unsigned char *)turn_params.secret_iv; stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(nbh), ioa_network_buffer_get_size(nbh), STUN_ATTRIBUTE_SOFTWARE); if (sar) { int token_len = stun_attr_get_len(sar); const u08bits* token_ptr = stun_attr_get_value(sar); u08bits token[128]; memcpy(token, token_ptr, token_len); token[token_len]=0; int err = stun_check_message_certificate(token, token_len, &cert, secret_key, iv); if(token_len && err == 0) { const char* password = cert.call_id; size_t sz = get_hmackey_size(SHATYPE_DEFAULT) * 2; char skey[sizeof(hmackey_t) * 2 + 1]; password2hmac(password, usname, realm, skey); if(convert_string_key_to_binary(skey, key, sz / 2) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n", skey, usname); } char buff[20]; struct tm * timeinfo; timeinfo = localtime (&cert.deadline); strftime(buff, sizeof(buff), "%Y %b %d %H:%M", timeinfo); time_t now; now = time(NULL); /* if(now - cert.deadline < -60 || // server's time's wrong? more tann 60 sec time diff now - cert.deadline > 60*60*24 ) // too much diff, something wrong { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Token expired: user: %s token: %s time: %s time_diff: %d sec\n", usname, token, buff, now - cert.deadline); return -1; } */ TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Token decrypted: user:%s seq:%s time:%s call:%s \n", usname, cert.seq, buff, cert.call_id); return 0; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Incorrect token: user %s token: %s Error: %d\n", usname, token, err); return -1; } } else TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Tokent not found: user %s\n", usname); int ret = -1; if(max_session_time) *max_session_time = 0; if(in_oauth && out_oauth && usname && usname[0]) { stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(nbh), ioa_network_buffer_get_size(nbh), STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN); if(sar) { int len = stun_attr_get_len(sar); const u08bits *value = stun_attr_get_value(sar); *out_oauth = 1; if(len>0 && value) { const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->get_oauth_key) { oauth_key_data_raw rawKey; ns_bzero(&rawKey,sizeof(rawKey)); int gres = (*(dbd->get_oauth_key))(usname,&rawKey); if(gres<0) return ret; if(!rawKey.kid[0]) return ret; if(rawKey.lifetime) { if(!turn_time_before(turn_time(),(turn_time_t)(rawKey.timestamp + rawKey.lifetime+OAUTH_TIME_DELTA))) { return ret; } } oauth_key_data okd; ns_bzero(&okd,sizeof(okd)); convert_oauth_key_data_raw(&rawKey, &okd); char err_msg[1025] = "\0"; size_t err_msg_size = sizeof(err_msg) - 1; oauth_key okey; ns_bzero(&okey,sizeof(okey)); if (convert_oauth_key_data(&okd, &okey, err_msg, err_msg_size) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s\n", err_msg); return -1; } oauth_token dot; ns_bzero((&dot),sizeof(dot)); encoded_oauth_token etoken; ns_bzero(&etoken,sizeof(etoken)); if((size_t)len > sizeof(etoken.token)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Encoded oAuth token is too large\n"); return -1; } ns_bcopy(value,etoken.token,(size_t)len); etoken.size = (size_t)len; const char* server_name = (char*)turn_params.oauth_server_name; if(!(server_name && server_name[0])) { server_name = (char*)realm; if(!(server_name && server_name[0])) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot determine oAuth server name"); return -1; } } if (decode_oauth_token((const u08bits *) server_name, &etoken,&okey, &dot) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot decode oauth token\n"); return -1; } switch(dot.enc_block.key_length) { case SHA1SIZEBYTES: break; case SHA256SIZEBYTES: case SHA384SIZEBYTES: case SHA512SIZEBYTES: default: TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length); return -1; }; password_t pwdtmp; if(stun_check_message_integrity_by_key_str(TURN_CREDENTIALS_LONG_TERM, ioa_network_buffer_data(nbh), ioa_network_buffer_get_size(nbh), dot.enc_block.mac_key, pwdtmp, SHATYPE_DEFAULT)>0) { turn_time_t lifetime = (turn_time_t)(dot.enc_block.lifetime); if(lifetime) { turn_time_t ts = (turn_time_t)(dot.enc_block.timestamp >> 16); turn_time_t to = ts + lifetime + OAUTH_TIME_DELTA; turn_time_t ct = turn_time(); if(!turn_time_before(ct,to)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "oAuth token is too old\n"); return -1; } if(max_session_time) { *max_session_time = to - ct; } } ns_bcopy(dot.enc_block.mac_key,key,dot.enc_block.key_length); ret = 0; } } }