]> granicus.if.org Git - postgresql/blob - contrib/pgcrypto/pgp-info.c
pgindent run for 9.4
[postgresql] / contrib / pgcrypto / pgp-info.c
1 /*
2  * pgp-info.c
3  *        Provide info about PGP data.
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-info.c
30  */
31 #include "postgres.h"
32
33 #include "px.h"
34 #include "mbuf.h"
35 #include "pgp.h"
36
37 static int
38 read_pubkey_keyid(PullFilter *pkt, uint8 *keyid_buf)
39 {
40         int                     res;
41         PGP_PubKey *pk = NULL;
42
43         res = _pgp_read_public_key(pkt, &pk);
44         if (res < 0)
45                 goto err;
46
47         /* skip secret key part, if it exists */
48         res = pgp_skip_packet(pkt);
49         if (res < 0)
50                 goto err;
51
52         /* is it encryption key */
53         switch (pk->algo)
54         {
55                 case PGP_PUB_ELG_ENCRYPT:
56                 case PGP_PUB_RSA_ENCRYPT:
57                 case PGP_PUB_RSA_ENCRYPT_SIGN:
58                         memcpy(keyid_buf, pk->key_id, 8);
59                         res = 1;
60                         break;
61                 default:
62                         res = 0;
63         }
64
65 err:
66         pgp_key_free(pk);
67         return res;
68 }
69
70 static int
71 read_pubenc_keyid(PullFilter *pkt, uint8 *keyid_buf)
72 {
73         uint8           ver;
74         int                     res;
75
76         GETBYTE(pkt, ver);
77         if (ver != 3)
78                 return -1;
79
80         res = pullf_read_fixed(pkt, 8, keyid_buf);
81         if (res < 0)
82                 return res;
83
84         return pgp_skip_packet(pkt);
85 }
86
87 static const char hextbl[] = "0123456789ABCDEF";
88
89 static int
90 print_key(uint8 *keyid, char *dst)
91 {
92         int                     i;
93         unsigned        c;
94
95         for (i = 0; i < 8; i++)
96         {
97                 c = keyid[i];
98                 *dst++ = hextbl[(c >> 4) & 0x0F];
99                 *dst++ = hextbl[c & 0x0F];
100         }
101         *dst = 0;
102         return 8 * 2;
103 }
104
105 static const uint8 any_key[] =
106 {0, 0, 0, 0, 0, 0, 0, 0};
107
108 /*
109  * dst should have room for 17 bytes
110  */
111 int
112 pgp_get_keyid(MBuf *pgp_data, char *dst)
113 {
114         int                     res;
115         PullFilter *src;
116         PullFilter *pkt = NULL;
117         int                     len;
118         uint8           tag;
119         int                     got_pub_key = 0,
120                                 got_symenc_key = 0,
121                                 got_pubenc_key = 0;
122         int                     got_data = 0;
123         uint8           keyid_buf[8];
124         int                     got_main_key = 0;
125
126
127         res = pullf_create_mbuf_reader(&src, pgp_data);
128         if (res < 0)
129                 return res;
130
131         while (1)
132         {
133                 res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
134                 if (res <= 0)
135                         break;
136                 res = pgp_create_pkt_reader(&pkt, src, len, res, NULL);
137                 if (res < 0)
138                         break;
139
140                 switch (tag)
141                 {
142                         case PGP_PKT_SECRET_KEY:
143                         case PGP_PKT_PUBLIC_KEY:
144                                 /* main key is for signing, so ignore it */
145                                 if (!got_main_key)
146                                 {
147                                         got_main_key = 1;
148                                         res = pgp_skip_packet(pkt);
149                                 }
150                                 else
151                                         res = PXE_PGP_MULTIPLE_KEYS;
152                                 break;
153                         case PGP_PKT_SECRET_SUBKEY:
154                         case PGP_PKT_PUBLIC_SUBKEY:
155                                 res = read_pubkey_keyid(pkt, keyid_buf);
156                                 if (res < 0)
157                                         break;
158                                 if (res > 0)
159                                         got_pub_key++;
160                                 break;
161                         case PGP_PKT_PUBENCRYPTED_SESSKEY:
162                                 got_pubenc_key++;
163                                 res = read_pubenc_keyid(pkt, keyid_buf);
164                                 break;
165                         case PGP_PKT_SYMENCRYPTED_DATA:
166                         case PGP_PKT_SYMENCRYPTED_DATA_MDC:
167                                 /* don't skip it, just stop */
168                                 got_data = 1;
169                                 break;
170                         case PGP_PKT_SYMENCRYPTED_SESSKEY:
171                                 got_symenc_key++;
172                                 /* fallthru */
173                         case PGP_PKT_SIGNATURE:
174                         case PGP_PKT_MARKER:
175                         case PGP_PKT_TRUST:
176                         case PGP_PKT_USER_ID:
177                         case PGP_PKT_USER_ATTR:
178                         case PGP_PKT_PRIV_61:
179                                 res = pgp_skip_packet(pkt);
180                                 break;
181                         default:
182                                 res = PXE_PGP_CORRUPT_DATA;
183                 }
184
185                 if (pkt)
186                         pullf_free(pkt);
187                 pkt = NULL;
188
189                 if (res < 0 || got_data)
190                         break;
191         }
192
193         pullf_free(src);
194         if (pkt)
195                 pullf_free(pkt);
196
197         if (res < 0)
198                 return res;
199
200         /* now check sanity */
201         if (got_pub_key && got_pubenc_key)
202                 res = PXE_PGP_CORRUPT_DATA;
203
204         if (got_pub_key > 1)
205                 res = PXE_PGP_MULTIPLE_KEYS;
206
207         if (got_pubenc_key > 1)
208                 res = PXE_PGP_MULTIPLE_KEYS;
209
210         /*
211          * if still ok, look what we got
212          */
213         if (res >= 0)
214         {
215                 if (got_pubenc_key || got_pub_key)
216                 {
217                         if (memcmp(keyid_buf, any_key, 8) == 0)
218                         {
219                                 memcpy(dst, "ANYKEY", 7);
220                                 res = 6;
221                         }
222                         else
223                                 res = print_key(keyid_buf, dst);
224                 }
225                 else if (got_symenc_key)
226                 {
227                         memcpy(dst, "SYMKEY", 7);
228                         res = 6;
229                 }
230                 else
231                         res = PXE_PGP_NO_USABLE_KEY;
232         }
233
234         return res;
235 }