mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			558 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			558 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*-------------------------------------------------------------------------
 | 
						|
 *
 | 
						|
 * auth.c--
 | 
						|
 *    Routines to handle network authentication
 | 
						|
 *
 | 
						|
 * Copyright (c) 1994, Regents of the University of California
 | 
						|
 *
 | 
						|
 *
 | 
						|
 * IDENTIFICATION
 | 
						|
 *    $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.8 1996/11/16 08:09:15 bryanh Exp $
 | 
						|
 *
 | 
						|
 *-------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
/*
 | 
						|
 * INTERFACE ROUTINES
 | 
						|
 *
 | 
						|
 *     backend (postmaster) routines:
 | 
						|
 *	be_recvauth		receive authentication information
 | 
						|
 *	be_setauthsvc		do/do not permit an authentication service
 | 
						|
 *	be_getauthsvc		is an authentication service permitted?
 | 
						|
 *
 | 
						|
 *   NOTES
 | 
						|
 *	To add a new authentication system:
 | 
						|
 *	0. If you can't do your authentication over an existing socket,
 | 
						|
 *	   you lose -- get ready to hack around this framework instead of 
 | 
						|
 *	   using it.  Otherwise, you can assume you have an initialized
 | 
						|
 *	   and empty connection to work with.  (Please don't leave leftover
 | 
						|
 *	   gunk in the connection after the authentication transactions, or
 | 
						|
 *	   the POSTGRES routines that follow will be very unhappy.)
 | 
						|
 *	1. Write a set of routines that:
 | 
						|
 *		let a client figure out what user/principal name to use
 | 
						|
 *		send authentication information (client side)
 | 
						|
 *		receive authentication information (server side)
 | 
						|
 *	   You can include both routines in this file, using #ifdef FRONTEND
 | 
						|
 *	   to separate them.
 | 
						|
 *	2. Edit libpq/pqcomm.h and assign a MsgType for your protocol.
 | 
						|
 *	3. Edit the static "struct authsvc" array and the generic 
 | 
						|
 *	   {be,fe}_{get,set}auth{name,svc} routines in this file to reflect 
 | 
						|
 *	   the new service.  You may have to change the arguments of these
 | 
						|
 *	   routines; they basically just reflect what Kerberos v4 needs.
 | 
						|
 *	4. Hack on src/{,bin}/Makefile.global and src/{backend,libpq}/Makefile
 | 
						|
 *	   to add library and CFLAGS hooks -- basically, grep the Makefile
 | 
						|
 *	   hierarchy for KRBVERS to see where you need to add things.
 | 
						|
 *
 | 
						|
 *	Send mail to post_hackers@postgres.Berkeley.EDU if you have to make 
 | 
						|
 *	any changes to arguments, etc.  Context diffs would be nice, too.
 | 
						|
 *
 | 
						|
 *	Someday, this cruft will go away and magically be replaced by a
 | 
						|
 *	nice interface based on the GSS API or something.  For now, though,
 | 
						|
 *	there's no (stable) UNIX security API to work with...
 | 
						|
 *
 | 
						|
 */
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include <sys/param.h>	/* for MAXHOSTNAMELEN on most */
 | 
						|
#ifndef  MAXHOSTNAMELEN
 | 
						|
#include <netdb.h>	/* for MAXHOSTNAMELEN on some */
 | 
						|
#endif
 | 
						|
#include <pwd.h>
 | 
						|
#include <ctype.h>		        /* isspace() declaration */
 | 
						|
 | 
						|
#include <sys/types.h>    /* needed by in.h on Ultrix */
 | 
						|
#include <netinet/in.h>
 | 
						|
#include <arpa/inet.h>
 | 
						|
 | 
						|
#include <postgres.h>
 | 
						|
#include <miscadmin.h>
 | 
						|
 | 
						|
#include <libpq/auth.h>
 | 
						|
#include <libpq/libpq.h>
 | 
						|
#include <libpq/libpq-be.h>
 | 
						|
#include <libpq/hba.h>
 | 
						|
 | 
						|
/*----------------------------------------------------------------
 | 
						|
 * common definitions for generic fe/be routines
 | 
						|
 *----------------------------------------------------------------
 | 
						|
 */
 | 
						|
 | 
						|
struct authsvc {
 | 
						|
    char	name[16];	/* service nickname (for command line) */
 | 
						|
    MsgType	msgtype;	/* startup packet header type */
 | 
						|
    int		allowed;	/* initially allowed (before command line
 | 
						|
				 * option parsing)?
 | 
						|
				 */
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
 * Command-line parsing routines use this structure to map nicknames
 | 
						|
 * onto service types (and the startup packets to use with them).
 | 
						|
 *
 | 
						|
 * Programs receiving an authentication request use this structure to
 | 
						|
 * decide which authentication service types are currently permitted.
 | 
						|
 * By default, all authentication systems compiled into the system are
 | 
						|
 * allowed.  Unauthenticated connections are disallowed unless there
 | 
						|
 * isn't any authentication system.
 | 
						|
 */
 | 
						|
 | 
						|
#if defined(HBA)
 | 
						|
static int useHostBasedAuth = 1;
 | 
						|
#else
 | 
						|
static int useHostBasedAuth = 0;
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined(KRB4) || defined(KRB5) || defined(HBA)
 | 
						|
#define UNAUTH_ALLOWED 0
 | 
						|
#else
 | 
						|
#define UNAUTH_ALLOWED 1
 | 
						|
#endif
 | 
						|
 | 
						|
static struct authsvc authsvcs[] = {
 | 
						|
    { "unauth",   STARTUP_UNAUTH_MSG, UNAUTH_ALLOWED },
 | 
						|
    { "hba",      STARTUP_HBA_MSG,  1 },
 | 
						|
    { "krb4",     STARTUP_KRB4_MSG, 1 },
 | 
						|
    { "krb5",     STARTUP_KRB5_MSG, 1 },
 | 
						|
#if defined(KRB5) 
 | 
						|
    { "kerberos", STARTUP_KRB5_MSG, 1 }
 | 
						|
#else
 | 
						|
    { "kerberos", STARTUP_KRB4_MSG, 1 }
 | 
						|
#endif
 | 
						|
};
 | 
						|
 | 
						|
static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
 | 
						|
 | 
						|
#ifdef KRB4
 | 
						|
/* This has to be ifdef'd out because krb.h does exist.  This needs
 | 
						|
   to be fixed.
 | 
						|
*/
 | 
						|
/*----------------------------------------------------------------
 | 
						|
 * MIT Kerberos authentication system - protocol version 4
 | 
						|
 *----------------------------------------------------------------
 | 
						|
 */
 | 
						|
 | 
						|
#include <krb.h>
 | 
						|
 | 
						|
#ifdef FRONTEND
 | 
						|
/* moves to src/libpq/fe-auth.c  */
 | 
						|
#else /* !FRONTEND */
 | 
						|
 | 
						|
/*
 | 
						|
 * pg_krb4_recvauth -- server routine to receive authentication information
 | 
						|
 *		       from the client
 | 
						|
 *
 | 
						|
 * Nothing unusual here, except that we compare the username obtained from
 | 
						|
 * the client's setup packet to the authenticated name.  (We have to retain
 | 
						|
 * the name in the setup packet since we have to retain the ability to handle
 | 
						|
 * unauthenticated connections.)
 | 
						|
 */
 | 
						|
static int
 | 
						|
pg_krb4_recvauth(int sock,
 | 
						|
		 struct sockaddr_in *laddr,
 | 
						|
		 struct sockaddr_in *raddr,
 | 
						|
		 char *username)
 | 
						|
{
 | 
						|
    long		krbopts = 0;	/* one-way authentication */
 | 
						|
    KTEXT_ST	clttkt;
 | 
						|
    char		instance[INST_SZ];
 | 
						|
    AUTH_DAT	auth_data;
 | 
						|
    Key_schedule	key_sched;
 | 
						|
    char		version[KRB_SENDAUTH_VLEN];
 | 
						|
    int		status;
 | 
						|
    
 | 
						|
    strcpy(instance, "*");	/* don't care, but arg gets expanded anyway */
 | 
						|
    status = krb_recvauth(krbopts,
 | 
						|
			  sock,
 | 
						|
			  &clttkt,
 | 
						|
			  PG_KRB_SRVNAM,
 | 
						|
			  instance,
 | 
						|
			  raddr,
 | 
						|
			  laddr,
 | 
						|
			  &auth_data,
 | 
						|
			  PG_KRB_SRVTAB,
 | 
						|
			  key_sched,
 | 
						|
			  version);
 | 
						|
    if (status != KSUCCESS) {
 | 
						|
	(void) sprintf(PQerrormsg,
 | 
						|
		       "pg_krb4_recvauth: kerberos error: %s\n",
 | 
						|
		       krb_err_txt[status]);
 | 
						|
	fputs(PQerrormsg, stderr);
 | 
						|
	pqdebug("%s", PQerrormsg);
 | 
						|
	return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    if (strncmp(version, PG_KRB4_VERSION, KRB_SENDAUTH_VLEN)) {
 | 
						|
	(void) sprintf(PQerrormsg,
 | 
						|
		       "pg_krb4_recvauth: protocol version != \"%s\"\n",
 | 
						|
		       PG_KRB4_VERSION);
 | 
						|
	fputs(PQerrormsg, stderr);
 | 
						|
	pqdebug("%s", PQerrormsg);
 | 
						|
	return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    if (username && *username &&
 | 
						|
	strncmp(username, auth_data.pname, NAMEDATALEN)) {
 | 
						|
	(void) sprintf(PQerrormsg,
 | 
						|
		       "pg_krb4_recvauth: name \"%s\" != \"%s\"\n",
 | 
						|
		       username,
 | 
						|
		       auth_data.pname);
 | 
						|
	fputs(PQerrormsg, stderr);
 | 
						|
	pqdebug("%s", PQerrormsg);
 | 
						|
	return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    return(STATUS_OK);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* !FRONTEND */
 | 
						|
 | 
						|
#else
 | 
						|
static int
 | 
						|
pg_krb4_recvauth(int sock,
 | 
						|
		 struct sockaddr_in *laddr,
 | 
						|
		 struct sockaddr_in *raddr,
 | 
						|
		 char *username)
 | 
						|
{
 | 
						|
  (void) sprintf(PQerrormsg,
 | 
						|
                 "pg_krb4_recvauth: Kerberos not implemented on this "
 | 
						|
                 "server.\n");
 | 
						|
  fputs(PQerrormsg, stderr);
 | 
						|
  pqdebug("%s", PQerrormsg);
 | 
						|
 | 
						|
return(STATUS_ERROR);
 | 
						|
}
 | 
						|
#endif /* KRB4 */
 | 
						|
 | 
						|
 | 
						|
#ifdef KRB5
 | 
						|
/* This needs to be ifdef'd out because krb5.h doesn't exist.  This needs
 | 
						|
   to be fixed.
 | 
						|
*/
 | 
						|
/*----------------------------------------------------------------
 | 
						|
 * MIT Kerberos authentication system - protocol version 5
 | 
						|
 *----------------------------------------------------------------
 | 
						|
 */
 | 
						|
 | 
						|
#include <krb5/krb5.h>
 | 
						|
 | 
						|
/*
 | 
						|
 * pg_an_to_ln -- return the local name corresponding to an authentication
 | 
						|
 *		  name
 | 
						|
 *
 | 
						|
 * XXX Assumes that the first aname component is the user name.  This is NOT
 | 
						|
 *     necessarily so, since an aname can actually be something out of your
 | 
						|
 *     worst X.400 nightmare, like
 | 
						|
 *	  ORGANIZATION=U. C. Berkeley/NAME=Paul M. Aoki@CS.BERKELEY.EDU
 | 
						|
 *     Note that the MIT an_to_ln code does the same thing if you don't
 | 
						|
 *     provide an aname mapping database...it may be a better idea to use
 | 
						|
 *     krb5_an_to_ln, except that it punts if multiple components are found,
 | 
						|
 *     and we can't afford to punt.
 | 
						|
 */
 | 
						|
static char *
 | 
						|
pg_an_to_ln(char *aname)
 | 
						|
{
 | 
						|
    char	*p;
 | 
						|
    
 | 
						|
    if ((p = strchr(aname, '/')) || (p = strchr(aname, '@')))
 | 
						|
	*p = '\0';
 | 
						|
    return(aname);
 | 
						|
}
 | 
						|
 | 
						|
#ifdef FRONTEND
 | 
						|
/* moves to src/libpq/fe-auth.c  */
 | 
						|
#else /* !FRONTEND */
 | 
						|
 | 
						|
/*
 | 
						|
 * pg_krb5_recvauth -- server routine to receive authentication information
 | 
						|
 *		       from the client
 | 
						|
 *
 | 
						|
 * We still need to compare the username obtained from the client's setup
 | 
						|
 * packet to the authenticated name, as described in pg_krb4_recvauth.  This
 | 
						|
 * is a bit more problematic in v5, as described above in pg_an_to_ln.
 | 
						|
 *
 | 
						|
 * In addition, as described above in pg_krb5_sendauth, we still need to
 | 
						|
 * canonicalize the server name v4-style before constructing a principal
 | 
						|
 * from it.  Again, this is kind of iffy.
 | 
						|
 *
 | 
						|
 * Finally, we need to tangle with the fact that v5 doesn't let you explicitly
 | 
						|
 * set server keytab file names -- you have to feed lower-level routines a
 | 
						|
 * function to retrieve the contents of a keytab, along with a single argument
 | 
						|
 * that allows them to open the keytab.  We assume that a server keytab is
 | 
						|
 * always a real file so we can allow people to specify their own filenames.
 | 
						|
 * (This is important because the POSTGRES keytab needs to be readable by
 | 
						|
 * non-root users/groups; the v4 tools used to force you do dump a whole
 | 
						|
 * host's worth of keys into a file, effectively forcing you to use one file,
 | 
						|
 * but kdb5_edit allows you to select which principals to dump.  Yay!)
 | 
						|
 */
 | 
						|
static int
 | 
						|
pg_krb5_recvauth(int sock,
 | 
						|
		 struct sockaddr_in *laddr,
 | 
						|
		 struct sockaddr_in *raddr,
 | 
						|
		 char *username)
 | 
						|
{
 | 
						|
    char			servbuf[MAXHOSTNAMELEN + 1 +
 | 
						|
					sizeof(PG_KRB_SRVNAM)];
 | 
						|
    char			*hostp, *kusername = (char *) NULL;
 | 
						|
    krb5_error_code		code;
 | 
						|
    krb5_principal		client, server;
 | 
						|
    krb5_address		sender_addr;
 | 
						|
    krb5_rdreq_key_proc	keyproc = (krb5_rdreq_key_proc) NULL;
 | 
						|
    krb5_pointer		keyprocarg = (krb5_pointer) NULL;
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Set up server side -- since we have no ticket file to make this
 | 
						|
     * easy, we construct our own name and parse it.  See note on
 | 
						|
     * canonicalization above.
 | 
						|
     */
 | 
						|
    (void) strcpy(servbuf, PG_KRB_SRVNAM);
 | 
						|
    *(hostp = servbuf + (sizeof(PG_KRB_SRVNAM) - 1)) = '/';
 | 
						|
    if (gethostname(++hostp, MAXHOSTNAMELEN) < 0)
 | 
						|
	(void) strcpy(hostp, "localhost");
 | 
						|
    if (hostp = strchr(hostp, '.'))
 | 
						|
	*hostp = '\0';
 | 
						|
    if (code = krb5_parse_name(servbuf, &server)) {
 | 
						|
	(void) sprintf(PQerrormsg,
 | 
						|
		       "pg_krb5_recvauth: Kerberos error %d in krb5_parse_name\n",
 | 
						|
		       code);
 | 
						|
	com_err("pg_krb5_recvauth", code, "in krb5_parse_name");
 | 
						|
	return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * krb5_sendauth needs this to verify the address in the client
 | 
						|
     * authenticator.
 | 
						|
     */
 | 
						|
    sender_addr.addrtype = raddr->sin_family;
 | 
						|
    sender_addr.length = sizeof(raddr->sin_addr);
 | 
						|
    sender_addr.contents = (krb5_octet *) &(raddr->sin_addr);
 | 
						|
    
 | 
						|
    if (strcmp(PG_KRB_SRVTAB, "")) {
 | 
						|
	keyproc = krb5_kt_read_service_key;
 | 
						|
	keyprocarg = PG_KRB_SRVTAB;
 | 
						|
    }
 | 
						|
    
 | 
						|
    if (code = krb5_recvauth((krb5_pointer) &sock,
 | 
						|
			     PG_KRB5_VERSION,
 | 
						|
			     server,
 | 
						|
			     &sender_addr,
 | 
						|
			     (krb5_pointer) NULL,
 | 
						|
			     keyproc,
 | 
						|
			     keyprocarg,
 | 
						|
			     (char *) NULL,
 | 
						|
			     (krb5_int32 *) NULL,
 | 
						|
			     &client,
 | 
						|
			     (krb5_ticket **) NULL,
 | 
						|
			     (krb5_authenticator **) NULL)) {
 | 
						|
	(void) sprintf(PQerrormsg,
 | 
						|
		       "pg_krb5_recvauth: Kerberos error %d in krb5_recvauth\n",
 | 
						|
		       code);
 | 
						|
	com_err("pg_krb5_recvauth", code, "in krb5_recvauth");
 | 
						|
	krb5_free_principal(server);
 | 
						|
	return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    krb5_free_principal(server);
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * The "client" structure comes out of the ticket and is therefore
 | 
						|
     * authenticated.  Use it to check the username obtained from the
 | 
						|
     * postmaster startup packet.
 | 
						|
     */
 | 
						|
    if ((code = krb5_unparse_name(client, &kusername))) {
 | 
						|
	(void) sprintf(PQerrormsg,
 | 
						|
		       "pg_krb5_recvauth: Kerberos error %d in krb5_unparse_name\n",
 | 
						|
		       code);
 | 
						|
	com_err("pg_krb5_recvauth", code, "in krb5_unparse_name");
 | 
						|
	krb5_free_principal(client);
 | 
						|
	return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    krb5_free_principal(client);
 | 
						|
    if (!kusername) {
 | 
						|
	(void) sprintf(PQerrormsg,
 | 
						|
		       "pg_krb5_recvauth: could not decode username\n");
 | 
						|
	fputs(PQerrormsg, stderr);
 | 
						|
	pqdebug("%s", PQerrormsg);
 | 
						|
	return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    kusername = pg_an_to_ln(kusername);
 | 
						|
    if (username && strncmp(username, kusername, NAMEDATALEN)) {
 | 
						|
	(void) sprintf(PQerrormsg,
 | 
						|
		       "pg_krb5_recvauth: name \"%s\" != \"%s\"\n",
 | 
						|
		       username, kusername);
 | 
						|
	fputs(PQerrormsg, stderr);
 | 
						|
	pqdebug("%s", PQerrormsg);
 | 
						|
	free(kusername);
 | 
						|
	return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    free(kusername);
 | 
						|
    return(STATUS_OK);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* !FRONTEND */
 | 
						|
 | 
						|
 | 
						|
#else
 | 
						|
static int
 | 
						|
pg_krb5_recvauth(int sock,
 | 
						|
		 struct sockaddr_in *laddr,
 | 
						|
		 struct sockaddr_in *raddr,
 | 
						|
		 char *username)
 | 
						|
{
 | 
						|
  (void) sprintf(PQerrormsg,
 | 
						|
                 "pg_krb5_recvauth: Kerberos not implemented on this "
 | 
						|
                 "server.\n");
 | 
						|
  fputs(PQerrormsg, stderr);
 | 
						|
  pqdebug("%s", PQerrormsg);
 | 
						|
 | 
						|
return(STATUS_ERROR);
 | 
						|
}
 | 
						|
#endif /* KRB5 */
 | 
						|
 | 
						|
/*
 | 
						|
 * be_recvauth -- server demux routine for incoming authentication information
 | 
						|
 */
 | 
						|
int
 | 
						|
be_recvauth(MsgType msgtype_arg, Port *port, char *username, StartupInfo* sp)
 | 
						|
{
 | 
						|
    MsgType msgtype;
 | 
						|
 | 
						|
    /* A message type of STARTUP_MSG (which once upon a time was the only
 | 
						|
       startup message type) means user wants us to choose.  "unauth" is 
 | 
						|
       what used to be the only choice, but installation may choose "hba"
 | 
						|
       instead.
 | 
						|
       */
 | 
						|
    if (msgtype_arg == STARTUP_MSG && useHostBasedAuth)
 | 
						|
        msgtype = STARTUP_HBA_MSG;
 | 
						|
    else 
 | 
						|
        msgtype = STARTUP_UNAUTH_MSG;
 | 
						|
 | 
						|
    if (!username) {
 | 
						|
        (void) sprintf(PQerrormsg,
 | 
						|
                       "be_recvauth: no user name passed\n");
 | 
						|
        fputs(PQerrormsg, stderr);
 | 
						|
        pqdebug("%s", PQerrormsg);
 | 
						|
        return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    if (!port) {
 | 
						|
        (void) sprintf(PQerrormsg,
 | 
						|
        "be_recvauth: no port structure passed\n");
 | 
						|
        fputs(PQerrormsg, stderr);
 | 
						|
        pqdebug("%s", PQerrormsg);
 | 
						|
        return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    
 | 
						|
    switch (msgtype) {
 | 
						|
    case STARTUP_KRB4_MSG:
 | 
						|
        if (!be_getauthsvc(msgtype)) {
 | 
						|
            (void) sprintf(PQerrormsg,
 | 
						|
                           "be_recvauth: krb4 authentication disallowed\n");
 | 
						|
            fputs(PQerrormsg, stderr);
 | 
						|
            pqdebug("%s", PQerrormsg);
 | 
						|
            return(STATUS_ERROR);
 | 
						|
        }
 | 
						|
	if (pg_krb4_recvauth(port->sock, &port->laddr, &port->raddr,
 | 
						|
                             username) != STATUS_OK) {
 | 
						|
            (void) sprintf(PQerrormsg,
 | 
						|
                           "be_recvauth: krb4 authentication failed\n");
 | 
						|
            fputs(PQerrormsg, stderr);
 | 
						|
            pqdebug("%s", PQerrormsg);
 | 
						|
            return(STATUS_ERROR);
 | 
						|
        }
 | 
						|
	break;
 | 
						|
    case STARTUP_KRB5_MSG:
 | 
						|
        if (!be_getauthsvc(msgtype)) {
 | 
						|
            (void) sprintf(PQerrormsg,
 | 
						|
                           "be_recvauth: krb5 authentication disallowed\n");
 | 
						|
            fputs(PQerrormsg, stderr);
 | 
						|
            pqdebug("%s", PQerrormsg);
 | 
						|
            return(STATUS_ERROR);
 | 
						|
          }
 | 
						|
        if (pg_krb5_recvauth(port->sock, &port->laddr, &port->raddr,
 | 
						|
                             username) != STATUS_OK) {
 | 
						|
            (void) sprintf(PQerrormsg,
 | 
						|
                           "be_recvauth: krb5 authentication failed\n");
 | 
						|
            fputs(PQerrormsg, stderr);
 | 
						|
            pqdebug("%s", PQerrormsg);
 | 
						|
            return(STATUS_ERROR);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    case STARTUP_UNAUTH_MSG:
 | 
						|
        if (!be_getauthsvc(msgtype)) {
 | 
						|
            (void) sprintf(PQerrormsg,
 | 
						|
                           "be_recvauth: "
 | 
						|
                           "unauthenticated connections disallowed\n");
 | 
						|
            fputs(PQerrormsg, stderr);
 | 
						|
            pqdebug("%s", PQerrormsg);
 | 
						|
            return(STATUS_ERROR);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    case STARTUP_HBA_MSG:
 | 
						|
        if (hba_recvauth(port, sp->database, sp->user, DataDir) != STATUS_OK) {
 | 
						|
            (void) sprintf(PQerrormsg,
 | 
						|
                           "be_recvauth: host-based authentication failed\n");
 | 
						|
            fputs(PQerrormsg, stderr);
 | 
						|
            pqdebug("%s", PQerrormsg);
 | 
						|
            return(STATUS_ERROR);
 | 
						|
          }
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        (void) sprintf(PQerrormsg,
 | 
						|
                       "be_recvauth: unrecognized message type: %d\n",
 | 
						|
                       msgtype);
 | 
						|
        fputs(PQerrormsg, stderr);
 | 
						|
        pqdebug("%s", PQerrormsg);
 | 
						|
        return(STATUS_ERROR);
 | 
						|
    }
 | 
						|
    return(STATUS_OK);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * be_setauthsvc -- enable/disable the authentication services currently
 | 
						|
 *		    selected for use by the backend
 | 
						|
 * be_getauthsvc -- returns whether a particular authentication system
 | 
						|
 *		    (indicated by its message type) is permitted by the
 | 
						|
 *		    current selections
 | 
						|
 *
 | 
						|
 * be_setauthsvc encodes the command-line syntax that
 | 
						|
 *	-a "<service-name>"
 | 
						|
 * enables a service, whereas
 | 
						|
 *	-a "no<service-name>"
 | 
						|
 * disables it.
 | 
						|
 */
 | 
						|
void
 | 
						|
be_setauthsvc(char *name)
 | 
						|
{
 | 
						|
    int i, j;
 | 
						|
    int turnon = 1;
 | 
						|
    
 | 
						|
    if (!name)
 | 
						|
	return;
 | 
						|
    if (!strncmp("no", name, 2)) {
 | 
						|
	turnon = 0;
 | 
						|
	name += 2;
 | 
						|
    }
 | 
						|
    if (name[0] == '\0')
 | 
						|
	return;
 | 
						|
    for (i = 0; i < n_authsvcs; ++i)
 | 
						|
	if (!strcmp(name, authsvcs[i].name)) {
 | 
						|
	    for (j = 0; j < n_authsvcs; ++j)
 | 
						|
		if (authsvcs[j].msgtype == authsvcs[i].msgtype)
 | 
						|
		    authsvcs[j].allowed = turnon;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    if (i == n_authsvcs) {
 | 
						|
	(void) sprintf(PQerrormsg,
 | 
						|
		       "be_setauthsvc: invalid name %s, ignoring...\n",
 | 
						|
		       name);
 | 
						|
	fputs(PQerrormsg, stderr);
 | 
						|
	pqdebug("%s", PQerrormsg);
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
be_getauthsvc(MsgType msgtype)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    
 | 
						|
    for (i = 0; i < n_authsvcs; ++i)
 | 
						|
	if (msgtype == authsvcs[i].msgtype)
 | 
						|
	    return(authsvcs[i].allowed);
 | 
						|
    return(0);
 | 
						|
}
 |