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/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 "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 void set_authn_id (Port *port, const char *id)
 
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 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:1251
static int port
Definition: pg_regress.c:115
const char * gai_strerror(int ecode)

◆ IDENT_PORT

#define IDENT_PORT   113

Definition at line 70 of file auth.c.

◆ IDENT_USERNAME_MAX

#define IDENT_USERNAME_MAX   512

Definition at line 67 of file auth.c.

◆ RADIUS_ACCESS_ACCEPT

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2786 of file auth.c.

◆ RADIUS_ACCESS_REJECT

#define RADIUS_ACCESS_REJECT   3

Definition at line 2787 of file auth.c.

◆ RADIUS_ACCESS_REQUEST

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2785 of file auth.c.

◆ RADIUS_AUTHENTICATE_ONLY

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2796 of file auth.c.

◆ RADIUS_BUFFER_SIZE

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2765 of file auth.c.

◆ RADIUS_HEADER_LENGTH

#define RADIUS_HEADER_LENGTH   20

Definition at line 2761 of file auth.c.

◆ RADIUS_MAX_PASSWORD_LENGTH

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2762 of file auth.c.

◆ RADIUS_NAS_IDENTIFIER

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2793 of file auth.c.

◆ RADIUS_PASSWORD

#define RADIUS_PASSWORD   2

Definition at line 2791 of file auth.c.

◆ RADIUS_SERVICE_TYPE

#define RADIUS_SERVICE_TYPE   6

Definition at line 2792 of file auth.c.

◆ RADIUS_TIMEOUT

#define RADIUS_TIMEOUT   3

Definition at line 2799 of file auth.c.

◆ RADIUS_USER_NAME

#define RADIUS_USER_NAME   1

Definition at line 2790 of file auth.c.

◆ RADIUS_VECTOR_LENGTH

#define RADIUS_VECTOR_LENGTH   16

Definition at line 2760 of file auth.c.

Function Documentation

◆ auth_failed()

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

Definition at line 230 of file auth.c.

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

Referenced by ClientAuthentication().

◆ auth_peer()

static int auth_peer ( hbaPort port)
static

Definition at line 1839 of file auth.c.

1840{
1841 uid_t uid;
1842 gid_t gid;
1843#ifndef WIN32
1844 struct passwd pwbuf;
1845 struct passwd *pw;
1846 char buf[1024];
1847 int rc;
1848 int ret;
1849#endif
1850
1851 if (getpeereid(port->sock, &uid, &gid) != 0)
1852 {
1853 /* Provide special error message if getpeereid is a stub */
1854 if (errno == ENOSYS)
1855 ereport(LOG,
1856 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1857 errmsg("peer authentication is not supported on this platform")));
1858 else
1859 ereport(LOG,
1861 errmsg("could not get peer credentials: %m")));
1862 return STATUS_ERROR;
1863 }
1864
1865#ifndef WIN32
1866 rc = getpwuid_r(uid, &pwbuf, buf, sizeof buf, &pw);
1867 if (rc != 0)
1868 {
1869 errno = rc;
1870 ereport(LOG,
1871 errmsg("could not look up local user ID %ld: %m", (long) uid));
1872 return STATUS_ERROR;
1873 }
1874 else if (!pw)
1875 {
1876 ereport(LOG,
1877 errmsg("local user with ID %ld does not exist", (long) uid));
1878 return STATUS_ERROR;
1879 }
1880
1881 /*
1882 * Make a copy of static getpw*() result area; this is our authenticated
1883 * identity. Set it before calling check_usermap, because authentication
1884 * has already succeeded and we want the log file to reflect that.
1885 */
1886 set_authn_id(port, pw->pw_name);
1887
1888 ret = check_usermap(port->hba->usermap, port->user_name,
1890
1891 return ret;
1892#else
1893 /* should have failed with ENOSYS above */
1894 Assert(false);
1895 return STATUS_ERROR;
1896#endif
1897}
static void set_authn_id(Port *port, const char *id)
Definition: auth.c:328
#define Assert(condition)
Definition: c.h:815
#define STATUS_ERROR
Definition: c.h:1127
int errcode_for_socket_access(void)
Definition: elog.c:953
#define LOG
Definition: elog.h:31
int check_usermap(const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive)
Definition: hba.c:2908
ClientConnectionInfo MyClientConnectionInfo
Definition: miscinit.c:1066
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:105
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 866 of file auth.c.

867{
868 char md5Salt[4]; /* Password salt */
869 char *passwd;
870 int result;
871
872 /* include the salt to use for computing the response */
873 if (!pg_strong_random(md5Salt, 4))
874 {
875 ereport(LOG,
876 (errmsg("could not generate random MD5 salt")));
877 return STATUS_ERROR;
878 }
879
880 sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
881
882 passwd = recv_password_packet(port);
883 if (passwd == NULL)
884 return STATUS_EOF; /* client wouldn't send password */
885
886 if (shadow_pass)
887 result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
888 md5Salt, 4, logdetail);
889 else
890 result = STATUS_ERROR;
891
892 pfree(passwd);
893
894 return result;
895}
void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:660
static char * recv_password_packet(Port *port)
Definition: auth.c:690
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:1521
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 771 of file auth.c.

772{
773 char *passwd;
774 int result;
775 char *shadow_pass;
776
778
779 passwd = recv_password_packet(port);
780 if (passwd == NULL)
781 return STATUS_EOF; /* client wouldn't send password */
782
783 shadow_pass = get_role_password(port->user_name, logdetail);
784 if (shadow_pass)
785 {
786 result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
787 logdetail);
788 }
789 else
790 result = STATUS_ERROR;
791
792 if (shadow_pass)
793 pfree(shadow_pass);
794 pfree(passwd);
795
796 if (result == STATUS_OK)
797 set_authn_id(port, port->user_name);
798
799 return result;
800}
#define STATUS_OK
Definition: c.h:1126
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 806 of file auth.c.

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

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 2828 of file auth.c.

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

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

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(), ClientAuthentication_hook, clientCertFull, clientCertOff, ereport, errcode(), errmsg(), FATAL, hba_authname(), hba_getauthmethod(), HOSTNAME_LOOKUP_DETAIL, ident_inet(), LOG, Log_connections, MemoryContextAllocZero(), MyClientConnectionInfo, pg_getnameinfo_all(), port, secure_loaded_verify_locations(), sendAuthRequest(), STATUS_ERROR, STATUS_OK, TopMemoryContext, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaPAM, uaPassword, uaPeer, uaRADIUS, uaReject, uaSCRAM, uaSSPI, and uaTrust.

Referenced by PerformAuthentication().

◆ ident_inet()

static int ident_inet ( hbaPort port)
static

Definition at line 1654 of file auth.c.

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

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

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

2803{
2804 radius_attribute *attr;
2805
2806 if (packet->length + len > RADIUS_BUFFER_SIZE)
2807 {
2808 /*
2809 * With remotely realistic data, this can never happen. But catch it
2810 * just to make sure we don't overrun a buffer. We'll just skip adding
2811 * the broken attribute, which will in the end cause authentication to
2812 * fail.
2813 */
2814 elog(WARNING,
2815 "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
2816 type, len);
2817 return;
2818 }
2819
2820 attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2821 attr->attribute = type;
2822 attr->length = len + 2; /* total size includes type and length */
2823 memcpy(attr->data, data, len);
2824 packet->length += attr->length;
2825}
#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:2771
uint8 length
Definition: auth.c:2770
uint8 attribute
Definition: auth.c:2769
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 690 of file auth.c.

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

661{
663
665
667 pq_sendint32(&buf, (int32) areq);
668 if (extralen > 0)
669 pq_sendbytes(&buf, extradata, extralen);
670
672
673 /*
674 * Flush message so client will see it, except for AUTH_REQ_OK and
675 * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
676 * queries.
677 */
678 if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
679 pq_flush();
680
682}
#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()

static void set_authn_id ( Port port,
const char *  id 
)
static

Definition at line 328 of file auth.c.

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

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

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

Variable Documentation

◆ ClientAuthentication_hook

ClientAuthentication_hook_type ClientAuthentication_hook = NULL

Definition at line 214 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 166 of file auth.c.

Referenced by secure_open_gssapi().

◆ pg_krb_caseins_users

bool pg_krb_caseins_users

Definition at line 165 of file auth.c.

◆ pg_krb_server_keyfile

char* pg_krb_server_keyfile

Definition at line 164 of file auth.c.

Referenced by secure_open_gssapi().