PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
auth.c File Reference
#include "postgres.h"
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.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 "miscadmin.h"
#include "replication/walsender.h"
#include "storage/ipc.h"
#include "utils/backend_random.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 PG_MAX_AUTH_TOKEN_LENGTH   65535
 
#define HOSTNAME_LOOKUP_DETAIL(port)
 
#define RADIUS_VECTOR_LENGTH   16
 
#define RADIUS_HEADER_LENGTH   20
 
#define RADIUS_MAX_PASSWORD_LENGTH   128
 
#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_BUFFER_SIZE   1024
 
#define RADIUS_TIMEOUT   3
 

Functions

static void sendAuthRequest (Port *port, AuthRequest areq, char *extradata, int extralen)
 
static void auth_failed (Port *port, int status, char *logdetail)
 
static char * recv_password_packet (Port *port)
 
static int CheckMD5Auth (Port *port, char **logdetail)
 
static int CheckPasswordAuth (Port *port, char **logdetail)
 
static int ident_inet (hbaPort *port)
 
static int CheckRADIUSAuth (Port *port)
 
void ClientAuthentication (Port *port)
 
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
 
ClientAuthentication_hook_type ClientAuthentication_hook = NULL
 

Macro Definition Documentation

#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))
#define gai_strerror
Definition: getaddrinfo.h:148
int errdetail_log(const char *fmt,...)
Definition: elog.c:921
static int port
Definition: pg_regress.c:87

Referenced by ClientAuthentication().

#define IDENT_PORT   113

Definition at line 70 of file auth.c.

Referenced by ident_inet().

#define IDENT_USERNAME_MAX   512

Definition at line 67 of file auth.c.

Referenced by ident_inet(), and interpret_ident_response().

#define PG_MAX_AUTH_TOKEN_LENGTH   65535

Definition at line 213 of file auth.c.

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2410 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_ACCESS_REJECT   3

Definition at line 2411 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2409 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2420 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2423 of file auth.c.

Referenced by CheckRADIUSAuth(), and radius_add_attribute().

#define RADIUS_HEADER_LENGTH   20

Definition at line 2390 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2391 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2417 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_PASSWORD   2

Definition at line 2415 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_SERVICE_TYPE   6

Definition at line 2416 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_TIMEOUT   3

Definition at line 2426 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_USER_NAME   1

Definition at line 2414 of file auth.c.

Referenced by CheckRADIUSAuth().

#define RADIUS_VECTOR_LENGTH   16

Definition at line 2389 of file auth.c.

Referenced by CheckRADIUSAuth().

Function Documentation

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

Definition at line 242 of file auth.c.

References _, HbaLine::auth_method, ereport, errcode(), ERRCODE_INVALID_PASSWORD, errdetail_log(), errmsg(), FATAL, gettext_noop, Port::hba, HbaLine::linenumber, proc_exit(), psprintf(), HbaLine::rawline, STATUS_EOF, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaPAM, uaPassword, uaRADIUS, uaReject, uaSSPI, uaTrust, and Port::user_name.

Referenced by ClientAuthentication().

243 {
244  const char *errstr;
245  char *cdetail;
246  int errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION;
247 
248  /*
249  * If we failed due to EOF from client, just quit; there's no point in
250  * trying to send a message to the client, and not much point in logging
251  * the failure in the postmaster log. (Logging the failure might be
252  * desirable, were it not for the fact that libpq closes the connection
253  * unceremoniously if challenged for a password when it hasn't got one to
254  * send. We'll get a useless log entry for every psql connection under
255  * password auth, even if it's perfectly successful, if we log STATUS_EOF
256  * events.)
257  */
258  if (status == STATUS_EOF)
259  proc_exit(0);
260 
261  switch (port->hba->auth_method)
262  {
263  case uaReject:
264  case uaImplicitReject:
265  errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
266  break;
267  case uaTrust:
268  errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
269  break;
270  case uaIdent:
271  errstr = gettext_noop("Ident authentication failed for user \"%s\"");
272  break;
273  case uaPeer:
274  errstr = gettext_noop("Peer authentication failed for user \"%s\"");
275  break;
276  case uaPassword:
277  case uaMD5:
278  errstr = gettext_noop("password authentication failed for user \"%s\"");
279  /* We use it to indicate if a .pgpass password failed. */
280  errcode_return = ERRCODE_INVALID_PASSWORD;
281  break;
282  case uaGSS:
283  errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
284  break;
285  case uaSSPI:
286  errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
287  break;
288  case uaPAM:
289  errstr = gettext_noop("PAM authentication failed for user \"%s\"");
290  break;
291  case uaBSD:
292  errstr = gettext_noop("BSD authentication failed for user \"%s\"");
293  break;
294  case uaLDAP:
295  errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
296  break;
297  case uaCert:
298  errstr = gettext_noop("certificate authentication failed for user \"%s\"");
299  break;
300  case uaRADIUS:
301  errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");
302  break;
303  default:
304  errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
305  break;
306  }
307 
308  cdetail = psprintf(_("Connection matched pg_hba.conf line %d: \"%s\""),
309  port->hba->linenumber, port->hba->rawline);
310  if (logdetail)
311  logdetail = psprintf("%s\n%s", logdetail, cdetail);
312  else
313  logdetail = cdetail;
314 
315  ereport(FATAL,
316  (errcode(errcode_return),
317  errmsg(errstr, port->user_name),
318  logdetail ? errdetail_log("%s", logdetail) : 0));
319 
320  /* doesn't return */
321 }
Definition: hba.h:30
Definition: hba.h:37
Definition: hba.h:32
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
Definition: hba.h:34
#define gettext_noop(x)
Definition: c.h:139
void proc_exit(int code)
Definition: ipc.c:99
int errcode(int sqlerrcode)
Definition: elog.c:575
Definition: hba.h:33
Definition: hba.h:31
Definition: hba.h:38
#define FATAL
Definition: elog.h:52
Definition: hba.h:27
Definition: hba.h:29
char * user_name
Definition: libpq-be.h:139
int errdetail_log(const char *fmt,...)
Definition: elog.c:921
int linenumber
Definition: hba.h:62
#define ereport(elevel, rest)
Definition: elog.h:122
HbaLine * hba
Definition: libpq-be.h:146
Definition: hba.h:36
char * rawline
Definition: hba.h:63
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define STATUS_EOF
Definition: c.h:972
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:98
Definition: hba.h:35
#define _(x)
Definition: elog.c:84
Definition: hba.h:39
UserAuth auth_method
Definition: hba.h:71
static int CheckMD5Auth ( Port port,
char **  logdetail 
)
static

Definition at line 697 of file auth.c.

References AUTH_REQ_MD5, Db_user_namespace, ereport, errcode(), errmsg(), FATAL, get_role_password(), LOG, md5_crypt_verify(), NULL, pfree(), pg_backend_random(), recv_password_packet(), sendAuthRequest(), STATUS_EOF, STATUS_ERROR, STATUS_OK, and Port::user_name.

Referenced by ClientAuthentication().

698 {
699  char md5Salt[4]; /* Password salt */
700  char *passwd;
701  char *shadow_pass;
702  int result;
703 
704  if (Db_user_namespace)
705  ereport(FATAL,
706  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
707  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
708 
709  /* include the salt to use for computing the response */
710  if (!pg_backend_random(md5Salt, 4))
711  {
712  ereport(LOG,
713  (errmsg("could not generate random MD5 salt")));
714  return STATUS_ERROR;
715  }
716 
717  sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
718 
719  passwd = recv_password_packet(port);
720  if (passwd == NULL)
721  return STATUS_EOF; /* client wouldn't send password */
722 
723  result = get_role_password(port->user_name, &shadow_pass, logdetail);
724  if (result == STATUS_OK)
725  result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
726  md5Salt, 4, logdetail);
727 
728  if (shadow_pass)
729  pfree(shadow_pass);
730  pfree(passwd);
731 
732  return result;
733 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define STATUS_ERROR
Definition: c.h:971
#define LOG
Definition: elog.h:26
#define AUTH_REQ_MD5
Definition: pqcomm.h:170
void pfree(void *pointer)
Definition: mcxt.c:992
#define FATAL
Definition: elog.h:52
bool pg_backend_random(char *dst, int len)
bool Db_user_namespace
Definition: postmaster.c:240
char * user_name
Definition: libpq-be.h:139
static void sendAuthRequest(Port *port, AuthRequest areq, char *extradata, int extralen)
Definition: auth.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
#define STATUS_OK
Definition: c.h:970
static char * recv_password_packet(Port *port)
Definition: auth.c:627
#define NULL
Definition: c.h:226
int md5_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char *md5_salt, int md5_salt_len, char **logdetail)
Definition: crypt.c:178
int get_role_password(const char *role, char **shadow_pass, char **logdetail)
Definition: crypt.c:43
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define STATUS_EOF
Definition: c.h:972
static int CheckPasswordAuth ( Port port,
char **  logdetail 
)
static

Definition at line 741 of file auth.c.

References AUTH_REQ_PASSWORD, get_role_password(), NULL, pfree(), plain_crypt_verify(), recv_password_packet(), sendAuthRequest(), STATUS_EOF, STATUS_OK, and Port::user_name.

Referenced by ClientAuthentication().

742 {
743  char *passwd;
744  int result;
745  char *shadow_pass;
746 
748 
749  passwd = recv_password_packet(port);
750  if (passwd == NULL)
751  return STATUS_EOF; /* client wouldn't send password */
752 
753  result = get_role_password(port->user_name, &shadow_pass, logdetail);
754  if (result == STATUS_OK)
755  result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
756  logdetail);
757 
758  if (shadow_pass)
759  pfree(shadow_pass);
760  pfree(passwd);
761 
762  return result;
763 }
void pfree(void *pointer)
Definition: mcxt.c:992
char * user_name
Definition: libpq-be.h:139
static void sendAuthRequest(Port *port, AuthRequest areq, char *extradata, int extralen)
Definition: auth.c:598
#define STATUS_OK
Definition: c.h:970
static char * recv_password_packet(Port *port)
Definition: auth.c:627
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:168
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, char **logdetail)
Definition: crypt.c:255
#define NULL
Definition: c.h:226
int get_role_password(const char *role, char **shadow_pass, char **logdetail)
Definition: crypt.c:43
#define STATUS_EOF
Definition: c.h:972
static int CheckRADIUSAuth ( Port port)
static

Definition at line 2455 of file auth.c.

References addrinfo::ai_family, addrinfo::ai_socktype, Assert, AUTH_REQ_PASSWORD, bind, closesocket, radius_packet::code, EINTR, ereport, errmsg(), gai_strerror, gettimeofday(), Port::hba, i, radius_packet::id, in6addr_any, radius_packet::length, LOG, MemSet, NULL, offsetof, palloc(), pfree(), pg_backend_random(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_md5_binary(), PGINVALID_SOCKET, 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, HbaLine::radiusidentifier, HbaLine::radiusport, HbaLine::radiussecret, HbaLine::radiusserver, recv_password_packet(), select, sendAuthRequest(), snprintf(), socket, STATUS_EOF, STATUS_ERROR, STATUS_OK, Port::user_name, and radius_packet::vector.

Referenced by ClientAuthentication().

2456 {
2457  char *passwd;
2458  char *identifier = "postgresql";
2459  char radius_buffer[RADIUS_BUFFER_SIZE];
2460  char receive_buffer[RADIUS_BUFFER_SIZE];
2461  radius_packet *packet = (radius_packet *) radius_buffer;
2462  radius_packet *receivepacket = (radius_packet *) receive_buffer;
2463  int32 service = htonl(RADIUS_AUTHENTICATE_ONLY);
2464  uint8 *cryptvector;
2465  int encryptedpasswordlen;
2466  uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
2467  uint8 *md5trailer;
2468  int packetlength;
2469  pgsocket sock;
2470 
2471 #ifdef HAVE_IPV6
2472  struct sockaddr_in6 localaddr;
2473  struct sockaddr_in6 remoteaddr;
2474 #else
2475  struct sockaddr_in localaddr;
2476  struct sockaddr_in remoteaddr;
2477 #endif
2478  struct addrinfo hint;
2479  struct addrinfo *serveraddrs;
2480  char portstr[128];
2481  ACCEPT_TYPE_ARG3 addrsize;
2482  fd_set fdset;
2483  struct timeval endtime;
2484  int i,
2485  j,
2486  r;
2487 
2488  /* Make sure struct alignment is correct */
2489  Assert(offsetof(radius_packet, vector) == 4);
2490 
2491  /* Verify parameters */
2492  if (!port->hba->radiusserver || port->hba->radiusserver[0] == '\0')
2493  {
2494  ereport(LOG,
2495  (errmsg("RADIUS server not specified")));
2496  return STATUS_ERROR;
2497  }
2498 
2499  if (!port->hba->radiussecret || port->hba->radiussecret[0] == '\0')
2500  {
2501  ereport(LOG,
2502  (errmsg("RADIUS secret not specified")));
2503  return STATUS_ERROR;
2504  }
2505 
2506  if (port->hba->radiusport == 0)
2507  port->hba->radiusport = 1812;
2508 
2509  MemSet(&hint, 0, sizeof(hint));
2510  hint.ai_socktype = SOCK_DGRAM;
2511  hint.ai_family = AF_UNSPEC;
2512  snprintf(portstr, sizeof(portstr), "%d", port->hba->radiusport);
2513 
2514  r = pg_getaddrinfo_all(port->hba->radiusserver, portstr, &hint, &serveraddrs);
2515  if (r || !serveraddrs)
2516  {
2517  ereport(LOG,
2518  (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
2519  port->hba->radiusserver, gai_strerror(r))));
2520  if (serveraddrs)
2521  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2522  return STATUS_ERROR;
2523  }
2524  /* XXX: add support for multiple returned addresses? */
2525 
2526  if (port->hba->radiusidentifier && port->hba->radiusidentifier[0])
2527  identifier = port->hba->radiusidentifier;
2528 
2529  /* Send regular password request to client, and get the response */
2531 
2532  passwd = recv_password_packet(port);
2533  if (passwd == NULL)
2534  return STATUS_EOF; /* client wouldn't send password */
2535 
2536  if (strlen(passwd) == 0)
2537  {
2538  ereport(LOG,
2539  (errmsg("empty password returned by client")));
2540  return STATUS_ERROR;
2541  }
2542 
2543  if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
2544  {
2545  ereport(LOG,
2546  (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
2547  return STATUS_ERROR;
2548  }
2549 
2550 
2551  /* Construct RADIUS packet */
2552  packet->code = RADIUS_ACCESS_REQUEST;
2553  packet->length = RADIUS_HEADER_LENGTH;
2554  if (!pg_backend_random((char *) packet->vector, RADIUS_VECTOR_LENGTH))
2555  {
2556  ereport(LOG,
2557  (errmsg("could not generate random encryption vector")));
2558  return STATUS_ERROR;
2559  }
2560  packet->id = packet->vector[0];
2561  radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (unsigned char *) &service, sizeof(service));
2562  radius_add_attribute(packet, RADIUS_USER_NAME, (unsigned char *) port->user_name, strlen(port->user_name));
2563  radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *) identifier, strlen(identifier));
2564 
2565  /*
2566  * RADIUS password attributes are calculated as: e[0] = p[0] XOR
2567  * MD5(secret + Request Authenticator) for the first group of 16 octets,
2568  * and then: e[i] = p[i] XOR MD5(secret + e[i-1]) for the following ones
2569  * (if necessary)
2570  */
2571  encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
2572  cryptvector = palloc(strlen(port->hba->radiussecret) + RADIUS_VECTOR_LENGTH);
2573  memcpy(cryptvector, port->hba->radiussecret, strlen(port->hba->radiussecret));
2574 
2575  /* for the first iteration, we use the Request Authenticator vector */
2576  md5trailer = packet->vector;
2577  for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
2578  {
2579  memcpy(cryptvector + strlen(port->hba->radiussecret), md5trailer, RADIUS_VECTOR_LENGTH);
2580 
2581  /*
2582  * .. and for subsequent iterations the result of the previous XOR
2583  * (calculated below)
2584  */
2585  md5trailer = encryptedpassword + i;
2586 
2587  if (!pg_md5_binary(cryptvector, strlen(port->hba->radiussecret) + RADIUS_VECTOR_LENGTH, encryptedpassword + i))
2588  {
2589  ereport(LOG,
2590  (errmsg("could not perform MD5 encryption of password")));
2591  pfree(cryptvector);
2592  return STATUS_ERROR;
2593  }
2594 
2595  for (j = i; j < i + RADIUS_VECTOR_LENGTH; j++)
2596  {
2597  if (j < strlen(passwd))
2598  encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
2599  else
2600  encryptedpassword[j] = '\0' ^ encryptedpassword[j];
2601  }
2602  }
2603  pfree(cryptvector);
2604 
2605  radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
2606 
2607  /* Length need to be in network order on the wire */
2608  packetlength = packet->length;
2609  packet->length = htons(packet->length);
2610 
2611  sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
2612  if (sock == PGINVALID_SOCKET)
2613  {
2614  ereport(LOG,
2615  (errmsg("could not create RADIUS socket: %m")));
2616  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2617  return STATUS_ERROR;
2618  }
2619 
2620  memset(&localaddr, 0, sizeof(localaddr));
2621 #ifdef HAVE_IPV6
2622  localaddr.sin6_family = serveraddrs[0].ai_family;
2623  localaddr.sin6_addr = in6addr_any;
2624  if (localaddr.sin6_family == AF_INET6)
2625  addrsize = sizeof(struct sockaddr_in6);
2626  else
2627  addrsize = sizeof(struct sockaddr_in);
2628 #else
2629  localaddr.sin_family = serveraddrs[0].ai_family;
2630  localaddr.sin_addr.s_addr = INADDR_ANY;
2631  addrsize = sizeof(struct sockaddr_in);
2632 #endif
2633  if (bind(sock, (struct sockaddr *) & localaddr, addrsize))
2634  {
2635  ereport(LOG,
2636  (errmsg("could not bind local RADIUS socket: %m")));
2637  closesocket(sock);
2638  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2639  return STATUS_ERROR;
2640  }
2641 
2642  if (sendto(sock, radius_buffer, packetlength, 0,
2643  serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
2644  {
2645  ereport(LOG,
2646  (errmsg("could not send RADIUS packet: %m")));
2647  closesocket(sock);
2648  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2649  return STATUS_ERROR;
2650  }
2651 
2652  /* Don't need the server address anymore */
2653  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2654 
2655  /*
2656  * Figure out at what time we should time out. We can't just use a single
2657  * call to select() with a timeout, since somebody can be sending invalid
2658  * packets to our port thus causing us to retry in a loop and never time
2659  * out.
2660  *
2661  * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if
2662  * the latch was set would improve the responsiveness to
2663  * timeouts/cancellations.
2664  */
2665  gettimeofday(&endtime, NULL);
2666  endtime.tv_sec += RADIUS_TIMEOUT;
2667 
2668  while (true)
2669  {
2670  struct timeval timeout;
2671  struct timeval now;
2672  int64 timeoutval;
2673 
2674  gettimeofday(&now, NULL);
2675  timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
2676  if (timeoutval <= 0)
2677  {
2678  ereport(LOG,
2679  (errmsg("timeout waiting for RADIUS response")));
2680  closesocket(sock);
2681  return STATUS_ERROR;
2682  }
2683  timeout.tv_sec = timeoutval / 1000000;
2684  timeout.tv_usec = timeoutval % 1000000;
2685 
2686  FD_ZERO(&fdset);
2687  FD_SET(sock, &fdset);
2688 
2689  r = select(sock + 1, &fdset, NULL, NULL, &timeout);
2690  if (r < 0)
2691  {
2692  if (errno == EINTR)
2693  continue;
2694 
2695  /* Anything else is an actual error */
2696  ereport(LOG,
2697  (errmsg("could not check status on RADIUS socket: %m")));
2698  closesocket(sock);
2699  return STATUS_ERROR;
2700  }
2701  if (r == 0)
2702  {
2703  ereport(LOG,
2704  (errmsg("timeout waiting for RADIUS response")));
2705  closesocket(sock);
2706  return STATUS_ERROR;
2707  }
2708 
2709  /*
2710  * Attempt to read the response packet, and verify the contents.
2711  *
2712  * Any packet that's not actually a RADIUS packet, or otherwise does
2713  * not validate as an explicit reject, is just ignored and we retry
2714  * for another packet (until we reach the timeout). This is to avoid
2715  * the possibility to denial-of-service the login by flooding the
2716  * server with invalid packets on the port that we're expecting the
2717  * RADIUS response on.
2718  */
2719 
2720  addrsize = sizeof(remoteaddr);
2721  packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
2722  (struct sockaddr *) & remoteaddr, &addrsize);
2723  if (packetlength < 0)
2724  {
2725  ereport(LOG,
2726  (errmsg("could not read RADIUS response: %m")));
2727  return STATUS_ERROR;
2728  }
2729 
2730 #ifdef HAVE_IPV6
2731  if (remoteaddr.sin6_port != htons(port->hba->radiusport))
2732 #else
2733  if (remoteaddr.sin_port != htons(port->hba->radiusport))
2734 #endif
2735  {
2736 #ifdef HAVE_IPV6
2737  ereport(LOG,
2738  (errmsg("RADIUS response was sent from incorrect port: %d",
2739  ntohs(remoteaddr.sin6_port))));
2740 #else
2741  ereport(LOG,
2742  (errmsg("RADIUS response was sent from incorrect port: %d",
2743  ntohs(remoteaddr.sin_port))));
2744 #endif
2745  continue;
2746  }
2747 
2748  if (packetlength < RADIUS_HEADER_LENGTH)
2749  {
2750  ereport(LOG,
2751  (errmsg("RADIUS response too short: %d", packetlength)));
2752  continue;
2753  }
2754 
2755  if (packetlength != ntohs(receivepacket->length))
2756  {
2757  ereport(LOG,
2758  (errmsg("RADIUS response has corrupt length: %d (actual length %d)",
2759  ntohs(receivepacket->length), packetlength)));
2760  continue;
2761  }
2762 
2763  if (packet->id != receivepacket->id)
2764  {
2765  ereport(LOG,
2766  (errmsg("RADIUS response is to a different request: %d (should be %d)",
2767  receivepacket->id, packet->id)));
2768  continue;
2769  }
2770 
2771  /*
2772  * Verify the response authenticator, which is calculated as
2773  * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
2774  */
2775  cryptvector = palloc(packetlength + strlen(port->hba->radiussecret));
2776 
2777  memcpy(cryptvector, receivepacket, 4); /* code+id+length */
2778  memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request
2779  * authenticator, from
2780  * original packet */
2781  if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
2782  * attributes at all */
2783  memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
2784  memcpy(cryptvector + packetlength, port->hba->radiussecret, strlen(port->hba->radiussecret));
2785 
2786  if (!pg_md5_binary(cryptvector,
2787  packetlength + strlen(port->hba->radiussecret),
2788  encryptedpassword))
2789  {
2790  ereport(LOG,
2791  (errmsg("could not perform MD5 encryption of received packet")));
2792  pfree(cryptvector);
2793  continue;
2794  }
2795  pfree(cryptvector);
2796 
2797  if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
2798  {
2799  ereport(LOG,
2800  (errmsg("RADIUS response has incorrect MD5 signature")));
2801  continue;
2802  }
2803 
2804  if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
2805  {
2806  closesocket(sock);
2807  return STATUS_OK;
2808  }
2809  else if (receivepacket->code == RADIUS_ACCESS_REJECT)
2810  {
2811  closesocket(sock);
2812  return STATUS_ERROR;
2813  }
2814  else
2815  {
2816  ereport(LOG,
2817  (errmsg("RADIUS response has invalid code (%d) for user \"%s\"",
2818  receivepacket->code, port->user_name)));
2819  continue;
2820  }
2821  } /* while (true) */
2822 }
#define RADIUS_PASSWORD
Definition: auth.c:2415
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:105
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:89
const struct in6_addr in6addr_any
Definition: mingwcompat.c:22
#define closesocket
Definition: port.h:328
uint16 length
Definition: auth.c:2404
unsigned char uint8
Definition: c.h:263
#define RADIUS_VECTOR_LENGTH
Definition: auth.c:2389
#define socket(af, type, protocol)
Definition: win32.h:379
#define STATUS_ERROR
Definition: c.h:971
#define MemSet(start, val, len)
Definition: c.h:852
#define select(n, r, w, e, timeout)
Definition: win32.h:384
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
#define RADIUS_NAS_IDENTIFIER
Definition: auth.c:2417
#define RADIUS_TIMEOUT
Definition: auth.c:2426
#define gai_strerror
Definition: getaddrinfo.h:148
signed int int32
Definition: c.h:253
#define RADIUS_HEADER_LENGTH
Definition: auth.c:2390
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:58
char * radiussecret
Definition: hba.h:92
char * radiusserver
Definition: hba.h:91
void pfree(void *pointer)
Definition: mcxt.c:992
#define bind(s, addr, addrlen)
Definition: win32.h:380
int radiusport
Definition: hba.h:94
#define RADIUS_USER_NAME
Definition: auth.c:2414
bool pg_backend_random(char *dst, int len)
char * user_name
Definition: libpq-be.h:139
int pgsocket
Definition: port.h:22
char * radiusidentifier
Definition: hba.h:93
static void sendAuthRequest(Port *port, AuthRequest areq, char *extradata, int extralen)
Definition: auth.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
#define STATUS_OK
Definition: c.h:970
static char * recv_password_packet(Port *port)
Definition: auth.c:627
#define RADIUS_ACCESS_ACCEPT
Definition: auth.c:2410
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:168
HbaLine * hba
Definition: libpq-be.h:146
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2423
#define PGINVALID_SOCKET
Definition: port.h:24
#define EINTR
Definition: win32.h:295
#define RADIUS_AUTHENTICATE_ONLY
Definition: auth.c:2420
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define RADIUS_ACCESS_REQUEST
Definition: auth.c:2409
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2391
#define RADIUS_SERVICE_TYPE
Definition: auth.c:2416
uint8 id
Definition: auth.c:2403
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
uint8 code
Definition: auth.c:2402
uint8 vector[RADIUS_VECTOR_LENGTH]
Definition: auth.c:2405
bool pg_md5_binary(const void *buff, size_t len, void *outbuf)
Definition: md5.c:305
#define STATUS_EOF
Definition: c.h:972
static void radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
Definition: auth.c:2429
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1652
#define offsetof(type, field)
Definition: c.h:550
#define RADIUS_ACCESS_REJECT
Definition: auth.c:2411
int ai_family
Definition: getaddrinfo.h:103
void ClientAuthentication ( Port port)

Definition at line 329 of file auth.c.

References _, SockAddr::addr, am_walsender, Assert, auth_failed(), HbaLine::auth_method, AUTH_REQ_GSS, AUTH_REQ_OK, AUTH_REQ_SSPI, CHECK_FOR_INTERRUPTS, CheckMD5Auth(), CheckPasswordAuth(), CheckRADIUSAuth(), ClientAuthentication_hook, HbaLine::clientcert, Port::database_name, ereport, errcode(), errmsg(), FATAL, Port::hba, hba_getauthmethod(), HOSTNAME_LOOKUP_DETAIL, ident_inet(), NI_MAXHOST, NI_NUMERICHOST, NULL, Port::peer_cert_valid, pg_getnameinfo_all(), port, Port::raddr, SockAddr::salen, secure_loaded_verify_locations(), sendAuthRequest(), Port::ssl_in_use, status(), STATUS_ERROR, STATUS_OK, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaPAM, uaPassword, uaRADIUS, uaReject, uaSSPI, uaTrust, and Port::user_name.

Referenced by PerformAuthentication().

330 {
331  int status = STATUS_ERROR;
332  char *logdetail = NULL;
333 
334  /*
335  * Get the authentication method to use for this frontend/database
336  * combination. Note: we do not parse the file at this point; this has
337  * already been done elsewhere. hba.c dropped an error message into the
338  * server logfile if parsing the hba config file failed.
339  */
340  hba_getauthmethod(port);
341 
343 
344  /*
345  * This is the first point where we have access to the hba record for the
346  * current connection, so perform any verifications based on the hba
347  * options field that should be done *before* the authentication here.
348  */
349  if (port->hba->clientcert)
350  {
351  /* If we haven't loaded a root certificate store, fail */
353  ereport(FATAL,
354  (errcode(ERRCODE_CONFIG_FILE_ERROR),
355  errmsg("client certificates can only be checked if a root certificate store is available")));
356 
357  /*
358  * If we loaded a root certificate store, and if a certificate is
359  * present on the client, then it has been verified against our root
360  * certificate store, and the connection would have been aborted
361  * already if it didn't verify ok.
362  */
363  if (!port->peer_cert_valid)
364  ereport(FATAL,
365  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
366  errmsg("connection requires a valid client certificate")));
367  }
368 
369  /*
370  * Now proceed to do the actual authentication check
371  */
372  switch (port->hba->auth_method)
373  {
374  case uaReject:
375 
376  /*
377  * An explicit "reject" entry in pg_hba.conf. This report exposes
378  * the fact that there's an explicit reject entry, which is
379  * perhaps not so desirable from a security standpoint; but the
380  * message for an implicit reject could confuse the DBA a lot when
381  * the true situation is a match to an explicit reject. And we
382  * don't want to change the message for an implicit reject. As
383  * noted below, the additional information shown here doesn't
384  * expose anything not known to an attacker.
385  */
386  {
387  char hostinfo[NI_MAXHOST];
388 
389  pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
390  hostinfo, sizeof(hostinfo),
391  NULL, 0,
393 
394  if (am_walsender)
395  {
396 #ifdef USE_SSL
397  ereport(FATAL,
398  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
399  errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
400  hostinfo, port->user_name,
401  port->ssl_in_use ? _("SSL on") : _("SSL off"))));
402 #else
403  ereport(FATAL,
404  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
405  errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\"",
406  hostinfo, port->user_name)));
407 #endif
408  }
409  else
410  {
411 #ifdef USE_SSL
412  ereport(FATAL,
413  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
414  errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
415  hostinfo, port->user_name,
416  port->database_name,
417  port->ssl_in_use ? _("SSL on") : _("SSL off"))));
418 #else
419  ereport(FATAL,
420  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
421  errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\"",
422  hostinfo, port->user_name,
423  port->database_name)));
424 #endif
425  }
426  break;
427  }
428 
429  case uaImplicitReject:
430 
431  /*
432  * No matching entry, so tell the user we fell through.
433  *
434  * NOTE: the extra info reported here is not a security breach,
435  * because all that info is known at the frontend and must be
436  * assumed known to bad guys. We're merely helping out the less
437  * clueful good guys.
438  */
439  {
440  char hostinfo[NI_MAXHOST];
441 
442  pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
443  hostinfo, sizeof(hostinfo),
444  NULL, 0,
446 
447 #define HOSTNAME_LOOKUP_DETAIL(port) \
448  (port->remote_hostname ? \
449  (port->remote_hostname_resolv == +1 ? \
450  errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
451  port->remote_hostname) : \
452  port->remote_hostname_resolv == 0 ? \
453  errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
454  port->remote_hostname) : \
455  port->remote_hostname_resolv == -1 ? \
456  errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
457  port->remote_hostname) : \
458  port->remote_hostname_resolv == -2 ? \
459  errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
460  port->remote_hostname, \
461  gai_strerror(port->remote_hostname_errcode)) : \
462  0) \
463  : (port->remote_hostname_resolv == -2 ? \
464  errdetail_log("Could not resolve client IP address to a host name: %s.", \
465  gai_strerror(port->remote_hostname_errcode)) : \
466  0))
467 
468  if (am_walsender)
469  {
470 #ifdef USE_SSL
471  ereport(FATAL,
472  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
473  errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
474  hostinfo, port->user_name,
475  port->ssl_in_use ? _("SSL on") : _("SSL off")),
476  HOSTNAME_LOOKUP_DETAIL(port)));
477 #else
478  ereport(FATAL,
479  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
480  errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\"",
481  hostinfo, port->user_name),
482  HOSTNAME_LOOKUP_DETAIL(port)));
483 #endif
484  }
485  else
486  {
487 #ifdef USE_SSL
488  ereport(FATAL,
489  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
490  errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
491  hostinfo, port->user_name,
492  port->database_name,
493  port->ssl_in_use ? _("SSL on") : _("SSL off")),
494  HOSTNAME_LOOKUP_DETAIL(port)));
495 #else
496  ereport(FATAL,
497  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
498  errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
499  hostinfo, port->user_name,
500  port->database_name),
501  HOSTNAME_LOOKUP_DETAIL(port)));
502 #endif
503  }
504  break;
505  }
506 
507  case uaGSS:
508 #ifdef ENABLE_GSS
509  sendAuthRequest(port, AUTH_REQ_GSS, NULL, 0);
510  status = pg_GSS_recvauth(port);
511 #else
512  Assert(false);
513 #endif
514  break;
515 
516  case uaSSPI:
517 #ifdef ENABLE_SSPI
519  status = pg_SSPI_recvauth(port);
520 #else
521  Assert(false);
522 #endif
523  break;
524 
525  case uaPeer:
526 #ifdef HAVE_UNIX_SOCKETS
527  status = auth_peer(port);
528 #else
529  Assert(false);
530 #endif
531  break;
532 
533  case uaIdent:
534  status = ident_inet(port);
535  break;
536 
537  case uaMD5:
538  status = CheckMD5Auth(port, &logdetail);
539  break;
540 
541  case uaPassword:
542  status = CheckPasswordAuth(port, &logdetail);
543  break;
544 
545  case uaPAM:
546 #ifdef USE_PAM
547  status = CheckPAMAuth(port, port->user_name, "");
548 #else
549  Assert(false);
550 #endif /* USE_PAM */
551  break;
552 
553  case uaBSD:
554 #ifdef USE_BSD_AUTH
555  status = CheckBSDAuth(port, port->user_name);
556 #else
557  Assert(false);
558 #endif /* USE_BSD_AUTH */
559  break;
560 
561  case uaLDAP:
562 #ifdef USE_LDAP
563  status = CheckLDAPAuth(port);
564 #else
565  Assert(false);
566 #endif
567  break;
568 
569  case uaCert:
570 #ifdef USE_SSL
571  status = CheckCertAuth(port);
572 #else
573  Assert(false);
574 #endif
575  break;
576  case uaRADIUS:
577  status = CheckRADIUSAuth(port);
578  break;
579  case uaTrust:
580  status = STATUS_OK;
581  break;
582  }
583 
585  (*ClientAuthentication_hook) (port, status);
586 
587  if (status == STATUS_OK)
588  sendAuthRequest(port, AUTH_REQ_OK, NULL, 0);
589  else
590  auth_failed(port, status, logdetail);
591 }
#define HOSTNAME_LOOKUP_DETAIL(port)
Definition: hba.h:30
#define AUTH_REQ_SSPI
Definition: pqcomm.h:174
Definition: hba.h:37
#define NI_NUMERICHOST
Definition: getaddrinfo.h:80
Definition: hba.h:32
#define AUTH_REQ_OK
Definition: pqcomm.h:165
#define AUTH_REQ_GSS
Definition: pqcomm.h:172
Definition: hba.h:34
bool peer_cert_valid
Definition: libpq-be.h:185
struct sockaddr_storage addr
Definition: pqcomm.h:64
int errcode(int sqlerrcode)
Definition: elog.c:575
#define STATUS_ERROR
Definition: c.h:971
bool ssl_in_use
Definition: libpq-be.h:183
static int CheckRADIUSAuth(Port *port)
Definition: auth.c:2455
Definition: hba.h:33
Definition: hba.h:31
SockAddr raddr
Definition: libpq-be.h:124
bool am_walsender
Definition: walsender.c:106
#define NI_MAXHOST
Definition: getaddrinfo.h:90
Definition: hba.h:38
#define FATAL
Definition: elog.h:52
Definition: hba.h:27
Definition: hba.h:29
void hba_getauthmethod(hbaPort *port)
Definition: hba.c:2838
ClientAuthentication_hook_type ClientAuthentication_hook
Definition: auth.c:226
char * user_name
Definition: libpq-be.h:139
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
static void sendAuthRequest(Port *port, AuthRequest areq, char *extradata, int extralen)
Definition: auth.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
#define STATUS_OK
Definition: c.h:970
static int CheckMD5Auth(Port *port, char **logdetail)
Definition: auth.c:697
static int port
Definition: pg_regress.c:87
HbaLine * hba
Definition: libpq-be.h:146
static int ident_inet(hbaPort *port)
Definition: auth.c:1569
static int CheckPasswordAuth(Port *port, char **logdetail)
Definition: auth.c:741
Definition: hba.h:36
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:123
bool secure_loaded_verify_locations(void)
Definition: be-secure.c:97
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void auth_failed(Port *port, int status, char *logdetail)
Definition: auth.c:242
bool clientcert
Definition: hba.h:86
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
char * database_name
Definition: libpq-be.h:138
Definition: hba.h:35
#define _(x)
Definition: elog.c:84
Definition: hba.h:39
UserAuth auth_method
Definition: hba.h:71
static int ident_inet ( hbaPort port)
static

Definition at line 1569 of file auth.c.

References SockAddr::addr, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, AI_NUMERICHOST, addrinfo::ai_protocol, addrinfo::ai_socktype, bind, CHECK_FOR_INTERRUPTS, check_usermap(), closesocket, connect, EINTR, ereport, errcode_for_socket_access(), errmsg(), Port::hba, IDENT_PORT, IDENT_USERNAME_MAX, interpret_ident_response(), Port::laddr, LOG, NI_MAXHOST, NI_MAXSERV, NI_NUMERICHOST, NI_NUMERICSERV, NULL, pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_getnameinfo_all(), PGINVALID_SOCKET, Port::raddr, recv, SockAddr::salen, send, snprintf(), socket, STATUS_ERROR, Port::user_name, and HbaLine::usermap.

Referenced by ClientAuthentication().

1570 {
1571  const SockAddr remote_addr = port->raddr;
1572  const SockAddr local_addr = port->laddr;
1573  char ident_user[IDENT_USERNAME_MAX + 1];
1574  pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1575  int rc; /* Return code from a locally called function */
1576  bool ident_return;
1577  char remote_addr_s[NI_MAXHOST];
1578  char remote_port[NI_MAXSERV];
1579  char local_addr_s[NI_MAXHOST];
1580  char local_port[NI_MAXSERV];
1581  char ident_port[NI_MAXSERV];
1582  char ident_query[80];
1583  char ident_response[80 + IDENT_USERNAME_MAX];
1584  struct addrinfo *ident_serv = NULL,
1585  *la = NULL,
1586  hints;
1587 
1588  /*
1589  * Might look a little weird to first convert it to text and then back to
1590  * sockaddr, but it's protocol independent.
1591  */
1592  pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1593  remote_addr_s, sizeof(remote_addr_s),
1594  remote_port, sizeof(remote_port),
1596  pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1597  local_addr_s, sizeof(local_addr_s),
1598  local_port, sizeof(local_port),
1600 
1601  snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1602  hints.ai_flags = AI_NUMERICHOST;
1603  hints.ai_family = remote_addr.addr.ss_family;
1604  hints.ai_socktype = SOCK_STREAM;
1605  hints.ai_protocol = 0;
1606  hints.ai_addrlen = 0;
1607  hints.ai_canonname = NULL;
1608  hints.ai_addr = NULL;
1609  hints.ai_next = NULL;
1610  rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1611  if (rc || !ident_serv)
1612  {
1613  /* we don't expect this to happen */
1614  ident_return = false;
1615  goto ident_inet_done;
1616  }
1617 
1618  hints.ai_flags = AI_NUMERICHOST;
1619  hints.ai_family = local_addr.addr.ss_family;
1620  hints.ai_socktype = SOCK_STREAM;
1621  hints.ai_protocol = 0;
1622  hints.ai_addrlen = 0;
1623  hints.ai_canonname = NULL;
1624  hints.ai_addr = NULL;
1625  hints.ai_next = NULL;
1626  rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1627  if (rc || !la)
1628  {
1629  /* we don't expect this to happen */
1630  ident_return = false;
1631  goto ident_inet_done;
1632  }
1633 
1634  sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1635  ident_serv->ai_protocol);
1636  if (sock_fd == PGINVALID_SOCKET)
1637  {
1638  ereport(LOG,
1640  errmsg("could not create socket for Ident connection: %m")));
1641  ident_return = false;
1642  goto ident_inet_done;
1643  }
1644 
1645  /*
1646  * Bind to the address which the client originally contacted, otherwise
1647  * the ident server won't be able to match up the right connection. This
1648  * is necessary if the PostgreSQL server is running on an IP alias.
1649  */
1650  rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1651  if (rc != 0)
1652  {
1653  ereport(LOG,
1655  errmsg("could not bind to local address \"%s\": %m",
1656  local_addr_s)));
1657  ident_return = false;
1658  goto ident_inet_done;
1659  }
1660 
1661  rc = connect(sock_fd, ident_serv->ai_addr,
1662  ident_serv->ai_addrlen);
1663  if (rc != 0)
1664  {
1665  ereport(LOG,
1667  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1668  remote_addr_s, ident_port)));
1669  ident_return = false;
1670  goto ident_inet_done;
1671  }
1672 
1673  /* The query we send to the Ident server */
1674  snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1675  remote_port, local_port);
1676 
1677  /* loop in case send is interrupted */
1678  do
1679  {
1681 
1682  rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1683  } while (rc < 0 && errno == EINTR);
1684 
1685  if (rc < 0)
1686  {
1687  ereport(LOG,
1689  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1690  remote_addr_s, ident_port)));
1691  ident_return = false;
1692  goto ident_inet_done;
1693  }
1694 
1695  do
1696  {
1698 
1699  rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1700  } while (rc < 0 && errno == EINTR);
1701 
1702  if (rc < 0)
1703  {
1704  ereport(LOG,
1706  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1707  remote_addr_s, ident_port)));
1708  ident_return = false;
1709  goto ident_inet_done;
1710  }
1711 
1712  ident_response[rc] = '\0';
1713  ident_return = interpret_ident_response(ident_response, ident_user);
1714  if (!ident_return)
1715  ereport(LOG,
1716  (errmsg("invalidly formatted response from Ident server: \"%s\"",
1717  ident_response)));
1718 
1719 ident_inet_done:
1720  if (sock_fd != PGINVALID_SOCKET)
1721  closesocket(sock_fd);
1722  if (ident_serv)
1723  pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1724  if (la)
1725  pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1726 
1727  if (ident_return)
1728  /* Success! Check the usermap */
1729  return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1730  return STATUS_ERROR;
1731 }
#define send(s, buf, len, flags)
Definition: win32.h:386
#define connect(s, name, namelen)
Definition: win32.h:383
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:89
#define NI_NUMERICHOST
Definition: getaddrinfo.h:80
#define closesocket
Definition: port.h:328
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define socket(af, type, protocol)
Definition: win32.h:379
#define STATUS_ERROR
Definition: c.h:971
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define recv(s, buf, len, flags)
Definition: win32.h:385
#define LOG
Definition: elog.h:26
#define AI_NUMERICHOST
Definition: getaddrinfo.h:75
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:58
SockAddr raddr
Definition: libpq-be.h:124
#define IDENT_USERNAME_MAX
Definition: auth.c:67
#define NI_MAXHOST
Definition: getaddrinfo.h:90
#define bind(s, addr, addrlen)
Definition: win32.h:380
char * usermap
Definition: hba.h:73
#define IDENT_PORT
Definition: auth.c:70
#define NI_MAXSERV
Definition: getaddrinfo.h:93
char * user_name
Definition: libpq-be.h:139
int pgsocket
Definition: port.h:22
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define ereport(elevel, rest)
Definition: elog.h:122
int errcode_for_socket_access(void)
Definition: elog.c:669
SockAddr laddr
Definition: libpq-be.h:123
HbaLine * hba
Definition: libpq-be.h:146
#define PGINVALID_SOCKET
Definition: port.h:24
#define EINTR
Definition: win32.h:295
int check_usermap(const char *usermap_name, const char *pg_role, const char *auth_user, bool case_insensitive)
Definition: hba.c:2672
#define NI_NUMERICSERV
Definition: getaddrinfo.h:83
int ai_protocol
Definition: getaddrinfo.h:105
#define NULL
Definition: c.h:226
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:123
int ai_socktype
Definition: getaddrinfo.h:104
int errmsg(const char *fmt,...)
Definition: elog.c:797
size_t ai_addrlen
Definition: getaddrinfo.h:106
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1481
struct sockaddr * ai_addr
Definition: getaddrinfo.h:107
int ai_family
Definition: getaddrinfo.h:103
static bool interpret_ident_response ( const char *  ident_response,
char *  ident_user 
)
static

Definition at line 1481 of file auth.c.

References i, IDENT_USERNAME_MAX, and pg_isblank().

Referenced by ident_inet().

1483 {
1484  const char *cursor = ident_response; /* Cursor into *ident_response */
1485 
1486  /*
1487  * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1488  */
1489  if (strlen(ident_response) < 2)
1490  return false;
1491  else if (ident_response[strlen(ident_response) - 2] != '\r')
1492  return false;
1493  else
1494  {
1495  while (*cursor != ':' && *cursor != '\r')
1496  cursor++; /* skip port field */
1497 
1498  if (*cursor != ':')
1499  return false;
1500  else
1501  {
1502  /* We're positioned to colon before response type field */
1503  char response_type[80];
1504  int i; /* Index into *response_type */
1505 
1506  cursor++; /* Go over colon */
1507  while (pg_isblank(*cursor))
1508  cursor++; /* skip blanks */
1509  i = 0;
1510  while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1511  i < (int) (sizeof(response_type) - 1))
1512  response_type[i++] = *cursor++;
1513  response_type[i] = '\0';
1514  while (pg_isblank(*cursor))
1515  cursor++; /* skip blanks */
1516  if (strcmp(response_type, "USERID") != 0)
1517  return false;
1518  else
1519  {
1520  /*
1521  * It's a USERID response. Good. "cursor" should be pointing
1522  * to the colon that precedes the operating system type.
1523  */
1524  if (*cursor != ':')
1525  return false;
1526  else
1527  {
1528  cursor++; /* Go over colon */
1529  /* Skip over operating system field. */
1530  while (*cursor != ':' && *cursor != '\r')
1531  cursor++;
1532  if (*cursor != ':')
1533  return false;
1534  else
1535  {
1536  int i; /* Index into *ident_user */
1537 
1538  cursor++; /* Go over colon */
1539  while (pg_isblank(*cursor))
1540  cursor++; /* skip blanks */
1541  /* Rest of line is user name. Copy it over. */
1542  i = 0;
1543  while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1544  ident_user[i++] = *cursor++;
1545  ident_user[i] = '\0';
1546  return true;
1547  }
1548  }
1549  }
1550  }
1551  }
1552 }
bool pg_isblank(const char c)
Definition: hba.c:159
#define IDENT_USERNAME_MAX
Definition: auth.c:67
Definition: type.h:125
int i
static void radius_add_attribute ( radius_packet packet,
uint8  type,
const unsigned char *  data,
int  len 
)
static

Definition at line 2429 of file auth.c.

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

Referenced by CheckRADIUSAuth().

2430 {
2431  radius_attribute *attr;
2432 
2433  if (packet->length + len > RADIUS_BUFFER_SIZE)
2434  {
2435  /*
2436  * With remotely realistic data, this can never happen. But catch it
2437  * just to make sure we don't overrun a buffer. We'll just skip adding
2438  * the broken attribute, which will in the end cause authentication to
2439  * fail.
2440  */
2441  elog(WARNING,
2442  "Adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
2443  type, len);
2444  return;
2445  }
2446 
2447  attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2448  attr->attribute = type;
2449  attr->length = len + 2; /* total size includes type and length */
2450  memcpy(attr->data, data, len);
2451  packet->length += attr->length;
2452 }
uint16 length
Definition: auth.c:2404
uint8 attribute
Definition: auth.c:2395
#define WARNING
Definition: elog.h:40
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2423
uint8 data[FLEXIBLE_ARRAY_MEMBER]
Definition: auth.c:2397
#define elog
Definition: elog.h:219
uint8 length
Definition: auth.c:2396
static char * recv_password_packet ( Port port)
static

Definition at line 627 of file auth.c.

References buf, COMMERROR, StringInfoData::data, DEBUG5, elog, ereport, errcode(), errmsg(), initStringInfo(), StringInfoData::len, NULL, pfree(), PG_PROTOCOL_MAJOR, pq_getbyte(), pq_getmessage(), pq_peekbyte(), pq_startmsgread(), and Port::proto.

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

628 {
630 
631  pq_startmsgread();
632  if (PG_PROTOCOL_MAJOR(port->proto) >= 3)
633  {
634  /* Expect 'p' message type */
635  int mtype;
636 
637  mtype = pq_getbyte();
638  if (mtype != 'p')
639  {
640  /*
641  * If the client just disconnects without offering a password,
642  * don't make a log entry. This is legal per protocol spec and in
643  * fact commonly done by psql, so complaining just clutters the
644  * log.
645  */
646  if (mtype != EOF)
648  (errcode(ERRCODE_PROTOCOL_VIOLATION),
649  errmsg("expected password response, got message type %d",
650  mtype)));
651  return NULL; /* EOF or bad message type */
652  }
653  }
654  else
655  {
656  /* For pre-3.0 clients, avoid log entry if they just disconnect */
657  if (pq_peekbyte() == EOF)
658  return NULL; /* EOF */
659  }
660 
661  initStringInfo(&buf);
662  if (pq_getmessage(&buf, 1000)) /* receive password */
663  {
664  /* EOF - pq_getmessage already logged a suitable message */
665  pfree(buf.data);
666  return NULL;
667  }
668 
669  /*
670  * Apply sanity check: password packet length should agree with length of
671  * contained string. Note it is safe to use strlen here because
672  * StringInfo is guaranteed to have an appended '\0'.
673  */
674  if (strlen(buf.data) + 1 != buf.len)
676  (errcode(ERRCODE_PROTOCOL_VIOLATION),
677  errmsg("invalid password packet size")));
678 
679  /* Do not echo password to logs, for security. */
680  elog(DEBUG5, "received password packet");
681 
682  /*
683  * Return the received string. Note we do not attempt to do any
684  * character-set conversion on it; since we don't yet know the client's
685  * encoding, there wouldn't be much point.
686  */
687  return buf.data;
688 }
int pq_peekbyte(void)
Definition: pqcomm.c:966
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:104
void pfree(void *pointer)
Definition: mcxt.c:992
void pq_startmsgread(void)
Definition: pqcomm.c:1157
static char * buf
Definition: pg_test_fsync.c:65
#define COMMERROR
Definition: elog.h:30
#define ereport(elevel, rest)
Definition: elog.h:122
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1219
int pq_getbyte(void)
Definition: pqcomm.c:947
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define DEBUG5
Definition: elog.h:20
ProtocolVersion proto
Definition: libpq-be.h:122
static void sendAuthRequest ( Port port,
AuthRequest  areq,
char *  extradata,
int  extralen 
)
static

Definition at line 598 of file auth.c.

References AUTH_REQ_OK, buf, CHECK_FOR_INTERRUPTS, pq_beginmessage(), pq_endmessage(), pq_flush, pq_sendbytes(), and pq_sendint().

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

599 {
601 
603 
604  pq_beginmessage(&buf, 'R');
605  pq_sendint(&buf, (int32) areq, sizeof(int32));
606  if (extralen > 0)
607  pq_sendbytes(&buf, extradata, extralen);
608 
609  pq_endmessage(&buf);
610 
611  /*
612  * Flush message so client will see it, except for AUTH_REQ_OK, which need
613  * not be sent until we are ready for queries.
614  */
615  if (areq != AUTH_REQ_OK)
616  pq_flush();
617 
619 }
#define pq_flush()
Definition: libpq.h:40
#define AUTH_REQ_OK
Definition: pqcomm.h:165
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:88
signed int int32
Definition: c.h:253
static char * buf
Definition: pg_test_fsync.c:65
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:115
void pq_sendint(StringInfo buf, int i, int b)
Definition: pqformat.c:236
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:344
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97

Variable Documentation

ClientAuthentication_hook_type ClientAuthentication_hook = NULL

Definition at line 226 of file auth.c.

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

bool pg_krb_caseins_users

Definition at line 159 of file auth.c.

char* pg_krb_server_keyfile

Definition at line 158 of file auth.c.