Re: passwords in pg_shadow (duplicate). - Mailing list pgsql-general

From Bruce Momjian
Subject Re: passwords in pg_shadow (duplicate).
Date
Msg-id 200212052018.gB5KIab29557@candle.pha.pa.us
Whole thread Raw
In response to Re: passwords in pg_shadow (duplicate).  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-general
You were looking at last night's patch.  The one attached is the one
applied, and it addresses exactly the ugly issue you saw.  It compares
to see if pgpass was reassigned with new memory, and frees only in that
case.

Also, in CVS HEAD, the variables are renamed client_pass and shadow_pass
so it is clear which is which.

---------------------------------------------------------------------------

Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Good catch.  Seems like a bug.  I assumed we still want to support
> > 'password' even though pg_shadow contains MD5 encrypted passwords.  Is
> > that correct?  (We can't support crypt in those cases.)
>
> I think we should fix this for 7.3.1.
>
> >       if (port->auth_method == uaMD5)
> >           pfree(crypt_pwd);
> > +     if (port->auth_method != uaMD5 && port->auth_method != uaCrypt &&
> > +         isMD5(passwd))
> > +         pfree((char *)pgpass);
>
> This part of your patch seems awfully fragile though.  Better style
> would be to add a boolean:
>
>     bool    free_pgpass = false;
>
>     ...
>     {
>         palloc pgpass here;
>         free_pgpass = true;
>     }
>
>     if (free_pgpass)
>         free(pg_pass);
>
> This is less fragile and easily extends to more cases that palloc
> pg_pass in future.
>
>             regards, tom lane
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/backend/libpq/crypt.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/libpq/crypt.c,v
retrieving revision 1.49
diff -c -c -r1.49 crypt.c
*** src/backend/libpq/crypt.c    4 Sep 2002 20:31:19 -0000    1.49
--- src/backend/libpq/crypt.c    5 Dec 2002 18:03:53 -0000
***************
*** 29,35 ****


  int
! md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
  {
      char       *passwd = NULL,
                 *valuntil = NULL,
--- 29,35 ----


  int
! md5_crypt_verify(const Port *port, const char *user, char *pgpass)
  {
      char       *passwd = NULL,
                 *valuntil = NULL,
***************
*** 37,42 ****
--- 37,43 ----
      int            retval = STATUS_ERROR;
      List      **line;
      List       *token;
+     char       *crypt_pgpass = pgpass;

      if ((line = get_user_line(user)) == NULL)
          return STATUS_ERROR;
***************
*** 54,64 ****
      if (passwd == NULL || *passwd == '\0')
          return STATUS_ERROR;

!     /* If they encrypt their password, force MD5 */
!     if (isMD5(passwd) && port->auth_method != uaMD5)
      {
          elog(LOG, "Password is stored MD5 encrypted.  "
!              "'password' and 'crypt' auth methods cannot be used.");
          return STATUS_ERROR;
      }

--- 55,65 ----
      if (passwd == NULL || *passwd == '\0')
          return STATUS_ERROR;

!     /* We can't do crypt with pg_shadow MD5 passwords */
!     if (isMD5(passwd) && port->auth_method == uaCrypt)
      {
          elog(LOG, "Password is stored MD5 encrypted.  "
!              "'crypt' auth method cannot be used.");
          return STATUS_ERROR;
      }

***************
*** 72,77 ****
--- 73,79 ----
              crypt_pwd = palloc(MD5_PASSWD_LEN + 1);
              if (isMD5(passwd))
              {
+                 /* pg_shadow already encrypted, only do salt */
                  if (!EncryptMD5(passwd + strlen("md5"),
                                  (char *) port->md5Salt,
                                  sizeof(port->md5Salt), crypt_pwd))
***************
*** 82,87 ****
--- 84,90 ----
              }
              else
              {
+                 /* pg_shadow plain, double-encrypt */
                  char       *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1);

                  if (!EncryptMD5(passwd, port->user, strlen(port->user),
***************
*** 110,120 ****
                  break;
              }
          default:
              crypt_pwd = passwd;
              break;
      }

!     if (strcmp(pgpass, crypt_pwd) == 0)
      {
          /*
           * Password OK, now check to be sure we are not past valuntil
--- 113,134 ----
                  break;
              }
          default:
+             if (isMD5(passwd))
+             {
+                 /* Encrypt user-supplied password to match MD5 in pg_shadow */
+                 crypt_pgpass = palloc(MD5_PASSWD_LEN + 1);
+                 if (!EncryptMD5(pgpass, port->user, strlen(port->user),
+                                 crypt_pgpass))
+                 {
+                     pfree(crypt_pgpass);
+                     return STATUS_ERROR;
+                 }
+             }
              crypt_pwd = passwd;
              break;
      }

!     if (strcmp(crypt_pgpass, crypt_pwd) == 0)
      {
          /*
           * Password OK, now check to be sure we are not past valuntil
***************
*** 136,141 ****
--- 150,157 ----

      if (port->auth_method == uaMD5)
          pfree(crypt_pwd);
+     if (crypt_pgpass != pgpass)
+         pfree(crypt_pgpass);

      return retval;
  }
Index: src/include/libpq/crypt.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/libpq/crypt.h,v
retrieving revision 1.22
diff -c -c -r1.22 crypt.h
*** src/include/libpq/crypt.h    4 Sep 2002 20:31:42 -0000    1.22
--- src/include/libpq/crypt.h    5 Dec 2002 18:03:54 -0000
***************
*** 23,29 ****


  extern int md5_crypt_verify(const Port *port, const char *user,
!                  const char *pgpass);
  extern bool md5_hash(const void *buff, size_t len, char *hexsum);
  extern bool CheckMD5Pwd(char *passwd, char *storedpwd, char *seed);

--- 23,29 ----


  extern int md5_crypt_verify(const Port *port, const char *user,
!                 char *pgpass);
  extern bool md5_hash(const void *buff, size_t len, char *hexsum);
  extern bool CheckMD5Pwd(char *passwd, char *storedpwd, char *seed);


pgsql-general by date:

Previous
From: Lamar Owen
Date:
Subject: 7.3-2 RPMset released.
Next
From: "Francisco Reyes"
Date:
Subject: Re: Size for vacuum_mem