From 8dace7befe4e440fe66348c206838c96a9cd5950 Mon Sep 17 00:00:00 2001 From: Andrey Borodin Date: Mon, 19 Apr 2021 17:27:19 +0500 Subject: [PATCH] Pass auth information to server after recieving it from auth_query This should fix #291 for MD5 --- sources/auth.c | 74 +++++++++++++++++++++++++------------------- sources/auth.h | 2 +- sources/auth_query.c | 9 ++++-- sources/auth_query.h | 3 +- sources/backend.c | 8 ++--- sources/backend.h | 2 +- sources/client.h | 3 ++ sources/frontend.c | 2 +- 8 files changed, 60 insertions(+), 43 deletions(-) diff --git a/sources/auth.c b/sources/auth.c index 3ac2b1e5..0b606fa1 100644 --- a/sources/auth.c +++ b/sources/auth.c @@ -77,12 +77,10 @@ static inline int od_auth_frontend_cleartext(od_client_t *client) /* use remote or local password source */ kiwi_password_t client_password; - kiwi_password_init(&client_password); if (client->rule->auth_query) { char peer[128]; od_getpeername(client->io.io, peer, sizeof(peer), 1, 0); - rc = od_auth_query(client->global, client->rule, peer, - &client->startup.user, &client_password); + rc = od_auth_query(client, peer); if (rc == -1) { od_error(&instance->logger, "auth", client, NULL, "failed to make auth_query"); @@ -91,12 +89,11 @@ static inline int od_auth_frontend_cleartext(od_client_t *client) KIWI_INVALID_AUTHORIZATION_SPECIFICATION, "failed to make auth query"); kiwi_password_free(&client_token); - kiwi_password_free(&client_password); machine_msg_free(msg); return -1; } - if (client_password.password == NULL) { + if (client->password.password == NULL) { od_log(&instance->logger, "auth", client, NULL, "user '%s.%s' incorrect user from %s", client->startup.database.value, @@ -107,6 +104,7 @@ static inline int od_auth_frontend_cleartext(od_client_t *client) machine_msg_free(msg); return -1; } + client_password = client->password; } else { client_password.password_len = client->rule->password_len + 1; client_password.password = client->rule->password; @@ -116,8 +114,6 @@ static inline int od_auth_frontend_cleartext(od_client_t *client) int check = kiwi_password_compare(&client_password, &client_token); kiwi_password_free(&client_token); machine_msg_free(msg); - if (client->rule->auth_query) - kiwi_password_free(&client_password); if (check) return 0; @@ -188,13 +184,11 @@ static inline int od_auth_frontend_md5(od_client_t *client) kiwi_password_init(&client_password); kiwi_password_t query_password; - kiwi_password_init(&query_password); if (client->rule->auth_query) { char peer[128]; od_getpeername(client->io.io, peer, sizeof(peer), 1, 0); - rc = od_auth_query(client->global, client->rule, peer, - &client->startup.user, &query_password); + rc = od_auth_query(client, peer); if (rc == -1) { od_error(&instance->logger, "auth", client, NULL, "failed to make auth_query"); @@ -208,7 +202,7 @@ static inline int od_auth_frontend_md5(od_client_t *client) return -1; } - if (query_password.password == NULL) { + if (client->password.password == NULL) { od_log(&instance->logger, "auth", client, NULL, "user '%s.%s' incorrect user from %s", client->startup.database.value, @@ -219,7 +213,9 @@ static inline int od_auth_frontend_md5(od_client_t *client) machine_msg_free(msg); return -1; } - query_password.password_len--; + + query_password = client->password; + query_password.password_len = client->password.password_len - 1; } else { query_password.password_len = client->rule->password_len; query_password.password = client->rule->password; @@ -246,8 +242,6 @@ static inline int od_auth_frontend_md5(od_client_t *client) kiwi_password_free(&client_password); kiwi_password_free(&client_token); machine_msg_free(msg); - if (client->rule->auth_query) - kiwi_password_free(&query_password); if (!check) { od_log(&instance->logger, "auth", client, NULL, @@ -334,8 +328,7 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client) if (client->rule->auth_query) { char peer[128]; od_getpeername(client->io.io, peer, sizeof(peer), 1, 0); - rc = od_auth_query(client->global, client->rule, peer, - &client->startup.user, &query_password); + rc = od_auth_query(client, peer); if (rc == -1) { od_error(&instance->logger, "auth", client, NULL, "failed to make auth_query"); @@ -348,7 +341,7 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client) return -1; } - if (query_password.password == NULL) { + if (client->password.password == NULL) { od_log(&instance->logger, "auth", client, NULL, "user '%s.%s' incorrect user from %s", client->startup.database.value, @@ -358,7 +351,8 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client) machine_msg_free(msg); return -1; } - query_password.password_len--; + + query_password = client->password; } else { query_password.password_len = client->rule->password_len; query_password.password = client->rule->password; @@ -637,7 +631,8 @@ int od_auth_frontend(od_client_t *client) return 0; } -static inline int od_auth_backend_cleartext(od_server_t *server) +static inline int od_auth_backend_cleartext(od_server_t *server, + od_client_t *client) { od_instance_t *instance = server->global->instance; od_route_t *route = server->route; @@ -649,7 +644,11 @@ static inline int od_auth_backend_cleartext(od_server_t *server) /* use storage or user password */ char *password; int password_len; - if (route->rule->storage_password) { + + if (client != NULL && client->password.password != NULL) { + password = client->password.password; + password_len = client->password.password_len - 1; + } else if (route->rule->storage_password) { password = route->rule->storage_password; password_len = route->rule->storage_password_len; } else if (route->rule->password) { @@ -680,7 +679,8 @@ static inline int od_auth_backend_cleartext(od_server_t *server) return 0; } -static inline int od_auth_backend_md5(od_server_t *server, char salt[4]) +static inline int od_auth_backend_md5(od_server_t *server, char salt[4], + od_client_t *client) { od_instance_t *instance = server->global->instance; od_route_t *route = server->route; @@ -703,7 +703,10 @@ static inline int od_auth_backend_md5(od_server_t *server, char salt[4]) /* use storage or user password */ char *password; int password_len; - if (route->rule->storage_password) { + if (client != NULL && client->password.password != NULL) { + password = client->password.password; + password_len = client->password.password_len - 1; + } else if (route->rule->storage_password) { password = route->rule->storage_password; password_len = route->rule->storage_password_len; } else if (route->rule->password) { @@ -750,7 +753,7 @@ static inline int od_auth_backend_md5(od_server_t *server, char salt[4]) #ifdef USE_SCRAM -static inline int od_auth_backend_sasl(od_server_t *server) +static inline int od_auth_backend_sasl(od_server_t *server, od_client_t *client) { od_instance_t *instance = server->global->instance; od_route_t *route = server->route; @@ -768,7 +771,8 @@ static inline int od_auth_backend_sasl(od_server_t *server) od_debug(&instance->logger, "auth", NULL, server, "requested SASL authentication"); - if (!route->rule->storage_password && !route->rule->password) { + if (!route->rule->storage_password && !route->rule->password && + (client == NULL || client->password.password == NULL)) { od_error(&instance->logger, "auth", NULL, server, "password required for route '%s.%s'", route->rule->db_name, route->rule->user_name); @@ -798,7 +802,8 @@ static inline int od_auth_backend_sasl(od_server_t *server) } static inline int od_auth_backend_sasl_continue(od_server_t *server, char *auth_data, - size_t auth_data_size) + size_t auth_data_size, + od_client_t *client) { od_instance_t *instance = server->global->instance; od_route_t *route = server->route; @@ -824,7 +829,13 @@ static inline int od_auth_backend_sasl_continue(od_server_t *server, /* use storage or user password */ char *password; - if (route->rule->storage_password) { + if (client != NULL && client->password.password != NULL) { + od_error(&instance->logger, "auth", NULL, server, + "cannot authenticate with SCRAM secret from auth_query", + route->rule->db_name, route->rule->user_name); + + return -1; + } else if (route->rule->storage_password) { password = route->rule->storage_password; } else if (route->rule->password) { password = route->rule->password; @@ -895,7 +906,8 @@ static inline int od_auth_backend_sasl_final(od_server_t *server, #endif -int od_auth_backend(od_server_t *server, machine_msg_t *msg) +int od_auth_backend(od_server_t *server, machine_msg_t *msg, + od_client_t *client) { od_instance_t *instance = server->global->instance; assert(*(char *)machine_msg_data(msg) == KIWI_BE_AUTHENTICATION); @@ -920,24 +932,24 @@ int od_auth_backend(od_server_t *server, machine_msg_t *msg) return 0; /* AuthenticationCleartextPassword */ case 3: - rc = od_auth_backend_cleartext(server); + rc = od_auth_backend_cleartext(server, client); if (rc == -1) return -1; break; /* AuthenticationMD5Password */ case 5: - rc = od_auth_backend_md5(server, salt); + rc = od_auth_backend_md5(server, salt, client); if (rc == -1) return -1; break; #ifdef USE_SCRAM /* AuthenticationSASL */ case 10: - return od_auth_backend_sasl(server); + return od_auth_backend_sasl(server, client); /* AuthenticationSASLContinue */ case 11: return od_auth_backend_sasl_continue(server, auth_data, - auth_data_size); + auth_data_size, client); /* AuthenticationSASLContinue */ case 12: return od_auth_backend_sasl_final(server, auth_data, diff --git a/sources/auth.h b/sources/auth.h index f9588d69..e4c1d2cf 100644 --- a/sources/auth.h +++ b/sources/auth.h @@ -8,6 +8,6 @@ */ int od_auth_frontend(od_client_t *); -int od_auth_backend(od_server_t *, machine_msg_t *); +int od_auth_backend(od_server_t *, machine_msg_t *, od_client_t *); #endif /* ODYSSEY_AUTH_H */ diff --git a/sources/auth_query.c b/sources/auth_query.c index b592e3ea..2c60de6e 100644 --- a/sources/auth_query.c +++ b/sources/auth_query.c @@ -177,9 +177,12 @@ od_auth_query_format(od_rule_t *rule, kiwi_var_t *user, char *peer, return dst_pos - output; } -int od_auth_query(od_global_t *global, od_rule_t *rule, char *peer, - kiwi_var_t *user, kiwi_password_t *password) +int od_auth_query(od_client_t *client, char *peer) { + od_global_t *global = client->global; + od_rule_t *rule = client->rule; + kiwi_var_t *user = &client->startup.user; + kiwi_password_t *password = &client->password; od_instance_t *instance = global->instance; od_router_t *router = global->router; @@ -223,7 +226,7 @@ int od_auth_query(od_global_t *global, od_rule_t *rule, char *peer, /* connect to server, if necessary */ int rc; if (server->io.io == NULL) { - rc = od_backend_connect(server, "auth_query", NULL); + rc = od_backend_connect(server, "auth_query", NULL, NULL); if (rc == -1) { od_router_close(router, auth_client); od_router_unroute(router, auth_client); diff --git a/sources/auth_query.h b/sources/auth_query.h index bb952e45..2f5ca1f2 100644 --- a/sources/auth_query.h +++ b/sources/auth_query.h @@ -7,7 +7,6 @@ * Scalable PostgreSQL connection pooler. */ -int od_auth_query(od_global_t *, od_rule_t *, char *, kiwi_var_t *, - kiwi_password_t *); +int od_auth_query(od_client_t *, char *); #endif /* ODYSSEY_AUTH_QUERY_H */ diff --git a/sources/backend.c b/sources/backend.c index 42378561..5e6f7f65 100644 --- a/sources/backend.c +++ b/sources/backend.c @@ -101,7 +101,7 @@ int od_backend_ready(od_server_t *server, char *data, uint32_t size) } static inline int od_backend_startup(od_server_t *server, - kiwi_params_t *route_params) + kiwi_params_t *route_params, od_client_t *client) { od_instance_t *instance = server->global->instance; od_route_t *route = server->route; @@ -157,7 +157,7 @@ static inline int od_backend_startup(od_server_t *server, machine_msg_free(msg); return 0; case KIWI_BE_AUTHENTICATION: - rc = od_auth_backend(server, msg); + rc = od_auth_backend(server, msg, client); machine_msg_free(msg); if (rc == -1) return -1; @@ -385,7 +385,7 @@ static inline int od_backend_connect_to(od_server_t *server, char *context, } int od_backend_connect(od_server_t *server, char *context, - kiwi_params_t *route_params) + kiwi_params_t *route_params, od_client_t *client) { od_route_t *route = server->route; assert(route != NULL); @@ -400,7 +400,7 @@ int od_backend_connect(od_server_t *server, char *context, return -1; /* send startup and do initial configuration */ - rc = od_backend_startup(server, route_params); + rc = od_backend_startup(server, route_params, client); return rc; } diff --git a/sources/backend.h b/sources/backend.h index aa36caf9..bff34108 100644 --- a/sources/backend.h +++ b/sources/backend.h @@ -7,7 +7,7 @@ * Scalable PostgreSQL connection pooler. */ -int od_backend_connect(od_server_t *, char *, kiwi_params_t *); +int od_backend_connect(od_server_t *, char *, kiwi_params_t *, od_client_t*); int od_backend_connect_cancel(od_server_t *, od_rule_storage_t *, kiwi_key_t *); void od_backend_close_connection(od_server_t *); void od_backend_close(od_server_t *); diff --git a/sources/client.h b/sources/client.h index 7f535178..16df89e9 100644 --- a/sources/client.h +++ b/sources/client.h @@ -43,6 +43,7 @@ struct od_client { kiwi_key_t key; od_server_t *server; void *route; + kiwi_password_t password; od_global_t *global; od_list_t link_pool; od_list_t link; @@ -68,6 +69,7 @@ static inline void od_client_init(od_client_t *client) kiwi_key_init(&client->key); od_io_init(&client->io); od_relay_init(&client->relay, &client->io); + kiwi_password_init(&client->password); od_list_init(&client->link_pool); od_list_init(&client->link); } @@ -87,6 +89,7 @@ static inline void od_client_free(od_client_t *client) od_io_free(&client->io); if (client->cond) machine_cond_free(client->cond); + kiwi_password_free(&client->password); free(client); } diff --git a/sources/frontend.c b/sources/frontend.c index f22efade..b8afb456 100644 --- a/sources/frontend.c +++ b/sources/frontend.c @@ -220,7 +220,7 @@ od_frontend_attach(od_client_t *client, char *context, int rc; od_atomic_u32_inc(&router->servers_routing); - rc = od_backend_connect(server, context, route_params); + rc = od_backend_connect(server, context, route_params, client); od_atomic_u32_dec(&router->servers_routing); if (rc == -1) { /* In case of 'too many connections' error, retry attach attempt by