<commit_before>/*
 * Copyright (C) 2011, 2012, 2013 Citrix Systems
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the project nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include <ifaddrs.h>
#include <getopt.h>
#include <locale.h>
#include <libgen.h>

#include <pthread.h>

#include <signal.h>

#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/resource.h>

#include <event2/bufferevent.h>
#include <event2/buffer.h>

#include "userdb.h"
#include "dbdrivers/dbdriver.h"
#include "mainrelay.h"

#include "ns_turn_utils.h"

#include "ns_turn_server.h"
#include "ns_turn_maps.h"

#include "apputils.h"

//////////// REALM //////////////

static realm_params_t *default_realm_params_ptr = NULL;

static ur_string_map *realms = NULL;
static turn_mutex o_to_realm_mutex;
static ur_string_map *o_to_realm = NULL;
static secrets_list_t realms_list;

void lock_realms(void) {
	ur_string_map_lock(realms);
}

void unlock_realms(void) {
	ur_string_map_unlock(realms);
}

void update_o_to_realm(ur_string_map * o_to_realm_new) {
  TURN_MUTEX_LOCK(&o_to_realm_mutex);
  ur_string_map_free(&o_to_realm);
  o_to_realm = o_to_realm_new;
  TURN_MUTEX_UNLOCK(&o_to_realm_mutex);
}

void create_default_realm()
{
	if(default_realm_params_ptr) {
		return;
	}

	static realm_params_t _default_realm_params =
	{
	  1,
	  {
		"\0", /* name */
	    {0,0,0}
	  },
	  {0,NULL}
	};

	/* init everything: */
	TURN_MUTEX_INIT_RECURSIVE(&o_to_realm_mutex);
	init_secrets_list(&realms_list);
	o_to_realm = ur_string_map_create(free);
	default_realm_params_ptr = &_default_realm_params;
	realms = ur_string_map_create(NULL);
	ur_string_map_lock(realms);
	default_realm_params_ptr->status.alloc_counters =  ur_string_map_create(NULL);
	ur_string_map_unlock(realms);
}

void get_default_realm_options(realm_options_t* ro)
{
	if(ro) {
		ur_string_map_lock(realms);
		ns_bcopy(&(default_realm_params_ptr->options),ro,sizeof(realm_options_t));
		ur_string_map_unlock(realms);
	}
}

void set_default_realm_name(char *realm) {
	ur_string_map_lock(realms);
	ur_string_map_value_type value = (ur_string_map_value_type)default_realm_params_ptr;
	STRCPY(default_realm_params_ptr->options.name,realm);
	ur_string_map_put(realms, (ur_string_map_key_type)default_realm_params_ptr->options.name, value);
	add_to_secrets_list(&realms_list, realm);
	ur_string_map_unlock(realms);
}

realm_params_t* get_realm(char* name)
{
	if(name && name[0]) {
		ur_string_map_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)) {
			ur_string_map_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);
			ur_string_map_unlock(realms);
			return ret;
		}
	}

	return default_realm_params_ptr;
}

int get_realm_data(char* name, realm_params_t* rp)
{
	ur_string_map_lock(realms);
	ns_bcopy(get_realm(name),rp,sizeof(realm_params_t));
	ur_string_map_unlock(realms);
	return 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 = 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));
		free(realm);
		return 1;
	} else {
		TURN_MUTEX_UNLOCK(&o_to_realm_mutex);
		get_default_realm_options(ro);
		return 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));
}

int change_total_quota(char *realm, int value)
{
	int ret = value;
	ur_string_map_lock(realms);
	realm_params_t* rp = get_realm(realm);
	rp->options.perf_options.total_quota = value;
	ur_string_map_unlock(realms);
	return ret;
}

int change_user_quota(char *realm, int value)
{
	int ret = value;
	ur_string_map_lock(realms);
	realm_params_t* rp = get_realm(realm);
	rp->options.perf_options.user_quota = value;
	ur_string_map_unlock(realms);
	return ret;
}

static void must_set_admin_realm(void *realm0)
{
	char* realm = (char*)realm0;
	if(!realm || !realm[0]) {
		fprintf(stderr, "The operation cannot be completed: the realm must be set.\n");
		exit(-1);
	}
}

static void must_set_admin_user(void *user0)
{
	char* user = (char*)user0;
	if(!user || !user[0]) {
		fprintf(stderr, "The operation cannot be completed: the user must be set.\n");
		exit(-1);
	}
}

static void must_set_admin_pwd(void *pwd0)
{
	char* pwd = (char*)pwd0;
	if(!pwd || !pwd[0]) {
		fprintf(stderr, "The operation cannot be completed: the password must be set.\n");
		exit(-1);
	}
}

static void must_set_admin_origin(void *origin0)
{
	char* origin = (char*)origin0;
	if(!origin || !origin[0]) {
		fprintf(stderr, "The operation cannot be completed: the origin must be set.\n");
		exit(-1);
	}
}

/////////// SHARED SECRETS /////////////////

void init_secrets_list(secrets_list_t *sl)
{
	if(sl) {
		ns_bzero(sl,sizeof(secrets_list_t));
	}
}

void clean_secrets_list(secrets_list_t *sl)
{
	if(sl) {
		if(sl->secrets) {
			size_t i = 0;
			for(i = 0;i<sl->sz;++i) {
				if(sl->secrets[i]) {
					turn_free(sl->secrets[i], strlen(sl->secrets[i])+1);
				}
			}
			turn_free(sl->secrets,(sl->sz)*sizeof(char*));
			sl->secrets = NULL;
			sl->sz = 0;
		}
	}
}

size_t get_secrets_list_size(secrets_list_t *sl)
{
	if(sl && sl->secrets) {
		return sl->sz;
	}
	return 0;
}

const char* get_secrets_list_elem(secrets_list_t *sl, size_t i)
{
	if(get_secrets_list_size(sl)>i) {
		return sl->secrets[i];
	}
	return NULL;
}

void add_to_secrets_list(secrets_list_t *sl, const char* elem)
{
	if(sl && elem) {
		sl->secrets = (char**)realloc(sl->secrets,(sizeof(char*)*(sl->sz+1)));
		sl->secrets[sl->sz] = strdup(elem);
		sl->sz += 1;
	}
}

////////////////////////////////////////////

static int get_auth_secrets(secrets_list_t *sl, u08bits *realm)
{
	int ret = -1;
  turn_dbdriver_t * dbd = get_dbdriver();

	clean_secrets_list(sl);

	if(get_secrets_list_size(&turn_params.default_users_db.ram_db.static_auth_secrets)) {
		size_t i = 0;
		for(i=0;i<get_secrets_list_size(&turn_params.default_users_db.ram_db.static_auth_secrets);++i) {
			add_to_secrets_list(sl,get_secrets_list_elem(&turn_params.default_users_db.ram_db.static_auth_secrets,i));
		}
		ret=0;
	}
  
  if (dbd && dbd->get_auth_secrets) {
    ret = (*dbd->get_auth_secrets)(sl, realm);
  }

	return ret;
}

/*
 * Timestamp retrieval
 */
static turn_time_t get_rest_api_timestamp(char *usname)
{
	turn_time_t ts = 0;
	int ts_set = 0;

	char *col = strchr(usname,turn_params.rest_api_separator);

	if(col) {
		if(col == usname) {
			usname +=1;
		} else {
			char *ptr = usname;
			int found_non_figure = 0;
			while(ptr < col) {
				if(!(ptr[0]>='0' && ptr[0]<='9')) {
					found_non_figure=1;
					break;
				}
				++ptr;
			}
			if(found_non_figure) {
				ts = (turn_time_t)atol(col+1);
				ts_set = 1;
			} else {
				*col=0;
				ts = (turn_time_t)atol(usname);
				ts_set = 1;
				*col=turn_params.rest_api_separator;
			}
		}
	}

	if(!ts_set) {
		ts = (turn_time_t)atol(usname);
	}

	return ts;
}

static char *get_real_username(char *usname)
{
	if(usname[0] && turn_params.use_auth_secret_with_timestamp) {
		char *col=strchr(usname,turn_params.rest_api_separator);
		if(col) {
			if(col == usname) {
				usname +=1;
			} else {
				char *ptr = usname;
				int found_non_figure = 0;
				while(ptr < col) {
					if(!(ptr[0]>='0' && ptr[0]<='9')) {
						found_non_figure=1;
						break;
					}
					++ptr;
				}
				if(!found_non_figure) {
					usname = col+1;
				} else {
					*col=0;
					usname = strdup(usname);
					*col=turn_params.rest_api_separator;
					return usname;
				}
			}
		}
	}

	return strdup(usname);
}

/*
 * 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] && realm && realm[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) {

				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 (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;
					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;
					};

					st_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;
								if(*max_session_time > OAUTH_TIME_DELTA)
									*max_session_time -= OAUTH_TIME_DELTA;
								if(*max_session_time < OAUTH_TIME_DELTA)
									*max_session_time = OAUTH_TIME_DELTA;
							}
						}

						ns_bcopy(dot.enc_block.mac_key,key,dot.enc_block.key_length);

						ret = 0;
					}
				}
			}
		}
	}
<commit_msg>time fix<commit_after>/*
 * Copyright (C) 2011, 2012, 2013 Citrix Systems
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the project nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include <ifaddrs.h>
#include <getopt.h>
#include <locale.h>
#include <libgen.h>

#include <pthread.h>

#include <signal.h>

#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/resource.h>

#include <event2/bufferevent.h>
#include <event2/buffer.h>

#include "userdb.h"
#include "dbdrivers/dbdriver.h"
#include "mainrelay.h"

#include "ns_turn_utils.h"

#include "ns_turn_server.h"
#include "ns_turn_maps.h"

#include "apputils.h"

//////////// REALM //////////////

static realm_params_t *default_realm_params_ptr = NULL;

static ur_string_map *realms = NULL;
static turn_mutex o_to_realm_mutex;
static ur_string_map *o_to_realm = NULL;
static secrets_list_t realms_list;

void lock_realms(void) {
	ur_string_map_lock(realms);
}

void unlock_realms(void) {
	ur_string_map_unlock(realms);
}

void update_o_to_realm(ur_string_map * o_to_realm_new) {
  TURN_MUTEX_LOCK(&o_to_realm_mutex);
  ur_string_map_free(&o_to_realm);
  o_to_realm = o_to_realm_new;
  TURN_MUTEX_UNLOCK(&o_to_realm_mutex);
}

void create_default_realm()
{
	if(default_realm_params_ptr) {
		return;
	}

	static realm_params_t _default_realm_params =
	{
	  1,
	  {
		"\0", /* name */
	    {0,0,0}
	  },
	  {0,NULL}
	};

	/* init everything: */
	TURN_MUTEX_INIT_RECURSIVE(&o_to_realm_mutex);
	init_secrets_list(&realms_list);
	o_to_realm = ur_string_map_create(free);
	default_realm_params_ptr = &_default_realm_params;
	realms = ur_string_map_create(NULL);
	ur_string_map_lock(realms);
	default_realm_params_ptr->status.alloc_counters =  ur_string_map_create(NULL);
	ur_string_map_unlock(realms);
}

void get_default_realm_options(realm_options_t* ro)
{
	if(ro) {
		ur_string_map_lock(realms);
		ns_bcopy(&(default_realm_params_ptr->options),ro,sizeof(realm_options_t));
		ur_string_map_unlock(realms);
	}
}

void set_default_realm_name(char *realm) {
	ur_string_map_lock(realms);
	ur_string_map_value_type value = (ur_string_map_value_type)default_realm_params_ptr;
	STRCPY(default_realm_params_ptr->options.name,realm);
	ur_string_map_put(realms, (ur_string_map_key_type)default_realm_params_ptr->options.name, value);
	add_to_secrets_list(&realms_list, realm);
	ur_string_map_unlock(realms);
}

realm_params_t* get_realm(char* name)
{
	if(name && name[0]) {
		ur_string_map_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)) {
			ur_string_map_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);
			ur_string_map_unlock(realms);
			return ret;
		}
	}

	return default_realm_params_ptr;
}

int get_realm_data(char* name, realm_params_t* rp)
{
	ur_string_map_lock(realms);
	ns_bcopy(get_realm(name),rp,sizeof(realm_params_t));
	ur_string_map_unlock(realms);
	return 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 = 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));
		free(realm);
		return 1;
	} else {
		TURN_MUTEX_UNLOCK(&o_to_realm_mutex);
		get_default_realm_options(ro);
		return 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));
}

int change_total_quota(char *realm, int value)
{
	int ret = value;
	ur_string_map_lock(realms);
	realm_params_t* rp = get_realm(realm);
	rp->options.perf_options.total_quota = value;
	ur_string_map_unlock(realms);
	return ret;
}

int change_user_quota(char *realm, int value)
{
	int ret = value;
	ur_string_map_lock(realms);
	realm_params_t* rp = get_realm(realm);
	rp->options.perf_options.user_quota = value;
	ur_string_map_unlock(realms);
	return ret;
}

static void must_set_admin_realm(void *realm0)
{
	char* realm = (char*)realm0;
	if(!realm || !realm[0]) {
		fprintf(stderr, "The operation cannot be completed: the realm must be set.\n");
		exit(-1);
	}
}

static void must_set_admin_user(void *user0)
{
	char* user = (char*)user0;
	if(!user || !user[0]) {
		fprintf(stderr, "The operation cannot be completed: the user must be set.\n");
		exit(-1);
	}
}

static void must_set_admin_pwd(void *pwd0)
{
	char* pwd = (char*)pwd0;
	if(!pwd || !pwd[0]) {
		fprintf(stderr, "The operation cannot be completed: the password must be set.\n");
		exit(-1);
	}
}

static void must_set_admin_origin(void *origin0)
{
	char* origin = (char*)origin0;
	if(!origin || !origin[0]) {
		fprintf(stderr, "The operation cannot be completed: the origin must be set.\n");
		exit(-1);
	}
}

/////////// SHARED SECRETS /////////////////

void init_secrets_list(secrets_list_t *sl)
{
	if(sl) {
		ns_bzero(sl,sizeof(secrets_list_t));
	}
}

void clean_secrets_list(secrets_list_t *sl)
{
	if(sl) {
		if(sl->secrets) {
			size_t i = 0;
			for(i = 0;i<sl->sz;++i) {
				if(sl->secrets[i]) {
					turn_free(sl->secrets[i], strlen(sl->secrets[i])+1);
				}
			}
			turn_free(sl->secrets,(sl->sz)*sizeof(char*));
			sl->secrets = NULL;
			sl->sz = 0;
		}
	}
}

size_t get_secrets_list_size(secrets_list_t *sl)
{
	if(sl && sl->secrets) {
		return sl->sz;
	}
	return 0;
}

const char* get_secrets_list_elem(secrets_list_t *sl, size_t i)
{
	if(get_secrets_list_size(sl)>i) {
		return sl->secrets[i];
	}
	return NULL;
}

void add_to_secrets_list(secrets_list_t *sl, const char* elem)
{
	if(sl && elem) {
		sl->secrets = (char**)realloc(sl->secrets,(sizeof(char*)*(sl->sz+1)));
		sl->secrets[sl->sz] = strdup(elem);
		sl->sz += 1;
	}
}

////////////////////////////////////////////

static int get_auth_secrets(secrets_list_t *sl, u08bits *realm)
{
	int ret = -1;
  turn_dbdriver_t * dbd = get_dbdriver();

	clean_secrets_list(sl);

	if(get_secrets_list_size(&turn_params.default_users_db.ram_db.static_auth_secrets)) {
		size_t i = 0;
		for(i=0;i<get_secrets_list_size(&turn_params.default_users_db.ram_db.static_auth_secrets);++i) {
			add_to_secrets_list(sl,get_secrets_list_elem(&turn_params.default_users_db.ram_db.static_auth_secrets,i));
		}
		ret=0;
	}
  
  if (dbd && dbd->get_auth_secrets) {
    ret = (*dbd->get_auth_secrets)(sl, realm);
  }

	return ret;
}

/*
 * Timestamp retrieval
 */
static turn_time_t get_rest_api_timestamp(char *usname)
{
	turn_time_t ts = 0;
	int ts_set = 0;

	char *col = strchr(usname,turn_params.rest_api_separator);

	if(col) {
		if(col == usname) {
			usname +=1;
		} else {
			char *ptr = usname;
			int found_non_figure = 0;
			while(ptr < col) {
				if(!(ptr[0]>='0' && ptr[0]<='9')) {
					found_non_figure=1;
					break;
				}
				++ptr;
			}
			if(found_non_figure) {
				ts = (turn_time_t)atol(col+1);
				ts_set = 1;
			} else {
				*col=0;
				ts = (turn_time_t)atol(usname);
				ts_set = 1;
				*col=turn_params.rest_api_separator;
			}
		}
	}

	if(!ts_set) {
		ts = (turn_time_t)atol(usname);
	}

	return ts;
}

static char *get_real_username(char *usname)
{
	if(usname[0] && turn_params.use_auth_secret_with_timestamp) {
		char *col=strchr(usname,turn_params.rest_api_separator);
		if(col) {
			if(col == usname) {
				usname +=1;
			} else {
				char *ptr = usname;
				int found_non_figure = 0;
				while(ptr < col) {
					if(!(ptr[0]>='0' && ptr[0]<='9')) {
						found_non_figure=1;
						break;
					}
					++ptr;
				}
				if(!found_non_figure) {
					usname = col+1;
				} else {
					*col=0;
					usname = strdup(usname);
					*col=turn_params.rest_api_separator;
					return usname;
				}
			}
		}
	}

	return strdup(usname);
}

/*
 * 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] && realm && realm[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) {

				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 (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;
					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;
					};

					st_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;
					}
				}
			}
		}
	}

{'fraction_non_alphanumeric': 0.13257046140260506, 'fraction_numerical': 0.009419383324747958, 'mean_word_length': 4.054677329365817, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 116, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5158139', 'n_tokens_mistral': 12440, 'n_tokens_neox': 10731, 'n_words': 1955}