<commit_before>/*

SPDX-License-Identifier: MPL-2.0

 libCWebUI
 Copyright (C) 2007 - 2019  <NAME>

 Projekt URL : https://github.com/lordrasmus/libcwebui

 
 This Source Code Form is subject to the terms of the Mozilla Public
 License, v. 2.0. If a copy of the MPL was not distributed with this
 file, You can obtain one at https://mozilla.org/MPL/2.0/. 

*/


#include "webserver.h"

#include "stack.h"


#ifdef DMALLOC
#include <dmalloc/dmalloc.h>
#endif

/* * Session Managment *
// http://de.wikipedia.org/wiki/Session-ID
// Formulare mit versteckten Feldern
// Status in der URI
// HTTP Cookies  -  umgesetzt

// http://www.erich-kachel.de/?p=368  ->  Session-Angriffe - eine Analyse an PHP

// * Web Based Session Management
// * Best practices in managing HTTP-based client sessions
// http://www.technicalinfo.net/papers/WebBasedSessionManagement.html

// * generierung von session-ids *
// http://www.scip.ch/?labs.20101013

// * optimierungen *
// beim erzeugen eines session stores für eine session immer eine neue session-id generieren ( session fixation )
*/

static rb_red_blk_tree* session_store_tree;
static WS_MUTEX session_mutex;
static unsigned long last_timeout_check = 0;


static void SessionFreerFunc(void* a){
	sessionStore* ss=(sessionStore*)a;
	WebserverFreeSessionStore(ss);
}



static ws_variable* int_getSessionValue(http_request* s, STORE_TYPES store, const char* name);
static char int_setSessionValue(http_request* s, STORE_TYPES store, const char* name, const char* value);
static ws_variable* int_addSessionValue(http_request* s, STORE_TYPES store, const char* name );

void initSessions(void) {
	session_store_tree = RBTreeCreate(StrKeyComp, DummyFunc, SessionFreerFunc, DummyFuncConst, DummyFunc);

	PlatformCreateMutex( &session_mutex );
}

void freeSessions(void){
	RBTreeDestroy(session_store_tree);
}

#if 0
static void DummFreeFunc( UNUSED_PARA void * a){

}
#endif

static void checkSessionTimeout(void) {
	sessionStore* ss;
	unsigned long diff;
	unsigned int deleted = 0;
	stk_stack* stack;
	rb_red_blk_node* node;
	list_t del_list;

	/* nur alle 10 sekunden auf timeouts testen */
	diff = PlatformGetTick() - last_timeout_check;
	if (diff < (10 * PlatformGetTicksPerSeconde())){
		return;
	}

	last_timeout_check = PlatformGetTick();

	PlatformLockMutex( &session_mutex );

	ws_list_init(&del_list);
	stack = RBEnumerate(session_store_tree, (void*)"0", (void*)"z");

	while (0 != StackNotEmpty(stack)) {
		int timeout;

		node = (rb_red_blk_node*) StackPop(stack);
		ss = (sessionStore*) node->info;
		diff = PlatformGetTick() - ss->last_use;

		timeout = getConfigInt("session_timeout");

		if ( ( timeout != 0 ) && ( diff > timeout * PlatformGetTicksPerSeconde() ) ) {
#ifdef _WEBSERVER_SESSION_DEBUG_
			WebServerPrintf("Delete SessionStore GUID : %s\r\n",ss->guid);
#endif
			ws_list_append(&del_list, node);
			deleted++;
		}
	}
	free(stack);

	if (ws_list_size(&del_list) > 0) {
		ws_list_iterator_start(&del_list);
		while ((node = (rb_red_blk_node*) ws_list_iterator_next(&del_list))) {

			/*
			 Freigeben der Elemente ist in der RBTree Freer Function eingetragen ( SessionFreerFunc )
			*/
			RBDelete(session_store_tree, node);
		}
		ws_list_iterator_stop(&del_list);
	}
	ws_list_destroy(&del_list);

	PlatformUnlockMutex( &session_mutex );

#ifdef _WEBSERVER_SESSION_DEBUG_
	if (deleted > 0){
		WebServerPrintf("Deleted Sessions %d\n",deleted);
	}
#endif

}

static char guid_cmp(const char* a, const char* b) {
	int i;
	if (a[0] == 0){
		return 0;
	}
	for (i = 0; i < WEBSERVER_GUID_LENGTH; i++) {
		if (a[i] != b[i]){
			return 0;
		}
	}
	return 1;
}

int checkUserRegistered(http_request* s) {

	bool true_normal, got_giud;

	ws_variable* var;
	ws_variable* guid_var;

#ifdef WEBSERVER_USE_SSL

	bool true_ssl, got_normal, got_guid_ssl, true_both, guid_match;

	ws_variable* guid_var_ssl;

	true_ssl = false;
	true_both = false;
	got_guid_ssl = false;
	guid_match = false;
	got_normal = false;   

#endif

	true_normal = false;
	got_giud = false;

	PlatformLockMutex( &session_mutex );

	var = int_getSessionValue(s, SESSION_STORE, (char*) "registered");
	if (var != 0) {
#ifdef WEBSERVER_USE_SSL
		got_normal = true;
#endif
		if (var->type == VAR_TYPE_STRING) {
			if (0 == strcmp(var->val.value_string, "true")) {
				true_normal = true;
			} else {
				PlatformUnlockMutex( &session_mutex );
				return NOT_REGISTERED;
			}
		} else {
			PlatformUnlockMutex( &session_mutex );
			return NOT_REGISTERED;
		}
	} else {
		PlatformUnlockMutex( &session_mutex );
		return NOT_REGISTERED;
	}

#ifdef WEBSERVER_USE_SSL
	if (s->socket->use_ssl == 1) {
		var = int_getSessionValue(s, SESSION_STORE_SSL, (char*) "registered");
		if (var != 0) {
			if (var->type == VAR_TYPE_STRING) {
				if (0 == strcmp(var->val.value_string, "true")) {
					true_ssl = true;
					if (true_normal){
						true_both = true;
					}
				}
			}
		}
	}
#endif

	guid_var = int_getSessionValue(s, SESSION_STORE, (char*) "session-id");
	if (guid_var != 0) {
		got_giud = true;
	} else {
		PlatformUnlockMutex( &session_mutex );
		return NOT_REGISTERED;
	}

#ifdef WEBSERVER_USE_SSL
	if (s->socket->use_ssl == 1) {
		guid_var_ssl = int_getSessionValue(s, SESSION_STORE_SSL, (char*) "session-id-ssl");
		if (0 != guid_var_ssl) {
			got_guid_ssl = true;
			if (guid_cmp(guid_var->val.value_string, guid_var_ssl->val.value_string)) {
				guid_match = true;
				if (guid_match && true_both){
					PlatformUnlockMutex( &session_mutex );
					return SSL_CHECK_OK;
				}
			}
		}
	}

	PlatformUnlockMutex( &session_mutex );

	if (s->socket->use_ssl == 1) {
		if (got_guid_ssl != got_giud){
			return SESSION_MISMATCH_ERROR;
		}
		if (guid_match != true_both){
			return SESSION_MISMATCH_ERROR;
		}
		if (got_guid_ssl && got_normal && (true_normal != true_ssl)){
			return SESSION_MISMATCH_ERROR;
		}
	}
#endif



	if (got_giud && true_normal){
		return NORMAL_CHECK_OK;
	}

	return NOT_REGISTERED;
}

char setUserRegistered(http_request* s, char status) {
	ws_variable* var;
	static char buf1[WEBSERVER_GUID_LENGTH + 1];



	if(	status==false) {
		if (NOT_REGISTERED!=checkUserRegistered(s)) {<commit_msg>Session GUID compare fix<commit_after>/*

SPDX-License-Identifier: MPL-2.0

 libCWebUI
 Copyright (C) 2007 - 2019  <NAME>

 Projekt URL : https://github.com/lordrasmus/libcwebui

 
 This Source Code Form is subject to the terms of the Mozilla Public
 License, v. 2.0. If a copy of the MPL was not distributed with this
 file, You can obtain one at https://mozilla.org/MPL/2.0/. 

*/


#include "webserver.h"

#include "stack.h"


#ifdef DMALLOC
#include <dmalloc/dmalloc.h>
#endif

/* * Session Managment *
// http://de.wikipedia.org/wiki/Session-ID
// Formulare mit versteckten Feldern
// Status in der URI
// HTTP Cookies  -  umgesetzt

// http://www.erich-kachel.de/?p=368  ->  Session-Angriffe - eine Analyse an PHP

// * Web Based Session Management
// * Best practices in managing HTTP-based client sessions
// http://www.technicalinfo.net/papers/WebBasedSessionManagement.html

// * generierung von session-ids *
// http://www.scip.ch/?labs.20101013

// * optimierungen *
// beim erzeugen eines session stores für eine session immer eine neue session-id generieren ( session fixation )
*/

static rb_red_blk_tree* session_store_tree;
static WS_MUTEX session_mutex;
static unsigned long last_timeout_check = 0;


static void SessionFreerFunc(void* a){
	sessionStore* ss=(sessionStore*)a;
	WebserverFreeSessionStore(ss);
}



static ws_variable* int_getSessionValue(http_request* s, STORE_TYPES store, const char* name);
static char int_setSessionValue(http_request* s, STORE_TYPES store, const char* name, const char* value);
static ws_variable* int_addSessionValue(http_request* s, STORE_TYPES store, const char* name );

void initSessions(void) {
	session_store_tree = RBTreeCreate(StrKeyComp, DummyFunc, SessionFreerFunc, DummyFuncConst, DummyFunc);

	PlatformCreateMutex( &session_mutex );
}

void freeSessions(void){
	RBTreeDestroy(session_store_tree);
}

#if 0
static void DummFreeFunc( UNUSED_PARA void * a){

}
#endif

static void checkSessionTimeout(void) {
	sessionStore* ss;
	unsigned long diff;
	unsigned int deleted = 0;
	stk_stack* stack;
	rb_red_blk_node* node;
	list_t del_list;

	/* nur alle 10 sekunden auf timeouts testen */
	diff = PlatformGetTick() - last_timeout_check;
	if (diff < (10 * PlatformGetTicksPerSeconde())){
		return;
	}

	last_timeout_check = PlatformGetTick();

	PlatformLockMutex( &session_mutex );

	ws_list_init(&del_list);
	stack = RBEnumerate(session_store_tree, (void*)"0", (void*)"z");

	while (0 != StackNotEmpty(stack)) {
		int timeout;

		node = (rb_red_blk_node*) StackPop(stack);
		ss = (sessionStore*) node->info;
		diff = PlatformGetTick() - ss->last_use;

		timeout = getConfigInt("session_timeout");

		if ( ( timeout != 0 ) && ( diff > timeout * PlatformGetTicksPerSeconde() ) ) {
#ifdef _WEBSERVER_SESSION_DEBUG_
			WebServerPrintf("Delete SessionStore GUID : %s\r\n",ss->guid);
#endif
			ws_list_append(&del_list, node);
			deleted++;
		}
	}
	free(stack);

	if (ws_list_size(&del_list) > 0) {
		ws_list_iterator_start(&del_list);
		while ((node = (rb_red_blk_node*) ws_list_iterator_next(&del_list))) {

			/*
			 Freigeben der Elemente ist in der RBTree Freer Function eingetragen ( SessionFreerFunc )
			*/
			RBDelete(session_store_tree, node);
		}
		ws_list_iterator_stop(&del_list);
	}
	ws_list_destroy(&del_list);

	PlatformUnlockMutex( &session_mutex );

#ifdef _WEBSERVER_SESSION_DEBUG_
	if (deleted > 0){
		WebServerPrintf("Deleted Sessions %d\n",deleted);
	}
#endif

}

static char guid_cmp(const char* a, const char* b) {
	int i;
	if (a[0] == 0){
		return 0;
	}
	for (i = 0; i < WEBSERVER_GUID_LENGTH; i++) {
		if ( ( a[i] == b[i] ) && ( a[i] == 0 ) ) break;

		if (a[i] != b[i]){
			return 0;
		}
	}
	return 1;
}

int checkUserRegistered(http_request* s) {

	bool true_normal, got_giud;

	ws_variable* var;
	ws_variable* guid_var;

#ifdef WEBSERVER_USE_SSL

	bool true_ssl, got_normal, got_guid_ssl, true_both, guid_match;

	ws_variable* guid_var_ssl;

	true_ssl = false;
	true_both = false;
	got_guid_ssl = false;
	guid_match = false;
	got_normal = false;   

#endif

	true_normal = false;
	got_giud = false;

	PlatformLockMutex( &session_mutex );

	var = int_getSessionValue(s, SESSION_STORE, (char*) "registered");
	if (var != 0) {
#ifdef WEBSERVER_USE_SSL
		got_normal = true;
#endif
		if (var->type == VAR_TYPE_STRING) {
			if (0 == strcmp(var->val.value_string, "true")) {
				true_normal = true;
			} else {
				PlatformUnlockMutex( &session_mutex );
				return NOT_REGISTERED;
			}
		} else {
			PlatformUnlockMutex( &session_mutex );
			return NOT_REGISTERED;
		}
	} else {
		PlatformUnlockMutex( &session_mutex );
		return NOT_REGISTERED;
	}

#ifdef WEBSERVER_USE_SSL
	if (s->socket->use_ssl == 1) {
		var = int_getSessionValue(s, SESSION_STORE_SSL, (char*) "registered");
		if (var != 0) {
			if (var->type == VAR_TYPE_STRING) {
				if (0 == strcmp(var->val.value_string, "true")) {
					true_ssl = true;
					if (true_normal){
						true_both = true;
					}
				}
			}
		}
	}
#endif

	guid_var = int_getSessionValue(s, SESSION_STORE, (char*) "session-id");
	if (guid_var != 0) {
		got_giud = true;
	} else {
		PlatformUnlockMutex( &session_mutex );
		return NOT_REGISTERED;
	}

#ifdef WEBSERVER_USE_SSL
	if (s->socket->use_ssl == 1) {
		guid_var_ssl = int_getSessionValue(s, SESSION_STORE_SSL, (char*) "session-id-ssl");
		if (0 != guid_var_ssl) {
			got_guid_ssl = true;
			//printf("guid_var->val.value_string     : %s\n",guid_var->val.value_string);
			//printf("guid_var_ssl->val.value_string : %s\n",guid_var_ssl->val.value_string);
			if (guid_cmp(guid_var->val.value_string, guid_var_ssl->val.value_string)) {
				guid_match = true;
				if (guid_match && true_both){
					PlatformUnlockMutex( &session_mutex );
					return SSL_CHECK_OK;
				}
			}
		}
	}

	PlatformUnlockMutex( &session_mutex );

	if (s->socket->use_ssl == 1) {
		/*printf("got_guid_ssl: %d\n",got_guid_ssl);
		printf("got_normal: %d\n",got_normal);
		printf("got_giud: %d\n",got_giud);
		printf("true_both: %d\n",true_both);
		printf("true_normal: %d\n",true_normal);
		printf("true_ssl: %d\n",true_ssl);
		printf("guid_match: %d\n",guid_match);*/

		if (got_guid_ssl != got_giud){
			return SESSION_MISMATCH_ERROR;
		}

		if (guid_match != true_both){
			return SESSION_MISMATCH_ERROR;
		}

		if (got_guid_ssl && got_normal && (true_normal != true_ssl)){
			return SESSION_MISMATCH_ERROR;
		}
	}
#endif



	if (got_giud && true_normal){
		return NORMAL_CHECK_OK;
	}

	return NOT_REGISTERED;
}

char setUserRegistered(http_request* s, char status) {
	ws_variable* var;
	static char buf1[WEBSERVER_GUID_LENGTH + 1];



	if(	status==false) {
		if (NOT_REGISTERED!=checkUserRegistered(s)) {
{'fraction_non_alphanumeric': 0.12946149029430182, 'fraction_numerical': 0.008531621790857858, 'mean_word_length': 4.3104738154613464, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 49, 'https://': 4, 'lorem ipsum': 0, 'www.': 6, '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': '3051548', 'n_tokens_mistral': 5177, 'n_tokens_neox': 4745, 'n_words': 1031}