diff --git a/CMakeLists.txt b/CMakeLists.txt index fc5e0cbe..e36c25a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ project(odyssey C) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=aarch64") set(CLANGCOMPILERSTANDART gnu11) @@ -53,19 +54,19 @@ execute_process(COMMAND ${CMAKE_C_COMPILER} --version set(OD_DEVEL_LVL -1) if ("${CMAKE_BUILD_TYPE}" STREQUAL "") - set(CMAKE_BUILD_TYPE "Debug") - set(OD_DEVEL_LVL 1) + set(CMAKE_BUILD_TYPE "Debug") + set(OD_DEVEL_LVL 1) endif() if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") - set(CMAKE_C_FLAGS "-std=${CLANGCOMPILERSTANDART} -pedantic -Wall -Wextra -Wstrict-aliasing -g -O2 -pthread -D_GNU_SOURCE") - set(OD_DEVEL_LVL -1) + set(CMAKE_C_FLAGS "-std=${CLANGCOMPILERSTANDART} -pedantic -Wall -Wextra -Wstrict-aliasing -g -O2 -pthread -D_GNU_SOURCE") + set(OD_DEVEL_LVL -1) elseif("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - set(CMAKE_C_FLAGS "-std=${CLANGCOMPILERSTANDART} -pedantic -Wall -Wextra -Wstrict-aliasing -g -O0 -pthread -D_GNU_SOURCE") - set(OD_DEVEL_LVL 1) + set(CMAKE_C_FLAGS "-std=${CLANGCOMPILERSTANDART} -pedantic -Wall -Wextra -Wstrict-aliasing -g -O0 -pthread -D_GNU_SOURCE -DLDAP_DBG") + set(OD_DEVEL_LVL 1) elseif("${CMAKE_BUILD_TYPE}" STREQUAL "ASAN") - set(CMAKE_C_FLAGS "-std=${CLANGCOMPILERSTANDART} -g -fsanitize=address,undefined -fno-sanitize-recover=all -pedantic -Wall -Wextra -Wstrict-aliasing -g -O0 -pthread -D_GNU_SOURCE") + set(CMAKE_C_FLAGS "-std=${CLANGCOMPILERSTANDART} -g -fsanitize=address,undefined -fno-sanitize-recover=all -pedantic -Wall -Wextra -Wstrict-aliasing -g -O0 -pthread -D_GNU_SOURCE") elseif("${CMAKE_BUILD_TYPE}" STREQUAL "TSAN") - set(CMAKE_C_FLAGS "-std=${CLANGCOMPILERSTANDART} -g -fsanitize=thread -fno-sanitize-recover=all -pedantic -Wall -Wextra -Wstrict-aliasing -g -O0 -pthread -D_GNU_SOURCE") + set(CMAKE_C_FLAGS "-std=${CLANGCOMPILERSTANDART} -g -fsanitize=thread -fno-sanitize-recover=all -pedantic -Wall -Wextra -Wstrict-aliasing -g -O0 -pthread -D_GNU_SOURCE") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CC_FLAGS}") diff --git a/docker/shell-test/shell-test/test-ldap.sh b/docker/shell-test/shell-test/test-ldap.sh index c6c9a4b5..ce320c12 100755 --- a/docker/shell-test/shell-test/test-ldap.sh +++ b/docker/shell-test/shell-test/test-ldap.sh @@ -5,8 +5,8 @@ do sleep 0.1 for __ in $(seq 1 10); do - PGPASSWORD=lolol psql -h localhost -p6432 -dpostgres2 -Uuser3 -c 'select 3' & - PGPASSWORD=lolol psql -h localhost -p6432 -dpostgres2 -Uuser3 -c 'select pg_sleep(1)' & + PGPASSWORD=lolol psql -h localhost -p6432 -dpostgres2 -Uuser1 -c 'select 3' & + PGPASSWORD=lolol psql -h localhost -p6432 -dpostgres2 -Uuser1 -c 'select pg_sleep(1)' & done done diff --git a/odyssey-dev.conf b/odyssey-dev.conf index b9b52fb9..6d05dc9a 100644 --- a/odyssey-dev.conf +++ b/odyssey-dev.conf @@ -63,6 +63,16 @@ ldap_endpoint "ldap1" { ldapport 389 } +ldap_endpoint "ldap_unreachable" { + ldapscheme "ldap" + ldapbasedn "dc=example,dc=org" + ldapbinddn "cn=admin,dc=example,dc=org" + ldapbindpasswd "admin" + ldapsearchattribute "gecos" + ldapserver "localhost" + ldapport 38 +} + database default { user default { authentication "none" @@ -102,7 +112,6 @@ database "postgres2" { authentication "clear_text" storage "postgres_server" - storage_password "1" pool "session" pool_size 10 @@ -128,6 +137,43 @@ database "postgres2" { server_lifetime 3600 log_debug no + ldap_endpoint_name "ldap_unreachable" + + quantiles "0.99,0.95,0.5" + client_max 107 + } + user "user1" { + authentication "clear_text" + + storage "postgres_server" + storage_password "lolol" + pool "session" + + ldap_pool_size 1 + + ldap_pool_timeout 0 + + pool_size 1 + + pool_timeout 0 + + pool_ttl 60 + + pool_discard no + + pool_cancel yes + + pool_rollback yes + + client_fwd_error yes + + application_name_add_host yes + + reserve_session_server_connection no + + server_lifetime 3600 + log_debug no + ldap_endpoint_name "ldap1" quantiles "0.99,0.95,0.5" diff --git a/sources/frontend.c b/sources/frontend.c index d90c2e21..9f747b73 100644 --- a/sources/frontend.c +++ b/sources/frontend.c @@ -33,8 +33,9 @@ int od_frontend_error(od_client_t *client, char *code, char *fmt, ...) machine_msg_t *msg; msg = od_frontend_error_msg(client, NULL, code, fmt, args); va_end(args); - if (msg == NULL) + if (msg == NULL) { return -1; + } return od_write(&client->io, msg); } @@ -209,7 +210,9 @@ od_frontend_attach(od_client_t *client, char *context, continue; } od_debug(&instance->logger, context, client, server, - "client %s attached to %s%.*s", client->id.id, + "client %s%.*s attached to %s%.*s", + client->id.id_prefix, + (int)sizeof(client->id.id_prefix), client->id.id, server->id.id_prefix, (int)sizeof(server->id.id_prefix), server->id.id); diff --git a/sources/ldap.c b/sources/ldap.c index a5df721a..83262268 100644 --- a/sources/ldap.c +++ b/sources/ldap.c @@ -18,15 +18,56 @@ od_retcode_t od_ldap_server_free(od_ldap_server_t *serv) ldap_unbind(serv->conn); } - free(serv->auth_user); + if (serv->auth_user) { + free(serv->auth_user); + } free(serv); return OK_RESPONSE; } +//#define LDAP_DBG + +static inline od_retcode_t od_ldap_error_report_client(od_client_t *cl, int rc) +{ + switch (rc) { + case LDAP_SUCCESS: + return OK_RESPONSE; + case LDAP_INVALID_CREDENTIALS: + return NOT_OK_RESPONSE; + case LDAP_UNAVAILABLE: + case LDAP_UNWILLING_TO_PERFORM: + case LDAP_BUSY: { + od_frontend_error(cl, KIWI_SYNTAX_ERROR, + "LDAP auth failed: ldap server is down"); + return NOT_OK_RESPONSE; + } + case LDAP_INVALID_SYNTAX: { + od_frontend_error( + cl, KIWI_SYNTAX_ERROR, + "LDAP auth failed: invalid attribute value was specified"); + return NOT_OK_RESPONSE; + } + default: { +#ifdef LDAP_DBG + od_frontend_error(cl, KIWI_SYNTAX_ERROR, + "LDAP auth failed: %s %d", + ldap_err2string(rc), rc); +#else + od_frontend_error(cl, KIWI_SYNTAX_ERROR, + "LDAP auth failed: unknown error"); +#endif + return NOT_OK_RESPONSE; + } + } +} + static inline int od_init_ldap_conn(LDAP **l, char *uri) { od_retcode_t rc = ldap_initialize(l, uri); if (rc != LDAP_SUCCESS) { + // set to null, we do not need to unbind this + // ldap_initialize frees assosated memory + *l = NULL; return NOT_OK_RESPONSE; } @@ -34,6 +75,8 @@ static inline int od_init_ldap_conn(LDAP **l, char *uri) rc = ldap_set_option(*l, LDAP_OPT_PROTOCOL_VERSION, &ldapversion); if (rc != LDAP_SUCCESS) { + // same as above + *l = NULL; return NOT_OK_RESPONSE; } return OK_RESPONSE; @@ -166,6 +209,7 @@ od_ldap_server_t *od_ldap_server_allocate() od_ldap_server_t *serv = malloc(sizeof(od_ldap_server_t)); serv->conn = NULL; serv->endpoint = NULL; + serv->auth_user = NULL; return serv; } @@ -184,33 +228,29 @@ static inline od_retcode_t od_ldap_server_init(od_logger_t *logger, server->endpoint = le; if (od_init_ldap_conn(&server->conn, le->ldapurl) != OK_RESPONSE) { - od_ldap_server_free(server); return NOT_OK_RESPONSE; } if (od_ldap_server_prepare(logger, server, route) != OK_RESPONSE) { - od_ldap_server_free(server); return NOT_OK_RESPONSE; } - od_route_lock(route); - od_ldap_server_pool_set(&route->ldap_pool, server, OD_SERVER_UNDEF); - od_route_unlock(route); return OK_RESPONSE; } -static inline od_retcode_t od_ldap_server_auth(od_ldap_server_t *serv, - od_client_t *cl, - kiwi_password_t *tok) +static inline int od_ldap_server_auth(od_ldap_server_t *serv, od_client_t *cl, + kiwi_password_t *tok) { od_instance_t *instance = cl->global->instance; - od_retcode_t rc; + int rc; rc = ldap_simple_bind_s(serv->conn, serv->auth_user, tok->password); - if (rc != LDAP_SUCCESS) { - return NOT_OK_RESPONSE; + od_route_t *route = cl->route; + if (route->rule->client_fwd_error) { + od_ldap_error_report_client(cl, rc); } - return OK_RESPONSE; + + return rc; } static inline od_ldap_server_t *od_ldap_server_attach(od_route_t *route, @@ -222,11 +262,10 @@ static inline od_ldap_server_t *od_ldap_server_attach(od_route_t *route, od_logger_t *logger = &instance->logger; od_ldap_server_t *server = NULL; - od_retcode_t rc; - od_route_lock(route); #ifdef USE_POOL + od_retcode_t rc; /* get client server from route server pool */ bool restart_read = false; @@ -288,7 +327,21 @@ static inline od_ldap_server_t *od_ldap_server_attach(od_route_t *route, /* create new server object */ server = od_ldap_server_allocate(); - od_ldap_server_init(logger, server, route); + + int ldap_rc = od_ldap_server_init(logger, server, route); + + od_route_lock(route); + od_ldap_server_pool_set(&route->ldap_pool, server, + OD_SERVER_UNDEF); + od_route_unlock(route); + + if (ldap_rc != LDAP_SUCCESS) { + if (route->rule->client_fwd_error) { + od_ldap_error_report_client(client, ldap_rc); + } + od_ldap_server_free(server); + return NULL; + } od_route_lock(route); } @@ -316,15 +369,43 @@ od_retcode_t od_auth_ldap(od_client_t *cl, kiwi_password_t *tok) return NOT_OK_RESPONSE; } - od_retcode_t rc = od_ldap_server_auth(serv, cl, tok); + int ldap_rc = od_ldap_server_auth(serv, cl, tok); + switch (ldap_rc) { + case LDAP_SUCCESS: { #ifndef USE_POOL - od_ldap_conn_close(route, serv); + od_ldap_conn_close(route, serv); #else - od_ldap_server_pool_set(&route->ldap_pool, serv, OD_SERVER_IDLE); + od_route_lock(route); + od_ldap_server_pool_set(&route->ldap_pool, serv, + OD_SERVER_IDLE); + od_route_unlock(route); #endif - - return rc; + return OK_RESPONSE; + } + case LDAP_INVALID_SYNTAX: + case LDAP_INVALID_CREDENTIALS: +#ifndef USE_POOL + od_ldap_conn_close(route, serv); +#else + od_route_lock(route); + od_ldap_server_pool_set(&route->ldap_pool, serv, + OD_SERVER_IDLE); + od_route_unlock(route); +#endif + return NOT_OK_RESPONSE; + default: +#ifndef USE_POOL + od_ldap_conn_close(route, serv); +#else + od_route_lock(route); + /*Need to rebind */ + od_ldap_server_pool_set(&route->ldap_pool, serv, + OD_SERVER_UNDEF); + od_route_unlock(route); +#endif + return NOT_OK_RESPONSE; + } } od_retcode_t od_ldap_conn_close(od_attribute_unused() od_route_t *route,