Add 4-byte MD5 salt.
authorBruce Momjian
Fri, 17 Aug 2001 02:59:20 +0000 (02:59 +0000)
committerBruce Momjian
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);