]> granicus.if.org Git - postgresql/blob - src/backend/libpq/auth-scram.c
Remove configure switch --disable-strong-random
[postgresql] / src / backend / libpq / auth-scram.c
1 /*-------------------------------------------------------------------------
2  *
3  * auth-scram.c
4  *        Server-side implementation of the SASL SCRAM-SHA-256 mechanism.
5  *
6  * See the following RFCs for more details:
7  * - RFC 5802: https://tools.ietf.org/html/rfc5802
8  * - RFC 5803: https://tools.ietf.org/html/rfc5803
9  * - RFC 7677: https://tools.ietf.org/html/rfc7677
10  *
11  * Here are some differences:
12  *
13  * - Username from the authentication exchange is not used. The client
14  *       should send an empty string as the username.
15  *
16  * - If the password isn't valid UTF-8, or contains characters prohibited
17  *       by the SASLprep profile, we skip the SASLprep pre-processing and use
18  *       the raw bytes in calculating the hash.
19  *
20  * - If channel binding is used, the channel binding type is always
21  *       "tls-server-end-point".  The spec says the default is "tls-unique"
22  *       (RFC 5802, section 6.1. Default Channel Binding), but there are some
23  *       problems with that.  Firstly, not all SSL libraries provide an API to
24  *       get the TLS Finished message, required to use "tls-unique".  Secondly,
25  *       "tls-unique" is not specified for TLS v1.3, and as of this writing,
26  *       it's not clear if there will be a replacement.  We could support both
27  *       "tls-server-end-point" and "tls-unique", but for our use case,
28  *       "tls-unique" doesn't really have any advantages.  The main advantage
29  *       of "tls-unique" would be that it works even if the server doesn't
30  *       have a certificate, but PostgreSQL requires a server certificate
31  *       whenever SSL is used, anyway.
32  *
33  *
34  * The password stored in pg_authid consists of the iteration count, salt,
35  * StoredKey and ServerKey.
36  *
37  * SASLprep usage
38  * --------------
39  *
40  * One notable difference to the SCRAM specification is that while the
41  * specification dictates that the password is in UTF-8, and prohibits
42  * certain characters, we are more lenient.  If the password isn't a valid
43  * UTF-8 string, or contains prohibited characters, the raw bytes are used
44  * to calculate the hash instead, without SASLprep processing.  This is
45  * because PostgreSQL supports other encodings too, and the encoding being
46  * used during authentication is undefined (client_encoding isn't set until
47  * after authentication).  In effect, we try to interpret the password as
48  * UTF-8 and apply SASLprep processing, but if it looks invalid, we assume
49  * that it's in some other encoding.
50  *
51  * In the worst case, we misinterpret a password that's in a different
52  * encoding as being Unicode, because it happens to consists entirely of
53  * valid UTF-8 bytes, and we apply Unicode normalization to it.  As long
54  * as we do that consistently, that will not lead to failed logins.
55  * Fortunately, the UTF-8 byte sequences that are ignored by SASLprep
56  * don't correspond to any commonly used characters in any of the other
57  * supported encodings, so it should not lead to any significant loss in
58  * entropy, even if the normalization is incorrectly applied to a
59  * non-UTF-8 password.
60  *
61  * Error handling
62  * --------------
63  *
64  * Don't reveal user information to an unauthenticated client.  We don't
65  * want an attacker to be able to probe whether a particular username is
66  * valid.  In SCRAM, the server has to read the salt and iteration count
67  * from the user's password verifier, and send it to the client.  To avoid
68  * revealing whether a user exists, when the client tries to authenticate
69  * with a username that doesn't exist, or doesn't have a valid SCRAM
70  * verifier in pg_authid, we create a fake salt and iteration count
71  * on-the-fly, and proceed with the authentication with that.  In the end,
72  * we'll reject the attempt, as if an incorrect password was given.  When
73  * we are performing a "mock" authentication, the 'doomed' flag in
74  * scram_state is set.
75  *
76  * In the error messages, avoid printing strings from the client, unless
77  * you check that they are pure ASCII.  We don't want an unauthenticated
78  * attacker to be able to spam the logs with characters that are not valid
79  * to the encoding being used, whatever that is.  We cannot avoid that in
80  * general, after logging in, but let's do what we can here.
81  *
82  *
83  * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
84  * Portions Copyright (c) 1994, Regents of the University of California
85  *
86  * src/backend/libpq/auth-scram.c
87  *
88  *-------------------------------------------------------------------------
89  */
90 #include "postgres.h"
91
92 #include <unistd.h>
93
94 #include "access/xlog.h"
95 #include "catalog/pg_authid.h"
96 #include "catalog/pg_control.h"
97 #include "common/base64.h"
98 #include "common/saslprep.h"
99 #include "common/scram-common.h"
100 #include "common/sha2.h"
101 #include "libpq/auth.h"
102 #include "libpq/crypt.h"
103 #include "libpq/scram.h"
104 #include "miscadmin.h"
105 #include "utils/builtins.h"
106 #include "utils/timestamp.h"
107
108 /*
109  * Status data for a SCRAM authentication exchange.  This should be kept
110  * internal to this file.
111  */
112 typedef enum
113 {
114         SCRAM_AUTH_INIT,
115         SCRAM_AUTH_SALT_SENT,
116         SCRAM_AUTH_FINISHED
117 } scram_state_enum;
118
119 typedef struct
120 {
121         scram_state_enum state;
122
123         const char *username;           /* username from startup packet */
124
125         Port       *port;
126         bool            channel_binding_in_use;
127
128         int                     iterations;
129         char       *salt;                       /* base64-encoded */
130         uint8           StoredKey[SCRAM_KEY_LEN];
131         uint8           ServerKey[SCRAM_KEY_LEN];
132
133         /* Fields of the first message from client */
134         char            cbind_flag;
135         char       *client_first_message_bare;
136         char       *client_username;
137         char       *client_nonce;
138
139         /* Fields from the last message from client */
140         char       *client_final_message_without_proof;
141         char       *client_final_nonce;
142         char            ClientProof[SCRAM_KEY_LEN];
143
144         /* Fields generated in the server */
145         char       *server_first_message;
146         char       *server_nonce;
147
148         /*
149          * If something goes wrong during the authentication, or we are performing
150          * a "mock" authentication (see comments at top of file), the 'doomed'
151          * flag is set.  A reason for the failure, for the server log, is put in
152          * 'logdetail'.
153          */
154         bool            doomed;
155         char       *logdetail;
156 } scram_state;
157
158 static void read_client_first_message(scram_state *state, char *input);
159 static void read_client_final_message(scram_state *state, char *input);
160 static char *build_server_first_message(scram_state *state);
161 static char *build_server_final_message(scram_state *state);
162 static bool verify_client_proof(scram_state *state);
163 static bool verify_final_nonce(scram_state *state);
164 static bool parse_scram_verifier(const char *verifier, int *iterations,
165                                          char **salt, uint8 *stored_key, uint8 *server_key);
166 static void mock_scram_verifier(const char *username, int *iterations,
167                                         char **salt, uint8 *stored_key, uint8 *server_key);
168 static bool is_scram_printable(char *p);
169 static char *sanitize_char(char c);
170 static char *sanitize_str(const char *s);
171 static char *scram_mock_salt(const char *username);
172
173 /*
174  * pg_be_scram_get_mechanisms
175  *
176  * Get a list of SASL mechanisms that this module supports.
177  *
178  * For the convenience of building the FE/BE packet that lists the
179  * mechanisms, the names are appended to the given StringInfo buffer,
180  * separated by '\0' bytes.
181  */
182 void
183 pg_be_scram_get_mechanisms(Port *port, StringInfo buf)
184 {
185         /*
186          * Advertise the mechanisms in decreasing order of importance.  So the
187          * channel-binding variants go first, if they are supported.  Channel
188          * binding is only supported with SSL, and only if the SSL implementation
189          * has a function to get the certificate's hash.
190          */
191 #ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
192         if (port->ssl_in_use)
193         {
194                 appendStringInfoString(buf, SCRAM_SHA_256_PLUS_NAME);
195                 appendStringInfoChar(buf, '\0');
196         }
197 #endif
198         appendStringInfoString(buf, SCRAM_SHA_256_NAME);
199         appendStringInfoChar(buf, '\0');
200 }
201
202 /*
203  * pg_be_scram_init
204  *
205  * Initialize a new SCRAM authentication exchange status tracker.  This
206  * needs to be called before doing any exchange.  It will be filled later
207  * after the beginning of the exchange with verifier data.
208  *
209  * 'selected_mech' identifies the SASL mechanism that the client selected.
210  * It should be one of the mechanisms that we support, as returned by
211  * pg_be_scram_get_mechanisms().
212  *
213  * 'shadow_pass' is the role's password verifier, from pg_authid.rolpassword.
214  * The username was provided by the client in the startup message, and is
215  * available in port->user_name.  If 'shadow_pass' is NULL, we still perform
216  * an authentication exchange, but it will fail, as if an incorrect password
217  * was given.
218  */
219 void *
220 pg_be_scram_init(Port *port,
221                                  const char *selected_mech,
222                                  const char *shadow_pass)
223 {
224         scram_state *state;
225         bool            got_verifier;
226
227         state = (scram_state *) palloc0(sizeof(scram_state));
228         state->port = port;
229         state->state = SCRAM_AUTH_INIT;
230
231         /*
232          * Parse the selected mechanism.
233          *
234          * Note that if we don't support channel binding, either because the SSL
235          * implementation doesn't support it or we're not using SSL at all, we
236          * would not have advertised the PLUS variant in the first place.  If the
237          * client nevertheless tries to select it, it's a protocol violation like
238          * selecting any other SASL mechanism we don't support.
239          */
240 #ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
241         if (strcmp(selected_mech, SCRAM_SHA_256_PLUS_NAME) == 0 && port->ssl_in_use)
242                 state->channel_binding_in_use = true;
243         else
244 #endif
245         if (strcmp(selected_mech, SCRAM_SHA_256_NAME) == 0)
246                 state->channel_binding_in_use = false;
247         else
248                 ereport(ERROR,
249                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
250                                  errmsg("client selected an invalid SASL authentication mechanism")));
251
252         /*
253          * Parse the stored password verifier.
254          */
255         if (shadow_pass)
256         {
257                 int                     password_type = get_password_type(shadow_pass);
258
259                 if (password_type == PASSWORD_TYPE_SCRAM_SHA_256)
260                 {
261                         if (parse_scram_verifier(shadow_pass, &state->iterations, &state->salt,
262                                                                          state->StoredKey, state->ServerKey))
263                                 got_verifier = true;
264                         else
265                         {
266                                 /*
267                                  * The password looked like a SCRAM verifier, but could not be
268                                  * parsed.
269                                  */
270                                 ereport(LOG,
271                                                 (errmsg("invalid SCRAM verifier for user \"%s\"",
272                                                                 state->port->user_name)));
273                                 got_verifier = false;
274                         }
275                 }
276                 else
277                 {
278                         /*
279                          * The user doesn't have SCRAM verifier. (You cannot do SCRAM
280                          * authentication with an MD5 hash.)
281                          */
282                         state->logdetail = psprintf(_("User \"%s\" does not have a valid SCRAM verifier."),
283                                                                                 state->port->user_name);
284                         got_verifier = false;
285                 }
286         }
287         else
288         {
289                 /*
290                  * The caller requested us to perform a dummy authentication.  This is
291                  * considered normal, since the caller requested it, so don't set log
292                  * detail.
293                  */
294                 got_verifier = false;
295         }
296
297         /*
298          * If the user did not have a valid SCRAM verifier, we still go through
299          * the motions with a mock one, and fail as if the client supplied an
300          * incorrect password.  This is to avoid revealing information to an
301          * attacker.
302          */
303         if (!got_verifier)
304         {
305                 mock_scram_verifier(state->port->user_name, &state->iterations,
306                                                         &state->salt, state->StoredKey, state->ServerKey);
307                 state->doomed = true;
308         }
309
310         return state;
311 }
312
313 /*
314  * Continue a SCRAM authentication exchange.
315  *
316  * 'input' is the SCRAM payload sent by the client.  On the first call,
317  * 'input' contains the "Initial Client Response" that the client sent as
318  * part of the SASLInitialResponse message, or NULL if no Initial Client
319  * Response was given.  (The SASL specification distinguishes between an
320  * empty response and non-existing one.)  On subsequent calls, 'input'
321  * cannot be NULL.  For convenience in this function, the caller must
322  * ensure that there is a null terminator at input[inputlen].
323  *
324  * The next message to send to client is saved in 'output', for a length
325  * of 'outputlen'.  In the case of an error, optionally store a palloc'd
326  * string at *logdetail that will be sent to the postmaster log (but not
327  * the client).
328  */
329 int
330 pg_be_scram_exchange(void *opaq, char *input, int inputlen,
331                                          char **output, int *outputlen, char **logdetail)
332 {
333         scram_state *state = (scram_state *) opaq;
334         int                     result;
335
336         *output = NULL;
337
338         /*
339          * If the client didn't include an "Initial Client Response" in the
340          * SASLInitialResponse message, send an empty challenge, to which the
341          * client will respond with the same data that usually comes in the
342          * Initial Client Response.
343          */
344         if (input == NULL)
345         {
346                 Assert(state->state == SCRAM_AUTH_INIT);
347
348                 *output = pstrdup("");
349                 *outputlen = 0;
350                 return SASL_EXCHANGE_CONTINUE;
351         }
352
353         /*
354          * Check that the input length agrees with the string length of the input.
355          * We can ignore inputlen after this.
356          */
357         if (inputlen == 0)
358                 ereport(ERROR,
359                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
360                                  errmsg("malformed SCRAM message"),
361                                  errdetail("The message is empty.")));
362         if (inputlen != strlen(input))
363                 ereport(ERROR,
364                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
365                                  errmsg("malformed SCRAM message"),
366                                  errdetail("Message length does not match input length.")));
367
368         switch (state->state)
369         {
370                 case SCRAM_AUTH_INIT:
371
372                         /*
373                          * Initialization phase.  Receive the first message from client
374                          * and be sure that it parsed correctly.  Then send the challenge
375                          * to the client.
376                          */
377                         read_client_first_message(state, input);
378
379                         /* prepare message to send challenge */
380                         *output = build_server_first_message(state);
381
382                         state->state = SCRAM_AUTH_SALT_SENT;
383                         result = SASL_EXCHANGE_CONTINUE;
384                         break;
385
386                 case SCRAM_AUTH_SALT_SENT:
387
388                         /*
389                          * Final phase for the server.  Receive the response to the
390                          * challenge previously sent, verify, and let the client know that
391                          * everything went well (or not).
392                          */
393                         read_client_final_message(state, input);
394
395                         if (!verify_final_nonce(state))
396                                 ereport(ERROR,
397                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
398                                                  errmsg("invalid SCRAM response"),
399                                                  errdetail("Nonce does not match.")));
400
401                         /*
402                          * Now check the final nonce and the client proof.
403                          *
404                          * If we performed a "mock" authentication that we knew would fail
405                          * from the get go, this is where we fail.
406                          *
407                          * The SCRAM specification includes an error code,
408                          * "invalid-proof", for authentication failure, but it also allows
409                          * erroring out in an application-specific way.  We choose to do
410                          * the latter, so that the error message for invalid password is
411                          * the same for all authentication methods.  The caller will call
412                          * ereport(), when we return SASL_EXCHANGE_FAILURE with no output.
413                          *
414                          * NB: the order of these checks is intentional.  We calculate the
415                          * client proof even in a mock authentication, even though it's
416                          * bound to fail, to thwart timing attacks to determine if a role
417                          * with the given name exists or not.
418                          */
419                         if (!verify_client_proof(state) || state->doomed)
420                         {
421                                 result = SASL_EXCHANGE_FAILURE;
422                                 break;
423                         }
424
425                         /* Build final message for client */
426                         *output = build_server_final_message(state);
427
428                         /* Success! */
429                         result = SASL_EXCHANGE_SUCCESS;
430                         state->state = SCRAM_AUTH_FINISHED;
431                         break;
432
433                 default:
434                         elog(ERROR, "invalid SCRAM exchange state");
435                         result = SASL_EXCHANGE_FAILURE;
436         }
437
438         if (result == SASL_EXCHANGE_FAILURE && state->logdetail && logdetail)
439                 *logdetail = state->logdetail;
440
441         if (*output)
442                 *outputlen = strlen(*output);
443
444         return result;
445 }
446
447 /*
448  * Construct a verifier string for SCRAM, stored in pg_authid.rolpassword.
449  *
450  * The result is palloc'd, so caller is responsible for freeing it.
451  */
452 char *
453 pg_be_scram_build_verifier(const char *password)
454 {
455         char       *prep_password;
456         pg_saslprep_rc rc;
457         char            saltbuf[SCRAM_DEFAULT_SALT_LEN];
458         char       *result;
459
460         /*
461          * Normalize the password with SASLprep.  If that doesn't work, because
462          * the password isn't valid UTF-8 or contains prohibited characters, just
463          * proceed with the original password.  (See comments at top of file.)
464          */
465         rc = pg_saslprep(password, &prep_password);
466         if (rc == SASLPREP_SUCCESS)
467                 password = (const char *) prep_password;
468
469         /* Generate random salt */
470         if (!pg_strong_random(saltbuf, SCRAM_DEFAULT_SALT_LEN))
471                 ereport(ERROR,
472                                 (errcode(ERRCODE_INTERNAL_ERROR),
473                                  errmsg("could not generate random salt")));
474
475         result = scram_build_verifier(saltbuf, SCRAM_DEFAULT_SALT_LEN,
476                                                                   SCRAM_DEFAULT_ITERATIONS, password);
477
478         if (prep_password)
479                 pfree(prep_password);
480
481         return result;
482 }
483
484 /*
485  * Verify a plaintext password against a SCRAM verifier.  This is used when
486  * performing plaintext password authentication for a user that has a SCRAM
487  * verifier stored in pg_authid.
488  */
489 bool
490 scram_verify_plain_password(const char *username, const char *password,
491                                                         const char *verifier)
492 {
493         char       *encoded_salt;
494         char       *salt;
495         int                     saltlen;
496         int                     iterations;
497         uint8           salted_password[SCRAM_KEY_LEN];
498         uint8           stored_key[SCRAM_KEY_LEN];
499         uint8           server_key[SCRAM_KEY_LEN];
500         uint8           computed_key[SCRAM_KEY_LEN];
501         char       *prep_password;
502         pg_saslprep_rc rc;
503
504         if (!parse_scram_verifier(verifier, &iterations, &encoded_salt,
505                                                           stored_key, server_key))
506         {
507                 /*
508                  * The password looked like a SCRAM verifier, but could not be parsed.
509                  */
510                 ereport(LOG,
511                                 (errmsg("invalid SCRAM verifier for user \"%s\"", username)));
512                 return false;
513         }
514
515         salt = palloc(pg_b64_dec_len(strlen(encoded_salt)));
516         saltlen = pg_b64_decode(encoded_salt, strlen(encoded_salt), salt);
517         if (saltlen == -1)
518         {
519                 ereport(LOG,
520                                 (errmsg("invalid SCRAM verifier for user \"%s\"", username)));
521                 return false;
522         }
523
524         /* Normalize the password */
525         rc = pg_saslprep(password, &prep_password);
526         if (rc == SASLPREP_SUCCESS)
527                 password = prep_password;
528
529         /* Compute Server Key based on the user-supplied plaintext password */
530         scram_SaltedPassword(password, salt, saltlen, iterations, salted_password);
531         scram_ServerKey(salted_password, computed_key);
532
533         if (prep_password)
534                 pfree(prep_password);
535
536         /*
537          * Compare the verifier's Server Key with the one computed from the
538          * user-supplied password.
539          */
540         return memcmp(computed_key, server_key, SCRAM_KEY_LEN) == 0;
541 }
542
543
544 /*
545  * Parse and validate format of given SCRAM verifier.
546  *
547  * Returns true if the SCRAM verifier has been parsed, and false otherwise.
548  */
549 static bool
550 parse_scram_verifier(const char *verifier, int *iterations, char **salt,
551                                          uint8 *stored_key, uint8 *server_key)
552 {
553         char       *v;
554         char       *p;
555         char       *scheme_str;
556         char       *salt_str;
557         char       *iterations_str;
558         char       *storedkey_str;
559         char       *serverkey_str;
560         int                     decoded_len;
561         char       *decoded_salt_buf;
562
563         /*
564          * The verifier is of form:
565          *
566          * SCRAM-SHA-256$<iterations>:<salt>$<storedkey>:<serverkey>
567          */
568         v = pstrdup(verifier);
569         if ((scheme_str = strtok(v, "$")) == NULL)
570                 goto invalid_verifier;
571         if ((iterations_str = strtok(NULL, ":")) == NULL)
572                 goto invalid_verifier;
573         if ((salt_str = strtok(NULL, "$")) == NULL)
574                 goto invalid_verifier;
575         if ((storedkey_str = strtok(NULL, ":")) == NULL)
576                 goto invalid_verifier;
577         if ((serverkey_str = strtok(NULL, "")) == NULL)
578                 goto invalid_verifier;
579
580         /* Parse the fields */
581         if (strcmp(scheme_str, "SCRAM-SHA-256") != 0)
582                 goto invalid_verifier;
583
584         errno = 0;
585         *iterations = strtol(iterations_str, &p, 10);
586         if (*p || errno != 0)
587                 goto invalid_verifier;
588
589         /*
590          * Verify that the salt is in Base64-encoded format, by decoding it,
591          * although we return the encoded version to the caller.
592          */
593         decoded_salt_buf = palloc(pg_b64_dec_len(strlen(salt_str)));
594         decoded_len = pg_b64_decode(salt_str, strlen(salt_str), decoded_salt_buf);
595         if (decoded_len < 0)
596                 goto invalid_verifier;
597         *salt = pstrdup(salt_str);
598
599         /*
600          * Decode StoredKey and ServerKey.
601          */
602         if (pg_b64_dec_len(strlen(storedkey_str) != SCRAM_KEY_LEN))
603                 goto invalid_verifier;
604         decoded_len = pg_b64_decode(storedkey_str, strlen(storedkey_str),
605                                                                 (char *) stored_key);
606         if (decoded_len != SCRAM_KEY_LEN)
607                 goto invalid_verifier;
608
609         if (pg_b64_dec_len(strlen(serverkey_str) != SCRAM_KEY_LEN))
610                 goto invalid_verifier;
611         decoded_len = pg_b64_decode(serverkey_str, strlen(serverkey_str),
612                                                                 (char *) server_key);
613         if (decoded_len != SCRAM_KEY_LEN)
614                 goto invalid_verifier;
615
616         return true;
617
618 invalid_verifier:
619         pfree(v);
620         *salt = NULL;
621         return false;
622 }
623
624 static void
625 mock_scram_verifier(const char *username, int *iterations, char **salt,
626                                         uint8 *stored_key, uint8 *server_key)
627 {
628         char       *raw_salt;
629         char       *encoded_salt;
630         int                     encoded_len;
631
632         /* Generate deterministic salt */
633         raw_salt = scram_mock_salt(username);
634
635         encoded_salt = (char *) palloc(pg_b64_enc_len(SCRAM_DEFAULT_SALT_LEN) + 1);
636         encoded_len = pg_b64_encode(raw_salt, SCRAM_DEFAULT_SALT_LEN, encoded_salt);
637         encoded_salt[encoded_len] = '\0';
638
639         *salt = encoded_salt;
640         *iterations = SCRAM_DEFAULT_ITERATIONS;
641
642         /* StoredKey and ServerKey are not used in a doomed authentication */
643         memset(stored_key, 0, SCRAM_KEY_LEN);
644         memset(server_key, 0, SCRAM_KEY_LEN);
645 }
646
647 /*
648  * Read the value in a given SCRAM exchange message for given attribute.
649  */
650 static char *
651 read_attr_value(char **input, char attr)
652 {
653         char       *begin = *input;
654         char       *end;
655
656         if (*begin != attr)
657                 ereport(ERROR,
658                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
659                                  errmsg("malformed SCRAM message"),
660                                  errdetail("Expected attribute \"%c\" but found \"%s\".",
661                                                    attr, sanitize_char(*begin))));
662         begin++;
663
664         if (*begin != '=')
665                 ereport(ERROR,
666                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
667                                  errmsg("malformed SCRAM message"),
668                                  errdetail("Expected character \"=\" for attribute \"%c\".", attr)));
669         begin++;
670
671         end = begin;
672         while (*end && *end != ',')
673                 end++;
674
675         if (*end)
676         {
677                 *end = '\0';
678                 *input = end + 1;
679         }
680         else
681                 *input = end;
682
683         return begin;
684 }
685
686 static bool
687 is_scram_printable(char *p)
688 {
689         /*------
690          * Printable characters, as defined by SCRAM spec: (RFC 5802)
691          *
692          *      printable               = %x21-2B / %x2D-7E
693          *                                        ;; Printable ASCII except ",".
694          *                                        ;; Note that any "printable" is also
695          *                                        ;; a valid "value".
696          *------
697          */
698         for (; *p; p++)
699         {
700                 if (*p < 0x21 || *p > 0x7E || *p == 0x2C /* comma */ )
701                         return false;
702         }
703         return true;
704 }
705
706 /*
707  * Convert an arbitrary byte to printable form.  For error messages.
708  *
709  * If it's a printable ASCII character, print it as a single character.
710  * otherwise, print it in hex.
711  *
712  * The returned pointer points to a static buffer.
713  */
714 static char *
715 sanitize_char(char c)
716 {
717         static char buf[5];
718
719         if (c >= 0x21 && c <= 0x7E)
720                 snprintf(buf, sizeof(buf), "'%c'", c);
721         else
722                 snprintf(buf, sizeof(buf), "0x%02x", (unsigned char) c);
723         return buf;
724 }
725
726 /*
727  * Convert an arbitrary string to printable form, for error messages.
728  *
729  * Anything that's not a printable ASCII character is replaced with
730  * '?', and the string is truncated at 30 characters.
731  *
732  * The returned pointer points to a static buffer.
733  */
734 static char *
735 sanitize_str(const char *s)
736 {
737         static char buf[30 + 1];
738         int                     i;
739
740         for (i = 0; i < sizeof(buf) - 1; i++)
741         {
742                 char            c = s[i];
743
744                 if (c == '\0')
745                         break;
746
747                 if (c >= 0x21 && c <= 0x7E)
748                         buf[i] = c;
749                 else
750                         buf[i] = '?';
751         }
752         buf[i] = '\0';
753         return buf;
754 }
755
756 /*
757  * Read the next attribute and value in a SCRAM exchange message.
758  *
759  * Returns NULL if there is attribute.
760  */
761 static char *
762 read_any_attr(char **input, char *attr_p)
763 {
764         char       *begin = *input;
765         char       *end;
766         char            attr = *begin;
767
768         /*------
769          * attr-val                = ALPHA "=" value
770          *                                       ;; Generic syntax of any attribute sent
771          *                                       ;; by server or client
772          *------
773          */
774         if (!((attr >= 'A' && attr <= 'Z') ||
775                   (attr >= 'a' && attr <= 'z')))
776                 ereport(ERROR,
777                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
778                                  errmsg("malformed SCRAM message"),
779                                  errdetail("Attribute expected, but found invalid character \"%s\".",
780                                                    sanitize_char(attr))));
781         if (attr_p)
782                 *attr_p = attr;
783         begin++;
784
785         if (*begin != '=')
786                 ereport(ERROR,
787                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
788                                  errmsg("malformed SCRAM message"),
789                                  errdetail("Expected character \"=\" for attribute \"%c\".", attr)));
790         begin++;
791
792         end = begin;
793         while (*end && *end != ',')
794                 end++;
795
796         if (*end)
797         {
798                 *end = '\0';
799                 *input = end + 1;
800         }
801         else
802                 *input = end;
803
804         return begin;
805 }
806
807 /*
808  * Read and parse the first message from client in the context of a SCRAM
809  * authentication exchange message.
810  *
811  * At this stage, any errors will be reported directly with ereport(ERROR).
812  */
813 static void
814 read_client_first_message(scram_state *state, char *input)
815 {
816         char       *channel_binding_type;
817
818         input = pstrdup(input);
819
820         /*------
821          * The syntax for the client-first-message is: (RFC 5802)
822          *
823          * saslname                = 1*(value-safe-char / "=2C" / "=3D")
824          *                                       ;; Conforms to <value>.
825          *
826          * authzid                 = "a=" saslname
827          *                                       ;; Protocol specific.
828          *
829          * cb-name                 = 1*(ALPHA / DIGIT / "." / "-")
830          *                                        ;; See RFC 5056, Section 7.
831          *                                        ;; E.g., "tls-server-end-point" or
832          *                                        ;; "tls-unique".
833          *
834          * gs2-cbind-flag  = ("p=" cb-name) / "n" / "y"
835          *                                       ;; "n" -> client doesn't support channel binding.
836          *                                       ;; "y" -> client does support channel binding
837          *                                       ;;                but thinks the server does not.
838          *                                       ;; "p" -> client requires channel binding.
839          *                                       ;; The selected channel binding follows "p=".
840          *
841          * gs2-header      = gs2-cbind-flag "," [ authzid ] ","
842          *                                       ;; GS2 header for SCRAM
843          *                                       ;; (the actual GS2 header includes an optional
844          *                                       ;; flag to indicate that the GSS mechanism is not
845          *                                       ;; "standard", but since SCRAM is "standard", we
846          *                                       ;; don't include that flag).
847          *
848          * username                = "n=" saslname
849          *                                       ;; Usernames are prepared using SASLprep.
850          *
851          * reserved-mext  = "m=" 1*(value-char)
852          *                                       ;; Reserved for signaling mandatory extensions.
853          *                                       ;; The exact syntax will be defined in
854          *                                       ;; the future.
855          *
856          * nonce                   = "r=" c-nonce [s-nonce]
857          *                                       ;; Second part provided by server.
858          *
859          * c-nonce                 = printable
860          *
861          * client-first-message-bare =
862          *                                       [reserved-mext ","]
863          *                                       username "," nonce ["," extensions]
864          *
865          * client-first-message =
866          *                                       gs2-header client-first-message-bare
867          *
868          * For example:
869          * n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL
870          *
871          * The "n,," in the beginning means that the client doesn't support
872          * channel binding, and no authzid is given.  "n=user" is the username.
873          * However, in PostgreSQL the username is sent in the startup packet, and
874          * the username in the SCRAM exchange is ignored.  libpq always sends it
875          * as an empty string.  The last part, "r=fyko+d2lbbFgONRv9qkxdawL" is
876          * the client nonce.
877          *------
878          */
879
880         /*
881          * Read gs2-cbind-flag.  (For details see also RFC 5802 Section 6 "Channel
882          * Binding".)
883          */
884         state->cbind_flag = *input;
885         switch (*input)
886         {
887                 case 'n':
888
889                         /*
890                          * The client does not support channel binding or has simply
891                          * decided to not use it.  In that case just let it go.
892                          */
893                         if (state->channel_binding_in_use)
894                                 ereport(ERROR,
895                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
896                                                  errmsg("malformed SCRAM message"),
897                                                  errdetail("The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data.")));
898
899                         input++;
900                         if (*input != ',')
901                                 ereport(ERROR,
902                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
903                                                  errmsg("malformed SCRAM message"),
904                                                  errdetail("Comma expected, but found character \"%s\".",
905                                                                    sanitize_char(*input))));
906                         input++;
907                         break;
908                 case 'y':
909
910                         /*
911                          * The client supports channel binding and thinks that the server
912                          * does not.  In this case, the server must fail authentication if
913                          * it supports channel binding.
914                          */
915                         if (state->channel_binding_in_use)
916                                 ereport(ERROR,
917                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
918                                                  errmsg("malformed SCRAM message"),
919                                                  errdetail("The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data.")));
920
921 #ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
922                         if (state->port->ssl_in_use)
923                                 ereport(ERROR,
924                                                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
925                                                  errmsg("SCRAM channel binding negotiation error"),
926                                                  errdetail("The client supports SCRAM channel binding but thinks the server does not.  "
927                                                                    "However, this server does support channel binding.")));
928 #endif
929                         input++;
930                         if (*input != ',')
931                                 ereport(ERROR,
932                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
933                                                  errmsg("malformed SCRAM message"),
934                                                  errdetail("Comma expected, but found character \"%s\".",
935                                                                    sanitize_char(*input))));
936                         input++;
937                         break;
938                 case 'p':
939
940                         /*
941                          * The client requires channel binding.  Channel binding type
942                          * follows, e.g., "p=tls-server-end-point".
943                          */
944                         if (!state->channel_binding_in_use)
945                                 ereport(ERROR,
946                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
947                                                  errmsg("malformed SCRAM message"),
948                                                  errdetail("The client selected SCRAM-SHA-256 without channel binding, but the SCRAM message includes channel binding data.")));
949
950                         channel_binding_type = read_attr_value(&input, 'p');
951
952                         /*
953                          * The only channel binding type we support is
954                          * tls-server-end-point.
955                          */
956                         if (strcmp(channel_binding_type, "tls-server-end-point") != 0)
957                                 ereport(ERROR,
958                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
959                                                  (errmsg("unsupported SCRAM channel-binding type \"%s\"",
960                                                                  sanitize_str(channel_binding_type)))));
961                         break;
962                 default:
963                         ereport(ERROR,
964                                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
965                                          errmsg("malformed SCRAM message"),
966                                          errdetail("Unexpected channel-binding flag \"%s\".",
967                                                            sanitize_char(*input))));
968         }
969
970         /*
971          * Forbid optional authzid (authorization identity).  We don't support it.
972          */
973         if (*input == 'a')
974                 ereport(ERROR,
975                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
976                                  errmsg("client uses authorization identity, but it is not supported")));
977         if (*input != ',')
978                 ereport(ERROR,
979                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
980                                  errmsg("malformed SCRAM message"),
981                                  errdetail("Unexpected attribute \"%s\" in client-first-message.",
982                                                    sanitize_char(*input))));
983         input++;
984
985         state->client_first_message_bare = pstrdup(input);
986
987         /*
988          * Any mandatory extensions would go here.  We don't support any.
989          *
990          * RFC 5802 specifies error code "e=extensions-not-supported" for this,
991          * but it can only be sent in the server-final message.  We prefer to fail
992          * immediately (which the RFC also allows).
993          */
994         if (*input == 'm')
995                 ereport(ERROR,
996                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
997                                  errmsg("client requires an unsupported SCRAM extension")));
998
999         /*
1000          * Read username.  Note: this is ignored.  We use the username from the
1001          * startup message instead, still it is kept around if provided as it
1002          * proves to be useful for debugging purposes.
1003          */
1004         state->client_username = read_attr_value(&input, 'n');
1005
1006         /* read nonce and check that it is made of only printable characters */
1007         state->client_nonce = read_attr_value(&input, 'r');
1008         if (!is_scram_printable(state->client_nonce))
1009                 ereport(ERROR,
1010                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1011                                  errmsg("non-printable characters in SCRAM nonce")));
1012
1013         /*
1014          * There can be any number of optional extensions after this.  We don't
1015          * support any extensions, so ignore them.
1016          */
1017         while (*input != '\0')
1018                 read_any_attr(&input, NULL);
1019
1020         /* success! */
1021 }
1022
1023 /*
1024  * Verify the final nonce contained in the last message received from
1025  * client in an exchange.
1026  */
1027 static bool
1028 verify_final_nonce(scram_state *state)
1029 {
1030         int                     client_nonce_len = strlen(state->client_nonce);
1031         int                     server_nonce_len = strlen(state->server_nonce);
1032         int                     final_nonce_len = strlen(state->client_final_nonce);
1033
1034         if (final_nonce_len != client_nonce_len + server_nonce_len)
1035                 return false;
1036         if (memcmp(state->client_final_nonce, state->client_nonce, client_nonce_len) != 0)
1037                 return false;
1038         if (memcmp(state->client_final_nonce + client_nonce_len, state->server_nonce, server_nonce_len) != 0)
1039                 return false;
1040
1041         return true;
1042 }
1043
1044 /*
1045  * Verify the client proof contained in the last message received from
1046  * client in an exchange.
1047  */
1048 static bool
1049 verify_client_proof(scram_state *state)
1050 {
1051         uint8           ClientSignature[SCRAM_KEY_LEN];
1052         uint8           ClientKey[SCRAM_KEY_LEN];
1053         uint8           client_StoredKey[SCRAM_KEY_LEN];
1054         scram_HMAC_ctx ctx;
1055         int                     i;
1056
1057         /* calculate ClientSignature */
1058         scram_HMAC_init(&ctx, state->StoredKey, SCRAM_KEY_LEN);
1059         scram_HMAC_update(&ctx,
1060                                           state->client_first_message_bare,
1061                                           strlen(state->client_first_message_bare));
1062         scram_HMAC_update(&ctx, ",", 1);
1063         scram_HMAC_update(&ctx,
1064                                           state->server_first_message,
1065                                           strlen(state->server_first_message));
1066         scram_HMAC_update(&ctx, ",", 1);
1067         scram_HMAC_update(&ctx,
1068                                           state->client_final_message_without_proof,
1069                                           strlen(state->client_final_message_without_proof));
1070         scram_HMAC_final(ClientSignature, &ctx);
1071
1072         /* Extract the ClientKey that the client calculated from the proof */
1073         for (i = 0; i < SCRAM_KEY_LEN; i++)
1074                 ClientKey[i] = state->ClientProof[i] ^ ClientSignature[i];
1075
1076         /* Hash it one more time, and compare with StoredKey */
1077         scram_H(ClientKey, SCRAM_KEY_LEN, client_StoredKey);
1078
1079         if (memcmp(client_StoredKey, state->StoredKey, SCRAM_KEY_LEN) != 0)
1080                 return false;
1081
1082         return true;
1083 }
1084
1085 /*
1086  * Build the first server-side message sent to the client in a SCRAM
1087  * communication exchange.
1088  */
1089 static char *
1090 build_server_first_message(scram_state *state)
1091 {
1092         /*------
1093          * The syntax for the server-first-message is: (RFC 5802)
1094          *
1095          * server-first-message =
1096          *                                       [reserved-mext ","] nonce "," salt ","
1097          *                                       iteration-count ["," extensions]
1098          *
1099          * nonce                   = "r=" c-nonce [s-nonce]
1100          *                                       ;; Second part provided by server.
1101          *
1102          * c-nonce                 = printable
1103          *
1104          * s-nonce                 = printable
1105          *
1106          * salt                    = "s=" base64
1107          *
1108          * iteration-count = "i=" posit-number
1109          *                                       ;; A positive number.
1110          *
1111          * Example:
1112          *
1113          * r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096
1114          *------
1115          */
1116
1117         /*
1118          * Per the spec, the nonce may consist of any printable ASCII characters.
1119          * For convenience, however, we don't use the whole range available,
1120          * rather, we generate some random bytes, and base64 encode them.
1121          */
1122         char            raw_nonce[SCRAM_RAW_NONCE_LEN];
1123         int                     encoded_len;
1124
1125         if (!pg_strong_random(raw_nonce, SCRAM_RAW_NONCE_LEN))
1126                 ereport(ERROR,
1127                                 (errcode(ERRCODE_INTERNAL_ERROR),
1128                                  errmsg("could not generate random nonce")));
1129
1130         state->server_nonce = palloc(pg_b64_enc_len(SCRAM_RAW_NONCE_LEN) + 1);
1131         encoded_len = pg_b64_encode(raw_nonce, SCRAM_RAW_NONCE_LEN, state->server_nonce);
1132         state->server_nonce[encoded_len] = '\0';
1133
1134         state->server_first_message =
1135                 psprintf("r=%s%s,s=%s,i=%u",
1136                                  state->client_nonce, state->server_nonce,
1137                                  state->salt, state->iterations);
1138
1139         return pstrdup(state->server_first_message);
1140 }
1141
1142
1143 /*
1144  * Read and parse the final message received from client.
1145  */
1146 static void
1147 read_client_final_message(scram_state *state, char *input)
1148 {
1149         char            attr;
1150         char       *channel_binding;
1151         char       *value;
1152         char       *begin,
1153                            *proof;
1154         char       *p;
1155         char       *client_proof;
1156
1157         begin = p = pstrdup(input);
1158
1159         /*------
1160          * The syntax for the server-first-message is: (RFC 5802)
1161          *
1162          * gs2-header      = gs2-cbind-flag "," [ authzid ] ","
1163          *                                       ;; GS2 header for SCRAM
1164          *                                       ;; (the actual GS2 header includes an optional
1165          *                                       ;; flag to indicate that the GSS mechanism is not
1166          *                                       ;; "standard", but since SCRAM is "standard", we
1167          *                                       ;; don't include that flag).
1168          *
1169          * cbind-input   = gs2-header [ cbind-data ]
1170          *                                       ;; cbind-data MUST be present for
1171          *                                       ;; gs2-cbind-flag of "p" and MUST be absent
1172          *                                       ;; for "y" or "n".
1173          *
1174          * channel-binding = "c=" base64
1175          *                                       ;; base64 encoding of cbind-input.
1176          *
1177          * proof                   = "p=" base64
1178          *
1179          * client-final-message-without-proof =
1180          *                                       channel-binding "," nonce [","
1181          *                                       extensions]
1182          *
1183          * client-final-message =
1184          *                                       client-final-message-without-proof "," proof
1185          *------
1186          */
1187
1188         /*
1189          * Read channel binding.  This repeats the channel-binding flags and is
1190          * then followed by the actual binding data depending on the type.
1191          */
1192         channel_binding = read_attr_value(&p, 'c');
1193         if (state->channel_binding_in_use)
1194         {
1195 #ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
1196                 const char *cbind_data = NULL;
1197                 size_t          cbind_data_len = 0;
1198                 size_t          cbind_header_len;
1199                 char       *cbind_input;
1200                 size_t          cbind_input_len;
1201                 char       *b64_message;
1202                 int                     b64_message_len;
1203
1204                 Assert(state->cbind_flag == 'p');
1205
1206                 /* Fetch hash data of server's SSL certificate */
1207                 cbind_data = be_tls_get_certificate_hash(state->port,
1208                                                                                                  &cbind_data_len);
1209
1210                 /* should not happen */
1211                 if (cbind_data == NULL || cbind_data_len == 0)
1212                         elog(ERROR, "could not get server certificate hash");
1213
1214                 cbind_header_len = strlen("p=tls-server-end-point,,");  /* p=type,, */
1215                 cbind_input_len = cbind_header_len + cbind_data_len;
1216                 cbind_input = palloc(cbind_input_len);
1217                 snprintf(cbind_input, cbind_input_len, "p=tls-server-end-point,,");
1218                 memcpy(cbind_input + cbind_header_len, cbind_data, cbind_data_len);
1219
1220                 b64_message = palloc(pg_b64_enc_len(cbind_input_len) + 1);
1221                 b64_message_len = pg_b64_encode(cbind_input, cbind_input_len,
1222                                                                                 b64_message);
1223                 b64_message[b64_message_len] = '\0';
1224
1225                 /*
1226                  * Compare the value sent by the client with the value expected by the
1227                  * server.
1228                  */
1229                 if (strcmp(channel_binding, b64_message) != 0)
1230                         ereport(ERROR,
1231                                         (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
1232                                          (errmsg("SCRAM channel binding check failed"))));
1233 #else
1234                 /* shouldn't happen, because we checked this earlier already */
1235                 elog(ERROR, "channel binding not supported by this build");
1236 #endif
1237         }
1238         else
1239         {
1240                 /*
1241                  * If we are not using channel binding, the binding data is expected
1242                  * to always be "biws", which is "n,," base64-encoded, or "eSws",
1243                  * which is "y,,".  We also have to check whether the flag is the same
1244                  * one that the client originally sent.
1245                  */
1246                 if (!(strcmp(channel_binding, "biws") == 0 && state->cbind_flag == 'n') &&
1247                         !(strcmp(channel_binding, "eSws") == 0 && state->cbind_flag == 'y'))
1248                         ereport(ERROR,
1249                                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
1250                                          (errmsg("unexpected SCRAM channel-binding attribute in client-final-message"))));
1251         }
1252
1253         state->client_final_nonce = read_attr_value(&p, 'r');
1254
1255         /* ignore optional extensions */
1256         do
1257         {
1258                 proof = p - 1;
1259                 value = read_any_attr(&p, &attr);
1260         } while (attr != 'p');
1261
1262         client_proof = palloc(pg_b64_dec_len(strlen(value)));
1263         if (pg_b64_decode(value, strlen(value), client_proof) != SCRAM_KEY_LEN)
1264                 ereport(ERROR,
1265                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1266                                  errmsg("malformed SCRAM message"),
1267                                  errdetail("Malformed proof in client-final-message.")));
1268         memcpy(state->ClientProof, client_proof, SCRAM_KEY_LEN);
1269         pfree(client_proof);
1270
1271         if (*p != '\0')
1272                 ereport(ERROR,
1273                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1274                                  errmsg("malformed SCRAM message"),
1275                                  errdetail("Garbage found at the end of client-final-message.")));
1276
1277         state->client_final_message_without_proof = palloc(proof - begin + 1);
1278         memcpy(state->client_final_message_without_proof, input, proof - begin);
1279         state->client_final_message_without_proof[proof - begin] = '\0';
1280 }
1281
1282 /*
1283  * Build the final server-side message of an exchange.
1284  */
1285 static char *
1286 build_server_final_message(scram_state *state)
1287 {
1288         uint8           ServerSignature[SCRAM_KEY_LEN];
1289         char       *server_signature_base64;
1290         int                     siglen;
1291         scram_HMAC_ctx ctx;
1292
1293         /* calculate ServerSignature */
1294         scram_HMAC_init(&ctx, state->ServerKey, SCRAM_KEY_LEN);
1295         scram_HMAC_update(&ctx,
1296                                           state->client_first_message_bare,
1297                                           strlen(state->client_first_message_bare));
1298         scram_HMAC_update(&ctx, ",", 1);
1299         scram_HMAC_update(&ctx,
1300                                           state->server_first_message,
1301                                           strlen(state->server_first_message));
1302         scram_HMAC_update(&ctx, ",", 1);
1303         scram_HMAC_update(&ctx,
1304                                           state->client_final_message_without_proof,
1305                                           strlen(state->client_final_message_without_proof));
1306         scram_HMAC_final(ServerSignature, &ctx);
1307
1308         server_signature_base64 = palloc(pg_b64_enc_len(SCRAM_KEY_LEN) + 1);
1309         siglen = pg_b64_encode((const char *) ServerSignature,
1310                                                    SCRAM_KEY_LEN, server_signature_base64);
1311         server_signature_base64[siglen] = '\0';
1312
1313         /*------
1314          * The syntax for the server-final-message is: (RFC 5802)
1315          *
1316          * verifier                = "v=" base64
1317          *                                       ;; base-64 encoded ServerSignature.
1318          *
1319          * server-final-message = (server-error / verifier)
1320          *                                       ["," extensions]
1321          *
1322          *------
1323          */
1324         return psprintf("v=%s", server_signature_base64);
1325 }
1326
1327
1328 /*
1329  * Deterministically generate salt for mock authentication, using a SHA256
1330  * hash based on the username and a cluster-level secret key.  Returns a
1331  * pointer to a static buffer of size SCRAM_DEFAULT_SALT_LEN.
1332  */
1333 static char *
1334 scram_mock_salt(const char *username)
1335 {
1336         pg_sha256_ctx ctx;
1337         static uint8 sha_digest[PG_SHA256_DIGEST_LENGTH];
1338         char       *mock_auth_nonce = GetMockAuthenticationNonce();
1339
1340         /*
1341          * Generate salt using a SHA256 hash of the username and the cluster's
1342          * mock authentication nonce.  (This works as long as the salt length is
1343          * not larger the SHA256 digest length. If the salt is smaller, the caller
1344          * will just ignore the extra data.)
1345          */
1346         StaticAssertStmt(PG_SHA256_DIGEST_LENGTH >= SCRAM_DEFAULT_SALT_LEN,
1347                                          "salt length greater than SHA256 digest length");
1348
1349         pg_sha256_init(&ctx);
1350         pg_sha256_update(&ctx, (uint8 *) username, strlen(username));
1351         pg_sha256_update(&ctx, (uint8 *) mock_auth_nonce, MOCK_AUTH_NONCE_LEN);
1352         pg_sha256_final(&ctx, sha_digest);
1353
1354         return (char *) sha_digest;
1355 }