From: todd brandys
authorMarc G. Fournier
Thu, 4 Dec 1997 00:28:15 +0000 (00:28 +0000)
committerMarc G. Fournier
Thu, 4 Dec 1997 00:28:15 +0000 (00:28 +0000)
An extension to the code to allow for a pg_password authentication database
that is *seperate* from the system password file

19 files changed:
src/backend/commands/Makefile
src/backend/libpq/Makefile
src/backend/libpq/auth.c
src/backend/parser/gram.y
src/backend/parser/keywords.c
src/backend/postmaster/postmaster.c
src/backend/tcop/utility.c
src/bin/initdb/initdb.sh
src/bin/psql/psqlHelp.h
src/include/catalog/pg_attribute.h
src/include/catalog/pg_class.h
src/include/catalog/pg_user.h
src/include/libpq/pqcomm.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h
src/interfaces/libpq/fe-auth.c
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/fe-connect.h
src/interfaces/libpq/libpq-fe.h

index bb6524b79d928fd53cde2e374a7df7fe34328c6c..9e57883debad4127d9d8b5dbb7ee2bfb0e0c9c49 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for commands
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.7 1997/11/24 05:20:49 momjian Exp $
+#    $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.8 1997/12/04 00:26:44 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -19,7 +19,7 @@ CFLAGS+=$(INCLUDE_OPT)
 
 OBJS = async.o creatinh.o command.o copy.o defind.o define.o \
        remove.o rename.o vacuum.o version.o view.o cluster.o \
-       recipe.o explain.o sequence.o trigger.o proclang.o dbcommands.o
+       recipe.o explain.o sequence.o trigger.o user.o proclang.o dbcommands.o
 
 all: SUBSYS.o
 
index 84c2db63bb130908aa62349c5826321375316c53..ed43bdd1352d086e83090848b3fed1eea3b199ee 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.7 1997/04/04 10:39:19 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.8 1997/12/04 00:26:47 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -24,7 +24,7 @@ LDFLAGS+= $(KRBLIBS)
 endif
 
 OBJS = be-dumpdata.o be-fsstubs.o be-pqexec.o pqcomprim.o\
-       auth.o hba.o pqcomm.o portal.o util.o portalbuf.o pqpacket.o pqsignal.o \
+       auth.o hba.o crypt.o pqcomm.o portal.o util.o portalbuf.o pqpacket.o pqsignal.o \
        password.o
 
 all: SUBSYS.o
index aa9c541b168a1378e5db2734dfa4aca552c98af2..e4f1753800a42c9927181a9dfd26580ef5402a74 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.18 1997/11/17 16:10:06 thomas Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.19 1997/12/04 00:26:50 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,6 +71,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static int be_getauthsvc(MsgType msgtype);
 
@@ -122,7 +123,8 @@ static struct authsvc authsvcs[] = {
 #else
    {"kerberos", STARTUP_KRB4_MSG, 1},
 #endif
-   {"password", STARTUP_PASSWORD_MSG, 1}
+   {"password", STARTUP_PASSWORD_MSG, 1},
+   {"crypt", STARTUP_CRYPT_MSG, 1}
 };
 
 static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
@@ -445,6 +447,28 @@ pg_password_recvauth(Port *port, char *database, char *DataDir)
    return verify_password(user, password, port, database, DataDir);
 }
 
+static int
+crypt_recvauth(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);
+}
+
 /*
  * be_recvauth -- server demux routine for incoming authentication information
  */
@@ -571,6 +595,10 @@ be_recvauth(MsgType msgtype_arg, Port *port, char *username, StartupInfo *sp)
                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",
index 8cbc5397d1da66265ec65cdb7a7d819720227559..a7bc22d67c2b17c19e8e4704d47cca475792ae95 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.75 1997/12/02 16:09:15 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.76 1997/12/04 00:26:57 scrappy Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -40,6 +40,7 @@
 #include "nodes/print.h"
 #include "parser/gramparse.h"
 #include "utils/acl.h"
+#include "utils/palloc.h"
 #include "catalog/catname.h"
 #include "utils/elog.h"
 #include "access/xact.h"
@@ -83,6 +84,7 @@ Oid   param_type(int t); /* used in parse_expr.c */
    char                chr;
    char                *str;
    bool                boolean;
+   bool*               pboolean;   /* for pg_user privileges */
    List                *list;
    Node                *node;
    Value               *value;
@@ -119,10 +121,16 @@ Oid   param_type(int t); /* used in parse_expr.c */
        RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
        CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
        ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
-       ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
+       ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
+       CreateUserStmt, AlterUserStmt, DropUserStmt
 
 %type         opt_database, location
 
+%type  user_createdb_clause, user_createuser_clause
+%type    user_passwd_clause
+%type    user_valid_clause
+%type   user_group_list, user_group_clause
+
 %type    SubSelect
 %type         join_expr, join_outer, join_spec
 %type  TriggerActionTime, TriggerForSpec, PLangTrusted
@@ -268,6 +276,14 @@ Oid    param_type(int t); /* used in parse_expr.c */
        SEQUENCE, SETOF, SHOW, STDIN, STDOUT, TRUSTED, 
        VACUUM, VERBOSE, VERSION
 
+/*
+ * Tokens for pg_passwd support.  The CREATEDB and CREATEUSER tokens should go away
+ * when some sort of pg_privileges relation is introduced.
+ *
+ *                                    Todd A. Brandys
+ */
+%token  USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
+
 /* Special keywords, not in the query language - see the "lex" file */
 %token    IDENT, SCONST, Op
 %token   ICONST, PARAM
@@ -318,17 +334,20 @@ stmtmulti:  stmtmulti stmt ';'
        ;
 
 stmt :   AddAttrStmt
+       | AlterUserStmt
        | ClosePortalStmt
        | CopyStmt
        | CreateStmt
        | CreateSeqStmt
        | CreatePLangStmt
        | CreateTrigStmt
+       | CreateUserStmt
        | ClusterStmt
        | DefineStmt
        | DestroyStmt
        | DropPLangStmt
        | DropTrigStmt
+       | DropUserStmt
        | ExtendStmt
        | ExplainStmt
        | FetchStmt
@@ -356,6 +375,105 @@ stmt :      AddAttrStmt
        | VariableResetStmt
        ;
 
+/*****************************************************************************
+ *
+ * Create a new postresql DBMS user
+ *
+ *
+ *****************************************************************************/
+
+CreateUserStmt:   CREATE USER Id
+                      user_passwd_clause
+                      user_createdb_clause
+                      user_createuser_clause
+                      user_group_clause
+                      user_valid_clause
+              { CreateUserStmt *n = makeNode(CreateUserStmt);
+                n->user = $3;
+                n->password = $4;
+                n->createdb = $5;
+                n->createuser = $6;
+                  n->groupElts = $7;
+                n->validUntil = $8;
+                $$ = (Node *)n;
+              }
+      ;
+
+/*****************************************************************************
+ *
+ * Alter a postresql DBMS user
+ *
+ *
+ *****************************************************************************/
+
+AlterUserStmt:   ALTER USER Id
+                      user_passwd_clause
+                      user_createdb_clause
+                      user_createuser_clause
+                      user_group_clause
+                      user_valid_clause
+              { AlterUserStmt *n = makeNode(AlterUserStmt);
+                n->user = $3;
+                n->password = $4;
+                n->createdb = $5;
+                n->createuser = $6;
+                  n->groupElts = $7;
+                n->validUntil = $8;
+                $$ = (Node *)n;
+              }
+      ;
+
+/*****************************************************************************
+ *
+ * Drop a postresql DBMS user
+ *
+ *
+ *****************************************************************************/
+
+DropUserStmt:  DROP USER Id
+              { DropUserStmt *n = makeNode(DropUserStmt);
+                n->user = $3;
+                  $$ = (Node *)n;
+              }
+      ;
+
+user_passwd_clause:  WITH PASSWORD Id         { $$ = $3; }
+                      | /*EMPTY*/             { $$ = NULL; }
+                      ;
+
+user_createdb_clause:  CREATEDB               { bool*  b;
+                                        $$ = (b = (bool*)palloc(sizeof(bool)));
+                                        *b = true;
+                                      }
+                      | NOCREATEDB    { bool*  b;
+                                        $$ = (b = (bool*)palloc(sizeof(bool)));
+                                        *b = false;
+                                      }
+                      | /*EMPTY*/     { $$ = NULL; }
+                      ;
+
+user_createuser_clause:  CREATEUSER   { bool*  b;
+                                        $$ = (b = (bool*)palloc(sizeof(bool)));
+                                        *b = true;
+                                      }
+                      | NOCREATEUSER  { bool*  b;
+                                        $$ = (b = (bool*)palloc(sizeof(bool)));
+                                        *b = false;
+                                      }
+                      | /*EMPTY*/     { $$ = NULL; }
+                      ;
+
+user_group_list:  user_group_list ','  Id { $$ = lcons((void*)makeString($3), $1); }
+                      | Id            { $$ = makeList((void*)makeString($1), NULL); }
+                      ;
+
+user_group_clause:  IN GROUP user_group_list  { $$ = $3; }
+                      | /*EMPTY*/             { $$ = NULL; }
+                      ;
+
+user_valid_clause:  VALID UNTIL SCONST        { $$ = $3; }
+                      | /*EMPTY*/             { $$ = NULL; }
+                      ;
 
 /*****************************************************************************
  *
index 0e17dc122461cf98f155f60547d8e4bd481c08e9..c51cc1f33d318f61888c56992f1b9d01567d29d3 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.26 1997/11/26 01:11:08 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.27 1997/12/04 00:27:04 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,6 +64,8 @@ static ScanKeyword ScanKeywords[] = {
    {"constraint", CONSTRAINT},
    {"copy", COPY},
    {"create", CREATE},
+   {"createdb", CREATEDB},
+   {"createuser", CREATEUSER},
    {"cross", CROSS},
    {"current", CURRENT},
    {"current_date", CURRENT_DATE},
@@ -133,6 +135,8 @@ static ScanKeyword ScanKeywords[] = {
    {"natural", NATURAL},
    {"nchar", NCHAR},
    {"new", NEW},
+   {"nocreatedb", NOCREATEDB},
+   {"nocreateuser", NOCREATEUSER},
    {"none", NONE},
    {"no", NO},
    {"not", NOT},
@@ -149,6 +153,7 @@ static ScanKeyword ScanKeywords[] = {
    {"order", ORDER},
    {"outer", OUTER_P},
    {"partial", PARTIAL},
+   {"password", PASSWORD},
    {"position", POSITION},
    {"precision", PRECISION},
    {"primary", PRIMARY},
@@ -188,9 +193,12 @@ static ScanKeyword ScanKeywords[] = {
    {"type", TYPE_P},
    {"union", UNION},
    {"unique", UNIQUE},
+   {"until", UNTIL},
    {"update", UPDATE},
+   {"user", USER},
    {"using", USING},
    {"vacuum", VACUUM},
+   {"valid", VALID},
    {"values", VALUES},
    {"varchar", VARCHAR},
    {"varying", VARYING},
index 52bc471853f2febf31c1800f267bcd46763d1913..b4d1f9559926883d1f1be150f3ea829c42a887c8 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.62 1997/11/17 03:47:28 scrappy Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.63 1997/12/04 00:27:17 scrappy Exp $
  *
  * NOTES
  *
@@ -47,6 +47,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if !defined(NO_UNISTD_H)
 #include 
@@ -78,6 +79,7 @@
 #include "libpq/auth.h"
 #include "libpq/pqcomm.h"
 #include "libpq/pqsignal.h"
+#include "libpq/crypt.h"
 #include "miscadmin.h"
 #include "version.h"
 #include "lib/dllist.h"
@@ -199,6 +201,7 @@ 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 void RandomSalt(char* salt);
 
 extern char *optarg;
 extern int optind,
@@ -663,7 +666,27 @@ ServerLoop(void)
                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; */
+                           continue;
+                       } else {
                            int         CSstatus;       /* Completion status of
                                                         * ConnStartup */
                            char        errormsg[200];  /* error msg from
@@ -1355,3 +1378,44 @@ dumpstatus(SIGNAL_ARGS)
        curr = DLGetSucc(curr);
    }
 }
+
+/*
+ * CharRemap
+ */
+static char
+CharRemap(long int ch) {
+
+  if (ch < 0)
+    ch = -ch;
+
+  ch = ch % 62;
+  if (ch < 26)
+    return ('A' + ch);
+
+  ch -= 26;
+  if (ch < 26)
+    return ('a' + ch);
+
+  ch -= 26;
+  return ('0' + ch);
+}
+
+/*
+ * RandomSalt
+ */
+static void
+RandomSalt(char* salt) {
+
+  static bool     initialized = false;
+
+  if (!initialized) {
+    time_t     now;
+
+    now = time(NULL);
+    srandom((unsigned int)now);
+    initialized = true;
+  }
+
+  *salt = CharRemap(random());
+  *(salt + 1) = CharRemap(random());
+}
index 2e9b764644d97a4b200333b4ae5e6b0fb4e05adf..57960aee87672d1a0ee802f08e86335b3586e19d 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.31 1997/11/24 05:32:40 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.32 1997/12/04 00:27:24 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -721,6 +721,32 @@ ProcessUtility(Node * parsetree,
            DropProceduralLanguage((DropPLangStmt *) parsetree);
            break;
 
+                      /*
+                       * ******************************** USER statements ****
+                       *
+                       */
+                case T_CreateUserStmt:
+                        commandTag = "CREATE USER";
+                        CHECK_IF_ABORTED();
+
+                        DefineUser((CreateUserStmt*)parsetree);
+                        break;
+
+                case T_AlterUserStmt:
+                        commandTag = "ALTER USER";
+                        CHECK_IF_ABORTED();
+
+                        AlterUser((AlterUserStmt*)parsetree);
+                        break;
+
+                case T_DropUserStmt:
+                        commandTag = "DROP USER";
+                        CHECK_IF_ABORTED();
+
+                        RemoveUser(((DropUserStmt*)parsetree)->user);
+                        break;
+
+
            /*
             * ******************************** default ********************************
             *
index 6d6456f957dc68e802508704e9a6a180f950a50d..76ebc8ea6659563b89101736efccb9c05b56cf08 100644 (file)
@@ -26,7 +26,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.29 1997/11/16 04:36:14 momjian Exp $
+#    $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.30 1997/12/04 00:27:31 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -351,6 +351,13 @@ echo "vacuuming template1"
 echo "vacuum" | postgres -F -Q -D$PGDATA template1 2>&1 > /dev/null |\
    grep -v "^DEBUG:"
 
+echo "Altering pg_user acl"
+echo "REVOKE ALL ON pg_user FROM public" | postgres -F -Q -D$PGDATA template1 2>&1 > /dev/null |\
+         grep -v "'DEBUG:"
+
+echo "COPY pg_user TO '$PGDATA/pg_pwd' USING DELIMITERS '#'" | postgres -F -Q -D$PGDATA template1 2>&1 > /dev/null |\
+         grep -v "'DEBUG:"
+
 echo "loading pg_description"
 echo "copy pg_description from '$TEMPLATE_DESCR'" | postgres -F -Q -D$PGDATA template1 > /dev/null
 echo "copy pg_description from '$GLOBAL_DESCR'" | postgres -F -Q -D$PGDATA template1 > /dev/null
index a91272e929792db12775cacbcd5d00733d6163ad..27f820d26e24064eb369a21a9de87e9cc9d4e42e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: psqlHelp.h,v 1.33 1997/11/21 18:11:46 momjian Exp $
+ * $Id: psqlHelp.h,v 1.34 1997/12/04 00:27:37 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,9 @@ static struct _helpStruct QL_HELP[] = {
    {"alter table",
        "add/rename attributes, rename tables",
    "\talter table  [*] add column  ;\n\talter table  [*] rename [column]  to ;\n\talter table  rename to "},
+   {"alter user",
+       "alter system information for a user",
+   "alter user \n\t[with password ]\n\t[createdb | noccreatedb]\n\t[createuser | nocreateuser]\n\t[in group , ..., ]\n\t[valid until ''];"},
    {"begin",
        "begin a new transaction",
    "begin [transaction|work];"},
@@ -84,6 +87,9 @@ static struct _helpStruct QL_HELP[] = {
    {"create type",
        "create a new user-defined base data type",
    "create type  (\n\tinternallength = ( | variable),\n\t[externallength = (|variable),]\n\tinput=, output = \n\t[,element = ][,delimiter=][,default=\'\']\n\t[,send = ][,receive = ][,passedbyvalue]);"},
+   {"create user",
+       "create a new user",
+   "create user \n\t[with password ]\n\t[createdb | nocreatedb]\n\t[createuser | nocreateuser]\n\t[in group , ..., ]\n\t[valid until ''];"},
    {"create view",
        "create a view",
    "create view  as select [as ][,... [as ]] [from ] [where ];"},
@@ -126,6 +132,9 @@ static struct _helpStruct QL_HELP[] = {
    {"drop type",
        "remove a user-defined base type",
    "drop type ;"},
+   {"drop user",
+       "remove a user from the system",
+   "drop user ;"},
    {"drop view",
        "remove a view",
    "drop view "},
index cb69640964b9918c608b1dcb55b98d7d4233201a..9be5e6ba23b1b1100ee29d5e7100bea0738ce74d 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_attribute.h,v 1.20 1997/11/21 18:12:01 momjian Exp $
+ * $Id: pg_attribute.h,v 1.21 1997/12/04 00:27:47 scrappy Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
@@ -275,12 +275,14 @@ DATA(insert OID = 0 ( 1255 cmax               29 0  4  -6 0 -1 t f i f f));
  *     pg_user
  * ----------------
  */
-DATA(insert OID = 0 ( 1260 usename         19 0 NAMEDATALEN   1 0 -1 f f i f f));
-DATA(insert OID = 0 ( 1260 usesysid            23 0  4   2 0 -1 t f s f f));
-DATA(insert OID = 0 ( 1260 usecreatedb     16 0  1   3 0 -1 t f c f f));
-DATA(insert OID = 0 ( 1260 usetrace            16 0  1   4 0 -1 t f c f f));
-DATA(insert OID = 0 ( 1260 usesuper            16 0  1   5 0 -1 t f c f f));
-DATA(insert OID = 0 ( 1260 usecatupd       16 0  1   6 0 -1 t f c f f));
+DATA(insert OID = 0 ( 1260 usename     19  0 NAMEDATALEN   1 0 -1 f f i f f));
+DATA(insert OID = 0 ( 1260 usesysid        23  0   4   2 0 -1 t f s f f));
+DATA(insert OID = 0 ( 1260 usecreatedb     16  0   1   3 0 -1 t f c f f));
+DATA(insert OID = 0 ( 1260 usetrace        16  0   1   4 0 -1 t f c f f));
+DATA(insert OID = 0 ( 1260 usesuper        16  0   1   5 0 -1 t f c f f));
+DATA(insert OID = 0 ( 1260 usecatupd       16  0   1   6 0 -1 t f c f f));
+DATA(insert OID = 0 ( 1260 passwd      25  0  -1   7 0 -1 f f i f f));
+DATA(insert OID = 0 ( 1260 valuntil        702 0   4   8 0 -1 t f i f f));
 DATA(insert OID = 0 ( 1260 ctid                27 0  6  -1 0 -1 f f i f f));
 DATA(insert OID = 0 ( 1260 oid             26 0  4  -2 0 -1 t f i f f));
 DATA(insert OID = 0 ( 1260 xmin                28 0  4  -3 0 -1 f f i f f));
index 1240e8ac4fe20d42c6c87f60401082cf46f436d1..7c0ee50fec9c8fad3fd465452ef98b6dc42f8566 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_class.h,v 1.16 1997/11/21 18:12:07 momjian Exp $
+ * $Id: pg_class.h,v 1.17 1997/12/04 00:27:50 scrappy Exp $
  *
  * NOTES
  *   ``pg_relation'' is being replaced by ``pg_class''.  currently
@@ -125,7 +125,7 @@ DATA(insert OID = 1255 (  pg_proc 81          PGUID 0 0 0 f f r 16 0 0 f _null_ ));
 DESCR("");
 DATA(insert OID = 1259 (  pg_class 83        PGUID 0 0 0 f f r 18 0 0 f _null_ ));
 DESCR("");
-DATA(insert OID = 1260 (  pg_user 86         PGUID 0 0 0 f t r 6  0 0 f _null_ ));
+DATA(insert OID = 1260 (  pg_user 86         PGUID 0 0 0 f t r 8  0 0 f _null_ ));
 DESCR("");
 DATA(insert OID = 1261 (  pg_group 87        PGUID 0 0 0 f t s 3  0 0 f _null_ ));
 DESCR("");
index 7f7bd8b6525e84a1224a37a346d291e31aff3632..8e6bb2cd0ee1a825dee3d21344741d846b87ddd5 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_user.h,v 1.5 1997/09/08 02:35:34 momjian Exp $
+ * $Id: pg_user.h,v 1.6 1997/12/04 00:27:54 scrappy Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
@@ -36,6 +36,8 @@ CATALOG(pg_user) BOOTSTRAP
    bool        usetrace;
    bool        usesuper;
    bool        usecatupd;
+   text        passwd;
+   int4        valuntil;
 } FormData_pg_user;
 
 /* ----------------
@@ -49,46 +51,48 @@ typedef FormData_pg_user *Form_pg_user;
  *     compiler constants for pg_user
  * ----------------
  */
-#define Natts_pg_user                  6
+#define Natts_pg_user                  8
 #define Anum_pg_user_usename           1
 #define Anum_pg_user_usesysid          2
 #define Anum_pg_user_usecreatedb       3
 #define Anum_pg_user_usetrace          4
 #define Anum_pg_user_usesuper          5
 #define Anum_pg_user_usecatupd         6
+#define Anum_pg_user_passwd            7
+#define Anum_pg_user_valuntil          8
 
 /* ----------------
  *     initial contents of pg_user
  * ----------------
  */
-DATA(insert OID = 0 ( postgres PGUID t t t t ));
+DATA(insert OID = 0 ( postgres PGUID t t t t postgres 2116994400 ));
 
 BKI_BEGIN
 #ifdef ALLOW_PG_GROUP
 BKI_END
 
-DATA(insert OID = 0 ( mike 799 t t t t ));
-DATA(insert OID = 0 ( mao 1806 t t t t ));
-DATA(insert OID = 0 ( hellers 1089 t t t t ));
-DATA(insert OID = 0 ( joey 5209 t t t t ));
-DATA(insert OID = 0 ( jolly 5443 t t t t ));
-DATA(insert OID = 0 ( sunita 6559 t t t t ));
-DATA(insert OID = 0 ( paxson 3029 t t t t ));
-DATA(insert OID = 0 ( marc 2435 t t t t ));
-DATA(insert OID = 0 ( jiangwu 6124 t t t t ));
-DATA(insert OID = 0 ( aoki 2360 t t t t ));
-DATA(insert OID = 0 ( avi 31080 t t t t ));
-DATA(insert OID = 0 ( kristin 1123 t t t t ));
-DATA(insert OID = 0 ( andrew 5229 t t t t ));
-DATA(insert OID = 0 ( nobuko 5493 t t t t ));
-DATA(insert OID = 0 ( hartzell 6676 t t t t ));
-DATA(insert OID = 0 ( devine 6724 t t t t ));
-DATA(insert OID = 0 ( boris 6396 t t t t ));
-DATA(insert OID = 0 ( sklower 354 t t t t ));
-DATA(insert OID = 0 ( marcel 31113 t t t t ));
-DATA(insert OID = 0 ( ginger 3692 t t t t ));
-DATA(insert OID = 0 ( woodruff 31026 t t t t ));
-DATA(insert OID = 0 ( searcher 8261 t t t t ));
+DATA(insert OID = 0 ( mike 799 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( mao 1806 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( hellers 1089 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( joey 5209 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( jolly 5443 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( sunita 6559 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( paxson 3029 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( marc 2435 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( jiangwu 6124 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( aoki 2360 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( avi 31080 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( kristin 1123 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( andrew 5229 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( nobuko 5493 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( hartzell 6676 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( devine 6724 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( boris 6396 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( sklower 354 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( marcel 31113 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( ginger 3692 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( woodruff 31026 t t t t _null_ 2116994400 ));
+DATA(insert OID = 0 ( searcher 8261 t t t t _null_ 2116994400 ));
 
 BKI_BEGIN
 #endif                         /* ALLOW_PG_GROUP */
index 399e3231b65c928efb93a6bd107bfde156d0b661..a832918f947c022097ec7509bc64c730093ebd87 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqcomm.h,v 1.16 1997/11/07 20:52:06 momjian Exp $
+ * $Id: pqcomm.h,v 1.17 1997/12/04 00:27:56 scrappy Exp $
  *
  * NOTES
  *   Some of this should move to libpq.h
@@ -59,7 +59,16 @@ typedef enum _MsgType
    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 */
+   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 */
@@ -119,6 +128,7 @@ typedef struct Port
     * PacketBufId              id;
 *//* id of packet buf currently in use */
    PacketBuf   buf;            /* stream implementation (curr pack buf) */
+   char        salt[2];
 } Port;
 
 /* invalid socket descriptor */
index 7239818bd95527ffc49da26e759ba193ad3b5148..7388c0af8322335ce928dc5b4a9dcab700d0af9c 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.17 1997/11/21 18:12:25 momjian Exp $
+ * $Id: nodes.h,v 1.18 1997/12/04 00:28:01 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -186,6 +186,9 @@ typedef enum NodeTag
    T_DropTrigStmt,
    T_CreatePLangStmt,
    T_DropPLangStmt,
+   T_CreateUserStmt,
+   T_AlterUserStmt,
+   T_DropUserStmt,
 
    T_A_Expr = 700,
    T_Attr,
index c0a77d1ff3a5b7d23a510bb8c53a38e1b8b0ea39..8674f456dd154c386bdf0929d3b51c0266920c0d 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.35 1997/11/24 05:09:50 momjian Exp $
+ * $Id: parsenodes.h,v 1.36 1997/12/04 00:28:03 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -197,6 +197,30 @@ typedef struct DropPLangStmt
 }          DropPLangStmt;
 
 
+/* ----------------------
+ *              Create/Alter/Drop User Statements
+ * ----------------------
+ */
+typedef struct CreateUserStmt
+{
+        NodeTag         type;
+        char*           user;           /* PostgreSQL user login              */
+        char*           password;       /* PostgreSQL user password           */
+        bool*           createdb;       /* Can the user create databases?     */
+        bool*           createuser;     /* Can this user create users?        */
+        List*           groupElts;      /* The groups the user is a member of */
+        char*           validUntil;     /* The time the login is valid until  */
+} CreateUserStmt;
+
+typedef CreateUserStmt        AlterUserStmt;
+
+typedef struct DropUserStmt
+{
+        NodeTag         type;
+        char*           user;           /* PostgreSQL user login              */
+} DropUserStmt;
+
+
 /* ----------------------
  *     Create SEQUENCE Statement
  * ----------------------
index 3bcd919dc0cf8a006952c072115b8957b818dd3e..8f96230f02d1ecc263e670ad79c5230918161c69 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.11 1997/09/08 21:55:32 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.12 1997/12/04 00:28:08 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -511,6 +511,7 @@ fe_sendauth(MsgType msgtype, Port *port, const char *hostname,
        case STARTUP_MSG:
            break;
        case STARTUP_PASSWORD_MSG:
+       case STARTUP_CRYPT_MSG:
            pg_password_sendauth(port, user, password);
        default:
            break;
index cd5331f7981fad6a1032b12b32b4b7aaada15b58..84fa1f6742c45f0eac73ff3a0cfa68f9b0d80df8 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.49 1997/12/01 22:02:46 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.50 1997/12/04 00:28:11 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,9 @@
 #ifndef HAVE_STRDUP
 #include "strdup.h"
 #endif
+#ifdef HAVE_CRYPT_H
+#include 
+#endif
 
 
 /* use a local version instead of the one found in pqpacket.c */
@@ -284,7 +287,7 @@ PQconndefaults(void)
 }
 
 /* ----------------
- *     PQsetdb
+ *     PQsetdbLogin
  *
  * establishes a connection to a postgres backend through the postmaster
  * at the specified host and port.
@@ -324,7 +327,7 @@ PQconndefaults(void)
  * ----------------
  */
 PGconn    *
-PQsetdb(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName)
+PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd)
 {
    PGconn     *conn;
    char       *tmp;
@@ -386,7 +389,12 @@ PQsetdb(const char *pghost, const char *pgport, const char *pgoptions, const cha
        else
            conn->pgoptions = strdup(pgoptions);
 
-       if ((tmp = getenv("PGUSER")) != NULL)
+       if (login)
+       {
+           error = FALSE;
+           conn->pguser = strdup(login);
+       }
+       else if ((tmp = getenv("PGUSER")) != NULL)
        {
            error = FALSE;
            conn->pguser = strdup(tmp);
@@ -407,8 +415,14 @@ PQsetdb(const char *pghost, const char *pgport, const char *pgoptions, const cha
            }
        }
 
-       if ((tmp = getenv("PGPASSWORD")) != NULL)
+       if (pwd)
+       {
+           conn->pgpass = strdup(pwd);
+       }
+       else if ((tmp = getenv("PGPASSWORD")) != NULL)
+       {
            conn->pgpass = strdup(tmp);
+       }
        else
            conn->pgpass = 0;
 
@@ -479,6 +493,7 @@ connectDB(PGconn *conn)
 
    StartupInfo startup;
    PacketBuf   pacBuf;
+   PacketLen   pacLen;
    int         status;
    MsgType     msgtype;
    int         laddrlen = sizeof(struct sockaddr);
@@ -486,6 +501,8 @@ connectDB(PGconn *conn)
    int         portno,
                family,
                len;
+   bool            salted = false;
+   char*           tmp;
 
    /*
     * Initialize the startup packet.
@@ -592,7 +609,57 @@ connectDB(PGconn *conn)
    }
 
    /* by this point, connection has been opened */
-   msgtype = fe_getauthsvc(conn->errorMessage);
+
+        /* 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);
@@ -820,6 +887,63 @@ packetSend(Port *port,
    return (STATUS_OK);
 }
 
+/*
+ * 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
+
+ * 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;
+}
+
 /*
  * startup2PacketBuf()
  *
index bbacedf6dd6dcf25271f055cd060383abb3c0d01..7a68e3dedcd5f068f581173e3a16b99c662637b3 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fe-connect.h,v 1.4 1997/09/08 21:55:39 momjian Exp $
+ * $Id: fe-connect.h,v 1.5 1997/12/04 00:28:13 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
  */
 
 extern int packetSend(Port *port, PacketBuf *buf, PacketLen len, bool nonBlocking);
+extern int packetReceive(Port *port, PacketBuf *buf, bool nonBlocking);
 
 #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 6f2d93b8db47918862fd25839bdf4bb6fe7f2fc3..ce54af85b04ee897f405ff0fa3406c5cbba4144d 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-fe.h,v 1.23 1997/09/08 21:55:45 momjian Exp $
+ * $Id: libpq-fe.h,v 1.24 1997/12/04 00:28:15 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -221,8 +221,9 @@ extern      "C"
    /* make a new client connection to the backend */
    extern PGconn *PQconnectdb(const char *conninfo);
    extern PQconninfoOption *PQconndefaults(void);
-   extern PGconn *PQsetdb(const char *pghost, const char *pgport, const char *pgoptions,
-                                 const char *pgtty, const char *dbName);
+   extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
+                     const char *pgtty, const char *dbName, const char *login, const char *pwd);
+#define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME)   PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL)
    /* close the current connection and free the PGconn data structure */
    extern void PQfinish(PGconn *conn);