PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
sasl.h File Reference
#include "lib/stringinfo.h"
#include "libpq/libpq-be.h"
Include dependency graph for sasl.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  pg_be_sasl_mech
 

Macros

#define PG_SASL_EXCHANGE_CONTINUE   0
 
#define PG_SASL_EXCHANGE_SUCCESS   1
 
#define PG_SASL_EXCHANGE_FAILURE   2
 
#define PG_MAX_SASL_MESSAGE_LENGTH   1024
 

Typedefs

typedef struct pg_be_sasl_mech pg_be_sasl_mech
 

Functions

int CheckSASLAuth (const pg_be_sasl_mech *mech, Port *port, char *shadow_pass, const char **logdetail)
 

Macro Definition Documentation

◆ PG_MAX_SASL_MESSAGE_LENGTH

#define PG_MAX_SASL_MESSAGE_LENGTH   1024

Definition at line 35 of file sasl.h.

◆ PG_SASL_EXCHANGE_CONTINUE

#define PG_SASL_EXCHANGE_CONTINUE   0

Definition at line 25 of file sasl.h.

◆ PG_SASL_EXCHANGE_FAILURE

#define PG_SASL_EXCHANGE_FAILURE   2

Definition at line 27 of file sasl.h.

◆ PG_SASL_EXCHANGE_SUCCESS

#define PG_SASL_EXCHANGE_SUCCESS   1

Definition at line 26 of file sasl.h.

Typedef Documentation

◆ pg_be_sasl_mech

Function Documentation

◆ CheckSASLAuth()

int CheckSASLAuth ( const pg_be_sasl_mech mech,
Port port,
char *  shadow_pass,
const char **  logdetail 
)

Definition at line 44 of file auth-sasl.c.

46{
47 StringInfoData sasl_mechs;
48 int mtype;
50 void *opaq = NULL;
51 char *output = NULL;
52 int outputlen = 0;
53 const char *input;
54 int inputlen;
55 int result;
56 bool initial;
57
58 /*
59 * Send the SASL authentication request to user. It includes the list of
60 * authentication mechanisms that are supported.
61 */
62 initStringInfo(&sasl_mechs);
63
64 mech->get_mechanisms(port, &sasl_mechs);
65 /* Put another '\0' to mark that list is finished. */
66 appendStringInfoChar(&sasl_mechs, '\0');
67
68 sendAuthRequest(port, AUTH_REQ_SASL, sasl_mechs.data, sasl_mechs.len);
69 pfree(sasl_mechs.data);
70
71 /*
72 * Loop through SASL message exchange. This exchange can consist of
73 * multiple messages sent in both directions. First message is always
74 * from the client. All messages from client to server are password
75 * packets (type 'p').
76 */
77 initial = true;
78 do
79 {
81 mtype = pq_getbyte();
82 if (mtype != PqMsg_SASLResponse)
83 {
84 /* Only log error if client didn't disconnect. */
85 if (mtype != EOF)
86 {
88 (errcode(ERRCODE_PROTOCOL_VIOLATION),
89 errmsg("expected SASL response, got message type %d",
90 mtype)));
91 }
92 else
93 return STATUS_EOF;
94 }
95
96 /* Get the actual SASL message */
99 {
100 /* EOF - pq_getmessage already logged error */
101 pfree(buf.data);
102 return STATUS_ERROR;
103 }
104
105 elog(DEBUG4, "processing received SASL response of length %d", buf.len);
106
107 /*
108 * The first SASLInitialResponse message is different from the others.
109 * It indicates which SASL mechanism the client selected, and contains
110 * an optional Initial Client Response payload. The subsequent
111 * SASLResponse messages contain just the SASL payload.
112 */
113 if (initial)
114 {
115 const char *selected_mech;
116
117 selected_mech = pq_getmsgrawstring(&buf);
118
119 /*
120 * Initialize the status tracker for message exchanges.
121 *
122 * If the user doesn't exist, or doesn't have a valid password, or
123 * it's expired, we still go through the motions of SASL
124 * authentication, but tell the authentication method that the
125 * authentication is "doomed". That is, it's going to fail, no
126 * matter what.
127 *
128 * This is because we don't want to reveal to an attacker what
129 * usernames are valid, nor which users have a valid password.
130 */
131 opaq = mech->init(port, selected_mech, shadow_pass);
132
133 inputlen = pq_getmsgint(&buf, 4);
134 if (inputlen == -1)
135 input = NULL;
136 else
137 input = pq_getmsgbytes(&buf, inputlen);
138
139 initial = false;
140 }
141 else
142 {
143 inputlen = buf.len;
144 input = pq_getmsgbytes(&buf, buf.len);
145 }
147
148 /*
149 * The StringInfo guarantees that there's a \0 byte after the
150 * response.
151 */
152 Assert(input == NULL || input[inputlen] == '\0');
153
154 /*
155 * Hand the incoming message to the mechanism implementation.
156 */
157 result = mech->exchange(opaq, input, inputlen,
158 &output, &outputlen,
159 logdetail);
160
161 /* input buffer no longer used */
162 pfree(buf.data);
163
164 if (output)
165 {
166 /*
167 * PG_SASL_EXCHANGE_FAILURE with some output is forbidden by SASL.
168 * Make sure here that the mechanism used got that right.
169 */
170 if (result == PG_SASL_EXCHANGE_FAILURE)
171 elog(ERROR, "output message found after SASL exchange failure");
172
173 /*
174 * Negotiation generated data to be sent to the client.
175 */
176 elog(DEBUG4, "sending SASL challenge of length %d", outputlen);
177
178 if (result == PG_SASL_EXCHANGE_SUCCESS)
180 else
182
183 pfree(output);
184 }
185 } while (result == PG_SASL_EXCHANGE_CONTINUE);
186
187 /* Oops, Something bad happened */
188 if (result != PG_SASL_EXCHANGE_SUCCESS)
189 {
190 return STATUS_ERROR;
191 }
192
193 return STATUS_OK;
194}
void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:676
#define STATUS_OK
Definition: c.h:1126
#define Assert(condition)
Definition: c.h:815
#define STATUS_EOF
Definition: c.h:1128
#define STATUS_ERROR
Definition: c.h:1127
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
#define DEBUG4
Definition: elog.h:27
FILE * input
FILE * output
void pfree(void *pointer)
Definition: mcxt.c:1521
static int port
Definition: pg_regress.c:115
static char * buf
Definition: pg_test_fsync.c:72
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1203
int pq_getbyte(void)
Definition: pqcomm.c:964
void pq_startmsgread(void)
Definition: pqcomm.c:1141
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:635
const char * pq_getmsgrawstring(StringInfo msg)
Definition: pqformat.c:608
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:508
#define AUTH_REQ_SASL_CONT
Definition: protocol.h:85
#define PqMsg_SASLResponse
Definition: protocol.h:33
#define AUTH_REQ_SASL
Definition: protocol.h:84
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:86
#define PG_SASL_EXCHANGE_FAILURE
Definition: sasl.h:27
#define PG_SASL_EXCHANGE_CONTINUE
Definition: sasl.h:25
#define PG_SASL_EXCHANGE_SUCCESS
Definition: sasl.h:26
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
void *(* init)(Port *port, const char *mech, const char *shadow_pass)
Definition: sasl.h:88
int(* exchange)(void *state, const char *input, int inputlen, char **output, int *outputlen, const char **logdetail)
Definition: sasl.h:134
void(* get_mechanisms)(Port *port, StringInfo buf)
Definition: sasl.h:64
int max_message_length
Definition: sasl.h:140

References appendStringInfoChar(), Assert, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, AUTH_REQ_SASL_FIN, buf, StringInfoData::data, DEBUG4, elog, ereport, errcode(), errmsg(), ERROR, pg_be_sasl_mech::exchange, pg_be_sasl_mech::get_mechanisms, pg_be_sasl_mech::init, initStringInfo(), input, StringInfoData::len, pg_be_sasl_mech::max_message_length, output, pfree(), PG_SASL_EXCHANGE_CONTINUE, PG_SASL_EXCHANGE_FAILURE, PG_SASL_EXCHANGE_SUCCESS, port, pq_getbyte(), pq_getmessage(), pq_getmsgbytes(), pq_getmsgend(), pq_getmsgint(), pq_getmsgrawstring(), pq_startmsgread(), PqMsg_SASLResponse, sendAuthRequest(), STATUS_EOF, STATUS_ERROR, and STATUS_OK.

Referenced by CheckPWChallengeAuth().