PostgreSQL Source Code git master
auth.c File Reference
#include "postgres.h"
#include <sys/param.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pwd.h>
#include <unistd.h>
#include "commands/user.h"
#include "common/ip.h"
#include "common/md5.h"
#include "libpq/auth.h"
#include "libpq/crypt.h"
#include "libpq/libpq.h"
#include "libpq/oauth.h"
#include "libpq/pqformat.h"
#include "libpq/sasl.h"
#include "libpq/scram.h"
#include "miscadmin.h"
#include "port/pg_bswap.h"
#include "postmaster/postmaster.h"
#include "replication/walsender.h"
#include "storage/ipc.h"
#include "tcop/backend_startup.h"
#include "utils/memutils.h"
Include dependency graph for auth.c:

Go to the source code of this file.

Data Structures

struct  radius_attribute
 
struct  radius_packet
 

Macros

#define IDENT_USERNAME_MAX   512
 
#define IDENT_PORT   113
 
#define HOSTNAME_LOOKUP_DETAIL(port)
 
#define RADIUS_VECTOR_LENGTH   16
 
#define RADIUS_HEADER_LENGTH   20
 
#define RADIUS_MAX_PASSWORD_LENGTH   128
 
#define RADIUS_BUFFER_SIZE   1024
 
#define RADIUS_ACCESS_REQUEST   1
 
#define RADIUS_ACCESS_ACCEPT   2
 
#define RADIUS_ACCESS_REJECT   3
 
#define RADIUS_USER_NAME   1
 
#define RADIUS_PASSWORD   2
 
#define RADIUS_SERVICE_TYPE   6
 
#define RADIUS_NAS_IDENTIFIER   32
 
#define RADIUS_AUTHENTICATE_ONLY   8
 
#define RADIUS_TIMEOUT   3
 

Functions

static void auth_failed (Port *port, int status, const char *logdetail)
 
static char * recv_password_packet (Port *port)
 
static int CheckPasswordAuth (Port *port, const char **logdetail)
 
static int CheckPWChallengeAuth (Port *port, const char **logdetail)
 
static int CheckMD5Auth (Port *port, char *shadow_pass, const char **logdetail)
 
static int ident_inet (hbaPort *port)
 
static int auth_peer (hbaPort *port)
 
static int CheckRADIUSAuth (Port *port)
 
static int PerformRadiusTransaction (const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd)
 
void set_authn_id (Port *port, const char *id)
 
void ClientAuthentication (Port *port)
 
void sendAuthRequest (Port *port, AuthRequest areq, const char *extradata, int extralen)
 
static bool interpret_ident_response (const char *ident_response, char *ident_user)
 
static void radius_add_attribute (radius_packet *packet, uint8 type, const unsigned char *data, int len)
 

Variables

char * pg_krb_server_keyfile
 
bool pg_krb_caseins_users
 
bool pg_gss_accept_delegation
 
ClientAuthentication_hook_type ClientAuthentication_hook = NULL
 

Macro Definition Documentation

◆ HOSTNAME_LOOKUP_DETAIL

#define HOSTNAME_LOOKUP_DETAIL (   port)
Value:
(port->remote_hostname ? \
(port->remote_hostname_resolv == +1 ? \
errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
port->remote_hostname) : \
port->remote_hostname_resolv == 0 ? \
errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
port->remote_hostname) : \
port->remote_hostname_resolv == -1 ? \
errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
port->remote_hostname) : \
port->remote_hostname_resolv == -2 ? \
errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
port->remote_hostname, \
gai_strerror(port->remote_hostname_errcode)) : \
0) \
: (port->remote_hostname_resolv == -2 ? \
errdetail_log("Could not resolve client IP address to a host name: %s.", \
gai_strerror(port->remote_hostname_errcode)) : \
0))
int errdetail_log(const char *fmt,...)
Definition: elog.c:1252
static int port
Definition: pg_regress.c:115
const char * gai_strerror(int ecode)

◆ IDENT_PORT

#define IDENT_PORT   113

Definition at line 71 of file auth.c.

◆ IDENT_USERNAME_MAX

#define IDENT_USERNAME_MAX   512

Definition at line 68 of file auth.c.

◆ RADIUS_ACCESS_ACCEPT

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2795 of file auth.c.

◆ RADIUS_ACCESS_REJECT

#define RADIUS_ACCESS_REJECT   3

Definition at line 2796 of file auth.c.

◆ RADIUS_ACCESS_REQUEST

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2794 of file auth.c.

◆ RADIUS_AUTHENTICATE_ONLY

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2805 of file auth.c.

◆ RADIUS_BUFFER_SIZE

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2774 of file auth.c.

◆ RADIUS_HEADER_LENGTH

#define RADIUS_HEADER_LENGTH   20

Definition at line 2770 of file auth.c.

◆ RADIUS_MAX_PASSWORD_LENGTH

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2771 of file auth.c.

◆ RADIUS_NAS_IDENTIFIER

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2802 of file auth.c.

◆ RADIUS_PASSWORD

#define RADIUS_PASSWORD   2

Definition at line 2800 of file auth.c.

◆ RADIUS_SERVICE_TYPE

#define RADIUS_SERVICE_TYPE   6

Definition at line 2801 of file auth.c.

◆ RADIUS_TIMEOUT

#define RADIUS_TIMEOUT   3

Definition at line 2808 of file auth.c.

◆ RADIUS_USER_NAME

#define RADIUS_USER_NAME   1

Definition at line 2799 of file auth.c.

◆ RADIUS_VECTOR_LENGTH

#define RADIUS_VECTOR_LENGTH   16

Definition at line 2769 of file auth.c.

Function Documentation

◆ auth_failed()

static void auth_failed ( Port port,
int  status,
const char *  logdetail 
)
static

Definition at line 231 of file auth.c.

232{
233 const char *errstr;
234 char *cdetail;
235 int errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION;
236
237 /*
238 * If we failed due to EOF from client, just quit; there's no point in
239 * trying to send a message to the client, and not much point in logging
240 * the failure in the postmaster log. (Logging the failure might be
241 * desirable, were it not for the fact that libpq closes the connection
242 * unceremoniously if challenged for a password when it hasn't got one to
243 * send. We'll get a useless log entry for every psql connection under
244 * password auth, even if it's perfectly successful, if we log STATUS_EOF
245 * events.)
246 */
247 if (status == STATUS_EOF)
248 proc_exit(0);
249
250 switch (port->hba->auth_method)
251 {
252 case uaReject:
253 case uaImplicitReject:
254 errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
255 break;
256 case uaTrust:
257 errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
258 break;
259 case uaIdent:
260 errstr = gettext_noop("Ident authentication failed for user \"%s\"");
261 break;
262 case uaPeer:
263 errstr = gettext_noop("Peer authentication failed for user \"%s\"");
264 break;
265 case uaPassword:
266 case uaMD5:
267 case uaSCRAM:
268 errstr = gettext_noop("password authentication failed for user \"%s\"");
269 /* We use it to indicate if a .pgpass password failed. */
270 errcode_return = ERRCODE_INVALID_PASSWORD;
271 break;
272 case uaGSS:
273 errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
274 break;
275 case uaSSPI:
276 errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
277 break;
278 case uaPAM:
279 errstr = gettext_noop("PAM authentication failed for user \"%s\"");
280 break;
281 case uaBSD:
282 errstr = gettext_noop("BSD authentication failed for user \"%s\"");
283 break;
284 case uaLDAP:
285 errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
286 break;
287 case uaCert:
288 errstr = gettext_noop("certificate authentication failed for user \"%s\"");
289 break;
290 case uaRADIUS:
291 errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");
292 break;
293 case uaOAuth:
294 errstr = gettext_noop("OAuth bearer authentication failed for user \"%s\"");
295 break;
296 default:
297 errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
298 break;
299 }
300
301 cdetail = psprintf(_("Connection matched file \"%s\" line %d: \"%s\""),
302 port->hba->sourcefile, port->hba->linenumber,
303 port->hba->rawline);
304 if (logdetail)
305 logdetail = psprintf("%s\n%s", logdetail, cdetail);
306 else
307 logdetail = cdetail;
308
310 (errcode(errcode_return),
311 errmsg(errstr, port->user_name),
312 logdetail ? errdetail_log("%s", logdetail) : 0));
313
314 /* doesn't return */
315}
#define gettext_noop(x)
Definition: c.h:1167
#define STATUS_EOF
Definition: c.h:1142
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define _(x)
Definition: elog.c:91
#define FATAL
Definition: elog.h:41
#define ereport(elevel,...)
Definition: elog.h:149
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:92
@ uaBSD
Definition: hba.h:37
@ uaLDAP
Definition: hba.h:38
@ uaPeer
Definition: hba.h:41
@ uaPAM
Definition: hba.h:36
@ uaPassword
Definition: hba.h:31
@ uaCert
Definition: hba.h:39
@ uaMD5
Definition: hba.h:32
@ uaReject
Definition: hba.h:27
@ uaGSS
Definition: hba.h:34
@ uaSCRAM
Definition: hba.h:33
@ uaImplicitReject
Definition: hba.h:28
@ uaRADIUS
Definition: hba.h:40
@ uaIdent
Definition: hba.h:30
@ uaOAuth
Definition: hba.h:42
@ uaTrust
Definition: hba.h:29
@ uaSSPI
Definition: hba.h:35
void proc_exit(int code)
Definition: ipc.c:104
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43

References _, ereport, errcode(), ERRCODE_INVALID_PASSWORD, errdetail_log(), errmsg(), FATAL, gettext_noop, port, proc_exit(), psprintf(), STATUS_EOF, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaOAuth, uaPAM, uaPassword, uaPeer, uaRADIUS, uaReject, uaSCRAM, uaSSPI, and uaTrust.

Referenced by ClientAuthentication().

◆ auth_peer()

static int auth_peer ( hbaPort port)
static

Definition at line 1848 of file auth.c.

1849{
1850 uid_t uid;
1851 gid_t gid;
1852#ifndef WIN32
1853 struct passwd pwbuf;
1854 struct passwd *pw;
1855 char buf[1024];
1856 int rc;
1857 int ret;
1858#endif
1859
1860 if (getpeereid(port->sock, &uid, &gid) != 0)
1861 {
1862 /* Provide special error message if getpeereid is a stub */
1863 if (errno == ENOSYS)
1864 ereport(LOG,
1865 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1866 errmsg("peer authentication is not supported on this platform")));
1867 else
1868 ereport(LOG,
1870 errmsg("could not get peer credentials: %m")));
1871 return STATUS_ERROR;
1872 }
1873
1874#ifndef WIN32
1875 rc = getpwuid_r(uid, &pwbuf, buf, sizeof buf, &pw);
1876 if (rc != 0)
1877 {
1878 errno = rc;
1879 ereport(LOG,
1880 errmsg("could not look up local user ID %ld: %m", (long) uid));
1881 return STATUS_ERROR;
1882 }
1883 else if (!pw)
1884 {
1885 ereport(LOG,
1886 errmsg("local user with ID %ld does not exist", (long) uid));
1887 return STATUS_ERROR;
1888 }
1889
1890 /*
1891 * Make a copy of static getpw*() result area; this is our authenticated
1892 * identity. Set it before calling check_usermap, because authentication
1893 * has already succeeded and we want the log file to reflect that.
1894 */
1895 set_authn_id(port, pw->pw_name);
1896
1897 ret = check_usermap(port->hba->usermap, port->user_name,
1899
1900 return ret;
1901#else
1902 /* should have failed with ENOSYS above */
1903 Assert(false);
1904 return STATUS_ERROR;
1905#endif
1906}
void set_authn_id(Port *port, const char *id)
Definition: auth.c:333
#define STATUS_ERROR
Definition: c.h:1141
int errcode_for_socket_access(void)
Definition: elog.c:954
#define LOG
Definition: elog.h:31
Assert(PointerIsAligned(start, uint64))
int check_usermap(const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive)
Definition: hba.c:2966
ClientConnectionInfo MyClientConnectionInfo
Definition: miscinit.c:1069
static char * buf
Definition: pg_test_fsync.c:72
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition: getpeereid.c:33
const char * authn_id
Definition: libpq-be.h:99
int gid_t
Definition: win32_port.h:235
int uid_t
Definition: win32_port.h:234

References Assert(), ClientConnectionInfo::authn_id, buf, check_usermap(), ereport, errcode(), errcode_for_socket_access(), errmsg(), getpeereid(), LOG, MyClientConnectionInfo, port, set_authn_id(), and STATUS_ERROR.

Referenced by ClientAuthentication().

◆ CheckMD5Auth()

static int CheckMD5Auth ( Port port,
char *  shadow_pass,
const char **  logdetail 
)
static

Definition at line 875 of file auth.c.

876{
877 char md5Salt[4]; /* Password salt */
878 char *passwd;
879 int result;
880
881 /* include the salt to use for computing the response */
882 if (!pg_strong_random(md5Salt, 4))
883 {
884 ereport(LOG,
885 (errmsg("could not generate random MD5 salt")));
886 return STATUS_ERROR;
887 }
888
889 sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
890
891 passwd = recv_password_packet(port);
892 if (passwd == NULL)
893 return STATUS_EOF; /* client wouldn't send password */
894
895 if (shadow_pass)
896 result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
897 md5Salt, 4, logdetail);
898 else
899 result = STATUS_ERROR;
900
901 pfree(passwd);
902
903 return result;
904}
void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:669
static char * recv_password_packet(Port *port)
Definition: auth.c:699
int md5_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char *md5_salt, int md5_salt_len, const char **logdetail)
Definition: crypt.c:202
void pfree(void *pointer)
Definition: mcxt.c:2150
bool pg_strong_random(void *buf, size_t len)
#define AUTH_REQ_MD5
Definition: protocol.h:79

References AUTH_REQ_MD5, ereport, errmsg(), LOG, md5_crypt_verify(), pfree(), pg_strong_random(), port, recv_password_packet(), sendAuthRequest(), STATUS_EOF, and STATUS_ERROR.

Referenced by CheckPWChallengeAuth().

◆ CheckPasswordAuth()

static int CheckPasswordAuth ( Port port,
const char **  logdetail 
)
static

Definition at line 780 of file auth.c.

781{
782 char *passwd;
783 int result;
784 char *shadow_pass;
785
787
788 passwd = recv_password_packet(port);
789 if (passwd == NULL)
790 return STATUS_EOF; /* client wouldn't send password */
791
792 shadow_pass = get_role_password(port->user_name, logdetail);
793 if (shadow_pass)
794 {
795 result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
796 logdetail);
797 }
798 else
799 result = STATUS_ERROR;
800
801 if (shadow_pass)
802 pfree(shadow_pass);
803 pfree(passwd);
804
805 if (result == STATUS_OK)
806 set_authn_id(port, port->user_name);
807
808 return result;
809}
#define STATUS_OK
Definition: c.h:1140
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
Definition: crypt.c:256
char * get_role_password(const char *role, const char **logdetail)
Definition: crypt.c:38
#define AUTH_REQ_PASSWORD
Definition: protocol.h:77

References AUTH_REQ_PASSWORD, get_role_password(), pfree(), plain_crypt_verify(), port, recv_password_packet(), sendAuthRequest(), set_authn_id(), STATUS_EOF, STATUS_ERROR, and STATUS_OK.

Referenced by ClientAuthentication().

◆ CheckPWChallengeAuth()

static int CheckPWChallengeAuth ( Port port,
const char **  logdetail 
)
static

Definition at line 815 of file auth.c.

816{
817 int auth_result;
818 char *shadow_pass;
819 PasswordType pwtype;
820
821 Assert(port->hba->auth_method == uaSCRAM ||
822 port->hba->auth_method == uaMD5);
823
824 /* First look up the user's password. */
825 shadow_pass = get_role_password(port->user_name, logdetail);
826
827 /*
828 * If the user does not exist, or has no password or it's expired, we
829 * still go through the motions of authentication, to avoid revealing to
830 * the client that the user didn't exist. If 'md5' is allowed, we choose
831 * whether to use 'md5' or 'scram-sha-256' authentication based on current
832 * password_encryption setting. The idea is that most genuine users
833 * probably have a password of that type, and if we pretend that this user
834 * had a password of that type, too, it "blends in" best.
835 */
836 if (!shadow_pass)
837 pwtype = Password_encryption;
838 else
839 pwtype = get_password_type(shadow_pass);
840
841 /*
842 * If 'md5' authentication is allowed, decide whether to perform 'md5' or
843 * 'scram-sha-256' authentication based on the type of password the user
844 * has. If it's an MD5 hash, we must do MD5 authentication, and if it's a
845 * SCRAM secret, we must do SCRAM authentication.
846 *
847 * If MD5 authentication is not allowed, always use SCRAM. If the user
848 * had an MD5 password, CheckSASLAuth() with the SCRAM mechanism will
849 * fail.
850 */
851 if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
852 auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
853 else
854 auth_result = CheckSASLAuth(&pg_be_scram_mech, port, shadow_pass,
855 logdetail);
856
857 if (shadow_pass)
858 pfree(shadow_pass);
859 else
860 {
861 /*
862 * If get_role_password() returned error, authentication better not
863 * have succeeded.
864 */
865 Assert(auth_result != STATUS_OK);
866 }
867
868 if (auth_result == STATUS_OK)
869 set_authn_id(port, port->user_name);
870
871 return auth_result;
872}
int CheckSASLAuth(const pg_be_sasl_mech *mech, Port *port, char *shadow_pass, const char **logdetail)
Definition: auth-sasl.c:44
const pg_be_sasl_mech pg_be_scram_mech
Definition: auth-scram.c:114
static int CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
Definition: auth.c:875
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:90
PasswordType
Definition: crypt.h:41
@ PASSWORD_TYPE_MD5
Definition: crypt.h:43
int Password_encryption
Definition: user.c:86

References Assert(), CheckMD5Auth(), CheckSASLAuth(), get_password_type(), get_role_password(), Password_encryption, PASSWORD_TYPE_MD5, pfree(), pg_be_scram_mech, port, set_authn_id(), STATUS_OK, uaMD5, and uaSCRAM.

Referenced by ClientAuthentication().

◆ CheckRADIUSAuth()

static int CheckRADIUSAuth ( Port port)
static

Definition at line 2837 of file auth.c.

2838{
2839 char *passwd;
2840 ListCell *server,
2841 *secrets,
2842 *radiusports,
2843 *identifiers;
2844
2845 /* Make sure struct alignment is correct */
2846 Assert(offsetof(radius_packet, vector) == 4);
2847
2848 /* Verify parameters */
2849 if (port->hba->radiusservers == NIL)
2850 {
2851 ereport(LOG,
2852 (errmsg("RADIUS server not specified")));
2853 return STATUS_ERROR;
2854 }
2855
2856 if (port->hba->radiussecrets == NIL)
2857 {
2858 ereport(LOG,
2859 (errmsg("RADIUS secret not specified")));
2860 return STATUS_ERROR;
2861 }
2862
2863 /* Send regular password request to client, and get the response */
2865
2866 passwd = recv_password_packet(port);
2867 if (passwd == NULL)
2868 return STATUS_EOF; /* client wouldn't send password */
2869
2870 if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
2871 {
2872 ereport(LOG,
2873 (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
2874 pfree(passwd);
2875 return STATUS_ERROR;
2876 }
2877
2878 /*
2879 * Loop over and try each server in order.
2880 */
2881 secrets = list_head(port->hba->radiussecrets);
2882 radiusports = list_head(port->hba->radiusports);
2883 identifiers = list_head(port->hba->radiusidentifiers);
2884 foreach(server, port->hba->radiusservers)
2885 {
2886 int ret = PerformRadiusTransaction(lfirst(server),
2887 lfirst(secrets),
2888 radiusports ? lfirst(radiusports) : NULL,
2889 identifiers ? lfirst(identifiers) : NULL,
2890 port->user_name,
2891 passwd);
2892
2893 /*------
2894 * STATUS_OK = Login OK
2895 * STATUS_ERROR = Login not OK, but try next server
2896 * STATUS_EOF = Login not OK, and don't try next server
2897 *------
2898 */
2899 if (ret == STATUS_OK)
2900 {
2901 set_authn_id(port, port->user_name);
2902
2903 pfree(passwd);
2904 return STATUS_OK;
2905 }
2906 else if (ret == STATUS_EOF)
2907 {
2908 pfree(passwd);
2909 return STATUS_ERROR;
2910 }
2911
2912 /*
2913 * secret, port and identifiers either have length 0 (use default),
2914 * length 1 (use the same everywhere) or the same length as servers.
2915 * So if the length is >1, we advance one step. In other cases, we
2916 * don't and will then reuse the correct value.
2917 */
2918 if (list_length(port->hba->radiussecrets) > 1)
2919 secrets = lnext(port->hba->radiussecrets, secrets);
2920 if (list_length(port->hba->radiusports) > 1)
2921 radiusports = lnext(port->hba->radiusports, radiusports);
2922 if (list_length(port->hba->radiusidentifiers) > 1)
2923 identifiers = lnext(port->hba->radiusidentifiers, identifiers);
2924 }
2925
2926 /* No servers left to try, so give up */
2927 pfree(passwd);
2928 return STATUS_ERROR;
2929}
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2771
static int PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd)
Definition: auth.c:2932
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343

References Assert(), AUTH_REQ_PASSWORD, ereport, errmsg(), lfirst, list_head(), list_length(), lnext(), LOG, NIL, PerformRadiusTransaction(), pfree(), port, RADIUS_MAX_PASSWORD_LENGTH, recv_password_packet(), sendAuthRequest(), set_authn_id(), STATUS_EOF, STATUS_ERROR, and STATUS_OK.

Referenced by ClientAuthentication().

◆ ClientAuthentication()

void ClientAuthentication ( Port port)

Definition at line 371 of file auth.c.

372{
373 int status = STATUS_ERROR;
374 const char *logdetail = NULL;
375
376 /*
377 * Get the authentication method to use for this frontend/database
378 * combination. Note: we do not parse the file at this point; this has
379 * already been done elsewhere. hba.c dropped an error message into the
380 * server logfile if parsing the hba config file failed.
381 */
383
385
386 /*
387 * This is the first point where we have access to the hba record for the
388 * current connection, so perform any verifications based on the hba
389 * options field that should be done *before* the authentication here.
390 */
391 if (port->hba->clientcert != clientCertOff)
392 {
393 /* If we haven't loaded a root certificate store, fail */
396 (errcode(ERRCODE_CONFIG_FILE_ERROR),
397 errmsg("client certificates can only be checked if a root certificate store is available")));
398
399 /*
400 * If we loaded a root certificate store, and if a certificate is
401 * present on the client, then it has been verified against our root
402 * certificate store, and the connection would have been aborted
403 * already if it didn't verify ok.
404 */
405 if (!port->peer_cert_valid)
407 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
408 errmsg("connection requires a valid client certificate")));
409 }
410
411 /*
412 * Now proceed to do the actual authentication check
413 */
414 switch (port->hba->auth_method)
415 {
416 case uaReject:
417
418 /*
419 * An explicit "reject" entry in pg_hba.conf. This report exposes
420 * the fact that there's an explicit reject entry, which is
421 * perhaps not so desirable from a security standpoint; but the
422 * message for an implicit reject could confuse the DBA a lot when
423 * the true situation is a match to an explicit reject. And we
424 * don't want to change the message for an implicit reject. As
425 * noted below, the additional information shown here doesn't
426 * expose anything not known to an attacker.
427 */
428 {
429 char hostinfo[NI_MAXHOST];
430 const char *encryption_state;
431
432 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
433 hostinfo, sizeof(hostinfo),
434 NULL, 0,
435 NI_NUMERICHOST);
436
437 encryption_state =
438#ifdef ENABLE_GSS
439 (port->gss && port->gss->enc) ? _("GSS encryption") :
440#endif
441#ifdef USE_SSL
442 port->ssl_in_use ? _("SSL encryption") :
443#endif
444 _("no encryption");
445
448 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
449 /* translator: last %s describes encryption state */
450 errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
451 hostinfo, port->user_name,
452 encryption_state)));
453 else
455 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
456 /* translator: last %s describes encryption state */
457 errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
458 hostinfo, port->user_name,
459 port->database_name,
460 encryption_state)));
461 break;
462 }
463
464 case uaImplicitReject:
465
466 /*
467 * No matching entry, so tell the user we fell through.
468 *
469 * NOTE: the extra info reported here is not a security breach,
470 * because all that info is known at the frontend and must be
471 * assumed known to bad guys. We're merely helping out the less
472 * clueful good guys.
473 */
474 {
475 char hostinfo[NI_MAXHOST];
476 const char *encryption_state;
477
478 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
479 hostinfo, sizeof(hostinfo),
480 NULL, 0,
481 NI_NUMERICHOST);
482
483 encryption_state =
484#ifdef ENABLE_GSS
485 (port->gss && port->gss->enc) ? _("GSS encryption") :
486#endif
487#ifdef USE_SSL
488 port->ssl_in_use ? _("SSL encryption") :
489#endif
490 _("no encryption");
491
492#define HOSTNAME_LOOKUP_DETAIL(port) \
493 (port->remote_hostname ? \
494 (port->remote_hostname_resolv == +1 ? \
495 errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
496 port->remote_hostname) : \
497 port->remote_hostname_resolv == 0 ? \
498 errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
499 port->remote_hostname) : \
500 port->remote_hostname_resolv == -1 ? \
501 errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
502 port->remote_hostname) : \
503 port->remote_hostname_resolv == -2 ? \
504 errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
505 port->remote_hostname, \
506 gai_strerror(port->remote_hostname_errcode)) : \
507 0) \
508 : (port->remote_hostname_resolv == -2 ? \
509 errdetail_log("Could not resolve client IP address to a host name: %s.", \
510 gai_strerror(port->remote_hostname_errcode)) : \
511 0))
512
515 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
516 /* translator: last %s describes encryption state */
517 errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
518 hostinfo, port->user_name,
519 encryption_state),
521 else
523 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
524 /* translator: last %s describes encryption state */
525 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
526 hostinfo, port->user_name,
527 port->database_name,
528 encryption_state),
530 break;
531 }
532
533 case uaGSS:
534#ifdef ENABLE_GSS
535 /* We might or might not have the gss workspace already */
536 if (port->gss == NULL)
537 port->gss = (pg_gssinfo *)
539 sizeof(pg_gssinfo));
540 port->gss->auth = true;
541
542 /*
543 * If GSS state was set up while enabling encryption, we can just
544 * check the client's principal. Otherwise, ask for it.
545 */
546 if (port->gss->enc)
547 status = pg_GSS_checkauth(port);
548 else
549 {
551 status = pg_GSS_recvauth(port);
552 }
553#else
554 Assert(false);
555#endif
556 break;
557
558 case uaSSPI:
559#ifdef ENABLE_SSPI
560 if (port->gss == NULL)
561 port->gss = (pg_gssinfo *)
563 sizeof(pg_gssinfo));
565 status = pg_SSPI_recvauth(port);
566#else
567 Assert(false);
568#endif
569 break;
570
571 case uaPeer:
572 status = auth_peer(port);
573 break;
574
575 case uaIdent:
576 status = ident_inet(port);
577 break;
578
579 case uaMD5:
580 case uaSCRAM:
581 status = CheckPWChallengeAuth(port, &logdetail);
582 break;
583
584 case uaPassword:
585 status = CheckPasswordAuth(port, &logdetail);
586 break;
587
588 case uaPAM:
589#ifdef USE_PAM
590 status = CheckPAMAuth(port, port->user_name, "");
591#else
592 Assert(false);
593#endif /* USE_PAM */
594 break;
595
596 case uaBSD:
597#ifdef USE_BSD_AUTH
598 status = CheckBSDAuth(port, port->user_name);
599#else
600 Assert(false);
601#endif /* USE_BSD_AUTH */
602 break;
603
604 case uaLDAP:
605#ifdef USE_LDAP
606 status = CheckLDAPAuth(port);
607#else
608 Assert(false);
609#endif
610 break;
611 case uaRADIUS:
612 status = CheckRADIUSAuth(port);
613 break;
614 case uaCert:
615 /* uaCert will be treated as if clientcert=verify-full (uaTrust) */
616 case uaTrust:
617 status = STATUS_OK;
618 break;
619 case uaOAuth:
620 status = CheckSASLAuth(&pg_be_oauth_mech, port, NULL, NULL);
621 break;
622 }
623
624 if ((status == STATUS_OK && port->hba->clientcert == clientCertFull)
625 || port->hba->auth_method == uaCert)
626 {
627 /*
628 * Make sure we only check the certificate if we use the cert method
629 * or verify-full option.
630 */
631#ifdef USE_SSL
632 status = CheckCertAuth(port);
633#else
634 Assert(false);
635#endif
636 }
637
639 status == STATUS_OK &&
641 {
642 /*
643 * Normally, if log_connections is set, the call to set_authn_id()
644 * will log the connection. However, if that function is never
645 * called, perhaps because the trust method is in use, then we handle
646 * the logging here instead.
647 */
648 ereport(LOG,
649 errmsg("connection authenticated: user=\"%s\" method=%s "
650 "(%s:%d)",
651 port->user_name, hba_authname(port->hba->auth_method),
652 port->hba->sourcefile, port->hba->linenumber));
653 }
654
656 (*ClientAuthentication_hook) (port, status);
657
658 if (status == STATUS_OK)
660 else
661 auth_failed(port, status, logdetail);
662}
const pg_be_sasl_mech pg_be_oauth_mech
Definition: auth-oauth.c:48
static int CheckPWChallengeAuth(Port *port, const char **logdetail)
Definition: auth.c:815
static int ident_inet(hbaPort *port)
Definition: auth.c:1663
static int CheckRADIUSAuth(Port *port)
Definition: auth.c:2837
static void auth_failed(Port *port, int status, const char *logdetail)
Definition: auth.c:231
ClientAuthentication_hook_type ClientAuthentication_hook
Definition: auth.c:215
static int auth_peer(hbaPort *port)
Definition: auth.c:1848
#define HOSTNAME_LOOKUP_DETAIL(port)
static int CheckPasswordAuth(Port *port, const char **logdetail)
Definition: auth.c:780
uint32 log_connections
@ LOG_CONNECTION_AUTHENTICATION
bool secure_loaded_verify_locations(void)
Definition: be-secure.c:99
void hba_getauthmethod(hbaPort *port)
Definition: hba.c:3110
const char * hba_authname(UserAuth auth_method)
Definition: hba.c:3123
@ clientCertOff
Definition: hba.h:70
@ clientCertFull
Definition: hba.h:72
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:114
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1294
MemoryContext TopMemoryContext
Definition: mcxt.c:165
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
#define AUTH_REQ_SSPI
Definition: protocol.h:83
#define AUTH_REQ_GSS
Definition: protocol.h:81
#define AUTH_REQ_OK
Definition: protocol.h:74
bool am_walsender
Definition: walsender.c:120
bool am_db_walsender
Definition: walsender.c:123

References _, am_db_walsender, am_walsender, Assert(), auth_failed(), auth_peer(), AUTH_REQ_GSS, AUTH_REQ_OK, AUTH_REQ_SSPI, ClientConnectionInfo::authn_id, CHECK_FOR_INTERRUPTS, CheckPasswordAuth(), CheckPWChallengeAuth(), CheckRADIUSAuth(), CheckSASLAuth(), ClientAuthentication_hook, clientCertFull, clientCertOff, ereport, errcode(), errmsg(), FATAL, hba_authname(), hba_getauthmethod(), HOSTNAME_LOOKUP_DETAIL, ident_inet(), LOG, LOG_CONNECTION_AUTHENTICATION, log_connections, MemoryContextAllocZero(), MyClientConnectionInfo, pg_be_oauth_mech, pg_getnameinfo_all(), port, secure_loaded_verify_locations(), sendAuthRequest(), STATUS_ERROR, STATUS_OK, TopMemoryContext, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaOAuth, uaPAM, uaPassword, uaPeer, uaRADIUS, uaReject, uaSCRAM, uaSSPI, and uaTrust.

Referenced by PerformAuthentication().

◆ ident_inet()

static int ident_inet ( hbaPort port)
static

Definition at line 1663 of file auth.c.

1664{
1665 const SockAddr remote_addr = port->raddr;
1666 const SockAddr local_addr = port->laddr;
1667 char ident_user[IDENT_USERNAME_MAX + 1];
1668 pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1669 int rc; /* Return code from a locally called function */
1670 bool ident_return;
1671 char remote_addr_s[NI_MAXHOST];
1672 char remote_port[NI_MAXSERV];
1673 char local_addr_s[NI_MAXHOST];
1674 char local_port[NI_MAXSERV];
1675 char ident_port[NI_MAXSERV];
1676 char ident_query[80];
1677 char ident_response[80 + IDENT_USERNAME_MAX];
1678 struct addrinfo *ident_serv = NULL,
1679 *la = NULL,
1680 hints;
1681
1682 /*
1683 * Might look a little weird to first convert it to text and then back to
1684 * sockaddr, but it's protocol independent.
1685 */
1686 pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1687 remote_addr_s, sizeof(remote_addr_s),
1688 remote_port, sizeof(remote_port),
1689 NI_NUMERICHOST | NI_NUMERICSERV);
1690 pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1691 local_addr_s, sizeof(local_addr_s),
1692 local_port, sizeof(local_port),
1693 NI_NUMERICHOST | NI_NUMERICSERV);
1694
1695 snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1696 hints.ai_flags = AI_NUMERICHOST;
1697 hints.ai_family = remote_addr.addr.ss_family;
1698 hints.ai_socktype = SOCK_STREAM;
1699 hints.ai_protocol = 0;
1700 hints.ai_addrlen = 0;
1701 hints.ai_canonname = NULL;
1702 hints.ai_addr = NULL;
1703 hints.ai_next = NULL;
1704 rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1705 if (rc || !ident_serv)
1706 {
1707 /* we don't expect this to happen */
1708 ident_return = false;
1709 goto ident_inet_done;
1710 }
1711
1712 hints.ai_flags = AI_NUMERICHOST;
1713 hints.ai_family = local_addr.addr.ss_family;
1714 hints.ai_socktype = SOCK_STREAM;
1715 hints.ai_protocol = 0;
1716 hints.ai_addrlen = 0;
1717 hints.ai_canonname = NULL;
1718 hints.ai_addr = NULL;
1719 hints.ai_next = NULL;
1720 rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1721 if (rc || !la)
1722 {
1723 /* we don't expect this to happen */
1724 ident_return = false;
1725 goto ident_inet_done;
1726 }
1727
1728 sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1729 ident_serv->ai_protocol);
1730 if (sock_fd == PGINVALID_SOCKET)
1731 {
1732 ereport(LOG,
1734 errmsg("could not create socket for Ident connection: %m")));
1735 ident_return = false;
1736 goto ident_inet_done;
1737 }
1738
1739 /*
1740 * Bind to the address which the client originally contacted, otherwise
1741 * the ident server won't be able to match up the right connection. This
1742 * is necessary if the PostgreSQL server is running on an IP alias.
1743 */
1744 rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1745 if (rc != 0)
1746 {
1747 ereport(LOG,
1749 errmsg("could not bind to local address \"%s\": %m",
1750 local_addr_s)));
1751 ident_return = false;
1752 goto ident_inet_done;
1753 }
1754
1755 rc = connect(sock_fd, ident_serv->ai_addr,
1756 ident_serv->ai_addrlen);
1757 if (rc != 0)
1758 {
1759 ereport(LOG,
1761 errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1762 remote_addr_s, ident_port)));
1763 ident_return = false;
1764 goto ident_inet_done;
1765 }
1766
1767 /* The query we send to the Ident server */
1768 snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1769 remote_port, local_port);
1770
1771 /* loop in case send is interrupted */
1772 do
1773 {
1775
1776 rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1777 } while (rc < 0 && errno == EINTR);
1778
1779 if (rc < 0)
1780 {
1781 ereport(LOG,
1783 errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1784 remote_addr_s, ident_port)));
1785 ident_return = false;
1786 goto ident_inet_done;
1787 }
1788
1789 do
1790 {
1792
1793 rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1794 } while (rc < 0 && errno == EINTR);
1795
1796 if (rc < 0)
1797 {
1798 ereport(LOG,
1800 errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1801 remote_addr_s, ident_port)));
1802 ident_return = false;
1803 goto ident_inet_done;
1804 }
1805
1806 ident_response[rc] = '\0';
1807 ident_return = interpret_ident_response(ident_response, ident_user);
1808 if (!ident_return)
1809 ereport(LOG,
1810 (errmsg("invalidly formatted response from Ident server: \"%s\"",
1811 ident_response)));
1812
1813ident_inet_done:
1814 if (sock_fd != PGINVALID_SOCKET)
1815 closesocket(sock_fd);
1816 if (ident_serv)
1817 pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1818 if (la)
1819 pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1820
1821 if (ident_return)
1822 {
1823 /*
1824 * Success! Store the identity, then check the usermap. Note that
1825 * setting the authenticated identity is done before checking the
1826 * usermap, because at this point authentication has succeeded.
1827 */
1828 set_authn_id(port, ident_user);
1829 return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1830 }
1831 return STATUS_ERROR;
1832}
#define IDENT_USERNAME_MAX
Definition: auth.c:68
#define IDENT_PORT
Definition: auth.c:71
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1582
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:82
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:53
int pgsocket
Definition: port.h:29
#define snprintf
Definition: port.h:239
#define PGINVALID_SOCKET
Definition: port.h:31
#define closesocket
Definition: port.h:377
struct sockaddr_storage addr
Definition: pqcomm.h:32
socklen_t salen
Definition: pqcomm.h:33
#define bind(s, addr, addrlen)
Definition: win32_port.h:499
#define EINTR
Definition: win32_port.h:364
#define recv(s, buf, len, flags)
Definition: win32_port.h:504
#define send(s, buf, len, flags)
Definition: win32_port.h:505
#define socket(af, type, protocol)
Definition: win32_port.h:498
#define connect(s, name, namelen)
Definition: win32_port.h:502

References SockAddr::addr, bind, CHECK_FOR_INTERRUPTS, check_usermap(), closesocket, connect, EINTR, ereport, errcode_for_socket_access(), errmsg(), IDENT_PORT, IDENT_USERNAME_MAX, interpret_ident_response(), LOG, pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_getnameinfo_all(), PGINVALID_SOCKET, port, recv, SockAddr::salen, send, set_authn_id(), snprintf, socket, and STATUS_ERROR.

Referenced by ClientAuthentication().

◆ interpret_ident_response()

static bool interpret_ident_response ( const char *  ident_response,
char *  ident_user 
)
static

Definition at line 1582 of file auth.c.

1584{
1585 const char *cursor = ident_response; /* Cursor into *ident_response */
1586
1587 /*
1588 * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1589 */
1590 if (strlen(ident_response) < 2)
1591 return false;
1592 else if (ident_response[strlen(ident_response) - 2] != '\r')
1593 return false;
1594 else
1595 {
1596 while (*cursor != ':' && *cursor != '\r')
1597 cursor++; /* skip port field */
1598
1599 if (*cursor != ':')
1600 return false;
1601 else
1602 {
1603 /* We're positioned to colon before response type field */
1604 char response_type[80];
1605 int i; /* Index into *response_type */
1606
1607 cursor++; /* Go over colon */
1608 while (pg_isblank(*cursor))
1609 cursor++; /* skip blanks */
1610 i = 0;
1611 while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1612 i < (int) (sizeof(response_type) - 1))
1613 response_type[i++] = *cursor++;
1614 response_type[i] = '\0';
1615 while (pg_isblank(*cursor))
1616 cursor++; /* skip blanks */
1617 if (strcmp(response_type, "USERID") != 0)
1618 return false;
1619 else
1620 {
1621 /*
1622 * It's a USERID response. Good. "cursor" should be pointing
1623 * to the colon that precedes the operating system type.
1624 */
1625 if (*cursor != ':')
1626 return false;
1627 else
1628 {
1629 cursor++; /* Go over colon */
1630 /* Skip over operating system field. */
1631 while (*cursor != ':' && *cursor != '\r')
1632 cursor++;
1633 if (*cursor != ':')
1634 return false;
1635 else
1636 {
1637 cursor++; /* Go over colon */
1638 while (pg_isblank(*cursor))
1639 cursor++; /* skip blanks */
1640 /* Rest of line is user name. Copy it over. */
1641 i = 0;
1642 while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1643 ident_user[i++] = *cursor++;
1644 ident_user[i] = '\0';
1645 return true;
1646 }
1647 }
1648 }
1649 }
1650 }
1651}
bool pg_isblank(const char c)
Definition: hba.c:146
int i
Definition: isn.c:77
Definition: type.h:138

References i, IDENT_USERNAME_MAX, and pg_isblank().

Referenced by ident_inet().

◆ PerformRadiusTransaction()

static int PerformRadiusTransaction ( const char *  server,
const char *  secret,
const char *  portstr,
const char *  identifier,
const char *  user_name,
const char *  passwd 
)
static

Definition at line 2932 of file auth.c.

2933{
2934 radius_packet radius_send_pack;
2935 radius_packet radius_recv_pack;
2936 radius_packet *packet = &radius_send_pack;
2937 radius_packet *receivepacket = &radius_recv_pack;
2938 void *radius_buffer = &radius_send_pack;
2939 void *receive_buffer = &radius_recv_pack;
2941 uint8 *cryptvector;
2942 int encryptedpasswordlen;
2943 uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
2944 uint8 *md5trailer;
2945 int packetlength;
2946 pgsocket sock;
2947
2948 struct sockaddr_in6 localaddr;
2949 struct sockaddr_in6 remoteaddr;
2950 struct addrinfo hint;
2951 struct addrinfo *serveraddrs;
2952 int port;
2953 socklen_t addrsize;
2954 fd_set fdset;
2955 struct timeval endtime;
2956 int i,
2957 j,
2958 r;
2959
2960 /* Assign default values */
2961 if (portstr == NULL)
2962 portstr = "1812";
2963 if (identifier == NULL)
2964 identifier = "postgresql";
2965
2966 MemSet(&hint, 0, sizeof(hint));
2967 hint.ai_socktype = SOCK_DGRAM;
2968 hint.ai_family = AF_UNSPEC;
2969 port = atoi(portstr);
2970
2971 r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs);
2972 if (r || !serveraddrs)
2973 {
2974 ereport(LOG,
2975 (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
2976 server, gai_strerror(r))));
2977 if (serveraddrs)
2978 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2979 return STATUS_ERROR;
2980 }
2981 /* XXX: add support for multiple returned addresses? */
2982
2983 /* Construct RADIUS packet */
2984 packet->code = RADIUS_ACCESS_REQUEST;
2985 packet->length = RADIUS_HEADER_LENGTH;
2987 {
2988 ereport(LOG,
2989 (errmsg("could not generate random encryption vector")));
2990 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2991 return STATUS_ERROR;
2992 }
2993 packet->id = packet->vector[0];
2994 radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (const unsigned char *) &service, sizeof(service));
2995 radius_add_attribute(packet, RADIUS_USER_NAME, (const unsigned char *) user_name, strlen(user_name));
2996 radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (const unsigned char *) identifier, strlen(identifier));
2997
2998 /*
2999 * RADIUS password attributes are calculated as: e[0] = p[0] XOR
3000 * MD5(secret + Request Authenticator) for the first group of 16 octets,
3001 * and then: e[i] = p[i] XOR MD5(secret + e[i-1]) for the following ones
3002 * (if necessary)
3003 */
3004 encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
3005 cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH);
3006 memcpy(cryptvector, secret, strlen(secret));
3007
3008 /* for the first iteration, we use the Request Authenticator vector */
3009 md5trailer = packet->vector;
3010 for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
3011 {
3012 const char *errstr = NULL;
3013
3014 memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
3015
3016 /*
3017 * .. and for subsequent iterations the result of the previous XOR
3018 * (calculated below)
3019 */
3020 md5trailer = encryptedpassword + i;
3021
3022 if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH,
3023 encryptedpassword + i, &errstr))
3024 {
3025 ereport(LOG,
3026 (errmsg("could not perform MD5 encryption of password: %s",
3027 errstr)));
3028 pfree(cryptvector);
3029 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3030 return STATUS_ERROR;
3031 }
3032
3033 for (j = i; j < i + RADIUS_VECTOR_LENGTH; j++)
3034 {
3035 if (j < strlen(passwd))
3036 encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
3037 else
3038 encryptedpassword[j] = '\0' ^ encryptedpassword[j];
3039 }
3040 }
3041 pfree(cryptvector);
3042
3043 radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
3044
3045 /* Length needs to be in network order on the wire */
3046 packetlength = packet->length;
3047 packet->length = pg_hton16(packet->length);
3048
3049 sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
3050 if (sock == PGINVALID_SOCKET)
3051 {
3052 ereport(LOG,
3053 (errmsg("could not create RADIUS socket: %m")));
3054 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3055 return STATUS_ERROR;
3056 }
3057
3058 memset(&localaddr, 0, sizeof(localaddr));
3059 localaddr.sin6_family = serveraddrs[0].ai_family;
3060 localaddr.sin6_addr = in6addr_any;
3061 if (localaddr.sin6_family == AF_INET6)
3062 addrsize = sizeof(struct sockaddr_in6);
3063 else
3064 addrsize = sizeof(struct sockaddr_in);
3065
3066 if (bind(sock, (struct sockaddr *) &localaddr, addrsize))
3067 {
3068 ereport(LOG,
3069 (errmsg("could not bind local RADIUS socket: %m")));
3070 closesocket(sock);
3071 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3072 return STATUS_ERROR;
3073 }
3074
3075 if (sendto(sock, radius_buffer, packetlength, 0,
3076 serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
3077 {
3078 ereport(LOG,
3079 (errmsg("could not send RADIUS packet: %m")));
3080 closesocket(sock);
3081 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3082 return STATUS_ERROR;
3083 }
3084
3085 /* Don't need the server address anymore */
3086 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3087
3088 /*
3089 * Figure out at what time we should time out. We can't just use a single
3090 * call to select() with a timeout, since somebody can be sending invalid
3091 * packets to our port thus causing us to retry in a loop and never time
3092 * out.
3093 *
3094 * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if
3095 * the latch was set would improve the responsiveness to
3096 * timeouts/cancellations.
3097 */
3098 gettimeofday(&endtime, NULL);
3099 endtime.tv_sec += RADIUS_TIMEOUT;
3100
3101 while (true)
3102 {
3103 struct timeval timeout;
3104 struct timeval now;
3105 int64 timeoutval;
3106 const char *errstr = NULL;
3107
3108 gettimeofday(&now, NULL);
3109 timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
3110 if (timeoutval <= 0)
3111 {
3112 ereport(LOG,
3113 (errmsg("timeout waiting for RADIUS response from %s",
3114 server)));
3115 closesocket(sock);
3116 return STATUS_ERROR;
3117 }
3118 timeout.tv_sec = timeoutval / 1000000;
3119 timeout.tv_usec = timeoutval % 1000000;
3120
3121 FD_ZERO(&fdset);
3122 FD_SET(sock, &fdset);
3123
3124 r = select(sock + 1, &fdset, NULL, NULL, &timeout);
3125 if (r < 0)
3126 {
3127 if (errno == EINTR)
3128 continue;
3129
3130 /* Anything else is an actual error */
3131 ereport(LOG,
3132 (errmsg("could not check status on RADIUS socket: %m")));
3133 closesocket(sock);
3134 return STATUS_ERROR;
3135 }
3136 if (r == 0)
3137 {
3138 ereport(LOG,
3139 (errmsg("timeout waiting for RADIUS response from %s",
3140 server)));
3141 closesocket(sock);
3142 return STATUS_ERROR;
3143 }
3144
3145 /*
3146 * Attempt to read the response packet, and verify the contents.
3147 *
3148 * Any packet that's not actually a RADIUS packet, or otherwise does
3149 * not validate as an explicit reject, is just ignored and we retry
3150 * for another packet (until we reach the timeout). This is to avoid
3151 * the possibility to denial-of-service the login by flooding the
3152 * server with invalid packets on the port that we're expecting the
3153 * RADIUS response on.
3154 */
3155
3156 addrsize = sizeof(remoteaddr);
3157 packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
3158 (struct sockaddr *) &remoteaddr, &addrsize);
3159 if (packetlength < 0)
3160 {
3161 ereport(LOG,
3162 (errmsg("could not read RADIUS response: %m")));
3163 closesocket(sock);
3164 return STATUS_ERROR;
3165 }
3166
3167 if (remoteaddr.sin6_port != pg_hton16(port))
3168 {
3169 ereport(LOG,
3170 (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3171 server, pg_ntoh16(remoteaddr.sin6_port))));
3172 continue;
3173 }
3174
3175 if (packetlength < RADIUS_HEADER_LENGTH)
3176 {
3177 ereport(LOG,
3178 (errmsg("RADIUS response from %s too short: %d", server, packetlength)));
3179 continue;
3180 }
3181
3182 if (packetlength != pg_ntoh16(receivepacket->length))
3183 {
3184 ereport(LOG,
3185 (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)",
3186 server, pg_ntoh16(receivepacket->length), packetlength)));
3187 continue;
3188 }
3189
3190 if (packet->id != receivepacket->id)
3191 {
3192 ereport(LOG,
3193 (errmsg("RADIUS response from %s is to a different request: %d (should be %d)",
3194 server, receivepacket->id, packet->id)));
3195 continue;
3196 }
3197
3198 /*
3199 * Verify the response authenticator, which is calculated as
3200 * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
3201 */
3202 cryptvector = palloc(packetlength + strlen(secret));
3203
3204 memcpy(cryptvector, receivepacket, 4); /* code+id+length */
3205 memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request
3206 * authenticator, from
3207 * original packet */
3208 if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
3209 * attributes at all */
3210 memcpy(cryptvector + RADIUS_HEADER_LENGTH,
3211 (char *) receive_buffer + RADIUS_HEADER_LENGTH,
3212 packetlength - RADIUS_HEADER_LENGTH);
3213 memcpy(cryptvector + packetlength, secret, strlen(secret));
3214
3215 if (!pg_md5_binary(cryptvector,
3216 packetlength + strlen(secret),
3217 encryptedpassword, &errstr))
3218 {
3219 ereport(LOG,
3220 (errmsg("could not perform MD5 encryption of received packet: %s",
3221 errstr)));
3222 pfree(cryptvector);
3223 continue;
3224 }
3225 pfree(cryptvector);
3226
3227 if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
3228 {
3229 ereport(LOG,
3230 (errmsg("RADIUS response from %s has incorrect MD5 signature",
3231 server)));
3232 continue;
3233 }
3234
3235 if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
3236 {
3237 closesocket(sock);
3238 return STATUS_OK;
3239 }
3240 else if (receivepacket->code == RADIUS_ACCESS_REJECT)
3241 {
3242 closesocket(sock);
3243 return STATUS_EOF;
3244 }
3245 else
3246 {
3247 ereport(LOG,
3248 (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"",
3249 server, receivepacket->code, user_name)));
3250 continue;
3251 }
3252 } /* while (true) */
3253}
static void radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
Definition: auth.c:2811
#define RADIUS_HEADER_LENGTH
Definition: auth.c:2770
#define RADIUS_AUTHENTICATE_ONLY
Definition: auth.c:2805
#define RADIUS_ACCESS_REQUEST
Definition: auth.c:2794
#define RADIUS_NAS_IDENTIFIER
Definition: auth.c:2802
#define RADIUS_TIMEOUT
Definition: auth.c:2808
#define RADIUS_USER_NAME
Definition: auth.c:2799
#define RADIUS_SERVICE_TYPE
Definition: auth.c:2801
#define RADIUS_PASSWORD
Definition: auth.c:2800
#define RADIUS_ACCESS_REJECT
Definition: auth.c:2796
#define RADIUS_ACCESS_ACCEPT
Definition: auth.c:2795
#define RADIUS_VECTOR_LENGTH
Definition: auth.c:2769
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2774
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1609
uint8_t uint8
Definition: c.h:500
int64_t int64
Definition: c.h:499
int32_t int32
Definition: c.h:498
#define MemSet(start, val, len)
Definition: c.h:991
int j
Definition: isn.c:78
void * palloc(Size size)
Definition: mcxt.c:1943
bool pg_md5_binary(const void *buff, size_t len, void *outbuf, const char **errstr)
Definition: md5_common.c:108
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define pg_hton16(x)
Definition: pg_bswap.h:120
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
static char portstr[16]
Definition: pg_regress.c:116
unsigned int socklen_t
Definition: port.h:40
uint8 vector[RADIUS_VECTOR_LENGTH]
Definition: auth.c:2788
uint16 length
Definition: auth.c:2787
uint8 code
Definition: auth.c:2785
uint8 id
Definition: auth.c:2786
#define select(n, r, w, e, timeout)
Definition: win32_port.h:503
int gettimeofday(struct timeval *tp, void *tzp)

References bind, closesocket, radius_packet::code, EINTR, ereport, errmsg(), gai_strerror(), gettimeofday(), i, radius_packet::id, j, radius_packet::length, LOG, MemSet, now(), palloc(), pfree(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_hton16, pg_hton32, pg_md5_binary(), pg_ntoh16, pg_strong_random(), PGINVALID_SOCKET, port, portstr, RADIUS_ACCESS_ACCEPT, RADIUS_ACCESS_REJECT, RADIUS_ACCESS_REQUEST, radius_add_attribute(), RADIUS_AUTHENTICATE_ONLY, RADIUS_BUFFER_SIZE, RADIUS_HEADER_LENGTH, RADIUS_MAX_PASSWORD_LENGTH, RADIUS_NAS_IDENTIFIER, RADIUS_PASSWORD, RADIUS_SERVICE_TYPE, RADIUS_TIMEOUT, RADIUS_USER_NAME, RADIUS_VECTOR_LENGTH, select, socket, STATUS_EOF, STATUS_ERROR, STATUS_OK, and radius_packet::vector.

Referenced by CheckRADIUSAuth().

◆ radius_add_attribute()

static void radius_add_attribute ( radius_packet packet,
uint8  type,
const unsigned char *  data,
int  len 
)
static

Definition at line 2811 of file auth.c.

2812{
2813 radius_attribute *attr;
2814
2815 if (packet->length + len > RADIUS_BUFFER_SIZE)
2816 {
2817 /*
2818 * With remotely realistic data, this can never happen. But catch it
2819 * just to make sure we don't overrun a buffer. We'll just skip adding
2820 * the broken attribute, which will in the end cause authentication to
2821 * fail.
2822 */
2823 elog(WARNING,
2824 "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
2825 type, len);
2826 return;
2827 }
2828
2829 attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2830 attr->attribute = type;
2831 attr->length = len + 2; /* total size includes type and length */
2832 memcpy(attr->data, data, len);
2833 packet->length += attr->length;
2834}
#define WARNING
Definition: elog.h:36
#define elog(elevel,...)
Definition: elog.h:225
const void size_t len
const void * data
uint8 data[FLEXIBLE_ARRAY_MEMBER]
Definition: auth.c:2780
uint8 length
Definition: auth.c:2779
uint8 attribute
Definition: auth.c:2778
const char * type

References radius_attribute::attribute, radius_attribute::data, data, elog, len, radius_attribute::length, radius_packet::length, RADIUS_BUFFER_SIZE, type, and WARNING.

Referenced by PerformRadiusTransaction().

◆ recv_password_packet()

static char * recv_password_packet ( Port port)
static

Definition at line 699 of file auth.c.

700{
702 int mtype;
703
705
706 /* Expect 'p' message type */
707 mtype = pq_getbyte();
708 if (mtype != PqMsg_PasswordMessage)
709 {
710 /*
711 * If the client just disconnects without offering a password, don't
712 * make a log entry. This is legal per protocol spec and in fact
713 * commonly done by psql, so complaining just clutters the log.
714 */
715 if (mtype != EOF)
717 (errcode(ERRCODE_PROTOCOL_VIOLATION),
718 errmsg("expected password response, got message type %d",
719 mtype)));
720 return NULL; /* EOF or bad message type */
721 }
722
724 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH)) /* receive password */
725 {
726 /* EOF - pq_getmessage already logged a suitable message */
727 pfree(buf.data);
728 return NULL;
729 }
730
731 /*
732 * Apply sanity check: password packet length should agree with length of
733 * contained string. Note it is safe to use strlen here because
734 * StringInfo is guaranteed to have an appended '\0'.
735 */
736 if (strlen(buf.data) + 1 != buf.len)
738 (errcode(ERRCODE_PROTOCOL_VIOLATION),
739 errmsg("invalid password packet size")));
740
741 /*
742 * Don't allow an empty password. Libpq treats an empty password the same
743 * as no password at all, and won't even try to authenticate. But other
744 * clients might, so allowing it would be confusing.
745 *
746 * Note that this only catches an empty password sent by the client in
747 * plaintext. There's also a check in CREATE/ALTER USER that prevents an
748 * empty string from being stored as a user's password in the first place.
749 * We rely on that for MD5 and SCRAM authentication, but we still need
750 * this check here, to prevent an empty password from being used with
751 * authentication methods that check the password against an external
752 * system, like PAM, LDAP and RADIUS.
753 */
754 if (buf.len == 1)
757 errmsg("empty password returned by client")));
758
759 /* Do not echo password to logs, for security. */
760 elog(DEBUG5, "received password packet");
761
762 /*
763 * Return the received string. Note we do not attempt to do any
764 * character-set conversion on it; since we don't yet know the client's
765 * encoding, there wouldn't be much point.
766 */
767 return buf.data;
768}
#define PG_MAX_AUTH_TOKEN_LENGTH
Definition: auth.h:33
#define ERROR
Definition: elog.h:39
#define DEBUG5
Definition: elog.h:26
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1204
int pq_getbyte(void)
Definition: pqcomm.c:964
void pq_startmsgread(void)
Definition: pqcomm.c:1142
#define PqMsg_PasswordMessage
Definition: protocol.h:31
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97

References buf, DEBUG5, elog, ereport, errcode(), ERRCODE_INVALID_PASSWORD, errmsg(), ERROR, initStringInfo(), pfree(), PG_MAX_AUTH_TOKEN_LENGTH, pq_getbyte(), pq_getmessage(), pq_startmsgread(), and PqMsg_PasswordMessage.

Referenced by CheckMD5Auth(), CheckPasswordAuth(), and CheckRADIUSAuth().

◆ sendAuthRequest()

void sendAuthRequest ( Port port,
AuthRequest  areq,
const char *  extradata,
int  extralen 
)

Definition at line 669 of file auth.c.

670{
672
674
676 pq_sendint32(&buf, (int32) areq);
677 if (extralen > 0)
678 pq_sendbytes(&buf, extradata, extralen);
679
681
682 /*
683 * Flush message so client will see it, except for AUTH_REQ_OK and
684 * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
685 * queries.
686 */
687 if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
688 pq_flush();
689
691}
#define pq_flush()
Definition: libpq.h:46
void pq_sendbytes(StringInfo buf, const void *data, int datalen)
Definition: pqformat.c:126
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:296
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:88
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
#define PqMsg_AuthenticationRequest
Definition: protocol.h:50
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:86

References AUTH_REQ_OK, AUTH_REQ_SASL_FIN, buf, CHECK_FOR_INTERRUPTS, pq_beginmessage(), pq_endmessage(), pq_flush, pq_sendbytes(), pq_sendint32(), and PqMsg_AuthenticationRequest.

Referenced by CheckMD5Auth(), CheckPasswordAuth(), CheckRADIUSAuth(), CheckSASLAuth(), and ClientAuthentication().

◆ set_authn_id()

void set_authn_id ( Port port,
const char *  id 
)

Definition at line 333 of file auth.c.

334{
335 Assert(id);
336
338 {
339 /*
340 * An existing authn_id should never be overwritten; that means two
341 * authentication providers are fighting (or one is fighting itself).
342 * Don't leak any authn details to the client, but don't let the
343 * connection continue, either.
344 */
346 (errmsg("authentication identifier set more than once"),
347 errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
349 }
350
352 MyClientConnectionInfo.auth_method = port->hba->auth_method;
353
355 {
356 ereport(LOG,
357 errmsg("connection authenticated: identity=\"%s\" method=%s "
358 "(%s:%d)",
361 port->hba->sourcefile, port->hba->linenumber));
362 }
363}
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:2312
UserAuth auth_method
Definition: libpq-be.h:105

References Assert(), ClientConnectionInfo::auth_method, ClientConnectionInfo::authn_id, ereport, errdetail_log(), errmsg(), FATAL, hba_authname(), LOG, LOG_CONNECTION_AUTHENTICATION, log_connections, MemoryContextStrdup(), MyClientConnectionInfo, port, and TopMemoryContext.

Referenced by auth_peer(), CheckPasswordAuth(), CheckPWChallengeAuth(), CheckRADIUSAuth(), ident_inet(), and validate().

Variable Documentation

◆ ClientAuthentication_hook

ClientAuthentication_hook_type ClientAuthentication_hook = NULL

Definition at line 215 of file auth.c.

Referenced by _PG_init(), ClientAuthentication(), and sepgsql_init_client_label().

◆ pg_gss_accept_delegation

bool pg_gss_accept_delegation

Definition at line 167 of file auth.c.

Referenced by secure_open_gssapi().

◆ pg_krb_caseins_users

bool pg_krb_caseins_users

Definition at line 166 of file auth.c.

◆ pg_krb_server_keyfile

char* pg_krb_server_keyfile

Definition at line 165 of file auth.c.

Referenced by secure_open_gssapi().