LCOV - differential code coverage report
Current view: top level - src/backend/libpq - auth-scram.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 77.4 % 394 305 19 59 11 22 195 41 47 55 223 1 16
Current Date: 2023-04-08 17:13:01 Functions: 89.5 % 19 17 2 14 3 2 17
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (60,120] days: 100.0 % 40 40 40
(240..) days: 74.8 % 353 264 19 59 11 22 195 47 53 213
Function coverage date bins:
(60,120] days: 100.0 % 3 3 3
(240..) days: 41.2 % 34 14 2 14 2 16

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

Generated by: LCOV version v1.16-55-g56c0a2a