Add 4-byte MD5 salt.
authorBruce Momjian <bruce@momjian.us>
Fri, 17 Aug 2001 02:59:20 +0000 (02:59 +0000)
committerBruce Momjian <bruce@momjian.us>
Fri, 17 Aug 2001 02:59:20 +0000 (02:59 +0000)
src/backend/commands/user.c
src/backend/libpq/auth.c
src/backend/libpq/crypt.c
src/backend/libpq/md5.c
src/backend/postmaster/postmaster.c
src/include/libpq/crypt.h
src/include/libpq/libpq-be.h
src/interfaces/libpq/fe-auth.c
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/libpq-int.h
src/interfaces/odbc/connection.c

index 3b730a3a0d80ee511c4859063daa8ef8f3619f48..d830dfdfc9049c230f1dd8c682ea83acfd1fdbfc 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.81 2001/08/15 21:08:20 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.82 2001/08/17 02:59:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -351,7 +351,8 @@ CreateUser(CreateUserStmt *stmt)
                                DirectFunctionCall1(textin, CStringGetDatum(password));
                else
                {
-                       if (!EncryptMD5(password, stmt->user, encrypted_password))
+                       if (!EncryptMD5(password, stmt->user, strlen(stmt->user),
+                               encrypted_password))
                                elog(ERROR, "CREATE USER: password encryption failed");
                        new_record[Anum_pg_shadow_passwd - 1] =
                                DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
@@ -583,7 +584,8 @@ AlterUser(AlterUserStmt *stmt)
                                DirectFunctionCall1(textin, CStringGetDatum(password));
                else
                {
-                       if (!EncryptMD5(password, stmt->user, encrypted_password))
+                       if (!EncryptMD5(password, stmt->user, strlen(stmt->user),
+                               encrypted_password))
                                elog(ERROR, "CREATE USER: password encryption failed");
                        new_record[Anum_pg_shadow_passwd - 1] =
                                DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
index c139f93f715cca3861b25c4684bf3a18a55a0ca0..048f67c3013626ff0ed0a70263f3171e3e380e1e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.59 2001/08/16 16:24:15 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.60 2001/08/17 02:59:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -536,10 +536,17 @@ sendAuthRequest(Port *port, AuthRequest areq)
        pq_sendint(&buf, (int32) areq, sizeof(int32));
 
        /* Add the salt for encrypted passwords. */
-       if (areq == AUTH_REQ_CRYPT || areq == AUTH_REQ_MD5)
+       if (areq == AUTH_REQ_MD5)
        {
-               pq_sendint(&buf, port->salt[0], 1);
-               pq_sendint(&buf, port->salt[1], 1);
+               pq_sendint(&buf, port->md5Salt[0], 1);
+               pq_sendint(&buf, port->md5Salt[1], 1);
+               pq_sendint(&buf, port->md5Salt[2], 1);
+               pq_sendint(&buf, port->md5Salt[3], 1);
+       }
+       if (areq == AUTH_REQ_CRYPT)
+       {
+               pq_sendint(&buf, port->cryptSalt[0], 1);
+               pq_sendint(&buf, port->cryptSalt[1], 1);
        }
 
        pq_endmessage(&buf);
index a08c4f6baae9a2772f7ad5a89463f79d3d291de3..f82e44ccb25d8b078fa9136d6dcf78f9382425a0 100644 (file)
@@ -9,7 +9,7 @@
  * Dec 17, 1997 - Todd A. Brandys
  *     Orignal Version Completed.
  *
- * $Id: crypt.c,v 1.34 2001/08/15 21:08:21 momjian Exp $
+ * $Id: crypt.c,v 1.35 2001/08/17 02:59:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 
 #include "postgres.h"
 #include "libpq/crypt.h"
+#include "libpq/libpq.h"
 #include "miscadmin.h"
 #include "storage/fd.h"
 #include "utils/nabstime.h"
@@ -276,22 +277,33 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
                return STATUS_ERROR;
        }
 
+       /* If they encrypt their password, force MD5 */
+       if (isMD5(passwd) && port->auth_method != uaMD5)
+       {
+               snprintf(PQerrormsg, PQERRORMSG_LENGTH,
+                       "Password is stored MD5 encrypted.  "
+                       "Only pg_hba.conf's MD5 protocol can be used for this user.\n");
+               fputs(PQerrormsg, stderr);
+               pqdebug("%s", PQerrormsg);
+               return STATUS_ERROR;
+       }
+
        /*
         * Compare with the encrypted or plain password depending on the
         * authentication method being used for this connection.
         */
-        switch (port->auth_method)
-        {
+       switch (port->auth_method)
+       {
                case uaCrypt:
-                       crypt_pwd = crypt(passwd, port->salt);
+                       crypt_pwd = crypt(passwd, port->cryptSalt);
                        break;
                case uaMD5:
                        crypt_pwd = palloc(MD5_PASSWD_LEN+1);
-
                        if (isMD5(passwd))
                        {
                                if (!EncryptMD5(passwd + strlen("md5"),
-                                                               (char *)port->salt, crypt_pwd))
+                                                               (char *)port->md5Salt,
+                                                               sizeof(port->md5Salt), crypt_pwd))
                                {
                                        pfree(crypt_pwd);
                                        return STATUS_ERROR;
@@ -301,14 +313,15 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
                        {
                                char *crypt_pwd2 = palloc(MD5_PASSWD_LEN+1);
 
-                               if (!EncryptMD5(passwd, port->user, crypt_pwd2))
+                               if (!EncryptMD5(passwd, port->user, strlen(port->user),
+                                                               crypt_pwd2))
                                {
                                        pfree(crypt_pwd);
                                        pfree(crypt_pwd2);
                                        return STATUS_ERROR;
                                }
-                               if (!EncryptMD5(crypt_pwd2 + strlen("md5"), port->salt,
-                                                               crypt_pwd))
+                               if (!EncryptMD5(crypt_pwd2 + strlen("md5"), port->md5Salt,
+                                                               sizeof(port->md5Salt), crypt_pwd))
                                {
                                        pfree(crypt_pwd);
                                        pfree(crypt_pwd2);
@@ -324,7 +337,6 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
 
        if (!strcmp(pgpass, crypt_pwd))
        {
-
                /*
                 * check here to be sure we are not past valuntil
                 */
index 846202a7b17b6f5e8aa3eaabc07e7cc20bd80de5..76d54d50b0d799e24aa60ae8c039e8e38590b7c4 100644 (file)
@@ -295,16 +295,18 @@ md5_hash(const void *buff, size_t len, char *hexsum)
  * puts  md5(username+passwd)  in buf provided buflen is at least 36 bytes
  * returns 1 on success, 0 on any kind of failure and sets errno accordingly
  */
-bool EncryptMD5(const char *passwd, const char *salt, char *buf)
+bool EncryptMD5(const char *passwd, const char *salt, size_t salt_len,
+                               char *buf)
 {
        char crypt_buf[128];
 
-       if (strlen(salt) + strlen(passwd) > 127)
+       if (salt_len + strlen(passwd) > 127)
                return false;
 
        strcpy(buf, "md5");
        memset(crypt_buf, 0, 128);
-       sprintf(crypt_buf,"%s%s", salt, passwd);
+       memcpy(crypt_buf, salt, salt_len);
+       memcpy(crypt_buf+salt_len, passwd, strlen(passwd));
 
-       return md5_hash(crypt_buf, strlen(crypt_buf), buf + 3);
+       return md5_hash(crypt_buf, salt_len + strlen(passwd), buf + 3);
 }
index c3036630bc55544a282ec150624265753f55bb2c..1a6ebec5daf287b3c5fee362ede308c5ba2cdc95 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.235 2001/08/05 02:06:50 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.236 2001/08/17 02:59:19 momjian Exp $
  *
  * NOTES
  *
@@ -243,7 +243,7 @@ static void processCancelRequest(Port *port, void *pkt);
 static int     initMasks(fd_set *rmask, fd_set *wmask);
 static char *canAcceptConnections(void);
 static long PostmasterRandom(void);
-static void RandomSalt(char *salt);
+static void RandomSalt(char *cryptSalt, char *md5Salt);
 static void SignalChildren(int signal);
 static int     CountChildren(void);
 static bool CreateOptsFile(int argc, char *argv[]);
@@ -1211,7 +1211,7 @@ ConnCreate(int serverFd)
        }
        else
        {
-               RandomSalt(port->salt);
+               RandomSalt(port->cryptSalt, port->md5Salt);
                port->pktInfo.state = Idle;
        }
 
@@ -2099,12 +2099,19 @@ CharRemap(long int ch)
  * RandomSalt
  */
 static void
-RandomSalt(char *salt)
+RandomSalt(char *cryptSalt, char *md5Salt)
 {
        long            rand = PostmasterRandom();
 
-       *salt = CharRemap(rand % 62);
-       *(salt + 1) = CharRemap(rand / 62);
+       cryptSalt[0] = CharRemap(rand % 62);
+       cryptSalt[1] = CharRemap(rand / 62);
+       /* Grab top 16-bits of two random runs so as not to send full
+          random value over the network.  The high-order bits are more random. */
+       md5Salt[0] = rand & 0xff000000;
+       md5Salt[1] = rand & 0x00ff0000;
+       rand = PostmasterRandom();
+       md5Salt[2] = rand & 0xff000000;
+       md5Salt[3] = rand & 0x00ff0000;
 }
 
 /*
index 86b9f2497c5fb1dd9cf34625af6c9e1c93ab2682..bec71ca168bb608a6ab4eb0ffaf52096a19d4511 100644 (file)
@@ -26,7 +26,8 @@ extern int md5_crypt_verify(const Port *port, const char *user, const char *pgpa
 
 extern bool md5_hash(const void *buff, size_t len, char *hexsum);
 extern bool CheckMD5Pwd(char *passwd, char *storedpwd, char *seed);
-extern bool EncryptMD5(const char *passwd, const char *salt, char *buf);
+extern bool EncryptMD5(const char *passwd, const char *salt, 
+                                          size_t salt_len, char *buf);
 
 #define MD5_PASSWD_LEN 35
 
index 1d4f9d06b0b6b31017d416c7ded051eb340f1edc..56e6443cb7f9deff41791df5eba578d42b924627 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-be.h,v 1.21 2001/01/24 19:43:24 momjian Exp $
+ * $Id: libpq-be.h,v 1.22 2001/08/17 02:59:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,7 +58,7 @@ typedef struct ErrorMessagePacket
 
 typedef struct AuthRequestPacket
 {
-       char            data[1 + sizeof(AuthRequest) + 2];              /* 'R' + the request +
+       char            data[1 + sizeof(AuthRequest) + 4];              /* 'R' + the request +
                                                                                                                 * optional salt. */
 } AuthRequestPacket;
 
@@ -119,7 +119,8 @@ typedef struct Port
        Packet          pktInfo;                /* For the packet handlers */
        SockAddr        laddr;                  /* local addr (us) */
        SockAddr        raddr;                  /* remote addr (them) */
-       char            salt[2];                /* Password salt */
+       char            md5Salt[4];             /* Password salt */
+       char            cryptSalt[2];   /* Password salt */
 
        /*
         * Information that needs to be held during the fe/be authentication
index d4cb0ffc31754670e70b7809f7b07d7d661aaad1..4e4a8f6d9368bfb6eb5849a8ba8ab6d69372dd2f 100644 (file)
@@ -10,7 +10,7 @@
  * exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.50 2001/08/15 21:08:21 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.51 2001/08/17 02:59:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -443,7 +443,7 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
        switch (areq)
        {
                case AUTH_REQ_CRYPT:
-                       crypt_pwd = crypt(password, conn->salt);
+                       crypt_pwd = crypt(password, conn->cryptSalt);
                        break;
                case AUTH_REQ_MD5:
                        {
@@ -455,14 +455,15 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
                                        perror("malloc");
                                        return STATUS_ERROR;
                                }
-                               if (!EncryptMD5(password, conn->pguser, crypt_pwd2))
+                               if (!EncryptMD5(password, conn->pguser,
+                                                               strlen(conn->pguser), crypt_pwd2))
                                {
                                        free(crypt_pwd);
                                        free(crypt_pwd2);
                                        return STATUS_ERROR;
                                }
-                               if (!EncryptMD5(crypt_pwd2 + strlen("md5"), conn->salt,
-                                                               crypt_pwd))
+                               if (!EncryptMD5(crypt_pwd2 + strlen("md5"), conn->md5Salt,
+                                                               sizeof(conn->md5Salt), crypt_pwd))
                                {
                                        free(crypt_pwd);
                                        free(crypt_pwd2);
index 32983c53ad1a57a195b3fed2dd3e2cb58e451051..d97c1004b37a34038cecf75c5a496c3127077da3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.173 2001/08/15 18:42:15 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.174 2001/08/17 02:59:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1341,9 +1341,19 @@ keep_going:                                              /* We will come back to here until there
                                }
 
                                /* Get the password salt if there is one. */
-                               if (areq == AUTH_REQ_CRYPT || areq == AUTH_REQ_MD5)
+                               if (areq == AUTH_REQ_MD5)
                                {
-                                       if (pqGetnchar(conn->salt, sizeof(conn->salt), conn))
+                                       if (pqGetnchar(conn->md5Salt,
+                                                                  sizeof(conn->md5Salt), conn))
+                                       {
+                                               /* We'll come back when there are more data */
+                                               return PGRES_POLLING_READING;
+                                       }
+                               }
+                               if (areq == AUTH_REQ_CRYPT)
+                               {
+                                       if (pqGetnchar(conn->cryptSalt,
+                                                                  sizeof(conn->cryptSalt), conn))
                                        {
                                                /* We'll come back when there are more data */
                                                return PGRES_POLLING_READING;
index bab52c390b394bb2f470d8f44556573b66974465..580ac0f0698010b7e38c7500a38bebc91bde0740 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-int.h,v 1.38 2001/08/16 04:27:18 momjian Exp $
+ * $Id: libpq-int.h,v 1.39 2001/08/17 02:59:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -236,7 +236,8 @@ struct pg_conn
        /* Miscellaneous stuff */
        int                     be_pid;                 /* PID of backend --- needed for cancels */
        int                     be_key;                 /* key of backend --- needed for cancels */
-       char            salt[2];                /* password salt received from backend */
+       char            md5Salt[4];             /* password salt received from backend */
+       char            cryptSalt[2];           /* password salt received from backend */
        PGlobjfuncs *lobjfuncs;         /* private state for large-object access
                                                                 * fns */
 
index 42196df9eedd2e005edc350f51b15ba32643f388..8c9719745f3988fcc9d9dbcf457e1af6fdc23870 100644 (file)
@@ -507,7 +507,7 @@ CC_connect(ConnectionClass *self, char do_password)
        int                     areq = -1;
        int                     beresp;
        char            msgbuffer[ERROR_MSG_LENGTH];
-       char            salt[2];
+       char            salt[5];
        static char *func = "CC_connect";
 
        mylog("%s: entering...\n", func);
@@ -677,7 +677,9 @@ CC_connect(ConnectionClass *self, char do_password)
                                                mylog("auth got 'R'\n");
 
                                                areq = SOCK_get_int(sock, 4);
-                                               if (areq == AUTH_REQ_CRYPT || areq == AUTH_REQ_MD5)
+                                               if (areq == AUTH_REQ_MD5)
+                                                       SOCK_get_n_char(sock, salt, 4);
+                                               if (areq == AUTH_REQ_CRYPT)
                                                        SOCK_get_n_char(sock, salt, 2);
 
                                                mylog("areq = %d\n", areq);