Skip to content

Commit 3d3e087

Browse files
committed
fix leak in scram sha 256
Signed-off-by: roman khapov <[email protected]>
1 parent 97f717f commit 3d3e087

File tree

5 files changed

+97
-60
lines changed

5 files changed

+97
-60
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ functional-test:
126126
ODYSSEY_TEST_TARGET=functional-entrypoint \
127127
ODYSSEY_FUNCTIONAL_TESTS_SELECTOR="$(ODYSSEY_TEST_SELECTOR)" \
128128
ODYSSEY_CC="$(ODYSSEY_CC)" \
129-
docker compose -f ./docker/functional/docker-compose.yml --progress plain up --exit-code-from odyssey --build --remove-orphans
129+
docker compose -f ./docker/functional/docker-compose.yml up --exit-code-from odyssey --build --remove-orphans
130130

131131
jemalloc-test:
132132
docker compose -f ./docker/jeamalloc/docker-compose.yml down || true
Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
11
#!/bin/bash -x
22

3-
psql 'host=ip4-localhost port=6432 user=backend_auth_with_incorrect_password dbname=scram_db sslmode=disable' -c "SELECT 1" 2>&1 && {
4-
echo "ERROR: successfully backend auth with incorrect password"
53

6-
cat /var/log/odyssey.log
7-
echo "
4+
for _ in $(seq 1 5); do
5+
psql 'host=ip4-localhost port=6432 user=backend_auth_with_incorrect_password dbname=scram_db sslmode=disable' -c "SELECT 1" 2>&1 && {
6+
echo "ERROR: successfully backend auth with incorrect password"
87

8+
cat /var/log/odyssey.log
9+
echo "
910
10-
"
11-
cat /var/log/postgresql/postgresql-16-main.log
1211
13-
exit 1
14-
}
12+
"
13+
cat /var/log/postgresql/postgresql-16-main.log
1514

16-
psql 'host=ip4-localhost port=6432 user=backend_auth_with_correct_password dbname=scram_db sslmode=disable' -c "SELECT 1" 2>&1 || {
17-
echo "ERROR: failed backend auth with correct password"
15+
exit 1
16+
}
17+
done
1818

19-
cat /var/log/odyssey.log
20-
echo "
19+
for _ in $(seq 1 5); do
20+
psql 'host=ip4-localhost port=6432 user=backend_auth_with_correct_password dbname=scram_db sslmode=disable' -c "SELECT 1" 2>&1 || {
21+
echo "ERROR: failed backend auth with correct password"
2122

23+
cat /var/log/odyssey.log
24+
echo "
2225
23-
"
24-
cat /var/log/postgresql/postgresql-16-main.log
2526
26-
exit 1
27-
}
27+
"
28+
cat /var/log/postgresql/postgresql-16-main.log
29+
30+
exit 1
31+
}
32+
done
Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
#!/bin/bash -x
22

3-
psql 'host=localhost port=6432 user=frontend_auth_plain dbname=scram_db password=incorrect_password sslmode=disable' -c "SELECT 1" 2>&1 && {
4-
echo "ERROR: successfully auth with incorrect password and plain password in config"
5-
ody-stop
6-
exit 1
7-
}
3+
for _ in $(seq 1 5); do
4+
psql 'host=localhost port=6432 user=frontend_auth_plain dbname=scram_db password=incorrect_password sslmode=disable' -c "SELECT 1" 2>&1 && {
5+
echo "ERROR: successfully auth with incorrect password and plain password in config"
6+
ody-stop
7+
exit 1
8+
}
9+
done
810

9-
psql 'host=localhost port=6432 user=frontend_auth_plain dbname=scram_db password=correct_password sslmode=disable' -c "SELECT 1" 2>&1 || {
10-
echo "ERROR: failed auth with correct password and plain password in config"
11-
ody-stop
12-
exit 1
13-
}
11+
for _ in $(seq 1 5); do
12+
psql 'host=localhost port=6432 user=frontend_auth_plain dbname=scram_db password=correct_password sslmode=disable' -c "SELECT 1" 2>&1 || {
13+
echo "ERROR: failed auth with correct password and plain password in config"
14+
ody-stop
15+
exit 1
16+
}
17+
done
1418

15-
psql 'host=localhost port=6432 user=frontend_auth_scram_secret dbname=scram_db password=incorrect_password sslmode=disable' -c "SELECT 1" 2>&1 && {
16-
echo "ERROR: successfully auth with incorrect password and scram secret in config"
17-
ody-stop
18-
exit 1
19-
}
19+
for _ in $(seq 1 5); do
20+
psql 'host=localhost port=6432 user=frontend_auth_scram_secret dbname=scram_db password=incorrect_password sslmode=disable' -c "SELECT 1" 2>&1 && {
21+
echo "ERROR: successfully auth with incorrect password and scram secret in config"
22+
ody-stop
23+
exit 1
24+
}
25+
done
2026

21-
psql 'host=localhost port=6432 user=frontend_auth_scram_secret dbname=scram_db password=correct_password sslmode=disable' -c "SELECT 1" 2>&1 || {
22-
echo "ERROR: failed auth with correct password and scram secret in config"
23-
ody-stop
24-
exit 1
25-
}
27+
for _ in $(seq 1 5); do
28+
psql 'host=localhost port=6432 user=frontend_auth_scram_secret dbname=scram_db password=correct_password sslmode=disable' -c "SELECT 1" 2>&1 || {
29+
echo "ERROR: failed auth with correct password and scram secret in config"
30+
ody-stop
31+
exit 1
32+
}
33+
done

sources/auth.c

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,12 @@ static inline int od_auth_frontend_md5(od_client_t *client)
420420

421421
#ifdef POSTGRESQL_FOUND
422422

423-
static inline int od_auth_frontend_scram_sha_256(od_client_t *client)
423+
static inline int
424+
od_auth_frontend_scram_sha_256_internal(od_client_t *client,
425+
od_scram_state_t *scram_state)
424426
{
427+
/* separated function to ensure, that scram_state will be fried properly in caller */
428+
425429
od_instance_t *instance = client->global->instance;
426430
char *mechanisms[2] = { "SCRAM-SHA-256", "SCRAM-SHA-256-PLUS" };
427431

@@ -529,11 +533,8 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client)
529533
query_password.password = client->rule->password;
530534
}
531535

532-
od_scram_state_t scram_state;
533-
od_scram_state_init(&scram_state);
534-
535536
/* try to parse authentication data */
536-
rc = od_scram_read_client_first_message(&scram_state, auth_data,
537+
rc = od_scram_read_client_first_message(scram_state, auth_data,
537538
auth_data_size);
538539
machine_msg_free(msg);
539540
switch (rc) {
@@ -568,9 +569,9 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client)
568569
return -1;
569570
}
570571

571-
rc = od_scram_parse_verifier(&scram_state, query_password.password);
572+
rc = od_scram_parse_verifier(scram_state, query_password.password);
572573
if (rc == -1)
573-
rc = od_scram_init_from_plain_password(&scram_state,
574+
rc = od_scram_init_from_plain_password(scram_state,
574575
query_password.password);
575576

576577
if (rc == -1) {
@@ -581,10 +582,9 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client)
581582
return -1;
582583
}
583584

584-
msg = od_scram_create_server_first_message(&scram_state);
585+
msg = od_scram_create_server_first_message(scram_state);
585586
if (msg == NULL) {
586587
kiwi_password_free(&query_password);
587-
od_scram_state_free(&scram_state);
588588

589589
return -1;
590590
}
@@ -637,7 +637,7 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client)
637637
char *final_nonce;
638638
size_t final_nonce_size;
639639
char *client_proof;
640-
rc = od_scram_read_client_final_message(client->io.io, &scram_state,
640+
rc = od_scram_read_client_final_message(client->io.io, scram_state,
641641
auth_data, auth_data_size,
642642
&final_nonce, &final_nonce_size,
643643
&client_proof);
@@ -651,7 +651,7 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client)
651651
}
652652

653653
/* verify signatures */
654-
rc = od_scram_verify_final_nonce(&scram_state, final_nonce,
654+
rc = od_scram_verify_final_nonce(scram_state, final_nonce,
655655
final_nonce_size);
656656
if (rc == -1) {
657657
od_frontend_error(
@@ -663,7 +663,7 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client)
663663
return -1;
664664
}
665665

666-
rc = od_scram_verify_client_proof(&scram_state, client_proof);
666+
rc = od_scram_verify_client_proof(scram_state, client_proof);
667667
od_free(client_proof);
668668
if (rc == -1) {
669669
od_frontend_error(
@@ -676,10 +676,9 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client)
676676

677677
machine_msg_free(msg);
678678
/* SASLFinal Message */
679-
msg = od_scram_create_server_final_message(&scram_state);
679+
msg = od_scram_create_server_final_message(scram_state);
680680
if (msg == NULL) {
681681
kiwi_password_free(&query_password);
682-
od_scram_state_free(&scram_state);
683682

684683
return -1;
685684
}
@@ -692,10 +691,21 @@ static inline int od_auth_frontend_scram_sha_256(od_client_t *client)
692691
return -1;
693692
}
694693

695-
od_scram_state_free(&scram_state);
696694
return 0;
697695
}
698696

697+
static inline int od_auth_frontend_scram_sha_256(od_client_t *client)
698+
{
699+
od_scram_state_t scram_state;
700+
od_scram_state_init(&scram_state);
701+
702+
int rc = od_auth_frontend_scram_sha_256_internal(client, &scram_state);
703+
704+
od_scram_state_free(&scram_state);
705+
706+
return rc;
707+
}
708+
699709
#endif
700710

701711
static inline int od_auth_frontend_cert(od_client_t *client)
@@ -957,6 +967,9 @@ static inline int od_auth_backend_sasl(od_server_t *server, od_client_t *client)
957967

958968
assert(route != NULL);
959969

970+
/* free possible stale state from previous unlucky auth */
971+
od_scram_state_free(&server->scram_state);
972+
960973
if (server->scram_state.client_nonce != NULL) {
961974
od_error(
962975
&instance->logger, "auth", NULL, server,
@@ -1105,8 +1118,6 @@ static inline int od_auth_backend_sasl_final(od_server_t *server,
11051118
return -1;
11061119
}
11071120

1108-
od_scram_state_free(&server->scram_state);
1109-
11101121
return 0;
11111122
}
11121123

@@ -1155,15 +1166,25 @@ int od_auth_backend(od_server_t *server, machine_msg_t *msg,
11551166
#ifdef POSTGRESQL_FOUND
11561167
/* AuthenticationSASL */
11571168
case 10:
1158-
return od_auth_backend_sasl(server, client);
1169+
rc = od_auth_backend_sasl(server, client);
1170+
if (rc != OK_RESPONSE) {
1171+
od_scram_state_free(&server->scram_state);
1172+
}
1173+
return rc;
11591174
/* AuthenticationSASLContinue */
11601175
case 11:
1161-
return od_auth_backend_sasl_continue(server, auth_data,
1162-
auth_data_size, client);
1163-
/* AuthenticationSASLContinue */
1176+
rc = od_auth_backend_sasl_continue(server, auth_data,
1177+
auth_data_size, client);
1178+
if (rc != OK_RESPONSE) {
1179+
od_scram_state_free(&server->scram_state);
1180+
}
1181+
return rc;
1182+
/* AuthenticationSASLFinal */
11641183
case 12:
1165-
return od_auth_backend_sasl_final(server, auth_data,
1166-
auth_data_size);
1184+
rc = od_auth_backend_sasl_final(server, auth_data,
1185+
auth_data_size);
1186+
od_scram_state_free(&server->scram_state);
1187+
return rc;
11671188
#endif
11681189
/* unsupported */
11691190
default:

sources/server.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ static inline void od_server_free(od_server_t *server)
129129
if (server->prep_stmts) {
130130
od_hashmap_free(server->prep_stmts);
131131
}
132+
#ifdef POSTGRESQL_FOUND
133+
od_scram_state_free(&server->scram_state);
134+
#endif
132135
od_free(server);
133136
}
134137

0 commit comments

Comments
 (0)