Beispiel #1
0
void recalculate_restapi_hmac(void) {

	if (g_use_auth_secret_with_timestamp) {

		u08bits hmac[MAXSHASIZE];
		unsigned int hmac_len;

		hmac_len = SHA256SIZEBYTES;

		hmac[0] = 0;

		if (stun_calculate_hmac(g_uname, strlen((char*) g_uname),
				(u08bits*) g_auth_secret, strlen(g_auth_secret), hmac,
				&hmac_len, SHATYPE_SHA256) >= 0) {
			size_t pwd_length = 0;
			char *pwd = base64_encode(hmac, hmac_len, &pwd_length);

			if (pwd) {
				if (pwd_length > 0) {
					ns_bcopy(pwd,g_upwd,pwd_length);
					g_upwd[pwd_length] = 0;
				}
			}
			turn_free(pwd,strlen(pwd)+1);
		}
	}
}
Beispiel #2
0
int get_canonic_origin(const char* o, char *co, int sz)
{
	int ret = -1;

	if(o && o[0] && co) {
		co[0]=0;
		struct evhttp_uri *uri = evhttp_uri_parse(o);
		if(uri) {
			const char *scheme = evhttp_uri_get_scheme(uri);
			if(scheme && scheme[0]) {
				size_t schlen = strlen(scheme);
				if((schlen<(size_t)sz) && (schlen<STUN_MAX_ORIGIN_SIZE)) {
					const char *host = evhttp_uri_get_host(uri);
					if(host && host[0]) {
						char otmp[STUN_MAX_ORIGIN_SIZE+STUN_MAX_ORIGIN_SIZE];
						ns_bcopy(scheme,otmp,schlen);
						otmp[schlen]=0;

						{
							unsigned char *s = (unsigned char*)otmp;
							while(*s) {
								*s = (unsigned char)tolower((int)*s);
								++s;
							}
						}

						int port = evhttp_uri_get_port(uri);
						if(port<1) {
							port = get_default_protocol_port(otmp, schlen);
						}
						if(port>0)
							snprintf(otmp+schlen,sizeof(otmp)-schlen-1,"://%s:%d",host,port);
						else
							snprintf(otmp+schlen,sizeof(otmp)-schlen-1,"://%s",host);

						{
							unsigned char *s = (unsigned char*)otmp + schlen + 3;
							while(*s) {
								*s = (unsigned char)tolower((int)*s);
								++s;
							}
						}

						strncpy(co,otmp,sz);
						co[sz]=0;
						ret = 0;
					}
				}
			}
			evhttp_uri_free(uri);
		}
	}

	if(ret<0) {
		strncpy(co,o,sz);
		co[sz]=0;
	}

	return ret;
}
Beispiel #3
0
int get_realm_data(char* name, realm_params_t* rp)
{
	lock_realms();
	ns_bcopy(get_realm(name),rp,sizeof(realm_params_t));
	unlock_realms();
	return 0;
}
Beispiel #4
0
int read_mobility_ticket(app_ur_conn_info *clnet_info, stun_buffer *message)
{
	int ret = 0;
	if(clnet_info && message) {
		stun_attr_ref s_mobile_id_sar = stun_attr_get_first_by_type(message, STUN_ATTRIBUTE_MOBILITY_TICKET);
		if(s_mobile_id_sar) {
			int smid_len = stun_attr_get_len(s_mobile_id_sar);
			if(smid_len>0 && (((size_t)smid_len)<sizeof(clnet_info->s_mobile_id))) {
				const u08bits* smid_val = stun_attr_get_value(s_mobile_id_sar);
				if(smid_val) {
					ns_bcopy(smid_val, clnet_info->s_mobile_id, (size_t)smid_len);
					clnet_info->s_mobile_id[smid_len] = 0;
					if (clnet_verbose)
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
									"%s: smid=%s\n", __FUNCTION__, clnet_info->s_mobile_id);
				}
			} else {
				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
							"%s: ERROR: smid_len=%d\n", __FUNCTION__, smid_len);
				ret = -1;
			}
		}
	}
	return ret;
}
Beispiel #5
0
void get_default_realm_options(realm_options_t* ro)
{
	if(ro) {
		lock_realms();
		ns_bcopy(&(default_realm_params_ptr->options),ro,sizeof(realm_options_t));
		unlock_realms();
	}
}
Beispiel #6
0
static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd,
				struct sockaddr *sa, int socklen, void *arg)
{

	UNUSED_ARG(l);

	tcp_listener_relay_server_type * server = (tcp_listener_relay_server_type*) arg;

	if(!(server->e->connect_cb)) {
		close(fd);
		return;
	}

	FUNCSTART;

	if (!server)
		return;

	if (server->stats)
		++(*(server->stats));

	ioa_addr client_addr;
	ns_bcopy(sa,&client_addr,socklen);

	addr_debug_print(server->verbose, &client_addr,"tcp connected to");

	ioa_socket_handle ioas =
				create_ioa_socket_from_fd(
							server->e,
							fd,
							TCP_SOCKET,
							CLIENT_SOCKET,
							&client_addr,
							&(server->addr));

	if (ioas) {
		ioa_net_data nd = { &client_addr, NULL, 0, TTL_IGNORE, TOS_IGNORE };
		int rc = server->e->connect_cb(server->e, ioas, &nd);

		if (rc < 0) {
			TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
					"Cannot create tcp session\n");
			IOA_CLOSE_SOCKET(ioas);
		}
	} else {
		TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
				"Cannot create ioa_socket from FD\n");
		close(fd);
	}

	FUNCEND	;
}
Beispiel #7
0
int get_realm_options_by_origin(char *origin, realm_options_t* ro)
{
	ur_string_map_value_type value = 0;
	TURN_MUTEX_LOCK(&o_to_realm_mutex);
	if (ur_string_map_get(o_to_realm, (ur_string_map_key_type) origin, &value) && value) {
		char *realm = turn_strdup((char*)value);
		TURN_MUTEX_UNLOCK(&o_to_realm_mutex);
		realm_params_t rp;
		get_realm_data(realm, &rp);
		ns_bcopy(&(rp.options),ro,sizeof(realm_options_t));
		turn_free(realm,strlen(realm)+1);
		return 1;
	} else {
		TURN_MUTEX_UNLOCK(&o_to_realm_mutex);
		get_default_realm_options(ro);
		return 0;
	}
}
tcp_connection *create_tcp_connection(u08bits server_id, allocation *a, stun_tid *tid, ioa_addr *peer_addr, int *err_code)
{
	tcp_connection_list *tcl = &(a->tcl);
	while(tcl->next) {
		tcp_connection *otc = (tcp_connection*)(tcl->next);
		if(addr_eq(&(otc->peer_addr),peer_addr)) {
			*err_code = 446;
			return NULL;
		}
		tcl=tcl->next;
	}
	tcp_connection *tc = (tcp_connection*)turn_malloc(sizeof(tcp_connection));
	ns_bzero(tc,sizeof(tcp_connection));
	tcl->next = &(tc->list);
	addr_cpy(&(tc->peer_addr),peer_addr);
	if(tid)
		ns_bcopy(tid,&(tc->tid),sizeof(stun_tid));
	tc->owner = a;
	set_new_tc_id(server_id, tc);
	return tc;
}
Beispiel #9
0
realm_params_t* get_realm(char* name)
{
	if(name && name[0]) {
		lock_realms();
		ur_string_map_value_type value = 0;
		ur_string_map_key_type key = (ur_string_map_key_type)name;
		if (ur_string_map_get(realms, key, &value)) {
			unlock_realms();
			return (realm_params_t*)value;
		} else {
			realm_params_t *ret = (realm_params_t*)turn_malloc(sizeof(realm_params_t));
			ns_bcopy(default_realm_params_ptr,ret,sizeof(realm_params_t));
			STRCPY(ret->options.name,name);
			value = (ur_string_map_value_type)ret;
			ur_string_map_put(realms, key, value);
			ret->status.alloc_counters =  ur_string_map_create(NULL);
			add_to_secrets_list(&realms_list, name);
			unlock_realms();
			return ret;
		}
	}

	return default_realm_params_ptr;
}
Beispiel #10
0
int main(int argc, char **argv)
{
	int port = 0;
	int messagenumber = 5;
	char local_addr[256];
	int c;
	int mclient = 1;
	char peer_address[129] = "\0";
	int peer_port = PEER_DEFAULT_PORT;

	char rest_api_separator = ':';
	int use_null_cipher=0;

	set_logfile("stdout");

	set_execdir();

	set_system_parameters(0);

	ns_bzero(local_addr, sizeof(local_addr));

	while ((c = getopt(argc, argv, "d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:vsyhcxXgtTSAPDNOUHMRIGB")) != -1) {
		switch (c){
		case 'B':
			random_disconnect = 1;
			break;
		case 'G':
			extra_requests = 1;
			break;
		case 'F':
			STRCPY(cipher_suite,optarg);
			break;
		case 'I':
			no_permissions = 1;
			break;
		case 'M':
			mobility = 1;
			break;
		case 'H':
			shatype = SHATYPE_SHA256;
			break;
		case 'E':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			STRCPY(ca_cert_file,fn);
		}
			break;
		case 'O':
			dos = 1;
			break;
		case 'C':
			rest_api_separator=*optarg;
			break;
		case 'D':
			mandatory_channel_padding = 1;
			break;
		case 'N':
			negative_test = 1;
			break;
		case 'R':
			negative_protocol_test = 1;
			break;
		case 'z':
			RTP_PACKET_INTERVAL = atoi(optarg);
			break;
		case 'A':
			use_short_term = 1;
			break;
		case 'u':
			STRCPY(g_uname, optarg);
			break;
		case 'w':
			STRCPY(g_upwd, optarg);
			break;
		case 'g':
			dont_fragment = 1;
			break;
		case 'd':
			STRCPY(client_ifname, optarg);
			break;
		case 'x':
			default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
			break;
		case 'X':
			default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
			break;
		case 'l':
			clmessage_length = atoi(optarg);
			break;
		case 's':
			do_not_use_channel = 1;
			break;
		case 'n':
			messagenumber = atoi(optarg);
			break;
		case 'p':
			port = atoi(optarg);
			break;
		case 'L':
			STRCPY(local_addr, optarg);
			break;
		case 'e':
			STRCPY(peer_address, optarg);
			break;
		case 'r':
			peer_port = atoi(optarg);
			break;
		case 'v':
			clnet_verbose = TURN_VERBOSE_NORMAL;
			break;
		case 'h':
			hang_on = 1;
			break;
		case 'c':
			no_rtcp = 1;
			break;
		case 'm':
			mclient = atoi(optarg);
			break;
		case 'y':
			c2c = 1;
			break;
		case 't':
			use_tcp = 1;
			break;
		case 'P':
			passive_tcp = 1;
			/* implies 'T': */
			/* no break */
		case 'T':
			relay_transport = STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE;
			break;
		case 'U':
		  use_null_cipher = 1;
		  /* implies 'S' */
		  /* no break */
		case 'S':
			use_secure = 1;
			break;
		case 'W':
			g_use_auth_secret_with_timestamp = 1;
			STRCPY(g_auth_secret,optarg);
			break;
		case 'i':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			STRCPY(cert_file,fn);
			free(fn);
		}
			break;
		case 'k':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			STRCPY(pkey_file,fn);
			free(fn);
		}
			break;
		default:
			fprintf(stderr, "%s\n", Usage);
			exit(1);
		}
	}

	if(g_use_auth_secret_with_timestamp) {

		if(use_short_term) {
			fprintf(stderr,"ERROR: You cannot use authentication secret (REST API) with short-term credentials mechanism.\n");
			exit(-1);
		}
		{
			char new_uname[1025];
			const unsigned long exp_time = 3600 * 24; /* one day */
			if(g_uname[0]) {
			  snprintf(new_uname,sizeof(new_uname),"%lu%c%s",(unsigned long)time(NULL) + exp_time,rest_api_separator, (char*)g_uname);
			} else {
			  snprintf(new_uname,sizeof(new_uname),"%lu", (unsigned long)time(NULL) + exp_time);
			}
			STRCPY(g_uname,new_uname);
		}
		{
			u08bits hmac[MAXSHASIZE];
			unsigned int hmac_len;

			switch(shatype) {
			case SHATYPE_SHA256:
				hmac_len = SHA256SIZEBYTES;
				break;
			default:
				hmac_len = SHA1SIZEBYTES;
			};

			hmac[0]=0;

			if(stun_calculate_hmac(g_uname, strlen((char*)g_uname), (u08bits*)g_auth_secret, strlen(g_auth_secret), hmac, &hmac_len, shatype)>=0) {
				size_t pwd_length = 0;
				char *pwd = base64_encode(hmac,hmac_len,&pwd_length);

				if(pwd) {
					if(pwd_length>0) {
						ns_bcopy(pwd,g_upwd,pwd_length);
						g_upwd[pwd_length]=0;
					}
				}
				free(pwd);
			}
		}
	}

	if(is_TCP_relay()) {
		dont_fragment = 0;
		no_rtcp = 1;
		c2c = 1;
		use_tcp = 1;
		do_not_use_channel = 1;
	}

	if(port == 0) {
		if(use_secure)
			port = DEFAULT_STUN_TLS_PORT;
		else
			port = DEFAULT_STUN_PORT;
	}

	if (clmessage_length < (int) sizeof(message_info))
		clmessage_length = (int) sizeof(message_info);

	const int max_header = 100;
	if(clmessage_length > (int)(STUN_BUFFER_SIZE-max_header)) {
		fprintf(stderr,"Message length was corrected to %d\n",(STUN_BUFFER_SIZE-max_header));
		clmessage_length = (int)(STUN_BUFFER_SIZE-max_header);
	}

	if (optind >= argc) {
		fprintf(stderr, "%s\n", Usage);
		exit(-1);
	}

	if (!c2c) {
		if (make_ioa_addr((const u08bits*) peer_address, peer_port, &peer_addr) < 0)
			return -1;
		if(peer_addr.ss.sa_family == AF_INET6)
			default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;

	}

	/* SSL Init ==>> */

	if(use_secure) {

		SSL_load_error_strings();
		OpenSSL_add_ssl_algorithms();

		const char *csuite = "ALL"; //"AES256-SHA" "DH"
		if(use_null_cipher)
			csuite = "eNULL";
		else if(cipher_suite[0])
			csuite=cipher_suite;

		if(use_tcp) {
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(SSLv23_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(SSLv3_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#if defined(SSL_TXT_TLSV1_1)
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_1_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#if defined(SSL_TXT_TLSV1_2)
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_2_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#endif
#endif
		} else {
#if defined(TURN_NO_DTLS)
		  fprintf(stderr,"ERROR: DTLS is not supported.\n");
		  exit(-1);
#else
		  if(OPENSSL_VERSION_NUMBER < 0x10000000L) {
		  	TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: OpenSSL version is rather old, DTLS may not be working correctly.\n");
		  }
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#endif
		}

		int sslind = 0;
		for(sslind = 0; sslind<root_tls_ctx_num; sslind++) {

			if(cert_file[0]) {
				if (!SSL_CTX_use_certificate_chain_file(root_tls_ctx[sslind], cert_file)) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: no certificate found!\n");
					exit(-1);
				}
			}

			if (!SSL_CTX_use_PrivateKey_file(root_tls_ctx[sslind], pkey_file,
						SSL_FILETYPE_PEM)) {
				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: no private key found!\n");
				exit(-1);
			}

			if(cert_file[0]) {
				if (!SSL_CTX_check_private_key(root_tls_ctx[sslind])) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: invalid private key!\n");
					exit(-1);
				}
			}

			if (ca_cert_file[0]) {
				if (!SSL_CTX_load_verify_locations(root_tls_ctx[sslind], ca_cert_file, NULL )) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
							"ERROR: cannot load CA from file: %s\n",
							ca_cert_file);
				}

				/* Set to require peer (client) certificate verification */
				SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_PEER, NULL );

				/* Set the verification depth to 9 */
				SSL_CTX_set_verify_depth(root_tls_ctx[sslind], 9);
			} else {
				SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_NONE, NULL );
			}

			if(!use_tcp)
				SSL_CTX_set_read_ahead(root_tls_ctx[sslind], 1);
		}
	}

	start_mclient(argv[optind], port, client_ifname, local_addr, messagenumber, mclient);

	return 0;
}
Beispiel #11
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;
					}
				}
			}
Beispiel #12
0
void get_realm_options_by_name(char *realm, realm_options_t* ro)
{
	realm_params_t rp;
	get_realm_data(realm, &rp);
	ns_bcopy(&(rp.options),ro,sizeof(realm_options_t));
}
Beispiel #13
0
static int clnet_allocate(int verbose,
		app_ur_conn_info *clnet_info,
		ioa_addr *relay_addr,
		int af,
		char *turn_addr, u16bits *turn_port) {

	int af_cycle = 0;
	int reopen_socket = 0;

	int allocate_finished;

	stun_buffer request_message, response_message;

	beg_allocate:

	allocate_finished=0;

	while (!allocate_finished && af_cycle++ < 32) {

		int allocate_sent = 0;

		if(reopen_socket && !use_tcp) {
			socket_closesocket(clnet_info->fd);
			clnet_info->fd = -1;
			if (clnet_connect(addr_get_port(&(clnet_info->remote_addr)), clnet_info->rsaddr, (u08bits*)clnet_info->ifname, clnet_info->lsaddr,
					verbose, clnet_info) < 0) {
				exit(-1);
			}
			reopen_socket = 0;
		}

		int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4);
		int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6);

		uint64_t reservation_token = 0;
		char* rt = NULL;
		int ep = !no_rtcp && !dual_allocation;

		if(!no_rtcp) {
			if (!never_allocate_rtcp && allocate_rtcp) {
				reservation_token = ioa_ntoh64(current_reservation_token);
				rt = (char*) (&reservation_token);
			}
		}

		if(is_TCP_relay()) {
			ep = -1;
		} else if(rt) {
			ep = -1;
		} else if(!ep) {
			ep = (((u08bits)random()) % 2);
			ep = ep-1;
		}

		if(!dos)
			stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility, rt, ep);
		else
			stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility, rt, ep);

		if(bps)
			stun_attr_add_bandwidth_str(request_message.buf, (size_t*)(&(request_message.len)), bps);

		if(dont_fragment)
			stun_attr_add(&request_message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0);

		add_origin(&request_message);

		if(add_integrity(clnet_info, &request_message)<0) return -1;

		stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len));

		while (!allocate_sent) {

			int len = send_buffer(clnet_info, &request_message,0,0);

			if (len > 0) {
				if (verbose) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allocate sent\n");
				}
				allocate_sent = 1;
			} else {
				perror("send");
				exit(1);
			}
		}

		////////////<<==allocate send

		if(not_rare_event()) return 0;

		////////allocate response==>>
		{
			int allocate_received = 0;
			while (!allocate_received) {

				int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message);

				if (len > 0) {
					if (verbose) {
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
								"allocate response received: \n");
					}
					response_message.len = len;
					int err_code = 0;
					u08bits err_msg[129];
					if (stun_is_success_response(&response_message)) {
						allocate_received = 1;
						allocate_finished = 1;

						if(clnet_info->nonce[0]) {
							if(check_integrity(clnet_info, &response_message)<0)
								return -1;
						}

						if (verbose) {
							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n");
						}
						{
							int found = 0;

							stun_attr_ref sar = stun_attr_get_first(&response_message);
							while (sar) {

								int attr_type = stun_attr_get_type(sar);
								if(attr_type == STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS) {

									if (stun_attr_get_addr(&response_message, sar, relay_addr, NULL) < 0) {
										TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
											"%s: !!!: relay addr cannot be received (1)\n",
											__FUNCTION__);
										return -1;
									} else {
										if (verbose) {
											ioa_addr raddr;
											memcpy(&raddr, relay_addr,sizeof(ioa_addr));
											addr_debug_print(verbose, &raddr,"Received relay addr");
										}

										if(!addr_any(relay_addr)) {
											if(relay_addr->ss.sa_family == AF_INET) {
												if(default_address_family != STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) {
													found = 1;
													addr_cpy(&(clnet_info->relay_addr),relay_addr);
													break;
												}
											}
											if(relay_addr->ss.sa_family == AF_INET6) {
												if(default_address_family == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) {
													found = 1;
													addr_cpy(&(clnet_info->relay_addr),relay_addr);
													break;
												}
											}
										}
									}
								}

								sar = stun_attr_get_next(&response_message,sar);
							}

							if(!found) {
								TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
										"%s: !!!: relay addr cannot be received (2)\n",
										__FUNCTION__);
								return -1;
							}
						}

						stun_attr_ref rt_sar = stun_attr_get_first_by_type(
								&response_message, STUN_ATTRIBUTE_RESERVATION_TOKEN);
						uint64_t rtv = stun_attr_get_reservation_token_value(rt_sar);
						current_reservation_token = rtv;
						if (verbose)
							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
								      "%s: rtv=%llu\n", __FUNCTION__, (long long unsigned int)rtv);

						read_mobility_ticket(clnet_info, &response_message);

					} else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len,
									&err_code,err_msg,sizeof(err_msg),
									clnet_info->realm,clnet_info->nonce,
									clnet_info->server_name, &(clnet_info->oauth))) {
						goto beg_allocate;
					} else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) {

						allocate_received = 1;

						if(err_code == 300) {

							if(clnet_info->nonce[0]) {
								if(check_integrity(clnet_info, &response_message)<0)
									return -1;
							}

							ioa_addr alternate_server;
							if(stun_attr_get_first_addr(&response_message, STUN_ATTRIBUTE_ALTERNATE_SERVER, &alternate_server, NULL)==-1) {
								//error
							} else if(turn_addr && turn_port){
								addr_to_string_no_port(&alternate_server, (u08bits*)turn_addr);
								*turn_port = (u16bits)addr_get_port(&alternate_server);
							}

						}

						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n",
								      err_code,(char*)err_msg);
						if (err_code != 437) {
							allocate_finished = 1;
							current_reservation_token = 0;
							return -1;
						} else {
							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
									"trying allocate again %d...\n", err_code);
							sleep(1);
							reopen_socket = 1;
						}
					} else {
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
									"unknown allocate response\n");
						/* Try again ? */
					}
				} else {
					perror("recv");
					exit(-1);
					break;
				}
			}
		}
	}
	////////////<<== allocate response received

	if(rare_event()) return 0;

	if(!allocate_finished) {
	  TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
			"Cannot complete Allocation\n");
	  exit(-1);
	}

	allocate_rtcp = !allocate_rtcp;

	if (1) {

	  af_cycle = 0;

	  if(clnet_info->s_mobile_id[0]) {

		  int fd = clnet_info->fd;
		  SSL* ssl = clnet_info->ssl;

		  int close_now = (int)(random()%2);

		  if(close_now) {
			  int close_socket = (int)(random()%2);
			  if(ssl && !close_socket) {
				  SSL_shutdown(ssl);
				  SSL_FREE(ssl);
				  fd = -1;
			  } else if(fd>=0) {
				  close(fd);
				  fd = -1;
				  ssl = NULL;
			  }
		  }

		  app_ur_conn_info ci;
		  ns_bcopy(clnet_info,&ci,sizeof(ci));
		  ci.fd = -1;
		  ci.ssl = NULL;
		  clnet_info->fd = -1;
		  clnet_info->ssl = NULL;
		  //Reopen:
		  if(clnet_connect(addr_get_port(&(ci.remote_addr)), ci.rsaddr,
		  		(unsigned char*)ci.ifname, ci.lsaddr, clnet_verbose,
		  		clnet_info)<0) {
			  exit(-1);
		  }

		  if(ssl) {
			  SSL_shutdown(ssl);
		  	  SSL_FREE(ssl);
		  } else if(fd>=0) {
		  	  close(fd);
		  }
	  }

		beg_refresh:

	  if(af_cycle++>32) {
	    TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
			  "Cannot complete Refresh\n");
	    exit(-1);
	  }

		//==>>refresh request, for an example only:
		{
			int refresh_sent = 0;

			stun_init_request(STUN_METHOD_REFRESH, &request_message);
			uint32_t lt = htonl(UCLIENT_SESSION_LIFETIME);
			stun_attr_add(&request_message, STUN_ATTRIBUTE_LIFETIME, (const char*) &lt, 4);

			if(clnet_info->s_mobile_id[0]) {
				stun_attr_add(&request_message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id));
			}

			if(dual_allocation && !mobility) {
				int t = ((u08bits)random())%3;
				if(t) {
					u08bits field[4];
					field[0] = (t==1) ? (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4 : (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
					field[1]=0;
					field[2]=0;
					field[3]=0;
					stun_attr_add(&request_message, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY, (const char*) field, 4);
				}
			}

			add_origin(&request_message);

			if(add_integrity(clnet_info, &request_message)<0) return -1;

			stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len));

			while (!refresh_sent) {

				int len = send_buffer(clnet_info, &request_message, 0,0);

				if (len > 0) {
					if (verbose) {
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "refresh sent\n");
					}
					refresh_sent = 1;

					if(clnet_info->s_mobile_id[0]) {
						usleep(10000);
						send_buffer(clnet_info, &request_message, 0,0);
					}
				} else {
					perror("send");
					exit(1);
				}
			}
		}

		if(not_rare_event()) return 0;

		////////refresh response==>>
		{
			int refresh_received = 0;
			while (!refresh_received) {

				int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message);

				if(clnet_info->s_mobile_id[0]) {
					len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message);
				}

				if (len > 0) {
					if (verbose) {
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
								"refresh response received: \n");
					}
					response_message.len = len;
					int err_code = 0;
					u08bits err_msg[129];
					if (stun_is_success_response(&response_message)) {
						read_mobility_ticket(clnet_info, &response_message);
						refresh_received = 1;
						if (verbose) {
							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n");
						}
					} else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len,
										&err_code,err_msg,sizeof(err_msg),
										clnet_info->realm,clnet_info->nonce,
										clnet_info->server_name, &(clnet_info->oauth))) {
						goto beg_refresh;
					} else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) {
						refresh_received = 1;
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n",
								      err_code,(char*)err_msg);
						return -1;
					} else {
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown refresh response\n");
						/* Try again ? */
					}
				} else {
					perror("recv");
					exit(-1);
					break;
				}
			}
		}
	}

	return 0;
}
static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd,
				struct sockaddr *sa, int socklen, void *arg)
{

	UNUSED_ARG(l);

	tls_listener_relay_server_type * server = (tls_listener_relay_server_type*) arg;

	if(!(server->connect_cb)) {
		socket_closesocket(fd);
		return;
	}

	FUNCSTART;

	if (!server)
		return;

	ns_bcopy(sa,&(server->sm.m.sm.nd.src_addr),socklen);

	addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr),"tcp or tls connected to");

	SOCKET_TYPE st = TENTATIVE_TCP_SOCKET;

	if(no_tls)
		st = TCP_SOCKET;
	else if(no_tcp)
		st = TLS_SOCKET;

	ioa_socket_handle ioas =
				create_ioa_socket_from_fd(
							server->e,
							fd,
							NULL,
							st,
							CLIENT_SOCKET,
							&(server->sm.m.sm.nd.src_addr),
							&(server->addr));

	if (ioas) {

		ioas->listener_server = server;

		server->sm.m.sm.nd.recv_ttl = TTL_IGNORE;
		server->sm.m.sm.nd.recv_tos = TOS_IGNORE;
		server->sm.m.sm.nd.nbh = NULL;
		server->sm.m.sm.s = ioas;
		server->sm.relay_server = server->relay_server;

		int rc = server->connect_cb(server->e, &(server->sm));

		if (rc < 0) {
			TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
					"Cannot create tcp or tls session\n");
		}
	} else {
		TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
				"Cannot create ioa_socket from FD\n");
		socket_closesocket(fd);
	}

	FUNCEND	;
}
Beispiel #15
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;
					}
				}
			}