PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pgp-pgsql.c
Go to the documentation of this file.
1 /*
2  * pgp-pgsql.c
3  * PostgreSQL wrappers for pgp.
4  *
5  * Copyright (c) 2005 Marko Kreen
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * contrib/pgcrypto/pgp-pgsql.c
30  */
31 
32 #include "postgres.h"
33 
34 #include "lib/stringinfo.h"
35 #include "catalog/pg_type.h"
36 #include "mb/pg_wchar.h"
37 #include "utils/builtins.h"
38 #include "utils/array.h"
39 #include "funcapi.h"
40 
41 #include "mbuf.h"
42 #include "px.h"
43 #include "pgp.h"
44 
45 /*
46  * public functions
47  */
52 
57 
59 
63 
64 /*
65  * Mix a block of data into RNG.
66  */
67 static void
69 {
70  uint8 sha1[20];
71 
72  px_md_reset(md);
73  px_md_update(md, (uint8 *) VARDATA(data), VARSIZE(data) - VARHDRSZ);
74  px_md_finish(md, sha1);
75 
76  px_add_entropy(sha1, 20);
77 
78  px_memset(sha1, 0, 20);
79 }
80 
81 /*
82  * Mix user data into RNG. It is for user own interests to have
83  * RNG state shuffled.
84  */
85 static void
86 add_entropy(text *data1, text *data2, text *data3)
87 {
88  PX_MD *md;
89  uint8 rnd[3];
90 
91  if (!data1 && !data2 && !data3)
92  return;
93 
94  if (px_get_random_bytes(rnd, 3) < 0)
95  return;
96 
97  if (px_find_digest("sha1", &md) < 0)
98  return;
99 
100  /*
101  * Try to make the feeding unpredictable.
102  *
103  * Prefer data over keys, as it's rather likely that key is same in
104  * several calls.
105  */
106 
107  /* chance: 7/8 */
108  if (data1 && rnd[0] >= 32)
109  add_block_entropy(md, data1);
110 
111  /* chance: 5/8 */
112  if (data2 && rnd[1] >= 160)
113  add_block_entropy(md, data2);
114 
115  /* chance: 5/8 */
116  if (data3 && rnd[2] >= 160)
117  add_block_entropy(md, data3);
118 
119  px_md_free(md);
120  px_memset(rnd, 0, sizeof(rnd));
121 }
122 
123 /*
124  * returns src in case of no conversion or error
125  */
126 static text *
127 convert_charset(text *src, int cset_from, int cset_to)
128 {
129  int src_len = VARSIZE(src) - VARHDRSZ;
130  unsigned char *dst;
131  unsigned char *csrc = (unsigned char *) VARDATA(src);
132  text *res;
133 
134  dst = pg_do_encoding_conversion(csrc, src_len, cset_from, cset_to);
135  if (dst == csrc)
136  return src;
137 
138  res = cstring_to_text((char *) dst);
139  pfree(dst);
140  return res;
141 }
142 
143 static text *
145 {
147 }
148 
149 static text *
151 {
153 }
154 
155 static bool
156 string_is_ascii(const char *str)
157 {
158  const char *p;
159 
160  for (p = str; *p; p++)
161  {
162  if (IS_HIGHBIT_SET(*p))
163  return false;
164  }
165  return true;
166 }
167 
168 static void
170 {
171  px_memset(p, 0, VARSIZE(p));
172  pfree(p);
173 }
174 
175 /*
176  * expect-* arguments storage
177  */
179 {
180  int debug;
181  int expect;
183  int s2k_mode;
191 };
192 
193 static void
194 fill_expect(struct debug_expect * ex, int text_mode)
195 {
196  ex->debug = 0;
197  ex->expect = 0;
198  ex->cipher_algo = -1;
199  ex->s2k_mode = -1;
200  ex->s2k_count = -1;
201  ex->s2k_cipher_algo = -1;
202  ex->s2k_digest_algo = -1;
203  ex->compress_algo = -1;
204  ex->use_sess_key = -1;
205  ex->disable_mdc = -1;
206  ex->unicode_mode = -1;
207 }
208 
209 #define EX_MSG(arg) \
210  ereport(NOTICE, (errmsg( \
211  "pgp_decrypt: unexpected %s: expected %d got %d", \
212  CppAsString(arg), ex->arg, ctx->arg)))
213 
214 #define EX_CHECK(arg) do { \
215  if (ex->arg >= 0 && ex->arg != ctx->arg) EX_MSG(arg); \
216  } while (0)
217 
218 static void
220 {
221  EX_CHECK(cipher_algo);
222  EX_CHECK(s2k_mode);
223  EX_CHECK(s2k_count);
224  EX_CHECK(s2k_digest_algo);
225  EX_CHECK(use_sess_key);
226  if (ctx->use_sess_key)
227  EX_CHECK(s2k_cipher_algo);
228  EX_CHECK(disable_mdc);
229  EX_CHECK(compress_algo);
230  EX_CHECK(unicode_mode);
231 }
232 
233 static void
234 show_debug(const char *msg)
235 {
236  ereport(NOTICE, (errmsg("dbg: %s", msg)));
237 }
238 
239 static int
240 set_arg(PGP_Context *ctx, char *key, char *val,
241  struct debug_expect * ex)
242 {
243  int res = 0;
244 
245  if (strcmp(key, "cipher-algo") == 0)
246  res = pgp_set_cipher_algo(ctx, val);
247  else if (strcmp(key, "disable-mdc") == 0)
248  res = pgp_disable_mdc(ctx, atoi(val));
249  else if (strcmp(key, "sess-key") == 0)
250  res = pgp_set_sess_key(ctx, atoi(val));
251  else if (strcmp(key, "s2k-mode") == 0)
252  res = pgp_set_s2k_mode(ctx, atoi(val));
253  else if (strcmp(key, "s2k-count") == 0)
254  res = pgp_set_s2k_count(ctx, atoi(val));
255  else if (strcmp(key, "s2k-digest-algo") == 0)
256  res = pgp_set_s2k_digest_algo(ctx, val);
257  else if (strcmp(key, "s2k-cipher-algo") == 0)
258  res = pgp_set_s2k_cipher_algo(ctx, val);
259  else if (strcmp(key, "compress-algo") == 0)
260  res = pgp_set_compress_algo(ctx, atoi(val));
261  else if (strcmp(key, "compress-level") == 0)
262  res = pgp_set_compress_level(ctx, atoi(val));
263  else if (strcmp(key, "convert-crlf") == 0)
264  res = pgp_set_convert_crlf(ctx, atoi(val));
265  else if (strcmp(key, "unicode-mode") == 0)
266  res = pgp_set_unicode_mode(ctx, atoi(val));
267 
268  /*
269  * The remaining options are for debugging/testing and are therefore not
270  * documented in the user-facing docs.
271  */
272  else if (ex != NULL && strcmp(key, "debug") == 0)
273  ex->debug = atoi(val);
274  else if (ex != NULL && strcmp(key, "expect-cipher-algo") == 0)
275  {
276  ex->expect = 1;
277  ex->cipher_algo = pgp_get_cipher_code(val);
278  }
279  else if (ex != NULL && strcmp(key, "expect-disable-mdc") == 0)
280  {
281  ex->expect = 1;
282  ex->disable_mdc = atoi(val);
283  }
284  else if (ex != NULL && strcmp(key, "expect-sess-key") == 0)
285  {
286  ex->expect = 1;
287  ex->use_sess_key = atoi(val);
288  }
289  else if (ex != NULL && strcmp(key, "expect-s2k-mode") == 0)
290  {
291  ex->expect = 1;
292  ex->s2k_mode = atoi(val);
293  }
294  else if (ex != NULL && strcmp(key, "expect-s2k-count") == 0)
295  {
296  ex->expect = 1;
297  ex->s2k_count = atoi(val);
298  }
299  else if (ex != NULL && strcmp(key, "expect-s2k-digest-algo") == 0)
300  {
301  ex->expect = 1;
303  }
304  else if (ex != NULL && strcmp(key, "expect-s2k-cipher-algo") == 0)
305  {
306  ex->expect = 1;
308  }
309  else if (ex != NULL && strcmp(key, "expect-compress-algo") == 0)
310  {
311  ex->expect = 1;
312  ex->compress_algo = atoi(val);
313  }
314  else if (ex != NULL && strcmp(key, "expect-unicode-mode") == 0)
315  {
316  ex->expect = 1;
317  ex->unicode_mode = atoi(val);
318  }
319  else
320  res = PXE_ARGUMENT_ERROR;
321 
322  return res;
323 }
324 
325 /*
326  * Find next word. Handle ',' and '=' as words. Skip whitespace.
327  * Put word info into res_p, res_len.
328  * Returns ptr to next word.
329  */
330 static char *
331 getword(char *p, char **res_p, int *res_len)
332 {
333  /* whitespace at start */
334  while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
335  p++;
336 
337  /* word data */
338  *res_p = p;
339  if (*p == '=' || *p == ',')
340  p++;
341  else
342  while (*p && !(*p == ' ' || *p == '\t' || *p == '\n'
343  || *p == '=' || *p == ','))
344  p++;
345 
346  /* word end */
347  *res_len = p - *res_p;
348 
349  /* whitespace at end */
350  while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
351  p++;
352 
353  return p;
354 }
355 
356 /*
357  * Convert to lowercase asciiz string.
358  */
359 static char *
360 downcase_convert(const uint8 *s, int len)
361 {
362  int c,
363  i;
364  char *res = palloc(len + 1);
365 
366  for (i = 0; i < len; i++)
367  {
368  c = s[i];
369  if (c >= 'A' && c <= 'Z')
370  c += 'a' - 'A';
371  res[i] = c;
372  }
373  res[len] = 0;
374  return res;
375 }
376 
377 static int
378 parse_args(PGP_Context *ctx, uint8 *args, int arg_len,
379  struct debug_expect * ex)
380 {
381  char *str = downcase_convert(args, arg_len);
382  char *key,
383  *val;
384  int key_len,
385  val_len;
386  int res = 0;
387  char *p = str;
388 
389  while (*p)
390  {
391  res = PXE_ARGUMENT_ERROR;
392  p = getword(p, &key, &key_len);
393  if (*p++ != '=')
394  break;
395  p = getword(p, &val, &val_len);
396  if (*p == '\0')
397  ;
398  else if (*p++ != ',')
399  break;
400 
401  if (*key == 0 || *val == 0 || val_len == 0)
402  break;
403 
404  key[key_len] = 0;
405  val[val_len] = 0;
406 
407  res = set_arg(ctx, key, val, ex);
408  if (res < 0)
409  break;
410  }
411  pfree(str);
412  return res;
413 }
414 
415 static MBuf *
417 {
418  return mbuf_create_from_data((uint8 *) VARDATA(data),
419  VARSIZE(data) - VARHDRSZ);
420 }
421 
422 static void
423 init_work(PGP_Context **ctx_p, int is_text,
424  text *args, struct debug_expect * ex)
425 {
426  int err = pgp_init(ctx_p);
427 
428  fill_expect(ex, is_text);
429 
430  if (err == 0 && args != NULL)
431  err = parse_args(*ctx_p, (uint8 *) VARDATA(args),
432  VARSIZE(args) - VARHDRSZ, ex);
433 
434  if (err)
435  {
436  ereport(ERROR,
437  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
438  errmsg("%s", px_strerror(err))));
439  }
440 
441  if (ex->debug)
443 
444  pgp_set_text_mode(*ctx_p, is_text);
445 }
446 
447 static bytea *
448 encrypt_internal(int is_pubenc, int is_text,
449  text *data, text *key, text *args)
450 {
451  MBuf *src,
452  *dst;
453  uint8 tmp[VARHDRSZ];
454  uint8 *restmp;
455  bytea *res;
456  int res_len;
457  PGP_Context *ctx;
458  int err;
459  struct debug_expect ex;
460  text *tmp_data = NULL;
461 
462  /*
463  * Add data and key info RNG.
464  */
465  add_entropy(data, key, NULL);
466 
467  init_work(&ctx, is_text, args, &ex);
468 
469  if (is_text && pgp_get_unicode_mode(ctx))
470  {
471  tmp_data = convert_to_utf8(data);
472  if (tmp_data == data)
473  tmp_data = NULL;
474  else
475  data = tmp_data;
476  }
477 
478  src = create_mbuf_from_vardata(data);
479  dst = mbuf_create(VARSIZE(data) + 128);
480 
481  /*
482  * reserve room for header
483  */
484  mbuf_append(dst, tmp, VARHDRSZ);
485 
486  /*
487  * set key
488  */
489  if (is_pubenc)
490  {
491  MBuf *kbuf = create_mbuf_from_vardata(key);
492 
493  err = pgp_set_pubkey(ctx, kbuf,
494  NULL, 0, 0);
495  mbuf_free(kbuf);
496  }
497  else
498  err = pgp_set_symkey(ctx, (uint8 *) VARDATA(key),
499  VARSIZE(key) - VARHDRSZ);
500 
501  /*
502  * encrypt
503  */
504  if (err >= 0)
505  err = pgp_encrypt(ctx, src, dst);
506 
507  /*
508  * check for error
509  */
510  if (err)
511  {
512  if (ex.debug)
514  if (tmp_data)
515  clear_and_pfree(tmp_data);
516  pgp_free(ctx);
517  mbuf_free(src);
518  mbuf_free(dst);
519  ereport(ERROR,
520  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
521  errmsg("%s", px_strerror(err))));
522  }
523 
524  /* res_len includes VARHDRSZ */
525  res_len = mbuf_steal_data(dst, &restmp);
526  res = (bytea *) restmp;
527  SET_VARSIZE(res, res_len);
528 
529  if (tmp_data)
530  clear_and_pfree(tmp_data);
531  pgp_free(ctx);
532  mbuf_free(src);
533  mbuf_free(dst);
534 
536 
537  return res;
538 }
539 
540 static bytea *
541 decrypt_internal(int is_pubenc, int need_text, text *data,
542  text *key, text *keypsw, text *args)
543 {
544  int err;
545  MBuf *src = NULL,
546  *dst = NULL;
547  uint8 tmp[VARHDRSZ];
548  uint8 *restmp;
549  bytea *res;
550  int res_len;
551  PGP_Context *ctx = NULL;
552  struct debug_expect ex;
553  int got_unicode = 0;
554 
555 
556  init_work(&ctx, need_text, args, &ex);
557 
558  src = mbuf_create_from_data((uint8 *) VARDATA(data),
559  VARSIZE(data) - VARHDRSZ);
560  dst = mbuf_create(VARSIZE(data) + 2048);
561 
562  /*
563  * reserve room for header
564  */
565  mbuf_append(dst, tmp, VARHDRSZ);
566 
567  /*
568  * set key
569  */
570  if (is_pubenc)
571  {
572  uint8 *psw = NULL;
573  int psw_len = 0;
574  MBuf *kbuf;
575 
576  if (keypsw)
577  {
578  psw = (uint8 *) VARDATA(keypsw);
579  psw_len = VARSIZE(keypsw) - VARHDRSZ;
580  }
581  kbuf = create_mbuf_from_vardata(key);
582  err = pgp_set_pubkey(ctx, kbuf, psw, psw_len, 1);
583  mbuf_free(kbuf);
584  }
585  else
586  err = pgp_set_symkey(ctx, (uint8 *) VARDATA(key),
587  VARSIZE(key) - VARHDRSZ);
588 
589  /* decrypt */
590  if (err >= 0)
591  {
592  err = pgp_decrypt(ctx, src, dst);
593 
594  if (ex.expect)
595  check_expect(ctx, &ex);
596 
597  /* remember the setting */
598  got_unicode = pgp_get_unicode_mode(ctx);
599  }
600 
601  mbuf_free(src);
602  pgp_free(ctx);
603 
604  if (err)
605  {
607  mbuf_free(dst);
608  ereport(ERROR,
609  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
610  errmsg("%s", px_strerror(err))));
611  }
612 
613  res_len = mbuf_steal_data(dst, &restmp);
614  mbuf_free(dst);
615 
616  /* res_len includes VARHDRSZ */
617  res = (bytea *) restmp;
618  SET_VARSIZE(res, res_len);
619 
620  if (need_text && got_unicode)
621  {
622  text *utf = convert_from_utf8(res);
623 
624  if (utf != res)
625  {
626  clear_and_pfree(res);
627  res = utf;
628  }
629  }
631 
632  /*
633  * add successful decryptions also into RNG
634  */
635  add_entropy(res, key, keypsw);
636 
637  return res;
638 }
639 
640 /*
641  * Wrappers for symmetric-key functions
642  */
643 Datum
645 {
646  bytea *data,
647  *key;
648  text *arg = NULL;
649  text *res;
650 
651  data = PG_GETARG_BYTEA_P(0);
652  key = PG_GETARG_BYTEA_P(1);
653  if (PG_NARGS() > 2)
654  arg = PG_GETARG_BYTEA_P(2);
655 
656  res = encrypt_internal(0, 0, data, key, arg);
657 
658  PG_FREE_IF_COPY(data, 0);
659  PG_FREE_IF_COPY(key, 1);
660  if (PG_NARGS() > 2)
661  PG_FREE_IF_COPY(arg, 2);
662  PG_RETURN_TEXT_P(res);
663 }
664 
665 Datum
667 {
668  bytea *data,
669  *key;
670  text *arg = NULL;
671  text *res;
672 
673  data = PG_GETARG_BYTEA_P(0);
674  key = PG_GETARG_BYTEA_P(1);
675  if (PG_NARGS() > 2)
676  arg = PG_GETARG_BYTEA_P(2);
677 
678  res = encrypt_internal(0, 1, data, key, arg);
679 
680  PG_FREE_IF_COPY(data, 0);
681  PG_FREE_IF_COPY(key, 1);
682  if (PG_NARGS() > 2)
683  PG_FREE_IF_COPY(arg, 2);
684  PG_RETURN_TEXT_P(res);
685 }
686 
687 
688 Datum
690 {
691  bytea *data,
692  *key;
693  text *arg = NULL;
694  text *res;
695 
696  data = PG_GETARG_BYTEA_P(0);
697  key = PG_GETARG_BYTEA_P(1);
698  if (PG_NARGS() > 2)
699  arg = PG_GETARG_BYTEA_P(2);
700 
701  res = decrypt_internal(0, 0, data, key, NULL, arg);
702 
703  PG_FREE_IF_COPY(data, 0);
704  PG_FREE_IF_COPY(key, 1);
705  if (PG_NARGS() > 2)
706  PG_FREE_IF_COPY(arg, 2);
707  PG_RETURN_TEXT_P(res);
708 }
709 
710 Datum
712 {
713  bytea *data,
714  *key;
715  text *arg = NULL;
716  text *res;
717 
718  data = PG_GETARG_BYTEA_P(0);
719  key = PG_GETARG_BYTEA_P(1);
720  if (PG_NARGS() > 2)
721  arg = PG_GETARG_BYTEA_P(2);
722 
723  res = decrypt_internal(0, 1, data, key, NULL, arg);
724 
725  PG_FREE_IF_COPY(data, 0);
726  PG_FREE_IF_COPY(key, 1);
727  if (PG_NARGS() > 2)
728  PG_FREE_IF_COPY(arg, 2);
729  PG_RETURN_TEXT_P(res);
730 }
731 
732 /*
733  * Wrappers for public-key functions
734  */
735 
736 Datum
738 {
739  bytea *data,
740  *key;
741  text *arg = NULL;
742  text *res;
743 
744  data = PG_GETARG_BYTEA_P(0);
745  key = PG_GETARG_BYTEA_P(1);
746  if (PG_NARGS() > 2)
747  arg = PG_GETARG_BYTEA_P(2);
748 
749  res = encrypt_internal(1, 0, data, key, arg);
750 
751  PG_FREE_IF_COPY(data, 0);
752  PG_FREE_IF_COPY(key, 1);
753  if (PG_NARGS() > 2)
754  PG_FREE_IF_COPY(arg, 2);
755  PG_RETURN_TEXT_P(res);
756 }
757 
758 Datum
760 {
761  bytea *data,
762  *key;
763  text *arg = NULL;
764  text *res;
765 
766  data = PG_GETARG_BYTEA_P(0);
767  key = PG_GETARG_BYTEA_P(1);
768  if (PG_NARGS() > 2)
769  arg = PG_GETARG_BYTEA_P(2);
770 
771  res = encrypt_internal(1, 1, data, key, arg);
772 
773  PG_FREE_IF_COPY(data, 0);
774  PG_FREE_IF_COPY(key, 1);
775  if (PG_NARGS() > 2)
776  PG_FREE_IF_COPY(arg, 2);
777  PG_RETURN_TEXT_P(res);
778 }
779 
780 
781 Datum
783 {
784  bytea *data,
785  *key;
786  text *psw = NULL,
787  *arg = NULL;
788  text *res;
789 
790  data = PG_GETARG_BYTEA_P(0);
791  key = PG_GETARG_BYTEA_P(1);
792  if (PG_NARGS() > 2)
793  psw = PG_GETARG_BYTEA_P(2);
794  if (PG_NARGS() > 3)
795  arg = PG_GETARG_BYTEA_P(3);
796 
797  res = decrypt_internal(1, 0, data, key, psw, arg);
798 
799  PG_FREE_IF_COPY(data, 0);
800  PG_FREE_IF_COPY(key, 1);
801  if (PG_NARGS() > 2)
802  PG_FREE_IF_COPY(psw, 2);
803  if (PG_NARGS() > 3)
804  PG_FREE_IF_COPY(arg, 3);
805  PG_RETURN_TEXT_P(res);
806 }
807 
808 Datum
810 {
811  bytea *data,
812  *key;
813  text *psw = NULL,
814  *arg = NULL;
815  text *res;
816 
817  data = PG_GETARG_BYTEA_P(0);
818  key = PG_GETARG_BYTEA_P(1);
819  if (PG_NARGS() > 2)
820  psw = PG_GETARG_BYTEA_P(2);
821  if (PG_NARGS() > 3)
822  arg = PG_GETARG_BYTEA_P(3);
823 
824  res = decrypt_internal(1, 1, data, key, psw, arg);
825 
826  PG_FREE_IF_COPY(data, 0);
827  PG_FREE_IF_COPY(key, 1);
828  if (PG_NARGS() > 2)
829  PG_FREE_IF_COPY(psw, 2);
830  if (PG_NARGS() > 3)
831  PG_FREE_IF_COPY(arg, 3);
832  PG_RETURN_TEXT_P(res);
833 }
834 
835 
836 /*
837  * Wrappers for PGP ascii armor
838  */
839 
840 /*
841  * Helper function for pgp_armor. Converts arrays of keys and values into
842  * plain C arrays, and checks that they don't contain invalid characters.
843  */
844 static int
846  char ***p_keys, char ***p_values)
847 {
848  int nkdims = ARR_NDIM(key_array);
849  int nvdims = ARR_NDIM(val_array);
850  char **keys,
851  **values;
852  Datum *key_datums,
853  *val_datums;
854  bool *key_nulls,
855  *val_nulls;
856  int key_count,
857  val_count;
858  int i;
859 
860  if (nkdims > 1 || nkdims != nvdims)
861  ereport(ERROR,
862  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
863  errmsg("wrong number of array subscripts")));
864  if (nkdims == 0)
865  return 0;
866 
867  deconstruct_array(key_array,
868  TEXTOID, -1, false, 'i',
869  &key_datums, &key_nulls, &key_count);
870 
871  deconstruct_array(val_array,
872  TEXTOID, -1, false, 'i',
873  &val_datums, &val_nulls, &val_count);
874 
875  if (key_count != val_count)
876  ereport(ERROR,
877  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
878  errmsg("mismatched array dimensions")));
879 
880  keys = (char **) palloc(sizeof(char *) * key_count);
881  values = (char **) palloc(sizeof(char *) * val_count);
882 
883  for (i = 0; i < key_count; i++)
884  {
885  char *v;
886 
887  /* Check that the key doesn't contain anything funny */
888  if (key_nulls[i])
889  ereport(ERROR,
890  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
891  errmsg("null value not allowed for header key")));
892 
893  v = TextDatumGetCString(key_datums[i]);
894 
895  if (!string_is_ascii(v))
896  ereport(ERROR,
897  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
898  errmsg("header key must not contain non-ASCII characters")));
899  if (strstr(v, ": "))
900  ereport(ERROR,
901  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
902  errmsg("header key must not contain \": \"")));
903  if (strchr(v, '\n'))
904  ereport(ERROR,
905  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
906  errmsg("header key must not contain newlines")));
907  keys[i] = v;
908 
909  /* And the same for the value */
910  if (val_nulls[i])
911  ereport(ERROR,
912  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
913  errmsg("null value not allowed for header value")));
914 
915  v = TextDatumGetCString(val_datums[i]);
916 
917  if (!string_is_ascii(v))
918  ereport(ERROR,
919  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
920  errmsg("header value must not contain non-ASCII characters")));
921  if (strchr(v, '\n'))
922  ereport(ERROR,
923  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
924  errmsg("header value must not contain newlines")));
925 
926  values[i] = v;
927  }
928 
929  *p_keys = keys;
930  *p_values = values;
931  return key_count;
932 }
933 
934 Datum
936 {
937  bytea *data;
938  text *res;
939  int data_len;
941  int num_headers;
942  char **keys = NULL,
943  **values = NULL;
944 
945  data = PG_GETARG_BYTEA_P(0);
946  data_len = VARSIZE(data) - VARHDRSZ;
947  if (PG_NARGS() == 3)
948  {
951  &keys, &values);
952  }
953  else if (PG_NARGS() == 1)
954  num_headers = 0;
955  else
956  elog(ERROR, "unexpected number of arguments %d", PG_NARGS());
957 
958  initStringInfo(&buf);
959 
960  pgp_armor_encode((uint8 *) VARDATA(data), data_len, &buf,
961  num_headers, keys, values);
962 
963  res = palloc(VARHDRSZ + buf.len);
964  SET_VARSIZE(res, VARHDRSZ + buf.len);
965  memcpy(VARDATA(res), buf.data, buf.len);
966  pfree(buf.data);
967 
968  PG_FREE_IF_COPY(data, 0);
969  PG_RETURN_TEXT_P(res);
970 }
971 
972 Datum
974 {
975  text *data;
976  bytea *res;
977  int data_len;
978  int ret;
980 
981  data = PG_GETARG_TEXT_P(0);
982  data_len = VARSIZE(data) - VARHDRSZ;
983 
984  initStringInfo(&buf);
985 
986  ret = pgp_armor_decode((uint8 *) VARDATA(data), data_len, &buf);
987  if (ret < 0)
988  ereport(ERROR,
989  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
990  errmsg("%s", px_strerror(ret))));
991  res = palloc(VARHDRSZ + buf.len);
992  SET_VARSIZE(res, VARHDRSZ + buf.len);
993  memcpy(VARDATA(res), buf.data, buf.len);
994  pfree(buf.data);
995 
996  PG_FREE_IF_COPY(data, 0);
997  PG_RETURN_TEXT_P(res);
998 }
999 
1000 /* cross-call state for pgp_armor_headers */
1001 typedef struct
1002 {
1004  char **keys;
1005  char **values;
1007 
1008 Datum
1010 {
1011  FuncCallContext *funcctx;
1013  char *utf8key;
1014  char *utf8val;
1015  HeapTuple tuple;
1016  TupleDesc tupdesc;
1017  AttInMetadata *attinmeta;
1018 
1019  if (SRF_IS_FIRSTCALL())
1020  {
1021  text *data = PG_GETARG_TEXT_PP(0);
1022  int res;
1023  MemoryContext oldcontext;
1024 
1025  funcctx = SRF_FIRSTCALL_INIT();
1026 
1027  /* we need the state allocated in the multi call context */
1028  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1029 
1030  /* Build a tuple descriptor for our result type */
1031  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1032  elog(ERROR, "return type must be a row type");
1033 
1034  attinmeta = TupleDescGetAttInMetadata(tupdesc);
1035  funcctx->attinmeta = attinmeta;
1036 
1038 
1040  VARSIZE_ANY_EXHDR(data),
1041  &state->nheaders, &state->keys,
1042  &state->values);
1043  if (res < 0)
1044  ereport(ERROR,
1045  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
1046  errmsg("%s", px_strerror(res))));
1047 
1048  MemoryContextSwitchTo(oldcontext);
1049  funcctx->user_fctx = state;
1050  }
1051 
1052  funcctx = SRF_PERCALL_SETUP();
1053  state = (pgp_armor_headers_state *) funcctx->user_fctx;
1054 
1055  if (funcctx->call_cntr >= state->nheaders)
1056  SRF_RETURN_DONE(funcctx);
1057  else
1058  {
1059  char *values[2];
1060 
1061  /* we assume that the keys (and values) are in UTF-8. */
1062  utf8key = state->keys[funcctx->call_cntr];
1063  utf8val = state->values[funcctx->call_cntr];
1064 
1065  values[0] = pg_any_to_server(utf8key, strlen(utf8key), PG_UTF8);
1066  values[1] = pg_any_to_server(utf8val, strlen(utf8val), PG_UTF8);
1067 
1068  /* build a tuple */
1069  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
1070  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
1071  }
1072 }
1073 
1074 
1075 
1076 /*
1077  * Wrappers for PGP key id
1078  */
1079 
1080 Datum
1082 {
1083  bytea *data;
1084  text *res;
1085  int res_len;
1086  MBuf *buf;
1087 
1088  data = PG_GETARG_BYTEA_P(0);
1089  buf = create_mbuf_from_vardata(data);
1090  res = palloc(VARHDRSZ + 17);
1091 
1092  res_len = pgp_get_keyid(buf, VARDATA(res));
1093  mbuf_free(buf);
1094  if (res_len < 0)
1095  ereport(ERROR,
1096  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
1097  errmsg("%s", px_strerror(res_len))));
1098  SET_VARSIZE(res, VARHDRSZ + res_len);
1099 
1100  PG_FREE_IF_COPY(data, 0);
1101  PG_RETURN_TEXT_P(res);
1102 }
uint64 call_cntr
Definition: funcapi.h:65
Datum pgp_key_id_w(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:1081
Datum pg_armor(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:935
static void add_block_entropy(PX_MD *md, text *data)
Definition: pgp-pgsql.c:68
PG_FUNCTION_INFO_V1(pgp_sym_encrypt_bytea)
MBuf * mbuf_create(int len)
Definition: mbuf.c:119
int disable_mdc
Definition: pgp-pgsql.c:189
static char * downcase_convert(const uint8 *s, int len)
Definition: pgp-pgsql.c:360
#define PXE_ARGUMENT_ERROR
Definition: px.h:76
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:212
int pgp_get_cipher_code(const char *name)
Definition: pgp.c:116
#define VARDATA_ANY(PTR)
Definition: postgres.h:349
#define VARDATA(PTR)
Definition: postgres.h:305
int pgp_get_unicode_mode(PGP_Context *ctx)
Definition: pgp.c:352
int pgp_set_s2k_cipher_algo(PGP_Context *ctx, const char *name)
Definition: pgp.c:330
int pgp_set_pubkey(PGP_Context *ctx, MBuf *keypkt, const uint8 *key, int key_len, int pubtype)
Definition: pgp-pubkey.c:566
Datum pgp_pub_encrypt_text(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:759
Datum pgp_sym_encrypt_bytea(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:644
int pgp_set_s2k_digest_algo(PGP_Context *ctx, const char *name)
Definition: pgp.c:341
int unicode_mode
Definition: pgp-pgsql.c:190
int pgp_set_s2k_mode(PGP_Context *ctx, int mode)
Definition: pgp.c:256
#define TEXTOID
Definition: pg_type.h:324
#define VARSIZE(PTR)
Definition: postgres.h:306
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
static void clear_and_pfree(text *p)
Definition: pgp-pgsql.c:169
Datum pgp_pub_decrypt_text(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:809
#define VARHDRSZ
Definition: c.h:440
#define px_md_update(md, data, dlen)
Definition: px.h:215
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned char uint8
Definition: c.h:263
static text * convert_charset(text *src, int cset_from, int cset_to)
Definition: pgp-pgsql.c:127
int errcode(int sqlerrcode)
Definition: elog.c:575
int mbuf_free(MBuf *mbuf)
Definition: mbuf.c:68
Datum pg_dearmor(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:973
int pgp_get_keyid(MBuf *pgp_data, char *dst)
Definition: pgp-info.c:112
int pgp_get_digest_code(const char *name)
Definition: pgp.c:105
unsigned char * pg_do_encoding_conversion(unsigned char *src, int len, int src_encoding, int dest_encoding)
Definition: mbutils.c:337
#define px_md_finish(md, buf)
Definition: px.h:216
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
static void fill_expect(struct debug_expect *ex, int text_mode)
Definition: pgp-pgsql.c:194
#define px_md_reset(md)
Definition: px.h:214
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
Definition: execTuples.c:1118
int s2k_digest_algo
Definition: pgp-pgsql.c:186
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:270
Datum pgp_pub_decrypt_bytea(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:782
int use_sess_key
Definition: pgp.h:148
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
int pgp_set_sess_key(PGP_Context *ctx, int use)
Definition: pgp.c:242
#define PG_GETARG_BYTEA_P(n)
Definition: fmgr.h:267
static void check_expect(PGP_Context *ctx, struct debug_expect *ex)
Definition: pgp-pgsql.c:219
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
void pfree(void *pointer)
Definition: mcxt.c:995
#define IS_HIGHBIT_SET(ch)
Definition: c.h:949
#define ERROR
Definition: elog.h:43
static text * convert_from_utf8(text *src)
Definition: pgp-pgsql.c:144
int s2k_cipher_algo
Definition: pgp-pgsql.c:185
Datum pgp_pub_encrypt_bytea(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:737
Definition: px.h:115
int cipher_algo
Definition: pgp-pgsql.c:182
int pgp_set_compress_level(PGP_Context *ctx, int level)
Definition: pgp.c:301
int pgp_armor_decode(const uint8 *src, int len, StringInfo dst)
Definition: pgp-armor.c:314
Datum pgp_sym_encrypt_text(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:666
void pgp_armor_encode(const uint8 *src, unsigned len, StringInfo dst, int num_headers, char **keys, char **values)
Definition: pgp-armor.c:207
char * c
int px_get_random_bytes(uint8 *dst, unsigned count)
Definition: internal.c:675
static char * buf
Definition: pg_test_fsync.c:65
Datum pgp_sym_decrypt_text(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:711
AttInMetadata * attinmeta
Definition: funcapi.h:99
int compress_algo
Definition: pgp-pgsql.c:187
int pgp_set_symkey(PGP_Context *ctx, const uint8 *key, int len)
Definition: pgp.c:365
void px_set_debug_handler(void(*handler)(const char *))
Definition: px.c:126
#define ereport(elevel, rest)
Definition: elog.h:122
static bool string_is_ascii(const char *str)
Definition: pgp-pgsql.c:156
int pgp_set_convert_crlf(PGP_Context *ctx, int doit)
Definition: pgp.c:249
int px_add_entropy(const uint8 *data, unsigned count)
Definition: internal.c:683
int pgp_init(PGP_Context **ctx_p)
Definition: pgp.c:200
const char * px_strerror(int err)
Definition: px.c:94
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
int mbuf_append(MBuf *dst, const uint8 *buf, int len)
Definition: mbuf.c:102
#define px_md_free(md)
Definition: px.h:217
#define TextDatumGetCString(d)
Definition: builtins.h:807
uintptr_t Datum
Definition: postgres.h:374
int GetDatabaseEncoding(void)
Definition: mbutils.c:1015
int pgp_set_unicode_mode(PGP_Context *ctx, int mode)
Definition: pgp.c:358
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
Definition: execTuples.c:1071
Datum pgp_armor_headers(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:1009
int pgp_decrypt(PGP_Context *ctx, MBuf *msrc, MBuf *mdst)
Definition: pgp-decrypt.c:1090
#define EX_CHECK(arg)
Definition: pgp-pgsql.c:214
int pgp_extract_armor_headers(const uint8 *src, unsigned len, int *nheaders, char ***keys, char ***values)
Definition: pgp-armor.c:390
int pgp_set_cipher_algo(PGP_Context *ctx, const char *name)
Definition: pgp.c:319
#define NOTICE
Definition: elog.h:37
int pgp_disable_mdc(PGP_Context *ctx, int disable)
Definition: pgp.c:235
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
text * cstring_to_text(const char *s)
Definition: varlena.c:150
#define NULL
Definition: c.h:226
int pgp_encrypt(PGP_Context *ctx, MBuf *src, MBuf *dst)
Definition: pgp-encrypt.c:603
Definition: regguts.h:313
static char * getword(char *p, char **res_p, int *res_len)
Definition: pgp-pgsql.c:331
static void show_debug(const char *msg)
Definition: pgp-pgsql.c:234
static void add_entropy(text *data1, text *data2, text *data3)
Definition: pgp-pgsql.c:86
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
Datum pgp_sym_decrypt_bytea(PG_FUNCTION_ARGS)
Definition: pgp-pgsql.c:689
Definition: mbuf.c:39
static int parse_args(PGP_Context *ctx, uint8 *args, int arg_len, struct debug_expect *ex)
Definition: pgp-pgsql.c:378
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:216
#define PG_NARGS()
Definition: fmgr.h:160
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
#define ARR_NDIM(a)
Definition: array.h:271
static int parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array, char ***p_keys, char ***p_values)
Definition: pgp-pgsql.c:845
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
int pgp_set_s2k_count(PGP_Context *ctx, int count)
Definition: pgp.c:275
static Datum values[MAXATTR]
Definition: bootstrap.c:160
void * user_fctx
Definition: funcapi.h:90
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:342
void * palloc(Size size)
Definition: mcxt.c:894
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
MBuf * mbuf_create_from_data(uint8 *data, int len)
Definition: mbuf.c:139
static bytea * decrypt_internal(int is_pubenc, int need_text, text *data, text *key, text *keypsw, text *args)
Definition: pgp-pgsql.c:541
int i
int pgp_set_text_mode(PGP_Context *ctx, int mode)
Definition: pgp.c:312
void * arg
Definition: c.h:434
#define PG_FUNCTION_ARGS
Definition: fmgr.h:150
static MBuf * create_mbuf_from_vardata(text *data)
Definition: pgp-pgsql.c:416
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
static bytea * encrypt_internal(int is_pubenc, int is_text, text *data, text *key, text *args)
Definition: pgp-pgsql.c:448
#define elog
Definition: elog.h:218
static int set_arg(PGP_Context *ctx, char *key, char *val, struct debug_expect *ex)
Definition: pgp-pgsql.c:240
int pgp_free(PGP_Context *ctx)
Definition: pgp.c:225
static text * convert_to_utf8(text *src)
Definition: pgp-pgsql.c:150
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:572
int px_find_digest(const char *name, PX_MD **res)
Definition: internal.c:579
long val
Definition: informix.c:689
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:106
int pgp_set_compress_algo(PGP_Context *ctx, int algo)
Definition: pgp.c:286
int use_sess_key
Definition: pgp-pgsql.c:188
int mbuf_steal_data(MBuf *mbuf, uint8 **data_p)
Definition: mbuf.c:177
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
static void init_work(PGP_Context **ctx_p, int is_text, text *args, struct debug_expect *ex)
Definition: pgp-pgsql.c:423
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287