[patch 3/6] better error handling - Mailing list pgsql-patches

From Marko Kreen
Subject [patch 3/6] better error handling
Date
Msg-id 20050319234647.126944000@grue
Whole thread Raw
In response to [patch 0/6] pgcrypto update  (Marko Kreen <marko@l-t.ee>)
List pgsql-patches
* Use error codes instead of -1
* px_strerror for new error codes
* calling convention change for px_gen_salt - return error code
* use px_strerror in pgcrypto.c


Index: pgsql/contrib/pgcrypto/px.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/px.c
--- pgsql/contrib/pgcrypto/px.c
***************
*** 33,38 ****
--- 33,73 ----

  #include "px.h"

+ struct error_desc {
+     int err;
+     const char *desc;
+ };
+
+ static const struct error_desc px_err_list[] = {
+     {PXE_OK, "Everything ok"},
+     {PXE_ERR_GENERIC, "Some PX error (not specified)"},
+     {PXE_NO_HASH, "No such hash algorithm"},
+     {PXE_NO_CIPHER, "No such cipher algorithm"},
+     {PXE_NOTBLOCKSIZE, "Data not a multiple of block size"},
+     {PXE_BAD_OPTION, "Unknown option"},
+     {PXE_BAD_FORMAT, "Badly formatted type"},
+     {PXE_KEY_TOO_BIG, "Key was too big"},
+     {PXE_CIPHER_INIT, "Cipher cannot be initalized ?"},
+     {PXE_HASH_UNUSABLE_FOR_HMAC, "This hash algorithm is unusable for HMAC"},
+     {PXE_DEV_READ_ERROR, "Error reading from random device"},
+     {PXE_OSSL_RAND_ERROR, "OpenSSL PRNG error"},
+     {PXE_BUG, "pgcrypto bug"},
+     {PXE_ARGUMENT_ERROR, "Illegal argument to function"},
+     {PXE_UNKNOWN_SALT_ALGO, "Unknown salt algorithm"},
+     {PXE_BAD_SALT_ROUNDS, "Incorrect number of rounds"},
+     {PXE_MCRYPT_INTERNAL, "mcrypt internal error"},
+     {0, NULL},
+ };
+
+ const char *px_strerror(int err)
+ {
+     const struct error_desc *e;
+     for (e = px_err_list; e->desc; e++)
+         if (e->err == err)
+             return e->desc;
+     return "Bad error code";
+ }
+

  const char *
  px_resolve_alias(const PX_Alias * list, const char *name)
*************** combo_decrypt(PX_Combo * cx, const uint8
*** 215,224 ****

      return 0;

-     /* error reporting should be done in pgcrypto.c */
  block_error:
!     elog(WARNING, "Data not a multiple of block size");
!     return -1;
  }

  static void
--- 250,257 ----

      return 0;

  block_error:
!     return PXE_NOTBLOCKSIZE;
  }

  static void
*************** parse_cipher_name(char *full, char **cip
*** 262,271 ****
              if (!strcmp(p, "pad"))
                  *pad = p2;
              else
!                 return -1;
          }
          else
!             return -1;

          p = q;
      }
--- 295,304 ----
              if (!strcmp(p, "pad"))
                  *pad = p2;
              else
!                 return PXE_BAD_OPTION;
          }
          else
!             return PXE_BAD_FORMAT;

          p = q;
      }
*************** err1:
*** 332,336 ****
          px_cipher_free(cx->cipher);
      px_free(cx);
      px_free(buf);
!     return -1;
  }
--- 365,369 ----
          px_cipher_free(cx->cipher);
      px_free(cx);
      px_free(buf);
!     return PXE_NO_CIPHER;
  }
Index: pgsql/contrib/pgcrypto/px.h
===================================================================
*** pgsql.orig/contrib/pgcrypto/px.h
--- pgsql/contrib/pgcrypto/px.h
*************** void        px_free(void *p);
*** 63,68 ****
--- 63,88 ----
  /* max salt returned */
  #define PX_MAX_SALT_LEN        128

+ /*
+  * PX error codes
+  */
+ #define PXE_OK                        0
+ #define PXE_ERR_GENERIC                -1
+ #define PXE_NO_HASH                    -2
+ #define PXE_NO_CIPHER                -3
+ #define PXE_NOTBLOCKSIZE            -4
+ #define PXE_BAD_OPTION                -5
+ #define PXE_BAD_FORMAT                -6
+ #define PXE_KEY_TOO_BIG                -7
+ #define PXE_CIPHER_INIT                -8
+ #define PXE_HASH_UNUSABLE_FOR_HMAC    -9
+ #define PXE_DEV_READ_ERROR            -10
+ #define PXE_OSSL_RAND_ERROR            -11
+ #define PXE_BUG                        -12
+ #define PXE_ARGUMENT_ERROR            -13
+ #define PXE_UNKNOWN_SALT_ALGO        -14
+ #define PXE_BAD_SALT_ROUNDS            -15
+ #define PXE_MCRYPT_INTERNAL            -16

  typedef struct px_digest PX_MD;
  typedef struct px_alias PX_Alias;
*************** int            px_find_combo(const char *name, PX
*** 149,154 ****
--- 169,176 ----

  int            px_get_random_bytes(uint8 *dst, unsigned count);

+ const char *px_strerror(int err);
+
  const char *px_resolve_alias(const PX_Alias * aliases, const char *name);

  #define px_md_result_size(md)        (md)->result_size(md)
Index: pgsql/contrib/pgcrypto/internal.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/internal.c
--- pgsql/contrib/pgcrypto/internal.c
*************** rj_init(PX_Cipher * c, const uint8 *key,
*** 275,281 ****
      else if (klen <= 256 / 8)
          cx->keylen = 256 / 8;
      else
!         return -1;

      memcpy(&cx->keybuf, key, klen);

--- 275,281 ----
      else if (klen <= 256 / 8)
          cx->keylen = 256 / 8;
      else
!         return PXE_KEY_TOO_BIG;

      memcpy(&cx->keybuf, key, klen);

*************** rj_encrypt(PX_Cipher * c, const uint8 *d
*** 300,313 ****
      if (!cx->is_init)
      {
          if (rj_real_init(cx, 1))
!             return -1;
      }

      if (dlen == 0)
          return 0;

      if (dlen & 15)
!         return -1;

      memcpy(res, data, dlen);

--- 300,313 ----
      if (!cx->is_init)
      {
          if (rj_real_init(cx, 1))
!             return PXE_CIPHER_INIT;
      }

      if (dlen == 0)
          return 0;

      if (dlen & 15)
!         return PXE_NOTBLOCKSIZE;

      memcpy(res, data, dlen);

*************** rj_decrypt(PX_Cipher * c, const uint8 *d
*** 329,341 ****

      if (!cx->is_init)
          if (rj_real_init(cx, 0))
!             return -1;

      if (dlen == 0)
          return 0;

      if (dlen & 15)
!         return -1;

      memcpy(res, data, dlen);

--- 329,341 ----

      if (!cx->is_init)
          if (rj_real_init(cx, 0))
!             return PXE_CIPHER_INIT;

      if (dlen == 0)
          return 0;

      if (dlen & 15)
!         return PXE_NOTBLOCKSIZE;

      memcpy(res, data, dlen);

*************** bf_encrypt(PX_Cipher * c, const uint8 *d
*** 422,428 ****
          return 0;

      if (dlen & 7)
!         return -1;

      memcpy(res, data, dlen);
      switch (cx->mode)
--- 422,428 ----
          return 0;

      if (dlen & 7)
!         return PXE_NOTBLOCKSIZE;

      memcpy(res, data, dlen);
      switch (cx->mode)
*************** bf_decrypt(PX_Cipher * c, const uint8 *d
*** 446,452 ****
          return 0;

      if (dlen & 7)
!         return -1;

      memcpy(res, data, dlen);
      switch (cx->mode)
--- 446,452 ----
          return 0;

      if (dlen & 7)
!         return PXE_NOTBLOCKSIZE;

      memcpy(res, data, dlen);
      switch (cx->mode)
*************** px_find_digest(const char *name, PX_MD *
*** 556,562 ****

              return 0;
          }
!     return -1;
  }

  int
--- 556,562 ----

              return 0;
          }
!     return PXE_NO_HASH;
  }

  int
*************** px_find_cipher(const char *name, PX_Ciph
*** 575,581 ****
          }

      if (c == NULL)
!         return -1;

      *res = c;
      return 0;
--- 575,581 ----
          }

      if (c == NULL)
!         return PXE_NO_CIPHER;

      *res = c;
      return 0;
Index: pgsql/contrib/pgcrypto/openssl.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/openssl.c
--- pgsql/contrib/pgcrypto/openssl.c
*************** px_find_digest(const char *name, PX_MD *
*** 112,118 ****

      md = EVP_get_digestbyname(name);
      if (md == NULL)
!         return -1;

      ctx = px_alloc(sizeof(*ctx));
      EVP_DigestInit(ctx, md);
--- 112,118 ----

      md = EVP_get_digestbyname(name);
      if (md == NULL)
!         return PXE_NO_HASH;

      ctx = px_alloc(sizeof(*ctx));
      EVP_DigestInit(ctx, md);
*************** px_find_cipher(const char *name, PX_Ciph
*** 504,510 ****
          if (!strcmp(i->name, name))
              break;
      if (i->name == NULL)
!         return -1;

      od = px_alloc(sizeof(*od));
      memset(od, 0, sizeof(*od));
--- 504,510 ----
          if (!strcmp(i->name, name))
              break;
      if (i->name == NULL)
!         return PXE_NO_CIPHER;

      od = px_alloc(sizeof(*od));
      memset(od, 0, sizeof(*od));
Index: pgsql/contrib/pgcrypto/px-hmac.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/px-hmac.c
--- pgsql/contrib/pgcrypto/px-hmac.c
*************** px_find_hmac(const char *name, PX_HMAC *
*** 158,164 ****
      if (bs < 2)
      {
          px_md_free(md);
!         return -1;
      }

      h = px_alloc(sizeof(*h));
--- 158,164 ----
      if (bs < 2)
      {
          px_md_free(md);
!         return PXE_HASH_UNUSABLE_FOR_HMAC;
      }

      h = px_alloc(sizeof(*h));
Index: pgsql/contrib/pgcrypto/random.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/random.c
--- pgsql/contrib/pgcrypto/random.c
*************** safe_read(int fd, void *buf, size_t coun
*** 55,61 ****
          {
              if (errno == EINTR)
                  continue;
!             return -1;
          }
          p += res;
          done += res;
--- 55,61 ----
          {
              if (errno == EINTR)
                  continue;
!             return PXE_DEV_READ_ERROR;
          }
          p += res;
          done += res;
*************** px_get_random_bytes(uint8 *dst, unsigned
*** 72,78 ****

      fd = open(RAND_DEV, O_RDONLY);
      if (fd == -1)
!         return -1;
      res = safe_read(fd, dst, count);
      close(fd);
      return res;
--- 72,78 ----

      fd = open(RAND_DEV, O_RDONLY);
      if (fd == -1)
!         return PXE_DEV_READ_ERROR;
      res = safe_read(fd, dst, count);
      close(fd);
      return res;
*************** px_get_random_bytes(uint8 *dst, unsigned
*** 117,126 ****
       */

      res = RAND_bytes(dst, count);
!     if (res > 0)
          return count;

!     return -1;
  }

  #else
--- 117,126 ----
       */

      res = RAND_bytes(dst, count);
!     if (res == 1)
          return count;

!     return PXE_OSSL_RAND_ERROR;
  }

  #else
Index: pgsql/contrib/pgcrypto/px-crypt.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/px-crypt.c
--- pgsql/contrib/pgcrypto/px-crypt.c
*************** static struct generator gen_list[] = {
*** 147,185 ****
      {NULL, NULL, 0, 0, 0, 0}
  };

! unsigned
  px_gen_salt(const char *salt_type, char *buf, int rounds)
  {
!     int            i,
!                 res;
      struct generator *g;
      char       *p;
      char        rbuf[16];

!     for (i = 0; gen_list[i].name; i++)
!     {
!         g = &gen_list[i];
!         if (pg_strcasecmp(g->name, salt_type) != 0)
!             continue;
!
!         if (g->def_rounds)
!         {
!             if (rounds == 0)
!                 rounds = g->def_rounds;
!
!             if (rounds < g->min_rounds || rounds > g->max_rounds)
!                 return 0;
!         }
!
!         res = px_get_random_bytes(rbuf, g->input_len);
!         if (res != g->input_len)
!             return 0;

!         p = g->gen(rounds, rbuf, g->input_len, buf, PX_MAX_SALT_LEN);
!         memset(rbuf, 0, sizeof(rbuf));

!         return p != NULL ? strlen(p) : 0;
      }

!     return 0;
  }
--- 147,186 ----
      {NULL, NULL, 0, 0, 0, 0}
  };

! int
  px_gen_salt(const char *salt_type, char *buf, int rounds)
  {
!     int            res;
      struct generator *g;
      char       *p;
      char        rbuf[16];

!     for (g = gen_list; g->name; g++)
!         if (pg_strcasecmp(g->name, salt_type) == 0)
!             break;
!
!     if (g->name == NULL)
!         return PXE_UNKNOWN_SALT_ALGO;

!     if (g->def_rounds)
!     {
!         if (rounds == 0)
!             rounds = g->def_rounds;

!         if (rounds < g->min_rounds || rounds > g->max_rounds)
!             return PXE_BAD_SALT_ROUNDS;
      }

!     res = px_get_random_bytes(rbuf, g->input_len);
!     if (res < 0)
!         return res;
!
!     p = g->gen(rounds, rbuf, g->input_len, buf, PX_MAX_SALT_LEN);
!     memset(rbuf, 0, sizeof(rbuf));
!
!     if (p == NULL)
!         return PXE_BAD_SALT_ROUNDS;
!
!     return strlen(p);
  }
+
Index: pgsql/contrib/pgcrypto/px-crypt.h
===================================================================
*** pgsql.orig/contrib/pgcrypto/px-crypt.h
--- pgsql/contrib/pgcrypto/px-crypt.h
***************
*** 49,55 ****
   * main interface
   */
  char       *px_crypt(const char *psw, const char *salt, char *buf, unsigned buflen);
! unsigned    px_gen_salt(const char *salt_type, char *dst, int rounds);

  /*
   * internal functions
--- 49,55 ----
   * main interface
   */
  char       *px_crypt(const char *psw, const char *salt, char *buf, unsigned buflen);
! int            px_gen_salt(const char *salt_type, char *dst, int rounds);

  /*
   * internal functions
Index: pgsql/contrib/pgcrypto/pgcrypto.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgcrypto.c
--- pgsql/contrib/pgcrypto/pgcrypto.c
*************** Datum
*** 190,196 ****
  pg_gen_salt(PG_FUNCTION_ARGS)
  {
      text       *arg0;
!     unsigned    len;
      text       *res;
      char        buf[PX_MAX_SALT_LEN + 1];

--- 190,196 ----
  pg_gen_salt(PG_FUNCTION_ARGS)
  {
      text       *arg0;
!     int            len;
      text       *res;
      char        buf[PX_MAX_SALT_LEN + 1];

*************** pg_gen_salt(PG_FUNCTION_ARGS)
*** 204,213 ****
      memcpy(buf, VARDATA(arg0), len);
      buf[len] = 0;
      len = px_gen_salt(buf, buf, 0);
!     if (len == 0)
          ereport(ERROR,
                  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                  errmsg("no such crypt algorithm")));

      res = (text *) palloc(len + VARHDRSZ);
      VARATT_SIZEP(res) = len + VARHDRSZ;
--- 204,213 ----
      memcpy(buf, VARDATA(arg0), len);
      buf[len] = 0;
      len = px_gen_salt(buf, buf, 0);
!     if (len < 0)
          ereport(ERROR,
                  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                  errmsg("gen_salt: %s", px_strerror(len))));

      res = (text *) palloc(len + VARHDRSZ);
      VARATT_SIZEP(res) = len + VARHDRSZ;
*************** pg_gen_salt_rounds(PG_FUNCTION_ARGS)
*** 226,232 ****
  {
      text       *arg0;
      int            rounds;
!     unsigned    len;
      text       *res;
      char        buf[PX_MAX_SALT_LEN + 1];

--- 226,232 ----
  {
      text       *arg0;
      int            rounds;
!     int            len;
      text       *res;
      char        buf[PX_MAX_SALT_LEN + 1];

*************** pg_gen_salt_rounds(PG_FUNCTION_ARGS)
*** 241,250 ****
      memcpy(buf, VARDATA(arg0), len);
      buf[len] = 0;
      len = px_gen_salt(buf, buf, rounds);
!     if (len == 0)
          ereport(ERROR,
                  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!              errmsg("no such crypt algorithm or bad number of rounds")));

      res = (text *) palloc(len + VARHDRSZ);
      VARATT_SIZEP(res) = len + VARHDRSZ;
--- 241,250 ----
      memcpy(buf, VARDATA(arg0), len);
      buf[len] = 0;
      len = px_gen_salt(buf, buf, rounds);
!     if (len < 0)
          ereport(ERROR,
                  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!              errmsg("gen_salt: %s", px_strerror(len))));

      res = (text *) palloc(len + VARHDRSZ);
      VARATT_SIZEP(res) = len + VARHDRSZ;
*************** pg_encrypt(PG_FUNCTION_ARGS)
*** 360,366 ****
          pfree(res);
          ereport(ERROR,
                  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
!                  errmsg("encrypt error: %d", err)));
      }

      VARATT_SIZEP(res) = VARHDRSZ + rlen;
--- 360,366 ----
          pfree(res);
          ereport(ERROR,
                  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
!                  errmsg("encrypt error: %s", px_strerror(err))));
      }

      VARATT_SIZEP(res) = VARHDRSZ + rlen;
*************** pg_decrypt(PG_FUNCTION_ARGS)
*** 406,412 ****
      if (err)
          ereport(ERROR,
                  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
!                  errmsg("decrypt error: %d", err)));

      VARATT_SIZEP(res) = VARHDRSZ + rlen;

--- 406,412 ----
      if (err)
          ereport(ERROR,
                  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
!                  errmsg("decrypt error: %s", px_strerror(err))));

      VARATT_SIZEP(res) = VARHDRSZ + rlen;

*************** pg_encrypt_iv(PG_FUNCTION_ARGS)
*** 461,467 ****
      if (err)
          ereport(ERROR,
                  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
!                  errmsg("encrypt_iv error: %d", err)));

      VARATT_SIZEP(res) = VARHDRSZ + rlen;

--- 461,467 ----
      if (err)
          ereport(ERROR,
                  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
!                  errmsg("encrypt_iv error: %s", px_strerror(err))));

      VARATT_SIZEP(res) = VARHDRSZ + rlen;

*************** pg_decrypt_iv(PG_FUNCTION_ARGS)
*** 517,523 ****
      if (err)
          ereport(ERROR,
                  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
!                  errmsg("decrypt_iv error: %d", err)));

      VARATT_SIZEP(res) = VARHDRSZ + rlen;

--- 517,523 ----
      if (err)
          ereport(ERROR,
                  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
!                  errmsg("decrypt_iv error: %s", px_strerror(err))));

      VARATT_SIZEP(res) = VARHDRSZ + rlen;

*************** find_provider(text *name,
*** 568,574 ****
      if (err && !silent)
          ereport(ERROR,
                  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                  errmsg("%s type does not exist: \"%s\"", desc, buf)));

      pfree(buf);

--- 568,574 ----
      if (err && !silent)
          ereport(ERROR,
                  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                  errmsg("Cannot use \"%s\": %s", buf, px_strerror(err))));

      pfree(buf);


--

pgsql-patches by date:

Previous
From: Marko Kreen
Date:
Subject: [patch 5/6] pseudo random bytes
Next
From: Marko Kreen
Date:
Subject: [patch 2/6] various cleanups