At update of non-LP_NORMAL TID, fail instead of corrupting page header.
[pgsql.git] / contrib / pgcrypto / pgp-pgsql.c
blob7c9f4c7b39b88ea812bc32331585513ee995b1ce
1 /*
2 * pgp-pgsql.c
3 * PostgreSQL wrappers for pgp.
5 * Copyright (c) 2005 Marko Kreen
6 * All rights reserved.
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.
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.
29 * contrib/pgcrypto/pgp-pgsql.c
32 #include "postgres.h"
34 #include "catalog/pg_type.h"
35 #include "common/string.h"
36 #include "funcapi.h"
37 #include "lib/stringinfo.h"
38 #include "mb/pg_wchar.h"
39 #include "mbuf.h"
40 #include "pgp.h"
41 #include "px.h"
42 #include "utils/array.h"
43 #include "utils/builtins.h"
46 * public functions
48 PG_FUNCTION_INFO_V1(pgp_sym_encrypt_bytea);
49 PG_FUNCTION_INFO_V1(pgp_sym_encrypt_text);
50 PG_FUNCTION_INFO_V1(pgp_sym_decrypt_bytea);
51 PG_FUNCTION_INFO_V1(pgp_sym_decrypt_text);
53 PG_FUNCTION_INFO_V1(pgp_pub_encrypt_bytea);
54 PG_FUNCTION_INFO_V1(pgp_pub_encrypt_text);
55 PG_FUNCTION_INFO_V1(pgp_pub_decrypt_bytea);
56 PG_FUNCTION_INFO_V1(pgp_pub_decrypt_text);
58 PG_FUNCTION_INFO_V1(pgp_key_id_w);
60 PG_FUNCTION_INFO_V1(pg_armor);
61 PG_FUNCTION_INFO_V1(pg_dearmor);
62 PG_FUNCTION_INFO_V1(pgp_armor_headers);
65 * returns src in case of no conversion or error
67 static text *
68 convert_charset(text *src, int cset_from, int cset_to)
70 int src_len = VARSIZE_ANY_EXHDR(src);
71 unsigned char *dst;
72 unsigned char *csrc = (unsigned char *) VARDATA_ANY(src);
73 text *res;
75 dst = pg_do_encoding_conversion(csrc, src_len, cset_from, cset_to);
76 if (dst == csrc)
77 return src;
79 res = cstring_to_text((char *) dst);
80 pfree(dst);
81 return res;
84 static text *
85 convert_from_utf8(text *src)
87 return convert_charset(src, PG_UTF8, GetDatabaseEncoding());
90 static text *
91 convert_to_utf8(text *src)
93 return convert_charset(src, GetDatabaseEncoding(), PG_UTF8);
96 static void
97 clear_and_pfree(text *p)
99 px_memset(p, 0, VARSIZE_ANY(p));
100 pfree(p);
104 * expect-* arguments storage
106 struct debug_expect
108 int debug;
109 int expect;
110 int cipher_algo;
111 int s2k_mode;
112 int s2k_count;
113 int s2k_cipher_algo;
114 int s2k_digest_algo;
115 int compress_algo;
116 int use_sess_key;
117 int disable_mdc;
118 int unicode_mode;
121 static void
122 fill_expect(struct debug_expect *ex, int text_mode)
124 ex->debug = 0;
125 ex->expect = 0;
126 ex->cipher_algo = -1;
127 ex->s2k_mode = -1;
128 ex->s2k_count = -1;
129 ex->s2k_cipher_algo = -1;
130 ex->s2k_digest_algo = -1;
131 ex->compress_algo = -1;
132 ex->use_sess_key = -1;
133 ex->disable_mdc = -1;
134 ex->unicode_mode = -1;
137 #define EX_MSG(arg) \
138 ereport(NOTICE, (errmsg( \
139 "pgp_decrypt: unexpected %s: expected %d got %d", \
140 CppAsString(arg), ex->arg, ctx->arg)))
142 #define EX_CHECK(arg) do { \
143 if (ex->arg >= 0 && ex->arg != ctx->arg) EX_MSG(arg); \
144 } while (0)
146 static void
147 check_expect(PGP_Context *ctx, struct debug_expect *ex)
149 EX_CHECK(cipher_algo);
150 EX_CHECK(s2k_mode);
151 EX_CHECK(s2k_count);
152 EX_CHECK(s2k_digest_algo);
153 EX_CHECK(use_sess_key);
154 if (ctx->use_sess_key)
155 EX_CHECK(s2k_cipher_algo);
156 EX_CHECK(disable_mdc);
157 EX_CHECK(compress_algo);
158 EX_CHECK(unicode_mode);
161 static void
162 show_debug(const char *msg)
164 ereport(NOTICE, (errmsg("dbg: %s", msg)));
167 static int
168 set_arg(PGP_Context *ctx, char *key, char *val,
169 struct debug_expect *ex)
171 int res = 0;
173 if (strcmp(key, "cipher-algo") == 0)
174 res = pgp_set_cipher_algo(ctx, val);
175 else if (strcmp(key, "disable-mdc") == 0)
176 res = pgp_disable_mdc(ctx, atoi(val));
177 else if (strcmp(key, "sess-key") == 0)
178 res = pgp_set_sess_key(ctx, atoi(val));
179 else if (strcmp(key, "s2k-mode") == 0)
180 res = pgp_set_s2k_mode(ctx, atoi(val));
181 else if (strcmp(key, "s2k-count") == 0)
182 res = pgp_set_s2k_count(ctx, atoi(val));
183 else if (strcmp(key, "s2k-digest-algo") == 0)
184 res = pgp_set_s2k_digest_algo(ctx, val);
185 else if (strcmp(key, "s2k-cipher-algo") == 0)
186 res = pgp_set_s2k_cipher_algo(ctx, val);
187 else if (strcmp(key, "compress-algo") == 0)
188 res = pgp_set_compress_algo(ctx, atoi(val));
189 else if (strcmp(key, "compress-level") == 0)
190 res = pgp_set_compress_level(ctx, atoi(val));
191 else if (strcmp(key, "convert-crlf") == 0)
192 res = pgp_set_convert_crlf(ctx, atoi(val));
193 else if (strcmp(key, "unicode-mode") == 0)
194 res = pgp_set_unicode_mode(ctx, atoi(val));
197 * The remaining options are for debugging/testing and are therefore not
198 * documented in the user-facing docs.
200 else if (ex != NULL && strcmp(key, "debug") == 0)
201 ex->debug = atoi(val);
202 else if (ex != NULL && strcmp(key, "expect-cipher-algo") == 0)
204 ex->expect = 1;
205 ex->cipher_algo = pgp_get_cipher_code(val);
207 else if (ex != NULL && strcmp(key, "expect-disable-mdc") == 0)
209 ex->expect = 1;
210 ex->disable_mdc = atoi(val);
212 else if (ex != NULL && strcmp(key, "expect-sess-key") == 0)
214 ex->expect = 1;
215 ex->use_sess_key = atoi(val);
217 else if (ex != NULL && strcmp(key, "expect-s2k-mode") == 0)
219 ex->expect = 1;
220 ex->s2k_mode = atoi(val);
222 else if (ex != NULL && strcmp(key, "expect-s2k-count") == 0)
224 ex->expect = 1;
225 ex->s2k_count = atoi(val);
227 else if (ex != NULL && strcmp(key, "expect-s2k-digest-algo") == 0)
229 ex->expect = 1;
230 ex->s2k_digest_algo = pgp_get_digest_code(val);
232 else if (ex != NULL && strcmp(key, "expect-s2k-cipher-algo") == 0)
234 ex->expect = 1;
235 ex->s2k_cipher_algo = pgp_get_cipher_code(val);
237 else if (ex != NULL && strcmp(key, "expect-compress-algo") == 0)
239 ex->expect = 1;
240 ex->compress_algo = atoi(val);
242 else if (ex != NULL && strcmp(key, "expect-unicode-mode") == 0)
244 ex->expect = 1;
245 ex->unicode_mode = atoi(val);
247 else
248 res = PXE_ARGUMENT_ERROR;
250 return res;
254 * Find next word. Handle ',' and '=' as words. Skip whitespace.
255 * Put word info into res_p, res_len.
256 * Returns ptr to next word.
258 static char *
259 getword(char *p, char **res_p, int *res_len)
261 /* whitespace at start */
262 while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
263 p++;
265 /* word data */
266 *res_p = p;
267 if (*p == '=' || *p == ',')
268 p++;
269 else
270 while (*p && !(*p == ' ' || *p == '\t' || *p == '\n'
271 || *p == '=' || *p == ','))
272 p++;
274 /* word end */
275 *res_len = p - *res_p;
277 /* whitespace at end */
278 while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
279 p++;
281 return p;
285 * Convert to lowercase asciiz string.
287 static char *
288 downcase_convert(const uint8 *s, int len)
290 int c,
292 char *res = palloc(len + 1);
294 for (i = 0; i < len; i++)
296 c = s[i];
297 if (c >= 'A' && c <= 'Z')
298 c += 'a' - 'A';
299 res[i] = c;
301 res[len] = 0;
302 return res;
305 static int
306 parse_args(PGP_Context *ctx, uint8 *args, int arg_len,
307 struct debug_expect *ex)
309 char *str = downcase_convert(args, arg_len);
310 char *key,
311 *val;
312 int key_len,
313 val_len;
314 int res = 0;
315 char *p = str;
317 while (*p)
319 res = PXE_ARGUMENT_ERROR;
320 p = getword(p, &key, &key_len);
321 if (*p++ != '=')
322 break;
323 p = getword(p, &val, &val_len);
324 if (*p == '\0')
326 else if (*p++ != ',')
327 break;
329 if (*key == 0 || *val == 0 || val_len == 0)
330 break;
332 key[key_len] = 0;
333 val[val_len] = 0;
335 res = set_arg(ctx, key, val, ex);
336 if (res < 0)
337 break;
339 pfree(str);
340 return res;
343 static MBuf *
344 create_mbuf_from_vardata(text *data)
346 return mbuf_create_from_data((uint8 *) VARDATA_ANY(data),
347 VARSIZE_ANY_EXHDR(data));
350 static void
351 init_work(PGP_Context **ctx_p, int is_text,
352 text *args, struct debug_expect *ex)
354 int err = pgp_init(ctx_p);
356 fill_expect(ex, is_text);
358 if (err == 0 && args != NULL)
359 err = parse_args(*ctx_p, (uint8 *) VARDATA_ANY(args),
360 VARSIZE_ANY_EXHDR(args), ex);
362 if (err)
363 px_THROW_ERROR(err);
365 if (ex->debug)
366 px_set_debug_handler(show_debug);
368 pgp_set_text_mode(*ctx_p, is_text);
371 static bytea *
372 encrypt_internal(int is_pubenc, int is_text,
373 text *data, text *key, text *args)
375 MBuf *src,
376 *dst;
377 uint8 tmp[VARHDRSZ];
378 uint8 *restmp;
379 bytea *res;
380 int res_len;
381 PGP_Context *ctx;
382 int err;
383 struct debug_expect ex;
384 text *tmp_data = NULL;
386 init_work(&ctx, is_text, args, &ex);
388 if (is_text && pgp_get_unicode_mode(ctx))
390 tmp_data = convert_to_utf8(data);
391 if (tmp_data == data)
392 tmp_data = NULL;
393 else
394 data = tmp_data;
397 src = create_mbuf_from_vardata(data);
398 dst = mbuf_create(VARSIZE_ANY(data) + 128);
401 * reserve room for header
403 mbuf_append(dst, tmp, VARHDRSZ);
406 * set key
408 if (is_pubenc)
410 MBuf *kbuf = create_mbuf_from_vardata(key);
412 err = pgp_set_pubkey(ctx, kbuf,
413 NULL, 0, 0);
414 mbuf_free(kbuf);
416 else
417 err = pgp_set_symkey(ctx, (uint8 *) VARDATA_ANY(key),
418 VARSIZE_ANY_EXHDR(key));
421 * encrypt
423 if (err >= 0)
424 err = pgp_encrypt(ctx, src, dst);
427 * check for error
429 if (err)
431 if (ex.debug)
432 px_set_debug_handler(NULL);
433 if (tmp_data)
434 clear_and_pfree(tmp_data);
435 pgp_free(ctx);
436 mbuf_free(src);
437 mbuf_free(dst);
438 px_THROW_ERROR(err);
441 /* res_len includes VARHDRSZ */
442 res_len = mbuf_steal_data(dst, &restmp);
443 res = (bytea *) restmp;
444 SET_VARSIZE(res, res_len);
446 if (tmp_data)
447 clear_and_pfree(tmp_data);
448 pgp_free(ctx);
449 mbuf_free(src);
450 mbuf_free(dst);
452 px_set_debug_handler(NULL);
454 return res;
457 static bytea *
458 decrypt_internal(int is_pubenc, int need_text, text *data,
459 text *key, text *keypsw, text *args)
461 int err;
462 MBuf *src = NULL,
463 *dst = NULL;
464 uint8 tmp[VARHDRSZ];
465 uint8 *restmp;
466 bytea *res;
467 int res_len;
468 PGP_Context *ctx = NULL;
469 struct debug_expect ex;
470 int got_unicode = 0;
473 init_work(&ctx, need_text, args, &ex);
475 src = mbuf_create_from_data((uint8 *) VARDATA_ANY(data),
476 VARSIZE_ANY_EXHDR(data));
477 dst = mbuf_create(VARSIZE_ANY(data) + 2048);
480 * reserve room for header
482 mbuf_append(dst, tmp, VARHDRSZ);
485 * set key
487 if (is_pubenc)
489 uint8 *psw = NULL;
490 int psw_len = 0;
491 MBuf *kbuf;
493 if (keypsw)
495 psw = (uint8 *) VARDATA_ANY(keypsw);
496 psw_len = VARSIZE_ANY_EXHDR(keypsw);
498 kbuf = create_mbuf_from_vardata(key);
499 err = pgp_set_pubkey(ctx, kbuf, psw, psw_len, 1);
500 mbuf_free(kbuf);
502 else
503 err = pgp_set_symkey(ctx, (uint8 *) VARDATA_ANY(key),
504 VARSIZE_ANY_EXHDR(key));
506 /* decrypt */
507 if (err >= 0)
509 err = pgp_decrypt(ctx, src, dst);
511 if (ex.expect)
512 check_expect(ctx, &ex);
514 /* remember the setting */
515 got_unicode = pgp_get_unicode_mode(ctx);
518 mbuf_free(src);
519 pgp_free(ctx);
521 if (err)
523 px_set_debug_handler(NULL);
524 mbuf_free(dst);
525 px_THROW_ERROR(err);
528 res_len = mbuf_steal_data(dst, &restmp);
529 mbuf_free(dst);
531 /* res_len includes VARHDRSZ */
532 res = (bytea *) restmp;
533 SET_VARSIZE(res, res_len);
535 if (need_text && got_unicode)
537 text *utf = convert_from_utf8(res);
539 if (utf != res)
541 clear_and_pfree(res);
542 res = utf;
545 px_set_debug_handler(NULL);
547 return res;
551 * Wrappers for symmetric-key functions
553 Datum
554 pgp_sym_encrypt_bytea(PG_FUNCTION_ARGS)
556 bytea *data;
557 text *arg = NULL;
558 text *res,
559 *key;
561 data = PG_GETARG_BYTEA_PP(0);
562 key = PG_GETARG_TEXT_PP(1);
563 if (PG_NARGS() > 2)
564 arg = PG_GETARG_TEXT_PP(2);
566 res = encrypt_internal(0, 0, data, key, arg);
568 PG_FREE_IF_COPY(data, 0);
569 PG_FREE_IF_COPY(key, 1);
570 if (PG_NARGS() > 2)
571 PG_FREE_IF_COPY(arg, 2);
572 PG_RETURN_TEXT_P(res);
575 Datum
576 pgp_sym_encrypt_text(PG_FUNCTION_ARGS)
578 text *data,
579 *key;
580 text *arg = NULL;
581 text *res;
583 data = PG_GETARG_TEXT_PP(0);
584 key = PG_GETARG_TEXT_PP(1);
585 if (PG_NARGS() > 2)
586 arg = PG_GETARG_TEXT_PP(2);
588 res = encrypt_internal(0, 1, data, key, arg);
590 PG_FREE_IF_COPY(data, 0);
591 PG_FREE_IF_COPY(key, 1);
592 if (PG_NARGS() > 2)
593 PG_FREE_IF_COPY(arg, 2);
594 PG_RETURN_TEXT_P(res);
598 Datum
599 pgp_sym_decrypt_bytea(PG_FUNCTION_ARGS)
601 bytea *data;
602 text *arg = NULL;
603 text *res,
604 *key;
606 data = PG_GETARG_BYTEA_PP(0);
607 key = PG_GETARG_TEXT_PP(1);
608 if (PG_NARGS() > 2)
609 arg = PG_GETARG_TEXT_PP(2);
611 res = decrypt_internal(0, 0, data, key, NULL, arg);
613 PG_FREE_IF_COPY(data, 0);
614 PG_FREE_IF_COPY(key, 1);
615 if (PG_NARGS() > 2)
616 PG_FREE_IF_COPY(arg, 2);
617 PG_RETURN_TEXT_P(res);
620 Datum
621 pgp_sym_decrypt_text(PG_FUNCTION_ARGS)
623 bytea *data;
624 text *arg = NULL;
625 text *res,
626 *key;
628 data = PG_GETARG_BYTEA_PP(0);
629 key = PG_GETARG_TEXT_PP(1);
630 if (PG_NARGS() > 2)
631 arg = PG_GETARG_TEXT_PP(2);
633 res = decrypt_internal(0, 1, data, key, NULL, arg);
635 PG_FREE_IF_COPY(data, 0);
636 PG_FREE_IF_COPY(key, 1);
637 if (PG_NARGS() > 2)
638 PG_FREE_IF_COPY(arg, 2);
639 PG_RETURN_TEXT_P(res);
643 * Wrappers for public-key functions
646 Datum
647 pgp_pub_encrypt_bytea(PG_FUNCTION_ARGS)
649 bytea *data,
650 *key;
651 text *arg = NULL;
652 text *res;
654 data = PG_GETARG_BYTEA_PP(0);
655 key = PG_GETARG_BYTEA_PP(1);
656 if (PG_NARGS() > 2)
657 arg = PG_GETARG_TEXT_PP(2);
659 res = encrypt_internal(1, 0, data, key, arg);
661 PG_FREE_IF_COPY(data, 0);
662 PG_FREE_IF_COPY(key, 1);
663 if (PG_NARGS() > 2)
664 PG_FREE_IF_COPY(arg, 2);
665 PG_RETURN_TEXT_P(res);
668 Datum
669 pgp_pub_encrypt_text(PG_FUNCTION_ARGS)
671 bytea *key;
672 text *arg = NULL;
673 text *res,
674 *data;
676 data = PG_GETARG_TEXT_PP(0);
677 key = PG_GETARG_BYTEA_PP(1);
678 if (PG_NARGS() > 2)
679 arg = PG_GETARG_TEXT_PP(2);
681 res = encrypt_internal(1, 1, data, key, arg);
683 PG_FREE_IF_COPY(data, 0);
684 PG_FREE_IF_COPY(key, 1);
685 if (PG_NARGS() > 2)
686 PG_FREE_IF_COPY(arg, 2);
687 PG_RETURN_TEXT_P(res);
691 Datum
692 pgp_pub_decrypt_bytea(PG_FUNCTION_ARGS)
694 bytea *data,
695 *key;
696 text *psw = NULL,
697 *arg = NULL;
698 text *res;
700 data = PG_GETARG_BYTEA_PP(0);
701 key = PG_GETARG_BYTEA_PP(1);
702 if (PG_NARGS() > 2)
703 psw = PG_GETARG_TEXT_PP(2);
704 if (PG_NARGS() > 3)
705 arg = PG_GETARG_TEXT_PP(3);
707 res = decrypt_internal(1, 0, data, key, psw, arg);
709 PG_FREE_IF_COPY(data, 0);
710 PG_FREE_IF_COPY(key, 1);
711 if (PG_NARGS() > 2)
712 PG_FREE_IF_COPY(psw, 2);
713 if (PG_NARGS() > 3)
714 PG_FREE_IF_COPY(arg, 3);
715 PG_RETURN_TEXT_P(res);
718 Datum
719 pgp_pub_decrypt_text(PG_FUNCTION_ARGS)
721 bytea *data,
722 *key;
723 text *psw = NULL,
724 *arg = NULL;
725 text *res;
727 data = PG_GETARG_BYTEA_PP(0);
728 key = PG_GETARG_BYTEA_PP(1);
729 if (PG_NARGS() > 2)
730 psw = PG_GETARG_TEXT_PP(2);
731 if (PG_NARGS() > 3)
732 arg = PG_GETARG_TEXT_PP(3);
734 res = decrypt_internal(1, 1, data, key, psw, arg);
736 PG_FREE_IF_COPY(data, 0);
737 PG_FREE_IF_COPY(key, 1);
738 if (PG_NARGS() > 2)
739 PG_FREE_IF_COPY(psw, 2);
740 if (PG_NARGS() > 3)
741 PG_FREE_IF_COPY(arg, 3);
742 PG_RETURN_TEXT_P(res);
747 * Wrappers for PGP ascii armor
751 * Helper function for pg_armor. Converts arrays of keys and values into
752 * plain C arrays, and checks that they don't contain invalid characters.
754 static int
755 parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
756 char ***p_keys, char ***p_values)
758 int nkdims = ARR_NDIM(key_array);
759 int nvdims = ARR_NDIM(val_array);
760 char **keys,
761 **values;
762 Datum *key_datums,
763 *val_datums;
764 bool *key_nulls,
765 *val_nulls;
766 int key_count,
767 val_count;
768 int i;
770 if (nkdims > 1 || nkdims != nvdims)
771 ereport(ERROR,
772 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
773 errmsg("wrong number of array subscripts")));
774 if (nkdims == 0)
775 return 0;
777 deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
778 deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count);
780 if (key_count != val_count)
781 ereport(ERROR,
782 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
783 errmsg("mismatched array dimensions")));
785 keys = (char **) palloc(sizeof(char *) * key_count);
786 values = (char **) palloc(sizeof(char *) * val_count);
788 for (i = 0; i < key_count; i++)
790 char *v;
792 /* Check that the key doesn't contain anything funny */
793 if (key_nulls[i])
794 ereport(ERROR,
795 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
796 errmsg("null value not allowed for header key")));
798 v = TextDatumGetCString(key_datums[i]);
800 if (!pg_is_ascii(v))
801 ereport(ERROR,
802 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
803 errmsg("header key must not contain non-ASCII characters")));
804 if (strstr(v, ": "))
805 ereport(ERROR,
806 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
807 errmsg("header key must not contain \": \"")));
808 if (strchr(v, '\n'))
809 ereport(ERROR,
810 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
811 errmsg("header key must not contain newlines")));
812 keys[i] = v;
814 /* And the same for the value */
815 if (val_nulls[i])
816 ereport(ERROR,
817 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
818 errmsg("null value not allowed for header value")));
820 v = TextDatumGetCString(val_datums[i]);
822 if (!pg_is_ascii(v))
823 ereport(ERROR,
824 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
825 errmsg("header value must not contain non-ASCII characters")));
826 if (strchr(v, '\n'))
827 ereport(ERROR,
828 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
829 errmsg("header value must not contain newlines")));
831 values[i] = v;
834 *p_keys = keys;
835 *p_values = values;
836 return key_count;
839 Datum
840 pg_armor(PG_FUNCTION_ARGS)
842 bytea *data;
843 text *res;
844 int data_len;
845 StringInfoData buf;
846 int num_headers;
847 char **keys = NULL,
848 **values = NULL;
850 data = PG_GETARG_BYTEA_PP(0);
851 data_len = VARSIZE_ANY_EXHDR(data);
852 if (PG_NARGS() == 3)
854 num_headers = parse_key_value_arrays(PG_GETARG_ARRAYTYPE_P(1),
855 PG_GETARG_ARRAYTYPE_P(2),
856 &keys, &values);
858 else if (PG_NARGS() == 1)
859 num_headers = 0;
860 else
861 elog(ERROR, "unexpected number of arguments %d", PG_NARGS());
863 initStringInfo(&buf);
865 pgp_armor_encode((uint8 *) VARDATA_ANY(data), data_len, &buf,
866 num_headers, keys, values);
868 res = palloc(VARHDRSZ + buf.len);
869 SET_VARSIZE(res, VARHDRSZ + buf.len);
870 memcpy(VARDATA(res), buf.data, buf.len);
871 pfree(buf.data);
873 PG_FREE_IF_COPY(data, 0);
874 PG_RETURN_TEXT_P(res);
877 Datum
878 pg_dearmor(PG_FUNCTION_ARGS)
880 text *data;
881 bytea *res;
882 int data_len;
883 int ret;
884 StringInfoData buf;
886 data = PG_GETARG_TEXT_PP(0);
887 data_len = VARSIZE_ANY_EXHDR(data);
889 initStringInfo(&buf);
891 ret = pgp_armor_decode((uint8 *) VARDATA_ANY(data), data_len, &buf);
892 if (ret < 0)
893 px_THROW_ERROR(ret);
894 res = palloc(VARHDRSZ + buf.len);
895 SET_VARSIZE(res, VARHDRSZ + buf.len);
896 memcpy(VARDATA(res), buf.data, buf.len);
897 pfree(buf.data);
899 PG_FREE_IF_COPY(data, 0);
900 PG_RETURN_TEXT_P(res);
903 /* cross-call state for pgp_armor_headers */
904 typedef struct
906 int nheaders;
907 char **keys;
908 char **values;
909 } pgp_armor_headers_state;
911 Datum
912 pgp_armor_headers(PG_FUNCTION_ARGS)
914 FuncCallContext *funcctx;
915 pgp_armor_headers_state *state;
916 char *utf8key;
917 char *utf8val;
918 HeapTuple tuple;
919 TupleDesc tupdesc;
920 AttInMetadata *attinmeta;
922 if (SRF_IS_FIRSTCALL())
924 text *data = PG_GETARG_TEXT_PP(0);
925 int res;
926 MemoryContext oldcontext;
928 funcctx = SRF_FIRSTCALL_INIT();
930 /* we need the state allocated in the multi call context */
931 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
933 /* Build a tuple descriptor for our result type */
934 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
935 elog(ERROR, "return type must be a row type");
937 attinmeta = TupleDescGetAttInMetadata(tupdesc);
938 funcctx->attinmeta = attinmeta;
940 state = (pgp_armor_headers_state *) palloc(sizeof(pgp_armor_headers_state));
942 res = pgp_extract_armor_headers((uint8 *) VARDATA_ANY(data),
943 VARSIZE_ANY_EXHDR(data),
944 &state->nheaders, &state->keys,
945 &state->values);
946 if (res < 0)
947 px_THROW_ERROR(res);
949 MemoryContextSwitchTo(oldcontext);
950 funcctx->user_fctx = state;
953 funcctx = SRF_PERCALL_SETUP();
954 state = (pgp_armor_headers_state *) funcctx->user_fctx;
956 if (funcctx->call_cntr >= state->nheaders)
957 SRF_RETURN_DONE(funcctx);
958 else
960 char *values[2];
962 /* we assume that the keys (and values) are in UTF-8. */
963 utf8key = state->keys[funcctx->call_cntr];
964 utf8val = state->values[funcctx->call_cntr];
966 values[0] = pg_any_to_server(utf8key, strlen(utf8key), PG_UTF8);
967 values[1] = pg_any_to_server(utf8val, strlen(utf8val), PG_UTF8);
969 /* build a tuple */
970 tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
971 SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
978 * Wrappers for PGP key id
981 Datum
982 pgp_key_id_w(PG_FUNCTION_ARGS)
984 bytea *data;
985 text *res;
986 int res_len;
987 MBuf *buf;
989 data = PG_GETARG_BYTEA_PP(0);
990 buf = create_mbuf_from_vardata(data);
991 res = palloc(VARHDRSZ + 17);
993 res_len = pgp_get_keyid(buf, VARDATA(res));
994 mbuf_free(buf);
995 if (res_len < 0)
996 px_THROW_ERROR(res_len);
997 SET_VARSIZE(res, VARHDRSZ + res_len);
999 PG_FREE_IF_COPY(data, 0);
1000 PG_RETURN_TEXT_P(res);