]> granicus.if.org Git - postgresql/commitdiff
From: Phil Thompson <phil@river-bank.demon.co.uk>
authorMarc G. Fournier <scrappy@hub.org>
Mon, 26 Jan 1998 01:42:53 +0000 (01:42 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Mon, 26 Jan 1998 01:42:53 +0000 (01:42 +0000)
I've completed the patch to fix the protocol and authentication issues I
was discussing a couple of weeks ago.  The particular changes are:

- the protocol has a version number
- network byte order is used throughout
- the pg_hba.conf file is used to specify what method is used to
  authenticate a frontend (either password, ident, trust, reject, krb4
  or krb5)
- support for multiplexed backends is removed
- appropriate changes to man pages
- the -a switch to many programs to specify an authentication service
  no longer has any effect
- the libpq.so version number has changed to 1.1

The new backend still supports the old protocol so old interfaces won't
break.

41 files changed:
src/backend/libpq/auth.c
src/backend/libpq/be-dumpdata.c
src/backend/libpq/be-pqexec.c
src/backend/libpq/crypt.c
src/backend/libpq/hba.c
src/backend/libpq/password.c
src/backend/libpq/pg_hba.conf.sample
src/backend/libpq/pqcomm.c
src/backend/libpq/pqcomprim.c
src/backend/libpq/pqpacket.c
src/backend/postmaster/postmaster.c
src/backend/tcop/dest.c
src/backend/tcop/fastpath.c
src/backend/tcop/postgres.c
src/backend/utils/init/globals.c
src/include/c.h
src/include/libpq/auth.h
src/include/libpq/crypt.h
src/include/libpq/hba.h
src/include/libpq/libpq-be.h
src/include/libpq/libpq.h
src/include/libpq/password.h
src/include/libpq/pqcomm.h
src/interfaces/libpq/Makefile.in
src/interfaces/libpq/fe-auth.c
src/interfaces/libpq/fe-auth.h
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/fe-connect.h
src/interfaces/libpq/fe-exec.c
src/interfaces/libpq/fe-misc.c
src/interfaces/libpq/libpq-fe.h
src/man/createdb.1
src/man/createuser.1
src/man/destroydb.1
src/man/destroyuser.1
src/man/libpq.3
src/man/pg_passwd.1
src/man/pgintro.1
src/man/postgres.1
src/man/postmaster.1
src/man/psql.1

index 8aa3efca9b31377bc816e1f45f5bf493d6fc7db0..74643037288a142af5ae9c93f88c65ac42006708 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.20 1997/12/09 03:10:31 scrappy Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.21 1998/01/26 01:41:04 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
  *
  *        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 <libpq/auth.h>
 #include <libpq/libpq.h>
-#include <libpq/libpq-be.h>
 #include <libpq/hba.h>
 #include <libpq/password.h>
 #include <libpq/crypt.h>
 
-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)? */
-};
+static void sendAuthRequest(Port *port, AuthRequest areq, void (*handler)());
+static void handle_done_auth(Port *port);
+static void handle_krb4_auth(Port *port);
+static void handle_krb5_auth(Port *port);
+static void handle_password_auth(Port *port);
+static void readPasswordPacket(char *arg, PacketLen len, char *pkt);
+static void pg_passwordv0_recvauth(char *arg, PacketLen len, char *pkt);
+static int old_be_recvauth(Port *port);
+static int map_old_to_new(Port *port, UserAuth old, int status);
 
-/*
- * 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
-       {"password", STARTUP_PASSWORD_MSG, 1},
-       {"crypt", STARTUP_CRYPT_MSG, 1}
-};
-
-static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
 
 #ifdef KRB4
 /* This has to be ifdef'd out because krb.h does exist.  This needs
@@ -140,10 +62,6 @@ static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
 
 #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
@@ -154,10 +72,7 @@ static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
  * unauthenticated connections.)
  */
 static int
-pg_krb4_recvauth(int sock,
-                                struct sockaddr_in * laddr,
-                                struct sockaddr_in * raddr,
-                                char *username)
+pg_krb4_recvauth(Port *)
 {
        long            krbopts = 0;    /* one-way authentication */
        KTEXT_ST        clttkt;
@@ -170,12 +85,12 @@ pg_krb4_recvauth(int sock,
        strcpy(instance, "*");          /* don't care, but arg gets expanded
                                                                 * anyway */
        status = krb_recvauth(krbopts,
-                                                 sock,
+                                                 port->sock,
                                                  &clttkt,
                                                  PG_KRB_SRVNAM,
                                                  instance,
-                                                 raddr,
-                                                 laddr,
+                                                 &port->raddr.in,
+                                                 &port->laddr.in,
                                                  &auth_data,
                                                  PG_KRB_SRVTAB,
                                                  key_sched,
@@ -198,12 +113,11 @@ pg_krb4_recvauth(int sock,
                pqdebug("%s", PQerrormsg);
                return (STATUS_ERROR);
        }
-       if (username && *username &&
-               strncmp(username, auth_data.pname, NAMEDATALEN))
+       if (strncmp(port->user, auth_data.pname, SM_USER))
        {
                sprintf(PQerrormsg,
                                "pg_krb4_recvauth: name \"%s\" != \"%s\"\n",
-                               username,
+                               port->username,
                                auth_data.pname);
                fputs(PQerrormsg, stderr);
                pqdebug("%s", PQerrormsg);
@@ -212,14 +126,9 @@ pg_krb4_recvauth(int sock,
        return (STATUS_OK);
 }
 
-#endif                                                 /* !FRONTEND */
-
 #else
 static int
-pg_krb4_recvauth(int sock,
-                                struct sockaddr_in * laddr,
-                                struct sockaddr_in * raddr,
-                                char *username)
+pg_krb4_recvauth(Port *port)
 {
        sprintf(PQerrormsg,
                        "pg_krb4_recvauth: Kerberos not implemented on this "
@@ -267,10 +176,6 @@ pg_an_to_ln(char *aname)
        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
@@ -294,10 +199,7 @@ pg_an_to_ln(char *aname)
  * 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)
+pg_krb5_recvauth(Port *port)
 {
        char            servbuf[MAXHOSTNAMELEN + 1 +
                                                                        sizeof(PG_KRB_SRVNAM)];
@@ -334,9 +236,9 @@ pg_krb5_recvauth(int sock,
         * 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);
+       sender_addr.addrtype = port->raddr.in.sin_family;
+       sender_addr.length = sizeof(port->raddr.in.sin_addr);
+       sender_addr.contents = (krb5_octet *) & (port->raddr.in.sin_addr);
 
        if (strcmp(PG_KRB_SRVTAB, ""))
        {
@@ -344,7 +246,7 @@ pg_krb5_recvauth(int sock,
                keyprocarg = PG_KRB_SRVTAB;
        }
 
-       if (code = krb5_recvauth((krb5_pointer) & sock,
+       if (code = krb5_recvauth((krb5_pointer) & port->sock,
                                                         PG_KRB5_VERSION,
                                                         server,
                                                         &sender_addr,
@@ -390,11 +292,11 @@ pg_krb5_recvauth(int sock,
                return (STATUS_ERROR);
        }
        kusername = pg_an_to_ln(kusername);
-       if (username && strncmp(username, kusername, NAMEDATALEN))
+       if (strncmp(username, kusername, SM_USER))
        {
                sprintf(PQerrormsg,
                                "pg_krb5_recvauth: name \"%s\" != \"%s\"\n",
-                               username, kusername);
+                               port->username, kusername);
                fputs(PQerrormsg, stderr);
                pqdebug("%s", PQerrormsg);
                pfree(kusername);
@@ -404,15 +306,9 @@ pg_krb5_recvauth(int sock,
        return (STATUS_OK);
 }
 
-#endif                                                 /* !FRONTEND */
-
-
 #else
 static int
-pg_krb5_recvauth(int sock,
-                                struct sockaddr_in * laddr,
-                                struct sockaddr_in * raddr,
-                                char *username)
+pg_krb5_recvauth(Port *port)
 {
        sprintf(PQerrormsg,
                        "pg_krb5_recvauth: Kerberos not implemented on this "
@@ -425,246 +321,360 @@ pg_krb5_recvauth(int sock,
 
 #endif                                                 /* KRB5 */
 
-static int
-pg_password_recvauth(Port *port, char *database, char *DataDir)
+
+/*
+ * Handle a v0 password packet.
+ */
+
+static void pg_passwordv0_recvauth(char *arg, PacketLen len, char *pkt)
 {
-       PacketBuf       buf;
-       char       *user,
-                          *password;
+       Port *port;
+       PasswordPacketV0 *pp;
+       char *user, *password, *cp, *start;
 
-       if (PacketReceive(port, &buf, BLOCKING) != STATUS_OK)
+       port = (Port *)arg;
+       pp = (PasswordPacketV0 *)pkt;
+
+       /*
+        * The packet is supposed to comprise the user name and the password
+        * as C strings.  Be careful the check that this is the case.
+        */
+
+       user = password = NULL;
+
+       len -= sizeof (pp->unused);
+
+       cp = start = pp->data;
+
+       while (len > 0)
+       if (*cp++ == '\0')
+       {
+               if (user == NULL)
+                       user = start;
+               else
+               {
+                       password = start;
+                       break;
+               }
+
+               start = cp;
+       }
+
+       if (user == NULL || password == NULL)
        {
                sprintf(PQerrormsg,
-                               "pg_password_recvauth: failed to receive authentication packet.\n");
+                               "pg_password_recvauth: badly formed password packet.\n");
                fputs(PQerrormsg, stderr);
                pqdebug("%s", PQerrormsg);
-               return STATUS_ERROR;
+
+               auth_failed(port);
        }
+       else if (map_old_to_new(port, uaPassword,
+                               verify_password(port->auth_arg, user, password)) != STATUS_OK)
+               auth_failed(port);
+}
 
-       user = buf.data;
-       password = buf.data + strlen(user) + 1;
 
-       return verify_password(user, password, port, database, DataDir);
-}
+/*
+ * Tell the user the authentication failed, but not why.
+ */
 
-static int
-crypt_recvauth(Port *port)
+void auth_failed(Port *port)
 {
-      PacketBuf       buf;
-      char       *user,
-                         *password;
-
-      if (PacketReceive(port, &buf, BLOCKING) != STATUS_OK)
-      {
-              sprintf(PQerrormsg,
-                              "crypt_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;
-
-      return crypt_verify(port, user, password);
+       PacketSendError(&port->pktInfo, "User authentication failed");
 }
 
+
 /*
  * be_recvauth -- server demux routine for incoming authentication information
  */
-int
-be_recvauth(MsgType msgtype_arg, Port *port, char *username, StartupInfo *sp)
+void be_recvauth(Port *port)
 {
-       MsgType         msgtype;
+       AuthRequest areq;
+       void (*auth_handler)();
 
        /*
-        * 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.
+        * Get the authentication method to use for this frontend/database
+        * combination.
         */
-       if (msgtype_arg == STARTUP_MSG)
+
+       if (hba_getauthmethod(&port->raddr, port->database, port->auth_arg,
+                               &port->auth_method) != STATUS_OK)
        {
-               if (useHostBasedAuth)
-                       msgtype = STARTUP_HBA_MSG;
-               else
-                       msgtype = STARTUP_UNAUTH_MSG;
+               PacketSendError(&port->pktInfo, "Error getting authentication method");
+               return;
        }
-       else
-               msgtype = msgtype_arg;
 
+       /* Handle old style authentication. */
 
-       if (!username)
+       if (PG_PROTOCOL_MAJOR(port->proto) == 0)
        {
-               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 (old_be_recvauth(port) != STATUS_OK)
+                       auth_failed(port);
+
+               return;
        }
 
-       switch (msgtype)
+       /* Handle new style authentication. */
+
+       switch (port->auth_method)
        {
-               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, (struct sockaddr_in *) &port->laddr,
-                                                                (struct sockaddr_in *) &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, (struct sockaddr_in *) &port->laddr,
-                                                                (struct sockaddr_in *) &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;
-               case STARTUP_CRYPT_MSG:
-                       if (crypt_recvauth(port) != STATUS_OK)
-                          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);
+       case uaReject:
+               auth_failed(port);
+               return;
+       case uaKrb4:
+               areq = AUTH_REQ_KRB4;
+               auth_handler = handle_krb4_auth;
+               break;
+
+       case uaKrb5:
+               areq = AUTH_REQ_KRB5;
+               auth_handler = handle_krb5_auth;
+               break;
+
+       case uaTrust:
+               areq = AUTH_REQ_OK;
+               auth_handler = handle_done_auth;
+               break;
+
+       case uaIdent:
+               if (authident(&port->raddr.in, &port->laddr.in, port->user,
+                               port->auth_arg) != STATUS_OK)
+               {
+                       auth_failed(port);
+                       return;
+               }
+
+               areq = AUTH_REQ_OK;
+               auth_handler = handle_done_auth;
+               break;
+
+       case uaPassword:
+               areq = AUTH_REQ_PASSWORD;
+               auth_handler = handle_password_auth;
+               break;
+
+       case uaCrypt:
+               areq = AUTH_REQ_CRYPT;
+               auth_handler = handle_password_auth;
+               break;
+       }
+
+       /* Tell the frontend what we want next. */
+
+       sendAuthRequest(port, areq, auth_handler);
 }
 
 /*
- * 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.
+ * Send an authentication request packet to the frontend.
  */
-void
-be_setauthsvc(char *name)
+
+static void sendAuthRequest(Port *port, AuthRequest areq, void (*handler)())
 {
-       int                     i,
-                               j;
-       int                     turnon = 1;
+       char *dp, *sp;
+       int i;
+       uint32 net_areq;
 
-       if (!name)
-               return;
-       if (!strncmp("no", name, 2))
+       /* Convert to a byte stream. */
+
+       net_areq = htonl(areq);
+
+       dp = port->pktInfo.pkt.ar.data;
+       sp = (char *)&net_areq;
+
+       *dp++ = 'R';
+
+       for (i = 1; i <= 4; ++i)
+               *dp++ = *sp++;
+
+       /* Add the salt for encrypted passwords. */
+
+       if (areq == AUTH_REQ_CRYPT)
        {
-               turnon = 0;
-               name += 2;
+               *dp++ = port->salt[0];
+               *dp++ = port->salt[1];
+               i += 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)
+
+       PacketSendSetup(&port -> pktInfo, i, handler, (char *)port);
+}
+
+
+/*
+ * Called when we have told the front end that it is authorised.
+ */
+
+static void handle_done_auth(Port *port)
+{
+       /*
+        * Don't generate any more traffic.  This will cause the backend to
+        * start.
+        */
+
+       return;
+}
+
+
+/*
+ * Called when we have told the front end that it should use Kerberos V4
+ * authentication.
+ */
+
+static void handle_krb4_auth(Port *port)
+{
+       if (pg_krb4_recvauth(port) != STATUS_OK)
+               auth_failed(port);
+       else
+               sendAuthRequest(port, AUTH_REQ_OK, handle_done_auth);
+}
+
+
+/*
+ * Called when we have told the front end that it should use Kerberos V5
+ * authentication.
+ */
+
+static void handle_krb5_auth(Port *port)
+{
+       if (pg_krb5_recvauth(port) != STATUS_OK)
+               auth_failed(port);
+       else
+               sendAuthRequest(port, AUTH_REQ_OK, handle_done_auth);
+}
+
+
+/*
+ * Called when we have told the front end that it should use password
+ * authentication.
+ */
+
+static void handle_password_auth(Port *port)
+{
+       /* Set up the read of the password packet. */
+
+       PacketReceiveSetup(&port->pktInfo, readPasswordPacket, (char *)port);
+}
+
+
+/*
+ * Called when we have received the password packet.
+ */
+
+static void readPasswordPacket(char *arg, PacketLen len, char *pkt)
+{
+       char password[sizeof (PasswordPacket) + 1];
+       Port *port;
+
+       port = (Port *)arg;
+
+       /* Silently truncate a password that is too big. */
+
+       if (len > sizeof (PasswordPacket))
+               len = sizeof (PasswordPacket);
+               
+       StrNCpy(password, ((PasswordPacket *)pkt)->passwd, len);
+
+       /*
+        * Use the local flat password file if clear passwords are used and the
+        * file is specified.  Otherwise use the password in the pg_user table,
+        * encrypted or not.
+        */
+
+       if (port->auth_method == uaPassword && port->auth_arg[0] != '\0')
        {
-               sprintf(PQerrormsg,
-                               "be_setauthsvc: invalid name %s, ignoring...\n",
-                               name);
-               fputs(PQerrormsg, stderr);
-               pqdebug("%s", PQerrormsg);
+               if (verify_password(port->auth_arg, port->user, password) != STATUS_OK)
+                       auth_failed(port);
        }
-       return;
+       else if (crypt_verify(port, port->user, password) != STATUS_OK)
+               auth_failed(port);
+       else
+               sendAuthRequest(port, AUTH_REQ_OK, handle_done_auth);
 }
 
-static int
-be_getauthsvc(MsgType msgtype)
+
+/*
+ * Server demux routine for incoming authentication information for protocol
+ * version 0.
+ */
+static int old_be_recvauth(Port *port)
 {
-       int                     i;
+       int status;
+       MsgType msgtype = (MsgType)port->proto;
+
+       /* Handle the authentication that's offered. */
+
+       switch (msgtype)
+       {
+       case STARTUP_KRB4_MSG:
+               status = map_old_to_new(port,uaKrb4,pg_krb4_recvauth(port));
+               break;
+
+       case STARTUP_KRB5_MSG:
+               status = map_old_to_new(port,uaKrb5,pg_krb5_recvauth(port));
+               break;
+
+       case STARTUP_MSG:
+               status = map_old_to_new(port,uaTrust,STATUS_OK);
+               break;
+
+       case STARTUP_PASSWORD_MSG:
+               PacketReceiveSetup(&port->pktInfo, pg_passwordv0_recvauth,
+                                       (char *)port);
 
-       for (i = 0; i < n_authsvcs; ++i)
-               if (msgtype == authsvcs[i].msgtype)
-                       return (authsvcs[i].allowed);
-       return (0);
+               return STATUS_OK;
+
+       default:
+               fprintf(stderr, "Invalid startup message type: %u\n", msgtype);
+
+               return STATUS_OK;
+       }
+
+       return status;
+}
+
+/*
+ * The old style authentication has been done.  Modify the result of this (eg.
+ * allow the connection anyway, disallow it anyway, or use the result)
+ * depending on what authentication we really want to use.
+ */
+
+static int map_old_to_new(Port *port, UserAuth old, int status)
+{
+       switch (port->auth_method)
+       {
+       case uaCrypt:
+       case uaReject:
+               status = STATUS_ERROR;
+               break;
+
+       case uaKrb4:
+               if (old != uaKrb4)
+                       status = STATUS_ERROR;
+               break;
+
+       case uaKrb5:
+               if (old != uaKrb5)
+                       status = STATUS_ERROR;
+               break;
+
+       case uaTrust:
+               status = STATUS_OK;
+               break;
+
+       case uaIdent:
+               status = authident(&port->raddr.in, &port->laddr.in,
+                                       port->user, port->auth_arg);
+               break;
+
+       case uaPassword:
+               if (old != uaPassword)
+                       status = STATUS_ERROR;
+
+               break;
+       }
+       return status;
 }
index f34be7cdab0a8a3be34423216352fbc2771336d7..7a20e26e543a6e793e67c5b1a16a729a659e5173 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-dumpdata.c,v 1.9 1997/09/12 04:07:50 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-dumpdata.c,v 1.10 1998/01/26 01:41:05 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,7 +34,7 @@
 #include <postgres.h>
 
 #include <lib/dllist.h>
-#include <libpq/libpq-be.h>
+#include <libpq/libpq.h>
 #include <access/heapam.h>
 #include <access/htup.h>
 #include <storage/buf.h>
index 69d8675a46dcbe9046a116d559a1110642a8bacb..a63ff4316160859526857b053baab6c7b3d0e40f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.13 1998/01/07 21:03:16 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.14 1998/01/26 01:41:06 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,7 +27,7 @@
 #include <tcop/fastpath.h>
 #include <tcop/tcopprot.h>
 #include <lib/dllist.h>
-#include <libpq/libpq-be.h>
+#include <libpq/libpq.h>
 #include <fmgr.h>
 #include <utils/exc.h>
 #include <utils/builtins.h>
index 6e6555503aa4b5b1102c8becebf2dd4171645b47..7a72275bc44a750e17167f2a2f83626bac20d68d 100644 (file)
@@ -17,9 +17,6 @@
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
-#ifdef HAVE_CRYPT_H
-#include <crypt.h>
-#endif
 
 #include "postgres.h"
 #include "miscadmin.h"
 #include "storage/fd.h"
 #include "libpq/crypt.h"
 
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
 char**     pwd_cache = NULL;
 int        pwd_cache_count = 0;
 
@@ -219,6 +220,7 @@ int crypt_getloginfo(const char* user, char** passwd, char** valuntil) {
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef 0
 MsgType crypt_salt(const char* user) {
 
   char*     passwd;
@@ -237,6 +239,7 @@ MsgType crypt_salt(const char* user) {
   if (valuntil) free((void*)valuntil);
   return STARTUP_SALT_MSG;
 }
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -258,7 +261,13 @@ int crypt_verify(Port* port, const char* user, const char* pgpass) {
     return STATUS_ERROR;
   }
 
-  crypt_pwd = crypt(passwd, port->salt);
+  /*
+   * Compare with the encrypted or plain password depending on the
+   * authentication method being used for this connection.
+   */
+
+  crypt_pwd = (port->auth_method == uaCrypt ? crypt(passwd, port->salt) : passwd);
+
   if (!strcmp(pgpass, crypt_pwd)) {
     /* check here to be sure we are not past valuntil
      */
index 3390f38f9a6a666a453734eead5284cbd841ebf0..048add7771e47d55f10c10b638f77fa678a414b9 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.25 1997/12/09 03:10:38 scrappy Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.26 1998/01/26 01:41:08 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -97,84 +97,56 @@ read_through_eol(FILE *file)
 
 
 static void
-read_hba_entry2(FILE *file, enum Userauth * userauth_p, char usermap_name[],
-                         bool *error_p, bool *matches_p, bool find_password_entries)
+read_hba_entry2(FILE *file, UserAuth * userauth_p, char auth_arg[],
+                         bool *error_p)
 {
 /*--------------------------------------------------------------------------
   Read from file FILE the rest of a host record, after the mask field,
-  and return the interpretation of it as *userauth_p, usermap_name, and
+  and return the interpretation of it as *userauth_p, auth_arg, and
   *error_p.
 ---------------------------------------------------------------------------*/
        char            buf[MAX_TOKEN];
 
-       bool            userauth_valid;
-
        /* Get authentication type token. */
        next_token(file, buf, sizeof(buf));
-       userauth_valid = false;
-       if (buf[0] == '\0')
-       {
-               *error_p = true;
-       }
+
+       if (strcmp(buf, "trust") == 0)
+               *userauth_p = uaTrust;
+       else if (strcmp(buf, "ident") == 0)
+               *userauth_p = uaIdent;
+       else if (strcmp(buf, "password") == 0)
+               *userauth_p = uaPassword;
+       else if (strcmp(buf, "krb4") == 0)
+               *userauth_p = uaKrb4;
+       else if (strcmp(buf, "krb5") == 0)
+               *userauth_p = uaKrb5;
+       else if (strcmp(buf, "reject") == 0)
+               *userauth_p = uaReject;
+       else if (strcmp(buf, "crypt") == 0)
+               *userauth_p = uaCrypt;
        else
        {
-               userauth_valid = true;
-               if (strcmp(buf, "trust") == 0)
-               {
-                       *userauth_p = Trust;
-               }
-               else if (strcmp(buf, "ident") == 0)
-               {
-                       *userauth_p = Ident;
-               }
-               else if (strcmp(buf, "password") == 0)
-               {
-                       *userauth_p = Password;
-               }
-               else
-               {
-                       userauth_valid = false;
-               }
+               *error_p = true;
 
-               if ((find_password_entries && strcmp(buf, "password") == 0) ||
-                       (!find_password_entries && strcmp(buf, "password") != 0))
-               {
-                       *matches_p = true;
-               }
-               else
-               {
-                       *matches_p = false;
-               }
+               if (buf[0] != '\0')
+                       read_through_eol(file);
        }
 
-       if (!userauth_valid || !*matches_p || *error_p)
-       {
-               if (!userauth_valid)
-               {
-                       *error_p = true;
-               }
-               read_through_eol(file);
-       }
-       else
+       if (!*error_p)
        {
-               /* Get the map name token, if any */
+               /* Get the authentication argument token, if any */
                next_token(file, buf, sizeof(buf));
                if (buf[0] == '\0')
-               {
-                       *error_p = false;
-                       usermap_name[0] = '\0';
-               }
+                       auth_arg[0] = '\0';
                else
                {
-                       strncpy(usermap_name, buf, USERMAP_NAME_SIZE);
+                       StrNCpy(auth_arg, buf, MAX_AUTH_ARG - 1);
                        next_token(file, buf, sizeof(buf));
                        if (buf[0] != '\0')
                        {
                                *error_p = true;
                                read_through_eol(file);
                        }
-                       else
-                               *error_p = false;
                }
        }
 }
@@ -182,139 +154,150 @@ read_hba_entry2(FILE *file, enum Userauth * userauth_p, char usermap_name[],
 
 
 static void
-process_hba_record(FILE *file,
-                                  const struct in_addr ip_addr, const char database[],
+process_hba_record(FILE *file, SockAddr *raddr, const char database[],
                                   bool *matches_p, bool *error_p,
-                                  enum Userauth * userauth_p, char usermap_name[],
-                                  bool find_password_entries)
+                                  UserAuth * userauth_p, char auth_arg[])
 {
 /*---------------------------------------------------------------------------
   Process the non-comment record in the config file that is next on the file.
-  See if it applies to a connection to a host with IP address "ip_addr"
+  See if it applies to a connection to a host with IP address "*raddr"
   to a database named "database[]".  If so, return *matches_p true
-  and *userauth_p and usermap_name[] as the values from the entry.
-  If not, return matches_p false.  If the record has a syntax error,
+  and *userauth_p and auth_arg[] as the values from the entry.
+  If not, leave *matches_p as it was.  If the record has a syntax error,
   return *error_p true, after issuing a message to stderr.     If no error,
   leave *error_p as it was.
 ---------------------------------------------------------------------------*/
-       char            buf[MAX_TOKEN]; /* A token from the record */
+       char db[MAX_TOKEN], buf[MAX_TOKEN];
+
+       /* Read the record type field. */
 
-       /* Read the record type field */
        next_token(file, buf, sizeof(buf));
+
        if (buf[0] == '\0')
-               *matches_p = false;
-       else
+               return;
+
+       /* Check the record type. */
+
+       if (strcmp(buf, "local") == 0)
+       {
+               /* Get the database. */
+
+               next_token(file, db, sizeof(db));
+
+               if (db[0] == '\0')
+                       goto syntax;
+
+               /* Read the rest of the line. */
+
+               read_hba_entry2(file, userauth_p, auth_arg, error_p);
+
+               /*
+                * For now, disallow methods that need AF_INET sockets to work.
+                */
+
+               if (!*error_p &&
+                               (*userauth_p == uaIdent ||
+                                *userauth_p == uaKrb4 ||
+                                *userauth_p == uaKrb5))
+                       *error_p = true;
+
+               if (*error_p)
+                       goto syntax;
+
+               /*
+                * If this record isn't for our database, or this is the wrong
+                * sort of connection, ignore it.
+                */
+
+               if ((strcmp(db, database) != 0 && strcmp(db, "all") != 0) ||
+                               raddr->sa.sa_family != AF_UNIX)
+                       return;
+       }
+       else if (strcmp(buf, "host") == 0)
        {
-               /* if this isn't a "host" record, it can't match. */
-               if (strcmp(buf, "host") != 0)
+               struct in_addr file_ip_addr, mask;
+
+               /* Get the database. */
+
+               next_token(file, db, sizeof(db));
+
+               if (db[0] == '\0')
+                       goto syntax;
+
+               /* Read the IP address field. */
+
+               next_token(file, buf, sizeof(buf));
+
+               if (buf[0] == '\0')
+                       goto syntax;
+
+               /* Remember the IP address field and go get mask field. */
+
+               if (!inet_aton(buf, &file_ip_addr))
                {
-                       *matches_p = false;
                        read_through_eol(file);
+                       goto syntax;
                }
-               else
+
+               /* Read the mask field. */
+
+               next_token(file, buf, sizeof(buf));
+
+               if (buf[0] == '\0')
+                       goto syntax;
+
+               if (!inet_aton(buf, &mask))
                {
-                       /* It's a "host" record.  Read the database name field. */
-                       next_token(file, buf, sizeof(buf));
-                       if (buf[0] == '\0')
-                               *matches_p = false;
-                       else
-                       {
-                               /* If this record isn't for our database, ignore it. */
-                               if (strcmp(buf, database) != 0 && strcmp(buf, "all") != 0)
-                               {
-                                       *matches_p = false;
-                                       read_through_eol(file);
-                               }
-                               else
-                               {
-                                       /* Read the IP address field */
-                                       next_token(file, buf, sizeof(buf));
-                                       if (buf[0] == '\0')
-                                               *matches_p = false;
-                                       else
-                                       {
-                                               int                     valid;          /* Field is valid dotted
-                                                                                                * decimal */
-
-                                               /*
-                                                * Remember the IP address field and go get mask
-                                                * field
-                                                */
-                                               struct in_addr file_ip_addr;    /* IP address field
-                                                                                                                * value */
-
-                                               valid = inet_aton(buf, &file_ip_addr);
-                                               if (!valid)
-                                               {
-                                                       *matches_p = false;
-                                                       read_through_eol(file);
-                                               }
-                                               else
-                                               {
-                                                       /* Read the mask field */
-                                                       next_token(file, buf, sizeof(buf));
-                                                       if (buf[0] == '\0')
-                                                               *matches_p = false;
-                                                       else
-                                                       {
-                                                               struct in_addr mask;
-
-                                                               /*
-                                                                * Got mask.  Now see if this record is
-                                                                * for our host.
-                                                                */
-                                                               valid = inet_aton(buf, &mask);
-                                                               if (!valid)
-                                                               {
-                                                                       *matches_p = false;
-                                                                       read_through_eol(file);
-                                                               }
-                                                               else
-                                                               {
-                                                                       if (((file_ip_addr.s_addr ^ ip_addr.s_addr) & mask.s_addr)
-                                                                               != 0x0000)
-                                                                       {
-                                                                               *matches_p = false;
-                                                                               read_through_eol(file);
-                                                                       }
-                                                                       else
-                                                                       {
-
-                                                                               /*
-                                                                                * This is the record we're
-                                                                                * looking for.  Read the rest of
-                                                                                * the info from it.
-                                                                                */
-                                                                               read_hba_entry2(file, userauth_p, usermap_name,
-                                                                                                               error_p, matches_p, find_password_entries);
-                                                                               if (*error_p)
-                                                                               {
-                                                                                       sprintf(PQerrormsg,
-                                                                                                       "process_hba_record: invalid syntax in "
-                                                                                                       "hba config file "
-                                                                                                       "for host record for IP address %s\n",
-                                                                                               inet_ntoa(file_ip_addr));
-                                                                                       fputs(PQerrormsg, stderr);
-                                                                                       pqdebug("%s", PQerrormsg);
-                                                                               }
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
+                       read_through_eol(file);
+                       goto syntax;
                }
+
+               /*
+                * This is the record we're looking for.  Read the rest of the
+                * info from it.
+                */
+
+               read_hba_entry2(file, userauth_p, auth_arg, error_p);
+
+               if (*error_p)
+                       goto syntax;
+
+               /*
+                * If this record isn't for our database, or this is the wrong
+                * sort of connection, ignore it.
+                */
+
+               if ((strcmp(db, database) != 0 && strcmp(db, "all") != 0) ||
+                       raddr->sa.sa_family != AF_INET ||
+                       ((file_ip_addr.s_addr ^ raddr->in.sin_addr.s_addr) & mask.s_addr) != 0x0000)
+                       return;
        }
+       else
+       {
+               read_through_eol(file);
+               goto syntax;
+       }
+
+       *matches_p = true;
+
+       return;
+
+syntax:
+       sprintf(PQerrormsg,
+               "process_hba_record: invalid syntax in pg_hba.conf file\n");
+
+       fputs(PQerrormsg, stderr);
+       pqdebug("%s", PQerrormsg);
+
+       *error_p = true;
 }
 
 
 
 static void
-process_open_config_file(FILE *file,
-                                        const struct in_addr ip_addr, const char database[],
-                                                bool *host_ok_p, enum Userauth * userauth_p,
-                                                char usermap_name[], bool find_password_entries)
+process_open_config_file(FILE *file, SockAddr *raddr, const char database[],
+                               bool *host_ok_p, UserAuth * userauth_p,
+                               char auth_arg[])
 {
 /*---------------------------------------------------------------------------
   This function does the same thing as find_hba_entry, only with
@@ -348,36 +331,26 @@ process_open_config_file(FILE *file,
                                read_through_eol(file);
                        else
                        {
-                               process_hba_record(file, ip_addr, database,
-                                                 &found_entry, &error, userauth_p, usermap_name,
-                                                                  find_password_entries);
+                               process_hba_record(file, raddr, database,
+                                                 &found_entry, &error, userauth_p, auth_arg);
                        }
                }
        }
-       if (found_entry)
-       {
-               if (error)
-                       *host_ok_p = false;
-               else
-                       *host_ok_p = true;
-       }
-       else
-               *host_ok_p = false;
+
+       if (found_entry && !error)
+               *host_ok_p = true;
 }
 
 
 
-void
-find_hba_entry(const char DataDir[], const struct in_addr ip_addr,
-                          const char database[],
-                          bool *host_ok_p, enum Userauth * userauth_p,
-                          char usermap_name[], bool find_password_entries)
+static void
+find_hba_entry(SockAddr *raddr, const char database[], bool *host_ok_p,
+               UserAuth * userauth_p, char auth_arg[])
 {
 /*--------------------------------------------------------------------------
   Read the config file and find an entry that allows connection from
-  host "ip_addr" to database "database".  If not found, return
-  *host_ok_p == false. If found, return *userauth_p and *usermap_name
-  representing the contents of that entry.
+  host "*raddr" to database "database".  If found, return *host_ok_p == true
+  and *userauth_p and *auth_arg representing the contents of that entry.
 
   When a record has invalid syntax, we either ignore it or reject the
   connection (depending on where it's invalid).  No message or anything.
@@ -436,8 +409,6 @@ find_hba_entry(const char DataDir[], const struct in_addr ip_addr,
                {
                        /* The open of the config file failed.  */
 
-                       *host_ok_p = false;
-
                        sprintf(PQerrormsg,
                                 "find_hba_entry: Host-based authentication config file "
                                "does not exist or permissions are not setup correctly! "
@@ -448,8 +419,8 @@ find_hba_entry(const char DataDir[], const struct in_addr ip_addr,
                }
                else
                {
-                       process_open_config_file(file, ip_addr, database, host_ok_p, userauth_p,
-                                                                        usermap_name, find_password_entries);
+                       process_open_config_file(file, raddr, database, host_ok_p, userauth_p,
+                                                                        auth_arg);
                        FreeFile(file);
                }
                pfree(conf_file);
@@ -754,8 +725,7 @@ verify_against_open_usermap(FILE *file,
 
 
 static void
-verify_against_usermap(const char DataDir[],
-                                          const char pguser[],
+verify_against_usermap(const char pguser[],
                                           const char ident_username[],
                                           const char usermap_name[],
                                           bool *checks_out_p)
@@ -834,20 +804,20 @@ verify_against_usermap(const char DataDir[],
 
 
 
-static void
-authident(const char DataDir[],
-                 const Port port, const char postgres_username[],
-                 const char usermap_name[],
-                 bool *authentic_p)
+int
+authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr,
+                 const char postgres_username[],
+                 const char auth_arg[])
 {
 /*---------------------------------------------------------------------------
   Talk to the ident server on the remote host and find out who owns the
   connection described by "port".  Then look in the usermap file under
-  the usermap usermap_name[] and see if that user is equivalent to
+  the usermap auth_arg[] and see if that user is equivalent to
   Postgres user user[].
 
-  Return *authentic_p true iff yes.
+  Return STATUS_OK if yes.
 ---------------------------------------------------------------------------*/
+       bool            checks_out;
        bool            ident_failed;
 
        /* We were unable to get ident to give us a username */
@@ -855,120 +825,35 @@ authident(const char DataDir[],
 
        /* The username returned by ident */
 
-       ident(port.raddr.in.sin_addr, port.laddr.in.sin_addr,
-                 port.raddr.in.sin_port, port.laddr.in.sin_port,
+       ident(raddr->sin_addr, laddr->sin_addr,
+                 raddr->sin_port, laddr->sin_port,
                  &ident_failed, ident_username);
 
        if (ident_failed)
-               *authentic_p = false;
-       else
-       {
-               bool            checks_out;
+               return STATUS_ERROR;
 
-               verify_against_usermap(DataDir,
-                                                postgres_username, ident_username, usermap_name,
+       verify_against_usermap(postgres_username, ident_username, auth_arg,
                                                           &checks_out);
-               if (checks_out)
-                       *authentic_p = true;
-               else
-                       *authentic_p = false;
-       }
+
+       return (checks_out ? STATUS_OK : STATUS_ERROR);
 }
 
 
 
 extern int
-hba_recvauth(const Port *port, const char database[], const char user[],
-                        const char DataDir[])
+hba_getauthmethod(SockAddr *raddr, char *database, char *auth_arg,
+                       UserAuth *auth_method)
 {
 /*---------------------------------------------------------------------------
-  Determine if the TCP connection described by "port" is with someone
-  allowed to act as user "user" and access database "database".  Return
-  STATUS_OK if yes; STATUS_ERROR if not.
+  Determine what authentication method should be used when accessing database
+  "database" from frontend "raddr".  Return the method, an optional argument,
+  and STATUS_OK.
 ----------------------------------------------------------------------------*/
        bool            host_ok;
 
-       /*
-        * There's an entry for this database and remote host in the pg_hba
-        * file
-        */
-       char            usermap_name[USERMAP_NAME_SIZE + 1];
-
-       /*
-        * The name of the map pg_hba specifies for this connection (or
-        * special value "SAMEUSER")
-        */
-       enum Userauth userauth;
-
-       /*
-        * The type of user authentication pg_hba specifies for this
-        * connection
-        */
-       int                     retvalue;
-
-       /* UNIX socket always OK, for now */
-       if (port->raddr.in.sin_family == AF_UNIX)
-               return STATUS_OK;
-       /* Our eventual return value */
-
-
-       find_hba_entry(DataDir, port->raddr.in.sin_addr, database,
-                                  &host_ok, &userauth, usermap_name,
-                                  false                /* don't find password entries of type
-                                          'password' */ );
+       host_ok = false;
 
-       if (!host_ok)
-               retvalue = STATUS_ERROR;
-       else
-       {
-               switch (userauth)
-               {
-                       case Trust:
-                               retvalue = STATUS_OK;
-                               break;
-                               case Ident:
-                               {
-
-                                       /*
-                                        * Here's where we need to call up ident and
-                                        * authenticate the user
-                                        */
-
-                                       bool            authentic;              /* He is who he says he
-                                                                                                * is. */
-
-                                                               authident(DataDir, *port, user, usermap_name, &authentic);
-
-                                       if                      (authentic)
-                                                                       retvalue = STATUS_OK;
-                                       else
-                                                                       retvalue = STATUS_ERROR;
-                               }
-                                                       break;
+       find_hba_entry(raddr, database, &host_ok, auth_method, auth_arg);
 
-                       default:
-                               retvalue = STATUS_ERROR;
-                               Assert(false);
-               }
-       }
-       return (retvalue);
+       return (host_ok ? STATUS_OK : STATUS_ERROR);
 }
-
-
-/*----------------------------------------------------------------
- * This version of hba was written by Bryan Henderson
- * in September 1996 for Release 6.0.  It changed the format of the
- * hba file and added ident function.
- *
- * Here are some notes about the original host based authentication
- * the preceded this one.
- *
- * based on the securelib package originally written by William
- * LeFebvre, EECS Department, Northwestern University
- * (phil@eecs.nwu.edu) - orginal configuration file code handling
- * by Sam Horrocks (sam@ics.uci.edu)
- *
- * modified and adapted for use with Postgres95 by Paul Fisher
- * (pnfisher@unity.ncsu.edu)
- *
- -----------------------------------------------------------------*/
index 8f26597f6a463bc7412ea1c45686eda8cb1f208e..c77b065e336887edfbb00f137107e774b6ed0a07 100644 (file)
@@ -1,6 +1,6 @@
 #include <postgres.h>
+#include <miscadmin.h>
 #include <libpq/password.h>
-#include <libpq/hba.h>
 #include <libpq/libpq.h>
 #include <storage/fd.h>
 #include <string.h>
 #endif
 
 int
-verify_password(char *user, char *password, Port *port,
-                               char *database, char *DataDir)
+verify_password(char *auth_arg, char *user, char *password)
 {
-       bool            host_ok;
-       enum Userauth userauth;
-       char            pw_file_name[PWFILE_NAME_SIZE + 1];
+       char    *pw_file_fullname;
+       FILE    *pw_file;
 
-       char       *pw_file_fullname;
-       FILE       *pw_file;
-
-       char            pw_file_line[255];
-       char       *p,
-                          *test_user,
-                          *test_pw;
-
-       find_hba_entry(DataDir, port->raddr.in.sin_addr, database,
-                                  &host_ok, &userauth, pw_file_name, true);
-
-       if (!host_ok)
-       {
-               sprintf(PQerrormsg,
-                  "verify_password: couldn't find entry for connecting host\n");
-               fputs(PQerrormsg, stderr);
-               pqdebug("%s", PQerrormsg);
-               return STATUS_ERROR;
-       }
-
-       if (userauth != Password)
-       {
-               sprintf(PQerrormsg,
-                               "verify_password: couldn't find entry of type 'password' "
-                               "for this host\n");
-               fputs(PQerrormsg, stderr);
-               pqdebug("%s", PQerrormsg);
-               return STATUS_ERROR;
-       }
-
-       if (!pw_file_name || pw_file_name[0] == '\0')
-       {
-               sprintf(PQerrormsg,
-                               "verify_password: no password file specified\n");
-               fputs(PQerrormsg, stderr);
-               pqdebug("%s", PQerrormsg);
-               return STATUS_ERROR;
-       }
-
-       pw_file_fullname = (char *) palloc(strlen(DataDir) + strlen(pw_file_name) + 2);
+       pw_file_fullname = (char *) palloc(strlen(DataDir) + strlen(auth_arg) + 2);
        strcpy(pw_file_fullname, DataDir);
        strcat(pw_file_fullname, "/");
-       strcat(pw_file_fullname, pw_file_name);
+       strcat(pw_file_fullname, auth_arg);
 
        pw_file = AllocateFile(pw_file_fullname, "r");
        if (!pw_file)
@@ -69,12 +28,17 @@ verify_password(char *user, char *password, Port *port,
                                pw_file_fullname);
                fputs(PQerrormsg, stderr);
                pqdebug("%s", PQerrormsg);
+
+               pfree(pw_file_fullname);
+
                return STATUS_ERROR;
        }
 
        while (!feof(pw_file))
        {
-               fgets(pw_file_line, 255, pw_file);
+               char pw_file_line[255], *p, *test_user, *test_pw;
+
+               fgets(pw_file_line, sizeof (pw_file_line), pw_file);
                p = pw_file_line;
 
                test_user = strtok(p, ":");
@@ -97,6 +61,9 @@ verify_password(char *user, char *password, Port *port,
                        if (strcmp(crypt(password, test_pw), test_pw) == 0)
                        {
                                /* it matched. */
+
+                               pfree(pw_file_fullname);
+
                                return STATUS_OK;
                        }
 
@@ -105,6 +72,9 @@ verify_password(char *user, char *password, Port *port,
                                        user);
                        fputs(PQerrormsg, stderr);
                        pqdebug("%s", PQerrormsg);
+
+                       pfree(pw_file_fullname);
+
                        return STATUS_ERROR;
                }
        }
@@ -114,5 +84,8 @@ verify_password(char *user, char *password, Port *port,
                        user);
        fputs(PQerrormsg, stderr);
        pqdebug("%s", PQerrormsg);
+
+       pfree(pw_file_fullname);
+
        return STATUS_ERROR;
 }
index bb0d34f4019556ce6920fbe7f0e58c480b8f7ff2..c746c752e47b5b886088cc70e22d9815d7a35b11 100644 (file)
@@ -4,6 +4,7 @@
 # 
 # This file controls what hosts are allowed to connect to what databases
 # and specifies some options on how users on a particular host are identified.
+# It is read each time a host tries to make a connection to a database.
 # 
 # Each line (terminated by a newline character) is a record.  A record cannot
 # be continued across two lines.
 # Record type "host"
 # ------------------
 # 
-# This record identifies a set of hosts that are permitted to connect to
-# databases.  No hosts are permitted to connect except as specified by a
-# "host" record.
+# This record identifies a set of network hosts that are permitted to connect
+# to databases.  No network hosts are permitted to connect except as specified
+# by a "host" record.  See the record type "local" to specify permitted
+# connections using UNIX sockets.
 #
 # Format:
 # 
-#   host DBNAME IP_ADDRESS ADDRESS_MASK USERAUTH [MAP]
+#   host DBNAME IP_ADDRESS ADDRESS_MASK USERAUTH [AUTH_ARGUMENT]
 # 
 # DBNAME is the name of a Postgres database, or "all" to indicate all 
 # databases.
 # under the Postgres username he supplies in his connection parameters.
 #
 #   ident:  Authentication is done by the ident server on the remote
-#           host, via the ident (RFC 1413) protocol.
+#           host, via the ident (RFC 1413) protocol.  AUTH_ARGUMENT, if
+#           specified, is a map name to be found in the pg_ident.conf file.
+#           That table maps from ident usernames to Postgres usernames.  The
+#           special map name "sameuser" indicates an implied map (not found
+#           in pg_ident.conf) that maps every ident username to the identical
+#           Postgres username.
 #
 #   trust:  No authentication is done.  Trust that the user has the 
 #           authority to user whatever username he says he does.
 #           Before Postgres Version 6, all authentication was this way.
 #
-# MAP is the name of a map that matches an authenticated principal with
-# a Postgres username.  If USERNAME is "trust", this value is ignored and
-# may be absent.
+#   reject: Reject the connection.
 #
-# In the case of USERAUTH=ident, this is a map name to be found in the 
-# pg_ident.conf file.  That table maps from ident usernames to Postgres 
-# usernames.  The special map name "sameuser" indicates an implied map
-# (not found in pg_ident.conf) that maps every ident username to the identical
-# Postgres username.
+#   password:  Authentication is done by matching a password supplied in clear
+#             by the host.  If AUTH_ARGUMENT is specified then the password is
+#             compared with the user's entry in that file (in the $PGDATA
+#             directory).  See pg_passwd(1).  If it is omitted then the
+#             password is compared with the user's entry in the pg_user table.
+#
+#   crypt:  Authentication is done by matching an encrypted password supplied
+#          by the host with that held for the user in the pg_user table.
+#
+#   krb4:   Kerberos V4 authentication is used.
+#
+#   krb5:   Kerberos V5 authentication is used.
 
+# Record type "local"
+# ------------------
 # 
+# This record identifies the authentication to use when connecting to a
+# particular database via a local UNIX socket.
+#
+# Format:
+# 
+#   local DBNAME USERAUTH [AUTH_ARGUMENT]
+#
+# The format is the same as that of the "host" record type except that the
+# IP_ADDRESS and ADDRESS_MASK are omitted and the "ident", "krb4" and "krb5"
+# values of USERAUTH are no allowed.
+
 # For backwards compatibility, PostgreSQL also accepts pre-Version 6 records,
 # which look like:
 # 
 #   all         127.0.0.1    0.0.0.0
-# 
-#
 
 # TYPE       DATABASE    IP_ADDRESS    MASK              USERAUTH  MAP
  
-host         all         127.0.0.1     255.255.255.255   trust     
+#host         all         127.0.0.1     255.255.255.255   trust     
  
 # The above allows any user on the local system to connect to any database
 # under any username.
@@ -86,10 +109,11 @@ host         all         127.0.0.1     255.255.255.255   trust
 # connect to database template1 as the same username that ident on that host
 # identifies him as (typically his Unix username).  
 
+#host         all        192.168.0.1   255.255.255.255   reject
 #host         all        0.0.0.0       0.0.0.0           trust
 
-# The above would allow anyone anywhere to connect to any database under
-# any username.
+# The above would allow anyone anywhere except from 192.168.0.1 to connect to
+# any database under any username.
 
 #host         all        192.168.0.0  255.255.255.0      ident     omicron
 #
index 8014ae14f82b42bd9f62ab2f0aba2f29bf9ad15b..2b4e25f87369420a79c58065fdabfbb55834bf26 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.34 1998/01/25 05:13:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.35 1998/01/26 01:41:11 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -43,6 +43,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
@@ -269,28 +270,6 @@ int
 pq_getnchar(char *s, int off, int maxlen)
 {
        return pqGetNBytes(s + off, maxlen, Pfin);
-
-#if 0
-       int                     c = '\0';
-
-       if (Pfin == (FILE *) NULL)
-       {
-/*             elog(DEBUG, "Input descriptor is null"); */
-               return (EOF);
-       }
-
-       s += off;
-       while (maxlen-- && (c = pq_getc(Pfin)) != EOF)
-               *s++ = c;
-
-       /* -----------------
-        *         If EOF reached let caller know
-        * -----------------
-        */
-       if (c == EOF)
-               return (EOF);
-       return (!EOF);
-#endif
 }
 
 /* --------------------------------
@@ -591,11 +570,7 @@ do_unlink()
 int
 StreamServerPort(char *hostName, short portName, int *fdP)
 {
-       union
-       {
-               struct sockaddr_in in;
-               struct sockaddr_un un;
-       }                       saddr;
+       SockAddr saddr;
        int                     fd,
                                err,
                                family;
@@ -624,20 +599,19 @@ StreamServerPort(char *hostName, short portName, int *fdP)
                return (STATUS_ERROR);
        }
        bzero(&saddr, sizeof(saddr));
+       saddr.sa.sa_family = family;
        if (family == AF_UNIX)
        {
-               saddr.un.sun_family = family;
                len = UNIXSOCK_PATH(saddr.un, portName);
                strcpy(sock_path, saddr.un.sun_path);
        }
        else
        {
-               saddr.in.sin_family = family;
                saddr.in.sin_addr.s_addr = htonl(INADDR_ANY);
                saddr.in.sin_port = htons(portName);
-               len = sizeof saddr.in;
+               len = sizeof (struct sockaddr_in);
        }
-       err = bind(fd, (struct sockaddr *) & saddr, len);
+       err = bind(fd, &saddr.sa, len);
        if (err < 0)
        {
          sprintf(PQerrormsg,
@@ -685,7 +659,7 @@ StreamConnection(int server_fd, Port *port)
 {
        int                     len,
                                addrlen;
-       int                     family = port->raddr.in.sin_family;
+       int                     family = port->raddr.sa.sa_family;
 
        /* accept connection (and fill in the client (remote) address) */
        len = family == AF_INET ?
@@ -726,8 +700,6 @@ StreamConnection(int server_fd, Port *port)
                }
        }
 
-       port->mask = 1 << port->sock;
-
        /* reset to non-blocking */
        fcntl(port->sock, F_SETFL, 1);
 
@@ -788,7 +760,7 @@ StreamOpen(char *hostName, short portName, Port *port)
                len = UNIXSOCK_PATH(port->raddr.un, portName);
        }
        /* connect to the server */
-       if ((port->sock = socket(port->raddr.in.sin_family, SOCK_STREAM, 0)) < 0)
+       if ((port->sock = socket(port->raddr.sa.sa_family, SOCK_STREAM, 0)) < 0)
        {
                sprintf(PQerrormsg,
                                "FATAL: StreamOpen: socket() failed: errno=%d\n",
@@ -797,7 +769,7 @@ StreamOpen(char *hostName, short portName, Port *port)
                pqdebug("%s", PQerrormsg);
                return (STATUS_ERROR);
        }
-       err = connect(port->sock, (struct sockaddr *) & port->raddr, len);
+       err = connect(port->sock, &port->raddr.sa, len);
        if (err < 0)
        {
                sprintf(PQerrormsg,
@@ -809,8 +781,7 @@ StreamOpen(char *hostName, short portName, Port *port)
        }
 
        /* fill in the client address */
-       if (getsockname(port->sock, (struct sockaddr *) & port->laddr,
-                                       &len) < 0)
+       if (getsockname(port->sock, &port->laddr.sa, &len) < 0)
        {
                sprintf(PQerrormsg,
                                "FATAL: StreamOpen: getsockname() failed: errno=%d\n",
@@ -822,32 +793,3 @@ StreamOpen(char *hostName, short portName, Port *port)
 
        return (STATUS_OK);
 }
-
-static char *authentication_type_name[] = {
-       0, 0, 0, 0, 0, 0, 0,
-       "the default authentication type",
-       0, 0,
-       "Kerberos v4",
-       "Kerberos v5",
-       "host-based authentication",
-       "unauthenication",
-       "plaintext password authentication"
-};
-
-char      *
-name_of_authentication_type(int type)
-{
-       char       *result = 0;
-
-       if (type >= 1 && type <= LAST_AUTHENTICATION_TYPE)
-       {
-               result = authentication_type_name[type];
-       }
-
-       if (result == 0)
-       {
-               result = "<unknown authentication type>";
-       }
-
-       return result;
-}
index 53742190f3e421cdc09d9b85b22f3f636221bcdd..0dd46d9205a0fb82ab11eb0636ceb2881cc61ce6 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
+#include <netinet/in.h>
 
 #include "postgres.h"
 #include "libpq/pqcomm.h"
 
-#ifdef           HAVE_ENDIAN_H
-#include       <endian.h>
-#endif
-
 
-/* --------------------------------------------------------------------- */
-/* These definitions for ntoh/hton are the other way around from the
- *     default system definitions, so we roll our own here.
+/*
+ * The backend supports the old little endian byte order and the current
+ * network byte order.
  */
 
+#ifndef FRONTEND
+
+#include "libpq/libpq-be.h"
+
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#endif
+
 #ifndef BYTE_ORDER
 #error BYTE_ORDER must be defined as LITTLE_ENDIAN, BIG_ENDIAN or PDP_ENDIAN
 #endif
 
 #if BYTE_ORDER == LITTLE_ENDIAN
-#define ntoh_s(n) n
-#define ntoh_l(n) n
-#define hton_s(n) n
-#define hton_l(n) n
-#else                                                  /* BYTE_ORDER != LITTLE_ENDIAN */
+
+#define ntoh_s(n)      n
+#define ntoh_l(n)      n
+#define hton_s(n)      n
+#define hton_l(n)      n
+
+#else
 #if BYTE_ORDER == BIG_ENDIAN
-#define ntoh_s(n) (u_short)(((u_char *)&n)[1] << 8 \
-                                                         | ((u_char *)&n)[0])
-#define ntoh_l(n) (uint32) (((u_char *)&n)[3] << 24 \
-                                                         | ((u_char *)&n)[2] << 16 \
-                                                         | ((u_char *)&n)[1] <<  8 \
-                                                         | ((u_char *)&n)[0])
-#define hton_s(n) (ntoh_s(n))
-#define hton_l(n) (ntoh_l(n))
+
+#define ntoh_s(n)      (uint16)(((u_char *)&n)[1] << 8 \
+                         | ((u_char *)&n)[0])
+#define ntoh_l(n)      (uint32)(((u_char *)&n)[3] << 24 \
+                         | ((u_char *)&n)[2] << 16 \
+                         | ((u_char *)&n)[1] <<  8 \
+                         | ((u_char *)&n)[0])
+#define hton_s(n)      (ntoh_s(n))
+#define hton_l(n)      (ntoh_l(n))
+
 #else
-/* BYTE_ORDER != BIG_ENDIAN */
 #if BYTE_ORDER == PDP_ENDIAN
+
 #error PDP_ENDIAN macros not written yet
+
 #else
-/* BYTE_ORDER !=  anything known */
+
 #error BYTE_ORDER not defined as anything understood
-#endif                                                 /* BYTE_ORDER == PDP_ENDIAN */
-#endif                                                 /* BYTE_ORDER == BIG_ENDIAN */
-#endif                                                 /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#endif
+#endif
+#endif
+
+#endif
+
 
 /* --------------------------------------------------------------------- */
 int
 pqPutShort(int integer, FILE *f)
 {
-       int                     retval = 0;
-       u_short         n,
-                               s;
+       uint16 n;
+
+#ifdef FRONTEND
+       n = htons((uint16)integer);
+#else
+       n = ((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? hton_s(integer) : htons((uint16)integer));
+#endif
 
-       s = integer;
-       n = hton_s(s);
-       if (fwrite(&n, sizeof(u_short), 1, f) != 1)
-               retval = EOF;
+       if (fwrite(&n, 2, 1, f) != 1)
+               return EOF;
 
-       return retval;
+       return 0;
 }
 
 /* --------------------------------------------------------------------- */
 int
 pqPutLong(int integer, FILE *f)
 {
-       int                     retval = 0;
-       uint32          n;
+       uint32 n;
 
-       n = hton_l(integer);
-       if (fwrite(&n, sizeof(uint32), 1, f) != 1)
-               retval = EOF;
+#ifdef FRONTEND
+       n = htonl((uint32)integer);
+#else
+       n = ((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? hton_l(integer) : htonl((uint32)integer));
+#endif
 
-       return retval;
+       if (fwrite(&n, 4, 1, f) != 1)
+               return EOF;
+
+       return 0;
 }
 
 /* --------------------------------------------------------------------- */
 int
 pqGetShort(int *result, FILE *f)
 {
-       int                     retval = 0;
-       u_short         n;
+       uint16 n;
 
-       if (fread(&n, sizeof(u_short), 1, f) != 1)
-               retval = EOF;
+       if (fread(&n, 2, 1, f) != 1)
+               return EOF;
+
+#ifdef FRONTEND
+       *result = (int)ntohs(n);
+#else
+       *result = (int)((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? ntoh_s(n) : ntohs(n));
+#endif
 
-       *result = ntoh_s(n);
-       return retval;
+       return 0;
 }
 
 /* --------------------------------------------------------------------- */
 int
 pqGetLong(int *result, FILE *f)
 {
-       int                     retval = 0;
-       uint32          n;
+       uint32 n;
 
-       if (fread(&n, sizeof(uint32), 1, f) != 1)
-               retval = EOF;
+       if (fread(&n, 4, 1, f) != 1)
+               return EOF;
 
-       *result = ntoh_l(n);
-       return retval;
+#ifdef FRONTEND
+       *result = (int)ntohl(n);
+#else
+       *result = (int)((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? ntoh_l(n) : ntohl(n));
+#endif
+
+       return 0;
 }
 
 /* --------------------------------------------------------------------- */
-/* pqGetNBytes: Read a chunk of exactly len bytes in buffer s.
+/* pqGetNBytes: Read a chunk of exactly len bytes in buffer s (which must be 1
+               byte longer) and terminate it with a '\0'.
                Return 0 if ok.
 */
 int
 pqGetNBytes(char *s, size_t len, FILE *f)
 {
-       int                     cnt;
+       int cnt;
 
        if (f == NULL)
                return EOF;
 
        cnt = fread(s, 1, len, f);
        s[cnt] = '\0';
-       /* mjl: actually needs up to len+1 bytes, is this okay? XXX */
 
        return (cnt == len) ? 0 : EOF;
 }
@@ -126,7 +154,7 @@ int
 pqPutNBytes(const char *s, size_t len, FILE *f)
 {
        if (f == NULL)
-               return 0;
+               return EOF;
 
        if (fwrite(s, 1, len, f) != len)
                return EOF;
@@ -138,15 +166,27 @@ pqPutNBytes(const char *s, size_t len, FILE *f)
 int
 pqGetString(char *s, size_t len, FILE *f)
 {
-       int                     c;
+       int c;
 
        if (f == NULL)
                return EOF;
 
-       while (len-- && (c = getc(f)) != EOF && c)
-               *s++ = c;
+       /*
+        * Keep on reading until we get the terminating '\0' and discard those
+        * bytes we don't have room for.
+        */
+
+       while ((c = getc(f)) != EOF && c != '\0')
+               if (len > 1)
+               {
+                       *s++ = c;
+                       len--;
+               }
+
        *s = '\0';
-       /* mjl: actually needs up to len+1 bytes, is this okay? XXX */
+
+       if (c == EOF)
+               return EOF;
 
        return 0;
 }
@@ -183,5 +223,3 @@ pqPutByte(int c, FILE *f)
 
        return (putc(c, f) == c) ? 0 : EOF;
 }
-
-/* --------------------------------------------------------------------- */
index b62eb3ee3633c616de0a13ad53a35d8ce3a8174d..0a00a97ec6856c52dac54a95b566c4c12aabd018 100644 (file)
@@ -8,36 +8,14 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.12 1997/12/09 03:10:51 scrappy Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.13 1998/01/26 01:41:12 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
-/* NOTES
- *       This is the module that understands the lowest-level part
- *       of the communication protocol.  All of the trickiness in
- *       this module is for making sure that non-blocking I/O in
- *       the Postmaster works correctly.       Check the notes in PacketRecv
- *       on non-blocking I/O.
- *
- * Data Structures:
- *             Port has two important functions. (1) It records the
- *             sock/addr used in communication. (2) It holds partially
- *             read in messages.  This is especially important when
- *             we haven't seen enough to construct a complete packet
- *             header.
- *
- * PacketBuf -- None of the clients of this module should know
- *             what goes into a packet hdr (although they know how big
- *             it is).  This routine is in charge of host to net order
- *             conversion for headers.  Data conversion is someone elses
- *             responsibility.
- *
- * IMPORTANT: these routines are called by backends, clients, and
- *             the Postmaster.
- *
- */
+
 #include <stdio.h>
 #include <unistd.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netdb.h>
 #include <storage/ipc.h>
 #include <libpq/libpq.h>
 
+
 /*
- * PacketReceive -- receive a packet on a port.
- *
- * RETURNS: connection id of the packet sender, if one
- * is available.
- *
+ * Set up a packet read for the postmaster event loop.
  */
-int
-PacketReceive(Port *port,              /* receive port */
-                         PacketBuf *buf,       /* MAX_PACKET_SIZE-worth of buffer space */
-                         bool nonBlocking) /* NON_BLOCKING or BLOCKING i/o */
+
+void PacketReceiveSetup(Packet *pkt, void (*iodone)(), char *arg)
 {
-       PacketLen       max_size = sizeof(PacketBuf);
-       PacketLen       cc;                             /* character count -- bytes recvd */
-       PacketLen       packetLen;              /* remaining packet chars to read */
-       Addr            tmp;                    /* curr recv buf pointer */
-       int                     hdrLen;
-       int                     flag;
-       int                     decr;
+       pkt->nrtodo = sizeof (pkt->len);
+       pkt->ptr = (char *)&pkt->len;
+       pkt->iodone = iodone;
+       pkt->arg = arg;
+       pkt->state = ReadingPacketLength;
+}
 
-       hdrLen = sizeof(buf->len);
 
-       if (nonBlocking == NON_BLOCKING)
-       {
-               flag = MSG_PEEK;
-               decr = 0;
-       }
-       else
-       {
-               flag = 0;
-               decr = hdrLen;
-       }
+/*
+ * Read a packet fragment.  Return STATUS_OK if the connection should stay
+ * open.
+ */
 
-       /*
-        * Assume port->nBytes is zero unless we were interrupted during
-        * non-blocking I/O.  This first recv() is to get the hdr information
-        * so we know how many bytes to read.  Life would be very complicated
-        * if we read too much data (buffering).
-        */
-       tmp = ((Addr) buf) + port->nBytes;
+int PacketReceiveFragment(Packet *pkt, int sock)
+{
+       int got;
 
-       if (port->nBytes >= hdrLen)
+       if ((got = read(sock,pkt->ptr,pkt->nrtodo)) > 0)
        {
-               packetLen = ntohl(buf->len) - port->nBytes;
-       }
-       else
-       {
-               /* peeking into the incoming message */
-               cc = recv(port->sock, (char *) &(buf->len), hdrLen, flag);
-               if (cc < hdrLen)
+               pkt->nrtodo -= got;
+               pkt->ptr += got;
+
+               /* See if we have got what we need for the packet length. */
+
+               if (pkt->nrtodo == 0 && pkt->state == ReadingPacketLength)
                {
-                       /* if cc is negative, the system call failed */
-                       if (cc < 0)
-                       {
-                               return (STATUS_ERROR);
-                       }
+                       pkt->len = ntohl(pkt->len);
 
-                       /*
-                        * cc == 0 means the connection was broken at the other end.
-                        */
-                       else if (!cc)
+                       if (pkt->len < sizeof (pkt->len) ||
+                           pkt->len > sizeof (pkt->len) + sizeof (pkt->pkt))
                        {
-                               return (STATUS_INVALID);
+                               PacketSendError(pkt,"Invalid packet length");
 
+                               return STATUS_OK;
                        }
-                       else
-                       {
 
-                               /*
-                                * Worst case.  We didn't even read in enough data to get
-                                * the header length. since we are using a data stream,
-                                * this happens only if the client is mallicious.
-                                *
-                                * Don't save the number of bytes we've read so far. Since we
-                                * only peeked at the incoming message, the kernel is
-                                * going to keep it for us.
-                                */
-                               return (STATUS_NOT_DONE);
-                       }
+                       /* Set up for the rest of the packet. */
+
+                       pkt->nrtodo = pkt->len - sizeof (pkt->len);
+                       pkt->ptr = (char *)&pkt->pkt;
+                       pkt->state = ReadingPacket;
                }
-               else
-               {
 
-                       /*
-                        * This is an attempt to shield the Postmaster from mallicious
-                        * attacks by placing tighter restrictions on the reported
-                        * packet length.
-                        *
-                        * Check for negative packet length
-                        */
-                       if ((buf->len) <= 0)
-                       {
-                               return (STATUS_INVALID);
-                       }
+               /* See if we have got what we need for the packet. */
 
-                       /*
-                        * Check for oversize packet
-                        */
-                       if ((ntohl(buf->len)) > max_size)
-                       {
-                               return (STATUS_INVALID);
-                       }
+               if (pkt->nrtodo == 0 && pkt->state == ReadingPacket)
+               {
+                       pkt->state = Idle;
 
-                       /*
-                        * great. got the header. now get the true length (including
-                        * header size).
-                        */
-                       packetLen = ntohl(buf->len);
+                       /* Special case to close the connection. */
 
-                       /*
-                        * if someone is sending us junk, close the connection
-                        */
-                       if (packetLen > max_size)
-                       {
-                               port->nBytes = packetLen;
-                               return (STATUS_BAD_PACKET);
-                       }
-                       packetLen -= decr;
-                       tmp += decr - port->nBytes;
+                       if (pkt->iodone == NULL)
+                               return STATUS_ERROR;
+
+                       (*pkt->iodone)(pkt->arg, pkt->len - sizeof (pkt->len), 
+                                       (char *)&pkt->pkt);
                }
+
+               return STATUS_OK;
        }
 
-       /*
-        * Now that we know how big it is, read the packet.  We read the
-        * entire packet, since the last call was just a peek.
-        */
-       while (packetLen)
-       {
-               cc = read(port->sock, tmp, packetLen);
-               if (cc < 0)
-                       return (STATUS_ERROR);
+       if (got == 0)
+               return STATUS_ERROR;
 
-               /*
-                * cc == 0 means the connection was broken at the other end.
-                */
-               else if (!cc)
-                       return (STATUS_INVALID);
+       if (errno == EINTR)
+               return STATUS_OK;
 
-/*
-   fprintf(stderr,"expected packet of %d bytes, got %d bytes\n",
-                  packetLen, cc);
-*/
-               tmp += cc;
-               packetLen -= cc;
-
-               /* if non-blocking, we're done. */
-               if (nonBlocking && packetLen)
-               {
-                       port->nBytes += cc;
-                       return (STATUS_NOT_DONE);
-               }
-       }
+       fprintf(stderr, "read() system call failed\n");
 
-       port->nBytes = 0;
-       return (STATUS_OK);
+       return STATUS_ERROR;
 }
 
+
 /*
- * PacketSend -- send a single-packet message.
- *
- * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
- * SIDE_EFFECTS: may block.
- * NOTES: Non-blocking writes would significantly complicate
- *             buffer management.      For now, we're not going to do it.
- *
+ * Set up a packet write for the postmaster event loop.
  */
-int
-PacketSend(Port *port,
-                  PacketBuf *buf,
-                  PacketLen len,
-                  bool nonBlocking)
+
+void PacketSendSetup(Packet *pkt, int nbytes, void (*iodone)(), char *arg)
 {
-       PacketLen       doneLen;
+       pkt->nrtodo = nbytes;
+       pkt->ptr = (char *)&pkt->pkt;
+       pkt->iodone = iodone;
+       pkt->arg = arg;
+       pkt->state = WritingPacket;
+}
+
+
+/*
+ * Write a packet fragment.  Return STATUS_OK if the connection should stay
+ * open.
+ */
 
-       Assert(!nonBlocking);
-       Assert(buf);
+int PacketSendFragment(Packet *pkt, int sock)
+{
+       int done;
 
-       doneLen = write(port->sock, buf, len);
-       if (doneLen < len)
+       if ((done = write(sock,pkt->ptr,pkt->nrtodo)) > 0)
        {
-               sprintf(PQerrormsg,
-                 "FATAL: PacketSend: couldn't send complete packet: errno=%d\n",
-                               errno);
-               fputs(PQerrormsg, stderr);
-               return (STATUS_ERROR);
+               pkt->nrtodo -= done;
+               pkt->ptr += done;
+
+               /* See if we have written the whole packet. */
+
+               if (pkt->nrtodo == 0)
+               {
+                       pkt->state = Idle;
+
+                       /* Special case to close the connection. */
+
+                       if (pkt->iodone == NULL)
+                               return STATUS_ERROR;
+
+                       (*pkt->iodone)(pkt->arg);
+               }
+
+               return STATUS_OK;
        }
 
-       return (STATUS_OK);
-}
+       if (done == 0)
+               return STATUS_ERROR;
 
-/*
- * StartupInfo2PacketBuf -
- *      convert the fields of the StartupInfo to a PacketBuf
- *
- */
-/* moved to src/libpq/fe-connect.c */
-/*
-PacketBuf*
-StartupInfo2PacketBuf(StartupInfo* s)
-{
-  PacketBuf* res;
-  char* tmp;
-
-  res = (PacketBuf*)palloc(sizeof(PacketBuf));
-  res->len = htonl(sizeof(PacketBuf));
-  res->data[0] = '\0';
-
-  tmp= res->data;
-
-  strncpy(tmp, s->database, sizeof(s->database));
-  tmp += sizeof(s->database);
-  strncpy(tmp, s->user, sizeof(s->user));
-  tmp += sizeof(s->user);
-  strncpy(tmp, s->options, sizeof(s->options));
-  tmp += sizeof(s->options);
-  strncpy(tmp, s->execFile, sizeof(s->execFile));
-  tmp += sizeof(s->execFile);
-  strncpy(tmp, s->tty, sizeof(s->execFile));
-
-  return res;
+       if (errno == EINTR)
+               return STATUS_OK;
+
+       fprintf(stderr, "write() system call failed\n");
+
+       return STATUS_ERROR;
 }
-*/
+
 
 /*
- * PacketBuf2StartupInfo -
- *      convert the fields of the StartupInfo to a PacketBuf
- *
+ * Send an error message from the postmaster to the frontend.
  */
-/* moved to postmaster.c
-StartupInfo*
-PacketBuf2StartupInfo(PacketBuf* p)
+
+void PacketSendError(Packet *pkt, char *errormsg)
 {
-  StartupInfo* res;
-  char* tmp;
-
-  res = (StartupInfo*)palloc(sizeof(StartupInfo));
-
-  res->database[0]='\0';
-  res->user[0]='\0';
-  res->options[0]='\0';
-  res->execFile[0]='\0';
-  res->tty[0]='\0';
-
-  tmp= p->data;
-  strncpy(res->database,tmp,sizeof(res->database));
-  tmp += sizeof(res->database);
-  strncpy(res->user,tmp, sizeof(res->user));
-  tmp += sizeof(res->user);
-  strncpy(res->options,tmp, sizeof(res->options));
-  tmp += sizeof(res->options);
-  strncpy(res->execFile,tmp, sizeof(res->execFile));
-  tmp += sizeof(res->execFile);
-  strncpy(res->tty,tmp, sizeof(res->tty));
-
-  return res;
+       fprintf(stderr, "%s\n", errormsg);
+
+       pkt->pkt.em.data[0] = 'E';
+       StrNCpy(&pkt->pkt.em.data[1], errormsg, sizeof (pkt->pkt.em.data) - 2);
+
+       /*
+        * The NULL i/o callback will cause the connection to be broken when
+        * the error message has been sent.
+        */
+
+       PacketSendSetup(pkt, strlen(pkt->pkt.em.data) + 1, NULL, NULL);
 }
-*/
index e445aa34f69dd50ffc8cde2113ad15dc8e4fd1e8..386bd049a6dce60cf50d6305c1e95b0707931430 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.69 1998/01/25 05:13:35 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.70 1998/01/26 01:41:15 scrappy Exp $
  *
  * NOTES
  *
 #endif
 #endif
 
-#define LINGER_TIME 3
+#define        INVALID_SOCK    (-1)
+#define        ARGV_SIZE       64
 
  /*
   * Max time in seconds for socket to linger (close() to block) waiting
@@ -182,28 +183,24 @@ static int        SendStop = 0;
 
 static int     NetServer = 0;          /* if not zero, postmaster listen for
                                                                 * non-local connections */
-static int     MultiplexedBackends = 0;
-static int     MultiplexedBackendPort;
 
 /*
  * postmaster.c - function prototypes
  */
 static void pmdaemonize(void);
-static void
-ConnStartup(Port *port, int *status,
-                       char *errormsg, const int errormsg_len);
-static int     ConnCreate(int serverFd, int *newFdP);
+static Port *ConnCreate(int serverFd);
 static void reset_shared(short port);
 static void pmdie(SIGNAL_ARGS);
 static void reaper(SIGNAL_ARGS);
 static void dumpstatus(SIGNAL_ARGS);
 static void CleanupProc(int pid, int exitstatus);
-static int     DoExec(StartupInfo *packet, int portFd);
+static int     DoExec(Port *port);
 static void ExitPostmaster(int status);
 static void usage(const char *);
 static int     ServerLoop(void);
-static int     BackendStartup(StartupInfo *packet, Port *port, int *pidPtr);
-static void send_error_reply(Port *port, const char *errormsg);
+static int     BackendStartup(Port *port);
+static void readStartupPacket(char *arg, PacketLen len, char *pkt);
+static int initMasks(fd_set *rmask, fd_set *wmask);
 static void RandomSalt(char* salt);
 
 extern char *optarg;
@@ -307,8 +304,7 @@ PostmasterMain(int argc, char *argv[])
                switch (opt)
                {
                        case 'a':
-                               /* Set the authentication system. */
-                               be_setauthsvc(optarg);
+                               /* Can no longer set authentication method. */
                                break;
                        case 'B':
 
@@ -354,8 +350,7 @@ PostmasterMain(int argc, char *argv[])
                                NetServer = 1;
                                break;
                        case 'm':
-                               MultiplexedBackends = 1;
-                               MultiplexedBackendPort = atoi(optarg);
+                               /* Multiplexed backends no longer supported. */
                                break;
                        case 'M':
 
@@ -501,13 +496,11 @@ static void
 usage(const char *progname)
 {
        fprintf(stderr, "usage: %s [options..]\n", progname);
-       fprintf(stderr, "\t-a authsys\tdo/do not permit use of an authentication system\n");
        fprintf(stderr, "\t-B nbufs\tset number of shared buffers\n");
        fprintf(stderr, "\t-b backend\tuse a specific backend server executable\n");
        fprintf(stderr, "\t-d [1|2|3]\tset debugging level\n");
        fprintf(stderr, "\t-D datadir\tset data directory\n");
        fprintf(stderr, "\t-i \tlisten on TCP/IP sockets as well as Unix domain socket\n");
-       fprintf(stderr, "\t-m \tstart up multiplexing backends\n");
        fprintf(stderr, "\t-n\t\tdon't reinitialize shared memory after abnormal exit\n");
        fprintf(stderr, "\t-o option\tpass 'option' to each backend servers\n");
        fprintf(stderr, "\t-p port\t\tspecify port for postmaster to listen on\n");
@@ -519,15 +512,9 @@ usage(const char *progname)
 static int
 ServerLoop(void)
 {
-       fd_set          rmask,
-                               basemask;
-       int                     nSockets,
-                               nSelected,
-                               status,
-                               oldFd,
-                               newFd;
-       Dlelem     *next,
-                          *curr;
+       fd_set readmask, writemask;
+       int nSockets;
+       Dlelem *curr;
 
        /*
         * GH: For !HAVE_SIGPROCMASK (NEXTSTEP), TRH implemented an
@@ -541,16 +528,8 @@ ServerLoop(void)
        int                     orgsigmask = sigblock(0);
 
 #endif
-       FD_ZERO(&basemask);
-       FD_SET(ServerSock_UNIX, &basemask);
-       nSockets = ServerSock_UNIX;
-       if (ServerSock_INET != INVALID_SOCK)
-       {
-               FD_SET(ServerSock_INET, &basemask);
-               if (ServerSock_INET > ServerSock_UNIX)
-                       nSockets = ServerSock_INET;
-       }
-       nSockets++;
+
+       nSockets = initMasks(&readmask, &writemask);
 
 #ifdef HAVE_SIGPROCMASK
        sigprocmask(0, 0, &oldsigmask);
@@ -559,17 +538,19 @@ ServerLoop(void)
 #endif
        for (;;)
        {
+               Port *port;
+               fd_set rmask, wmask;
+
 #ifdef HAVE_SIGPROCMASK
                sigprocmask(SIG_SETMASK, &oldsigmask, 0);
 #else
                sigsetmask(orgsigmask);
 #endif
-               newFd = -1;
-               memmove((char *) &rmask, (char *) &basemask, sizeof(fd_set));
-               if ((nSelected = select(nSockets, &rmask,
-                                                               (fd_set *) NULL,
-                                                               (fd_set *) NULL,
-                                                               (struct timeval *) NULL)) < 0)
+
+               memmove((char *) &rmask, (char *) &readmask, sizeof(fd_set));
+               memmove((char *) &wmask, (char *) &writemask, sizeof(fd_set));
+               if (select(nSockets, &rmask, &wmask, (fd_set *) NULL,
+                               (struct timeval *) NULL) < 0)
                {
                        if (errno == EINTR)
                                continue;
@@ -589,344 +570,209 @@ ServerLoop(void)
 #else
                sigblock(sigmask(SIGCHLD));             /* XXX[TRH] portability */
 #endif
-               if (DebugLvl > 1)
-               {
-                       fprintf(stderr, "%s: ServerLoop: %d sockets pending\n",
-                                       progname, nSelected);
-               }
 
                /* new connection pending on our well-known port's socket */
-               oldFd = -1;
-               if (FD_ISSET(ServerSock_UNIX, &rmask))
-                       oldFd = ServerSock_UNIX;
-               else if (ServerSock_INET != INVALID_SOCK &&
-                                FD_ISSET(ServerSock_INET, &rmask))
-                       oldFd = ServerSock_INET;
-               if (oldFd >= 0)
-               {
 
-                       /*
-                        * connect and make an addition to PortList.  If the
-                        * connection dies and we notice it, just forget about the
-                        * whole thing.
-                        */
-                       if (ConnCreate(oldFd, &newFd) == STATUS_OK)
-                       {
-                               if (newFd >= nSockets)
-                                       nSockets = newFd + 1;
-                               FD_SET(newFd, &rmask);
-                               FD_SET(newFd, &basemask);
-                               if (DebugLvl)
-                                       fprintf(stderr, "%s: ServerLoop: connect on %d\n",
-                                                       progname, newFd);
-                       }
-                       else if (DebugLvl)
-                               fprintf(stderr,
-                                               "%s: ServerLoop: connect failed: (%d) %s\n",
-                                               progname, errno, strerror(errno));
-                       --nSelected;
-                       FD_CLR(oldFd, &rmask);
-               }
+               if (ServerSock_UNIX != INVALID_SOCK &&
+                               FD_ISSET(ServerSock_UNIX, &rmask) &&
+                               (port = ConnCreate(ServerSock_UNIX)) != NULL)
+                       PacketReceiveSetup(&port->pktInfo,
+                                               readStartupPacket,
+                                               (char *)port);
 
-               if (DebugLvl > 1)
-               {
-                       fprintf(stderr, "%s: ServerLoop:\tnSelected=%d\n",
-                                       progname, nSelected);
-                       curr = DLGetHead(PortList);
-                       while (curr)
-                       {
-                               Port       *port = DLE_VAL(curr);
-
-                               fprintf(stderr, "%s: ServerLoop:\t\tport %d%s pending\n",
-                                               progname, port->sock,
-                                               FD_ISSET(port->sock, &rmask)
-                                               ? "" :
-                                               " not");
-                               curr = DLGetSucc(curr);
-                       }
-               }
+               if (ServerSock_INET != INVALID_SOCK &&
+                               FD_ISSET(ServerSock_INET, &rmask) &&
+                               (port = ConnCreate(ServerSock_INET)) != NULL)
+                       PacketReceiveSetup(&port->pktInfo,
+                                               readStartupPacket,
+                                               (char *)port);
+
+               /* Build up new masks for select(). */
+
+               nSockets = initMasks(&readmask, &writemask);
 
                curr = DLGetHead(PortList);
 
                while (curr)
                {
                        Port       *port = (Port *) DLE_VAL(curr);
-                       int                     lastbytes = port->nBytes;
+                       int status = STATUS_OK;
+                       Dlelem *next;
+
+                       if (FD_ISSET(port->sock, &rmask))
+                       {
+                               if (DebugLvl > 1)
+                                       fprintf(stderr, "%s: ServerLoop:\t\thandling reading %d\n",
+                                                       progname, port->sock);
+
+                               if (PacketReceiveFragment(&port->pktInfo, port->sock) != STATUS_OK)
+                                       status = STATUS_ERROR;
+                       }
 
-                       if (FD_ISSET(port->sock, &rmask) && port->sock != newFd)
+                       if (FD_ISSET(port->sock, &wmask))
                        {
                                if (DebugLvl > 1)
-                                       fprintf(stderr, "%s: ServerLoop:\t\thandling %d\n",
+                                       fprintf(stderr, "%s: ServerLoop:\t\thandling writing %d\n",
                                                        progname, port->sock);
-                               --nSelected;
 
+                               if (PacketSendFragment(&port->pktInfo, port->sock) != STATUS_OK)
+                                       status = STATUS_ERROR;
+                       }
+
+                       /* Get this before the connection might be closed. */
+
+                       next = DLGetSucc(curr);
+
+                       /*
+                        * If there is no error and no outstanding data transfer
+                        * going on, then the authentication handshake must be
+                        * complete to the postmaster's satisfaction.  So,
+                        * start the backend.
+                        */
+
+                       if (status == STATUS_OK && port->pktInfo.state == Idle)
+                       {
                                /*
-                                * Read the incoming packet into its packet buffer. Read
-                                * the connection id out of the packet so we know who the
-                                * packet is from.
+                                * If the backend start fails then keep the
+                                * connection open to report it.  Otherwise,
+                                * pretend there is an error to close the
+                                * connection which will now be managed by the
+                                * backend.
                                 */
-receive_again:
-                               status = PacketReceive(port, &port->buf, NON_BLOCKING);
-                               switch (status)
-                               {
-                                       case STATUS_OK:
-                                               /* Here is where we check for a USER login packet.  If there is one, then
-                                                * we must deterine whether the login has a password in pg_user.  If so, send
-                                                * back a salt to crypt() the password with.  Otherwise, send an unsalt packet
-                                                * back and read the real startup packet.
-                                                */
-                                               if (ntohl(port->buf.msgtype) == STARTUP_USER_MSG) {
-                                                 PacketLen     plen;
-
-                                                 port->buf.msgtype = htonl(crypt_salt(port->buf.data));
-                                                 plen = sizeof(port->buf.len) + sizeof(port->buf.msgtype) + 2;
-                                                 port->buf.len = htonl(plen);
-                                                 RandomSalt(port->salt);
-                                                 memcpy((void*)port->buf.data, (void*)port->salt, 2);
-
-                                                 status = PacketSend(port, &port->buf, plen, BLOCKING);
-                                                 if (status != STATUS_OK)
-                                                   break;
-
-                                                 /* port->nBytes = 0; */
-                                                       goto receive_again;
-                                               } else {
-                                                       int                     CSstatus;               /* Completion status of
-                                                                                                                * ConnStartup */
-                                                       char            errormsg[200];  /* error msg from
-                                                                                                                * ConnStartup */
-
-                                                       ConnStartup(port, &CSstatus, errormsg, sizeof(errormsg));
-
-                                                       if (CSstatus == STATUS_ERROR)
-                                                               send_error_reply(port, errormsg);
-                                                       ActiveBackends = TRUE;
-                                               }
-                                               /* FALLTHROUGH */
-                                       case STATUS_INVALID:
-                                               if (DebugLvl)
-                                                       fprintf(stderr, "%s: ServerLoop:\t\tdone with %d\n",
-                                                                       progname, port->sock);
-                                               break;
-                                       case STATUS_BAD_PACKET:
-
-                                               /*
-                                                * This is a bogus client, kill the connection and
-                                                * forget the whole thing.
-                                                */
-                                               if (DebugLvl)
-                                                       fprintf(stderr, "%s: ServerLoop:\t\tbad packet format (reported packet size of %d read on port %d\n", progname, port->nBytes, port->sock);
-                                               break;
-                                       case STATUS_NOT_DONE:
-                                               if (DebugLvl)
-                                                       fprintf(stderr, "%s: ServerLoop:\t\tpartial packet (%d bytes actually read) on %d\n",
-                                                                       progname, port->nBytes, port->sock);
-
-                                               /*
-                                                * If we've received at least a PacketHdr's worth
-                                                * of data and we're still receiving data each
-                                                * time we read, we're ok.  If the client gives us
-                                                * less than a PacketHdr at the beginning, just
-                                                * kill the connection and forget about the whole
-                                                * thing.
-                                                */
-                                               if (lastbytes < port->nBytes)
-                                               {
-                                                       if (DebugLvl)
-                                                               fprintf(stderr, "%s: ServerLoop:\t\tpartial packet on %d ok\n",
-                                                                               progname, port->sock);
-                                                       curr = DLGetSucc(curr);
-                                                       continue;
-                                               }
-                                               break;
-                                       case STATUS_ERROR:      /* system call error - die */
-                                               fprintf(stderr, "%s: ServerLoop:\t\terror receiving packet\n",
-                                                               progname);
-                                               return (STATUS_ERROR);
-                               }
-                               FD_CLR(port->sock, &basemask);
+
+                               if (BackendStartup(port) != STATUS_OK)
+                                       PacketSendError(&port->pktInfo,
+                                               "Backend startup failed");
+                               else
+                                       status = STATUS_ERROR;
+                       }
+
+                       /* Close the connection if required. */
+
+                       if (status != STATUS_OK)
+                       {
                                StreamClose(port->sock);
-                               next = DLGetSucc(curr);
                                DLRemove(curr);
                                free(port);
                                DLFreeElem(curr);
-                               curr = next;
-                               continue;
                        }
-                       curr = DLGetSucc(curr);
+                       else
+                       {
+                               /* Set the masks for this connection. */
+
+                               if (nSockets <= port->sock)
+                                       nSockets = port->sock + 1;
+
+                               if (port->pktInfo.state == WritingPacket)
+                                       FD_SET(port->sock, &writemask);
+                               else
+                                       FD_SET(port->sock, &readmask);
+                       }
+
+                       curr = next;
                }
-               Assert(nSelected == 0);
        }
 }
 
 
-
 /*
-       ConnStartup: get the startup packet from the front end (client),
-       authenticate the user, and start up a backend.
-
-       If all goes well, return *status == STATUS_OK.
-       Otherwise, return *status == STATUS_ERROR and return a text string
-       explaining why in the "errormsg_len" bytes at "errormsg",
-*/
+ * Initialise the read and write masks for select() for the well-known ports
+ * we are listening on.  Return the number of sockets to listen on.
+ */
 
-static void
-ConnStartup(Port *port, int *status,
-                       char *errormsg, const int errormsg_len)
+static int initMasks(fd_set *rmask, fd_set *wmask)
 {
-       MsgType         msgType;
-       char            namebuf[NAMEDATALEN];
-       int                     pid;
-       PacketBuf  *p;
-       StartupInfo sp;
-       char       *tmp;
-
-       p = &port->buf;
-
-       sp.database[0] = '\0';
-       sp.user[0] = '\0';
-       sp.options[0] = '\0';
-       sp.execFile[0] = '\0';
-       sp.tty[0] = '\0';
-
-       tmp = p->data;
-       strncpy(sp.database, tmp, sizeof(sp.database));
-       tmp += sizeof(sp.database);
-       strncpy(sp.user, tmp, sizeof(sp.user));
-       tmp += sizeof(sp.user);
-       strncpy(sp.options, tmp, sizeof(sp.options));
-       tmp += sizeof(sp.options);
-       strncpy(sp.execFile, tmp, sizeof(sp.execFile));
-       tmp += sizeof(sp.execFile);
-       strncpy(sp.tty, tmp, sizeof(sp.tty));
-
-       msgType = (MsgType) ntohl(port->buf.msgtype);
-
-       StrNCpy(namebuf, sp.user, NAMEDATALEN);
-       if (!namebuf[0])
+       int nsocks = -1;
+
+       FD_ZERO(rmask);
+       FD_ZERO(wmask);
+
+       if (ServerSock_UNIX != INVALID_SOCK)
        {
-               strncpy(errormsg,
-                               "No Postgres username specified in startup packet.",
-                               errormsg_len);
-               *status = STATUS_ERROR;
+               FD_SET(ServerSock_UNIX, rmask);
+
+               if (ServerSock_UNIX > nsocks)
+                       nsocks = ServerSock_UNIX;
        }
-       else
+
+       if (ServerSock_INET != INVALID_SOCK)
        {
-               if (be_recvauth(msgType, port, namebuf, &sp) != STATUS_OK)
-               {
-                       char            buffer[200 + sizeof(namebuf)];
-
-                       sprintf(buffer,
-                                       "Failed to authenticate client as Postgres user '%s' "
-                                       "using %s: %s",
-                         namebuf, name_of_authentication_type(msgType), PQerrormsg);
-                       strncpy(errormsg, buffer, errormsg_len);
-                       *status = STATUS_ERROR;
-               }
-               else
-               {
-                       if (BackendStartup(&sp, port, &pid) != STATUS_OK)
-                       {
-                               strncpy(errormsg, "Startup (fork) of backend failed.",
-                                               errormsg_len);
-                               *status = STATUS_ERROR;
-                       }
-                       else
-                       {
-                               errormsg[0] = '\0';             /* just for robustness */
-                               *status = STATUS_OK;
-                       }
-               }
+               FD_SET(ServerSock_INET, rmask);
+
+               if (ServerSock_INET > nsocks)
+                       nsocks = ServerSock_INET;
        }
-       if (*status == STATUS_ERROR)
-               fprintf(stderr, "%s: ConnStartup: %s\n", progname, errormsg);
+
+       return (nsocks + 1);
 }
 
 
 /*
-        send_error_reply: send a reply to the front end telling it that
-        the connection was a bust, and why.
-
-        "port" tells to whom and how to send the reply.  "errormsg" is
-        the string of text telling what the problem was.
-
-        It should be noted that we're executing a pretty messy protocol
-        here.  The postmaster does not reply when the connection is
-        successful, but rather just hands the connection off to the
-        backend and the backend waits for a query from the frontend.
-        Thus, the frontend is not expecting any reply in regards to the
-        connect request.
-
-        But when the connection fails, we send this reply that starts
-        with "E".      The frontend only gets this reply when it sends its
-        first query and waits for the reply.  Nobody receives that query,
-        but this reply is already in the pipe, so that's what the
-        frontend sees.
-
-        Note that the backend closes the socket immediately after sending
-        the reply, so to give the frontend a fighting chance to see the
-        error info, we set the socket to linger up to 3 seconds waiting
-        for the frontend to retrieve the message.      That's all the delay
-        we can afford, since we have other clients to serve and the
-        postmaster will be blocked the whole time.  Also, if there is no
-        message space in the socket for the reply (shouldn't be a
-        problem) the postmaster will block until the frontend reads the
-        reply.
-
-*/
+ * Called when the startup packet has been read.
+ */
 
-static void
-send_error_reply(Port *port, const char *errormsg)
+static void readStartupPacket(char *arg, PacketLen len, char *pkt)
 {
-       int                     rc;                             /* return code from write */
-       char       *reply;
+       Port *port;
+       StartupPacket *si;
 
-       /*
-        * The literal reply string we put into the socket.  This is a pointer
-        * to storage we malloc.
-        */
-       const struct linger linger_parm = {true, LINGER_TIME};
+       port = (Port *)arg;
+       si = (StartupPacket *)pkt;
 
-       /*
-        * A parameter for setsockopt() that tells it to have close() block
-        * for a while waiting for the frontend to read its outstanding
-        * messages.
-        */
+       /* At the moment the startup packet must be a fixed length. */
 
-       reply = malloc(strlen(errormsg) + 10);
+       if (len != sizeof (StartupPacket))
+       {
+               PacketSendError(&port->pktInfo, "Invalid startup packet.");
+               return;
+       }
 
-       sprintf(reply, "E%s", errormsg);
+       /* Get the parameters from the startup packet as C strings. */
 
-       rc = write(port->sock, (Addr) reply, strlen(reply) + 1);
-       if (rc < 0)
-               fprintf(stderr,
-                               "%s: ServerLoop:\t\t"
-                               "Failed to send error reply to front end\n",
-                               progname);
-       else if (rc < strlen(reply) + 1)
-               fprintf(stderr,
-                               "%s: ServerLoop:\t\t"
-                               "Only partial error reply sent to front end.\n",
-                               progname);
+       StrNCpy(port->database, si->database, sizeof (port->database) - 1);
+       StrNCpy(port->user, si->user, sizeof (port->user) - 1);
+       StrNCpy(port->options, si->options, sizeof (port->options) - 1);
+       StrNCpy(port->tty, si->tty, sizeof (port->tty) - 1);
 
-       free(reply);
+       /* The database defaults to the user name. */
 
-       /*
-        * Now we have to make sure frontend has a chance to see what we just
-        * wrote.
-        */
-       rc = setsockopt(port->sock, SOL_SOCKET, SO_LINGER,
-                                       &linger_parm, sizeof(linger_parm));
+       if (port->database[0] == '\0')
+               StrNCpy(port->database, si->user, sizeof (port->database) - 1);
+
+       /* Check we can handle the protocol the frontend is using. */
+
+       port->proto = ntohl(si->protoVersion);
+
+       if (PG_PROTOCOL_MAJOR(port->proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
+           PG_PROTOCOL_MAJOR(port->proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) ||
+           (PG_PROTOCOL_MAJOR(port->proto) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) &&
+            PG_PROTOCOL_MINOR(port->proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))
+       {
+               PacketSendError(&port->pktInfo, "Unsupported frontend protocol.");
+               return;
+       }
+
+       /* Check a user name was given. */
+
+       if (port->user[0] == '\0')
+       {
+               PacketSendError(&port->pktInfo,
+                               "No Postgres username specified in startup packet.");
+               return;
+       }
+
+       /* Start the authentication itself. */
+
+       be_recvauth(port);
 }
 
 
 /*
  * ConnCreate -- create a local connection data structure
  */
-static int
-ConnCreate(int serverFd, int *newFdP)
+static Port *
+ConnCreate(int serverFd)
 {
-       int                     status;
        Port       *port;
 
 
@@ -937,18 +783,20 @@ ConnCreate(int serverFd, int *newFdP)
                ExitPostmaster(1);
        }
 
-       if ((status = StreamConnection(serverFd, port)) != STATUS_OK)
+       if (StreamConnection(serverFd, port) != STATUS_OK)
        {
                StreamClose(port->sock);
                free(port);
+               port = NULL;
        }
        else
        {
                DLAddHead(PortList, DLNewElem(port));
-               *newFdP = port->sock;
+               RandomSalt(port->salt);
+               port->pktInfo.state = Idle;
        }
 
-       return (status);
+       return port;
 }
 
 /*
@@ -1125,9 +973,7 @@ CleanupProc(int pid,
  *
  */
 static int
-BackendStartup(StartupInfo *packet,            /* client's startup packet */
-                          Port *port,
-                          int *pidPtr)
+BackendStartup(Port *port)
 {
        Backend    *bn;                         /* for backend cleanup */
        int                     pid,
@@ -1148,7 +994,7 @@ BackendStartup(StartupInfo *packet,                /* client's startup packet */
        putenv(envEntry[0]);
        sprintf(envEntry[1], "POSTID=%d", NextBackendId);
        putenv(envEntry[1]);
-       sprintf(envEntry[2], "PG_USER=%s", packet->user);
+       sprintf(envEntry[2], "PG_USER=%s", port->user);
        putenv(envEntry[2]);
        if (!getenv("PGDATA"))
        {
@@ -1173,7 +1019,7 @@ BackendStartup(StartupInfo *packet,               /* client's startup packet */
 
        if ((pid = FORK()) == 0)
        {                                                       /* child */
-               if (DoExec(packet, port->sock))
+               if (DoExec(port))
                        fprintf(stderr, "%s child[%d]: BackendStartup: execv failed\n",
                                        progname, pid);
                /* use _exit to keep from double-flushing stdio */
@@ -1190,8 +1036,7 @@ BackendStartup(StartupInfo *packet,               /* client's startup packet */
 
        if (DebugLvl)
                fprintf(stderr, "%s: BackendStartup: pid %d user %s db %s socket %d\n",
-                               progname, pid, packet->user,
-                (packet->database[0] == '\0' ? packet->user : packet->database),
+                               progname, pid, port->user, port->database,
                                port->sock);
 
        /* adjust backend counter */
@@ -1212,10 +1057,7 @@ BackendStartup(StartupInfo *packet,              /* client's startup packet */
        bn->pid = pid;
        DLAddHead(BackendList, DLNewElem(bn));
 
-       if (MultiplexedBackends)
-               MultiplexedBackendPort++;
-
-       *pidPtr = pid;
+       ActiveBackends = TRUE;
 
        return (STATUS_OK);
 }
@@ -1262,19 +1104,19 @@ split_opts(char **argv, int *argcp, char *s)
  *             If execv() fails, return status.
  */
 static int
-DoExec(StartupInfo *packet, int portFd)
+DoExec(Port *port)
 {
        char            execbuf[MAXPATHLEN];
        char            portbuf[ARGV_SIZE];
-       char            mbbuf[ARGV_SIZE];
        char            debugbuf[ARGV_SIZE];
        char            ttybuf[ARGV_SIZE + 1];
+       char            protobuf[ARGV_SIZE + 1];
        char            argbuf[(2 * ARGV_SIZE) + 1];
 
        /*
         * each argument takes at least three chars, so we can't have more
         * than ARGV_SIZE arguments in (2 * ARGV_SIZE) chars (i.e.,
-        * packet->options plus ExtraOptions)...
+        * port->options plus ExtraOptions)...
         */
        char       *av[ARGV_SIZE];
        char            dbbuf[ARGV_SIZE + 1];
@@ -1304,34 +1146,30 @@ DoExec(StartupInfo *packet, int portFd)
                av[ac++] = "-Q";
 
        /* Pass the requested debugging output file */
-       if (packet->tty[0])
+       if (port->tty[0])
        {
-               strncpy(ttybuf, packet->tty, ARGV_SIZE);
+               strncpy(ttybuf, port->tty, ARGV_SIZE);
                av[ac++] = "-o";
                av[ac++] = ttybuf;
        }
 
-       /* tell the multiplexed backend to start on a certain port */
-       if (MultiplexedBackends)
-       {
-               sprintf(mbbuf, "-m %d", MultiplexedBackendPort);
-               av[ac++] = mbbuf;
-       }
        /* Tell the backend the descriptor of the fe/be socket */
-       sprintf(portbuf, "-P%d", portFd);
+       sprintf(portbuf, "-P%d", port->sock);
        av[ac++] = portbuf;
 
-       StrNCpy(argbuf, packet->options, ARGV_SIZE);
+       StrNCpy(argbuf, port->options, ARGV_SIZE);
        strncat(argbuf, ExtraOptions, ARGV_SIZE);
        argbuf[(2 * ARGV_SIZE)] = '\0';
        split_opts(av, &ac, argbuf);
 
-       if (packet->database[0])
-               StrNCpy(dbbuf, packet->database, ARGV_SIZE);
-       else
-               StrNCpy(dbbuf, packet->user, NAMEDATALEN);
+       StrNCpy(dbbuf, port->database, ARGV_SIZE);
        av[ac++] = dbbuf;
 
+       /* Tell the backend what protocol the frontend is using. */
+
+       sprintf(protobuf, "-v %u", port->proto);
+       av[ac++] = protobuf;
+
        av[ac] = (char *) NULL;
 
        if (DebugLvl > 1)
@@ -1375,10 +1213,7 @@ dumpstatus(SIGNAL_ARGS)
                Port       *port = DLE_VAL(curr);
 
                fprintf(stderr, "%s: dumpstatus:\n", progname);
-               fprintf(stderr, "\tsock %d: nBytes=%d, laddr=0x%lx, raddr=0x%lx\n",
-                               port->sock, port->nBytes,
-                               (long int) port->laddr.in.sin_addr.s_addr,
-                               (long int) port->raddr.in.sin_addr.s_addr);
+               fprintf(stderr, "\tsock %d\n", port->sock);
                curr = DLGetSucc(curr);
        }
 }
index c808a46e1d014cca97e09e822aa6573bbc59daf3..25b8ad984c342113c00af5d3cbc8f0032b4dcd77 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.15 1997/12/06 22:57:02 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.16 1998/01/26 01:41:23 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,7 +29,7 @@
 #include "postgres.h"
 
 #include "access/htup.h"
-#include "libpq/libpq-be.h"
+#include "libpq/libpq.h"
 #include "access/printtup.h"
 #include "utils/portal.h"
 #include "utils/palloc.h"
index 5a49b382fc925dfb3ae4646f8de5d396db1cc4e7..1f2bd4b92f281938ff4450df274f5ae5e2624f3b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.11 1998/01/11 21:16:01 scrappy Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.12 1998/01/26 01:41:28 scrappy Exp $
  *
  * NOTES
  *       This cruft is the server side of PQfn.
@@ -336,7 +336,7 @@ HandleFunctionRequest()
                                else
                                {                               /* ... fixed */
                                        /* XXX cross our fingers and trust "argsize" */
-                                       if (!(p = palloc(argsize)))
+                                       if (!(p = palloc(argsize + 1)))
                                        {
                                                elog(ERROR, "HandleFunctionRequest: palloc failed");
                                        }
index 7e392bd30f3d7eebeafe690830275908c41037f3..b5c55d335d0f2a338b5a9e82ade7e4249d39719c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.62 1998/01/25 05:14:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.63 1998/01/26 01:41:35 scrappy Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -47,8 +47,8 @@
 #include "commands/async.h"
 #include "executor/execdebug.h"
 #include "executor/executor.h"
-#include "lib/dllist.h"
 #include "libpq/libpq.h"
+#include "libpq/libpq-be.h"
 #include "libpq/pqsignal.h"
 #include "nodes/pg_list.h"
 #include "nodes/print.h"
@@ -131,18 +131,6 @@ static int ShowPlannerStats;
 int                    ShowExecutorStats;
 FILE      *StatFp;
 
-typedef struct frontend
-{
-       bool            fn_connected;
-       Port            fn_port;
-       FILE       *fn_Pfin;            /* the input fd */
-       FILE       *fn_Pfout;           /* the output fd */
-       bool            fn_done;                /* set after the frontend closes its
-                                                                * connection */
-} FrontEnd;
-
-static Dllist *frontendList;
-
 /* ----------------
  *             people who want to use EOF should #define DONTUSENEWLINE in
  *             tcop/tcopdebug.h
@@ -188,8 +176,8 @@ int                 _exec_repeat_ = 1;
  * ----------------------------------------------------------------
  */
 static char InteractiveBackend(char *inBuf);
-static char SocketBackend(char *inBuf, bool multiplexedBackend);
-static char ReadCommand(char *inBuf, bool multiplexedBackend);
+static char SocketBackend(char *inBuf);
+static char ReadCommand(char *inBuf);
 
 
 /* ----------------------------------------------------------------
@@ -305,7 +293,7 @@ InteractiveBackend(char *inBuf)
  */
 
 static char
-SocketBackend(char *inBuf, bool multiplexedBackend)
+SocketBackend(char *inBuf)
 {
        char            qtype[2];
        char            result = '\0';
@@ -321,12 +309,7 @@ SocketBackend(char *inBuf, bool multiplexedBackend)
                 *      when front-end applications quits/dies
                 * ------------
                 */
-               if (multiplexedBackend)
-               {
-                       return 'X';
-               }
-               else
-                       exitpg(0);
+               exitpg(0);
        }
 
        switch (*qtype)
@@ -380,10 +363,10 @@ SocketBackend(char *inBuf, bool multiplexedBackend)
  * ----------------
  */
 static char
-ReadCommand(char *inBuf, bool multiplexedBackend)
+ReadCommand(char *inBuf)
 {
-       if (IsUnderPostmaster || multiplexedBackend)
-               return SocketBackend(inBuf, multiplexedBackend);
+       if (IsUnderPostmaster)
+               return SocketBackend(inBuf);
        else
                return InteractiveBackend(inBuf);
 }
@@ -793,7 +776,7 @@ static void
 usage(char *progname)
 {
        fprintf(stderr,
-                       "Usage: %s [-B nbufs] [-d lvl] ] [-f plantype] \t[-m portno] [\t -o filename]\n",
+                       "Usage: %s [-B nbufs] [-d lvl] ] [-f plantype] \t[-v protocol] [\t -o filename]\n",
                        progname);
        fprintf(stderr, "\t[-P portno] [-t tracetype] [-x opttype] [-bCEiLFNopQSs] [dbname]\n");
        fprintf(stderr, "    b: consider bushy plan trees during optimization\n");
@@ -809,7 +792,6 @@ usage(char *progname)
        fprintf(stderr, "    K: set locking debug level [0|1|2]\n");
 #endif
        fprintf(stderr, "    L: turn off locking\n");
-       fprintf(stderr, "    m: set up a listening backend at portno to support multiple front-ends\n");
        fprintf(stderr, "    M: start as postmaster\n");
        fprintf(stderr, "    N: don't use newline as query delimiter\n");
        fprintf(stderr, "    o: send stdout and stderr to given filename \n");
@@ -820,6 +802,7 @@ usage(char *progname)
        fprintf(stderr, "    s: show stats after each query\n");
        fprintf(stderr, "    t: trace component execution times\n");
        fprintf(stderr, "    T: execute all possible plans for each query\n");
+       fprintf(stderr, "    v: set protocol version being used by frontend\n");
        fprintf(stderr, "    x: control expensive function optimization\n");
 }
 
@@ -845,24 +828,6 @@ PostgresMain(int argc, char *argv[])
        char            parser_input[MAX_PARSE_BUFFER];
        char       *userName;
 
-       bool            multiplexedBackend;
-       char       *hostName;           /* the host name of the backend server */
-       int                     serverSock;
-       int                     serverPortnum = 0;
-       int                     nSelected;              /* number of descriptors ready from
-                                                                * select(); */
-       int                     maxFd = 0;              /* max file descriptor + 1 */
-       fd_set          rmask,
-                               basemask;
-       FrontEnd   *newFE,
-                          *currentFE = NULL;
-       int                     numFE = 0;              /* keep track of number of active
-                                                                * frontends */
-       Port       *newPort;
-       int                     newFd;
-       Dlelem     *curr;
-       int                     status;
-
        char       *DBDate = NULL;
        extern int      optind;
        extern char *optarg;
@@ -906,7 +871,6 @@ PostgresMain(int argc, char *argv[])
         * get hostname is either the environment variable PGHOST or NULL
         * NULL means Unix-socket only
         */
-       hostName = getenv("PGHOST");
        DataDir = getenv("PGDATA");
        /*
         * Try to get initial values for date styles and formats.
@@ -933,9 +897,8 @@ PostgresMain(int argc, char *argv[])
                else if (strcasecmp(DBDate, "EURO") == 0)
                        EuroDates = TRUE;
        }
-       multiplexedBackend = false;
 
-       while ((flag = getopt(argc, argv, "B:bCD:d:Eef:iK:Lm:MNo:P:pQS:st:x:F"))
+       while ((flag = getopt(argc, argv, "B:bCD:d:Eef:iK:Lm:MNo:P:pQS:st:v:x:F"))
                   != EOF)
                switch (flag)
                {
@@ -1051,16 +1014,7 @@ PostgresMain(int argc, char *argv[])
                                break;
 
                        case 'm':
-
-                               /*
-                                * start up a listening backend that can respond to
-                                * multiple front-ends.  (Note:  all the front-end
-                                * connections are still connected to a single-threaded
-                                * backend.  Requests are FCFS.  Everything is in one
-                                * transaction
-                                */
-                               multiplexedBackend = true;
-                               serverPortnum = atoi(optarg);
+                               /* Multiplexed backends are no longer supported. */
                                break;
                        case 'M':
                                exit(PostmasterMain(argc, argv));
@@ -1162,6 +1116,10 @@ PostgresMain(int argc, char *argv[])
                                }
                                break;
 
+                       case 'v':
+                               FrontendProtocol = (ProtocolVersion)atoi(optarg);
+                               break;
+
                        case 'x':
 #if 0                                                  /* planner/xfunc.h */
 
@@ -1267,7 +1225,6 @@ PostgresMain(int argc, char *argv[])
                printf("\tsortmem   =    %d\n", SortMem);
 
                printf("\tquery echo =   %c\n", EchoQuery ? 't' : 'f');
-               printf("\tmultiplexed backend? =  %c\n", multiplexedBackend ? 't' : 'f');
                printf("\tDatabaseName = [%s]\n", DBName);
                puts("\t----------------\n");
        }
@@ -1285,53 +1242,8 @@ PostgresMain(int argc, char *argv[])
                        Portfd = open(NULL_DEV, O_RDWR, 0666);
                }
                pq_init(Portfd);
-       }
-
-       if (multiplexedBackend)
-       {
-               if (serverPortnum == 0 ||
-                   StreamServerPort(hostName, serverPortnum, &serverSock) != STATUS_OK)
-               {
-                       fprintf(stderr, "Postgres: cannot create stream port %d\n", serverPortnum);
-                       exit(1);
-               }
-/*
-{
-       char buf[100];
-       sprintf(buf, "stream port %d created, socket = %d\n", serverPortnum, serverSock);
-       puts(buf);
-}
-*/
-               FD_ZERO(&rmask);
-               FD_ZERO(&basemask);
-               FD_SET(serverSock, &basemask);
-
-               frontendList = DLNewList();
-               /* add the original FrontEnd to the list */
-               if (IsUnderPostmaster == true)
-               {
-                       FrontEnd   *fe = malloc(sizeof(FrontEnd));
-
-                       FD_SET(Portfd, &basemask);
-                       maxFd = Max(serverSock, Portfd) + 1;
-
-                       fe->fn_connected = true;
-                       fe->fn_Pfin = Pfin;
-                       fe->fn_Pfout = Pfout;
-                       fe->fn_done = false;
-                       (fe->fn_port).sock = Portfd;
-                       DLAddHead(frontendList, DLNewElem(fe));
-                       numFE++;
-               }
-               else
-               {
-                       numFE = 1;
-                       maxFd = serverSock + 1;
-               }
-       }
-
-       if (IsUnderPostmaster || multiplexedBackend)
                whereToSendOutput = Remote;
+       }
        else
                whereToSendOutput = Debug;
 
@@ -1381,7 +1293,7 @@ PostgresMain(int argc, char *argv[])
        if (IsUnderPostmaster == false)
        {
                puts("\nPOSTGRES backend interactive interface");
-               puts("$Revision: 1.62 $ $Date: 1998/01/25 05:14:18 $");
+               puts("$Revision: 1.63 $ $Date: 1998/01/26 01:41:35 $");
        }
 
        /* ----------------
@@ -1395,106 +1307,13 @@ PostgresMain(int argc, char *argv[])
 
        for (;;)
        {
-
-               if (multiplexedBackend)
-               {
-                       if (numFE == 0)
-                               break;
-
-                       memmove((char *) &rmask, (char *) &basemask, sizeof(fd_set));
-                       nSelected = select(maxFd, &rmask, 0, 0, 0);
-
-                       if (nSelected < 0)
-                       {
-
-                               if (errno == EINTR)
-                                       continue;
-                               fprintf(stderr, "postgres: multiplexed backend select failed\n");
-                               exitpg(1);
-                       }
-                       if (FD_ISSET(serverSock, &rmask))
-                       {
-                               /* new connection pending on our well-known port's socket */
-                               newFE = (FrontEnd *) malloc(sizeof(FrontEnd));
-                               MemSet(newFE, 0, sizeof(FrontEnd));
-                               newFE->fn_connected = false;
-                               newFE->fn_done = false;
-                               newPort = &(newFE->fn_port);
-                               if (StreamConnection(serverSock, newPort) != STATUS_OK)
-                               {
-                                       StreamClose(newPort->sock);
-                                       newFd = -1;
-                               }
-                               else
-                               {
-                                       DLAddHead(frontendList, DLNewElem(newFE));
-                                       numFE++;
-                                       newFd = newPort->sock;
-                                       if (newFd >= maxFd)
-                                               maxFd = newFd + 1;
-                                       FD_SET(newFd, &rmask);
-                                       FD_SET(newFd, &basemask);
-                                       --nSelected;
-                                       FD_CLR(serverSock, &rmask);
-                               }
-                               continue;
-                       }                                       /* if FD_ISSET(serverSock) */
-
-                       /*
-                        * if we get here, it means that the serverSocket was not the
-                        * one selected.  Instead, one of the front ends was selected.
-                        * find which one
-                        */
-                       curr = DLGetHead(frontendList);
-                       while (curr)
-                       {
-                               FrontEnd   *fe = (FrontEnd *) DLE_VAL(curr);
-                               Port       *port = &(fe->fn_port);
-
-                               /* this is lifted from postmaster.c */
-                               if (FD_ISSET(port->sock, &rmask))
-                               {
-                                       if (fe->fn_connected == false)
-                                       {
-                                               /* we have a message from a new frontEnd */
-                                               status = PacketReceive(port, &port->buf, NON_BLOCKING);
-                                               if (status == STATUS_OK)
-                                               {
-                                                       fe->fn_connected = true;
-                                                       pq_init(port->sock);
-                                                       fe->fn_Pfin = Pfin;
-                                                       fe->fn_Pfout = Pfout;
-                                               }
-                                               else
-                                                       fprintf(stderr, "Multiplexed backend: error in reading packets from %d\n", port->sock);
-                                       }
-                                       else
-/* we have a query from an existing,  active FrontEnd */
-                                       {
-                                               Pfin = fe->fn_Pfin;
-                                               Pfout = fe->fn_Pfout;
-                                               currentFE = fe;
-                                       }
-                                       if (fe->fn_done)
-                                       {
-                                               Dlelem     *c = curr;
-
-                                               curr = DLGetSucc(curr);
-                                               DLRemove(c);
-                                       }
-                                       break;
-                               }
-                               else
-                                       curr = DLGetSucc(curr);
-                       }
-               }
                /* ----------------
                 *       (1) read a command.
                 * ----------------
                 */
                MemSet(parser_input, 0, MAX_PARSE_BUFFER);
 
-               firstchar = ReadCommand(parser_input, multiplexedBackend);
+               firstchar = ReadCommand(parser_input);
                /* process the command */
                switch (firstchar)
                {
@@ -1564,12 +1383,6 @@ PostgresMain(int argc, char *argv[])
                                 */
                        case 'X':
                                IsEmptyQuery = true;
-                               if (multiplexedBackend)
-                               {
-                                       FD_CLR(currentFE->fn_port.sock, &basemask);
-                                       currentFE->fn_done = true;
-                                       numFE--;
-                               }
                                pq_close();
                                break;
 
@@ -1596,7 +1409,7 @@ PostgresMain(int argc, char *argv[])
                }
                else
                {
-                       if (IsUnderPostmaster || multiplexedBackend)
+                       if (IsUnderPostmaster)
                                NullCommand(Remote);
                }
 
index 1cc310df9065e464b994c67225476fdb7ffdfacb..71ccc417fe687553c4718173bc829eb54b4047e6 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.18 1998/01/25 05:14:42 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.19 1998/01/26 01:41:42 scrappy Exp $
  *
  * NOTES
  *       Globals used all over the place should be declared here and not
 #include "storage/sinvaladt.h"
 #include "storage/lmgr.h"
 #include "utils/elog.h"
-
+#include "libpq/pqcomm.h"
 #include "catalog/catname.h"
 
+ProtocolVersion                FrontendProtocol = PG_PROTOCOL_LATEST;
 int                    Portfd = -1;
 int                    Noversion = 0;
 int                    Quiet = 1;
index e6ec2c65597d815289a88bfc079dd2b49d600fec..549f3481a68bdad1bf828281d3438d3ce43a9921 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: c.h,v 1.28 1998/01/24 22:47:43 momjian Exp $
+ * $Id: c.h,v 1.29 1998/01/26 01:41:49 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -204,21 +204,23 @@ typedef char *Pointer;
 
 /*
  * intN --
- *             Signed integer, AT LEAST N BITS IN SIZE,
- *             used for numerical computations.
+ *             Signed integer, EXACTLY N BITS IN SIZE,
+ *             used for numerical computations and the
+ *             frontend/backend protocol.
  */
-typedef signed char int8;              /* >= 8 bits */
-typedef signed short int16;            /* >= 16 bits */
-typedef signed int int32;              /* >= 32 bits */
+typedef signed char int8;              /* == 8 bits */
+typedef signed short int16;            /* == 16 bits */
+typedef signed int int32;              /* == 32 bits */
 
 /*
  * uintN --
- *             Unsigned integer, AT LEAST N BITS IN SIZE,
- *             used for numerical computations.
+ *             Unsigned integer, EXACTLY N BITS IN SIZE,
+ *             used for numerical computations and the
+ *             frontend/backend protocol.
  */
-typedef unsigned char uint8;   /* >= 8 bits */
-typedef unsigned short uint16; /* >= 16 bits */
-typedef unsigned int uint32;   /* >= 32 bits */
+typedef unsigned char uint8;   /* == 8 bits */
+typedef unsigned short uint16; /* == 16 bits */
+typedef unsigned int uint32;   /* == 32 bits */
 
 /*
  * floatN --
index 6a4160e65df0b8c911370ee9a4fb7e3ae142b92a..bf85ee599618df3b9d6a5743c4342440ebe2c866 100644 (file)
@@ -6,40 +6,22 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: auth.h,v 1.7 1997/09/08 21:52:28 momjian Exp $
+ * $Id: auth.h,v 1.8 1998/01/26 01:42:05 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef AUTH_H
 #define AUTH_H
 
-#include <libpq/pqcomm.h>
+#include "libpq/libpq-be.h"
 
 /*----------------------------------------------------------------
  * Common routines and definitions
  *----------------------------------------------------------------
  */
 
-/* what we call "no authentication system" */
-#define UNAUTHNAME                             "unauth"
-
-/* what a frontend uses by default */
-#if !defined(KRB4) && !defined(KRB5)
-#define DEFAULT_CLIENT_AUTHSVC UNAUTHNAME
-#else                                                  /* KRB4 || KRB5 */
-#define DEFAULT_CLIENT_AUTHSVC "kerberos"
-#endif                                                 /* KRB4 || KRB5 */
-
-extern int     fe_sendauth(MsgType msgtype, Port *port, char *hostname);
-extern void fe_setauthsvc(char *name);
-extern MsgType fe_getauthsvc();
-extern char *fe_getauthname(void);
-extern int     be_recvauth(MsgType msgtype, Port *port, char *username, StartupInfo *sp);
-extern void be_setauthsvc(char *name);
-
-/* the value that matches any dbName value when doing
-   host based authentication*/
-#define ALL_DBNAME             "*"
+void be_recvauth(Port *port);
+void auth_failed(Port *port);
 
 #define PG_KRB4_VERSION "PGVER4.1"             /* at most KRB_SENDAUTH_VLEN chars */
 #define PG_KRB5_VERSION "PGVER5.1"
index 928ff86a9c43c71c2be53f34c115a2c031fc4408..77d4fb7d03b1abf711261cbf9302e3b8c8820a6b 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef PG_CRYPT_H
 #define PG_CRYPT_H
 
-#include <libpq/pqcomm.h>
+#include <libpq/libpq-be.h>
 
 #define CRYPT_PWD_FILE "pg_pwd"
 #define CRYPT_PWD_FILE_SEPCHAR "'\\t'"
@@ -21,7 +21,9 @@ extern int        pwd_cache_count;
 
 extern char* crypt_getpwdfilename(void);
 extern char* crypt_getpwdreloadfilename(void);
+#ifdef 0
 extern MsgType crypt_salt(const char* user);
+#endif
 extern int crypt_verify(Port* port, const char* user, const char* pgpass);
 
 #endif
index 31ae6f2c0db7cb2f8b8dc678cbf4c4ed514431da..fdadfc0d85c57ddcd126aac9a46885abca3d9899 100644 (file)
@@ -4,14 +4,17 @@
  *       Interface to hba.c
  *
  *
- * $Id: hba.h,v 1.6 1998/01/24 22:49:15 momjian Exp $
+ * $Id: hba.h,v 1.7 1998/01/26 01:42:15 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef HBA_H
 #define HBA_H
 
-#include <libpq/pqcomm.h>
+#include <netinet/in.h>
+
+#include "libpq/libpq-be.h"
+
 
 #define CONF_FILE "pg_hba.conf"
  /* Name of the config file  */
@@ -28,7 +31,7 @@
 #define MAX_TOKEN 80
 /* Maximum size of one token in the configuration file */
 
-#define USERMAP_NAME_SIZE 16   /* Max size of a usermap name */
+#define MAX_AUTH_ARG   80      /* Max size of an authentication arg */
 
 #define IDENT_PORT 113
  /* Standard TCP port number for Ident service.  Assigned by IANA */
 #define IDENT_USERNAME_MAX 512
  /* Max size of username ident server can return */
 
-enum Userauth
-{
-       Trust, Ident,
-                               Password
-};
-
-extern int hba_recvauth(const Port *port, const char database[], const char user[],
-                        const char DataDir[]);
-void
-find_hba_entry(const char DataDir[], const struct in_addr ip_addr,
-                          const char database[],
-                          bool *host_ok_p, enum Userauth * userauth_p,
-                          char usermap_name[], bool find_password_entries);
+typedef enum UserAuth {
+       uaReject,
+       uaKrb4,
+       uaKrb5,
+       uaTrust,
+       uaIdent,
+       uaPassword,
+       uaCrypt
+} UserAuth;
+
+int hba_getauthmethod(SockAddr *raddr, char *database, char *auth_arg,
+                                               UserAuth *auth_method);
+int authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr,
+                               const char postgres_username[], const char auth_arg[]);
 
 #endif
index e65d9b3232c53826b16f40e49783f295fa0271bf..4d0e186198c485b0108347ffb1e11445f4e11a17 100644 (file)
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-be.h,v 1.8 1998/01/24 22:49:18 momjian Exp $
+ * $Id: libpq-be.h,v 1.9 1998/01/26 01:42:17 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef LIBPQ_BE_H
 #define LIBPQ_BE_H
 
-#include <access/htup.h>
-#include <access/tupdesc.h>
-#include <libpq/libpq.h>
+#include <stdio.h>
+#include <sys/types.h>
 
-/* ----------------
- *             include stuff common to fe and be
- * ----------------
+#include "libpq/pqcomm.h"
+#include "libpq/hba.h"
+
+
+/* Protocol v0 password packet. */
+
+typedef struct PasswordPacketV0 {
+       uint32          unused;
+       char            data[288];              /* User and password as strings. */
+} PasswordPacketV0;
+
+
+/*
+ * Password packet.  The length of the password can be changed without
+ * affecting anything.
  */
+  
+typedef struct PasswordPacket {
+       char            passwd[100];            /* The password. */
+} PasswordPacket;
+
+
+/* Error message packet. */
+
+typedef struct ErrorMessagePacket {
+       char            data[1 + 100];          /* 'E' + the message. */
+} ErrorMessagePacket;
+
+
+/* Authentication request packet. */
+
+typedef struct AuthRequestPacket {
+       char            data[1 + sizeof (AuthRequest) + 2];     /* 'R' + the request + optional salt. */
+} AuthRequestPacket;
+
+  
+/* These are used by the packet handling routines. */
 
+typedef enum {
+       Idle,
+       ReadingPacketLength,
+       ReadingPacket,
+       WritingPacket
+} PacketState;
 
-/* ----------------
- *             declarations for backend libpq support routines
- * ----------------
+typedef struct Packet {
+       PacketState     state;                  /* What's in progress. */
+       PacketLen       len;                    /* Actual length */
+       int             nrtodo;                 /* Bytes still to transfer */
+       char            *ptr;                   /* Buffer pointer */
+       void            (*iodone)();            /* I/O complete callback */
+       char            *arg;                   /* Argument to callback */
+
+       /* A union of all the different packets. */
+
+       union {
+               /* These are outgoing so have no packet length prepended. */
+
+               ErrorMessagePacket      em;
+               AuthRequestPacket       ar;
+
+               /* These are incoming and have a packet length prepended. */
+
+               StartupPacket           si;
+               PasswordPacketV0        pwv0;
+               PasswordPacket          pw;
+       } pkt;
+} Packet;
+
+
+/*
+ * This is used by the postmaster in its communication with frontends.  It is
+ * contains all state information needed during this communication before the
+ * backend is run.
  */
+  
+typedef struct Port {
+       int             sock;                   /* File descriptor */
+       Packet          pktInfo;                /* For the packet handlers */
+       SockAddr        laddr;                  /* local addr (us) */
+       SockAddr        raddr;                  /* remote addr (them) */
+       char            salt[2];                /* Password salt */
+
+       /*
+        * Information that needs to be held during the fe/be authentication
+        * handshake.
+        */
+
+       ProtocolVersion proto;
+       char            database[SM_DATABASE + 1];
+       char            user[SM_USER + 1];
+       char            options[SM_OPTIONS + 1];
+       char            tty[SM_TTY + 1];
+       char            auth_arg[MAX_AUTH_ARG];
+       UserAuth        auth_method;
+} Port;
 
-/* in be-dumpdata.c */
-extern void be_portalinit(void);
-extern void be_portalpush(PortalEntry *entry);
-extern PortalEntry *be_portalpop(void);
-extern PortalEntry *be_currentportal(void);
-extern PortalEntry *be_newportal(void);
-extern void be_typeinit(PortalEntry *entry, TupleDesc attrs,
-                       int natts);
-extern void be_printtup(HeapTuple tuple, TupleDesc typeinfo);
-
-
-/* in be-pqexec.c */
-extern char * PQfn(int fnid, int *result_buf, int result_len, int result_is_int,
-        PQArgBlock *args, int nargs);
-extern char *PQexec(char *query);
-extern int     pqtest_PQexec(char *q);
-extern int     pqtest_PQfn(char *q);
-extern int32 pqtest(struct varlena * vlena);
 
+extern FILE *Pfout, *Pfin;
+extern int PQAsyncNotifyWaiting;
+extern ProtocolVersion FrontendProtocol;
+
+
+/*
+ * prototypes for functions in pqpacket.c
+ */
+void PacketReceiveSetup(Packet *pkt, void (*iodone)(), char *arg);
+int PacketReceiveFragment(Packet *pkt, int sock);
+void PacketSendSetup(Packet *pkt, int nbytes, void (*iodone)(), char *arg);
+int PacketSendFragment(Packet *pkt, int sock);
+void PacketSendError(Packet *pkt, char *errormsg);
+  
 #endif                                                 /* LIBPQ_BE_H */
index 19e5ca8fa54ee8614e62ca2fc592ec8e3e14fc5e..a77a2afccffa12018fe12c3d46f8cc5c5c503b5f 100644 (file)
@@ -6,20 +6,19 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq.h,v 1.9 1998/01/24 22:49:21 momjian Exp $
- *
- * NOTES
- *       This file contains definitions for structures and
- *       externs for functions used by both frontend applications
- *       and the POSTGRES backend.  See the files libpq-fe.h and
- *       libpq-be.h for frontend/backend specific information
+ * $Id: libpq.h,v 1.10 1998/01/26 01:42:18 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef LIBPQ_H
 #define LIBPQ_H
 
-#include <libpq/pqcomm.h>
+#include <netinet/in.h>
+
+#include "libpq/libpq-be.h"
+#include "access/htup.h"
+#include "access/tupdesc.h"
+
 
 /* ----------------
  * PQArgBlock --
@@ -228,6 +227,27 @@ extern int pbuf_findFnumber(GroupBuffer *group, char *field_name);
 extern void pbuf_checkFnumber(GroupBuffer *group, int field_number);
 extern char *pbuf_findFname(GroupBuffer *group, int field_number);
 
+/* in be-dumpdata.c */
+extern void be_portalinit(void);
+extern void be_portalpush(PortalEntry *entry);
+extern PortalEntry *be_portalpop(void);
+extern PortalEntry *be_currentportal(void);
+extern PortalEntry *be_newportal(void);
+extern void
+be_typeinit(PortalEntry *entry, TupleDesc attrs,
+                       int natts);
+extern void be_printtup(HeapTuple tuple, TupleDesc typeinfo);
+
+
+/* in be-pqexec.c */
+extern char *
+PQfn(int fnid, int *result_buf, int result_len, int result_is_int,
+        PQArgBlock *args, int nargs);
+extern char *PQexec(char *query);
+extern int     pqtest_PQexec(char *q);
+extern int     pqtest_PQfn(char *q);
+extern int32 pqtest(struct varlena * vlena);
+
 /*
  * prototypes for functions in pqcomm.c
  */
index 28b279a7c086a6ef24d3d65c58e656373792f0f3..f0c24794c3ea2b9f4b0f6c0b01bf0a24dad5e3e4 100644 (file)
@@ -1,13 +1,6 @@
 #ifndef PASSWORD_H
 #define PASSWORD_H
 
-#include <libpq/hba.h>
-#include <libpq/pqcomm.h>
-
-#define PWFILE_NAME_SIZE USERMAP_NAME_SIZE
-
-int
-verify_password(char *user, char *password, Port *port,
-                               char *database, char *DataDir);
+int verify_password(char *auth_arg, char *user, char *password);
 
 #endif
index 1b2823b7b1bb7130fb8e8135e344d4d41c59ec51..5f8633f7e4cc2577818da11358a66d4d9ee85e2b 100644 (file)
@@ -1,15 +1,12 @@
 /*-------------------------------------------------------------------------
  *
  * pqcomm.h--
- *       Parameters for the communication module
+ *      Definitions common to frontends and backends.
  *
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqcomm.h,v 1.18 1998/01/24 22:49:23 momjian Exp $
- *
- * NOTES
- *       Some of this should move to libpq.h
+ * $Id: pqcomm.h,v 1.19 1998/01/26 01:42:21 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include <stdio.h>
 #include <sys/types.h>
-#include <netinet/in.h>
+#include <sys/socket.h>
 #include <sys/un.h>
+#include <netinet/in.h>
+
+#include "c.h"
+
+
+/* Define a generic socket address type. */
+
+typedef union SockAddr {
+       struct sockaddr         sa;
+       struct sockaddr_in      in;
+       struct sockaddr_un      un;
+} SockAddr;
+
+
+/* Configure the UNIX socket address for the well known port. */
+
+#define        UNIXSOCK_PATH(sun,port) \
+       (sprintf((sun).sun_path, "/tmp/.s.PGSQL.%d", (port)) + \
+               sizeof ((sun).sun_family))
+
+
+/*
+ * These manipulate the frontend/backend protocol version number.
+ *
+ * The major number should be incremented for incompatible changes.  The minor
+ * number should be incremented for compatible changes (eg. additional
+ * functionality).
+ *
+ * If a backend supports version m.n of the protocol it must actually support
+ * versions m.0..n].  Backend support for version m-1 can be dropped after a
+ * `reasonable' length of time.
+ *
+ * A frontend isn't required to support anything other than the current
+ * version.
+ */
+
+#define        PG_PROTOCOL_MAJOR(v)    ((v) >> 16)
+#define        PG_PROTOCOL_MINOR(v)    ((v) & 0x0000ffff)
+#define        PG_PROTOCOL(m,n)        (((m) << 16) | (n))
 
+/* The earliest and latest frontend/backend protocol version supported. */
+
+#define        PG_PROTOCOL_EARLIEST    PG_PROTOCOL(0,0)
+#define        PG_PROTOCOL_LATEST      PG_PROTOCOL(1,0)
 
 /*
- * startup msg parameters: path length, argument string length
+ * All packets sent to the postmaster start with the length.  This is omitted
+ * from the different packet definitions specified below.
  */
-#define PATH_SIZE              64
-#define ARGV_SIZE              64
-
-#define UNIXSOCK_PATH(sun,port) \
-  sprintf(sun.sun_path,"/tmp/.s.PGSQL.%d",port) + sizeof(sun.sun_family) + 1;
-
-
-/* The various kinds of startup messages are for the various kinds of
-   user authentication systems.  In the beginning, there was only
-   STARTUP_MSG and all connections were unauthenticated.  Now, there are
-   several choices of authentication method (the client picks one, but
-   the server needn't necessarily accept it).  So now, the STARTUP_MSG
-   message means to start either an unauthenticated or a host-based
-   authenticated connection, depending on what the server prefers.     This
-   is possible because the protocol between server and client is the same
-   in both cases (basically, no negotiation is required at all).
-   */
-
-typedef enum _MsgType
-{
-       ACK_MSG = 0,                            /* acknowledge a message */
-       ERROR_MSG = 1,                          /* error response to client from server */
-       RESET_MSG = 2,                          /* client must reset connection */
-       PRINT_MSG = 3,                          /* tuples for client from server */
-       NET_ERROR = 4,                          /* error in net system call */
-       FUNCTION_MSG = 5,                       /* fastpath call (unused) */
-       QUERY_MSG = 6,                          /* client query to server */
-       STARTUP_MSG = 7,                        /* initialize a connection with a backend */
-       DUPLICATE_MSG = 8,                      /* duplicate msg arrived (errors msg only) */
-       INVALID_MSG = 9,                        /* for some control functions */
-       STARTUP_KRB4_MSG = 10,          /* krb4 session follows startup packet */
-       STARTUP_KRB5_MSG = 11,          /* krb5 session follows startup packet */
-       STARTUP_HBA_MSG = 12,           /* use host-based authentication */
-       STARTUP_UNAUTH_MSG = 13,        /* use unauthenticated connection */
-       STARTUP_PASSWORD_MSG = 14,      /* use plaintext password authentication */
-        /* The following three are not really a named authentication method
-           * since the front end has no choice in choosing the method.  The
-           * backend sends the SALT/UNSALT messages back to the frontend after
-           * the USER login has been given to the backend.
-           */
-       STARTUP_CRYPT_MSG = 15,               /* use crypt()'ed password authentication */
-       STARTUP_USER_MSG = 16,          /* send user name to check pg_user for password */
-       STARTUP_SALT_MSG = 17,          /* frontend should crypt the password it sends */
-       STARTUP_UNSALT_MSG = 18         /* frontend should NOT crypt the password it sends */
-       /* insert new values here -- DO NOT REORDER OR DELETE ENTRIES */
-       /* also change LAST_AUTHENTICATION_TYPE below and add to the */
-       /* authentication_type_name[] array in pqcomm.c */
-} MsgType;
-
-#define LAST_AUTHENTICATION_TYPE 14
-
-typedef char *Addr;
-typedef int PacketLen;                 /* packet length */
-
-
-typedef struct StartupInfo
-{
-/*        PacketHdr            hdr; */
-       char            database[PATH_SIZE];    /* database name */
-       char            user[NAMEDATALEN];              /* user name */
-       char            options[ARGV_SIZE];             /* possible additional args */
-       char            execFile[ARGV_SIZE];    /* possible backend to use */
-       char            tty[PATH_SIZE]; /* possible tty for debug output */
-} StartupInfo;
-
-/* amount of available data in a packet buffer */
-#define MESSAGE_SIZE   sizeof(StartupInfo)
-
-/* I/O can be blocking or non-blocking */
-#define BLOCKING               (FALSE)
-#define NON_BLOCKING   (TRUE)
-
-/* a PacketBuf gets shipped from client to server so be careful
-   of differences in representation.
-   Be sure to use htonl() and ntohl() on the len and msgtype fields! */
-typedef struct PacketBuf
-{
-       int                     len;
-       MsgType         msgtype;
-       char            data[MESSAGE_SIZE];
-} PacketBuf;
-
-/* update the conversion routines
-  StartupInfo2PacketBuf() and PacketBuf2StartupInfo() (decl. below)
-  if StartupInfo or PacketBuf structs ever change */
 
+typedef uint32 PacketLen;
+
 /*
- * socket descriptor port
- *             we need addresses of both sides to do authentication calls
+ * Startup message parameters sizes.  These must not be changed without changing
+ * the protcol version.  These are all strings that are '\0' terminated only if
+ * there is room.
  */
-typedef struct Port
-{
-       int                     sock;                   /* file descriptor */
-       int                     mask;                   /* select mask */
-       int                     nBytes;                 /* nBytes read in so far */
-       /* local addr (us) */
-        union {  struct sockaddr_in in; struct sockaddr_un un; } laddr;
-        /* remote addr (them) */
-        union {  struct sockaddr_in in; struct sockaddr_un un; }  raddr;
-       /*
-        * PacketBufId                          id;
-*//* id of packet buf currently in use */
-       PacketBuf       buf;                    /* stream implementation (curr pack buf) */
-       char            salt[2];
-} Port;
-
-/* invalid socket descriptor */
-#define INVALID_SOCK   (-1)
-
-#define INVALID_ID (-1)
-#define MAX_CONNECTIONS 10
-#define N_PACK_BUFS            20
-
-/* no multi-packet messages yet */
-#define MAX_PACKET_BACKLOG             1
-
-#define DEFAULT_STRING                 ""
-
-extern FILE *Pfout,
-                  *Pfin;
-extern int     PQAsyncNotifyWaiting;
+
+#define        SM_DATABASE             64
+#define        SM_USER                 32
+#define        SM_OPTIONS              64
+#define        SM_UNUSED               64
+#define        SM_TTY                  64
+
+typedef uint32 ProtocolVersion;                        /* Fe/Be protocol version nr. */
+
+typedef struct StartupPacket {
+       ProtocolVersion protoVersion;           /* Protocol version */
+       char            database[SM_DATABASE];  /* Database name */
+       char            user[SM_USER];          /* User name */
+       char            options[SM_OPTIONS];    /* Optional additional args */
+       char            unused[SM_UNUSED];      /* Unused */
+       char            tty[SM_TTY];            /* Tty for debug output */
+} StartupPacket;
+
+
+/* These are the authentication requests sent by the backend. */
+
+#define        AUTH_REQ_OK             0               /* User is authenticated  */
+#define        AUTH_REQ_KRB4           1               /* Kerberos V4 */
+#define        AUTH_REQ_KRB5           2               /* Kerberos V5 */
+#define        AUTH_REQ_PASSWORD       3               /* Password */
+#define        AUTH_REQ_CRYPT          4               /* Encrypted password */
+
+typedef uint32 AuthRequest;
+
+
+/* This next section is to maintain compatibility with protocol v0.0. */
+
+#define        STARTUP_MSG             7       /* Initialise a connection */
+#define        STARTUP_KRB4_MSG        10      /* krb4 session follows */
+#define        STARTUP_KRB5_MSG        11      /* krb5 session follows */
+#define        STARTUP_PASSWORD_MSG    14      /* Password follows */
+
+typedef ProtocolVersion MsgType;
+
 
 /* in pqcompriv.c */
 int                    pqGetShort(int *, FILE *);
@@ -160,15 +128,4 @@ int                        pqPutNBytes(const char *, size_t, FILE *);
 int                    pqPutString(const char *, FILE *);
 int                    pqPutByte(int, FILE *);
 
-/*
- * prototypes for functions in pqpacket.c
- */
-extern int     PacketReceive(Port *port, PacketBuf *buf, char nonBlocking);
-extern int PacketSend(Port *port, PacketBuf *buf,
-                  PacketLen len, char nonBlocking);
-
-/* extern PacketBuf* StartupInfo2PacketBuf(StartupInfo*); */
-/* extern StartupInfo* PacketBuf2StartupInfo(PacketBuf*); */
-extern char *name_of_authentication_type(int type);
-
 #endif                                                 /* PQCOMM_H */
index dd9c774a1180f6116ee42cdd70b9e5a54376686f..5f9c26d2db632346d141321cc9856cfa660f2664 100644 (file)
@@ -7,10 +7,13 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.4 1998/01/17 23:39:11 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.5 1998/01/26 01:42:24 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
+SO_MAJOR_VERSION=1
+SO_MINOR_VERSION=1
+
 SRCDIR= ../..
 include $(SRCDIR)/Makefile.global
 
@@ -19,7 +22,7 @@ INCLUDE_OPT= -I$(SRCDIR)/include -I$(SRCDIR)/backend
 
 PORTNAME=@PORTNAME@
 
-CFLAGS+= $(INCLUDE_OPT) 
+CFLAGS+= $(INCLUDE_OPT) -DFRONTEND
 
 ifdef KRBVERS
 CFLAGS+= $(KRBFLAGS)
@@ -34,20 +37,20 @@ install-shlib-dep :=
 ifeq ($(PORTNAME), linux)
   ifdef LINUX_ELF
     install-shlib-dep := install-shlib
-    shlib := libpq.so.1
+    shlib := libpq.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
     LDFLAGS_SL = -shared
     CFLAGS += $(CFLAGS_SL)
   endif
 endif
 ifeq ($(PORTNAME), bsd)
   install-shlib-dep := install-shlib
-  shlib := libpq.so.1.0
+  shlib := libpq.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
   LDFLAGS_SL = -x -Bshareable -Bforcearchive
   CFLAGS += $(CFLAGS_SL)
 endif
 ifeq ($(PORTNAME), i386_solaris)
   install-shlib-dep := install-shlib
-  shlib := libpq.so.1
+  shlib := libpq.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
   LDFLAGS_SL = -G -z text
   CFLAGS += $(CFLAGS_SL)
 endif
index 8f96230f02d1ecc263e670ad79c5230918161c69..7f25afcb38eb24ec2b8cd8f4de9c975441cdeafd 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.12 1997/12/04 00:28:08 scrappy Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.13 1998/01/26 01:42:25 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "fe-auth.h"
 #include "fe-connect.h"
 
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+
 /*----------------------------------------------------------------
  * common definitions for generic fe/be routines
  *----------------------------------------------------------------
@@ -457,49 +462,49 @@ pg_krb5_sendauth(const char *PQerrormsg, int sock,
 #endif                                                 /* KRB5 */
 
 static int
-pg_password_sendauth(Port *port, const char *user, const char *password)
+pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
 {
-       PacketBuf       buf;
-       char       *tmp;
+       /* Encrypt the password if needed. */
 
-       buf.len = htonl(sizeof(PacketBuf));
-       buf.msgtype = STARTUP_PASSWORD_MSG;
-       buf.data[0] = '\0';
+       if (areq == AUTH_REQ_CRYPT)
+               password = crypt(password, conn->salt);
 
-       tmp = buf.data;
-       strncpy(tmp, user, strlen(user) + 1);
-       tmp += strlen(user) + 1;
-       strncpy(tmp, password, strlen(password) + 1);
-
-       return packetSend(port, &buf, sizeof(PacketBuf), BLOCKING);
+       return packetSend(conn, password, strlen(password) + 1);
 }
 
 /*
  * fe_sendauth -- client demux routine for outgoing authentication information
  */
 int
-fe_sendauth(MsgType msgtype, Port *port, const char *hostname,
-                 const char *user, const char *password, const char *PQerrormsg)
+fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
+                 const char *password, const char *PQerrormsg)
 {
-       switch (msgtype)
+       switch (areq)
        {
+       case AUTH_REQ_OK:
+               break;
+
+       case AUTH_REQ_KRB4:
 #ifdef KRB4
-                       case STARTUP_KRB4_MSG:
-                       if (pg_krb4_sendauth(PQerrormsg, port->sock, &port->laddr,
-                                                                &port->raddr,
+                       if (pg_krb4_sendauth(PQerrormsg, conn->sock, &conn->laddr.in,
+                                                                &conn->raddr.in,
                                                                 hostname) != STATUS_OK)
                        {
                                (void) sprintf(PQerrormsg,
                                                        "fe_sendauth: krb4 authentication failed\n");
-/*                     fputs(PQerrormsg, stderr); */
                                return (STATUS_ERROR);
                        }
                        break;
+#else
+               (void)sprintf(PQerrormsg,
+                               "fe_sendauth: krb4 authentication not supported\n");
+               return (STATUS_ERROR);
 #endif
+
+       case AUTH_REQ_KRB5:
 #ifdef KRB5
-               case STARTUP_KRB5_MSG:
-                       if (pg_krb5_sendauth(PQerrormsg, port->sock, &port->laddr,
-                                                                &port->raddr,
+                       if (pg_krb5_sendauth(PQerrormsg, conn->sock, &conn->laddr.in,
+                                                                &conn->raddr.in,
                                                                 hostname) != STATUS_OK)
                        {
                                (void) sprintf(PQerrormsg,
@@ -507,15 +512,29 @@ fe_sendauth(MsgType msgtype, Port *port, const char *hostname,
                                return (STATUS_ERROR);
                        }
                        break;
+#else
+               (void)sprintf(PQerrormsg,
+                               "fe_sendauth: krb5 authentication not supported\n");
+               return (STATUS_ERROR);
 #endif
-               case STARTUP_MSG:
-                       break;
-               case STARTUP_PASSWORD_MSG:
-               case STARTUP_CRYPT_MSG:
-                       pg_password_sendauth(port, user, password);
-               default:
-                       break;
-       }
+
+       case AUTH_REQ_PASSWORD:
+       case AUTH_REQ_CRYPT:
+               if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
+               {
+                       (void)sprintf(PQerrormsg,
+                                       "fe_sendauth: error sending password authentication\n");
+                       return (STATUS_ERROR);
+               }
+
+               break;
+
+       default:
+               (void)sprintf(PQerrormsg,
+                               "fe_sendauth: authentication type %u not supported\n",areq);
+               return (STATUS_ERROR);
+       }
+
        return (STATUS_OK);
 }
 
index 6f188a541ec95290490bdccce910f2d2626fcd44..e4676fcd97ba815748bf6549103e6962980fb1ac 100644 (file)
@@ -6,13 +6,16 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fe-auth.h,v 1.6 1997/09/08 21:55:35 momjian Exp $
+ * $Id: fe-auth.h,v 1.7 1998/01/26 01:42:26 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef FE_AUTH_H
 #define FE_AUTH_H
 
+#include "libpq-fe.h"
+
+
 /*----------------------------------------------------------------
  * Common routines and definitions
  *----------------------------------------------------------------
@@ -29,9 +32,8 @@
 #endif                                                 /* KRB4 || KRB5 */
 
 extern int
-fe_sendauth(MsgType msgtype, Port *port, const char *hostname,
-                       const char *user, const char *password,
-                       const char *PQerromsg);
+fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
+                       const char *password, const char *PQerromsg);
 extern void fe_setauthsvc(const char *name, char *PQerrormsg);
 
 #define PG_KRB4_VERSION "PGVER4.1"             /* at most KRB_SENDAUTH_VLEN chars */
index 37dd88d425d8968dc27376cafbc508ab692932ce..ee95ac59de5dcfca07e2cfbf4f9e3bdf16dd4814 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.58 1998/01/23 02:31:18 scrappy Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.59 1998/01/26 01:42:28 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <ctype.h>
 #include <string.h>
 #include <netdb.h>
+#include <sys/un.h>
+#include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <errno.h>
 #include <signal.h>
 #include <ctype.h>                             /* for isspace() */
 
 #include "postgres.h"
-#include "libpq/pqcomm.h"              /* for decls of MsgType, PacketBuf,
-                                                                * StartupInfo */
 #include "fe-auth.h"
 #include "fe-connect.h"
 #include "libpq-fe.h"
@@ -44,7 +44,6 @@
 /* use a local version instead of the one found in pqpacket.c */
 static ConnStatusType connectDB(PGconn *conn);
 
-static void startup2PacketBuf(StartupInfo *s, PacketBuf *res);
 static void freePGconn(PGconn *conn);
 static void closePGconn(PGconn *conn);
 static int     conninfo_parse(const char *conninfo, char *errorMessage);
@@ -78,6 +77,7 @@ static PQconninfoOption PQconninfoOptions[] = {
 /*       Option-name           Environment-Var Compiled-in             Current value   */
 /*                                             Label                                                   Disp-Char               */
 /* ----------------- --------------- --------------- --------------- */
+       /* "authtype" is ignored as it is no longer used. */
        {"authtype", "PGAUTHTYPE", DefaultAuthtype, NULL,
        "Database-Authtype", "", 20},
 
@@ -183,7 +183,6 @@ PQconnectdb(const char *conninfo)
        conn->Pfout = NULL;
        conn->Pfin = NULL;
        conn->Pfdebug = NULL;
-       conn->port = NULL;
        conn->notifyList = DLNewList();
 
        tmp = conninfo_getval("host");
@@ -198,8 +197,6 @@ PQconnectdb(const char *conninfo)
        conn->pguser = tmp ? strdup(tmp) : NULL;
        tmp = conninfo_getval("password");
        conn->pgpass = tmp ? strdup(tmp) : NULL;
-       tmp = conninfo_getval("authtype");
-       conn->pgauth = tmp ? strdup(tmp) : NULL;
        tmp = conninfo_getval("dbname");
        conn->dbName = tmp ? strdup(tmp) : NULL;
 
@@ -209,14 +206,6 @@ PQconnectdb(const char *conninfo)
         */
        conninfo_free();
 
-       /*
-        * try to set the auth service if one was specified
-        */
-       if (conn->pgauth)
-       {
-               fe_setauthsvc(conn->pgauth, conn->errorMessage);
-       }
-
        /* ----------
         * Connect to the database
         * ----------
@@ -326,7 +315,6 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions, cons
                conn->Pfout = NULL;
                conn->Pfin = NULL;
                conn->Pfdebug = NULL;
-               conn->port = NULL;
                conn->notifyList = DLNewList();
 
                if ((pghost == NULL) || pghost[0] == '\0')
@@ -467,44 +455,31 @@ connectDB(PGconn *conn)
 {
        struct hostent *hp;
 
-       StartupInfo startup;
-       PacketBuf       pacBuf;
-       PacketLen       pacLen;
-       int                     status;
-       MsgType         msgtype;
-       int                     laddrlen = sizeof(struct sockaddr);
-       Port       *port = conn->port;
+       StartupPacket   sp;
+       AuthRequest     areq;
+       int                     laddrlen = sizeof(SockAddr);
        int                     portno,
                                family,
                                len;
-       bool                    salted = false;
-       char*                   tmp;
 
        /*
         * Initialize the startup packet.
-        *
-        * This data structure is used for the seq-packet protocol.  It describes
-        * the frontend-backend connection.
-        *
-        *
         */
-       strncpy(startup.user, conn->pguser, sizeof(startup.user));
-       strncpy(startup.database, conn->dbName, sizeof(startup.database));
-       strncpy(startup.tty, conn->pgtty, sizeof(startup.tty));
+
+       MemSet((char *)&sp, 0, sizeof (StartupPacket));
+
+       sp.protoVersion = (ProtocolVersion)htonl(PG_PROTOCOL_LATEST);
+
+       strncpy(sp.user, conn->pguser, SM_USER);
+       strncpy(sp.database, conn->dbName, SM_DATABASE);
+       strncpy(sp.tty, conn->pgtty, SM_TTY);
+
        if (conn->pgoptions)
-       {
-               strncpy(startup.options, conn->pgoptions, sizeof(startup.options));
-       }
-       else
-               startup.options[0] = '\0';
-       startup.execFile[0] = '\0'; /* not used */
+               strncpy(sp.options, conn->pgoptions, SM_OPTIONS);
 
        /*
         * Open a connection to postmaster/backend.
-        *
         */
-       port = (Port *) malloc(sizeof(Port));
-       MemSet((char *) port, 0, sizeof(Port));
 
        if (conn->pghost != NULL)
        {
@@ -524,28 +499,28 @@ connectDB(PGconn *conn)
 #endif
        portno = atoi(conn->pgport);
        family = (conn->pghost != NULL) ? AF_INET : AF_UNIX;
-       port->raddr.in.sin_family = family;
+       conn->raddr.sa.sa_family = family;
        if (family == AF_INET)
        {
-               memmove((char *) &(port->raddr.in.sin_addr),
+               memmove((char *) &(conn->raddr.in.sin_addr),
                                (char *) hp->h_addr,
                                hp->h_length);
-               port->raddr.in.sin_port = htons((unsigned short) (portno));
+               conn->raddr.in.sin_port = htons((unsigned short) (portno));
                len = sizeof(struct sockaddr_in);
        }
        else
        {
-               len = UNIXSOCK_PATH(port->raddr.un, portno);
+               len = UNIXSOCK_PATH(conn->raddr.un, portno);
        }
        /* connect to the server  */
-       if ((port->sock = socket(family, SOCK_STREAM, 0)) < 0)
+       if ((conn->sock = socket(family, SOCK_STREAM, 0)) < 0)
        {
                (void) sprintf(conn->errorMessage,
                                           "connectDB() -- socket() failed: errno=%d\n%s\n",
                                           errno, strerror(errno));
                goto connect_errReturn;
        }
-       if (connect(port->sock, (struct sockaddr *) & port->raddr, len) < 0)
+       if (connect(conn->sock, &conn->raddr.sa, len) < 0)
        {
                (void) sprintf(conn->errorMessage,
                                           "connectDB() failed: Is the postmaster running and accepting%s connections at '%s' on port '%s'?\n",
@@ -566,7 +541,7 @@ connectDB(PGconn *conn)
                                                   "connectDB(): getprotobyname failed\n");
                        goto connect_errReturn;
                }
-               if (setsockopt(port->sock, pe->p_proto, TCP_NODELAY,
+               if (setsockopt(conn->sock, pe->p_proto, TCP_NODELAY,
                                           &on, sizeof(on)) < 0)
                {
                        (void) sprintf(conn->errorMessage,
@@ -576,8 +551,7 @@ connectDB(PGconn *conn)
        }
 
        /* fill in the client address */
-       if (getsockname(port->sock, (struct sockaddr *) & port->laddr,
-                                       &laddrlen) < 0)
+       if (getsockname(conn->sock, &conn->laddr.sa, &laddrlen) < 0)
        {
                (void) sprintf(conn->errorMessage,
                                   "connectDB() -- getsockname() failed: errno=%d\n%s\n",
@@ -585,81 +559,93 @@ connectDB(PGconn *conn)
                goto connect_errReturn;
        }
 
-       /* by this point, connection has been opened */
-
-        /* This section of code is new as of Nov 19, 1997.  It sends just the
-         * user's login to the backend.  This allows the backend to search
-         * pg_user to see if the user has a password defined.  If the user
-         * does have a password in pg_user, then the backend will send a
-         * packet back with a randomly generated salt, so the user's password
-         * can be encrypted.
-         */
-        pacLen = sizeof(pacBuf.len) + sizeof(pacBuf.msgtype) + strlen(startup.user) + 1;
-        pacBuf.len = htonl(pacLen);
-        pacBuf.msgtype = htonl(STARTUP_USER_MSG);
-        strcpy(pacBuf.data, startup.user);
-        status = packetSend(port, &pacBuf, pacLen, BLOCKING);
-        if (status == STATUS_ERROR) {
-          sprintf(conn->errorMessage, "connectDB() --  couldn't send complete packet: errno=%d\n%s\n", errno, strerror(errno));
-          goto connect_errReturn;
-        }
-
-        /* Check to see if the server sent us a salt back to encrypt the
-         * password to send for authentication. --TAB
-         */
-        status = packetReceive(port, &pacBuf, BLOCKING);
-
-        if (status != STATUS_OK) {
-          sprintf(conn->errorMessage, "connectDB() -- couldn't receive un/salt packet: errno=%d\n%s\n", errno, strerror(errno));
-          goto connect_errReturn;
-        }
-        pacBuf.msgtype = ntohl(pacBuf.msgtype);
-        switch (pacBuf.msgtype) {
-          case STARTUP_SALT_MSG:
-            salted = true;
-            if (!conn->pgpass) {
-              sprintf(conn->errorMessage, "connectDB() -- backend requested a password, but none was given\n");
-              goto connect_errReturn;
-            }
-            tmp = crypt(conn->pgpass, pacBuf.data);
-            free((void*)conn->pgpass);
-            conn->pgpass = strdup(tmp);
-            break;
-          case STARTUP_UNSALT_MSG:
-            salted = false;
-            break;
-          default:
-            sprintf(conn->errorMessage, "connectDB() -- backend did not supply a salt packet\n");
-            goto connect_errReturn;
-        }
-
-        if (salted)
-          msgtype = STARTUP_CRYPT_MSG;
-        else
-        msgtype = fe_getauthsvc(conn->errorMessage);
-
-/*       pacBuf = startup2PacketBuf(&startup);*/
-       startup2PacketBuf(&startup, &pacBuf);
-       pacBuf.msgtype = (MsgType) htonl(msgtype);
-       status = packetSend(port, &pacBuf, sizeof(PacketBuf), BLOCKING);
-
-       if (status == STATUS_ERROR)
+       /* set up the socket file descriptors */
+       conn->Pfout = fdopen(conn->sock, "w");
+       conn->Pfin = fdopen(dup(conn->sock), "r");
+       if ((conn->Pfout == NULL) || (conn->Pfin == NULL))
+       {
+               (void) sprintf(conn->errorMessage,
+                                          "connectDB() -- fdopen() failed: errno=%d\n%s\n",
+                                          errno, strerror(errno));
+               goto connect_errReturn;
+       }
+
+       /* Send the startup packet. */
+
+       if (packetSend(conn, (char *)&sp, sizeof(StartupPacket)) != STATUS_OK)
        {
                sprintf(conn->errorMessage,
                                "connectDB() --  couldn't send complete packet: errno=%d\n%s\n", errno, strerror(errno));
                goto connect_errReturn;
        }
 
-       /* authenticate as required */
-       if (fe_sendauth(msgtype, port, conn->pghost,
-                                       conn->pguser, conn->pgpass,
-                                       conn->errorMessage) != STATUS_OK)
+       /*
+        * Get the response from the backend, either an error message or an
+        * authentication request.
+        */
+
+       do
        {
-               (void) sprintf(conn->errorMessage,
-                                          "connectDB() --  authentication failed with %s\n",
-                                          conn->pghost);
-               goto connect_errReturn;
+               int beresp;
+
+               if ((beresp = pqGetc(conn->Pfin, conn->Pfdebug)) == EOF)
+               {
+                       (void)sprintf(conn->errorMessage,
+                                       "connectDB() -- error getting authentication request\n");
+
+                       goto connect_errReturn;
+               }
+
+               /* Handle errors. */
+
+               if (beresp == 'E')
+               {
+                       pqGets(conn->errorMessage, sizeof (conn->errorMessage),
+                               conn->Pfin, conn->Pfdebug);
+
+                       goto connect_errReturn;
+               }
+
+               /* Check it was an authentication request. */
+
+               if (beresp != 'R')
+               {
+                       (void)sprintf(conn->errorMessage,
+                                       "connectDB() -- expected authentication request\n");
+
+                       goto connect_errReturn;
+               }
+
+               /* Get the type of request. */
+
+               if (pqGetInt((int *)&areq, 4, conn->Pfin, conn->Pfdebug))
+               {
+                       (void)sprintf(conn->errorMessage,
+                                       "connectDB() -- error getting authentication request type\n");
+
+                       goto connect_errReturn;
+               }
+
+               /* Get the password salt if there is one. */
+
+               if (areq == AUTH_REQ_CRYPT &&
+                       pqGetnchar(conn->salt, sizeof (conn->salt),
+                                       conn->Pfin, conn->Pfdebug))
+               {
+                       (void)sprintf(conn->errorMessage,
+                                       "connectDB() -- error getting password salt\n");
+
+                       goto connect_errReturn;
+               }
+
+
+               /* Respond to the request. */
+
+               if (fe_sendauth(areq, conn, conn->pghost, conn->pgpass,
+                                       conn->errorMessage) != STATUS_OK)
+                       goto connect_errReturn;
        }
+       while (areq != AUTH_REQ_OK);
 
        /* free the password so it's not hanging out in memory forever */
        if (conn->pgpass != NULL)
@@ -667,30 +653,9 @@ connectDB(PGconn *conn)
                free(conn->pgpass);
        }
 
-       /* set up the socket file descriptors */
-       conn->Pfout = fdopen(port->sock, "w");
-       conn->Pfin = fdopen(dup(port->sock), "r");
-       if ((conn->Pfout == NULL) || (conn->Pfin == NULL))
-       {
-               (void) sprintf(conn->errorMessage,
-                                          "connectDB() -- fdopen() failed: errno=%d\n%s\n",
-                                          errno, strerror(errno));
-               goto connect_errReturn;
-       }
-
-       conn->port = port;
-
        return CONNECTION_OK;
 
 connect_errReturn:
-
-       /*
-        * Igor/6/3/97 - We need to free it here...otherwise the function
-        * returns without setting conn->port to port. Because of that any way
-        * of referencing this variable will be lost and it's allocated memory
-        * will not be freed.
-        */
-       free(port);                                     /* PURIFY */
        return CONNECTION_BAD;
 
 }
@@ -746,8 +711,6 @@ freePGconn(PGconn *conn)
                free(conn->pguser);
        if (conn->notifyList)
                DLFreeList(conn->notifyList);
-       if (conn->port)
-               free(conn->port);
        free(conn);
 }
 
@@ -845,113 +808,28 @@ PQreset(PGconn *conn)
  *
  * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
  * SIDE_EFFECTS: may block.
- * NOTES: Non-blocking writes would significantly complicate
- *             buffer management.      For now, we're not going to do it.
- *
 */
 int
-packetSend(Port *port,
-                  PacketBuf *buf,
-                  PacketLen len,
-                  bool nonBlocking)
+packetSend(PGconn *conn,
+                  char *buf,
+                  size_t len)
 {
-       PacketLen       doneLen = write(port->sock, buf, len);
+       /* Send the total packet size. */
 
-       if (doneLen < len)
-       {
-               return (STATUS_ERROR);
-       }
-       return (STATUS_OK);
-}
+       if (pqPutInt(4 + len, 4, conn->Pfout, conn->Pfdebug))
+               return STATUS_ERROR;
 
-/*
- * packetReceive()
- *
- This is a less stringent PacketReceive(), defined in backend/libpq/pqpacket.c
- We define it here to avoid linking in all of libpq.a
+       /* Send the packet itself. */
 
- * packetReceive -- receive a packet on a port
- *
- * RETURNS: STATUS_ERROR if the read fails, STATUS_OK otherwise.
- * SIDE_EFFECTS: may block.
- * NOTES: Non-blocking reads would significantly complicate
- *            buffer management.      For now, we're not going to do it.
- *
-*/
-int
-packetReceive(Port *port, PacketBuf *buf, bool nonBlocking) {
-
-  PacketLen     max_size = sizeof(PacketBuf);
-  PacketLen     cc;                           /* character count -- recvd */
-  PacketLen     packetLen;
-  int           addrLen = sizeof(struct sockaddr_in);
-  int         hdrLen;
-  int           msgLen;
-
-  /* Read the packet length into the PacketBuf
-   */
-  hdrLen = sizeof(PacketLen);
-  cc = recvfrom(port->sock, (char*)&packetLen, hdrLen, 0, (struct sockaddr*)&port->raddr, &addrLen);
-  if (cc < 0)
-    return STATUS_ERROR;
-  else if (!cc)
-    return STATUS_INVALID;
-  else if (cc < hdrLen)
-    return STATUS_NOT_DONE;
-
-  /* convert to local form of integer and check for oversized packet
-   */
-  buf->len = packetLen;
-  if ((packetLen = ntohl(packetLen)) > max_size) {
-    port->nBytes = packetLen;
-    return STATUS_INVALID;
-  }
-
-  /* fetch the rest of the message
-   */
-  msgLen = packetLen - cc;
-  cc = recvfrom(port->sock, (char*)&buf->msgtype, msgLen, 0, (struct sockaddr*)&port->raddr, &addrLen);
-  if (cc < 0)
-    return STATUS_ERROR;
-  else if (!cc)
-    return STATUS_INVALID;
-  else if (cc < msgLen)
-    return STATUS_NOT_DONE;
-
-  return STATUS_OK;
-}
+       if (pqPutnchar(buf, len, conn->Pfout, conn->Pfdebug))
+               return STATUS_ERROR;
 
-/*
- * startup2PacketBuf()
- *
- * this is just like StartupInfo2Packet(), defined in backend/libpq/pqpacket.c
- * but we repeat it here so we don't have to link in libpq.a
- *
- * converts a StartupInfo structure to a PacketBuf
- */
-static void
-startup2PacketBuf(StartupInfo *s, PacketBuf *res)
-{
-       char       *tmp;
+       pqFlush(conn->Pfout, conn->Pfdebug);
 
-/*     res = (PacketBuf*)malloc(sizeof(PacketBuf)); */
-       res->len = htonl(sizeof(PacketBuf));
-       /* use \n to delimit the strings */
-       res->data[0] = '\0';
-
-       tmp = res->data;
-
-       strncpy(tmp, s->database, sizeof(s->database));
-       tmp += sizeof(s->database);
-       strncpy(tmp, s->user, sizeof(s->user));
-       tmp += sizeof(s->user);
-       strncpy(tmp, s->options, sizeof(s->options));
-       tmp += sizeof(s->options);
-       strncpy(tmp, s->execFile, sizeof(s->execFile));
-       tmp += sizeof(s->execFile);
-       strncpy(tmp, s->tty, sizeof(s->tty));
+       return STATUS_OK;
 }
 
+
 /* ----------------
  * Conninfo parser routine
  * ----------------
index 7a68e3dedcd5f068f581173e3a16b99c662637b3..999ae05dac443aadbba9b4b780aab6a339a30cc1 100644 (file)
@@ -6,26 +6,23 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fe-connect.h,v 1.5 1997/12/04 00:28:13 scrappy Exp $
+ * $Id: fe-connect.h,v 1.6 1998/01/26 01:42:30 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef FE_CONNECT_H
 #define                   FE_CONNECT_H
 
+#include <sys/types.h>
+
+#include "libpq-fe.h"
+
+
 /*----------------------------------------------------------------
  * Common routines and definitions
  *----------------------------------------------------------------
  */
 
-extern int     packetSend(Port *port, PacketBuf *buf, PacketLen len, bool nonBlocking);
-extern int     packetReceive(Port *port, PacketBuf *buf, bool nonBlocking);
+int packetSend(PGconn *conn, char *buf, size_t len);
 
 #endif                                                 /* FE_CONNECT_H */
-#ifndef FE_CONNECT_H
-#define FE_CONNECT_H
-
-int                    packetSend(Port *port, PacketBuf *buf, PacketLen len, bool nonBlocking);
-int                    packetReceive(Port *port, PacketBuf *buf, bool nonBlocking);
-
-#endif
index 1f452ffe2d190fd6244fda1415828bdd6a731092..b9517cebbf20dfa014a6fb203792f9be9f76991b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.45 1997/12/23 20:00:06 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.46 1998/01/26 01:42:35 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -168,7 +168,7 @@ getTuple(PGconn *conn, PGresult *result, int binary)
        if ((nfields % BYTELEN) > 0)
                nbytes++;
 
-       if (pqGetnchar(bitmap, nbytes, pfin, pfdebug) == 1)
+       if (nbytes >= MAX_FIELDS || pqGetnchar(bitmap, nbytes, pfin, pfdebug) == 1)
        {
                sprintf(conn->errorMessage,
                          "Error reading null-values bitmap from row data stream\n");
@@ -189,10 +189,10 @@ getTuple(PGconn *conn, PGresult *result, int binary)
                else
                {
                        /* get the value length (the first four bytes are for length) */
-                       pqGetInt(&vlen, VARHDRSZ, pfin, pfdebug);
+                       pqGetInt(&vlen, 4, pfin, pfdebug);
                        if (binary == 0)
                        {
-                               vlen = vlen - VARHDRSZ;
+                               vlen = vlen - 4;
                        }
                        if (vlen < 0)
                                vlen = 0;
index 9f5fd907b54335fc07383f724fadb452c12a21cd..d1c18ee05aef2cb5e4cb6dae1630270c0aa92442 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.8 1997/09/08 21:55:44 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.9 1998/01/26 01:42:36 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,38 +51,28 @@ pqGetc(FILE *fin, FILE *debug)
 int
 pqPutnchar(const char *s, int len, FILE *f, FILE *debug)
 {
-       if (f == NULL)
-               return 1;
-
        if (debug)
                fprintf(debug, "To backend> %s\n", s);
 
-       if (fwrite(s, 1, len, f) != len)
-               return 1;
-
-       return 0;
+       return (pqPutNBytes(s, len, f) == EOF ? 1 : 0);
 }
 
 /* --------------------------------------------------------------------- */
 /* pqGetnchar:
-   get a string of exactly len length from stream f
+   get a string of exactly len bytes in buffer s (which must be 1 byte
+   longer) from stream f and terminate it with a '\0'.
 */
 int
 pqGetnchar(char *s, int len, FILE *f, FILE *debug)
 {
-       int                     cnt;
-
-       if (f == NULL)
-               return 1;
+       int status;
 
-       cnt = fread(s, 1, len, f);
-       s[cnt] = '\0';
-       /* mjl: actually needs up to len+1 bytes, is this okay? XXX */
+       status = pqGetNBytes(s, len, f);
 
        if (debug)
                fprintf(debug, "From backend (%d)> %s\n", len, s);
 
-       return 0;
+       return (status == EOF ? 1 : 0);
 }
 
 /* --------------------------------------------------------------------- */
@@ -92,21 +82,14 @@ pqGetnchar(char *s, int len, FILE *f, FILE *debug)
 int
 pqGets(char *s, int len, FILE *f, FILE *debug)
 {
-       int                     c;
-       const char *str = s;
-
-       if (f == NULL)
-               return 1;
+       int status;
 
-       while (len-- && (c = getc(f)) != EOF && c)
-               *s++ = c;
-       *s = '\0';
-       /* mjl: actually needs up to len+1 bytes, is this okay? XXX */
+       status = pqGetString(s, len, f);
 
        if (debug)
-               fprintf(debug, "From backend> \"%s\"\n", str);
+               fprintf(debug, "From backend> \"%s\"\n", s);
 
-       return 0;
+       return (status == EOF ? 1 : 0);
 }
 
 /* --------------------------------------------------------------------- */
@@ -173,20 +156,13 @@ pqGetInt(int *result, int bytes, FILE *f, FILE *debug)
 int
 pqPuts(const char *s, FILE *f, FILE *debug)
 {
-       if (f == NULL)
+       if (pqPutString(s, f) == EOF)
                return 1;
 
-       if (fputs(s, f) == EOF)
-               return 1;
-
-       fputc('\0', f);                         /* important to send an ending \0 since
-                                                                * backend expects it */
        fflush(f);
 
        if (debug)
-       {
                fprintf(debug, "To backend> %s\n", s);
-       }
 
        return 0;
 }
index ce54af85b04ee897f405ff0fa3406c5cbba4144d..933c3034051d1c3349ac0df5134e950be416b5c4 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-fe.h,v 1.24 1997/12/04 00:28:15 scrappy Exp $
+ * $Id: libpq-fe.h,v 1.25 1998/01/26 01:42:37 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -138,13 +138,15 @@ extern            "C"
                FILE       *Pfin;
                FILE       *Pfout;
                FILE       *Pfdebug;
-               void       *port;               /* really a Port* */
+               int                     sock;   /* The socket */
+               SockAddr                laddr;  /* Local address */
+               SockAddr                raddr;  /* Remote address */
+               char                    salt[2];
                int                     asyncNotifyWaiting;
                Dllist     *notifyList;
                char       *pguser;             /* Postgres username of user who is
                                                                 * connected */
                char       *pgpass;
-               char       *pgauth;
                PGlobjfuncs *lobjfuncs; /* Backend function OID's for large object
                                                                 * access */
        } PGconn;
index 07fc66a852d54e30d4dae5f0b961eeed102932d0..eece687004590bfad40c5af47ee4e106c4808ebd 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/createdb.1,v 1.6 1998/01/11 22:17:23 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/createdb.1,v 1.7 1998/01/26 01:42:42 scrappy Exp $
 .TH CREATEDB UNIX 11/05/95 PostgreSQL PostgreSQL
 .SH NAME
 createdb - create a database
@@ -60,7 +60,7 @@ Specifies an authentication system
 .IR pgintro (1))
 to use in connecting to the 
 .IR postmaster
-process.  The default is site-specific.
+process.  This option no longer has any effect.
 .TP
 .BR "-D" " dbpath"
 Specifies the alternate database location for this database.
@@ -79,13 +79,13 @@ is listening for connections.  Defaults to 5432, or the value of the
 environment variable (if set).
 .SH EXAMPLES
 .nf
-# create 5432 demo database
+# create the demo database using the postmaster on the local host, port 5432.
 createdb demo
 .fi
 .nf
 # create the demo database using the postmaster on host eden,
-# port using the Kerberos authentication system.
-createdb -a kerberos -p 5432 -h eden demo
+# port 5000.
+createdb -p 5000 -h eden demo
 .fi
 .SH FILES
 .TP 5n
index 2453f0cb0e36eed32e9f61a1463e8347c6900d75..30a4cbac62dff2539c41bf3d7ea862945943a678 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/createuser.1,v 1.5 1998/01/11 22:17:23 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/createuser.1,v 1.6 1998/01/26 01:42:44 scrappy Exp $
 .TH CREATEUSER UNIX 11/05/95 PostgreSQL PostgreSQL
 .SH NAME
 createuser - create a Postgres user
@@ -55,7 +55,7 @@ Specifies an authentication system
 .IR pgintro (1))
 to use in connecting to the 
 .IR postmaster
-process.  The default is site-specific.
+process.  This option no longer has any effect.
 .TP
 .BR "-h" " host"
 Specifies the hostname of the machine on which the 
index a3c9ea33585eeff86a18ddc6d068f20a43639b7a..b451df6c5182ab0e50fe22d4d867ad355c3d6d86 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/destroydb.1,v 1.6 1998/01/11 22:17:25 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/destroydb.1,v 1.7 1998/01/26 01:42:45 scrappy Exp $
 .TH DESTROYDB UNIX 11/05/95 PostgreSQL PostgreSQL
 .SH NAME
 destroydb - destroy an existing database
@@ -65,7 +65,7 @@ Specifies an authentication system
 .IR pgintro (1))
 to use in connecting to the 
 .IR postmaster
-process.  The default is site-specific.
+process.  This option no longer has any effect.
 .TP
 .BR "-h" " host"
 Specifies the hostname of the machine on which the 
@@ -85,9 +85,8 @@ environment variable (if set).
 destroydb demo
 .fi
 .nf
-# destroy 5432 demo database using the postmaster on host eden,
-# port using the Kerberos authentication system.
-destroydb -a kerberos -p 5432 -h eden demo
+# destroy the demo database using the postmaster on host eden, port 5000.
+destroydb -p 5000 -h eden demo
 .fi
 .SH FILES
 .TP 5n
index 454cc77f0964b3e9878c9053c6b1bcd5eaffc01f..a1a04baf442b233b53dc50dc61f57dbfd418fb41 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/destroyuser.1,v 1.5 1998/01/11 22:17:25 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/destroyuser.1,v 1.6 1998/01/26 01:42:46 scrappy Exp $
 .TH DESTROYUSER UNIX 11/05/95 PostgreSQL PostgreSQL
 .SH NAME
 destroyuser - destroy a Postgres user and associated databases
@@ -55,7 +55,7 @@ Specifies an authentication system
 .IR pgintro (1))
 to use in connecting to the 
 .IR postmaster
-process.  The default is site-specific.
+process.  This option no longer has any effect.
 .TP
 .BR "-h" " host"
 Specifies the hostname of the machine on which the 
index 7adcd3c3ded4dee780859afe2e02ca6034139fb1..10006001eb9764dd53d0f2b068f9b43b8deb5d03 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/libpq.3,v 1.11 1997/12/04 20:26:31 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/libpq.3,v 1.12 1998/01/26 01:42:47 scrappy Exp $
 .TH LIBPQ INTRO 03/12/94 PostgreSQL PostgreSQL
 .SH DESCRIPTION
 Libpq is the programmer's interface to Postgres.  Libpq is a set of
@@ -591,9 +591,9 @@ If the user has generated the appropriate authentication credentials
 .I Kerberos
 tickets), the frontend/backend authentication process is handled by
 .I PQexec
-without any further intervention.  The following routines may be
-called by Libpq programs to tailor the behavior of the authentication
-process.
+without any further intervention.  The authentication method is now
+determined entirely by the DBA (see pga_hba.conf(5)).  The following
+routines no longer have any effect and should not be used.
 .PP
 .B fe_getauthname
 .IP
index 00caaf4d7a84677855732f7a0cc2755bb0e8dca2..69f2b9540462069367a3f7aad2d276d99ce08643 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/pg_passwd.1,v 1.2 1998/01/11 22:17:48 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/pg_passwd.1,v 1.3 1998/01/26 01:42:49 scrappy Exp $
 .TH PG_PASSWD UNIX 11/05/95 PostgreSQL PostgreSQL
 .SH NAME
 pg_passwd - manipulate the flat password file
@@ -80,7 +80,7 @@ The following lines show the sample usage of the option:
 uses the new style of the Pg.pm like this:
 .nf
 
-       $conn = Pg::connectdb("host=hyalos authtype=password dbname=unv
+       $conn = Pg::connectdb("host=hyalos dbname=unv
                               user=pg_guest password=xxxxxxx");
 
 .fi
@@ -96,7 +96,7 @@ option thus:
 .nf
 
        % set conn [pg_connect -conninfo \\
-               "host=hyalos authtype=password dbname=unv \\
+               "host=hyalos dbname=unv \\
                 user=pg_guest password=xxxxxxx "]
 
 .fi
index 3a8becaf247e696d3ecef524ea33c2070914d908..8801b6ed226d9b97b536d7cb92a1e8fea5523591 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/pgintro.1,v 1.2 1998/01/11 22:17:50 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/pgintro.1,v 1.3 1998/01/26 01:42:50 scrappy Exp $
 .TH PGINTRO UNIX 11/05/95 PostgreSQL PostgreSQL
 .SP INFORMATION UNIX 11/05/95
 .BH "SECTION 2 - Unix COMMANDS (Unix)"
@@ -105,26 +105,15 @@ conducted.
 If the Postgres system is built as distributed, access to the Internet
 TCP port of the
 .IR postmaster
-process is available to anyone.  However, Postgres offers optional
-host-based authentication where only access from certain hosts are
-allowed.  Of course, host-based authentication is not fool-proof in
+process is available to anyone.  The DBA configures the pg_hba.conf file
+in the PGDATA directory to specify what authentication system is to be used
+according to the host making the connection and which database it is
+connecting to.  See pg_hba.conf(5) for a description of the authentication
+systems available.  Of course, host-based authentication is not fool-proof in
 Unix, either. It is possible for determined intruders to also
 masquerade the origination host. Those security issues are beyond the
 scope of Postgres.
 .PP
-If greater security is desired, Postgres and its clients may be
-modified to use a network authentication system.  For example, the
-.IR postmaster ,
-.IR psql
-and the
-.IR libpq
-library have already been configured to use either Version 4 or Version 5 of
-the
-.IR Kerberos
-authentication system from the Massachusetts Institute of Technology.
-For more information on using
-.IR Kerberos
-with Postgres, see the appendix below.
 .SH "ACCESS CONTROL"
 Postgres provides mechanisms to allow users to limit the access to
 their data that is provided to other users.
index 5a0fdb3210192376fe003a085182a62d436c31a6..24d1bf4c46b93e5443af6c45c29217a31933eb01 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/postgres.1,v 1.9 1998/01/11 22:17:51 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/postgres.1,v 1.10 1998/01/26 01:42:51 scrappy Exp $
 .TH POSTGRESQL UNIX 12/08/96 PostgreSQL PostgreSQL
 .SH NAME
 postgres - the Postgres backend server
@@ -31,6 +31,9 @@ filedes]
 [\c
 .BR "-e"
 ]
+[\c
+.BR "-v protocol"
+]
 .br
 [\c
 .BR "-d"
@@ -145,6 +148,10 @@ but debugging output is sent to the controlling tty of the
 Print time information and other statistics at the end of each query.
 This is useful for benchmarking or for use in tuning the number of
 buffers.
+.TP
+.BR "-v" " protocol"
+Specifies the number of the frontend/backend protocol to be used for this
+particular session.
 .SH "DEPRECATED COMMAND OPTIONS"
 There are several other options that may be specified, used mainly
 for debugging purposes.  These are listed here only for the use by
index 36cb9bb04da7a5527086384173d40be68e6b6416..d11b9eeb735760fbff9a63a53853b6e190773eee 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/postmaster.1,v 1.10 1998/01/11 22:17:53 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/postmaster.1,v 1.11 1998/01/26 01:42:52 scrappy Exp $
 .TH POSTMASTER UNIX 11/05/95 PostgreSQL PostgreSQL
 .SH "NAME"
 postmaster - run the Postgres postmaster
@@ -105,7 +105,7 @@ authentication, use
 to deny any unauthenticated
 connections, use
 .BR "-a nounauth .
-The default is site-specific.
+This option no longer has any effect.
 .TP
 .BR "-b" " backend_pathname"
 .IR "backend_pathname"
index c867ab5777d502773a0a6b21dd14693aed732bee..2c5137b4c02eb848beb6d12fb98a97ba99ba07ec 100644 (file)
@@ -1,6 +1,6 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/psql.1,v 1.22 1998/01/25 06:12:52 scrappy Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/psql.1,v 1.23 1998/01/26 01:42:53 scrappy Exp $
 .TH PSQL UNIX 1/20/96 PostgreSQL PostgreSQL
 .SH NAME
 psql - run the interactive query front-end
@@ -125,7 +125,7 @@ Specifies an authentication system
 .IR pgintro (1))
 to use in connecting to the
 .IR postmaster
-process.  The default is site-specific.
+process.  This option no longer has any effect.
 .TP
 .BR "-A"
 Turn off fill justification when printing out table elements.
@@ -221,7 +221,11 @@ tabular output. For example
 will give you tables with borders.
 .TP
 .BR "-u"
-Turns on username/password authentication.
+Asks the user for the user name and password before connecting to the database.
+If the database does not require password authentication then these are
+ignored.  If the option i snot used (and the PGPASSWORD environment variable
+is not set) and the database requires password authentication, then the
+connection will fail.  The user name is ignored anyway.
 .TP
 .BR "-x"
 Turns on extended row format mode. When enabled each row will have its column