Sun Oct 31 19:45:53 2010 UTC ()
PR/42435 : Check pointers against NULL to avoid dereferencing them


(stacktic)
diff -r1.46 -r1.47 src/crypto/external/bsd/netpgp/dist/src/lib/keyring.c
diff -r1.77 -r1.78 src/crypto/external/bsd/netpgp/dist/src/lib/netpgp.c

cvs diff -r1.46 -r1.47 src/crypto/external/bsd/netpgp/dist/src/lib/keyring.c (switch to unified diff)

--- src/crypto/external/bsd/netpgp/dist/src/lib/keyring.c 2010/09/01 17:25:57 1.46
+++ src/crypto/external/bsd/netpgp/dist/src/lib/keyring.c 2010/10/31 19:45:53 1.47
@@ -1,1151 +1,1151 @@ @@ -1,1151 +1,1151 @@
1/*- 1/*-
2 * Copyright (c) 2009 The NetBSD Foundation, Inc. 2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * This code is derived from software contributed to The NetBSD Foundation 5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org) 6 * by Alistair Crooks (agc@NetBSD.org)
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE. 27 * POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29/* 29/*
30 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) 30 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31 * All rights reserved. 31 * All rights reserved.
32 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted 32 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33 * their moral rights under the UK Copyright Design and Patents Act 1988 to 33 * their moral rights under the UK Copyright Design and Patents Act 1988 to
34 * be recorded as the authors of this copyright work. 34 * be recorded as the authors of this copyright work.
35 * 35 *
36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37 * use this file except in compliance with the License. 37 * use this file except in compliance with the License.
38 * 38 *
39 * You may obtain a copy of the License at 39 * You may obtain a copy of the License at
40 * http://www.apache.org/licenses/LICENSE-2.0 40 * http://www.apache.org/licenses/LICENSE-2.0
41 * 41 *
42 * Unless required by applicable law or agreed to in writing, software 42 * Unless required by applicable law or agreed to in writing, software
43 * distributed under the License is distributed on an "AS IS" BASIS, 43 * distributed under the License is distributed on an "AS IS" BASIS,
44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45 * 45 *
46 * See the License for the specific language governing permissions and 46 * See the License for the specific language governing permissions and
47 * limitations under the License. 47 * limitations under the License.
48 */ 48 */
49 49
50/** \file 50/** \file
51 */ 51 */
52#include "config.h" 52#include "config.h"
53 53
54#ifdef HAVE_SYS_CDEFS_H 54#ifdef HAVE_SYS_CDEFS_H
55#include <sys/cdefs.h> 55#include <sys/cdefs.h>
56#endif 56#endif
57 57
58#if defined(__NetBSD__) 58#if defined(__NetBSD__)
59__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); 59__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60__RCSID("$NetBSD: keyring.c,v 1.46 2010/09/01 17:25:57 agc Exp $"); 60__RCSID("$NetBSD: keyring.c,v 1.47 2010/10/31 19:45:53 stacktic Exp $");
61#endif 61#endif
62 62
63#ifdef HAVE_FCNTL_H 63#ifdef HAVE_FCNTL_H
64#include <fcntl.h> 64#include <fcntl.h>
65#endif 65#endif
66 66
67#include <regex.h> 67#include <regex.h>
68#include <stdlib.h> 68#include <stdlib.h>
69#include <string.h> 69#include <string.h>
70 70
71#ifdef HAVE_TERMIOS_H 71#ifdef HAVE_TERMIOS_H
72#include <termios.h> 72#include <termios.h>
73#endif 73#endif
74 74
75#ifdef HAVE_UNISTD_H 75#ifdef HAVE_UNISTD_H
76#include <unistd.h> 76#include <unistd.h>
77#endif 77#endif
78 78
79#include "types.h" 79#include "types.h"
80#include "keyring.h" 80#include "keyring.h"
81#include "packet-parse.h" 81#include "packet-parse.h"
82#include "signature.h" 82#include "signature.h"
83#include "netpgpsdk.h" 83#include "netpgpsdk.h"
84#include "readerwriter.h" 84#include "readerwriter.h"
85#include "netpgpdefs.h" 85#include "netpgpdefs.h"
86#include "packet.h" 86#include "packet.h"
87#include "crypto.h" 87#include "crypto.h"
88#include "validate.h" 88#include "validate.h"
89#include "netpgpdefs.h" 89#include "netpgpdefs.h"
90#include "netpgpdigest.h" 90#include "netpgpdigest.h"
91 91
92 92
93 93
94/** 94/**
95 \ingroup HighLevel_Keyring 95 \ingroup HighLevel_Keyring
96 96
97 \brief Creates a new __ops_key_t struct 97 \brief Creates a new __ops_key_t struct
98 98
99 \return A new __ops_key_t struct, initialised to zero. 99 \return A new __ops_key_t struct, initialised to zero.
100 100
101 \note The returned __ops_key_t struct must be freed after use with __ops_keydata_free. 101 \note The returned __ops_key_t struct must be freed after use with __ops_keydata_free.
102*/ 102*/
103 103
104__ops_key_t * 104__ops_key_t *
105__ops_keydata_new(void) 105__ops_keydata_new(void)
106{ 106{
107 return calloc(1, sizeof(__ops_key_t)); 107 return calloc(1, sizeof(__ops_key_t));
108} 108}
109 109
110 110
111/** 111/**
112 \ingroup HighLevel_Keyring 112 \ingroup HighLevel_Keyring
113 113
114 \brief Frees keydata and its memory 114 \brief Frees keydata and its memory
115 115
116 \param keydata Key to be freed. 116 \param keydata Key to be freed.
117 117
118 \note This frees the keydata itself, as well as any other memory alloc-ed by it. 118 \note This frees the keydata itself, as well as any other memory alloc-ed by it.
119*/ 119*/
120void  120void
121__ops_keydata_free(__ops_key_t *keydata) 121__ops_keydata_free(__ops_key_t *keydata)
122{ 122{
123 unsigned n; 123 unsigned n;
124 124
125 for (n = 0; n < keydata->uidc; ++n) { 125 for (n = 0; n < keydata->uidc; ++n) {
126 __ops_userid_free(&keydata->uids[n]); 126 __ops_userid_free(&keydata->uids[n]);
127 } 127 }
128 free(keydata->uids); 128 free(keydata->uids);
129 keydata->uids = NULL; 129 keydata->uids = NULL;
130 keydata->uidc = 0; 130 keydata->uidc = 0;
131 131
132 for (n = 0; n < keydata->packetc; ++n) { 132 for (n = 0; n < keydata->packetc; ++n) {
133 __ops_subpacket_free(&keydata->packets[n]); 133 __ops_subpacket_free(&keydata->packets[n]);
134 } 134 }
135 free(keydata->packets); 135 free(keydata->packets);
136 keydata->packets = NULL; 136 keydata->packets = NULL;
137 keydata->packetc = 0; 137 keydata->packetc = 0;
138 138
139 if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) { 139 if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
140 __ops_pubkey_free(&keydata->key.pubkey); 140 __ops_pubkey_free(&keydata->key.pubkey);
141 } else { 141 } else {
142 __ops_seckey_free(&keydata->key.seckey); 142 __ops_seckey_free(&keydata->key.seckey);
143 } 143 }
144 144
145 free(keydata); 145 free(keydata);
146} 146}
147 147
148/** 148/**
149 \ingroup HighLevel_KeyGeneral 149 \ingroup HighLevel_KeyGeneral
150 150
151 \brief Returns the public key in the given keydata. 151 \brief Returns the public key in the given keydata.
152 \param keydata 152 \param keydata
153 153
154 \return Pointer to public key 154 \return Pointer to public key
155 155
156 \note This is not a copy, do not free it after use. 156 \note This is not a copy, do not free it after use.
157*/ 157*/
158 158
159const __ops_pubkey_t * 159const __ops_pubkey_t *
160__ops_get_pubkey(const __ops_key_t *keydata) 160__ops_get_pubkey(const __ops_key_t *keydata)
161{ 161{
162 return (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) ? 162 return (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) ?
163 &keydata->key.pubkey : 163 &keydata->key.pubkey :
164 &keydata->key.seckey.pubkey; 164 &keydata->key.seckey.pubkey;
165} 165}
166 166
167/** 167/**
168\ingroup HighLevel_KeyGeneral 168\ingroup HighLevel_KeyGeneral
169 169
170\brief Check whether this is a secret key or not. 170\brief Check whether this is a secret key or not.
171*/ 171*/
172 172
173unsigned  173unsigned
174__ops_is_key_secret(const __ops_key_t *data) 174__ops_is_key_secret(const __ops_key_t *data)
175{ 175{
176 return data->type != OPS_PTAG_CT_PUBLIC_KEY; 176 return data->type != OPS_PTAG_CT_PUBLIC_KEY;
177} 177}
178 178
179/** 179/**
180 \ingroup HighLevel_KeyGeneral 180 \ingroup HighLevel_KeyGeneral
181 181
182 \brief Returns the secret key in the given keydata. 182 \brief Returns the secret key in the given keydata.
183 183
184 \note This is not a copy, do not free it after use. 184 \note This is not a copy, do not free it after use.
185 185
186 \note This returns a const. If you need to be able to write to this 186 \note This returns a const. If you need to be able to write to this
187 pointer, use __ops_get_writable_seckey 187 pointer, use __ops_get_writable_seckey
188*/ 188*/
189 189
190const __ops_seckey_t * 190const __ops_seckey_t *
191__ops_get_seckey(const __ops_key_t *data) 191__ops_get_seckey(const __ops_key_t *data)
192{ 192{
193 return (data->type == OPS_PTAG_CT_SECRET_KEY) ? 193 return (data->type == OPS_PTAG_CT_SECRET_KEY) ?
194 &data->key.seckey : NULL; 194 &data->key.seckey : NULL;
195} 195}
196 196
197/** 197/**
198 \ingroup HighLevel_KeyGeneral 198 \ingroup HighLevel_KeyGeneral
199 199
200 \brief Returns the secret key in the given keydata. 200 \brief Returns the secret key in the given keydata.
201 201
202 \note This is not a copy, do not free it after use. 202 \note This is not a copy, do not free it after use.
203 203
204 \note If you do not need to be able to modify this key, there is an 204 \note If you do not need to be able to modify this key, there is an
205 equivalent read-only function __ops_get_seckey. 205 equivalent read-only function __ops_get_seckey.
206*/ 206*/
207 207
208__ops_seckey_t * 208__ops_seckey_t *
209__ops_get_writable_seckey(__ops_key_t *data) 209__ops_get_writable_seckey(__ops_key_t *data)
210{ 210{
211 return (data->type == OPS_PTAG_CT_SECRET_KEY) ? 211 return (data->type == OPS_PTAG_CT_SECRET_KEY) ?
212 &data->key.seckey : NULL; 212 &data->key.seckey : NULL;
213} 213}
214 214
215/* utility function to zero out memory */ 215/* utility function to zero out memory */
216void 216void
217__ops_forget(void *vp, unsigned size) 217__ops_forget(void *vp, unsigned size)
218{ 218{
219 (void) memset(vp, 0x0, size); 219 (void) memset(vp, 0x0, size);
220} 220}
221 221
222typedef struct { 222typedef struct {
223 FILE *passfp; 223 FILE *passfp;
224 const __ops_key_t *key; 224 const __ops_key_t *key;
225 char *passphrase; 225 char *passphrase;
226 __ops_seckey_t *seckey; 226 __ops_seckey_t *seckey;
227} decrypt_t; 227} decrypt_t;
228 228
229static __ops_cb_ret_t  229static __ops_cb_ret_t
230decrypt_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo) 230decrypt_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
231{ 231{
232 const __ops_contents_t *content = &pkt->u; 232 const __ops_contents_t *content = &pkt->u;
233 decrypt_t *decrypt; 233 decrypt_t *decrypt;
234 char pass[MAX_PASSPHRASE_LENGTH]; 234 char pass[MAX_PASSPHRASE_LENGTH];
235 235
236 decrypt = __ops_callback_arg(cbinfo); 236 decrypt = __ops_callback_arg(cbinfo);
237 switch (pkt->tag) { 237 switch (pkt->tag) {
238 case OPS_PARSER_PTAG: 238 case OPS_PARSER_PTAG:
239 case OPS_PTAG_CT_USER_ID: 239 case OPS_PTAG_CT_USER_ID:
240 case OPS_PTAG_CT_SIGNATURE: 240 case OPS_PTAG_CT_SIGNATURE:
241 case OPS_PTAG_CT_SIGNATURE_HEADER: 241 case OPS_PTAG_CT_SIGNATURE_HEADER:
242 case OPS_PTAG_CT_SIGNATURE_FOOTER: 242 case OPS_PTAG_CT_SIGNATURE_FOOTER:
243 case OPS_PTAG_CT_TRUST: 243 case OPS_PTAG_CT_TRUST:
244 break; 244 break;
245 245
246 case OPS_GET_PASSPHRASE: 246 case OPS_GET_PASSPHRASE:
247 (void) __ops_getpassphrase(decrypt->passfp, pass, sizeof(pass)); 247 (void) __ops_getpassphrase(decrypt->passfp, pass, sizeof(pass));
248 *content->skey_passphrase.passphrase = netpgp_strdup(pass); 248 *content->skey_passphrase.passphrase = netpgp_strdup(pass);
249 __ops_forget(pass, (unsigned)sizeof(pass)); 249 __ops_forget(pass, (unsigned)sizeof(pass));
250 return OPS_KEEP_MEMORY; 250 return OPS_KEEP_MEMORY;
251 251
252 case OPS_PARSER_ERRCODE: 252 case OPS_PARSER_ERRCODE:
253 switch (content->errcode.errcode) { 253 switch (content->errcode.errcode) {
254 case OPS_E_P_MPI_FORMAT_ERROR: 254 case OPS_E_P_MPI_FORMAT_ERROR:
255 /* Generally this means a bad passphrase */ 255 /* Generally this means a bad passphrase */
256 fprintf(stderr, "Bad passphrase!\n"); 256 fprintf(stderr, "Bad passphrase!\n");
257 return OPS_RELEASE_MEMORY; 257 return OPS_RELEASE_MEMORY;
258 258
259 case OPS_E_P_PACKET_CONSUMED: 259 case OPS_E_P_PACKET_CONSUMED:
260 /* And this is because of an error we've accepted */ 260 /* And this is because of an error we've accepted */
261 return OPS_RELEASE_MEMORY; 261 return OPS_RELEASE_MEMORY;
262 default: 262 default:
263 break; 263 break;
264 } 264 }
265 (void) fprintf(stderr, "parse error: %s\n", 265 (void) fprintf(stderr, "parse error: %s\n",
266 __ops_errcode(content->errcode.errcode)); 266 __ops_errcode(content->errcode.errcode));
267 return OPS_FINISHED; 267 return OPS_FINISHED;
268 268
269 case OPS_PARSER_ERROR: 269 case OPS_PARSER_ERROR:
270 fprintf(stderr, "parse error: %s\n", content->error); 270 fprintf(stderr, "parse error: %s\n", content->error);
271 return OPS_FINISHED; 271 return OPS_FINISHED;
272 272
273 case OPS_PTAG_CT_SECRET_KEY: 273 case OPS_PTAG_CT_SECRET_KEY:
274 if ((decrypt->seckey = calloc(1, sizeof(*decrypt->seckey))) == NULL) { 274 if ((decrypt->seckey = calloc(1, sizeof(*decrypt->seckey))) == NULL) {
275 (void) fprintf(stderr, "decrypt_cb: bad alloc\n"); 275 (void) fprintf(stderr, "decrypt_cb: bad alloc\n");
276 return OPS_FINISHED; 276 return OPS_FINISHED;
277 } 277 }
278 decrypt->seckey->checkhash = calloc(1, OPS_CHECKHASH_SIZE); 278 decrypt->seckey->checkhash = calloc(1, OPS_CHECKHASH_SIZE);
279 *decrypt->seckey = content->seckey; 279 *decrypt->seckey = content->seckey;
280 return OPS_KEEP_MEMORY; 280 return OPS_KEEP_MEMORY;
281 281
282 case OPS_PARSER_PACKET_END: 282 case OPS_PARSER_PACKET_END:
283 /* nothing to do */ 283 /* nothing to do */
284 break; 284 break;
285 285
286 default: 286 default:
287 fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag, 287 fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag,
288 pkt->tag); 288 pkt->tag);
289 return OPS_FINISHED; 289 return OPS_FINISHED;
290 } 290 }
291 291
292 return OPS_RELEASE_MEMORY; 292 return OPS_RELEASE_MEMORY;
293} 293}
294 294
295/** 295/**
296\ingroup Core_Keys 296\ingroup Core_Keys
297\brief Decrypts secret key from given keydata with given passphrase 297\brief Decrypts secret key from given keydata with given passphrase
298\param key Key from which to get secret key 298\param key Key from which to get secret key
299\param passphrase Passphrase to use to decrypt secret key 299\param passphrase Passphrase to use to decrypt secret key
300\return secret key 300\return secret key
301*/ 301*/
302__ops_seckey_t * 302__ops_seckey_t *
303__ops_decrypt_seckey(const __ops_key_t *key, void *passfp) 303__ops_decrypt_seckey(const __ops_key_t *key, void *passfp)
304{ 304{
305 __ops_stream_t *stream; 305 __ops_stream_t *stream;
306 const int printerrors = 1; 306 const int printerrors = 1;
307 decrypt_t decrypt; 307 decrypt_t decrypt;
308 308
309 (void) memset(&decrypt, 0x0, sizeof(decrypt)); 309 (void) memset(&decrypt, 0x0, sizeof(decrypt));
310 decrypt.key = key; 310 decrypt.key = key;
311 decrypt.passfp = passfp; 311 decrypt.passfp = passfp;
312 stream = __ops_new(sizeof(*stream)); 312 stream = __ops_new(sizeof(*stream));
313 __ops_keydata_reader_set(stream, key); 313 __ops_keydata_reader_set(stream, key);
314 __ops_set_callback(stream, decrypt_cb, &decrypt); 314 __ops_set_callback(stream, decrypt_cb, &decrypt);
315 stream->readinfo.accumulate = 1; 315 stream->readinfo.accumulate = 1;
316 __ops_parse(stream, !printerrors); 316 __ops_parse(stream, !printerrors);
317 return decrypt.seckey; 317 return decrypt.seckey;
318} 318}
319 319
320/** 320/**
321\ingroup Core_Keys 321\ingroup Core_Keys
322\brief Set secret key in content 322\brief Set secret key in content
323\param content Content to be set 323\param content Content to be set
324\param key Keydata to get secret key from 324\param key Keydata to get secret key from
325*/ 325*/
326void  326void
327__ops_set_seckey(__ops_contents_t *cont, const __ops_key_t *key) 327__ops_set_seckey(__ops_contents_t *cont, const __ops_key_t *key)
328{ 328{
329 *cont->get_seckey.seckey = &key->key.seckey; 329 *cont->get_seckey.seckey = &key->key.seckey;
330} 330}
331 331
332/** 332/**
333\ingroup Core_Keys 333\ingroup Core_Keys
334\brief Get Key ID from keydata 334\brief Get Key ID from keydata
335\param key Keydata to get Key ID from 335\param key Keydata to get Key ID from
336\return Pointer to Key ID inside keydata 336\return Pointer to Key ID inside keydata
337*/ 337*/
338const uint8_t * 338const uint8_t *
339__ops_get_key_id(const __ops_key_t *key) 339__ops_get_key_id(const __ops_key_t *key)
340{ 340{
341 return key->sigid; 341 return key->sigid;
342} 342}
343 343
344/** 344/**
345\ingroup Core_Keys 345\ingroup Core_Keys
346\brief How many User IDs in this key? 346\brief How many User IDs in this key?
347\param key Keydata to check 347\param key Keydata to check
348\return Num of user ids 348\return Num of user ids
349*/ 349*/
350unsigned  350unsigned
351__ops_get_userid_count(const __ops_key_t *key) 351__ops_get_userid_count(const __ops_key_t *key)
352{ 352{
353 return key->uidc; 353 return key->uidc;
354} 354}
355 355
356/** 356/**
357\ingroup Core_Keys 357\ingroup Core_Keys
358\brief Get indexed user id from key 358\brief Get indexed user id from key
359\param key Key to get user id from 359\param key Key to get user id from
360\param index Which key to get 360\param index Which key to get
361\return Pointer to requested user id 361\return Pointer to requested user id
362*/ 362*/
363const uint8_t * 363const uint8_t *
364__ops_get_userid(const __ops_key_t *key, unsigned subscript) 364__ops_get_userid(const __ops_key_t *key, unsigned subscript)
365{ 365{
366 return key->uids[subscript]; 366 return key->uids[subscript];
367} 367}
368 368
369/** 369/**
370 \ingroup HighLevel_Supported 370 \ingroup HighLevel_Supported
371 \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK 371 \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK
372 \param keydata Key to be checked 372 \param keydata Key to be checked
373 \return 1 if key algorithm and type are supported by OpenPGP::SDK; 0 if not 373 \return 1 if key algorithm and type are supported by OpenPGP::SDK; 0 if not
374*/ 374*/
375 375
376unsigned  376unsigned
377__ops_is_key_supported(const __ops_key_t *key) 377__ops_is_key_supported(const __ops_key_t *key)
378{ 378{
379 if (key->type == OPS_PTAG_CT_PUBLIC_KEY) { 379 if (key->type == OPS_PTAG_CT_PUBLIC_KEY) {
380 switch(key->key.pubkey.alg) { 380 switch(key->key.pubkey.alg) {
381 case OPS_PKA_RSA: 381 case OPS_PKA_RSA:
382 case OPS_PKA_DSA: 382 case OPS_PKA_DSA:
383 case OPS_PKA_ELGAMAL: 383 case OPS_PKA_ELGAMAL:
384 return 1; 384 return 1;
385 default: 385 default:
386 break; 386 break;
387 } 387 }
388 } 388 }
389 return 0; 389 return 0;
390} 390}
391 391
392/* \todo check where userid pointers are copied */ 392/* \todo check where userid pointers are copied */
393/** 393/**
394\ingroup Core_Keys 394\ingroup Core_Keys
395\brief Copy user id, including contents 395\brief Copy user id, including contents
396\param dst Destination User ID 396\param dst Destination User ID
397\param src Source User ID 397\param src Source User ID
398\note If dst already has a userid, it will be freed. 398\note If dst already has a userid, it will be freed.
399*/ 399*/
400static uint8_t *  400static uint8_t *
401__ops_copy_userid(uint8_t **dst, const uint8_t *src) 401__ops_copy_userid(uint8_t **dst, const uint8_t *src)
402{ 402{
403 size_t len; 403 size_t len;
404 404
405 len = strlen((const char *) src); 405 len = strlen((const char *) src);
406 if (*dst) { 406 if (*dst) {
407 free(*dst); 407 free(*dst);
408 } 408 }
409 if ((*dst = calloc(1, len + 1)) == NULL) { 409 if ((*dst = calloc(1, len + 1)) == NULL) {
410 (void) fprintf(stderr, "__ops_copy_userid: bad alloc\n"); 410 (void) fprintf(stderr, "__ops_copy_userid: bad alloc\n");
411 } else { 411 } else {
412 (void) memcpy(*dst, src, len); 412 (void) memcpy(*dst, src, len);
413 } 413 }
414 return *dst; 414 return *dst;
415} 415}
416 416
417/* \todo check where pkt pointers are copied */ 417/* \todo check where pkt pointers are copied */
418/** 418/**
419\ingroup Core_Keys 419\ingroup Core_Keys
420\brief Copy packet, including contents 420\brief Copy packet, including contents
421\param dst Destination packet 421\param dst Destination packet
422\param src Source packet 422\param src Source packet
423\note If dst already has a packet, it will be freed. 423\note If dst already has a packet, it will be freed.
424*/ 424*/
425static __ops_subpacket_t *  425static __ops_subpacket_t *
426__ops_copy_packet(__ops_subpacket_t *dst, const __ops_subpacket_t *src) 426__ops_copy_packet(__ops_subpacket_t *dst, const __ops_subpacket_t *src)
427{ 427{
428 if (dst->raw) { 428 if (dst->raw) {
429 free(dst->raw); 429 free(dst->raw);
430 } 430 }
431 if ((dst->raw = calloc(1, src->length)) == NULL) { 431 if ((dst->raw = calloc(1, src->length)) == NULL) {
432 (void) fprintf(stderr, "__ops_copy_packet: bad alloc\n"); 432 (void) fprintf(stderr, "__ops_copy_packet: bad alloc\n");
433 } else { 433 } else {
434 dst->length = src->length; 434 dst->length = src->length;
435 (void) memcpy(dst->raw, src->raw, src->length); 435 (void) memcpy(dst->raw, src->raw, src->length);
436 } 436 }
437 return dst; 437 return dst;
438} 438}
439 439
440/** 440/**
441\ingroup Core_Keys 441\ingroup Core_Keys
442\brief Add User ID to key 442\brief Add User ID to key
443\param key Key to which to add User ID 443\param key Key to which to add User ID
444\param userid User ID to add 444\param userid User ID to add
445\return Pointer to new User ID 445\return Pointer to new User ID
446*/ 446*/
447uint8_t * 447uint8_t *
448__ops_add_userid(__ops_key_t *key, const uint8_t *userid) 448__ops_add_userid(__ops_key_t *key, const uint8_t *userid)
449{ 449{
450 uint8_t **uidp; 450 uint8_t **uidp;
451 451
452 EXPAND_ARRAY(key, uid); 452 EXPAND_ARRAY(key, uid);
453 /* initialise new entry in array */ 453 /* initialise new entry in array */
454 uidp = &key->uids[key->uidc++]; 454 uidp = &key->uids[key->uidc++];
455 *uidp = NULL; 455 *uidp = NULL;
456 /* now copy it */ 456 /* now copy it */
457 return __ops_copy_userid(uidp, userid); 457 return __ops_copy_userid(uidp, userid);
458} 458}
459 459
460void print_packet_hex(const __ops_subpacket_t *pkt); 460void print_packet_hex(const __ops_subpacket_t *pkt);
461 461
462/** 462/**
463\ingroup Core_Keys 463\ingroup Core_Keys
464\brief Add packet to key 464\brief Add packet to key
465\param keydata Key to which to add packet 465\param keydata Key to which to add packet
466\param packet Packet to add 466\param packet Packet to add
467\return Pointer to new packet 467\return Pointer to new packet
468*/ 468*/
469__ops_subpacket_t * 469__ops_subpacket_t *
470__ops_add_subpacket(__ops_key_t *keydata, const __ops_subpacket_t *packet) 470__ops_add_subpacket(__ops_key_t *keydata, const __ops_subpacket_t *packet)
471{ 471{
472 __ops_subpacket_t *subpktp; 472 __ops_subpacket_t *subpktp;
473 473
474 EXPAND_ARRAY(keydata, packet); 474 EXPAND_ARRAY(keydata, packet);
475 /* initialise new entry in array */ 475 /* initialise new entry in array */
476 subpktp = &keydata->packets[keydata->packetc++]; 476 subpktp = &keydata->packets[keydata->packetc++];
477 subpktp->length = 0; 477 subpktp->length = 0;
478 subpktp->raw = NULL; 478 subpktp->raw = NULL;
479 /* now copy it */ 479 /* now copy it */
480 return __ops_copy_packet(subpktp, packet); 480 return __ops_copy_packet(subpktp, packet);
481} 481}
482 482
483/** 483/**
484\ingroup Core_Keys 484\ingroup Core_Keys
485\brief Add selfsigned User ID to key 485\brief Add selfsigned User ID to key
486\param keydata Key to which to add user ID 486\param keydata Key to which to add user ID
487\param userid Self-signed User ID to add 487\param userid Self-signed User ID to add
488\return 1 if OK; else 0 488\return 1 if OK; else 0
489*/ 489*/
490unsigned  490unsigned
491__ops_add_selfsigned_userid(__ops_key_t *key, uint8_t *userid) 491__ops_add_selfsigned_userid(__ops_key_t *key, uint8_t *userid)
492{ 492{
493 __ops_create_sig_t *sig; 493 __ops_create_sig_t *sig;
494 __ops_subpacket_t sigpacket; 494 __ops_subpacket_t sigpacket;
495 __ops_memory_t *mem_userid = NULL; 495 __ops_memory_t *mem_userid = NULL;
496 __ops_output_t *useridoutput = NULL; 496 __ops_output_t *useridoutput = NULL;
497 __ops_memory_t *mem_sig = NULL; 497 __ops_memory_t *mem_sig = NULL;
498 __ops_output_t *sigoutput = NULL; 498 __ops_output_t *sigoutput = NULL;
499 499
500 /* 500 /*
501 * create signature packet for this userid 501 * create signature packet for this userid
502 */ 502 */
503 503
504 /* create userid pkt */ 504 /* create userid pkt */
505 __ops_setup_memory_write(&useridoutput, &mem_userid, 128); 505 __ops_setup_memory_write(&useridoutput, &mem_userid, 128);
506 __ops_write_struct_userid(useridoutput, userid); 506 __ops_write_struct_userid(useridoutput, userid);
507 507
508 /* create sig for this pkt */ 508 /* create sig for this pkt */
509 sig = __ops_create_sig_new(); 509 sig = __ops_create_sig_new();
510 __ops_sig_start_key_sig(sig, &key->key.seckey.pubkey, userid, OPS_CERT_POSITIVE); 510 __ops_sig_start_key_sig(sig, &key->key.seckey.pubkey, userid, OPS_CERT_POSITIVE);
511 __ops_add_time(sig, (int64_t)time(NULL), "birth"); 511 __ops_add_time(sig, (int64_t)time(NULL), "birth");
512 __ops_add_issuer_keyid(sig, key->sigid); 512 __ops_add_issuer_keyid(sig, key->sigid);
513 __ops_add_primary_userid(sig, 1); 513 __ops_add_primary_userid(sig, 1);
514 __ops_end_hashed_subpkts(sig); 514 __ops_end_hashed_subpkts(sig);
515 515
516 __ops_setup_memory_write(&sigoutput, &mem_sig, 128); 516 __ops_setup_memory_write(&sigoutput, &mem_sig, 128);
517 __ops_write_sig(sigoutput, sig, &key->key.seckey.pubkey, &key->key.seckey); 517 __ops_write_sig(sigoutput, sig, &key->key.seckey.pubkey, &key->key.seckey);
518 518
519 /* add this packet to key */ 519 /* add this packet to key */
520 sigpacket.length = __ops_mem_len(mem_sig); 520 sigpacket.length = __ops_mem_len(mem_sig);
521 sigpacket.raw = __ops_mem_data(mem_sig); 521 sigpacket.raw = __ops_mem_data(mem_sig);
522 522
523 /* add userid to key */ 523 /* add userid to key */
524 (void) __ops_add_userid(key, userid); 524 (void) __ops_add_userid(key, userid);
525 (void) __ops_add_subpacket(key, &sigpacket); 525 (void) __ops_add_subpacket(key, &sigpacket);
526 526
527 /* cleanup */ 527 /* cleanup */
528 __ops_create_sig_delete(sig); 528 __ops_create_sig_delete(sig);
529 __ops_output_delete(useridoutput); 529 __ops_output_delete(useridoutput);
530 __ops_output_delete(sigoutput); 530 __ops_output_delete(sigoutput);
531 __ops_memory_free(mem_userid); 531 __ops_memory_free(mem_userid);
532 __ops_memory_free(mem_sig); 532 __ops_memory_free(mem_sig);
533 533
534 return 1; 534 return 1;
535} 535}
536 536
537/** 537/**
538\ingroup Core_Keys 538\ingroup Core_Keys
539\brief Initialise __ops_key_t 539\brief Initialise __ops_key_t
540\param keydata Keydata to initialise 540\param keydata Keydata to initialise
541\param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY 541\param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY
542*/ 542*/
543void  543void
544__ops_keydata_init(__ops_key_t *keydata, const __ops_content_enum type) 544__ops_keydata_init(__ops_key_t *keydata, const __ops_content_enum type)
545{ 545{
546 if (keydata->type != OPS_PTAG_CT_RESERVED) { 546 if (keydata->type != OPS_PTAG_CT_RESERVED) {
547 (void) fprintf(stderr, 547 (void) fprintf(stderr,
548 "__ops_keydata_init: wrong keydata type\n"); 548 "__ops_keydata_init: wrong keydata type\n");
549 } else if (type != OPS_PTAG_CT_PUBLIC_KEY && 549 } else if (type != OPS_PTAG_CT_PUBLIC_KEY &&
550 type != OPS_PTAG_CT_SECRET_KEY) { 550 type != OPS_PTAG_CT_SECRET_KEY) {
551 (void) fprintf(stderr, "__ops_keydata_init: wrong type\n"); 551 (void) fprintf(stderr, "__ops_keydata_init: wrong type\n");
552 } else { 552 } else {
553 keydata->type = type; 553 keydata->type = type;
554 } 554 }
555} 555}
556 556
557/* used to point to data during keyring read */ 557/* used to point to data during keyring read */
558typedef struct keyringcb_t { 558typedef struct keyringcb_t {
559 __ops_keyring_t *keyring; /* the keyring we're reading */ 559 __ops_keyring_t *keyring; /* the keyring we're reading */
560} keyringcb_t; 560} keyringcb_t;
561 561
562 562
563static __ops_cb_ret_t 563static __ops_cb_ret_t
564cb_keyring_read(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo) 564cb_keyring_read(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
565{ 565{
566 __ops_keyring_t *keyring; 566 __ops_keyring_t *keyring;
567 __ops_revoke_t *revocation; 567 __ops_revoke_t *revocation;
568 __ops_key_t *key; 568 __ops_key_t *key;
569 keyringcb_t *cb; 569 keyringcb_t *cb;
570 570
571 cb = __ops_callback_arg(cbinfo); 571 cb = __ops_callback_arg(cbinfo);
572 keyring = cb->keyring; 572 keyring = cb->keyring;
573 switch (pkt->tag) { 573 switch (pkt->tag) {
574 case OPS_PARSER_PTAG: 574 case OPS_PARSER_PTAG:
575 case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: 575 case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
576 /* we get these because we didn't prompt */ 576 /* we get these because we didn't prompt */
577 break; 577 break;
578 case OPS_PTAG_CT_SIGNATURE_HEADER: 578 case OPS_PTAG_CT_SIGNATURE_HEADER:
579 key = &keyring->keys[keyring->keyc - 1]; 579 key = &keyring->keys[keyring->keyc - 1];
580 EXPAND_ARRAY(key, subsig); 580 EXPAND_ARRAY(key, subsig);
581 key->subsigs[key->subsigc].uid = key->uidc - 1; 581 key->subsigs[key->subsigc].uid = key->uidc - 1;
582 (void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig, 582 (void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig,
583 sizeof(pkt->u.sig)); 583 sizeof(pkt->u.sig));
584 key->subsigc += 1; 584 key->subsigc += 1;
585 break; 585 break;
586 case OPS_PTAG_CT_SIGNATURE: 586 case OPS_PTAG_CT_SIGNATURE:
587 key = &keyring->keys[keyring->keyc - 1]; 587 key = &keyring->keys[keyring->keyc - 1];
588 EXPAND_ARRAY(key, subsig); 588 EXPAND_ARRAY(key, subsig);
589 key->subsigs[key->subsigc].uid = key->uidc - 1; 589 key->subsigs[key->subsigc].uid = key->uidc - 1;
590 (void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig, 590 (void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig,
591 sizeof(pkt->u.sig)); 591 sizeof(pkt->u.sig));
592 key->subsigc += 1; 592 key->subsigc += 1;
593 break; 593 break;
594 case OPS_PTAG_CT_TRUST: 594 case OPS_PTAG_CT_TRUST:
595 key = &keyring->keys[keyring->keyc - 1]; 595 key = &keyring->keys[keyring->keyc - 1];
596 key->subsigs[key->subsigc - 1].trustlevel = pkt->u.ss_trust.level; 596 key->subsigs[key->subsigc - 1].trustlevel = pkt->u.ss_trust.level;
597 key->subsigs[key->subsigc - 1].trustamount = pkt->u.ss_trust.amount; 597 key->subsigs[key->subsigc - 1].trustamount = pkt->u.ss_trust.amount;
598 break; 598 break;
599 case OPS_PTAG_SS_KEY_EXPIRY: 599 case OPS_PTAG_SS_KEY_EXPIRY:
600 EXPAND_ARRAY(keyring, key); 600 EXPAND_ARRAY(keyring, key);
601 if (keyring->keyc > 0) { 601 if (keyring->keyc > 0) {
602 keyring->keys[keyring->keyc - 1].key.pubkey.duration = pkt->u.ss_time; 602 keyring->keys[keyring->keyc - 1].key.pubkey.duration = pkt->u.ss_time;
603 } 603 }
604 break; 604 break;
605 case OPS_PTAG_SS_ISSUER_KEY_ID: 605 case OPS_PTAG_SS_ISSUER_KEY_ID:
606 key = &keyring->keys[keyring->keyc - 1]; 606 key = &keyring->keys[keyring->keyc - 1];
607 (void) memcpy(&key->subsigs[key->subsigc - 1].sig.info.signer_id, 607 (void) memcpy(&key->subsigs[key->subsigc - 1].sig.info.signer_id,
608 pkt->u.ss_issuer, 608 pkt->u.ss_issuer,
609 sizeof(pkt->u.ss_issuer)); 609 sizeof(pkt->u.ss_issuer));
610 key->subsigs[key->subsigc - 1].sig.info.signer_id_set = 1; 610 key->subsigs[key->subsigc - 1].sig.info.signer_id_set = 1;
611 break; 611 break;
612 case OPS_PTAG_SS_CREATION_TIME: 612 case OPS_PTAG_SS_CREATION_TIME:
613 key = &keyring->keys[keyring->keyc - 1]; 613 key = &keyring->keys[keyring->keyc - 1];
614 key->subsigs[key->subsigc - 1].sig.info.birthtime = pkt->u.ss_time; 614 key->subsigs[key->subsigc - 1].sig.info.birthtime = pkt->u.ss_time;
615 key->subsigs[key->subsigc - 1].sig.info.birthtime_set = 1; 615 key->subsigs[key->subsigc - 1].sig.info.birthtime_set = 1;
616 break; 616 break;
617 case OPS_PTAG_SS_EXPIRATION_TIME: 617 case OPS_PTAG_SS_EXPIRATION_TIME:
618 key = &keyring->keys[keyring->keyc - 1]; 618 key = &keyring->keys[keyring->keyc - 1];
619 key->subsigs[key->subsigc - 1].sig.info.duration = pkt->u.ss_time; 619 key->subsigs[key->subsigc - 1].sig.info.duration = pkt->u.ss_time;
620 key->subsigs[key->subsigc - 1].sig.info.duration_set = 1; 620 key->subsigs[key->subsigc - 1].sig.info.duration_set = 1;
621 break; 621 break;
622 case OPS_PTAG_SS_PRIMARY_USER_ID: 622 case OPS_PTAG_SS_PRIMARY_USER_ID:
623 key = &keyring->keys[keyring->keyc - 1]; 623 key = &keyring->keys[keyring->keyc - 1];
624 key->uid0 = key->uidc - 1; 624 key->uid0 = key->uidc - 1;
625 break; 625 break;
626 case OPS_PTAG_SS_REVOCATION_REASON: 626 case OPS_PTAG_SS_REVOCATION_REASON:
627 key = &keyring->keys[keyring->keyc - 1]; 627 key = &keyring->keys[keyring->keyc - 1];
628 if (key->uidc == 0) { 628 if (key->uidc == 0) {
629 /* revoke whole key */ 629 /* revoke whole key */
630 key->revoked = 1; 630 key->revoked = 1;
631 revocation = &key->revocation; 631 revocation = &key->revocation;
632 } else { 632 } else {
633 /* revoke the user id */ 633 /* revoke the user id */
634 EXPAND_ARRAY(key, revoke); 634 EXPAND_ARRAY(key, revoke);
635 revocation = &key->revokes[key->revokec]; 635 revocation = &key->revokes[key->revokec];
636 key->revokes[key->revokec].uid = key->uidc - 1; 636 key->revokes[key->revokec].uid = key->uidc - 1;
637 key->revokec += 1; 637 key->revokec += 1;
638 } 638 }
639 revocation->code = pkt->u.ss_revocation.code; 639 revocation->code = pkt->u.ss_revocation.code;
640 revocation->reason = netpgp_strdup(__ops_show_ss_rr_code(pkt->u.ss_revocation.code)); 640 revocation->reason = netpgp_strdup(__ops_show_ss_rr_code(pkt->u.ss_revocation.code));
641 break; 641 break;
642 case OPS_PTAG_CT_SIGNATURE_FOOTER: 642 case OPS_PTAG_CT_SIGNATURE_FOOTER:
643 case OPS_PARSER_ERRCODE: 643 case OPS_PARSER_ERRCODE:
644 break; 644 break;
645 645
646 default: 646 default:
647 break; 647 break;
648 } 648 }
649 649
650 return OPS_RELEASE_MEMORY; 650 return OPS_RELEASE_MEMORY;
651} 651}
652 652
653/** 653/**
654 \ingroup HighLevel_KeyringRead 654 \ingroup HighLevel_KeyringRead
655 655
656 \brief Reads a keyring from a file 656 \brief Reads a keyring from a file
657 657
658 \param keyring Pointer to an existing __ops_keyring_t struct 658 \param keyring Pointer to an existing __ops_keyring_t struct
659 \param armour 1 if file is armoured; else 0 659 \param armour 1 if file is armoured; else 0
660 \param filename Filename of keyring to be read 660 \param filename Filename of keyring to be read
661 661
662 \return __ops 1 if OK; 0 on error 662 \return __ops 1 if OK; 0 on error
663 663
664 \note Keyring struct must already exist. 664 \note Keyring struct must already exist.
665 665
666 \note Can be used with either a public or secret keyring. 666 \note Can be used with either a public or secret keyring.
667 667
668 \note You must call __ops_keyring_free() after usage to free alloc-ed memory. 668 \note You must call __ops_keyring_free() after usage to free alloc-ed memory.
669 669
670 \note If you call this twice on the same keyring struct, without calling 670 \note If you call this twice on the same keyring struct, without calling
671 __ops_keyring_free() between these calls, you will introduce a memory leak. 671 __ops_keyring_free() between these calls, you will introduce a memory leak.
672 672
673 \sa __ops_keyring_read_from_mem() 673 \sa __ops_keyring_read_from_mem()
674 \sa __ops_keyring_free() 674 \sa __ops_keyring_free()
675 675
676*/ 676*/
677 677
678unsigned  678unsigned
679__ops_keyring_fileread(__ops_keyring_t *keyring, 679__ops_keyring_fileread(__ops_keyring_t *keyring,
680 const unsigned armour, 680 const unsigned armour,
681 const char *filename) 681 const char *filename)
682{ 682{
683 __ops_stream_t *stream; 683 __ops_stream_t *stream;
684 keyringcb_t cb; 684 keyringcb_t cb;
685 unsigned res = 1; 685 unsigned res = 1;
686 int fd; 686 int fd;
687 687
688 (void) memset(&cb, 0x0, sizeof(cb)); 688 (void) memset(&cb, 0x0, sizeof(cb));
689 cb.keyring = keyring; 689 cb.keyring = keyring;
690 stream = __ops_new(sizeof(*stream)); 690 stream = __ops_new(sizeof(*stream));
691 691
692 /* add this for the moment, */ 692 /* add this for the moment, */
693 /* 693 /*
694 * \todo need to fix the problems with reading signature subpackets 694 * \todo need to fix the problems with reading signature subpackets
695 * later 695 * later
696 */ 696 */
697 697
698 /* __ops_parse_options(parse,OPS_PTAG_SS_ALL,OPS_PARSE_RAW); */ 698 /* __ops_parse_options(parse,OPS_PTAG_SS_ALL,OPS_PARSE_RAW); */
699 __ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); 699 __ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
700 700
701#ifdef O_BINARY 701#ifdef O_BINARY
702 fd = open(filename, O_RDONLY | O_BINARY); 702 fd = open(filename, O_RDONLY | O_BINARY);
703#else 703#else
704 fd = open(filename, O_RDONLY); 704 fd = open(filename, O_RDONLY);
705#endif 705#endif
706 if (fd < 0) { 706 if (fd < 0) {
707 __ops_stream_delete(stream); 707 __ops_stream_delete(stream);
708 perror(filename); 708 perror(filename);
709 return 0; 709 return 0;
710 } 710 }
711#ifdef USE_MMAP_FOR_FILES 711#ifdef USE_MMAP_FOR_FILES
712 __ops_reader_set_mmap(stream, fd); 712 __ops_reader_set_mmap(stream, fd);
713#else 713#else
714 __ops_reader_set_fd(stream, fd); 714 __ops_reader_set_fd(stream, fd);
715#endif 715#endif
716 716
717 __ops_set_callback(stream, cb_keyring_read, &cb); 717 __ops_set_callback(stream, cb_keyring_read, &cb);
718 718
719 if (armour) { 719 if (armour) {
720 __ops_reader_push_dearmour(stream); 720 __ops_reader_push_dearmour(stream);
721 } 721 }
722 res = __ops_parse_and_accumulate(keyring, stream); 722 res = __ops_parse_and_accumulate(keyring, stream);
723 __ops_print_errors(__ops_stream_get_errors(stream)); 723 __ops_print_errors(__ops_stream_get_errors(stream));
724 724
725 if (armour) { 725 if (armour) {
726 __ops_reader_pop_dearmour(stream); 726 __ops_reader_pop_dearmour(stream);
727 } 727 }
728 728
729 (void)close(fd); 729 (void)close(fd);
730 730
731 __ops_stream_delete(stream); 731 __ops_stream_delete(stream);
732 732
733 return res; 733 return res;
734} 734}
735 735
736/** 736/**
737 \ingroup HighLevel_KeyringRead 737 \ingroup HighLevel_KeyringRead
738 738
739 \brief Reads a keyring from memory 739 \brief Reads a keyring from memory
740 740
741 \param keyring Pointer to existing __ops_keyring_t struct 741 \param keyring Pointer to existing __ops_keyring_t struct
742 \param armour 1 if file is armoured; else 0 742 \param armour 1 if file is armoured; else 0
743 \param mem Pointer to a __ops_memory_t struct containing keyring to be read 743 \param mem Pointer to a __ops_memory_t struct containing keyring to be read
744 744
745 \return __ops 1 if OK; 0 on error 745 \return __ops 1 if OK; 0 on error
746 746
747 \note Keyring struct must already exist. 747 \note Keyring struct must already exist.
748 748
749 \note Can be used with either a public or secret keyring. 749 \note Can be used with either a public or secret keyring.
750 750
751 \note You must call __ops_keyring_free() after usage to free alloc-ed memory. 751 \note You must call __ops_keyring_free() after usage to free alloc-ed memory.
752 752
753 \note If you call this twice on the same keyring struct, without calling 753 \note If you call this twice on the same keyring struct, without calling
754 __ops_keyring_free() between these calls, you will introduce a memory leak. 754 __ops_keyring_free() between these calls, you will introduce a memory leak.
755 755
756 \sa __ops_keyring_fileread 756 \sa __ops_keyring_fileread
757 \sa __ops_keyring_free 757 \sa __ops_keyring_free
758*/ 758*/
759unsigned  759unsigned
760__ops_keyring_read_from_mem(__ops_io_t *io, 760__ops_keyring_read_from_mem(__ops_io_t *io,
761 __ops_keyring_t *keyring, 761 __ops_keyring_t *keyring,
762 const unsigned armour, 762 const unsigned armour,
763 __ops_memory_t *mem) 763 __ops_memory_t *mem)
764{ 764{
765 __ops_stream_t *stream; 765 __ops_stream_t *stream;
766 const unsigned noaccum = 0; 766 const unsigned noaccum = 0;
767 keyringcb_t cb; 767 keyringcb_t cb;
768 unsigned res; 768 unsigned res;
769 769
770 (void) memset(&cb, 0x0, sizeof(cb)); 770 (void) memset(&cb, 0x0, sizeof(cb));
771 cb.keyring = keyring; 771 cb.keyring = keyring;
772 stream = __ops_new(sizeof(*stream)); 772 stream = __ops_new(sizeof(*stream));
773 __ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); 773 __ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
774 __ops_setup_memory_read(io, &stream, mem, &cb, cb_keyring_read, 774 __ops_setup_memory_read(io, &stream, mem, &cb, cb_keyring_read,
775 noaccum); 775 noaccum);
776 if (armour) { 776 if (armour) {
777 __ops_reader_push_dearmour(stream); 777 __ops_reader_push_dearmour(stream);
778 } 778 }
779 res = (unsigned)__ops_parse_and_accumulate(keyring, stream); 779 res = (unsigned)__ops_parse_and_accumulate(keyring, stream);
780 __ops_print_errors(__ops_stream_get_errors(stream)); 780 __ops_print_errors(__ops_stream_get_errors(stream));
781 if (armour) { 781 if (armour) {
782 __ops_reader_pop_dearmour(stream); 782 __ops_reader_pop_dearmour(stream);
783 } 783 }
784 /* don't call teardown_memory_read because memory was passed in */ 784 /* don't call teardown_memory_read because memory was passed in */
785 __ops_stream_delete(stream); 785 __ops_stream_delete(stream);
786 return res; 786 return res;
787} 787}
788 788
789/** 789/**
790 \ingroup HighLevel_KeyringRead 790 \ingroup HighLevel_KeyringRead
791 791
792 \brief Frees keyring's contents (but not keyring itself) 792 \brief Frees keyring's contents (but not keyring itself)
793 793
794 \param keyring Keyring whose data is to be freed 794 \param keyring Keyring whose data is to be freed
795 795
796 \note This does not free keyring itself, just the memory alloc-ed in it. 796 \note This does not free keyring itself, just the memory alloc-ed in it.
797 */ 797 */
798void  798void
799__ops_keyring_free(__ops_keyring_t *keyring) 799__ops_keyring_free(__ops_keyring_t *keyring)
800{ 800{
801 (void)free(keyring->keys); 801 (void)free(keyring->keys);
802 keyring->keys = NULL; 802 keyring->keys = NULL;
803 keyring->keyc = keyring->keyvsize = 0; 803 keyring->keyc = keyring->keyvsize = 0;
804} 804}
805 805
806/** 806/**
807 \ingroup HighLevel_KeyringFind 807 \ingroup HighLevel_KeyringFind
808 808
809 \brief Finds key in keyring from its Key ID 809 \brief Finds key in keyring from its Key ID
810 810
811 \param keyring Keyring to be searched 811 \param keyring Keyring to be searched
812 \param keyid ID of required key 812 \param keyid ID of required key
813 813
814 \return Pointer to key, if found; NULL, if not found 814 \return Pointer to key, if found; NULL, if not found
815 815
816 \note This returns a pointer to the key inside the given keyring, 816 \note This returns a pointer to the key inside the given keyring,
817 not a copy. Do not free it after use. 817 not a copy. Do not free it after use.
818 818
819*/ 819*/
820const __ops_key_t * 820const __ops_key_t *
821__ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring, 821__ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring,
822 const uint8_t *keyid, unsigned *from, __ops_pubkey_t **pubkey) 822 const uint8_t *keyid, unsigned *from, __ops_pubkey_t **pubkey)
823{ 823{
824 uint8_t nullid[OPS_KEY_ID_SIZE]; 824 uint8_t nullid[OPS_KEY_ID_SIZE];
825 825
826 (void) memset(nullid, 0x0, sizeof(nullid)); 826 (void) memset(nullid, 0x0, sizeof(nullid));
827 for ( ; keyring && *from < keyring->keyc; *from += 1) { 827 for ( ; keyring && *from < keyring->keyc; *from += 1) {
828 if (__ops_get_debug_level(__FILE__)) { 828 if (__ops_get_debug_level(__FILE__)) {
829 hexdump(io->errs, "keyring keyid", keyring->keys[*from].sigid, OPS_KEY_ID_SIZE); 829 hexdump(io->errs, "keyring keyid", keyring->keys[*from].sigid, OPS_KEY_ID_SIZE);
830 hexdump(io->errs, "keyid", keyid, OPS_KEY_ID_SIZE); 830 hexdump(io->errs, "keyid", keyid, OPS_KEY_ID_SIZE);
831 } 831 }
832 if (memcmp(keyring->keys[*from].sigid, keyid, OPS_KEY_ID_SIZE) == 0 || 832 if (memcmp(keyring->keys[*from].sigid, keyid, OPS_KEY_ID_SIZE) == 0 ||
833 memcmp(&keyring->keys[*from].sigid[OPS_KEY_ID_SIZE / 2], 833 memcmp(&keyring->keys[*from].sigid[OPS_KEY_ID_SIZE / 2],
834 keyid, OPS_KEY_ID_SIZE / 2) == 0) { 834 keyid, OPS_KEY_ID_SIZE / 2) == 0) {
835 if (pubkey) { 835 if (pubkey) {
836 *pubkey = &keyring->keys[*from].key.pubkey; 836 *pubkey = &keyring->keys[*from].key.pubkey;
837 } 837 }
838 return &keyring->keys[*from]; 838 return &keyring->keys[*from];
839 } 839 }
840 if (memcmp(&keyring->keys[*from].encid, nullid, sizeof(nullid)) == 0) { 840 if (memcmp(&keyring->keys[*from].encid, nullid, sizeof(nullid)) == 0) {
841 continue; 841 continue;
842 } 842 }
843 if (memcmp(&keyring->keys[*from].encid, keyid, OPS_KEY_ID_SIZE) == 0 || 843 if (memcmp(&keyring->keys[*from].encid, keyid, OPS_KEY_ID_SIZE) == 0 ||
844 memcmp(&keyring->keys[*from].encid[OPS_KEY_ID_SIZE / 2], keyid, OPS_KEY_ID_SIZE / 2) == 0) { 844 memcmp(&keyring->keys[*from].encid[OPS_KEY_ID_SIZE / 2], keyid, OPS_KEY_ID_SIZE / 2) == 0) {
845 if (pubkey) { 845 if (pubkey) {
846 *pubkey = &keyring->keys[*from].enckey; 846 *pubkey = &keyring->keys[*from].enckey;
847 } 847 }
848 return &keyring->keys[*from]; 848 return &keyring->keys[*from];
849 } 849 }
850 } 850 }
851 return NULL; 851 return NULL;
852} 852}
853 853
854/* convert a string keyid into a binary keyid */ 854/* convert a string keyid into a binary keyid */
855static void 855static void
856str2keyid(const char *userid, uint8_t *keyid, size_t len) 856str2keyid(const char *userid, uint8_t *keyid, size_t len)
857{ 857{
858 static const char *uppers = "0123456789ABCDEF"; 858 static const char *uppers = "0123456789ABCDEF";
859 static const char *lowers = "0123456789abcdef"; 859 static const char *lowers = "0123456789abcdef";
860 const char *hi; 860 const char *hi;
861 const char *lo; 861 const char *lo;
862 uint8_t hichar; 862 uint8_t hichar;
863 uint8_t lochar; 863 uint8_t lochar;
864 size_t j; 864 size_t j;
865 int i; 865 int i;
866 866
867 for (i = 0, j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) { 867 for (i = 0, j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) {
868 if ((hi = strchr(uppers, userid[i])) == NULL) { 868 if ((hi = strchr(uppers, userid[i])) == NULL) {
869 if ((hi = strchr(lowers, userid[i])) == NULL) { 869 if ((hi = strchr(lowers, userid[i])) == NULL) {
870 break; 870 break;
871 } 871 }
872 hichar = (uint8_t)(hi - lowers); 872 hichar = (uint8_t)(hi - lowers);
873 } else { 873 } else {
874 hichar = (uint8_t)(hi - uppers); 874 hichar = (uint8_t)(hi - uppers);
875 } 875 }
876 if ((lo = strchr(uppers, userid[i + 1])) == NULL) { 876 if ((lo = strchr(uppers, userid[i + 1])) == NULL) {
877 if ((lo = strchr(lowers, userid[i + 1])) == NULL) { 877 if ((lo = strchr(lowers, userid[i + 1])) == NULL) {
878 break; 878 break;
879 } 879 }
880 lochar = (uint8_t)(lo - lowers); 880 lochar = (uint8_t)(lo - lowers);
881 } else { 881 } else {
882 lochar = (uint8_t)(lo - uppers); 882 lochar = (uint8_t)(lo - uppers);
883 } 883 }
884 keyid[j] = (hichar << 4) | (lochar); 884 keyid[j] = (hichar << 4) | (lochar);
885 } 885 }
886 keyid[j] = 0x0; 886 keyid[j] = 0x0;
887} 887}
888 888
889/* return the next key which matches, starting searching at *from */ 889/* return the next key which matches, starting searching at *from */
890static const __ops_key_t * 890static const __ops_key_t *
891getkeybyname(__ops_io_t *io, 891getkeybyname(__ops_io_t *io,
892 const __ops_keyring_t *keyring, 892 const __ops_keyring_t *keyring,
893 const char *name, 893 const char *name,
894 unsigned *from) 894 unsigned *from)
895{ 895{
896 const __ops_key_t *kp; 896 const __ops_key_t *kp;
897 uint8_t **uidp; 897 uint8_t **uidp;
898 unsigned i = 0; 898 unsigned i = 0;
899 __ops_key_t *keyp; 899 __ops_key_t *keyp;
900 unsigned savedstart; 900 unsigned savedstart;
901 regex_t r; 901 regex_t r;
902 uint8_t keyid[OPS_KEY_ID_SIZE + 1]; 902 uint8_t keyid[OPS_KEY_ID_SIZE + 1];
903 size_t len; 903 size_t len;
904 904
905 if (!keyring) { 905 if (!keyring || !name || !from) {
906 return NULL; 906 return NULL;
907 } 907 }
908 len = strlen(name); 908 len = strlen(name);
909 if (__ops_get_debug_level(__FILE__)) { 909 if (__ops_get_debug_level(__FILE__)) {
910 (void) fprintf(io->outs, "[%u] name '%s', len %zu\n", 910 (void) fprintf(io->outs, "[%u] name '%s', len %zu\n",
911 *from, name, len); 911 *from, name, len);
912 } 912 }
913 /* first try name as a keyid */ 913 /* first try name as a keyid */
914 (void) memset(keyid, 0x0, sizeof(keyid)); 914 (void) memset(keyid, 0x0, sizeof(keyid));
915 str2keyid(name, keyid, sizeof(keyid)); 915 str2keyid(name, keyid, sizeof(keyid));
916 if (__ops_get_debug_level(__FILE__)) { 916 if (__ops_get_debug_level(__FILE__)) {
917 hexdump(io->outs, "keyid", keyid, 4); 917 hexdump(io->outs, "keyid", keyid, 4);
918 } 918 }
919 savedstart = *from; 919 savedstart = *from;
920 if ((kp = __ops_getkeybyid(io, keyring, keyid, from, NULL)) != NULL) { 920 if ((kp = __ops_getkeybyid(io, keyring, keyid, from, NULL)) != NULL) {
921 return kp; 921 return kp;
922 } 922 }
923 *from = savedstart; 923 *from = savedstart;
924 if (__ops_get_debug_level(__FILE__)) { 924 if (__ops_get_debug_level(__FILE__)) {
925 (void) fprintf(io->outs, "regex match '%s' from %u\n", 925 (void) fprintf(io->outs, "regex match '%s' from %u\n",
926 name, *from); 926 name, *from);
927 } 927 }
928 /* match on full name or email address as a NOSUB, ICASE regexp */ 928 /* match on full name or email address as a NOSUB, ICASE regexp */
929 (void) regcomp(&r, name, REG_EXTENDED | REG_ICASE); 929 (void) regcomp(&r, name, REG_EXTENDED | REG_ICASE);
930 for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) { 930 for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) {
931 uidp = keyp->uids; 931 uidp = keyp->uids;
932 for (i = 0 ; i < keyp->uidc; i++, uidp++) { 932 for (i = 0 ; i < keyp->uidc; i++, uidp++) {
933 if (regexec(&r, (char *)*uidp, 0, NULL, 0) == 0) { 933 if (regexec(&r, (char *)*uidp, 0, NULL, 0) == 0) {
934 if (__ops_get_debug_level(__FILE__)) { 934 if (__ops_get_debug_level(__FILE__)) {
935 (void) fprintf(io->outs, 935 (void) fprintf(io->outs,
936 "MATCHED keyid \"%s\" len %" PRIsize "u\n", 936 "MATCHED keyid \"%s\" len %" PRIsize "u\n",
937 (char *) *uidp, len); 937 (char *) *uidp, len);
938 } 938 }
939 regfree(&r); 939 regfree(&r);
940 return keyp; 940 return keyp;
941 } 941 }
942 } 942 }
943 } 943 }
944 regfree(&r); 944 regfree(&r);
945 return NULL; 945 return NULL;
946} 946}
947 947
948/** 948/**
949 \ingroup HighLevel_KeyringFind 949 \ingroup HighLevel_KeyringFind
950 950
951 \brief Finds key from its User ID 951 \brief Finds key from its User ID
952 952
953 \param keyring Keyring to be searched 953 \param keyring Keyring to be searched
954 \param userid User ID of required key 954 \param userid User ID of required key
955 955
956 \return Pointer to Key, if found; NULL, if not found 956 \return Pointer to Key, if found; NULL, if not found
957 957
958 \note This returns a pointer to the key inside the keyring, not a 958 \note This returns a pointer to the key inside the keyring, not a
959 copy. Do not free it. 959 copy. Do not free it.
960 960
961*/ 961*/
962const __ops_key_t * 962const __ops_key_t *
963__ops_getkeybyname(__ops_io_t *io, 963__ops_getkeybyname(__ops_io_t *io,
964 const __ops_keyring_t *keyring, 964 const __ops_keyring_t *keyring,
965 const char *name) 965 const char *name)
966{ 966{
967 unsigned from; 967 unsigned from;
968 968
969 from = 0; 969 from = 0;
970 return getkeybyname(io, keyring, name, &from); 970 return getkeybyname(io, keyring, name, &from);
971} 971}
972 972
973const __ops_key_t * 973const __ops_key_t *
974__ops_getnextkeybyname(__ops_io_t *io, 974__ops_getnextkeybyname(__ops_io_t *io,
975 const __ops_keyring_t *keyring, 975 const __ops_keyring_t *keyring,
976 const char *name, 976 const char *name,
977 unsigned *n) 977 unsigned *n)
978{ 978{
979 return getkeybyname(io, keyring, name, n); 979 return getkeybyname(io, keyring, name, n);
980} 980}
981 981
982/** 982/**
983 \ingroup HighLevel_KeyringList 983 \ingroup HighLevel_KeyringList
984 984
985 \brief Prints all keys in keyring to stdout. 985 \brief Prints all keys in keyring to stdout.
986 986
987 \param keyring Keyring to use 987 \param keyring Keyring to use
988 988
989 \return none 989 \return none
990*/ 990*/
991int 991int
992__ops_keyring_list(__ops_io_t *io, const __ops_keyring_t *keyring, const int psigs) 992__ops_keyring_list(__ops_io_t *io, const __ops_keyring_t *keyring, const int psigs)
993{ 993{
994 __ops_key_t *key; 994 __ops_key_t *key;
995 unsigned n; 995 unsigned n;
996 996
997 (void) fprintf(io->res, "%u key%s\n", keyring->keyc, 997 (void) fprintf(io->res, "%u key%s\n", keyring->keyc,
998 (keyring->keyc == 1) ? "" : "s"); 998 (keyring->keyc == 1) ? "" : "s");
999 for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) { 999 for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) {
1000 if (__ops_is_key_secret(key)) { 1000 if (__ops_is_key_secret(key)) {
1001 __ops_print_keydata(io, keyring, key, "sec", 1001 __ops_print_keydata(io, keyring, key, "sec",
1002 &key->key.seckey.pubkey, 0); 1002 &key->key.seckey.pubkey, 0);
1003 } else { 1003 } else {
1004 __ops_print_keydata(io, keyring, key, "signature ", &key->key.pubkey, psigs); 1004 __ops_print_keydata(io, keyring, key, "signature ", &key->key.pubkey, psigs);
1005 } 1005 }
1006 (void) fputc('\n', io->res); 1006 (void) fputc('\n', io->res);
1007 } 1007 }
1008 return 1; 1008 return 1;
1009} 1009}
1010 1010
1011int 1011int
1012__ops_keyring_json(__ops_io_t *io, const __ops_keyring_t *keyring, mj_t *obj, const int psigs) 1012__ops_keyring_json(__ops_io_t *io, const __ops_keyring_t *keyring, mj_t *obj, const int psigs)
1013{ 1013{
1014 __ops_key_t *key; 1014 __ops_key_t *key;
1015 unsigned n; 1015 unsigned n;
1016 1016
1017 (void) memset(obj, 0x0, sizeof(*obj)); 1017 (void) memset(obj, 0x0, sizeof(*obj));
1018 mj_create(obj, "array"); 1018 mj_create(obj, "array");
1019 obj->size = keyring->keyvsize; 1019 obj->size = keyring->keyvsize;
1020 if (__ops_get_debug_level(__FILE__)) { 1020 if (__ops_get_debug_level(__FILE__)) {
1021 (void) fprintf(io->errs, "__ops_keyring_json: vsize %u\n", obj->size); 1021 (void) fprintf(io->errs, "__ops_keyring_json: vsize %u\n", obj->size);
1022 } 1022 }
1023 if ((obj->value.v = calloc(sizeof(*obj->value.v), obj->size)) == NULL) { 1023 if ((obj->value.v = calloc(sizeof(*obj->value.v), obj->size)) == NULL) {
1024 (void) fprintf(io->errs, "calloc failure\n"); 1024 (void) fprintf(io->errs, "calloc failure\n");
1025 return 0; 1025 return 0;
1026 } 1026 }
1027 for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) { 1027 for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) {
1028 if (__ops_is_key_secret(key)) { 1028 if (__ops_is_key_secret(key)) {
1029 __ops_sprint_mj(io, keyring, key, &obj->value.v[obj->c], 1029 __ops_sprint_mj(io, keyring, key, &obj->value.v[obj->c],
1030 "sec", &key->key.seckey.pubkey, psigs); 1030 "sec", &key->key.seckey.pubkey, psigs);
1031 } else { 1031 } else {
1032 __ops_sprint_mj(io, keyring, key, &obj->value.v[obj->c], 1032 __ops_sprint_mj(io, keyring, key, &obj->value.v[obj->c],
1033 "signature ", &key->key.pubkey, psigs); 1033 "signature ", &key->key.pubkey, psigs);
1034 } 1034 }
1035 if (obj->value.v[obj->c].type != 0) { 1035 if (obj->value.v[obj->c].type != 0) {
1036 obj->c += 1; 1036 obj->c += 1;
1037 } 1037 }
1038 } 1038 }
1039 if (__ops_get_debug_level(__FILE__)) { 1039 if (__ops_get_debug_level(__FILE__)) {
1040 char *s; 1040 char *s;
1041 1041
1042 mj_asprint(&s, obj); 1042 mj_asprint(&s, obj);
1043 (void) fprintf(stderr, "__ops_keyring_json: '%s'\n", s); 1043 (void) fprintf(stderr, "__ops_keyring_json: '%s'\n", s);
1044 free(s); 1044 free(s);
1045 } 1045 }
1046 return 1; 1046 return 1;
1047} 1047}
1048 1048
1049 1049
1050/* this interface isn't right - hook into callback for getting passphrase */ 1050/* this interface isn't right - hook into callback for getting passphrase */
1051char * 1051char *
1052__ops_export_key(__ops_io_t *io, const __ops_key_t *keydata, uint8_t *passphrase) 1052__ops_export_key(__ops_io_t *io, const __ops_key_t *keydata, uint8_t *passphrase)
1053{ 1053{
1054 __ops_output_t *output; 1054 __ops_output_t *output;
1055 __ops_memory_t *mem; 1055 __ops_memory_t *mem;
1056 char *cp; 1056 char *cp;
1057 1057
1058 __OPS_USED(io); 1058 __OPS_USED(io);
1059 __ops_setup_memory_write(&output, &mem, 128); 1059 __ops_setup_memory_write(&output, &mem, 128);
1060 if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) { 1060 if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
1061 __ops_write_xfer_pubkey(output, keydata, 1); 1061 __ops_write_xfer_pubkey(output, keydata, 1);
1062 } else { 1062 } else {
1063 __ops_write_xfer_seckey(output, keydata, passphrase, 1063 __ops_write_xfer_seckey(output, keydata, passphrase,
1064 strlen((char *)passphrase), 1); 1064 strlen((char *)passphrase), 1);
1065 } 1065 }
1066 cp = netpgp_strdup(__ops_mem_data(mem)); 1066 cp = netpgp_strdup(__ops_mem_data(mem));
1067 __ops_teardown_memory_write(output, mem); 1067 __ops_teardown_memory_write(output, mem);
1068 return cp; 1068 return cp;
1069} 1069}
1070 1070
1071/* add a key to a public keyring */ 1071/* add a key to a public keyring */
1072int 1072int
1073__ops_add_to_pubring(__ops_keyring_t *keyring, const __ops_pubkey_t *pubkey, __ops_content_enum tag) 1073__ops_add_to_pubring(__ops_keyring_t *keyring, const __ops_pubkey_t *pubkey, __ops_content_enum tag)
1074{ 1074{
1075 __ops_key_t *key; 1075 __ops_key_t *key;
1076 time_t duration; 1076 time_t duration;
1077 1077
1078 if (__ops_get_debug_level(__FILE__)) { 1078 if (__ops_get_debug_level(__FILE__)) {
1079 fprintf(stderr, "__ops_add_to_pubring (type %u)\n", tag); 1079 fprintf(stderr, "__ops_add_to_pubring (type %u)\n", tag);
1080 } 1080 }
1081 switch(tag) { 1081 switch(tag) {
1082 case OPS_PTAG_CT_PUBLIC_KEY: 1082 case OPS_PTAG_CT_PUBLIC_KEY:
1083 EXPAND_ARRAY(keyring, key); 1083 EXPAND_ARRAY(keyring, key);
1084 key = &keyring->keys[keyring->keyc++]; 1084 key = &keyring->keys[keyring->keyc++];
1085 duration = key->key.pubkey.duration; 1085 duration = key->key.pubkey.duration;
1086 (void) memset(key, 0x0, sizeof(*key)); 1086 (void) memset(key, 0x0, sizeof(*key));
1087 key->type = tag; 1087 key->type = tag;
1088 __ops_keyid(key->sigid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype); 1088 __ops_keyid(key->sigid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype);
1089 __ops_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype); 1089 __ops_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype);
1090 key->key.pubkey = *pubkey; 1090 key->key.pubkey = *pubkey;
1091 key->key.pubkey.duration = duration; 1091 key->key.pubkey.duration = duration;
1092 return 1; 1092 return 1;
1093 case OPS_PTAG_CT_PUBLIC_SUBKEY: 1093 case OPS_PTAG_CT_PUBLIC_SUBKEY:
1094 /* subkey is not the first */ 1094 /* subkey is not the first */
1095 key = &keyring->keys[keyring->keyc - 1]; 1095 key = &keyring->keys[keyring->keyc - 1];
1096 __ops_keyid(key->encid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype); 1096 __ops_keyid(key->encid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype);
1097 duration = key->key.pubkey.duration; 1097 duration = key->key.pubkey.duration;
1098 (void) memcpy(&key->enckey, pubkey, sizeof(key->enckey)); 1098 (void) memcpy(&key->enckey, pubkey, sizeof(key->enckey));
1099 key->enckey.duration = duration; 1099 key->enckey.duration = duration;
1100 return 1; 1100 return 1;
1101 default: 1101 default:
1102 return 0; 1102 return 0;
1103 } 1103 }
1104} 1104}
1105 1105
1106/* add a key to a secret keyring */ 1106/* add a key to a secret keyring */
1107int 1107int
1108__ops_add_to_secring(__ops_keyring_t *keyring, const __ops_seckey_t *seckey) 1108__ops_add_to_secring(__ops_keyring_t *keyring, const __ops_seckey_t *seckey)
1109{ 1109{
1110 const __ops_pubkey_t *pubkey; 1110 const __ops_pubkey_t *pubkey;
1111 __ops_key_t *key; 1111 __ops_key_t *key;
1112 1112
1113 if (__ops_get_debug_level(__FILE__)) { 1113 if (__ops_get_debug_level(__FILE__)) {
1114 fprintf(stderr, "__ops_add_to_secring\n"); 1114 fprintf(stderr, "__ops_add_to_secring\n");
1115 } 1115 }
1116 if (keyring->keyc > 0) { 1116 if (keyring->keyc > 0) {
1117 key = &keyring->keys[keyring->keyc - 1]; 1117 key = &keyring->keys[keyring->keyc - 1];
1118 if (__ops_get_debug_level(__FILE__) && 1118 if (__ops_get_debug_level(__FILE__) &&
1119 key->key.pubkey.alg == OPS_PKA_DSA && 1119 key->key.pubkey.alg == OPS_PKA_DSA &&
1120 seckey->pubkey.alg == OPS_PKA_ELGAMAL) { 1120 seckey->pubkey.alg == OPS_PKA_ELGAMAL) {
1121 fprintf(stderr, "__ops_add_to_secring: found elgamal seckey\n"); 1121 fprintf(stderr, "__ops_add_to_secring: found elgamal seckey\n");
1122 } 1122 }
1123 } 1123 }
1124 EXPAND_ARRAY(keyring, key); 1124 EXPAND_ARRAY(keyring, key);
1125 key = &keyring->keys[keyring->keyc++]; 1125 key = &keyring->keys[keyring->keyc++];
1126 (void) memset(key, 0x0, sizeof(*key)); 1126 (void) memset(key, 0x0, sizeof(*key));
1127 pubkey = &seckey->pubkey; 1127 pubkey = &seckey->pubkey;
1128 __ops_keyid(key->sigid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype); 1128 __ops_keyid(key->sigid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype);
1129 __ops_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype); 1129 __ops_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype);
1130 key->type = OPS_PTAG_CT_SECRET_KEY; 1130 key->type = OPS_PTAG_CT_SECRET_KEY;
1131 key->key.seckey = *seckey; 1131 key->key.seckey = *seckey;
1132 if (__ops_get_debug_level(__FILE__)) { 1132 if (__ops_get_debug_level(__FILE__)) {
1133 fprintf(stderr, "__ops_add_to_secring: keyc %u\n", keyring->keyc); 1133 fprintf(stderr, "__ops_add_to_secring: keyc %u\n", keyring->keyc);
1134 } 1134 }
1135 return 1; 1135 return 1;
1136} 1136}
1137 1137
1138/* append one keyring to another */ 1138/* append one keyring to another */
1139int 1139int
1140__ops_append_keyring(__ops_keyring_t *keyring, __ops_keyring_t *newring) 1140__ops_append_keyring(__ops_keyring_t *keyring, __ops_keyring_t *newring)
1141{ 1141{
1142 unsigned i; 1142 unsigned i;
1143 1143
1144 for (i = 0 ; i < newring->keyc ; i++) { 1144 for (i = 0 ; i < newring->keyc ; i++) {
1145 EXPAND_ARRAY(keyring, key); 1145 EXPAND_ARRAY(keyring, key);
1146 (void) memcpy(&keyring->keys[keyring->keyc], &newring->keys[i], 1146 (void) memcpy(&keyring->keys[keyring->keyc], &newring->keys[i],
1147 sizeof(newring->keys[i])); 1147 sizeof(newring->keys[i]));
1148 keyring->keyc += 1; 1148 keyring->keyc += 1;
1149 } 1149 }
1150 return 1; 1150 return 1;
1151} 1151}

cvs diff -r1.77 -r1.78 src/crypto/external/bsd/netpgp/dist/src/lib/netpgp.c (switch to unified diff)

--- src/crypto/external/bsd/netpgp/dist/src/lib/netpgp.c 2010/10/19 00:00:00 1.77
+++ src/crypto/external/bsd/netpgp/dist/src/lib/netpgp.c 2010/10/31 19:45:53 1.78
@@ -1,1424 +1,1426 @@ @@ -1,1424 +1,1426 @@
1/*- 1/*-
2 * Copyright (c) 2009 The NetBSD Foundation, Inc. 2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * This code is derived from software contributed to The NetBSD Foundation 5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org) 6 * by Alistair Crooks (agc@NetBSD.org)
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE. 27 * POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29#include "config.h" 29#include "config.h"
30 30
31#ifdef HAVE_SYS_CDEFS_H 31#ifdef HAVE_SYS_CDEFS_H
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#endif 33#endif
34 34
35#if defined(__NetBSD__) 35#if defined(__NetBSD__)
36__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); 36__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
37__RCSID("$NetBSD: netpgp.c,v 1.77 2010/10/19 00:00:00 agc Exp $"); 37__RCSID("$NetBSD: netpgp.c,v 1.78 2010/10/31 19:45:53 stacktic Exp $");
38#endif 38#endif
39 39
40#include <sys/types.h> 40#include <sys/types.h>
41#include <sys/stat.h> 41#include <sys/stat.h>
42#include <sys/param.h> 42#include <sys/param.h>
43#include <sys/mman.h> 43#include <sys/mman.h>
44 44
45#ifdef HAVE_SYS_RESOURCE_H 45#ifdef HAVE_SYS_RESOURCE_H
46#include <sys/resource.h> 46#include <sys/resource.h>
47#endif 47#endif
48 48
49#ifdef HAVE_FCNTL_H 49#ifdef HAVE_FCNTL_H
50#include <fcntl.h> 50#include <fcntl.h>
51#endif 51#endif
52 52
53#include <errno.h> 53#include <errno.h>
54#include <regex.h> 54#include <regex.h>
55#include <stdarg.h> 55#include <stdarg.h>
56#include <stdlib.h> 56#include <stdlib.h>
57#include <string.h> 57#include <string.h>
58#include <time.h> 58#include <time.h>
59 59
60#ifdef HAVE_UNISTD_H 60#ifdef HAVE_UNISTD_H
61#include <unistd.h> 61#include <unistd.h>
62#endif 62#endif
63 63
64#include <errno.h> 64#include <errno.h>
65 65
66#ifdef HAVE_LIMITS_H 66#ifdef HAVE_LIMITS_H
67#include <limits.h> 67#include <limits.h>
68#endif 68#endif
69 69
70#include <netpgp.h> 70#include <netpgp.h>
71 71
72#include "packet.h" 72#include "packet.h"
73#include "packet-parse.h" 73#include "packet-parse.h"
74#include "keyring.h" 74#include "keyring.h"
75#include "errors.h" 75#include "errors.h"
76#include "packet-show.h" 76#include "packet-show.h"
77#include "create.h" 77#include "create.h"
78#include "netpgpsdk.h" 78#include "netpgpsdk.h"
79#include "memory.h" 79#include "memory.h"
80#include "validate.h" 80#include "validate.h"
81#include "readerwriter.h" 81#include "readerwriter.h"
82#include "netpgpdefs.h" 82#include "netpgpdefs.h"
83#include "crypto.h" 83#include "crypto.h"
84#include "ops-ssh.h" 84#include "ops-ssh.h"
85#include "defs.h" 85#include "defs.h"
86 86
87/* read any gpg config file */ 87/* read any gpg config file */
88static int 88static int
89conffile(netpgp_t *netpgp, char *homedir, char *userid, size_t length) 89conffile(netpgp_t *netpgp, char *homedir, char *userid, size_t length)
90{ 90{
91 regmatch_t matchv[10]; 91 regmatch_t matchv[10];
92 regex_t keyre; 92 regex_t keyre;
93 char buf[BUFSIZ]; 93 char buf[BUFSIZ];
94 FILE *fp; 94 FILE *fp;
95 95
96 __OPS_USED(netpgp); 96 __OPS_USED(netpgp);
97 (void) snprintf(buf, sizeof(buf), "%s/gpg.conf", homedir); 97 (void) snprintf(buf, sizeof(buf), "%s/gpg.conf", homedir);
98 if ((fp = fopen(buf, "r")) == NULL) { 98 if ((fp = fopen(buf, "r")) == NULL) {
99 return 0; 99 return 0;
100 } 100 }
101 (void) memset(&keyre, 0x0, sizeof(keyre)); 101 (void) memset(&keyre, 0x0, sizeof(keyre));
102 (void) regcomp(&keyre, "^[ \t]*default-key[ \t]+([0-9a-zA-F]+)", 102 (void) regcomp(&keyre, "^[ \t]*default-key[ \t]+([0-9a-zA-F]+)",
103 REG_EXTENDED); 103 REG_EXTENDED);
104 while (fgets(buf, (int)sizeof(buf), fp) != NULL) { 104 while (fgets(buf, (int)sizeof(buf), fp) != NULL) {
105 if (regexec(&keyre, buf, 10, matchv, 0) == 0) { 105 if (regexec(&keyre, buf, 10, matchv, 0) == 0) {
106 (void) memcpy(userid, &buf[(int)matchv[1].rm_so], 106 (void) memcpy(userid, &buf[(int)matchv[1].rm_so],
107 MIN((unsigned)(matchv[1].rm_eo - 107 MIN((unsigned)(matchv[1].rm_eo -
108 matchv[1].rm_so), length)); 108 matchv[1].rm_so), length));
109 if (netpgp->passfp == NULL) { 109 if (netpgp->passfp == NULL) {
110 (void) fprintf(stderr, 110 (void) fprintf(stderr,
111 "netpgp: default key set to \"%.*s\"\n", 111 "netpgp: default key set to \"%.*s\"\n",
112 (int)(matchv[1].rm_eo - matchv[1].rm_so), 112 (int)(matchv[1].rm_eo - matchv[1].rm_so),
113 &buf[(int)matchv[1].rm_so]); 113 &buf[(int)matchv[1].rm_so]);
114 } 114 }
115 } 115 }
116 } 116 }
117 (void) fclose(fp); 117 (void) fclose(fp);
118 regfree(&keyre); 118 regfree(&keyre);
119 return 1; 119 return 1;
120} 120}
121 121
122/* small function to pretty print an 8-character raw userid */ 122/* small function to pretty print an 8-character raw userid */
123static char * 123static char *
124userid_to_id(const uint8_t *userid, char *id) 124userid_to_id(const uint8_t *userid, char *id)
125{ 125{
126 static const char *hexes = "0123456789abcdef"; 126 static const char *hexes = "0123456789abcdef";
127 int i; 127 int i;
128 128
129 for (i = 0; i < 8 ; i++) { 129 for (i = 0; i < 8 ; i++) {
130 id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4]; 130 id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
131 id[(i * 2) + 1] = hexes[userid[i] & 0xf]; 131 id[(i * 2) + 1] = hexes[userid[i] & 0xf];
132 } 132 }
133 id[8 * 2] = 0x0; 133 id[8 * 2] = 0x0;
134 return id; 134 return id;
135} 135}
136 136
137/* print out the successful signature information */ 137/* print out the successful signature information */
138static void 138static void
139resultp(__ops_io_t *io, 139resultp(__ops_io_t *io,
140 const char *f, 140 const char *f,
141 __ops_validation_t *res, 141 __ops_validation_t *res,
142 __ops_keyring_t *ring) 142 __ops_keyring_t *ring)
143{ 143{
144 const __ops_key_t *key; 144 const __ops_key_t *key;
145 __ops_pubkey_t *sigkey; 145 __ops_pubkey_t *sigkey;
146 unsigned from; 146 unsigned from;
147 unsigned i; 147 unsigned i;
148 time_t t; 148 time_t t;
149 char id[MAX_ID_LENGTH + 1]; 149 char id[MAX_ID_LENGTH + 1];
150 150
151 for (i = 0; i < res->validc; i++) { 151 for (i = 0; i < res->validc; i++) {
152 (void) fprintf(io->res, 152 (void) fprintf(io->res,
153 "Good signature for %s made %s", 153 "Good signature for %s made %s",
154 (f) ? f : "<stdin>", 154 (f) ? f : "<stdin>",
155 ctime(&res->valid_sigs[i].birthtime)); 155 ctime(&res->valid_sigs[i].birthtime));
156 if (res->duration > 0) { 156 if (res->duration > 0) {
157 t = res->birthtime + res->duration; 157 t = res->birthtime + res->duration;
158 (void) fprintf(io->res, "Valid until %s", ctime(&t)); 158 (void) fprintf(io->res, "Valid until %s", ctime(&t));
159 } 159 }
160 (void) fprintf(io->res, 160 (void) fprintf(io->res,
161 "using %s key %s\n", 161 "using %s key %s\n",
162 __ops_show_pka(res->valid_sigs[i].key_alg), 162 __ops_show_pka(res->valid_sigs[i].key_alg),
163 userid_to_id(res->valid_sigs[i].signer_id, id)); 163 userid_to_id(res->valid_sigs[i].signer_id, id));
164 from = 0; 164 from = 0;
165 key = __ops_getkeybyid(io, ring, 165 key = __ops_getkeybyid(io, ring,
166 (const uint8_t *) res->valid_sigs[i].signer_id, 166 (const uint8_t *) res->valid_sigs[i].signer_id,
167 &from, &sigkey); 167 &from, &sigkey);
168 if (sigkey == &key->enckey) { 168 if (sigkey == &key->enckey) {
169 (void) fprintf(io->res, 169 (void) fprintf(io->res,
170 "WARNING: signature for %s made with encryption key\n", 170 "WARNING: signature for %s made with encryption key\n",
171 (f) ? f : "<stdin>"); 171 (f) ? f : "<stdin>");
172 } 172 }
173 __ops_print_keydata(io, ring, key, "signature ", &key->key.pubkey, 0); 173 __ops_print_keydata(io, ring, key, "signature ", &key->key.pubkey, 0);
174 } 174 }
175} 175}
176 176
177/* check there's enough space in the arrays */ 177/* check there's enough space in the arrays */
178static int 178static int
179size_arrays(netpgp_t *netpgp, unsigned needed) 179size_arrays(netpgp_t *netpgp, unsigned needed)
180{ 180{
181 char **temp; 181 char **temp;
182 182
183 if (netpgp->size == 0) { 183 if (netpgp->size == 0) {
184 /* only get here first time around */ 184 /* only get here first time around */
185 netpgp->size = needed; 185 netpgp->size = needed;
186 if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) { 186 if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) {
187 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 187 (void) fprintf(stderr, "size_arrays: bad alloc\n");
188 return 0; 188 return 0;
189 } 189 }
190 if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) { 190 if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) {
191 free(netpgp->name); 191 free(netpgp->name);
192 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 192 (void) fprintf(stderr, "size_arrays: bad alloc\n");
193 return 0; 193 return 0;
194 } 194 }
195 } else if (netpgp->c == netpgp->size) { 195 } else if (netpgp->c == netpgp->size) {
196 /* only uses 'needed' when filled array */ 196 /* only uses 'needed' when filled array */
197 netpgp->size += needed; 197 netpgp->size += needed;
198 temp = realloc(netpgp->name, sizeof(char *) * needed); 198 temp = realloc(netpgp->name, sizeof(char *) * needed);
199 if (temp == NULL) { 199 if (temp == NULL) {
200 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 200 (void) fprintf(stderr, "size_arrays: bad alloc\n");
201 return 0; 201 return 0;
202 } 202 }
203 netpgp->name = temp; 203 netpgp->name = temp;
204 temp = realloc(netpgp->value, sizeof(char *) * needed); 204 temp = realloc(netpgp->value, sizeof(char *) * needed);
205 if (temp == NULL) { 205 if (temp == NULL) {
206 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 206 (void) fprintf(stderr, "size_arrays: bad alloc\n");
207 return 0; 207 return 0;
208 } 208 }
209 netpgp->value = temp; 209 netpgp->value = temp;
210 } 210 }
211 return 1; 211 return 1;
212} 212}
213 213
214/* find the name in the array */ 214/* find the name in the array */
215static int 215static int
216findvar(netpgp_t *netpgp, const char *name) 216findvar(netpgp_t *netpgp, const char *name)
217{ 217{
218 unsigned i; 218 unsigned i;
219 219
220 for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) { 220 for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) {
221 } 221 }
222 return (i == netpgp->c) ? -1 : (int)i; 222 return (i == netpgp->c) ? -1 : (int)i;
223} 223}
224 224
225/* read a keyring and return it */ 225/* read a keyring and return it */
226static void * 226static void *
227readkeyring(netpgp_t *netpgp, const char *name) 227readkeyring(netpgp_t *netpgp, const char *name)
228{ 228{
229 __ops_keyring_t *keyring; 229 __ops_keyring_t *keyring;
230 const unsigned noarmor = 0; 230 const unsigned noarmor = 0;
231 char f[MAXPATHLEN]; 231 char f[MAXPATHLEN];
232 char *filename; 232 char *filename;
233 char *homedir; 233 char *homedir;
234 234
235 homedir = netpgp_getvar(netpgp, "homedir"); 235 homedir = netpgp_getvar(netpgp, "homedir");
236 if ((filename = netpgp_getvar(netpgp, name)) == NULL) { 236 if ((filename = netpgp_getvar(netpgp, name)) == NULL) {
237 (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name); 237 (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name);
238 filename = f; 238 filename = f;
239 } 239 }
240 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 240 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) {
241 (void) fprintf(stderr, "readkeyring: bad alloc\n"); 241 (void) fprintf(stderr, "readkeyring: bad alloc\n");
242 return NULL; 242 return NULL;
243 } 243 }
244 if (!__ops_keyring_fileread(keyring, noarmor, filename)) { 244 if (!__ops_keyring_fileread(keyring, noarmor, filename)) {
245 free(keyring); 245 free(keyring);
246 (void) fprintf(stderr, "Can't read %s %s\n", name, filename); 246 (void) fprintf(stderr, "Can't read %s %s\n", name, filename);
247 return NULL; 247 return NULL;
248 } 248 }
249 netpgp_setvar(netpgp, name, filename); 249 netpgp_setvar(netpgp, name, filename);
250 return keyring; 250 return keyring;
251} 251}
252 252
253/* read keys from ssh key files */ 253/* read keys from ssh key files */
254static int 254static int
255readsshkeys(netpgp_t *netpgp, char *homedir, const char *needseckey) 255readsshkeys(netpgp_t *netpgp, char *homedir, const char *needseckey)
256{ 256{
257 __ops_keyring_t *pubring; 257 __ops_keyring_t *pubring;
258 __ops_keyring_t *secring; 258 __ops_keyring_t *secring;
259 struct stat st; 259 struct stat st;
260 unsigned hashtype; 260 unsigned hashtype;
261 char *hash; 261 char *hash;
262 char f[MAXPATHLEN]; 262 char f[MAXPATHLEN];
263 char *filename; 263 char *filename;
264 264
265 if ((filename = netpgp_getvar(netpgp, "sshkeyfile")) == NULL) { 265 if ((filename = netpgp_getvar(netpgp, "sshkeyfile")) == NULL) {
266 /* set reasonable default for RSA key */ 266 /* set reasonable default for RSA key */
267 (void) snprintf(f, sizeof(f), "%s/id_rsa.pub", homedir); 267 (void) snprintf(f, sizeof(f), "%s/id_rsa.pub", homedir);
268 filename = f; 268 filename = f;
269 } else if (strcmp(&filename[strlen(filename) - 4], ".pub") != 0) { 269 } else if (strcmp(&filename[strlen(filename) - 4], ".pub") != 0) {
270 /* got ssh keys, check for pub file name */ 270 /* got ssh keys, check for pub file name */
271 (void) snprintf(f, sizeof(f), "%s.pub", filename); 271 (void) snprintf(f, sizeof(f), "%s.pub", filename);
272 filename = f; 272 filename = f;
273 } 273 }
274 /* check the pub file exists */ 274 /* check the pub file exists */
275 if (stat(filename, &st) != 0) { 275 if (stat(filename, &st) != 0) {
276 (void) fprintf(stderr, "readsshkeys: bad pubkey filename '%s'\n", filename); 276 (void) fprintf(stderr, "readsshkeys: bad pubkey filename '%s'\n", filename);
277 return 0; 277 return 0;
278 } 278 }
279 if ((pubring = calloc(1, sizeof(*pubring))) == NULL) { 279 if ((pubring = calloc(1, sizeof(*pubring))) == NULL) {
280 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 280 (void) fprintf(stderr, "readsshkeys: bad alloc\n");
281 return 0; 281 return 0;
282 } 282 }
283 /* openssh2 keys use md5 by default */ 283 /* openssh2 keys use md5 by default */
284 hashtype = OPS_HASH_MD5; 284 hashtype = OPS_HASH_MD5;
285 if ((hash = netpgp_getvar(netpgp, "hash")) != NULL) { 285 if ((hash = netpgp_getvar(netpgp, "hash")) != NULL) {
286 /* openssh 2 hasn't really caught up to anything else yet */ 286 /* openssh 2 hasn't really caught up to anything else yet */
287 if (netpgp_strcasecmp(hash, "md5") == 0) { 287 if (netpgp_strcasecmp(hash, "md5") == 0) {
288 hashtype = OPS_HASH_MD5; 288 hashtype = OPS_HASH_MD5;
289 } else if (netpgp_strcasecmp(hash, "sha1") == 0) { 289 } else if (netpgp_strcasecmp(hash, "sha1") == 0) {
290 hashtype = OPS_HASH_SHA1; 290 hashtype = OPS_HASH_SHA1;
291 } else if (netpgp_strcasecmp(hash, "sha256") == 0) { 291 } else if (netpgp_strcasecmp(hash, "sha256") == 0) {
292 hashtype = OPS_HASH_SHA256; 292 hashtype = OPS_HASH_SHA256;
293 } 293 }
294 } 294 }
295 if (!__ops_ssh2_readkeys(netpgp->io, pubring, NULL, filename, NULL, hashtype)) { 295 if (!__ops_ssh2_readkeys(netpgp->io, pubring, NULL, filename, NULL, hashtype)) {
296 free(pubring); 296 free(pubring);
297 (void) fprintf(stderr, "readsshkeys: can't read %s\n", 297 (void) fprintf(stderr, "readsshkeys: can't read %s\n",
298 filename); 298 filename);
299 return 0; 299 return 0;
300 } 300 }
301 if (netpgp->pubring == NULL) { 301 if (netpgp->pubring == NULL) {
302 netpgp->pubring = pubring; 302 netpgp->pubring = pubring;
303 } else { 303 } else {
304 __ops_append_keyring(netpgp->pubring, pubring); 304 __ops_append_keyring(netpgp->pubring, pubring);
305 } 305 }
306 if (needseckey) { 306 if (needseckey) {
307 netpgp_setvar(netpgp, "sshpubfile", filename); 307 netpgp_setvar(netpgp, "sshpubfile", filename);
308 /* try to take the ".pub" off the end */ 308 /* try to take the ".pub" off the end */
309 if (filename == f) { 309 if (filename == f) {
310 f[strlen(f) - 4] = 0x0; 310 f[strlen(f) - 4] = 0x0;
311 } else { 311 } else {
312 (void) snprintf(f, sizeof(f), "%.*s", 312 (void) snprintf(f, sizeof(f), "%.*s",
313 (int)strlen(filename) - 4, filename); 313 (int)strlen(filename) - 4, filename);
314 filename = f; 314 filename = f;
315 } 315 }
316 if ((secring = calloc(1, sizeof(*secring))) == NULL) { 316 if ((secring = calloc(1, sizeof(*secring))) == NULL) {
317 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 317 (void) fprintf(stderr, "readsshkeys: bad alloc\n");
318 return 0; 318 return 0;
319 } 319 }
320 if (!__ops_ssh2_readkeys(netpgp->io, pubring, secring, NULL, filename, hashtype)) { 320 if (!__ops_ssh2_readkeys(netpgp->io, pubring, secring, NULL, filename, hashtype)) {
321 (void) fprintf(stderr, "readsshkeys: can't read sec %s\n", filename); 321 (void) fprintf(stderr, "readsshkeys: can't read sec %s\n", filename);
322 return 0; 322 return 0;
323 } 323 }
324 netpgp->secring = secring; 324 netpgp->secring = secring;
325 netpgp_setvar(netpgp, "sshsecfile", filename); 325 netpgp_setvar(netpgp, "sshsecfile", filename);
326 } 326 }
327 return 1; 327 return 1;
328} 328}
329 329
330/* set ssh uid to first one in pubring */ 330/* set ssh uid to first one in pubring */
331static void 331static void
332set_first_pubring(__ops_keyring_t *pubring, char *id, size_t len, int last) 332set_first_pubring(__ops_keyring_t *pubring, char *id, size_t len, int last)
333{ 333{
334 uint8_t *src; 334 uint8_t *src;
335 int i; 335 int i;
336 int n; 336 int n;
337 337
338 (void) memset(id, 0x0, len); 338 (void) memset(id, 0x0, len);
339 src = pubring->keys[(last) ? pubring->keyc - 1 : 0].sigid; 339 src = pubring->keys[(last) ? pubring->keyc - 1 : 0].sigid;
340 for (i = 0, n = 0 ; i < OPS_KEY_ID_SIZE ; i += 2) { 340 for (i = 0, n = 0 ; i < OPS_KEY_ID_SIZE ; i += 2) {
341 n += snprintf(&id[n], len - n, "%02x%02x", src[i], src[i + 1]); 341 n += snprintf(&id[n], len - n, "%02x%02x", src[i], src[i + 1]);
342 } 342 }
343 id[n] = 0x0; 343 id[n] = 0x0;
344} 344}
345 345
346/* find the time - in a specific %Y-%m-%d format - using a regexp */ 346/* find the time - in a specific %Y-%m-%d format - using a regexp */
347static int 347static int
348grabdate(char *s, int64_t *t) 348grabdate(char *s, int64_t *t)
349{ 349{
350 static regex_t r; 350 static regex_t r;
351 static int compiled; 351 static int compiled;
352 regmatch_t matches[10]; 352 regmatch_t matches[10];
353 struct tm tm; 353 struct tm tm;
354 354
355 if (!compiled) { 355 if (!compiled) {
356 compiled = 1; 356 compiled = 1;
357 (void) regcomp(&r, "([0-9][0-9][0-9][0-9])[-/]([0-9][0-9])[-/]([0-9][0-9])", REG_EXTENDED); 357 (void) regcomp(&r, "([0-9][0-9][0-9][0-9])[-/]([0-9][0-9])[-/]([0-9][0-9])", REG_EXTENDED);
358 } 358 }
359 if (regexec(&r, s, 10, matches, 0) == 0) { 359 if (regexec(&r, s, 10, matches, 0) == 0) {
360 (void) memset(&tm, 0x0, sizeof(tm)); 360 (void) memset(&tm, 0x0, sizeof(tm));
361 tm.tm_year = (int)strtol(&s[(int)matches[1].rm_so], NULL, 10); 361 tm.tm_year = (int)strtol(&s[(int)matches[1].rm_so], NULL, 10);
362 tm.tm_mon = (int)strtol(&s[(int)matches[2].rm_so], NULL, 10) - 1; 362 tm.tm_mon = (int)strtol(&s[(int)matches[2].rm_so], NULL, 10) - 1;
363 tm.tm_mday = (int)strtol(&s[(int)matches[3].rm_so], NULL, 10); 363 tm.tm_mday = (int)strtol(&s[(int)matches[3].rm_so], NULL, 10);
364 *t = mktime(&tm); 364 *t = mktime(&tm);
365 return 1; 365 return 1;
366 } 366 }
367 return 0; 367 return 0;
368} 368}
369 369
370/* get expiration in seconds */ 370/* get expiration in seconds */
371static uint64_t 371static uint64_t
372get_duration(char *s) 372get_duration(char *s)
373{ 373{
374 uint64_t now; 374 uint64_t now;
375 int64_t t; 375 int64_t t;
376 char *mult; 376 char *mult;
377 377
378 if (s == NULL) { 378 if (s == NULL) {
379 return 0; 379 return 0;
380 } 380 }
381 now = (uint64_t)strtoull(s, NULL, 10); 381 now = (uint64_t)strtoull(s, NULL, 10);
382 if ((mult = strchr("hdwmy", s[strlen(s) - 1])) != NULL) { 382 if ((mult = strchr("hdwmy", s[strlen(s) - 1])) != NULL) {
383 switch(*mult) { 383 switch(*mult) {
384 case 'h': 384 case 'h':
385 return now * 60 * 60; 385 return now * 60 * 60;
386 case 'd': 386 case 'd':
387 return now * 60 * 60 * 24; 387 return now * 60 * 60 * 24;
388 case 'w': 388 case 'w':
389 return now * 60 * 60 * 24 * 7; 389 return now * 60 * 60 * 24 * 7;
390 case 'm': 390 case 'm':
391 return now * 60 * 60 * 24 * 31; 391 return now * 60 * 60 * 24 * 31;
392 case 'y': 392 case 'y':
393 return now * 60 * 60 * 24 * 365; 393 return now * 60 * 60 * 24 * 365;
394 } 394 }
395 } 395 }
396 if (grabdate(s, &t)) { 396 if (grabdate(s, &t)) {
397 return t; 397 return t;
398 } 398 }
399 return (uint64_t)strtoll(s, NULL, 10); 399 return (uint64_t)strtoll(s, NULL, 10);
400} 400}
401 401
402/* get birthtime in seconds */ 402/* get birthtime in seconds */
403static int64_t 403static int64_t
404get_birthtime(char *s) 404get_birthtime(char *s)
405{ 405{
406 int64_t t; 406 int64_t t;
407 407
408 if (s == NULL) { 408 if (s == NULL) {
409 return time(NULL); 409 return time(NULL);
410 } 410 }
411 if (grabdate(s, &t)) { 411 if (grabdate(s, &t)) {
412 return t; 412 return t;
413 } 413 }
414 return (uint64_t)strtoll(s, NULL, 10); 414 return (uint64_t)strtoll(s, NULL, 10);
415} 415}
416 416
417/* resolve the userid */ 417/* resolve the userid */
418static const __ops_key_t * 418static const __ops_key_t *
419resolve_userid(netpgp_t *netpgp, const __ops_keyring_t *keyring, const char *userid) 419resolve_userid(netpgp_t *netpgp, const __ops_keyring_t *keyring, const char *userid)
420{ 420{
421 const __ops_key_t *key; 421 const __ops_key_t *key;
422 __ops_io_t *io; 422 __ops_io_t *io;
423 423
424 if (userid == NULL) { 424 if (userid == NULL) {
425 userid = netpgp_getvar(netpgp, "userid"); 425 userid = netpgp_getvar(netpgp, "userid");
 426 if (userid == NULL)
 427 return NULL;
426 } else if (userid[0] == '0' && userid[1] == 'x') { 428 } else if (userid[0] == '0' && userid[1] == 'x') {
427 userid += 2; 429 userid += 2;
428 } 430 }
429 io = netpgp->io; 431 io = netpgp->io;
430 if ((key = __ops_getkeybyname(io, keyring, userid)) == NULL) { 432 if ((key = __ops_getkeybyname(io, keyring, userid)) == NULL) {
431 (void) fprintf(io->errs, "Can't find key '%s'\n", userid); 433 (void) fprintf(io->errs, "Can't find key '%s'\n", userid);
432 } 434 }
433 return key; 435 return key;
434} 436}
435 437
436/* append a key to a keyring */ 438/* append a key to a keyring */
437static int 439static int
438appendkey(__ops_io_t *io, __ops_key_t *key, char *ringfile) 440appendkey(__ops_io_t *io, __ops_key_t *key, char *ringfile)
439{ 441{
440 __ops_output_t *create; 442 __ops_output_t *create;
441 const unsigned noarmor = 0; 443 const unsigned noarmor = 0;
442 int fd; 444 int fd;
443 445
444 if ((fd = __ops_setup_file_append(&create, ringfile)) < 0) { 446 if ((fd = __ops_setup_file_append(&create, ringfile)) < 0) {
445 fd = __ops_setup_file_write(&create, ringfile, 0); 447 fd = __ops_setup_file_write(&create, ringfile, 0);
446 } 448 }
447 if (fd < 0) { 449 if (fd < 0) {
448 (void) fprintf(io->errs, "can't open pubring '%s'\n", ringfile); 450 (void) fprintf(io->errs, "can't open pubring '%s'\n", ringfile);
449 return 0; 451 return 0;
450 } 452 }
451 if (!__ops_write_xfer_pubkey(create, key, noarmor)) { 453 if (!__ops_write_xfer_pubkey(create, key, noarmor)) {
452 (void) fprintf(io->errs, "Cannot write pubkey\n"); 454 (void) fprintf(io->errs, "Cannot write pubkey\n");
453 return 0; 455 return 0;
454 } 456 }
455 __ops_teardown_file_write(create, fd); 457 __ops_teardown_file_write(create, fd);
456 return 1; 458 return 1;
457} 459}
458 460
459/* return 1 if the file contains ascii-armoured text */ 461/* return 1 if the file contains ascii-armoured text */
460static unsigned 462static unsigned
461isarmoured(__ops_io_t *io, const char *f, const void *memory, const char *text) 463isarmoured(__ops_io_t *io, const char *f, const void *memory, const char *text)
462{ 464{
463 unsigned armoured; 465 unsigned armoured;
464 FILE *fp; 466 FILE *fp;
465 char buf[BUFSIZ]; 467 char buf[BUFSIZ];
466 468
467 armoured = 0; 469 armoured = 0;
468 if (f) { 470 if (f) {
469 if ((fp = fopen(f, "r")) == NULL) { 471 if ((fp = fopen(f, "r")) == NULL) {
470 (void) fprintf(io->errs, "isarmoured: can't open '%s'\n", f); 472 (void) fprintf(io->errs, "isarmoured: can't open '%s'\n", f);
471 return 0; 473 return 0;
472 } 474 }
473 if (fgets(buf, (int)sizeof(buf), fp) != NULL) { 475 if (fgets(buf, (int)sizeof(buf), fp) != NULL) {
474 armoured = (strncmp(buf, text, strlen(text)) == 0); 476 armoured = (strncmp(buf, text, strlen(text)) == 0);
475 } 477 }
476 (void) fclose(fp); 478 (void) fclose(fp);
477 } else { 479 } else {
478 armoured = (strncmp(memory, text, strlen(text)) == 0); 480 armoured = (strncmp(memory, text, strlen(text)) == 0);
479 } 481 }
480 return armoured; 482 return armoured;
481} 483}
482 484
483/* vararg print function */ 485/* vararg print function */
484static void 486static void
485p(FILE *fp, const char *s, ...) 487p(FILE *fp, const char *s, ...)
486{ 488{
487 va_list args; 489 va_list args;
488 490
489 va_start(args, s); 491 va_start(args, s);
490 while (s != NULL) { 492 while (s != NULL) {
491 (void) fprintf(fp, "%s", s); 493 (void) fprintf(fp, "%s", s);
492 s = va_arg(args, char *); 494 s = va_arg(args, char *);
493 } 495 }
494 va_end(args); 496 va_end(args);
495} 497}
496 498
497/* print a JSON object to the FILE stream */ 499/* print a JSON object to the FILE stream */
498static void 500static void
499pobj(FILE *fp, mj_t *obj, int depth) 501pobj(FILE *fp, mj_t *obj, int depth)
500{ 502{
501 unsigned i; 503 unsigned i;
502 504
503 if (obj == NULL) { 505 if (obj == NULL) {
504 (void) fprintf(stderr, "No object found\n"); 506 (void) fprintf(stderr, "No object found\n");
505 return; 507 return;
506 } 508 }
507 for (i = 0 ; i < (unsigned)depth ; i++) { 509 for (i = 0 ; i < (unsigned)depth ; i++) {
508 p(fp, " ", NULL); 510 p(fp, " ", NULL);
509 } 511 }
510 switch(obj->type) { 512 switch(obj->type) {
511 case MJ_NULL: 513 case MJ_NULL:
512 case MJ_FALSE: 514 case MJ_FALSE:
513 case MJ_TRUE: 515 case MJ_TRUE:
514 p(fp, (obj->type == MJ_NULL) ? "null" : (obj->type == MJ_FALSE) ? "false" : "true", NULL); 516 p(fp, (obj->type == MJ_NULL) ? "null" : (obj->type == MJ_FALSE) ? "false" : "true", NULL);
515 break; 517 break;
516 case MJ_NUMBER: 518 case MJ_NUMBER:
517 p(fp, obj->value.s, NULL); 519 p(fp, obj->value.s, NULL);
518 break; 520 break;
519 case MJ_STRING: 521 case MJ_STRING:
520 (void) fprintf(fp, "%.*s", (int)(obj->c), obj->value.s); 522 (void) fprintf(fp, "%.*s", (int)(obj->c), obj->value.s);
521 break; 523 break;
522 case MJ_ARRAY: 524 case MJ_ARRAY:
523 for (i = 0 ; i < obj->c ; i++) { 525 for (i = 0 ; i < obj->c ; i++) {
524 pobj(fp, &obj->value.v[i], depth + 1); 526 pobj(fp, &obj->value.v[i], depth + 1);
525 if (i < obj->c - 1) { 527 if (i < obj->c - 1) {
526 (void) fprintf(fp, ", ");  528 (void) fprintf(fp, ", ");
527 } 529 }
528 } 530 }
529 (void) fprintf(fp, "\n");  531 (void) fprintf(fp, "\n");
530 break; 532 break;
531 case MJ_OBJECT: 533 case MJ_OBJECT:
532 for (i = 0 ; i < obj->c ; i += 2) { 534 for (i = 0 ; i < obj->c ; i += 2) {
533 pobj(fp, &obj->value.v[i], depth + 1); 535 pobj(fp, &obj->value.v[i], depth + 1);
534 p(fp, ": ", NULL);  536 p(fp, ": ", NULL);
535 pobj(fp, &obj->value.v[i + 1], 0); 537 pobj(fp, &obj->value.v[i + 1], 0);
536 if (i < obj->c - 1) { 538 if (i < obj->c - 1) {
537 p(fp, ", ", NULL);  539 p(fp, ", ", NULL);
538 } 540 }
539 } 541 }
540 p(fp, "\n", NULL);  542 p(fp, "\n", NULL);
541 break; 543 break;
542 default: 544 default:
543 break; 545 break;
544 } 546 }
545} 547}
546 548
547/* return the time as a string */ 549/* return the time as a string */
548static char *  550static char *
549ptimestr(char *dest, size_t size, time_t t) 551ptimestr(char *dest, size_t size, time_t t)
550{ 552{
551 struct tm *tm; 553 struct tm *tm;
552 554
553 tm = gmtime(&t); 555 tm = gmtime(&t);
554 (void) snprintf(dest, size, "%04d-%02d-%02d", 556 (void) snprintf(dest, size, "%04d-%02d-%02d",
555 tm->tm_year + 1900, 557 tm->tm_year + 1900,
556 tm->tm_mon + 1, 558 tm->tm_mon + 1,
557 tm->tm_mday); 559 tm->tm_mday);
558 return dest; 560 return dest;
559} 561}
560 562
561/* format a JSON object */ 563/* format a JSON object */
562static void 564static void
563format_json_key(FILE *fp, mj_t *obj, const int psigs) 565format_json_key(FILE *fp, mj_t *obj, const int psigs)
564{ 566{
565 int64_t birthtime; 567 int64_t birthtime;
566 int64_t duration; 568 int64_t duration;
567 time_t now; 569 time_t now;
568 char tbuf[32]; 570 char tbuf[32];
569 char *s; 571 char *s;
570 mj_t *sub; 572 mj_t *sub;
571 int i; 573 int i;
572 574
573 if (__ops_get_debug_level(__FILE__)) { 575 if (__ops_get_debug_level(__FILE__)) {
574 mj_asprint(&s, obj); 576 mj_asprint(&s, obj);
575 (void) fprintf(stderr, "formatobj: json is '%s'\n", s); 577 (void) fprintf(stderr, "formatobj: json is '%s'\n", s);
576 free(s); 578 free(s);
577 } 579 }
578 if (obj->c == 2 && obj->value.v[1].type == MJ_STRING && 580 if (obj->c == 2 && obj->value.v[1].type == MJ_STRING &&
579 strcmp(obj->value.v[1].value.s, "[REVOKED]") == 0) { 581 strcmp(obj->value.v[1].value.s, "[REVOKED]") == 0) {
580 /* whole key has been rovoked - just return */ 582 /* whole key has been rovoked - just return */
581 return; 583 return;
582 } 584 }
583 pobj(fp, &obj->value.v[mj_object_find(obj, "header", 0, 2) + 1], 0); 585 pobj(fp, &obj->value.v[mj_object_find(obj, "header", 0, 2) + 1], 0);
584 p(fp, " ", NULL); 586 p(fp, " ", NULL);
585 pobj(fp, &obj->value.v[mj_object_find(obj, "key bits", 0, 2) + 1], 0); 587 pobj(fp, &obj->value.v[mj_object_find(obj, "key bits", 0, 2) + 1], 0);
586 p(fp, "/", NULL); 588 p(fp, "/", NULL);
587 pobj(fp, &obj->value.v[mj_object_find(obj, "pka", 0, 2) + 1], 0); 589 pobj(fp, &obj->value.v[mj_object_find(obj, "pka", 0, 2) + 1], 0);
588 p(fp, " ", NULL); 590 p(fp, " ", NULL);
589 pobj(fp, &obj->value.v[mj_object_find(obj, "key id", 0, 2) + 1], 0); 591 pobj(fp, &obj->value.v[mj_object_find(obj, "key id", 0, 2) + 1], 0);
590 birthtime = strtoll(obj->value.v[mj_object_find(obj, "birthtime", 0, 2) + 1].value.s, NULL, 10); 592 birthtime = strtoll(obj->value.v[mj_object_find(obj, "birthtime", 0, 2) + 1].value.s, NULL, 10);
591 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), birthtime), NULL); 593 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), birthtime), NULL);
592 duration = strtoll(obj->value.v[mj_object_find(obj, "duration", 0, 2) + 1].value.s, NULL, 10); 594 duration = strtoll(obj->value.v[mj_object_find(obj, "duration", 0, 2) + 1].value.s, NULL, 10);
593 if (duration > 0) { 595 if (duration > 0) {
594 now = time(NULL); 596 now = time(NULL);
595 p(fp, " ", (birthtime + duration < now) ? "[EXPIRED " : "[EXPIRES ", 597 p(fp, " ", (birthtime + duration < now) ? "[EXPIRED " : "[EXPIRES ",
596 ptimestr(tbuf, sizeof(tbuf), birthtime + duration), "]", NULL); 598 ptimestr(tbuf, sizeof(tbuf), birthtime + duration), "]", NULL);
597 } 599 }
598 p(fp, "\n", "Key fingerprint: ", NULL); 600 p(fp, "\n", "Key fingerprint: ", NULL);
599 pobj(fp, &obj->value.v[mj_object_find(obj, "fingerprint", 0, 2) + 1], 0); 601 pobj(fp, &obj->value.v[mj_object_find(obj, "fingerprint", 0, 2) + 1], 0);
600 p(fp, "\n", NULL); 602 p(fp, "\n", NULL);
601 /* go to field after \"duration\" */ 603 /* go to field after \"duration\" */
602 for (i = mj_object_find(obj, "duration", 0, 2) + 2; i < mj_arraycount(obj) ; i += 2) { 604 for (i = mj_object_find(obj, "duration", 0, 2) + 2; i < mj_arraycount(obj) ; i += 2) {
603 if (strcmp(obj->value.v[i].value.s, "uid") == 0) { 605 if (strcmp(obj->value.v[i].value.s, "uid") == 0) {
604 sub = &obj->value.v[i + 1]; 606 sub = &obj->value.v[i + 1];
605 p(fp, "uid", NULL); 607 p(fp, "uid", NULL);
606 pobj(fp, &sub->value.v[0], (psigs) ? 4 : 14); /* human name */ 608 pobj(fp, &sub->value.v[0], (psigs) ? 4 : 14); /* human name */
607 pobj(fp, &sub->value.v[1], 1); /* any revocation */ 609 pobj(fp, &sub->value.v[1], 1); /* any revocation */
608 p(fp, "\n", NULL); 610 p(fp, "\n", NULL);
609 } else if (strcmp(obj->value.v[i].value.s, "encryption") == 0) { 611 } else if (strcmp(obj->value.v[i].value.s, "encryption") == 0) {
610 sub = &obj->value.v[i + 1]; 612 sub = &obj->value.v[i + 1];
611 p(fp, "encryption", NULL); 613 p(fp, "encryption", NULL);
612 pobj(fp, &sub->value.v[0], 1); /* size */ 614 pobj(fp, &sub->value.v[0], 1); /* size */
613 p(fp, "/", NULL); 615 p(fp, "/", NULL);
614 pobj(fp, &sub->value.v[1], 0); /* alg */ 616 pobj(fp, &sub->value.v[1], 0); /* alg */
615 p(fp, " ", NULL); 617 p(fp, " ", NULL);
616 pobj(fp, &sub->value.v[2], 0); /* id */ 618 pobj(fp, &sub->value.v[2], 0); /* id */
617 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), strtoll(sub->value.v[3].value.s, NULL, 10)), 619 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), strtoll(sub->value.v[3].value.s, NULL, 10)),
618 "\n", NULL); 620 "\n", NULL);
619 } else if (strcmp(obj->value.v[i].value.s, "sig") == 0) { 621 } else if (strcmp(obj->value.v[i].value.s, "sig") == 0) {
620 sub = &obj->value.v[i + 1]; 622 sub = &obj->value.v[i + 1];
621 p(fp, "sig", NULL); 623 p(fp, "sig", NULL);
622 pobj(fp, &sub->value.v[0], 8); /* size */ 624 pobj(fp, &sub->value.v[0], 8); /* size */
623 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), strtoll(sub->value.v[1].value.s, NULL, 10)), 625 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), strtoll(sub->value.v[1].value.s, NULL, 10)),
624 " ", NULL); /* time */ 626 " ", NULL); /* time */
625 pobj(fp, &sub->value.v[2], 0); /* human name */ 627 pobj(fp, &sub->value.v[2], 0); /* human name */
626 p(fp, "\n", NULL); 628 p(fp, "\n", NULL);
627 } else { 629 } else {
628 fprintf(stderr, "weird '%s'\n", obj->value.v[i].value.s); 630 fprintf(stderr, "weird '%s'\n", obj->value.v[i].value.s);
629 pobj(fp, &obj->value.v[i], 0); /* human name */ 631 pobj(fp, &obj->value.v[i], 0); /* human name */
630 } 632 }
631 } 633 }
632 p(fp, "\n", NULL); 634 p(fp, "\n", NULL);
633} 635}
634 636
635/* save a pgp pubkey to a temp file */ 637/* save a pgp pubkey to a temp file */
636static int 638static int
637savepubkey(char *res, char *f, size_t size) 639savepubkey(char *res, char *f, size_t size)
638{ 640{
639 size_t len; 641 size_t len;
640 int cc; 642 int cc;
641 int wc; 643 int wc;
642 int fd; 644 int fd;
643 645
644 (void) snprintf(f, size, "/tmp/pgp2ssh.XXXXXXX"); 646 (void) snprintf(f, size, "/tmp/pgp2ssh.XXXXXXX");
645 if ((fd = mkstemp(f)) < 0) { 647 if ((fd = mkstemp(f)) < 0) {
646 (void) fprintf(stderr, "can't create temp file '%s'\n", f); 648 (void) fprintf(stderr, "can't create temp file '%s'\n", f);
647 return 0; 649 return 0;
648 } 650 }
649 len = strlen(res); 651 len = strlen(res);
650 for (cc = 0 ; (wc = write(fd, &res[cc], len - cc)) > 0 ; cc += wc) { 652 for (cc = 0 ; (wc = write(fd, &res[cc], len - cc)) > 0 ; cc += wc) {
651 } 653 }
652 (void) close(fd); 654 (void) close(fd);
653 return 1; 655 return 1;
654} 656}
655 657
656/* format a uint32_t */ 658/* format a uint32_t */
657static int 659static int
658formatu32(uint8_t *buffer, uint32_t value) 660formatu32(uint8_t *buffer, uint32_t value)
659{ 661{
660 buffer[0] = (uint8_t)(value >> 24) & 0xff; 662 buffer[0] = (uint8_t)(value >> 24) & 0xff;
661 buffer[1] = (uint8_t)(value >> 16) & 0xff; 663 buffer[1] = (uint8_t)(value >> 16) & 0xff;
662 buffer[2] = (uint8_t)(value >> 8) & 0xff; 664 buffer[2] = (uint8_t)(value >> 8) & 0xff;
663 buffer[3] = (uint8_t)value & 0xff; 665 buffer[3] = (uint8_t)value & 0xff;
664 return sizeof(uint32_t); 666 return sizeof(uint32_t);
665} 667}
666 668
667/* format a string as (len, string) */ 669/* format a string as (len, string) */
668static int 670static int
669formatstring(char *buffer, const uint8_t *s, size_t len) 671formatstring(char *buffer, const uint8_t *s, size_t len)
670{ 672{
671 int cc; 673 int cc;
672 674
673 cc = formatu32((uint8_t *)buffer, len); 675 cc = formatu32((uint8_t *)buffer, len);
674 (void) memcpy(&buffer[cc], s, len); 676 (void) memcpy(&buffer[cc], s, len);
675 return cc + len; 677 return cc + len;
676} 678}
677 679
678/* format a bignum, checking for "interesting" high bit values */ 680/* format a bignum, checking for "interesting" high bit values */
679static int 681static int
680formatbignum(char *buffer, BIGNUM *bn) 682formatbignum(char *buffer, BIGNUM *bn)
681{ 683{
682 size_t len; 684 size_t len;
683 uint8_t *cp; 685 uint8_t *cp;
684 int cc; 686 int cc;
685 687
686 len = (size_t) BN_num_bytes(bn); 688 len = (size_t) BN_num_bytes(bn);
687 if ((cp = calloc(1, len + 1)) == NULL) { 689 if ((cp = calloc(1, len + 1)) == NULL) {
688 (void) fprintf(stderr, "calloc failure in formatbignum\n"); 690 (void) fprintf(stderr, "calloc failure in formatbignum\n");
689 return 0; 691 return 0;
690 } 692 }
691 (void) BN_bn2bin(bn, cp + 1); 693 (void) BN_bn2bin(bn, cp + 1);
692 cp[0] = 0x0; 694 cp[0] = 0x0;
693 cc = (cp[1] & 0x80) ? formatstring(buffer, cp, len + 1) : formatstring(buffer, &cp[1], len); 695 cc = (cp[1] & 0x80) ? formatstring(buffer, cp, len + 1) : formatstring(buffer, &cp[1], len);
694 free(cp); 696 free(cp);
695 return cc; 697 return cc;
696} 698}
697 699
698/***************************************************************************/ 700/***************************************************************************/
699/* exported functions start here */ 701/* exported functions start here */
700/***************************************************************************/ 702/***************************************************************************/
701 703
702/* initialise a netpgp_t structure */ 704/* initialise a netpgp_t structure */
703int 705int
704netpgp_init(netpgp_t *netpgp) 706netpgp_init(netpgp_t *netpgp)
705{ 707{
706 __ops_io_t *io; 708 __ops_io_t *io;
707 char id[MAX_ID_LENGTH]; 709 char id[MAX_ID_LENGTH];
708 char *homedir; 710 char *homedir;
709 char *userid; 711 char *userid;
710 char *stream; 712 char *stream;
711 char *passfd; 713 char *passfd;
712 char *results; 714 char *results;
713 int coredumps; 715 int coredumps;
714 int last; 716 int last;
715 717
716#ifdef HAVE_SYS_RESOURCE_H 718#ifdef HAVE_SYS_RESOURCE_H
717 struct rlimit limit; 719 struct rlimit limit;
718 720
719 coredumps = netpgp_getvar(netpgp, "coredumps") != NULL; 721 coredumps = netpgp_getvar(netpgp, "coredumps") != NULL;
720 if (!coredumps) { 722 if (!coredumps) {
721 (void) memset(&limit, 0x0, sizeof(limit)); 723 (void) memset(&limit, 0x0, sizeof(limit));
722 if (setrlimit(RLIMIT_CORE, &limit) != 0) { 724 if (setrlimit(RLIMIT_CORE, &limit) != 0) {
723 (void) fprintf(stderr, 725 (void) fprintf(stderr,
724 "netpgp: warning - can't turn off core dumps\n"); 726 "netpgp: warning - can't turn off core dumps\n");
725 coredumps = 1; 727 coredumps = 1;
726 } 728 }
727 } 729 }
728#else 730#else
729 coredumps = 1; 731 coredumps = 1;
730#endif 732#endif
731 if ((io = calloc(1, sizeof(*io))) == NULL) { 733 if ((io = calloc(1, sizeof(*io))) == NULL) {
732 (void) fprintf(stderr, "netpgp_init: bad alloc\n"); 734 (void) fprintf(stderr, "netpgp_init: bad alloc\n");
733 return 0; 735 return 0;
734 } 736 }
735 io->outs = stdout; 737 io->outs = stdout;
736 if ((stream = netpgp_getvar(netpgp, "outs")) != NULL && 738 if ((stream = netpgp_getvar(netpgp, "outs")) != NULL &&
737 strcmp(stream, "<stderr>") == 0) { 739 strcmp(stream, "<stderr>") == 0) {
738 io->outs = stderr; 740 io->outs = stderr;
739 } 741 }
740 io->errs = stderr; 742 io->errs = stderr;
741 if ((stream = netpgp_getvar(netpgp, "errs")) != NULL && 743 if ((stream = netpgp_getvar(netpgp, "errs")) != NULL &&
742 strcmp(stream, "<stdout>") == 0) { 744 strcmp(stream, "<stdout>") == 0) {
743 io->errs = stdout; 745 io->errs = stdout;
744 } 746 }
745 if ((results = netpgp_getvar(netpgp, "res")) == NULL) { 747 if ((results = netpgp_getvar(netpgp, "res")) == NULL) {
746 io->res = io->errs; 748 io->res = io->errs;
747 } else if (strcmp(results, "<stdout>") == 0) { 749 } else if (strcmp(results, "<stdout>") == 0) {
748 io->res = stdout; 750 io->res = stdout;
749 } else if (strcmp(results, "<stderr>") == 0) { 751 } else if (strcmp(results, "<stderr>") == 0) {
750 io->res = stderr; 752 io->res = stderr;
751 } else { 753 } else {
752 if ((io->res = fopen(results, "w")) == NULL) { 754 if ((io->res = fopen(results, "w")) == NULL) {
753 (void) fprintf(io->errs, "Can't open results %s for writing\n", 755 (void) fprintf(io->errs, "Can't open results %s for writing\n",
754 results); 756 results);
755 free(io); 757 free(io);
756 return 0; 758 return 0;
757 } 759 }
758 } 760 }
759 netpgp->io = io; 761 netpgp->io = io;
760 if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL && 762 if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL &&
761 (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) { 763 (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) {
762 (void) fprintf(io->errs, "Can't open fd %s for reading\n", 764 (void) fprintf(io->errs, "Can't open fd %s for reading\n",
763 passfd); 765 passfd);
764 return 0; 766 return 0;
765 } 767 }
766 if (coredumps) { 768 if (coredumps) {
767 (void) fprintf(io->errs, 769 (void) fprintf(io->errs,
768 "netpgp: warning: core dumps enabled\n"); 770 "netpgp: warning: core dumps enabled\n");
769 } 771 }
770 if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) { 772 if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) {
771 (void) fprintf(io->errs, "netpgp: bad homedir\n"); 773 (void) fprintf(io->errs, "netpgp: bad homedir\n");
772 return 0; 774 return 0;
773 } 775 }
774 /* read from either gpg files or ssh keys */ 776 /* read from either gpg files or ssh keys */
775 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 777 if (netpgp_getvar(netpgp, "ssh keys") == NULL) {
776 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 778 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
777 (void) memset(id, 0x0, sizeof(id)); 779 (void) memset(id, 0x0, sizeof(id));
778 (void) conffile(netpgp, homedir, id, sizeof(id)); 780 (void) conffile(netpgp, homedir, id, sizeof(id));
779 if (id[0] != 0x0) { 781 if (id[0] != 0x0) {
780 netpgp_setvar(netpgp, "userid", userid = id); 782 netpgp_setvar(netpgp, "userid", userid = id);
781 } 783 }
782 } 784 }
783 if (userid == NULL) { 785 if (userid == NULL) {
784 if (netpgp_getvar(netpgp, "need userid") != NULL) { 786 if (netpgp_getvar(netpgp, "need userid") != NULL) {
785 (void) fprintf(io->errs, 787 (void) fprintf(io->errs,
786 "Cannot find user id\n"); 788 "Cannot find user id\n");
787 return 0; 789 return 0;
788 } 790 }
789 } else { 791 } else {
790 (void) netpgp_setvar(netpgp, "userid", userid); 792 (void) netpgp_setvar(netpgp, "userid", userid);
791 } 793 }
792 netpgp->pubring = readkeyring(netpgp, "pubring"); 794 netpgp->pubring = readkeyring(netpgp, "pubring");
793 if (netpgp->pubring == NULL) { 795 if (netpgp->pubring == NULL) {
794 (void) fprintf(io->errs, "Can't read pub keyring\n"); 796 (void) fprintf(io->errs, "Can't read pub keyring\n");
795 return 0; 797 return 0;
796 } 798 }
797 netpgp->secring = readkeyring(netpgp, "secring"); 799 netpgp->secring = readkeyring(netpgp, "secring");
798 if (netpgp->secring == NULL) { 800 if (netpgp->secring == NULL) {
799 (void) fprintf(io->errs, "Can't read sec keyring\n"); 801 (void) fprintf(io->errs, "Can't read sec keyring\n");
800 return 0; 802 return 0;
801 } 803 }
802 } else { 804 } else {
803 last = (netpgp->pubring != NULL); 805 last = (netpgp->pubring != NULL);
804 if (!readsshkeys(netpgp, homedir, netpgp_getvar(netpgp, "need seckey"))) { 806 if (!readsshkeys(netpgp, homedir, netpgp_getvar(netpgp, "need seckey"))) {
805 (void) fprintf(io->errs, "Can't read ssh keys\n"); 807 (void) fprintf(io->errs, "Can't read ssh keys\n");
806 return 0; 808 return 0;
807 } 809 }
808 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 810 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
809 set_first_pubring(netpgp->pubring, id, sizeof(id), last); 811 set_first_pubring(netpgp->pubring, id, sizeof(id), last);
810 netpgp_setvar(netpgp, "userid", userid = id); 812 netpgp_setvar(netpgp, "userid", userid = id);
811 } 813 }
812 if (userid == NULL) { 814 if (userid == NULL) {
813 if (netpgp_getvar(netpgp, "need userid") != NULL) { 815 if (netpgp_getvar(netpgp, "need userid") != NULL) {
814 (void) fprintf(io->errs, 816 (void) fprintf(io->errs,
815 "Cannot find user id\n"); 817 "Cannot find user id\n");
816 return 0; 818 return 0;
817 } 819 }
818 } else { 820 } else {
819 (void) netpgp_setvar(netpgp, "userid", userid); 821 (void) netpgp_setvar(netpgp, "userid", userid);
820 } 822 }
821 } 823 }
822 return 1; 824 return 1;
823} 825}
824 826
825/* finish off with the netpgp_t struct */ 827/* finish off with the netpgp_t struct */
826int 828int
827netpgp_end(netpgp_t *netpgp) 829netpgp_end(netpgp_t *netpgp)
828{ 830{
829 unsigned i; 831 unsigned i;
830 832
831 for (i = 0 ; i < netpgp->c ; i++) { 833 for (i = 0 ; i < netpgp->c ; i++) {
832 if (netpgp->name[i] != NULL) { 834 if (netpgp->name[i] != NULL) {
833 free(netpgp->name[i]); 835 free(netpgp->name[i]);
834 } 836 }
835 if (netpgp->value[i] != NULL) { 837 if (netpgp->value[i] != NULL) {
836 free(netpgp->value[i]); 838 free(netpgp->value[i]);
837 } 839 }
838 } 840 }
839 if (netpgp->name != NULL) { 841 if (netpgp->name != NULL) {
840 free(netpgp->name); 842 free(netpgp->name);
841 } 843 }
842 if (netpgp->value != NULL) { 844 if (netpgp->value != NULL) {
843 free(netpgp->value); 845 free(netpgp->value);
844 } 846 }
845 if (netpgp->pubring != NULL) { 847 if (netpgp->pubring != NULL) {
846 __ops_keyring_free(netpgp->pubring); 848 __ops_keyring_free(netpgp->pubring);
847 } 849 }
848 if (netpgp->secring != NULL) { 850 if (netpgp->secring != NULL) {
849 __ops_keyring_free(netpgp->secring); 851 __ops_keyring_free(netpgp->secring);
850 } 852 }
851 free(netpgp->io); 853 free(netpgp->io);
852 return 1; 854 return 1;
853} 855}
854 856
855/* list the keys in a keyring */ 857/* list the keys in a keyring */
856int 858int
857netpgp_list_keys(netpgp_t *netpgp, const int psigs) 859netpgp_list_keys(netpgp_t *netpgp, const int psigs)
858{ 860{
859 if (netpgp->pubring == NULL) { 861 if (netpgp->pubring == NULL) {
860 (void) fprintf(stderr, "No keyring\n"); 862 (void) fprintf(stderr, "No keyring\n");
861 return 0; 863 return 0;
862 } 864 }
863 return __ops_keyring_list(netpgp->io, netpgp->pubring, psigs); 865 return __ops_keyring_list(netpgp->io, netpgp->pubring, psigs);
864} 866}
865 867
866/* list the keys in a keyring, returning a JSON string */ 868/* list the keys in a keyring, returning a JSON string */
867int 869int
868netpgp_list_keys_json(netpgp_t *netpgp, char **json, const int psigs) 870netpgp_list_keys_json(netpgp_t *netpgp, char **json, const int psigs)
869{ 871{
870 mj_t obj; 872 mj_t obj;
871 int ret; 873 int ret;
872 874
873 if (netpgp->pubring == NULL) { 875 if (netpgp->pubring == NULL) {
874 (void) fprintf(stderr, "No keyring\n"); 876 (void) fprintf(stderr, "No keyring\n");
875 return 0; 877 return 0;
876 } 878 }
877 (void) memset(&obj, 0x0, sizeof(obj)); 879 (void) memset(&obj, 0x0, sizeof(obj));
878 if (!__ops_keyring_json(netpgp->io, netpgp->pubring, &obj, psigs)) { 880 if (!__ops_keyring_json(netpgp->io, netpgp->pubring, &obj, psigs)) {
879 (void) fprintf(stderr, "No keys in keyring\n"); 881 (void) fprintf(stderr, "No keys in keyring\n");
880 return 0; 882 return 0;
881 } 883 }
882 ret = mj_asprint(json, &obj); 884 ret = mj_asprint(json, &obj);
883 mj_delete(&obj); 885 mj_delete(&obj);
884 return ret; 886 return ret;
885} 887}
886 888
887DEFINE_ARRAY(strings_t, char *); 889DEFINE_ARRAY(strings_t, char *);
888 890
889#ifndef HKP_VERSION 891#ifndef HKP_VERSION
890#define HKP_VERSION 1 892#define HKP_VERSION 1
891#endif 893#endif
892 894
893/* find and list some keys in a keyring */ 895/* find and list some keys in a keyring */
894int 896int
895netpgp_match_keys(netpgp_t *netpgp, char *name, const char *fmt, void *vp, const int psigs) 897netpgp_match_keys(netpgp_t *netpgp, char *name, const char *fmt, void *vp, const int psigs)
896{ 898{
897 const __ops_key_t *key; 899 const __ops_key_t *key;
898 unsigned k; 900 unsigned k;
899 strings_t pubs; 901 strings_t pubs;
900 FILE *fp = (FILE *)vp; 902 FILE *fp = (FILE *)vp;
901 903
902 if (name[0] == '0' && name[1] == 'x') { 904 if (name[0] == '0' && name[1] == 'x') {
903 name += 2; 905 name += 2;
904 } 906 }
905 (void) memset(&pubs, 0x0, sizeof(pubs)); 907 (void) memset(&pubs, 0x0, sizeof(pubs));
906 k = 0; 908 k = 0;
907 do { 909 do {
908 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, 910 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring,
909 name, &k); 911 name, &k);
910 if (key != NULL) { 912 if (key != NULL) {
911 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, 913 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10,
912 "netpgp_match_keys", return 0); 914 "netpgp_match_keys", return 0);
913 if (strcmp(fmt, "mr") == 0) { 915 if (strcmp(fmt, "mr") == 0) {
914 __ops_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 916 __ops_hkp_sprint_keydata(netpgp->io, netpgp->pubring,
915 key, &pubs.v[pubs.c], 917 key, &pubs.v[pubs.c],
916 &key->key.pubkey, psigs); 918 &key->key.pubkey, psigs);
917 } else { 919 } else {
918 __ops_sprint_keydata(netpgp->io, netpgp->pubring, 920 __ops_sprint_keydata(netpgp->io, netpgp->pubring,
919 key, &pubs.v[pubs.c], 921 key, &pubs.v[pubs.c],
920 "signature ", 922 "signature ",
921 &key->key.pubkey, psigs); 923 &key->key.pubkey, psigs);
922 } 924 }
923 if (pubs.v[pubs.c] != NULL) { 925 if (pubs.v[pubs.c] != NULL) {
924 pubs.c += 1; 926 pubs.c += 1;
925 } 927 }
926 k += 1; 928 k += 1;
927 } 929 }
928 } while (key != NULL); 930 } while (key != NULL);
929 if (strcmp(fmt, "mr") == 0) { 931 if (strcmp(fmt, "mr") == 0) {
930 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); 932 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c);
931 } else { 933 } else {
932 (void) fprintf(fp, "%d key%s found\n", pubs.c, 934 (void) fprintf(fp, "%d key%s found\n", pubs.c,
933 (pubs.c == 1) ? "" : "s"); 935 (pubs.c == 1) ? "" : "s");
934 } 936 }
935 for (k = 0 ; k < pubs.c ; k++) { 937 for (k = 0 ; k < pubs.c ; k++) {
936 (void) fprintf(fp, "%s%s", pubs.v[k], (k < pubs.c - 1) ? "\n" : ""); 938 (void) fprintf(fp, "%s%s", pubs.v[k], (k < pubs.c - 1) ? "\n" : "");
937 free(pubs.v[k]); 939 free(pubs.v[k]);
938 } 940 }
939 free(pubs.v); 941 free(pubs.v);
940 return pubs.c; 942 return pubs.c;
941} 943}
942 944
943/* find and list some keys in a keyring - return JSON string */ 945/* find and list some keys in a keyring - return JSON string */
944int 946int
945netpgp_match_keys_json(netpgp_t *netpgp, char **json, char *name, const char *fmt, const int psigs) 947netpgp_match_keys_json(netpgp_t *netpgp, char **json, char *name, const char *fmt, const int psigs)
946{ 948{
947 const __ops_key_t *key; 949 const __ops_key_t *key;
948 unsigned k; 950 unsigned k;
949 mj_t id_array; 951 mj_t id_array;
950 int ret; 952 int ret;
951 953
952 if (name[0] == '0' && name[1] == 'x') { 954 if (name[0] == '0' && name[1] == 'x') {
953 name += 2; 955 name += 2;
954 } 956 }
955 (void) memset(&id_array, 0x0, sizeof(id_array)); 957 (void) memset(&id_array, 0x0, sizeof(id_array));
956 k = 0; 958 k = 0;
957 *json = NULL; 959 *json = NULL;
958 mj_create(&id_array, "array"); 960 mj_create(&id_array, "array");
959 do { 961 do {
960 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, 962 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring,
961 name, &k); 963 name, &k);
962 if (key != NULL) { 964 if (key != NULL) {
963 if (strcmp(fmt, "mr") == 0) { 965 if (strcmp(fmt, "mr") == 0) {
964#if 0 966#if 0
965 __ops_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 967 __ops_hkp_sprint_keydata(netpgp->io, netpgp->pubring,
966 key, &pubs.v[pubs.c], 968 key, &pubs.v[pubs.c],
967 &key->key.pubkey, psigs); 969 &key->key.pubkey, psigs);
968#endif 970#endif
969 } else { 971 } else {
970 ALLOC(mj_t, id_array.value.v, id_array.size, 972 ALLOC(mj_t, id_array.value.v, id_array.size,
971 id_array.c, 10, 10, "netpgp_match_keys_json", return 0); 973 id_array.c, 10, 10, "netpgp_match_keys_json", return 0);
972 __ops_sprint_mj(netpgp->io, netpgp->pubring, 974 __ops_sprint_mj(netpgp->io, netpgp->pubring,
973 key, &id_array.value.v[id_array.c++], 975 key, &id_array.value.v[id_array.c++],
974 "signature ", 976 "signature ",
975 &key->key.pubkey, psigs); 977 &key->key.pubkey, psigs);
976 } 978 }
977 k += 1; 979 k += 1;
978 } 980 }
979 } while (key != NULL); 981 } while (key != NULL);
980 ret = mj_asprint(json, &id_array); 982 ret = mj_asprint(json, &id_array);
981 mj_delete(&id_array); 983 mj_delete(&id_array);
982 return ret; 984 return ret;
983} 985}
984 986
985/* find and list some public keys in a keyring */ 987/* find and list some public keys in a keyring */
986int 988int
987netpgp_match_pubkeys(netpgp_t *netpgp, char *name, void *vp) 989netpgp_match_pubkeys(netpgp_t *netpgp, char *name, void *vp)
988{ 990{
989 const __ops_key_t *key; 991 const __ops_key_t *key;
990 unsigned k; 992 unsigned k;
991 strings_t pubs; 993 strings_t pubs;
992 FILE *fp = (FILE *)vp; 994 FILE *fp = (FILE *)vp;
993 995
994 (void) memset(&pubs, 0x0, sizeof(pubs)); 996 (void) memset(&pubs, 0x0, sizeof(pubs));
995 do { 997 do {
996 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, 998 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring,
997 name, &k); 999 name, &k);
998 if (key != NULL) { 1000 if (key != NULL) {
999 char out[1024 * 64]; 1001 char out[1024 * 64];
1000 1002
1001 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, 1003 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10,
1002 "netpgp_match_pubkeys", return 0); 1004 "netpgp_match_pubkeys", return 0);
1003 (void) __ops_sprint_pubkey(key, out, sizeof(out)); 1005 (void) __ops_sprint_pubkey(key, out, sizeof(out));
1004 pubs.v[pubs.c++] = netpgp_strdup(out); 1006 pubs.v[pubs.c++] = netpgp_strdup(out);
1005 k += 1; 1007 k += 1;
1006 } 1008 }
1007 } while (key != NULL); 1009 } while (key != NULL);
1008 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); 1010 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c);
1009 for (k = 0 ; k < pubs.c ; k++) { 1011 for (k = 0 ; k < pubs.c ; k++) {
1010 (void) fprintf(fp, "%s", pubs.v[k]); 1012 (void) fprintf(fp, "%s", pubs.v[k]);
1011 free(pubs.v[k]); 1013 free(pubs.v[k]);
1012 } 1014 }
1013 free(pubs.v); 1015 free(pubs.v);
1014 return pubs.c; 1016 return pubs.c;
1015} 1017}
1016 1018
1017/* find a key in a keyring */ 1019/* find a key in a keyring */
1018int 1020int
1019netpgp_find_key(netpgp_t *netpgp, char *id) 1021netpgp_find_key(netpgp_t *netpgp, char *id)
1020{ 1022{
1021 __ops_io_t *io; 1023 __ops_io_t *io;
1022 1024
1023 io = netpgp->io; 1025 io = netpgp->io;
1024 if (id == NULL) { 1026 if (id == NULL) {
1025 (void) fprintf(io->errs, "NULL id to search for\n"); 1027 (void) fprintf(io->errs, "NULL id to search for\n");
1026 return 0; 1028 return 0;
1027 } 1029 }
1028 return __ops_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL; 1030 return __ops_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL;
1029} 1031}
1030 1032
1031/* get a key in a keyring */ 1033/* get a key in a keyring */
1032char * 1034char *
1033netpgp_get_key(netpgp_t *netpgp, const char *name, const char *fmt) 1035netpgp_get_key(netpgp_t *netpgp, const char *name, const char *fmt)
1034{ 1036{
1035 const __ops_key_t *key; 1037 const __ops_key_t *key;
1036 char *newkey; 1038 char *newkey;
1037 1039
1038 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { 1040 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) {
1039 return NULL; 1041 return NULL;
1040 } 1042 }
1041 if (strcmp(fmt, "mr") == 0) { 1043 if (strcmp(fmt, "mr") == 0) {
1042 return (__ops_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 1044 return (__ops_hkp_sprint_keydata(netpgp->io, netpgp->pubring,
1043 key, &newkey, 1045 key, &newkey,
1044 &key->key.pubkey, 1046 &key->key.pubkey,
1045 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; 1047 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL;
1046 } 1048 }
1047 return (__ops_sprint_keydata(netpgp->io, netpgp->pubring, 1049 return (__ops_sprint_keydata(netpgp->io, netpgp->pubring,
1048 key, &newkey, "signature", 1050 key, &newkey, "signature",
1049 &key->key.pubkey, 1051 &key->key.pubkey,
1050 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; 1052 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL;
1051} 1053}
1052 1054
1053/* export a given key */ 1055/* export a given key */
1054char * 1056char *
1055netpgp_export_key(netpgp_t *netpgp, char *name) 1057netpgp_export_key(netpgp_t *netpgp, char *name)
1056{ 1058{
1057 const __ops_key_t *key; 1059 const __ops_key_t *key;
1058 __ops_io_t *io; 1060 __ops_io_t *io;
1059 1061
1060 io = netpgp->io; 1062 io = netpgp->io;
1061 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { 1063 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) {
1062 return NULL; 1064 return NULL;
1063 } 1065 }
1064 return __ops_export_key(io, key, NULL); 1066 return __ops_export_key(io, key, NULL);
1065} 1067}
1066 1068
1067#define IMPORT_ARMOR_HEAD "-----BEGIN PGP PUBLIC KEY BLOCK-----" 1069#define IMPORT_ARMOR_HEAD "-----BEGIN PGP PUBLIC KEY BLOCK-----"
1068 1070
1069/* import a key into our keyring */ 1071/* import a key into our keyring */
1070int 1072int
1071netpgp_import_key(netpgp_t *netpgp, char *f) 1073netpgp_import_key(netpgp_t *netpgp, char *f)
1072{ 1074{
1073 __ops_io_t *io; 1075 __ops_io_t *io;
1074 unsigned realarmor; 1076 unsigned realarmor;
1075 int done; 1077 int done;
1076 1078
1077 io = netpgp->io; 1079 io = netpgp->io;
1078 realarmor = isarmoured(io, f, NULL, IMPORT_ARMOR_HEAD); 1080 realarmor = isarmoured(io, f, NULL, IMPORT_ARMOR_HEAD);
1079 done = __ops_keyring_fileread(netpgp->pubring, realarmor, f); 1081 done = __ops_keyring_fileread(netpgp->pubring, realarmor, f);
1080 if (!done) { 1082 if (!done) {
1081 (void) fprintf(io->errs, "Cannot import key from file %s\n", f); 1083 (void) fprintf(io->errs, "Cannot import key from file %s\n", f);
1082 return 0; 1084 return 0;
1083 } 1085 }
1084 return __ops_keyring_list(io, netpgp->pubring, 0); 1086 return __ops_keyring_list(io, netpgp->pubring, 0);
1085} 1087}
1086 1088
1087/* generate a new key */ 1089/* generate a new key */
1088int 1090int
1089netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits) 1091netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits)
1090{ 1092{
1091 __ops_output_t *create; 1093 __ops_output_t *create;
1092 const unsigned noarmor = 0; 1094 const unsigned noarmor = 0;
1093 __ops_key_t *key; 1095 __ops_key_t *key;
1094 __ops_io_t *io; 1096 __ops_io_t *io;
1095 uint8_t *uid; 1097 uint8_t *uid;
1096 char newid[1024]; 1098 char newid[1024];
1097 char filename[MAXPATHLEN]; 1099 char filename[MAXPATHLEN];
1098 char dir[MAXPATHLEN]; 1100 char dir[MAXPATHLEN];
1099 char *cp; 1101 char *cp;
1100 char *ringfile; 1102 char *ringfile;
1101 int fd; 1103 int fd;
1102 1104
1103 uid = NULL; 1105 uid = NULL;
1104 io = netpgp->io; 1106 io = netpgp->io;
1105 /* generate a new key */ 1107 /* generate a new key */
1106 if (id) { 1108 if (id) {
1107 (void) snprintf(newid, sizeof(newid), "%s", id); 1109 (void) snprintf(newid, sizeof(newid), "%s", id);
1108 } else { 1110 } else {
1109 (void) snprintf(newid, sizeof(newid), "RSA %d-bit key <%s@localhost>", numbits, getenv("LOGNAME")); 1111 (void) snprintf(newid, sizeof(newid), "RSA %d-bit key <%s@localhost>", numbits, getenv("LOGNAME"));
1110 } 1112 }
1111 uid = (uint8_t *)newid; 1113 uid = (uint8_t *)newid;
1112 key = __ops_rsa_new_selfsign_key(numbits, 65537UL, uid, netpgp_getvar(netpgp, "hash")); 1114 key = __ops_rsa_new_selfsign_key(numbits, 65537UL, uid, netpgp_getvar(netpgp, "hash"));
1113 if (key == NULL) { 1115 if (key == NULL) {
1114 (void) fprintf(io->errs, "Cannot generate key\n"); 1116 (void) fprintf(io->errs, "Cannot generate key\n");
1115 return 0; 1117 return 0;
1116 } 1118 }
1117 cp = NULL; 1119 cp = NULL;
1118 __ops_sprint_keydata(netpgp->io, NULL, key, &cp, "signature ", &key->key.seckey.pubkey, 0); 1120 __ops_sprint_keydata(netpgp->io, NULL, key, &cp, "signature ", &key->key.seckey.pubkey, 0);
1119 (void) fprintf(stdout, "%s", cp); 1121 (void) fprintf(stdout, "%s", cp);
1120 /* write public key */ 1122 /* write public key */
1121 (void) snprintf(dir, sizeof(dir), "%s/%.16s", netpgp_getvar(netpgp, "homedir"), &cp[38]); 1123 (void) snprintf(dir, sizeof(dir), "%s/%.16s", netpgp_getvar(netpgp, "homedir"), &cp[38]);
1122 if (mkdir(dir, 0700) < 0) { 1124 if (mkdir(dir, 0700) < 0) {
1123 (void) fprintf(io->errs, "can't mkdir '%s'\n", dir); 1125 (void) fprintf(io->errs, "can't mkdir '%s'\n", dir);
1124 return 0; 1126 return 0;
1125 } 1127 }
1126 (void) fprintf(io->errs, "netpgp: generated keys in directory %s\n", dir); 1128 (void) fprintf(io->errs, "netpgp: generated keys in directory %s\n", dir);
1127 (void) snprintf(ringfile = filename, sizeof(filename), "%s/pubring.gpg", dir); 1129 (void) snprintf(ringfile = filename, sizeof(filename), "%s/pubring.gpg", dir);
1128 if (!appendkey(io, key, ringfile)) { 1130 if (!appendkey(io, key, ringfile)) {
1129 (void) fprintf(io->errs, "Cannot write pubkey to '%s'\n", ringfile); 1131 (void) fprintf(io->errs, "Cannot write pubkey to '%s'\n", ringfile);
1130 return 0; 1132 return 0;
1131 } 1133 }
1132 if (netpgp->pubring != NULL) { 1134 if (netpgp->pubring != NULL) {
1133 __ops_keyring_free(netpgp->pubring); 1135 __ops_keyring_free(netpgp->pubring);
1134 } 1136 }
1135 /* write secret key */ 1137 /* write secret key */
1136 (void) snprintf(ringfile = filename, sizeof(filename), "%s/secring.gpg", dir); 1138 (void) snprintf(ringfile = filename, sizeof(filename), "%s/secring.gpg", dir);
1137 if ((fd = __ops_setup_file_append(&create, ringfile)) < 0) { 1139 if ((fd = __ops_setup_file_append(&create, ringfile)) < 0) {
1138 fd = __ops_setup_file_write(&create, ringfile, 0); 1140 fd = __ops_setup_file_write(&create, ringfile, 0);
1139 } 1141 }
1140 if (fd < 0) { 1142 if (fd < 0) {
1141 (void) fprintf(io->errs, "can't append secring '%s'\n", ringfile); 1143 (void) fprintf(io->errs, "can't append secring '%s'\n", ringfile);
1142 return 0; 1144 return 0;
1143 } 1145 }
1144 if (!__ops_write_xfer_seckey(create, key, NULL, 0, noarmor)) { 1146 if (!__ops_write_xfer_seckey(create, key, NULL, 0, noarmor)) {
1145 (void) fprintf(io->errs, "Cannot write seckey\n"); 1147 (void) fprintf(io->errs, "Cannot write seckey\n");
1146 return 0; 1148 return 0;
1147 } 1149 }
1148 __ops_teardown_file_write(create, fd); 1150 __ops_teardown_file_write(create, fd);
1149 if (netpgp->secring != NULL) { 1151 if (netpgp->secring != NULL) {
1150 __ops_keyring_free(netpgp->secring); 1152 __ops_keyring_free(netpgp->secring);
1151 } 1153 }
1152 __ops_keydata_free(key); 1154 __ops_keydata_free(key);
1153 free(cp); 1155 free(cp);
1154 return 1; 1156 return 1;
1155} 1157}
1156 1158
1157/* encrypt a file */ 1159/* encrypt a file */
1158int 1160int
1159netpgp_encrypt_file(netpgp_t *netpgp, 1161netpgp_encrypt_file(netpgp_t *netpgp,
1160 const char *userid, 1162 const char *userid,
1161 const char *f, 1163 const char *f,
1162 char *out, 1164 char *out,
1163 int armored) 1165 int armored)
1164{ 1166{
1165 const __ops_key_t *key; 1167 const __ops_key_t *key;
1166 const unsigned overwrite = 1; 1168 const unsigned overwrite = 1;
1167 const char *suffix; 1169 const char *suffix;
1168 __ops_io_t *io; 1170 __ops_io_t *io;
1169 char outname[MAXPATHLEN]; 1171 char outname[MAXPATHLEN];
1170 1172
1171 io = netpgp->io; 1173 io = netpgp->io;
1172 if (f == NULL) { 1174 if (f == NULL) {
1173 (void) fprintf(io->errs, 1175 (void) fprintf(io->errs,
1174 "netpgp_encrypt_file: no filename specified\n"); 1176 "netpgp_encrypt_file: no filename specified\n");
1175 return 0; 1177 return 0;
1176 } 1178 }
1177 suffix = (armored) ? ".asc" : ".gpg"; 1179 suffix = (armored) ? ".asc" : ".gpg";
1178 /* get key with which to sign */ 1180 /* get key with which to sign */
1179 if ((key = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { 1181 if ((key = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) {
1180 return 0; 1182 return 0;
1181 } 1183 }
1182 if (out == NULL) { 1184 if (out == NULL) {
1183 (void) snprintf(outname, sizeof(outname), "%s%s", f, suffix); 1185 (void) snprintf(outname, sizeof(outname), "%s%s", f, suffix);
1184 out = outname; 1186 out = outname;
1185 } 1187 }
1186 return (int)__ops_encrypt_file(io, f, out, key, (unsigned)armored, 1188 return (int)__ops_encrypt_file(io, f, out, key, (unsigned)armored,
1187 overwrite); 1189 overwrite);
1188} 1190}
1189 1191
1190#define ARMOR_HEAD "-----BEGIN PGP MESSAGE-----" 1192#define ARMOR_HEAD "-----BEGIN PGP MESSAGE-----"
1191 1193
1192/* decrypt a file */ 1194/* decrypt a file */
1193int 1195int
1194netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored) 1196netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored)
1195{ 1197{
1196 const unsigned overwrite = 1; 1198 const unsigned overwrite = 1;
1197 __ops_io_t *io; 1199 __ops_io_t *io;
1198 unsigned realarmor; 1200 unsigned realarmor;
1199 unsigned sshkeys; 1201 unsigned sshkeys;
1200 1202
1201 __OPS_USED(armored); 1203 __OPS_USED(armored);
1202 io = netpgp->io; 1204 io = netpgp->io;
1203 if (f == NULL) { 1205 if (f == NULL) {
1204 (void) fprintf(io->errs, 1206 (void) fprintf(io->errs,
1205 "netpgp_decrypt_file: no filename specified\n"); 1207 "netpgp_decrypt_file: no filename specified\n");
1206 return 0; 1208 return 0;
1207 } 1209 }
1208 realarmor = isarmoured(io, f, NULL, ARMOR_HEAD); 1210 realarmor = isarmoured(io, f, NULL, ARMOR_HEAD);
1209 sshkeys = (unsigned)(netpgp_getvar(netpgp, "ssh keys") != NULL); 1211 sshkeys = (unsigned)(netpgp_getvar(netpgp, "ssh keys") != NULL);
1210 return __ops_decrypt_file(netpgp->io, f, out, netpgp->secring, 1212 return __ops_decrypt_file(netpgp->io, f, out, netpgp->secring,
1211 netpgp->pubring, 1213 netpgp->pubring,
1212 realarmor, overwrite, sshkeys, 1214 realarmor, overwrite, sshkeys,
1213 netpgp->passfp, get_passphrase_cb); 1215 netpgp->passfp, get_passphrase_cb);
1214} 1216}
1215 1217
1216/* sign a file */ 1218/* sign a file */
1217int 1219int
1218netpgp_sign_file(netpgp_t *netpgp, 1220netpgp_sign_file(netpgp_t *netpgp,
1219 const char *userid, 1221 const char *userid,
1220 const char *f, 1222 const char *f,
1221 char *out, 1223 char *out,
1222 int armored, 1224 int armored,
1223 int cleartext, 1225 int cleartext,
1224 int detached) 1226 int detached)
1225{ 1227{
1226 const __ops_key_t *keypair; 1228 const __ops_key_t *keypair;
1227 const __ops_key_t *pubkey; 1229 const __ops_key_t *pubkey;
1228 __ops_seckey_t *seckey; 1230 __ops_seckey_t *seckey;
1229 const unsigned overwrite = 1; 1231 const unsigned overwrite = 1;
1230 __ops_io_t *io; 1232 __ops_io_t *io;
1231 const char *hashalg; 1233 const char *hashalg;
1232 int ret; 1234 int ret;
1233 1235
1234 io = netpgp->io; 1236 io = netpgp->io;
1235 if (f == NULL) { 1237 if (f == NULL) {
1236 (void) fprintf(io->errs, 1238 (void) fprintf(io->errs,
1237 "netpgp_sign_file: no filename specified\n"); 1239 "netpgp_sign_file: no filename specified\n");
1238 return 0; 1240 return 0;
1239 } 1241 }
1240 /* get key with which to sign */ 1242 /* get key with which to sign */
1241 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { 1243 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) {
1242 return 0; 1244 return 0;
1243 } 1245 }
1244 ret = 1; 1246 ret = 1;
1245 do { 1247 do {
1246 if (netpgp->passfp == NULL) { 1248 if (netpgp->passfp == NULL) {
1247 /* print out the user id */ 1249 /* print out the user id */
1248 pubkey = __ops_getkeybyname(io, netpgp->pubring, userid); 1250 pubkey = __ops_getkeybyname(io, netpgp->pubring, userid);
1249 if (pubkey == NULL) { 1251 if (pubkey == NULL) {
1250 (void) fprintf(io->errs, 1252 (void) fprintf(io->errs,
1251 "netpgp: warning - using pubkey from secring\n"); 1253 "netpgp: warning - using pubkey from secring\n");
1252 __ops_print_keydata(io, netpgp->pubring, keypair, "signature ", 1254 __ops_print_keydata(io, netpgp->pubring, keypair, "signature ",
1253 &keypair->key.seckey.pubkey, 0); 1255 &keypair->key.seckey.pubkey, 0);
1254 } else { 1256 } else {
1255 __ops_print_keydata(io, netpgp->pubring, pubkey, "signature ", 1257 __ops_print_keydata(io, netpgp->pubring, pubkey, "signature ",
1256 &pubkey->key.pubkey, 0); 1258 &pubkey->key.pubkey, 0);
1257 } 1259 }
1258 } 1260 }
1259 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 1261 if (netpgp_getvar(netpgp, "ssh keys") == NULL) {
1260 /* now decrypt key */ 1262 /* now decrypt key */
1261 seckey = __ops_decrypt_seckey(keypair, netpgp->passfp); 1263 seckey = __ops_decrypt_seckey(keypair, netpgp->passfp);
1262 if (seckey == NULL) { 1264 if (seckey == NULL) {
1263 (void) fprintf(io->errs, "Bad passphrase\n"); 1265 (void) fprintf(io->errs, "Bad passphrase\n");
1264 } 1266 }
1265 } else { 1267 } else {
1266 __ops_keyring_t *secring; 1268 __ops_keyring_t *secring;
1267 1269
1268 secring = netpgp->secring; 1270 secring = netpgp->secring;
1269 seckey = &secring->keys[0].key.seckey; 1271 seckey = &secring->keys[0].key.seckey;
1270 } 1272 }
1271 } while (seckey == NULL); 1273 } while (seckey == NULL);
1272 /* sign file */ 1274 /* sign file */
1273 hashalg = netpgp_getvar(netpgp, "hash"); 1275 hashalg = netpgp_getvar(netpgp, "hash");
1274 if (seckey->pubkey.alg == OPS_PKA_DSA) { 1276 if (seckey->pubkey.alg == OPS_PKA_DSA) {
1275 hashalg = "sha1"; 1277 hashalg = "sha1";
1276 } 1278 }
1277 if (detached) { 1279 if (detached) {
1278 ret = __ops_sign_detached(io, f, out, seckey, hashalg, 1280 ret = __ops_sign_detached(io, f, out, seckey, hashalg,
1279 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1281 get_birthtime(netpgp_getvar(netpgp, "birthtime")),
1280 get_duration(netpgp_getvar(netpgp, "duration")), 1282 get_duration(netpgp_getvar(netpgp, "duration")),
1281 (unsigned)armored, 1283 (unsigned)armored,
1282 overwrite); 1284 overwrite);
1283 } else { 1285 } else {
1284 ret = __ops_sign_file(io, f, out, seckey, hashalg, 1286 ret = __ops_sign_file(io, f, out, seckey, hashalg,
1285 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1287 get_birthtime(netpgp_getvar(netpgp, "birthtime")),
1286 get_duration(netpgp_getvar(netpgp, "duration")), 1288 get_duration(netpgp_getvar(netpgp, "duration")),
1287 (unsigned)armored, (unsigned)cleartext, 1289 (unsigned)armored, (unsigned)cleartext,
1288 overwrite); 1290 overwrite);
1289 } 1291 }
1290 __ops_forget(seckey, (unsigned)sizeof(*seckey)); 1292 __ops_forget(seckey, (unsigned)sizeof(*seckey));
1291 return ret; 1293 return ret;
1292} 1294}
1293 1295
1294#define ARMOR_SIG_HEAD "-----BEGIN PGP SIGNATURE-----\r\n" 1296#define ARMOR_SIG_HEAD "-----BEGIN PGP SIGNATURE-----\r\n"
1295 1297
1296/* verify a file */ 1298/* verify a file */
1297int 1299int
1298netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored) 1300netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored)
1299{ 1301{
1300 __ops_validation_t result; 1302 __ops_validation_t result;
1301 __ops_io_t *io; 1303 __ops_io_t *io;
1302 unsigned realarmor; 1304 unsigned realarmor;
1303 1305
1304 __OPS_USED(armored); 1306 __OPS_USED(armored);
1305 (void) memset(&result, 0x0, sizeof(result)); 1307 (void) memset(&result, 0x0, sizeof(result));
1306 io = netpgp->io; 1308 io = netpgp->io;
1307 if (in == NULL) { 1309 if (in == NULL) {
1308 (void) fprintf(io->errs, 1310 (void) fprintf(io->errs,
1309 "netpgp_verify_file: no filename specified\n"); 1311 "netpgp_verify_file: no filename specified\n");
1310 return 0; 1312 return 0;
1311 } 1313 }
1312 realarmor = isarmoured(io, in, NULL, ARMOR_SIG_HEAD); 1314 realarmor = isarmoured(io, in, NULL, ARMOR_SIG_HEAD);
1313 if (__ops_validate_file(io, &result, in, out, (const int)realarmor, netpgp->pubring)) { 1315 if (__ops_validate_file(io, &result, in, out, (const int)realarmor, netpgp->pubring)) {
1314 resultp(io, in, &result, netpgp->pubring); 1316 resultp(io, in, &result, netpgp->pubring);
1315 return 1; 1317 return 1;
1316 } 1318 }
1317 if (result.validc + result.invalidc + result.unknownc == 0) { 1319 if (result.validc + result.invalidc + result.unknownc == 0) {
1318 (void) fprintf(io->errs, 1320 (void) fprintf(io->errs,
1319 "\"%s\": No signatures found - is this a signed file?\n", 1321 "\"%s\": No signatures found - is this a signed file?\n",
1320 in); 1322 in);
1321 } else if (result.invalidc == 0 && result.unknownc == 0) { 1323 } else if (result.invalidc == 0 && result.unknownc == 0) {
1322 (void) fprintf(io->errs, 1324 (void) fprintf(io->errs,
1323 "\"%s\": file verification failure: invalid signature time\n", in); 1325 "\"%s\": file verification failure: invalid signature time\n", in);
1324 } else { 1326 } else {
1325 (void) fprintf(io->errs, 1327 (void) fprintf(io->errs,
1326"\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n", 1328"\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n",
1327 in, result.invalidc, result.unknownc); 1329 in, result.invalidc, result.unknownc);
1328 } 1330 }
1329 return 0; 1331 return 0;
1330} 1332}
1331 1333
1332/* sign some memory */ 1334/* sign some memory */
1333int 1335int
1334netpgp_sign_memory(netpgp_t *netpgp, 1336netpgp_sign_memory(netpgp_t *netpgp,
1335 const char *userid, 1337 const char *userid,
1336 char *mem, 1338 char *mem,
1337 size_t size, 1339 size_t size,
1338 char *out, 1340 char *out,
1339 size_t outsize, 1341 size_t outsize,
1340 const unsigned armored, 1342 const unsigned armored,
1341 const unsigned cleartext) 1343 const unsigned cleartext)
1342{ 1344{
1343 const __ops_key_t *keypair; 1345 const __ops_key_t *keypair;
1344 const __ops_key_t *pubkey; 1346 const __ops_key_t *pubkey;
1345 __ops_seckey_t *seckey; 1347 __ops_seckey_t *seckey;
1346 __ops_memory_t *signedmem; 1348 __ops_memory_t *signedmem;
1347 __ops_io_t *io; 1349 __ops_io_t *io;
1348 const char *hashalg; 1350 const char *hashalg;
1349 int ret; 1351 int ret;
1350 1352
1351 io = netpgp->io; 1353 io = netpgp->io;
1352 if (mem == NULL) { 1354 if (mem == NULL) {
1353 (void) fprintf(io->errs, 1355 (void) fprintf(io->errs,
1354 "netpgp_sign_memory: no memory to sign\n"); 1356 "netpgp_sign_memory: no memory to sign\n");
1355 return 0; 1357 return 0;
1356 } 1358 }
1357 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { 1359 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) {
1358 return 0; 1360 return 0;
1359 } 1361 }
1360 ret = 1; 1362 ret = 1;
1361 do { 1363 do {
1362 if (netpgp->passfp == NULL) { 1364 if (netpgp->passfp == NULL) {
1363 /* print out the user id */ 1365 /* print out the user id */
1364 pubkey = __ops_getkeybyname(io, netpgp->pubring, userid); 1366 pubkey = __ops_getkeybyname(io, netpgp->pubring, userid);
1365 if (pubkey == NULL) { 1367 if (pubkey == NULL) {
1366 (void) fprintf(io->errs, 1368 (void) fprintf(io->errs,
1367 "netpgp: warning - using pubkey from secring\n"); 1369 "netpgp: warning - using pubkey from secring\n");
1368 __ops_print_keydata(io, netpgp->pubring, keypair, "signature ", 1370 __ops_print_keydata(io, netpgp->pubring, keypair, "signature ",
1369 &keypair->key.seckey.pubkey, 0); 1371 &keypair->key.seckey.pubkey, 0);
1370 } else { 1372 } else {
1371 __ops_print_keydata(io, netpgp->pubring, pubkey, "signature ", 1373 __ops_print_keydata(io, netpgp->pubring, pubkey, "signature ",
1372 &pubkey->key.pubkey, 0); 1374 &pubkey->key.pubkey, 0);
1373 } 1375 }
1374 } 1376 }
1375 /* now decrypt key */ 1377 /* now decrypt key */
1376 seckey = __ops_decrypt_seckey(keypair, netpgp->passfp); 1378 seckey = __ops_decrypt_seckey(keypair, netpgp->passfp);
1377 if (seckey == NULL) { 1379 if (seckey == NULL) {
1378 (void) fprintf(io->errs, "Bad passphrase\n"); 1380 (void) fprintf(io->errs, "Bad passphrase\n");
1379 } 1381 }
1380 } while (seckey == NULL); 1382 } while (seckey == NULL);
1381 /* sign file */ 1383 /* sign file */
1382 (void) memset(out, 0x0, outsize); 1384 (void) memset(out, 0x0, outsize);
1383 hashalg = netpgp_getvar(netpgp, "hash"); 1385 hashalg = netpgp_getvar(netpgp, "hash");
1384 if (seckey->pubkey.alg == OPS_PKA_DSA) { 1386 if (seckey->pubkey.alg == OPS_PKA_DSA) {
1385 hashalg = "sha1"; 1387 hashalg = "sha1";
1386 } 1388 }
1387 signedmem = __ops_sign_buf(io, mem, size, seckey, 1389 signedmem = __ops_sign_buf(io, mem, size, seckey,
1388 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1390 get_birthtime(netpgp_getvar(netpgp, "birthtime")),
1389 get_duration(netpgp_getvar(netpgp, "duration")), 1391 get_duration(netpgp_getvar(netpgp, "duration")),
1390 hashalg, armored, cleartext); 1392 hashalg, armored, cleartext);
1391 if (signedmem) { 1393 if (signedmem) {
1392 size_t m; 1394 size_t m;
1393 1395
1394 m = MIN(__ops_mem_len(signedmem), outsize); 1396 m = MIN(__ops_mem_len(signedmem), outsize);
1395 (void) memcpy(out, __ops_mem_data(signedmem), m); 1397 (void) memcpy(out, __ops_mem_data(signedmem), m);
1396 __ops_memory_free(signedmem); 1398 __ops_memory_free(signedmem);
1397 ret = (int)m; 1399 ret = (int)m;
1398 } else { 1400 } else {
1399 ret = 0; 1401 ret = 0;
1400 } 1402 }
1401 __ops_forget(seckey, (unsigned)sizeof(*seckey)); 1403 __ops_forget(seckey, (unsigned)sizeof(*seckey));
1402 return ret; 1404 return ret;
1403} 1405}
1404 1406
1405/* verify memory */ 1407/* verify memory */
1406int 1408int
1407netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size, 1409netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size,
1408 void *out, size_t outsize, const int armored) 1410 void *out, size_t outsize, const int armored)
1409{ 1411{
1410 __ops_validation_t result; 1412 __ops_validation_t result;
1411 __ops_memory_t *signedmem; 1413 __ops_memory_t *signedmem;
1412 __ops_memory_t *cat; 1414 __ops_memory_t *cat;
1413 __ops_io_t *io; 1415 __ops_io_t *io;
1414 size_t m; 1416 size_t m;
1415 int ret; 1417 int ret;
1416 1418
1417 (void) memset(&result, 0x0, sizeof(result)); 1419 (void) memset(&result, 0x0, sizeof(result));
1418 io = netpgp->io; 1420 io = netpgp->io;
1419 if (in == NULL) { 1421 if (in == NULL) {
1420 (void) fprintf(io->errs, 1422 (void) fprintf(io->errs,
1421 "netpgp_verify_memory: no memory to verify\n"); 1423 "netpgp_verify_memory: no memory to verify\n");
1422 return 0; 1424 return 0;
1423 } 1425 }
1424 signedmem = __ops_memory_new(); 1426 signedmem = __ops_memory_new();