]> granicus.if.org Git - postgresql/commitdiff
From: Dan McGuirk <mcguirk@indirect.com>
authorMarc G. Fournier <scrappy@hub.org>
Wed, 12 Mar 1997 21:23:16 +0000 (21:23 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Wed, 12 Mar 1997 21:23:16 +0000 (21:23 +0000)
Subject: [HACKERS] password authentication

This patch adds support for plaintext password authentication.  To use
it, you add a line like

host         all         0.0.0.0       0.0.0.0           password  pg_pwd.conf

to your pg_hba.conf, where 'pg_pwd.conf' is the name of a file containing
the usernames and password hashes in the format of the first two fields
of a Unix /etc/passwd file.  (Of course, you can use a specific database
name or IP instead.)

Then, to connect with a password through libpq, you use the PQconnectdb()
function, specifying the "password=" tag in the connect string and also
adding the tag "authtype=password".

I also added a command-line switch '-u' to psql that tells it to prompt
for a username and password and use password authentication.

13 files changed:
src/backend/libpq/Makefile
src/backend/libpq/auth.c
src/backend/libpq/hba.c
src/backend/libpq/pqcomm.c
src/backend/postmaster/postmaster.c
src/bin/psql/psql.c
src/include/config.h.in
src/include/libpq/hba.h
src/include/libpq/pqcomm.h
src/interfaces/libpq/fe-auth.c
src/interfaces/libpq/fe-auth.h
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/libpq-fe.h

index c8a0533a2b905645fce758175f9fa160d96ad875..a7c7f13704eba5591703c81bfe04718371ecfcc6 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for libpq subsystem (backend half of libpq interface)
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.4 1996/11/14 10:23:51 bryanh Exp $
+#    $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.5 1997/03/12 21:17:45 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -24,7 +24,8 @@ LDADD+= $(KRBLIBS)
 endif
 
 OBJS = be-dumpdata.o be-fsstubs.o be-pqexec.o \
-       auth.o hba.o pqcomm.o portal.o util.o portalbuf.o pqpacket.o pqsignal.o
+       auth.o hba.o pqcomm.o portal.o util.o portalbuf.o pqpacket.o pqsignal.o \
+       password.o
 
 all: SUBSYS.o
 
index d1cb560f1920e4a576e8da41fb104e3d31e4c5a7..333fb6ce7d1d6a65118f46e3c9171d4b2c4162fc 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.8 1996/11/16 08:09:15 bryanh Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.9 1997/03/12 21:17:48 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -70,6 +70,7 @@
 #include <libpq/libpq.h>
 #include <libpq/libpq-be.h>
 #include <libpq/hba.h>
+#include <libpq/password.h>
 
 /*----------------------------------------------------------------
  * common definitions for generic fe/be routines
@@ -113,10 +114,11 @@ static struct authsvc authsvcs[] = {
     { "krb4",     STARTUP_KRB4_MSG, 1 },
     { "krb5",     STARTUP_KRB5_MSG, 1 },
 #if defined(KRB5) 
-    { "kerberos", STARTUP_KRB5_MSG, 1 }
+    { "kerberos", STARTUP_KRB5_MSG, 1 },
 #else
-    { "kerberos", STARTUP_KRB4_MSG, 1 }
+    { "kerberos", STARTUP_KRB4_MSG, 1 },
 #endif
+    { "password", STARTUP_PASSWORD_MSG, 1 }
 };
 
 static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
@@ -403,6 +405,26 @@ return(STATUS_ERROR);
 }
 #endif /* KRB5 */
 
+static int
+pg_password_recvauth(Port *port, char *database, char *DataDir)
+{
+    PacketBuf buf;
+    char *user, *password;
+
+    if(PacketReceive(port, &buf, BLOCKING) != STATUS_OK) {
+       sprintf(PQerrormsg,
+               "pg_password_recvauth: failed to receive authentication packet.\n");
+       fputs(PQerrormsg, stderr);
+       pqdebug("%s", PQerrormsg);
+       return STATUS_ERROR;
+    }
+
+    user = buf.data;
+    password = buf.data + strlen(user) + 1;
+
+    return verify_password(user, password, port, database, DataDir);
+}
+
 /*
  * be_recvauth -- server demux routine for incoming authentication information
  */
@@ -418,8 +440,8 @@ be_recvauth(MsgType msgtype_arg, Port *port, char *username, StartupInfo* sp)
        */
     if (msgtype_arg == STARTUP_MSG && useHostBasedAuth)
         msgtype = STARTUP_HBA_MSG;
-    else 
-        msgtype = STARTUP_UNAUTH_MSG;
+    else
+        msgtype = msgtype_arg;
 
     if (!username) {
         (void) sprintf(PQerrormsg,
@@ -490,6 +512,21 @@ be_recvauth(MsgType msgtype_arg, Port *port, char *username, StartupInfo* sp)
             return(STATUS_ERROR);
           }
         break;
+    case STARTUP_PASSWORD_MSG:
+        if(!be_getauthsvc(msgtype)) {
+           sprintf(PQerrormsg, 
+                   "be_recvauth: "
+                   "plaintext password authentication disallowed\n");
+            fputs(PQerrormsg, stderr);
+            pqdebug("%s", PQerrormsg);
+            return(STATUS_ERROR);
+       }
+       if(pg_password_recvauth(port, sp->database, DataDir) != STATUS_OK) {
+           /* pg_password_recvauth or lower-level routines have already set */
+           /* the error message                                             */
+            return(STATUS_ERROR);
+       }
+       break;
     default:
         (void) sprintf(PQerrormsg,
                        "be_recvauth: unrecognized message type: %d\n",
index 4bdf497a759743d2ac4318a37d939c56244eee1c..22d532bf537f230fcf69826700e272065a60122a 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.15 1997/01/14 01:56:44 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.16 1997/03/12 21:17:53 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <port/inet_aton.h>    /* For inet_aton() */
 
 
-#define CONF_FILE "pg_hba.conf"             
-  /* Name of the config file  */
-
-#define MAP_FILE "pg_ident.conf"
-  /* Name of the usermap file */
-
-#define OLD_CONF_FILE "pg_hba"
-  /* Name of the config file in prior releases of Postgres. */
-
-#define MAX_LINES 255                    
-  /* Maximum number of config lines that can apply to one database    */
-
-#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 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};
-
 /* Some standard C libraries, including GNU, have an isblank() function.
    Others, including Solaris, do not.  So we have our own.
 */
@@ -108,7 +83,7 @@ read_through_eol(FILE *file) {
 
 static void
 read_hba_entry2(FILE *file, enum Userauth *userauth_p, char usermap_name[], 
-                bool *error_p) {
+                bool *error_p, bool *matches_p, bool find_password_entries) {
 /*--------------------------------------------------------------------------
   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
@@ -120,34 +95,47 @@ read_hba_entry2(FILE *file, enum Userauth *userauth_p, char usermap_name[],
 
   /* Get authentication type token. */
   next_token(file, buf, sizeof(buf));
+  userauth_valid = false;
   if (buf[0] == '\0') {
     *error_p = true;
-    read_through_eol(file);
   } else {
-    if (strcmp(buf, "trust") == 0) {
-      userauth_valid = true;
+    userauth_valid = true;
+    if(strcmp(buf, "trust") == 0) {
       *userauth_p = Trust;
-    } else if (strcmp(buf, "ident") == 0) {
-      userauth_valid = true;
+    } else if(strcmp(buf, "ident") == 0) {
       *userauth_p = Ident;
-    } else userauth_valid = false;
+    } else if(strcmp(buf, "password") == 0) {
+      *userauth_p = Password;
+    } else {
+      userauth_valid = false;
+    }
+
+    if((find_password_entries && strcmp(buf, "password") == 0) ||
+       (!find_password_entries && strcmp(buf, "password") != 0)) {
+      *matches_p = true;
+    } else {
+      *matches_p = false;
+    }
+  }
+
+  if(!userauth_valid || !*matches_p || *error_p) {
     if (!userauth_valid) {
       *error_p = true;
-      read_through_eol(file);
+    }
+    read_through_eol(file);
+  } else {
+    /* Get the map name token, if any */
+    next_token(file, buf, sizeof(buf));
+    if (buf[0] == '\0') {
+      *error_p = false;
+      usermap_name[0] = '\0';
     } else {
-      /* Get the map name token, if any */
+      strncpy(usermap_name, buf, USERMAP_NAME_SIZE);
       next_token(file, buf, sizeof(buf));
-      if (buf[0] == '\0') {
-        *error_p = false;
-        usermap_name[0] = '\0';
-      } else {
-        strncpy(usermap_name, buf, USERMAP_NAME_SIZE);
-        next_token(file, buf, sizeof(buf));
-        if (buf[0] != '\0') {
-          *error_p = true;
-          read_through_eol(file);
-        } else *error_p = false;
-      }
+      if (buf[0] != '\0') {
+       *error_p = true;
+       read_through_eol(file);
+      } else *error_p = false;
     }
   }
 }
@@ -158,7 +146,8 @@ static void
 process_hba_record(FILE *file, 
                    const struct in_addr ip_addr, const char database[],
                    bool *matches_p, bool *error_p, 
-                   enum Userauth *userauth_p, char usermap_name[] ) {
+                   enum Userauth *userauth_p, char usermap_name[],
+                  bool find_password_entries) {
 /*---------------------------------------------------------------------------
   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"
@@ -221,8 +210,7 @@ process_hba_record(FILE *file,
                        the rest of the info from it.
                        */
                     read_hba_entry2(file, userauth_p, usermap_name,
-                                    error_p);
-                    *matches_p = true;
+                                    error_p, matches_p, find_password_entries);
                     if (*error_p) {
                       sprintf(PQerrormsg,
                               "process_hba_record: invalid syntax in "
@@ -249,7 +237,7 @@ 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[] ) {
+                         char usermap_name[], bool find_password_entries) {
 /*---------------------------------------------------------------------------
   This function does the same thing as find_hba_entry, only with
   the config file already open on stream descriptor "file".
@@ -274,7 +262,8 @@ process_open_config_file(FILE *file,
       if (c == '#') read_through_eol(file);
       else {
         process_hba_record(file, ip_addr, database, 
-                           &found_entry, &error, userauth_p, usermap_name);
+                           &found_entry, &error, userauth_p, usermap_name,
+                          find_password_entries);
       }
     }    
   }
@@ -286,11 +275,11 @@ process_open_config_file(FILE *file,
 
 
 
-static void
+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[] ) {
+               char usermap_name[], bool find_password_entries) {
 /*--------------------------------------------------------------------------
   Read the config file and find an entry that allows connection from
   host "ip_addr" to database "database".  If not found, return 
@@ -360,7 +349,7 @@ find_hba_entry(const char DataDir[], const struct in_addr ip_addr,
       pqdebug("%s", PQerrormsg);
     } else {
       process_open_config_file(file, ip_addr, database, host_ok_p, userauth_p,
-                               usermap_name);
+                               usermap_name, find_password_entries);
       fclose(file);
     }
     free(conf_file);
@@ -731,7 +720,8 @@ hba_recvauth(const Port *port, const char database[], const char user[],
 
 
   find_hba_entry(DataDir, port->raddr.sin_addr, database, 
-                 &host_ok, &userauth, usermap_name);
+                 &host_ok, &userauth, usermap_name, 
+                false /* don't find password entries of type 'password' */);
   
   if (!host_ok) retvalue = STATUS_ERROR;
   else {
index 928bc281b8d9a3f773e36ebd6fb89e1e5522c6fb..6b8ecdac28bc0d5673acd6f84ba6ae303324e8d3 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.11 1997/02/14 04:15:29 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.12 1997/03/12 21:17:58 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -703,3 +703,29 @@ 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 628d44d7d9703d249bcedcebd5dcb8bc1368ab92..5c749c5f3537520afc3c262e66f7f3c1c97a8131 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.43 1997/03/02 02:17:32 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.44 1997/03/12 21:18:38 scrappy Exp $
  *
  * NOTES
  *
@@ -660,8 +660,8 @@ ConnStartup(Port *port, int *status,
             char buffer[200 + sizeof(namebuf)];
             sprintf(buffer, 
                     "Failed to authenticate client as Postgres user '%s' "
-                    "using authentication scheme %d.",
-                    namebuf, msgType);
+                    "using %s: %s",
+                    namebuf, name_of_authentication_type(msgType), PQerrormsg);
             strncpy(errormsg, buffer, errormsg_len);
             *status = STATUS_ERROR;
         } else {
index 4330c19fd8fcf131262fe06cd5e97001d641fbce..6fd299605b4b7141bd331b7f4c79aeb61ccb28bd 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.57 1997/02/13 08:31:48 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.58 1997/03/12 21:19:14 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,6 +29,9 @@
 #ifndef HAVE_STRDUP
 #include "strdup.h"
 #endif
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
 
 #ifdef HAVE_LIBREADLINE
 # ifdef HAVE_READLINE_H
@@ -67,6 +70,7 @@ typedef struct _psqlSettings {
     bool            singleStep;        /* prompt before for each query */
     bool            singleLineMode;    /* query terminated by newline */
     bool            useReadline;/* use libreadline routines */
+    bool            getPassword;/* prompt the user for a username and password */
 }               PsqlSettings;
 
 /* declarations for functions in this file */
@@ -78,6 +82,9 @@ handleCopyIn(PGresult * res, const bool mustprompt,
             FILE * copystream);
 static int      tableList(PsqlSettings * ps, bool deep_tablelist);
 static int      tableDesc(PsqlSettings * ps, char *table);
+static void     prompt_for_password(char *username, char *password);
+static char *   make_connect_string(char *host, char *port, char *dbname,
+                                   char *username, char *password);
 
 char           *gets_noreadline(char *prompt, FILE * source);
 char           *gets_readline(char *prompt, FILE * source);
@@ -125,6 +132,7 @@ usage(char *progname)
     fprintf(stderr, "\t -s                      single step mode (prompts for each query)\n");
     fprintf(stderr, "\t -S                      single line mode (i.e. query terminated by newline)\n");
     fprintf(stderr, "\t -t                      turn off printing of headings and row count\n");
+    fprintf(stderr, "\t -u                      ask for a username and password for authentication\n");
     fprintf(stderr, "\t -T html                 set html3.0 table command options (cf. -H)\n");
     fprintf(stderr, "\t -x                      turn on expanded output (field names on left)\n");
     exit(1);
@@ -1463,8 +1471,13 @@ main(int argc, char **argv)
     else
        settings.useReadline = 1;
 #endif
+#ifdef PSQL_ALWAYS_GET_PASSWORDS
+    settings.getPassword = 1;
+#else
+    settings.getPassword = 0;
+#endif
 
-    while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lh:Hnso:p:qStT:x")) != EOF) {
+    while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lh:Hnso:p:qStT:ux")) != EOF) {
        switch (c) {
        case 'A':
            settings.opt.align = 0;
@@ -1523,6 +1536,9 @@ main(int argc, char **argv)
        case 'T':
            settings.opt.tableOpt = optarg;
            break;
+       case 'u':
+           settings.getPassword = 1;
+           break;
        case 'x':
            settings.opt.expanded = 1;
            break;
@@ -1538,7 +1554,21 @@ main(int argc, char **argv)
     if (listDatabases)
        dbname = "template1";
 
-    settings.db = PQsetdb(host, port, NULL, NULL, dbname);
+    if(settings.getPassword) {
+       char username[9];
+       char password[9];
+       char *connect_string;
+
+       prompt_for_password(username, password);
+
+       /* now use PQconnectdb so we can pass these options */
+       connect_string = make_connect_string(host, port, dbname, username, password);
+       settings.db = PQconnectdb(connect_string);
+       free(connect_string);
+    } else {
+       settings.db = PQsetdb(host, port, NULL, NULL, dbname);
+    }
+
     dbname = PQdb(settings.db);
 
     if (PQstatus(settings.db) == CONNECTION_BAD) {
@@ -1711,3 +1741,87 @@ setFout(PsqlSettings * ps, char *fname)
     }
     return ps->queryFout;
 }
+
+static void prompt_for_password(char *username, char *password)
+{
+    int length;
+#ifdef HAVE_TERMIOS_H
+    struct termios t_orig, t;
+#endif
+
+    printf("Username: ");
+    fgets(username, 9, stdin);
+    length = strlen(username);
+    if(length > 0 && username[length-1] == '\n') username[length-1] = '\0';
+
+    printf("Password: ");
+#ifdef HAVE_TERMIOS_H
+    tcgetattr(0, &t);
+    t_orig = t;
+    t.c_lflag &= ~ECHO;
+    tcsetattr(0, TCSADRAIN, &t);
+#endif
+    fgets(password, 9, stdin);
+#ifdef HAVE_TERMIOS_H
+    tcsetattr(0, TCSADRAIN, &t_orig);
+#endif
+
+    length = strlen(password);
+    if(length > 0 && password[length-1] == '\n') password[length-1] = '\0';
+
+    printf("\n\n");
+}
+
+static char *make_connect_string(char *host, char *port, char *dbname,
+                                char *username, char *password)
+{
+    int connect_string_len = 0;
+    char *connect_string;
+    
+    if(host)
+       connect_string_len += 6 + strlen(host);       /* 6 == "host=" + " " */
+    if(username) 
+       connect_string_len += 6 + strlen(username);   /* 6 == "user=" + " " */
+    if(password)
+       connect_string_len += 10 + strlen(password);  /* 10 == "password=" + " " */
+    if(port)
+       connect_string_len += 6 + strlen(port);       /* 6 == "port=" + " " */
+    if(dbname)
+       connect_string_len += 8 + strlen(dbname);     /* 8 == "dbname=" + " " */
+    connect_string_len += 18;   /* "authtype=password" + null */
+    
+    connect_string = (char *)malloc(connect_string_len);
+    if(!connect_string) {
+       return 0;
+    }
+    connect_string[0] = '\0';
+    if(host) {
+       strcat(connect_string, "host=");
+       strcat(connect_string, host);
+       strcat(connect_string, " ");
+    }
+    if(username) {
+       strcat(connect_string, "user=");
+       strcat(connect_string, username);
+       strcat(connect_string, " ");
+    }
+    if(password) {
+       strcat(connect_string, "password=");
+       strcat(connect_string, password);
+       strcat(connect_string, " ");
+    }
+    if(port) {
+       strcat(connect_string, "port=");
+       strcat(connect_string, port);
+       strcat(connect_string, " ");
+    }
+    if(dbname) {
+       strcat(connect_string, "dbname=");
+       strcat(connect_string, dbname);
+       strcat(connect_string, " ");
+    }
+    strcat(connect_string, "authtype=password");
+
+    return connect_string;
+}
+    
index c0f56a2ac09da86b28294e114e894375a5d54f9e..99973dde07f7d38dec03d3d4e02a18ffcbf984de 100644 (file)
  */
 /*#define GEQO */ /* backend/optimizer/path/allpaths.c */
 
-
-
+/*
+ * Define this if you want psql to _always_ ask for a username and a password
+ * for password authentication.
+ */
+/* #define PSQL_ALWAYS_GET_PASSWORDS */
 
 /* Undocumented "features"? */
 #define FASTBUILD /* access/nbtree/nbtsort.c */
index c68fefefd80e23c167c17c2b5067516634f8c4fa..14847438b0d6bb685be321313e14c28fde59c74c 100644 (file)
@@ -4,16 +4,46 @@
  *    Interface to hba.c
  *
  *
- * $Id: hba.h,v 1.2 1996/11/06 10:29:58 scrappy Exp $
+ * $Id: hba.h,v 1.3 1997/03/12 21:22:16 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef HBA_H
 #define        HBA_H
 
+#include <libpq/pqcomm.h>
+
+#define CONF_FILE "pg_hba.conf"             
+  /* Name of the config file  */
+
+#define MAP_FILE "pg_ident.conf"
+  /* Name of the usermap file */
+
+#define OLD_CONF_FILE "pg_hba"
+  /* Name of the config file in prior releases of Postgres. */
+
+#define MAX_LINES 255                    
+  /* Maximum number of config lines that can apply to one database    */
+
+#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 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);
 
 #endif
index 0a23d226ce022849ff04a3cc599c5be0d96de510..cc9d941800abd553b42b072a31c483b15081f88d 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqcomm.h,v 1.7 1997/02/11 15:37:18 momjian Exp $
+ * $Id: pqcomm.h,v 1.8 1997/03/12 21:22:19 scrappy Exp $
  *
  * NOTES
  *    Some of this should move to libpq.h
@@ -52,10 +52,15 @@ typedef enum _MsgType {
     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_UNAUTH_MSG=13,      /* use unauthenticated connection */
+    STARTUP_PASSWORD_MSG=14     /* use plaintext password authentication */
     /* 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 */
 
@@ -126,6 +131,6 @@ 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 103e64fdf5738018f61b0d152f8383a3c121c97d..66c2acf9ecc457f233d35ccad713a13b6da3ebca 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.6 1996/11/03 07:14:30 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.7 1997/03/12 21:23:02 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,6 +40,7 @@
 
 #include "libpq-fe.h"
 #include "fe-auth.h"
+#include "fe-connect.h"
 
 /*----------------------------------------------------------------
  * common definitions for generic fe/be routines
@@ -79,7 +80,8 @@ static struct authsvc authsvcs[] = {
 #else /* !(KRB4 || KRB5) */
          1
 #endif /* !(KRB4 || KRB5) */
-    }
+    },
+    { "password", STARTUP_PASSWORD_MSG, 0 }
 };
 
 static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
@@ -431,12 +433,30 @@ pg_krb5_sendauth(const char* PQerrormsg,int sock,
 
 #endif /* KRB5 */
 
+static int
+pg_password_sendauth(Port *port, const char *user, const char *password)
+{
+    PacketBuf buf;
+    char *tmp;
+
+    buf.len = htonl(sizeof(PacketBuf));
+    buf.msgtype = STARTUP_PASSWORD_MSG;
+    buf.data[0] = '\0';
+
+    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);
+}
 
 /*
  * fe_sendauth -- client demux routine for outgoing authentication information
  */
 int
-fe_sendauth(MsgType msgtype, Port *port, const char *hostname, const char* PQerrormsg)
+fe_sendauth(MsgType msgtype, Port *port, const char *hostname, 
+           const char *user, const char *password, const char* PQerrormsg)
 {
     switch (msgtype) {
 #ifdef KRB4
@@ -464,6 +484,8 @@ fe_sendauth(MsgType msgtype, Port *port, const char *hostname, const char* PQerr
 #endif
     case STARTUP_MSG:
        break;
+    case STARTUP_PASSWORD_MSG:
+        pg_password_sendauth(port, user, password);
     default:
        break;
     }
index fa939ac122f7e75481ef1b8ed11382697aa0bb61..646f93df37ac0e4562f7ae6a74e04309a040c6af 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fe-auth.h,v 1.2 1996/08/06 16:16:44 scrappy Exp $
+ * $Id: fe-auth.h,v 1.3 1997/03/12 21:23:04 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,7 +28,9 @@
 #define        DEFAULT_CLIENT_AUTHSVC  "kerberos"
 #endif /* KRB4 || KRB5 */
 
-extern int fe_sendauth(MsgType msgtype, Port *port, const char *hostname, const char* PQerromsg);
+extern int fe_sendauth(MsgType msgtype, Port *port, const char *hostname, 
+                      const char *user, 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 cb2d06c0aba40c5f995bda88d426ba828c729311..60f55ae599357a18fefd4be263a3c78ef785d450 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.23 1997/02/13 08:32:08 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.24 1997/03/12 21:23:09 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,6 +28,7 @@
 #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"
 
 #ifndef HAVE_STRDUP
@@ -38,8 +39,6 @@
 /* use a local version instead of the one found in pqpacket.c */
 static ConnStatusType connectDB(PGconn *conn);
 
-static int packetSend(Port *port, PacketBuf *buf, PacketLen len,
-                     bool nonBlocking);
 static void startup2PacketBuf(StartupInfo* s, PacketBuf* res);
 static void freePGconn(PGconn *conn);
 static void closePGconn(PGconn *conn);
@@ -73,9 +72,15 @@ static PQconninfoOption PQconninfoOptions[] = {
 /*    Option-name      Environment-Var Compiled-in     Current value   */
 /*                     Label                           Disp-Char       */
 /*    ----------------- --------------- --------------- --------------- */
+    { "authtype",       "PGAUTHTYPE",   NULL,           NULL,
+                        "Database-Authtype",            "", 20  },
+
     { "user",          "PGUSER",       NULL,           NULL,
                        "Database-User",                "", 20  },
 
+    { "password",       "PGPASSWORD",   NULL,           NULL,
+                        "Database-Password",            "", 20  },
+
     { "dbname",                "PGDATABASE",   NULL,           NULL,
                        "Database-Name",                "", 20  },
 
@@ -187,6 +192,8 @@ PQconnectdb(const char *conninfo)
     conn->pgtty     = strdup(conninfo_getval("tty"));
     conn->pgoptions = strdup(conninfo_getval("options"));
     conn->pguser    = strdup(conninfo_getval("user"));
+    conn->pgpass    = strdup(conninfo_getval("password"));
+    conn->pgauth    = strdup(conninfo_getval("authtype"));
     conn->dbName    = strdup(conninfo_getval("dbname"));
 
     /* ----------
@@ -195,6 +202,13 @@ 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
      * ----------
@@ -260,6 +274,8 @@ PQconndefaults(void)
  *
  *    PGUSER       Postgres username to associate with the connection.
  *
+ *    PGPASSWORD   The user's password.
+ *
  *    PGDATABASE   name of database to which to connect if <pgdatabase> 
  *                 argument is NULL or a null string
  *
@@ -336,6 +352,12 @@ PQsetdb(const char *pghost, const char* pgport, const char* pgoptions, const cha
       }
     }
 
+    if((tmp = getenv("PGPASSWORD"))) {
+      conn->pgpass = strdup(tmp);
+    } else {
+      conn->pgpass = 0;
+    }
+
     if (!error) {
       if (((tmp = (char *)dbName) && (dbName[0] != '\0')) ||
           ((tmp = getenv("PGDATABASE")))) {
@@ -467,6 +489,7 @@ connectDB(PGconn *conn)
 
     /* authenticate as required*/
     if (fe_sendauth(msgtype, port, conn->pghost, 
+                   conn->pguser, conn->pgpass,
                    conn->errorMessage) != STATUS_OK) {
       (void) sprintf(conn->errorMessage,
             "connectDB() --  authentication failed with %s\n",
@@ -474,6 +497,11 @@ connectDB(PGconn *conn)
       goto connect_errReturn;  
     }
     
+    /* free the password so it's not hanging out in memory forever */
+    if(conn->pgpass) {
+      free(conn->pgpass);
+    }
+    
     /* set up the socket file descriptors */
     conn->Pfout = fdopen(port->sock, "w");
     conn->Pfin = fdopen(dup(port->sock), "r");
@@ -595,7 +623,7 @@ PQreset(PGconn *conn)
  *     buffer management.  For now, we're not going to do it.
  *
 */
-static int
+int
 packetSend(Port *port,
           PacketBuf *buf,
           PacketLen len,
index 8d9182ac3ea5df7d0d754df40e09a3c204394ae5..c765661e71770e288dc48d70a9ad99c68b6d29de 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-fe.h,v 1.17 1997/01/06 10:11:11 bryanh Exp $
+ * $Id: libpq-fe.h,v 1.18 1997/03/12 21:23:16 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -125,6 +125,8 @@ typedef struct pg_conn{
   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;