diff options
Diffstat (limited to 'src/backend/libpq/auth.c')
-rw-r--r-- | src/backend/libpq/auth.c | 838 |
1 files changed, 439 insertions, 399 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index abf59e25b17..ff6711d3b5c 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -1,65 +1,65 @@ /*------------------------------------------------------------------------- * * auth.c-- - * Routines to handle network authentication + * 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.14 1997/08/19 21:31:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.15 1997/09/07 04:42:09 momjian 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? + * 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. + * 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. + * 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... + * 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 */ +#include <sys/param.h> /* for MAXHOSTNAMELEN on most */ #ifndef MAXHOSTNAMELEN -#include <netdb.h> /* for MAXHOSTNAMELEN on some */ +#include <netdb.h> /* for MAXHOSTNAMELEN on some */ #endif #include <pwd.h> -#include <ctype.h> /* isspace() declaration */ +#include <ctype.h> /* isspace() declaration */ -#include <sys/types.h> /* needed by in.h on Ultrix */ +#include <sys/types.h> /* needed by in.h on Ultrix */ #include <netinet/in.h> #include <arpa/inet.h> @@ -72,19 +72,19 @@ #include <libpq/hba.h> #include <libpq/password.h> -static int be_getauthsvc(MsgType msgtype); +static int be_getauthsvc(MsgType msgtype); /*---------------------------------------------------------------- * 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)? - */ +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)? */ }; /* @@ -99,9 +99,11 @@ struct authsvc { */ #if defined(HBA) -static int useHostBasedAuth = 1; +static int useHostBasedAuth = 1; + #else -static int useHostBasedAuth = 0; +static int useHostBasedAuth = 0; + #endif #if defined(KRB4) || defined(KRB5) || defined(HBA) @@ -111,19 +113,19 @@ static int useHostBasedAuth = 0; #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 }, + {"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 }, + {"kerberos", STARTUP_KRB4_MSG, 1}, #endif - { "password", STARTUP_PASSWORD_MSG, 1 } + {"password", STARTUP_PASSWORD_MSG, 1} }; -static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc); +static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc); #ifdef KRB4 /* This has to be ifdef'd out because krb.h does exist. This needs @@ -138,11 +140,11 @@ static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc); #ifdef FRONTEND /* moves to src/libpq/fe-auth.c */ -#else /* !FRONTEND */ +#else /* !FRONTEND */ /* * pg_krb4_recvauth -- server routine to receive authentication information - * from the client + * 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 @@ -151,77 +153,82 @@ static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc); */ static int pg_krb4_recvauth(int sock, - struct sockaddr_in *laddr, - struct sockaddr_in *raddr, - char *username) + 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) { - 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)) { - 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)) { - 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); + 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) + { + 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)) + { + 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)) + { + 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 */ +#endif /* !FRONTEND */ #else static int pg_krb4_recvauth(int sock, - struct sockaddr_in *laddr, - struct sockaddr_in *raddr, - char *username) + struct sockaddr_in * laddr, + struct sockaddr_in * raddr, + char *username) { - sprintf(PQerrormsg, - "pg_krb4_recvauth: Kerberos not implemented on this " - "server.\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + sprintf(PQerrormsg, + "pg_krb4_recvauth: Kerberos not implemented on this " + "server.\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); -return(STATUS_ERROR); + return (STATUS_ERROR); } -#endif /* KRB4 */ + +#endif /* KRB4 */ #ifdef KRB5 @@ -237,37 +244,37 @@ return(STATUS_ERROR); /* * pg_an_to_ln -- return the local name corresponding to an authentication - * name + * 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. + * 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 * +static char * pg_an_to_ln(char *aname) { - char *p; - - if ((p = strchr(aname, '/')) || (p = strchr(aname, '@'))) - *p = '\0'; - return(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 */ +#else /* !FRONTEND */ /* * pg_krb5_recvauth -- server routine to receive authentication information - * from the client + * 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 + * 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 @@ -286,315 +293,348 @@ pg_an_to_ln(char *aname) */ static int pg_krb5_recvauth(int sock, - struct sockaddr_in *laddr, - struct sockaddr_in *raddr, - char *username) + 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. - */ - strcpy(servbuf, PG_KRB_SRVNAM); - *(hostp = servbuf + (sizeof(PG_KRB_SRVNAM) - 1)) = '/'; - if (gethostname(++hostp, MAXHOSTNAMELEN) < 0) - strcpy(hostp, "localhost"); - if (hostp = strchr(hostp, '.')) - *hostp = '\0'; - if (code = krb5_parse_name(servbuf, &server)) { - 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)) { - sprintf(PQerrormsg, - "pg_krb5_recvauth: Kerberos error %d in krb5_recvauth\n", - code); - com_err("pg_krb5_recvauth", code, "in krb5_recvauth"); + 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. + */ + strcpy(servbuf, PG_KRB_SRVNAM); + *(hostp = servbuf + (sizeof(PG_KRB_SRVNAM) - 1)) = '/'; + if (gethostname(++hostp, MAXHOSTNAMELEN) < 0) + strcpy(hostp, "localhost"); + if (hostp = strchr(hostp, '.')) + *hostp = '\0'; + if (code = krb5_parse_name(servbuf, &server)) + { + 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)) + { + 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); - 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))) { - sprintf(PQerrormsg, - "pg_krb5_recvauth: Kerberos error %d in krb5_unparse_name\n", - code); - com_err("pg_krb5_recvauth", code, "in krb5_unparse_name"); + + /* + * 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))) + { + 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); - return(STATUS_ERROR); - } - krb5_free_principal(client); - if (!kusername) { - 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)) { - sprintf(PQerrormsg, - "pg_krb5_recvauth: name \"%s\" != \"%s\"\n", - username, kusername); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + if (!kusername) + { + 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)) + { + 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_ERROR); - } - free(kusername); - return(STATUS_OK); + return (STATUS_OK); } -#endif /* !FRONTEND */ +#endif /* !FRONTEND */ #else static int pg_krb5_recvauth(int sock, - struct sockaddr_in *laddr, - struct sockaddr_in *raddr, - char *username) + struct sockaddr_in * laddr, + struct sockaddr_in * raddr, + char *username) { - sprintf(PQerrormsg, - "pg_krb5_recvauth: Kerberos not implemented on this " - "server.\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + sprintf(PQerrormsg, + "pg_krb5_recvauth: Kerberos not implemented on this " + "server.\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); -return(STATUS_ERROR); + return (STATUS_ERROR); } -#endif /* KRB5 */ + +#endif /* KRB5 */ static int -pg_password_recvauth(Port *port, char *database, char *DataDir) +pg_password_recvauth(Port * port, char *database, char *DataDir) { - PacketBuf buf; - char *user, *password; - - if(PacketReceive(port, &buf, BLOCKING) != STATUS_OK) { - sprintf(PQerrormsg, - "pg_password_recvauth: failed to receive authentication packet.\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return STATUS_ERROR; - } + PacketBuf buf; + char *user, + *password; + + if (PacketReceive(port, &buf, BLOCKING) != STATUS_OK) + { + sprintf(PQerrormsg, + "pg_password_recvauth: failed to receive authentication packet.\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return STATUS_ERROR; + } - user = buf.data; - password = buf.data + strlen(user) + 1; + user = buf.data; + password = buf.data + strlen(user) + 1; - return verify_password(user, password, port, database, DataDir); + return verify_password(user, password, port, database, DataDir); } /* * be_recvauth -- server demux routine for incoming authentication information */ int -be_recvauth(MsgType msgtype_arg, Port *port, char *username, StartupInfo* sp) +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) { - if(useHostBasedAuth) - msgtype = STARTUP_HBA_MSG; - else - msgtype = STARTUP_UNAUTH_MSG; - } else - msgtype = msgtype_arg; - - - if (!username) { - sprintf(PQerrormsg, - "be_recvauth: no user name passed\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); - } - if (!port) { - 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)) { - 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) { - 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)) { - 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) { - 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)) { - 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) { - sprintf(PQerrormsg, - "be_recvauth: host-based authentication failed\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); - } - break; - case STARTUP_PASSWORD_MSG: - if(!be_getauthsvc(msgtype)) { - sprintf(PQerrormsg, - "be_recvauth: " - "plaintext password authentication disallowed\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); + 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) + { + if (useHostBasedAuth) + msgtype = STARTUP_HBA_MSG; + else + msgtype = STARTUP_UNAUTH_MSG; + } + else + msgtype = msgtype_arg; + + + if (!username) + { + sprintf(PQerrormsg, + "be_recvauth: no user name passed\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); + } + if (!port) + { + sprintf(PQerrormsg, + "be_recvauth: no port structure passed\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); } - if(pg_password_recvauth(port, sp->database, DataDir) != STATUS_OK) { - /* pg_password_recvauth or lower-level routines have already set */ - /* the error message */ - return(STATUS_ERROR); + + switch (msgtype) + { + case STARTUP_KRB4_MSG: + if (!be_getauthsvc(msgtype)) + { + 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) + { + 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)) + { + 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) + { + 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)) + { + 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) + { + sprintf(PQerrormsg, + "be_recvauth: host-based authentication failed\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); + } + break; + case STARTUP_PASSWORD_MSG: + if (!be_getauthsvc(msgtype)) + { + sprintf(PQerrormsg, + "be_recvauth: " + "plaintext password authentication disallowed\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); + } + if (pg_password_recvauth(port, sp->database, DataDir) != STATUS_OK) + { + + /* + * pg_password_recvauth or lower-level routines have already + * set + */ + /* the error message */ + return (STATUS_ERROR); + } + break; + default: + sprintf(PQerrormsg, + "be_recvauth: unrecognized message type: %d\n", + msgtype); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); } - break; - default: - sprintf(PQerrormsg, - "be_recvauth: unrecognized message type: %d\n", - msgtype); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); - } - return(STATUS_OK); + return (STATUS_OK); } /* * be_setauthsvc -- enable/disable the authentication services currently - * selected for use by the backend + * 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 + * (indicated by its message type) is permitted by the + * current selections * * be_setauthsvc encodes the command-line syntax that - * -a "<service-name>" + * -a "<service-name>" * enables a service, whereas - * -a "no<service-name>" + * -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; + int i, + j; + int turnon = 1; + + if (!name) + return; + if (!strncmp("no", name, 2)) + { + turnon = 0; + name += 2; } - if (i == n_authsvcs) { - sprintf(PQerrormsg, - "be_setauthsvc: invalid name %s, ignoring...\n", - name); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - } - return; + 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) + { + sprintf(PQerrormsg, + "be_setauthsvc: invalid name %s, ignoring...\n", + name); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + } + return; } static 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); + int i; + + for (i = 0; i < n_authsvcs; ++i) + if (msgtype == authsvcs[i].msgtype) + return (authsvcs[i].allowed); + return (0); } |