Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * fe-auth-scram.c
4 : * The front-end (client) implementation of SCRAM authentication.
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : * IDENTIFICATION
10 : * src/interfaces/libpq/fe-auth-scram.c
11 : *
12 : *-------------------------------------------------------------------------
13 : */
14 :
15 : #include "postgres_fe.h"
16 :
17 : #include "common/base64.h"
18 : #include "common/hmac.h"
19 : #include "common/saslprep.h"
20 : #include "common/scram-common.h"
21 : #include "fe-auth.h"
22 :
23 :
24 : /* The exported SCRAM callback mechanism. */
25 : static void *scram_init(PGconn *conn, const char *password,
26 : const char *sasl_mechanism);
27 : static void scram_exchange(void *opaq, char *input, int inputlen,
28 : char **output, int *outputlen,
29 : bool *done, bool *success);
30 : static bool scram_channel_bound(void *opaq);
31 : static void scram_free(void *opaq);
32 :
33 : const pg_fe_sasl_mech pg_scram_mech = {
34 : scram_init,
35 : scram_exchange,
36 : scram_channel_bound,
37 : scram_free
38 : };
39 :
40 : /*
41 : * Status of exchange messages used for SCRAM authentication via the
42 : * SASL protocol.
43 : */
44 : typedef enum
45 : {
46 : FE_SCRAM_INIT,
47 : FE_SCRAM_NONCE_SENT,
48 : FE_SCRAM_PROOF_SENT,
49 : FE_SCRAM_FINISHED
50 : } fe_scram_state_enum;
51 :
52 : typedef struct
53 : {
54 : fe_scram_state_enum state;
55 :
56 : /* These are supplied by the user */
57 : PGconn *conn;
58 : char *password;
59 : char *sasl_mechanism;
60 :
61 : /* State data depending on the hash type */
62 : pg_cryptohash_type hash_type;
63 : int key_length;
64 :
65 : /* We construct these */
66 : uint8 SaltedPassword[SCRAM_MAX_KEY_LEN];
67 : char *client_nonce;
68 : char *client_first_message_bare;
69 : char *client_final_message_without_proof;
70 :
71 : /* These come from the server-first message */
72 : char *server_first_message;
73 : char *salt;
74 : int saltlen;
75 : int iterations;
76 : char *nonce;
77 :
78 : /* These come from the server-final message */
79 : char *server_final_message;
80 : char ServerSignature[SCRAM_MAX_KEY_LEN];
81 : } fe_scram_state;
82 :
83 : static bool read_server_first_message(fe_scram_state *state, char *input);
84 : static bool read_server_final_message(fe_scram_state *state, char *input);
85 : static char *build_client_first_message(fe_scram_state *state);
86 : static char *build_client_final_message(fe_scram_state *state);
87 : static bool verify_server_signature(fe_scram_state *state, bool *match,
88 : const char **errstr);
89 : static bool calculate_client_proof(fe_scram_state *state,
90 : const char *client_final_message_without_proof,
91 : uint8 *result, const char **errstr);
92 :
93 : /*
94 : * Initialize SCRAM exchange status.
95 : */
96 : static void *
641 michael 97 GIC 34 : scram_init(PGconn *conn,
98 : const char *password,
99 : const char *sasl_mechanism)
100 : {
2224 heikki.linnakangas 101 ECB : fe_scram_state *state;
102 : char *prep_password;
103 : pg_saslprep_rc rc;
104 :
1968 peter_e 105 GIC 34 : Assert(sasl_mechanism != NULL);
106 :
2224 heikki.linnakangas 107 34 : state = (fe_scram_state *) malloc(sizeof(fe_scram_state));
108 34 : if (!state)
2224 heikki.linnakangas 109 LBC 0 : return NULL;
2224 heikki.linnakangas 110 GIC 34 : memset(state, 0, sizeof(fe_scram_state));
1921 peter_e 111 CBC 34 : state->conn = conn;
2224 heikki.linnakangas 112 34 : state->state = FE_SCRAM_INIT;
110 michael 113 GNC 34 : state->key_length = SCRAM_SHA_256_KEY_LEN;
114 34 : state->hash_type = PG_SHA256;
1938 peter_e 115 ECB :
110 michael 116 GNC 34 : state->sasl_mechanism = strdup(sasl_mechanism);
1968 peter_e 117 CBC 34 : if (!state->sasl_mechanism)
1968 peter_e 118 ECB : {
1968 peter_e 119 LBC 0 : free(state);
120 0 : return NULL;
121 : }
1968 peter_e 122 ECB :
2193 heikki.linnakangas 123 : /* Normalize the password with SASLprep, if possible */
2193 heikki.linnakangas 124 GIC 34 : rc = pg_saslprep(password, &prep_password);
2193 heikki.linnakangas 125 GBC 34 : if (rc == SASLPREP_OOM)
2193 heikki.linnakangas 126 EUB : {
1968 peter_e 127 UIC 0 : free(state->sasl_mechanism);
2193 heikki.linnakangas 128 0 : free(state);
129 0 : return NULL;
2193 heikki.linnakangas 130 ECB : }
2193 heikki.linnakangas 131 CBC 34 : if (rc != SASLPREP_SUCCESS)
132 : {
2193 heikki.linnakangas 133 GBC 2 : prep_password = strdup(password);
134 2 : if (!prep_password)
2193 heikki.linnakangas 135 EUB : {
1968 peter_e 136 UIC 0 : free(state->sasl_mechanism);
2193 heikki.linnakangas 137 LBC 0 : free(state);
2193 heikki.linnakangas 138 UIC 0 : return NULL;
2193 heikki.linnakangas 139 ECB : }
140 : }
2193 heikki.linnakangas 141 GIC 34 : state->password = prep_password;
2224 heikki.linnakangas 142 EUB :
2224 heikki.linnakangas 143 GBC 34 : return state;
2224 heikki.linnakangas 144 EUB : }
145 :
146 : /*
1294 jdavis 147 ECB : * Return true if channel binding was employed and the SCRAM exchange
148 : * completed. This should be used after a successful exchange to determine
149 : * whether the server authenticated itself to the client.
150 : *
151 : * Note that the caller must also ensure that the exchange was actually
152 : * successful.
153 : */
154 : static bool
641 michael 155 GIC 3 : scram_channel_bound(void *opaq)
156 : {
1294 jdavis 157 3 : fe_scram_state *state = (fe_scram_state *) opaq;
158 :
159 : /* no SCRAM exchange done */
160 3 : if (state == NULL)
1294 jdavis 161 LBC 0 : return false;
162 :
1294 jdavis 163 ECB : /* SCRAM exchange not completed */
1294 jdavis 164 GIC 3 : if (state->state != FE_SCRAM_FINISHED)
1294 jdavis 165 UIC 0 : return false;
1294 jdavis 166 ECB :
1294 jdavis 167 EUB : /* channel binding mechanism not used */
1294 jdavis 168 GIC 3 : if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) != 0)
1294 jdavis 169 UIC 0 : return false;
1294 jdavis 170 ECB :
1294 jdavis 171 EUB : /* all clear! */
1294 jdavis 172 GIC 3 : return true;
173 : }
1294 jdavis 174 ECB :
2224 heikki.linnakangas 175 EUB : /*
176 : * Free SCRAM exchange status
177 : */
641 michael 178 ECB : static void
641 michael 179 GIC 34 : scram_free(void *opaq)
180 : {
2224 heikki.linnakangas 181 34 : fe_scram_state *state = (fe_scram_state *) opaq;
182 :
297 peter 183 GNC 34 : free(state->password);
184 34 : free(state->sasl_mechanism);
2193 heikki.linnakangas 185 ECB :
186 : /* client messages */
297 peter 187 GNC 34 : free(state->client_nonce);
188 34 : free(state->client_first_message_bare);
189 34 : free(state->client_final_message_without_proof);
2224 heikki.linnakangas 190 ECB :
191 : /* first message from server */
297 peter 192 GNC 34 : free(state->server_first_message);
193 34 : free(state->salt);
194 34 : free(state->nonce);
2224 heikki.linnakangas 195 ECB :
196 : /* final message from server */
297 peter 197 GNC 34 : free(state->server_final_message);
198 :
2224 heikki.linnakangas 199 GIC 34 : free(state);
200 34 : }
201 :
202 : /*
2224 heikki.linnakangas 203 ECB : * Exchange a SCRAM message with backend.
204 : */
205 : static void
641 michael 206 GIC 96 : scram_exchange(void *opaq, char *input, int inputlen,
641 michael 207 ECB : char **output, int *outputlen,
208 : bool *done, bool *success)
2224 heikki.linnakangas 209 : {
2224 heikki.linnakangas 210 GIC 96 : fe_scram_state *state = (fe_scram_state *) opaq;
1921 peter_e 211 CBC 96 : PGconn *conn = state->conn;
451 michael 212 96 : const char *errstr = NULL;
2224 heikki.linnakangas 213 ECB :
2224 heikki.linnakangas 214 CBC 96 : *done = false;
2224 heikki.linnakangas 215 GIC 96 : *success = false;
216 96 : *output = NULL;
217 96 : *outputlen = 0;
218 :
219 : /*
2224 heikki.linnakangas 220 ECB : * Check that the input length agrees with the string length of the input.
221 : * We can ignore inputlen after this.
222 : */
2224 heikki.linnakangas 223 GIC 96 : if (state->state != FE_SCRAM_INIT)
2224 heikki.linnakangas 224 EUB : {
2224 heikki.linnakangas 225 GBC 62 : if (inputlen == 0)
226 : {
145 peter 227 UNC 0 : libpq_append_conn_error(conn, "malformed SCRAM message (empty message)");
2224 heikki.linnakangas 228 UBC 0 : goto error;
2224 heikki.linnakangas 229 EUB : }
2224 heikki.linnakangas 230 GIC 62 : if (inputlen != strlen(input))
231 : {
145 peter 232 UNC 0 : libpq_append_conn_error(conn, "malformed SCRAM message (length mismatch)");
2224 heikki.linnakangas 233 UIC 0 : goto error;
2224 heikki.linnakangas 234 ECB : }
235 : }
236 :
2224 heikki.linnakangas 237 CBC 96 : switch (state->state)
2224 heikki.linnakangas 238 EUB : {
2224 heikki.linnakangas 239 GIC 34 : case FE_SCRAM_INIT:
2224 heikki.linnakangas 240 ECB : /* Begin the SCRAM handshake, by sending client nonce */
1921 peter_e 241 CBC 34 : *output = build_client_first_message(state);
2224 heikki.linnakangas 242 34 : if (*output == NULL)
2224 heikki.linnakangas 243 LBC 0 : goto error;
244 :
2224 heikki.linnakangas 245 CBC 34 : *outputlen = strlen(*output);
2224 heikki.linnakangas 246 GIC 34 : *done = false;
2224 heikki.linnakangas 247 CBC 34 : state->state = FE_SCRAM_NONCE_SENT;
2224 heikki.linnakangas 248 GBC 34 : break;
249 :
2224 heikki.linnakangas 250 CBC 34 : case FE_SCRAM_NONCE_SENT:
2224 heikki.linnakangas 251 ECB : /* Receive salt and server nonce, send response. */
1921 peter_e 252 GBC 34 : if (!read_server_first_message(state, input))
2224 heikki.linnakangas 253 UIC 0 : goto error;
2224 heikki.linnakangas 254 ECB :
1921 peter_e 255 CBC 34 : *output = build_client_final_message(state);
2224 heikki.linnakangas 256 34 : if (*output == NULL)
2224 heikki.linnakangas 257 LBC 0 : goto error;
258 :
2224 heikki.linnakangas 259 CBC 34 : *outputlen = strlen(*output);
2224 heikki.linnakangas 260 GIC 34 : *done = false;
2224 heikki.linnakangas 261 CBC 34 : state->state = FE_SCRAM_PROOF_SENT;
2224 heikki.linnakangas 262 GBC 34 : break;
263 :
2224 heikki.linnakangas 264 GIC 28 : case FE_SCRAM_PROOF_SENT:
265 : /* Receive server signature */
1921 peter_e 266 28 : if (!read_server_final_message(state, input))
2224 heikki.linnakangas 267 UIC 0 : goto error;
2224 heikki.linnakangas 268 ECB :
269 : /*
2172 heikki.linnakangas 270 EUB : * Verify server signature, to make sure we're talking to the
1294 jdavis 271 : * genuine server.
272 : */
451 michael 273 GIC 28 : if (!verify_server_signature(state, success, &errstr))
858 michael 274 ECB : {
145 peter 275 UNC 0 : libpq_append_conn_error(conn, "could not verify server signature: %s", errstr);
858 michael 276 UIC 0 : goto error;
858 michael 277 ECB : }
278 :
858 michael 279 CBC 28 : if (!*success)
2224 heikki.linnakangas 280 ECB : {
145 peter 281 UNC 0 : libpq_append_conn_error(conn, "incorrect server signature");
282 : }
2224 heikki.linnakangas 283 GBC 28 : *done = true;
284 28 : state->state = FE_SCRAM_FINISHED;
26 michael 285 GNC 28 : state->conn->client_finished_auth = true;
2224 heikki.linnakangas 286 GIC 28 : break;
2224 heikki.linnakangas 287 ECB :
2224 heikki.linnakangas 288 UIC 0 : default:
2224 heikki.linnakangas 289 EUB : /* shouldn't happen */
145 peter 290 UNC 0 : libpq_append_conn_error(conn, "invalid SCRAM exchange state");
2224 heikki.linnakangas 291 UIC 0 : goto error;
292 : }
2224 heikki.linnakangas 293 GIC 96 : return;
294 :
2224 heikki.linnakangas 295 UIC 0 : error:
296 0 : *done = true;
297 0 : *success = false;
298 : }
299 :
300 : /*
301 : * Read value for an attribute part of a SCRAM message.
818 tgl 302 ECB : *
303 : * The buffer at **input is destructively modified, and *input is
304 : * advanced over the "attr=value" string and any following comma.
305 : *
306 : * On failure, append an error message to *errorMessage and return NULL.
2224 heikki.linnakangas 307 : */
308 : static char *
2224 heikki.linnakangas 309 GBC 130 : read_attr_value(char **input, char attr, PQExpBuffer errorMessage)
310 : {
2224 heikki.linnakangas 311 GIC 130 : char *begin = *input;
2224 heikki.linnakangas 312 EUB : char *end;
313 :
2224 heikki.linnakangas 314 CBC 130 : if (*begin != attr)
315 : {
145 peter 316 UNC 0 : libpq_append_error(errorMessage,
317 : "malformed SCRAM message (attribute \"%c\" expected)",
318 : attr);
2224 heikki.linnakangas 319 UIC 0 : return NULL;
320 : }
2224 heikki.linnakangas 321 GBC 130 : begin++;
322 :
2224 heikki.linnakangas 323 CBC 130 : if (*begin != '=')
324 : {
145 peter 325 UNC 0 : libpq_append_error(errorMessage,
326 : "malformed SCRAM message (expected character \"=\" for attribute \"%c\")",
327 : attr);
2224 heikki.linnakangas 328 UIC 0 : return NULL;
2224 heikki.linnakangas 329 ECB : }
2224 heikki.linnakangas 330 GIC 130 : begin++;
2224 heikki.linnakangas 331 ECB :
2224 heikki.linnakangas 332 CBC 130 : end = begin;
2224 heikki.linnakangas 333 GIC 3944 : while (*end && *end != ',')
334 3814 : end++;
2224 heikki.linnakangas 335 ECB :
2224 heikki.linnakangas 336 GIC 130 : if (*end)
2224 heikki.linnakangas 337 ECB : {
2224 heikki.linnakangas 338 GIC 68 : *end = '\0';
339 68 : *input = end + 1;
340 : }
341 : else
342 62 : *input = end;
343 :
2224 heikki.linnakangas 344 CBC 130 : return begin;
345 : }
2224 heikki.linnakangas 346 ECB :
347 : /*
348 : * Build the first exchange message sent by the client.
349 : */
350 : static char *
1921 peter_e 351 GIC 34 : build_client_first_message(fe_scram_state *state)
352 : {
353 34 : PGconn *conn = state->conn;
354 : char raw_nonce[SCRAM_RAW_NONCE_LEN + 1];
355 : char *result;
356 : int channel_info_len;
2224 heikki.linnakangas 357 ECB : int encoded_len;
358 : PQExpBufferData buf;
2224 heikki.linnakangas 359 EUB :
360 : /*
361 : * Generate a "raw" nonce. This is converted to ASCII-printable form by
362 : * base64-encoding it.
2224 heikki.linnakangas 363 ECB : */
1559 michael 364 GIC 34 : if (!pg_strong_random(raw_nonce, SCRAM_RAW_NONCE_LEN))
2224 heikki.linnakangas 365 ECB : {
145 peter 366 UNC 0 : libpq_append_conn_error(conn, "could not generate nonce");
2224 heikki.linnakangas 367 UBC 0 : return NULL;
2224 heikki.linnakangas 368 EUB : }
369 :
1375 michael 370 CBC 34 : encoded_len = pg_b64_enc_len(SCRAM_RAW_NONCE_LEN);
371 : /* don't forget the zero-terminator */
372 34 : state->client_nonce = malloc(encoded_len + 1);
2224 heikki.linnakangas 373 GIC 34 : if (state->client_nonce == NULL)
2224 heikki.linnakangas 374 EUB : {
145 peter 375 UNC 0 : libpq_append_conn_error(conn, "out of memory");
2224 heikki.linnakangas 376 LBC 0 : return NULL;
377 : }
1375 michael 378 GIC 34 : encoded_len = pg_b64_encode(raw_nonce, SCRAM_RAW_NONCE_LEN,
379 : state->client_nonce, encoded_len);
380 34 : if (encoded_len < 0)
381 : {
145 peter 382 UNC 0 : libpq_append_conn_error(conn, "could not encode nonce");
1375 michael 383 UIC 0 : return NULL;
1375 michael 384 ECB : }
2224 heikki.linnakangas 385 GIC 34 : state->client_nonce[encoded_len] = '\0';
386 :
387 : /*
388 : * Generate message. The username is left empty as the backend uses the
2224 heikki.linnakangas 389 ECB : * value provided by the startup packet. Also, as this username is not
390 : * prepared with SASLprep, the message parsing would fail if it includes
391 : * '=' or ',' characters.
392 : */
393 :
1968 peter_e 394 GIC 34 : initPQExpBuffer(&buf);
1968 peter_e 395 ECB :
396 : /*
397 : * First build the gs2-header with channel binding information.
398 : */
1895 peter_e 399 GIC 34 : if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0)
400 : {
1921 peter_e 401 GBC 5 : Assert(conn->ssl_in_use);
1375 drowley 402 GIC 5 : appendPQExpBufferStr(&buf, "p=tls-server-end-point");
403 : }
404 : #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
1294 jdavis 405 29 : else if (conn->channel_binding[0] != 'd' && /* disable */
406 27 : conn->ssl_in_use)
407 : {
408 : /*
1968 peter_e 409 ECB : * Client supports channel binding, but thinks the server does not.
410 : */
1375 drowley 411 UIC 0 : appendPQExpBufferChar(&buf, 'y');
1968 peter_e 412 ECB : }
1708 heikki.linnakangas 413 EUB : #endif
414 : else
1968 peter_e 415 ECB : {
416 : /*
1294 jdavis 417 : * Client does not support channel binding, or has disabled it.
1968 peter_e 418 : */
1375 drowley 419 GBC 29 : appendPQExpBufferChar(&buf, 'n');
420 : }
421 :
1968 peter_e 422 GIC 34 : if (PQExpBufferDataBroken(buf))
1968 peter_e 423 UIC 0 : goto oom_error;
424 :
1968 peter_e 425 CBC 34 : channel_info_len = buf.len;
1968 peter_e 426 ECB :
1968 peter_e 427 GBC 34 : appendPQExpBuffer(&buf, ",,n=,r=%s", state->client_nonce);
1968 peter_e 428 GIC 34 : if (PQExpBufferDataBroken(buf))
1968 peter_e 429 LBC 0 : goto oom_error;
1968 peter_e 430 ECB :
1968 peter_e 431 EUB : /*
432 : * The first message content needs to be saved without channel binding
1968 peter_e 433 ECB : * information.
434 : */
1968 peter_e 435 GIC 34 : state->client_first_message_bare = strdup(buf.data + channel_info_len + 2);
1968 peter_e 436 GBC 34 : if (!state->client_first_message_bare)
1968 peter_e 437 UBC 0 : goto oom_error;
1968 peter_e 438 EUB :
1968 peter_e 439 GBC 34 : result = strdup(buf.data);
1968 peter_e 440 GIC 34 : if (result == NULL)
1968 peter_e 441 UIC 0 : goto oom_error;
442 :
1968 peter_e 443 GIC 34 : termPQExpBuffer(&buf);
444 34 : return result;
445 :
1968 peter_e 446 LBC 0 : oom_error:
1968 peter_e 447 UIC 0 : termPQExpBuffer(&buf);
145 peter 448 UNC 0 : libpq_append_conn_error(conn, "out of memory");
1968 peter_e 449 UIC 0 : return NULL;
450 : }
451 :
2224 heikki.linnakangas 452 ECB : /*
453 : * Build the final exchange message sent from the client.
454 : */
455 : static char *
1921 peter_e 456 GIC 34 : build_client_final_message(fe_scram_state *state)
457 : {
458 : PQExpBufferData buf;
459 34 : PGconn *conn = state->conn;
460 : uint8 client_proof[SCRAM_MAX_KEY_LEN];
461 : char *result;
462 : int encoded_len;
451 michael 463 34 : const char *errstr = NULL;
2224 heikki.linnakangas 464 ECB :
2224 heikki.linnakangas 465 GIC 34 : initPQExpBuffer(&buf);
466 :
2224 heikki.linnakangas 467 ECB : /*
468 : * Construct client-final-message-without-proof. We need to remember it
469 : * for verifying the server proof in the final step of authentication.
470 : *
471 : * The channel binding flag handling (p/y/n) must be consistent with
472 : * build_client_first_message(), because the server will check that it's
473 : * the same flag both times.
474 : */
1895 peter_e 475 GIC 34 : if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0)
1968 peter_e 476 ECB : {
477 : #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
1921 peter_e 478 CBC 5 : char *cbind_data = NULL;
1921 peter_e 479 GIC 5 : size_t cbind_data_len = 0;
480 : size_t cbind_header_len;
1968 peter_e 481 EUB : char *cbind_input;
482 : size_t cbind_input_len;
483 : int encoded_cbind_len;
484 :
1708 heikki.linnakangas 485 ECB : /* Fetch hash data of server's SSL certificate */
486 : cbind_data =
1708 heikki.linnakangas 487 GIC 5 : pgtls_get_peer_certificate_hash(state->conn,
1708 heikki.linnakangas 488 ECB : &cbind_data_len);
1708 heikki.linnakangas 489 CBC 5 : if (cbind_data == NULL)
1968 peter_e 490 ECB : {
1708 heikki.linnakangas 491 : /* error message is already set on error */
1968 peter_e 492 UIC 0 : termPQExpBuffer(&buf);
1968 peter_e 493 UBC 0 : return NULL;
1968 peter_e 494 EUB : }
495 :
1375 drowley 496 CBC 5 : appendPQExpBufferStr(&buf, "c=");
1968 peter_e 497 ECB :
498 : /* p=type,, */
1708 heikki.linnakangas 499 CBC 5 : cbind_header_len = strlen("p=tls-server-end-point,,");
1968 peter_e 500 5 : cbind_input_len = cbind_header_len + cbind_data_len;
1968 peter_e 501 GIC 5 : cbind_input = malloc(cbind_input_len);
1968 peter_e 502 GBC 5 : if (!cbind_input)
1921 peter_e 503 EUB : {
1921 peter_e 504 UBC 0 : free(cbind_data);
1968 peter_e 505 UIC 0 : goto oom_error;
1921 peter_e 506 ECB : }
1708 heikki.linnakangas 507 CBC 5 : memcpy(cbind_input, "p=tls-server-end-point,,", cbind_header_len);
1968 peter_e 508 GIC 5 : memcpy(cbind_input + cbind_header_len, cbind_data, cbind_data_len);
1968 peter_e 509 ECB :
1375 michael 510 GIC 5 : encoded_cbind_len = pg_b64_enc_len(cbind_input_len);
1375 michael 511 GBC 5 : if (!enlargePQExpBuffer(&buf, encoded_cbind_len))
1968 peter_e 512 EUB : {
1921 peter_e 513 UBC 0 : free(cbind_data);
1968 514 0 : free(cbind_input);
1968 peter_e 515 UIC 0 : goto oom_error;
1968 peter_e 516 EUB : }
1375 michael 517 GIC 5 : encoded_cbind_len = pg_b64_encode(cbind_input, cbind_input_len,
1375 michael 518 CBC 5 : buf.data + buf.len,
1375 michael 519 ECB : encoded_cbind_len);
1375 michael 520 GIC 5 : if (encoded_cbind_len < 0)
1375 michael 521 ECB : {
1375 michael 522 LBC 0 : free(cbind_data);
1375 michael 523 UIC 0 : free(cbind_input);
524 0 : termPQExpBuffer(&buf);
818 tgl 525 0 : appendPQExpBufferStr(&conn->errorMessage,
526 : "could not encode cbind data for channel binding\n");
1375 michael 527 0 : return NULL;
528 : }
1375 michael 529 GIC 5 : buf.len += encoded_cbind_len;
1968 peter_e 530 5 : buf.data[buf.len] = '\0';
531 :
1921 532 5 : free(cbind_data);
1968 533 5 : free(cbind_input);
534 : #else
1708 heikki.linnakangas 535 ECB : /*
536 : * Chose channel binding, but the SSL library doesn't support it.
1708 heikki.linnakangas 537 EUB : * Shouldn't happen.
538 : */
539 : termPQExpBuffer(&buf);
818 tgl 540 ECB : appendPQExpBufferStr(&conn->errorMessage,
541 : "channel binding not supported by this build\n");
1708 heikki.linnakangas 542 : return NULL;
1674 tgl 543 EUB : #endif /* HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH */
544 : }
1708 heikki.linnakangas 545 ECB : #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
1294 jdavis 546 CBC 29 : else if (conn->channel_binding[0] != 'd' && /* disable */
1294 jdavis 547 GBC 27 : conn->ssl_in_use)
1375 drowley 548 UIC 0 : appendPQExpBufferStr(&buf, "c=eSws"); /* base64 of "y,," */
1708 heikki.linnakangas 549 ECB : #endif
1968 peter_e 550 : else
1375 drowley 551 GBC 29 : appendPQExpBufferStr(&buf, "c=biws"); /* base64 of "n,," */
552 :
1968 peter_e 553 GIC 34 : if (PQExpBufferDataBroken(buf))
1968 peter_e 554 LBC 0 : goto oom_error;
1968 peter_e 555 ECB :
1968 peter_e 556 GIC 34 : appendPQExpBuffer(&buf, ",r=%s", state->nonce);
2224 heikki.linnakangas 557 34 : if (PQExpBufferDataBroken(buf))
2224 heikki.linnakangas 558 UBC 0 : goto oom_error;
2224 heikki.linnakangas 559 EUB :
2224 heikki.linnakangas 560 GBC 34 : state->client_final_message_without_proof = strdup(buf.data);
2224 heikki.linnakangas 561 GIC 34 : if (state->client_final_message_without_proof == NULL)
2224 heikki.linnakangas 562 UIC 0 : goto oom_error;
2224 heikki.linnakangas 563 ECB :
564 : /* Append proof to it, to form client-final-message. */
858 michael 565 CBC 34 : if (!calculate_client_proof(state,
858 michael 566 GBC 34 : state->client_final_message_without_proof,
451 michael 567 ECB : client_proof, &errstr))
568 : {
858 michael 569 LBC 0 : termPQExpBuffer(&buf);
145 peter 570 UNC 0 : libpq_append_conn_error(conn, "could not calculate client proof: %s", errstr);
858 michael 571 UBC 0 : return NULL;
858 michael 572 EUB : }
2224 heikki.linnakangas 573 :
1375 drowley 574 GIC 34 : appendPQExpBufferStr(&buf, ",p=");
110 michael 575 GNC 34 : encoded_len = pg_b64_enc_len(state->key_length);
1375 michael 576 CBC 34 : if (!enlargePQExpBuffer(&buf, encoded_len))
2224 heikki.linnakangas 577 UIC 0 : goto oom_error;
1375 michael 578 CBC 34 : encoded_len = pg_b64_encode((char *) client_proof,
579 : state->key_length,
1375 michael 580 GBC 34 : buf.data + buf.len,
581 : encoded_len);
1375 michael 582 CBC 34 : if (encoded_len < 0)
1375 michael 583 ECB : {
1375 michael 584 UIC 0 : termPQExpBuffer(&buf);
145 peter 585 UNC 0 : libpq_append_conn_error(conn, "could not encode client proof");
1375 michael 586 UBC 0 : return NULL;
1375 michael 587 EUB : }
1375 michael 588 GIC 34 : buf.len += encoded_len;
2224 heikki.linnakangas 589 34 : buf.data[buf.len] = '\0';
590 :
591 34 : result = strdup(buf.data);
592 34 : if (result == NULL)
2224 heikki.linnakangas 593 UIC 0 : goto oom_error;
2224 heikki.linnakangas 594 ECB :
2224 heikki.linnakangas 595 GIC 34 : termPQExpBuffer(&buf);
2224 heikki.linnakangas 596 CBC 34 : return result;
597 :
2224 heikki.linnakangas 598 UIC 0 : oom_error:
599 0 : termPQExpBuffer(&buf);
145 peter 600 UNC 0 : libpq_append_conn_error(conn, "out of memory");
2224 heikki.linnakangas 601 UIC 0 : return NULL;
2224 heikki.linnakangas 602 ECB : }
603 :
604 : /*
2224 heikki.linnakangas 605 EUB : * Read the first exchange message coming from the server.
606 : */
607 : static bool
1921 peter_e 608 GIC 34 : read_server_first_message(fe_scram_state *state, char *input)
609 : {
1921 peter_e 610 CBC 34 : PGconn *conn = state->conn;
611 : char *iterations_str;
2224 heikki.linnakangas 612 ECB : char *endptr;
613 : char *encoded_salt;
614 : char *nonce;
1375 michael 615 EUB : int decoded_salt_len;
616 :
2224 heikki.linnakangas 617 GIC 34 : state->server_first_message = strdup(input);
618 34 : if (state->server_first_message == NULL)
2224 heikki.linnakangas 619 ECB : {
145 peter 620 UNC 0 : libpq_append_conn_error(conn, "out of memory");
2224 heikki.linnakangas 621 UBC 0 : return false;
2224 heikki.linnakangas 622 EUB : }
623 :
624 : /* parse the message */
1921 peter_e 625 CBC 34 : nonce = read_attr_value(&input, 'r',
1921 peter_e 626 ECB : &conn->errorMessage);
2224 heikki.linnakangas 627 GIC 34 : if (nonce == NULL)
2224 heikki.linnakangas 628 EUB : {
818 tgl 629 : /* read_attr_value() has appended an error string */
2224 heikki.linnakangas 630 UIC 0 : return false;
631 : }
2224 heikki.linnakangas 632 ECB :
633 : /* Verify immediately that the server used our part of the nonce */
2147 heikki.linnakangas 634 GIC 34 : if (strlen(nonce) < strlen(state->client_nonce) ||
635 34 : memcmp(nonce, state->client_nonce, strlen(state->client_nonce)) != 0)
2224 heikki.linnakangas 636 EUB : {
145 peter 637 UNC 0 : libpq_append_conn_error(conn, "invalid SCRAM response (nonce mismatch)");
2224 heikki.linnakangas 638 LBC 0 : return false;
2224 heikki.linnakangas 639 ECB : }
640 :
2224 heikki.linnakangas 641 GBC 34 : state->nonce = strdup(nonce);
642 34 : if (state->nonce == NULL)
643 : {
145 peter 644 UNC 0 : libpq_append_conn_error(conn, "out of memory");
2224 heikki.linnakangas 645 UIC 0 : return false;
646 : }
2224 heikki.linnakangas 647 ECB :
1921 peter_e 648 GIC 34 : encoded_salt = read_attr_value(&input, 's', &conn->errorMessage);
2224 heikki.linnakangas 649 GBC 34 : if (encoded_salt == NULL)
2224 heikki.linnakangas 650 EUB : {
651 : /* read_attr_value() has appended an error string */
2224 heikki.linnakangas 652 UIC 0 : return false;
2224 heikki.linnakangas 653 ECB : }
1375 michael 654 CBC 34 : decoded_salt_len = pg_b64_dec_len(strlen(encoded_salt));
1375 michael 655 GIC 34 : state->salt = malloc(decoded_salt_len);
2224 heikki.linnakangas 656 34 : if (state->salt == NULL)
2224 heikki.linnakangas 657 EUB : {
145 peter 658 UNC 0 : libpq_append_conn_error(conn, "out of memory");
2224 heikki.linnakangas 659 LBC 0 : return false;
660 : }
2224 heikki.linnakangas 661 GBC 68 : state->saltlen = pg_b64_decode(encoded_salt,
662 34 : strlen(encoded_salt),
663 : state->salt,
664 : decoded_salt_len);
1392 michael 665 CBC 34 : if (state->saltlen < 0)
1392 michael 666 EUB : {
145 peter 667 UNC 0 : libpq_append_conn_error(conn, "malformed SCRAM message (invalid salt)");
1392 michael 668 UIC 0 : return false;
669 : }
670 :
1921 peter_e 671 GIC 34 : iterations_str = read_attr_value(&input, 'i', &conn->errorMessage);
2224 heikki.linnakangas 672 34 : if (iterations_str == NULL)
673 : {
818 tgl 674 ECB : /* read_attr_value() has appended an error string */
2224 heikki.linnakangas 675 UIC 0 : return false;
2224 heikki.linnakangas 676 ECB : }
2194 heikki.linnakangas 677 GIC 34 : state->iterations = strtol(iterations_str, &endptr, 10);
2224 678 34 : if (*endptr != '\0' || state->iterations < 1)
679 : {
145 peter 680 UNC 0 : libpq_append_conn_error(conn, "malformed SCRAM message (invalid iteration count)");
2224 heikki.linnakangas 681 LBC 0 : return false;
682 : }
2224 heikki.linnakangas 683 EUB :
2224 heikki.linnakangas 684 GBC 34 : if (*input != '\0')
145 peter 685 UNC 0 : libpq_append_conn_error(conn, "malformed SCRAM message (garbage at end of server-first-message)");
686 :
2224 heikki.linnakangas 687 CBC 34 : return true;
688 : }
2224 heikki.linnakangas 689 EUB :
690 : /*
691 : * Read the final exchange message coming from the server.
692 : */
693 : static bool
1921 peter_e 694 GIC 28 : read_server_final_message(fe_scram_state *state, char *input)
2224 heikki.linnakangas 695 EUB : {
1921 peter_e 696 GIC 28 : PGconn *conn = state->conn;
2172 heikki.linnakangas 697 EUB : char *encoded_server_signature;
698 : char *decoded_server_signature;
699 : int server_signature_len;
700 :
2224 heikki.linnakangas 701 GIC 28 : state->server_final_message = strdup(input);
702 28 : if (!state->server_final_message)
2224 heikki.linnakangas 703 ECB : {
145 peter 704 UNC 0 : libpq_append_conn_error(conn, "out of memory");
2224 heikki.linnakangas 705 UIC 0 : return false;
706 : }
2224 heikki.linnakangas 707 EUB :
708 : /* Check for error result. */
2224 heikki.linnakangas 709 GIC 28 : if (*input == 'e')
2224 heikki.linnakangas 710 ECB : {
1921 peter_e 711 UBC 0 : char *errmsg = read_attr_value(&input, 'e',
712 : &conn->errorMessage);
2224 heikki.linnakangas 713 ECB :
818 tgl 714 LBC 0 : if (errmsg == NULL)
818 tgl 715 ECB : {
716 : /* read_attr_value() has appended an error message */
818 tgl 717 UBC 0 : return false;
818 tgl 718 EUB : }
145 peter 719 UNC 0 : libpq_append_conn_error(conn, "error received from server in SCRAM exchange: %s",
720 : errmsg);
2224 heikki.linnakangas 721 LBC 0 : return false;
722 : }
723 :
2224 heikki.linnakangas 724 ECB : /* Parse the message. */
1921 peter_e 725 GIC 28 : encoded_server_signature = read_attr_value(&input, 'v',
1921 peter_e 726 EUB : &conn->errorMessage);
2172 heikki.linnakangas 727 GBC 28 : if (encoded_server_signature == NULL)
2224 heikki.linnakangas 728 EUB : {
729 : /* read_attr_value() has appended an error message */
2224 heikki.linnakangas 730 LBC 0 : return false;
2224 heikki.linnakangas 731 ECB : }
732 :
2224 heikki.linnakangas 733 GIC 28 : if (*input != '\0')
145 peter 734 UNC 0 : libpq_append_conn_error(conn, "malformed SCRAM message (garbage at end of server-final-message)");
735 :
1392 michael 736 GIC 28 : server_signature_len = pg_b64_dec_len(strlen(encoded_server_signature));
737 28 : decoded_server_signature = malloc(server_signature_len);
738 28 : if (!decoded_server_signature)
739 : {
145 peter 740 UNC 0 : libpq_append_conn_error(conn, "out of memory");
1392 michael 741 LBC 0 : return false;
742 : }
743 :
2172 heikki.linnakangas 744 GIC 28 : server_signature_len = pg_b64_decode(encoded_server_signature,
745 28 : strlen(encoded_server_signature),
746 : decoded_server_signature,
747 : server_signature_len);
110 michael 748 GNC 28 : if (server_signature_len != state->key_length)
749 : {
1392 michael 750 UIC 0 : free(decoded_server_signature);
145 peter 751 UNC 0 : libpq_append_conn_error(conn, "malformed SCRAM message (invalid server signature)");
2224 heikki.linnakangas 752 UIC 0 : return false;
2224 heikki.linnakangas 753 EUB : }
110 michael 754 GNC 28 : memcpy(state->ServerSignature, decoded_server_signature,
755 28 : state->key_length);
1392 michael 756 GIC 28 : free(decoded_server_signature);
757 :
2224 heikki.linnakangas 758 28 : return true;
759 : }
760 :
761 : /*
2224 heikki.linnakangas 762 ECB : * Calculate the client proof, part of the final exchange message sent
451 michael 763 : * by the client. Returns true on success, false on failure with *errstr
764 : * pointing to a message about the error details.
2224 heikki.linnakangas 765 : */
858 michael 766 : static bool
2224 heikki.linnakangas 767 CBC 34 : calculate_client_proof(fe_scram_state *state,
2224 heikki.linnakangas 768 ECB : const char *client_final_message_without_proof,
769 : uint8 *result, const char **errstr)
770 : {
771 : uint8 StoredKey[SCRAM_MAX_KEY_LEN];
772 : uint8 ClientKey[SCRAM_MAX_KEY_LEN];
773 : uint8 ClientSignature[SCRAM_MAX_KEY_LEN];
774 : int i;
775 : pg_hmac_ctx *ctx;
736 michael 776 :
110 michael 777 GNC 34 : ctx = pg_hmac_create(state->hash_type);
736 michael 778 CBC 34 : if (ctx == NULL)
451 michael 779 ECB : {
451 michael 780 LBC 0 : *errstr = pg_hmac_error(NULL); /* returns OOM */
736 781 0 : return false;
451 michael 782 ECB : }
2224 heikki.linnakangas 783 :
2172 784 : /*
785 : * Calculate SaltedPassword, and store it in 'state' so that we can reuse
786 : * it later in verify_server_signature.
787 : */
110 michael 788 GNC 34 : if (scram_SaltedPassword(state->password, state->hash_type,
789 34 : state->key_length, state->salt, state->saltlen,
451 michael 790 GIC 34 : state->iterations, state->SaltedPassword,
451 michael 791 GBC 34 : errstr) < 0 ||
110 michael 792 GNC 34 : scram_ClientKey(state->SaltedPassword, state->hash_type,
793 34 : state->key_length, ClientKey, errstr) < 0 ||
794 34 : scram_H(ClientKey, state->hash_type, state->key_length,
795 : StoredKey, errstr) < 0)
796 : {
797 : /* errstr is already filled here */
451 michael 798 LBC 0 : pg_hmac_free(ctx);
799 0 : return false;
800 : }
451 michael 801 ECB :
110 michael 802 GNC 68 : if (pg_hmac_init(ctx, StoredKey, state->key_length) < 0 ||
736 michael 803 GIC 34 : pg_hmac_update(ctx,
804 34 : (uint8 *) state->client_first_message_bare,
805 68 : strlen(state->client_first_message_bare)) < 0 ||
806 68 : pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
807 34 : pg_hmac_update(ctx,
808 34 : (uint8 *) state->server_first_message,
809 68 : strlen(state->server_first_message)) < 0 ||
810 68 : pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
811 34 : pg_hmac_update(ctx,
812 : (uint8 *) client_final_message_without_proof,
736 michael 813 CBC 34 : strlen(client_final_message_without_proof)) < 0 ||
110 michael 814 GNC 34 : pg_hmac_final(ctx, ClientSignature, state->key_length) < 0)
815 : {
451 michael 816 UIC 0 : *errstr = pg_hmac_error(ctx);
736 817 0 : pg_hmac_free(ctx);
858 818 0 : return false;
819 : }
2224 heikki.linnakangas 820 ECB :
110 michael 821 GNC 1122 : for (i = 0; i < state->key_length; i++)
2224 heikki.linnakangas 822 GIC 1088 : result[i] = ClientKey[i] ^ ClientSignature[i];
858 michael 823 EUB :
736 michael 824 GBC 34 : pg_hmac_free(ctx);
858 michael 825 GIC 34 : return true;
826 : }
2224 heikki.linnakangas 827 ECB :
828 : /*
829 : * Validate the server signature, received as part of the final exchange
830 : * message received from the server. *match tracks if the server signature
858 michael 831 EUB : * matched or not. Returns true if the server signature got verified, and
451 832 : * false for a processing error with *errstr pointing to a message about the
833 : * error details.
834 : */
835 : static bool
451 michael 836 CBC 28 : verify_server_signature(fe_scram_state *state, bool *match,
451 michael 837 ECB : const char **errstr)
2224 heikki.linnakangas 838 : {
839 : uint8 expected_ServerSignature[SCRAM_MAX_KEY_LEN];
840 : uint8 ServerKey[SCRAM_MAX_KEY_LEN];
736 michael 841 : pg_hmac_ctx *ctx;
842 :
110 michael 843 GNC 28 : ctx = pg_hmac_create(state->hash_type);
736 michael 844 CBC 28 : if (ctx == NULL)
451 michael 845 ECB : {
451 michael 846 LBC 0 : *errstr = pg_hmac_error(NULL); /* returns OOM */
847 0 : return false;
451 michael 848 ECB : }
849 :
110 michael 850 GNC 28 : if (scram_ServerKey(state->SaltedPassword, state->hash_type,
851 : state->key_length, ServerKey, errstr) < 0)
451 michael 852 EUB : {
853 : /* errstr is filled already */
451 michael 854 UBC 0 : pg_hmac_free(ctx);
736 michael 855 UIC 0 : return false;
856 : }
2224 heikki.linnakangas 857 ECB :
858 : /* calculate ServerSignature */
110 michael 859 GNC 56 : if (pg_hmac_init(ctx, ServerKey, state->key_length) < 0 ||
736 michael 860 CBC 28 : pg_hmac_update(ctx,
861 28 : (uint8 *) state->client_first_message_bare,
736 michael 862 GBC 56 : strlen(state->client_first_message_bare)) < 0 ||
736 michael 863 GIC 56 : pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
736 michael 864 CBC 28 : pg_hmac_update(ctx,
736 michael 865 GIC 28 : (uint8 *) state->server_first_message,
736 michael 866 CBC 56 : strlen(state->server_first_message)) < 0 ||
736 michael 867 GIC 56 : pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
868 28 : pg_hmac_update(ctx,
869 28 : (uint8 *) state->client_final_message_without_proof,
870 56 : strlen(state->client_final_message_without_proof)) < 0 ||
871 28 : pg_hmac_final(ctx, expected_ServerSignature,
110 michael 872 GNC 28 : state->key_length) < 0)
873 : {
451 michael 874 UIC 0 : *errstr = pg_hmac_error(ctx);
736 875 0 : pg_hmac_free(ctx);
858 michael 876 LBC 0 : return false;
877 : }
878 :
736 michael 879 GIC 28 : pg_hmac_free(ctx);
880 :
881 : /* signature processed, so now check after it */
110 michael 882 GNC 28 : if (memcmp(expected_ServerSignature, state->ServerSignature,
883 28 : state->key_length) != 0)
858 michael 884 UIC 0 : *match = false;
885 : else
858 michael 886 GIC 28 : *match = true;
887 :
2224 heikki.linnakangas 888 28 : return true;
889 : }
2224 heikki.linnakangas 890 ECB :
2167 891 : /*
892 : * Build a new SCRAM secret.
451 michael 893 EUB : *
894 : * On error, returns NULL and sets *errstr to point to a message about the
895 : * error details.
2167 heikki.linnakangas 896 ECB : */
897 : char *
13 dgustafsson 898 GNC 1 : pg_fe_scram_build_secret(const char *password, int iterations, const char **errstr)
899 : {
1674 tgl 900 ECB : char *prep_password;
901 : pg_saslprep_rc rc;
2167 heikki.linnakangas 902 EUB : char saltbuf[SCRAM_DEFAULT_SALT_LEN];
903 : char *result;
904 :
905 : /*
906 : * Normalize the password with SASLprep. If that doesn't work, because
2167 heikki.linnakangas 907 ECB : * the password isn't valid UTF-8 or contains prohibited characters, just
908 : * proceed with the original password. (See comments at the top of
909 : * auth-scram.c.)
910 : */
2167 heikki.linnakangas 911 GIC 1 : rc = pg_saslprep(password, &prep_password);
2167 heikki.linnakangas 912 CBC 1 : if (rc == SASLPREP_OOM)
913 : {
227 peter 914 LBC 0 : *errstr = libpq_gettext("out of memory");
2167 heikki.linnakangas 915 UIC 0 : return NULL;
916 : }
2167 heikki.linnakangas 917 GIC 1 : if (rc == SASLPREP_SUCCESS)
918 1 : password = (const char *) prep_password;
919 :
920 : /* Generate a random salt */
1559 michael 921 1 : if (!pg_strong_random(saltbuf, SCRAM_DEFAULT_SALT_LEN))
922 : {
227 peter 923 UIC 0 : *errstr = libpq_gettext("could not generate random salt");
297 peter 924 UNC 0 : free(prep_password);
2167 heikki.linnakangas 925 UIC 0 : return NULL;
926 : }
927 :
110 michael 928 GNC 1 : result = scram_build_secret(PG_SHA256, SCRAM_SHA_256_KEY_LEN, saltbuf,
929 : SCRAM_DEFAULT_SALT_LEN,
930 : iterations, password,
931 : errstr);
932 :
297 peter 933 1 : free(prep_password);
934 :
2167 heikki.linnakangas 935 GIC 1 : return result;
936 : }
|