1 /*- 2 * Copyright (c) 2009 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Alistair Crooks (agc@NetBSD.org) 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 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 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 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 #include "config.h" 30 31 #ifdef HAVE_SYS_CDEFS_H 32 #include <sys/cdefs.h> 33 #endif 34 35 #if defined(__NetBSD__) 36 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); 37 __RCSID("$NetBSD: netpgp.c,v 1.92 2011/06/28 03:35:28 agc Exp $"); 38 #endif 39 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 #include <sys/param.h> 43 #include <sys/mman.h> 44 45 #ifdef HAVE_SYS_RESOURCE_H 46 #include <sys/resource.h> 47 #endif 48 49 #ifdef HAVE_FCNTL_H 50 #include <fcntl.h> 51 #endif 52 53 #include <errno.h> 54 #include <regex.h> 55 #include <stdarg.h> 56 #include <stdlib.h> 57 #include <string.h> 58 #include <time.h> 59 60 #ifdef HAVE_UNISTD_H 61 #include <unistd.h> 62 #endif 63 64 #include <errno.h> 65 66 #ifdef HAVE_LIMITS_H 67 #include <limits.h> 68 #endif 69 70 #include <netpgp.h> 71 72 #include "packet.h" 73 #include "packet-parse.h" 74 #include "keyring.h" 75 #include "errors.h" 76 #include "packet-show.h" 77 #include "create.h" 78 #include "netpgpsdk.h" 79 #include "memory.h" 80 #include "validate.h" 81 #include "readerwriter.h" 82 #include "netpgpdefs.h" 83 #include "crypto.h" 84 #include "ssh2pgp.h" 85 #include "defs.h" 86 87 /* read any gpg config file */ 88 static int 89 conffile(netpgp_t *netpgp, char *homedir, char *userid, size_t length) 90 { 91 regmatch_t matchv[10]; 92 regex_t keyre; 93 char buf[BUFSIZ]; 94 FILE *fp; 95 96 __PGP_USED(netpgp); 97 (void) snprintf(buf, sizeof(buf), "%s/gpg.conf", homedir); 98 if ((fp = fopen(buf, "r")) == NULL) { 99 return 0; 100 } 101 (void) memset(&keyre, 0x0, sizeof(keyre)); 102 (void) regcomp(&keyre, "^[ \t]*default-key[ \t]+([0-9a-zA-F]+)", 103 REG_EXTENDED); 104 while (fgets(buf, (int)sizeof(buf), fp) != NULL) { 105 if (regexec(&keyre, buf, 10, matchv, 0) == 0) { 106 (void) memcpy(userid, &buf[(int)matchv[1].rm_so], 107 MIN((unsigned)(matchv[1].rm_eo - 108 matchv[1].rm_so), length)); 109 if (netpgp->passfp == NULL) { 110 (void) fprintf(stderr, 111 "netpgp: default key set to \"%.*s\"\n", 112 (int)(matchv[1].rm_eo - matchv[1].rm_so), 113 &buf[(int)matchv[1].rm_so]); 114 } 115 } 116 } 117 (void) fclose(fp); 118 regfree(&keyre); 119 return 1; 120 } 121 122 /* small function to pretty print an 8-character raw userid */ 123 static char * 124 userid_to_id(const uint8_t *userid, char *id) 125 { 126 static const char *hexes = "0123456789abcdef"; 127 int i; 128 129 for (i = 0; i < 8 ; i++) { 130 id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4]; 131 id[(i * 2) + 1] = hexes[userid[i] & 0xf]; 132 } 133 id[8 * 2] = 0x0; 134 return id; 135 } 136 137 /* print out the successful signature information */ 138 static void 139 resultp(pgp_io_t *io, 140 const char *f, 141 pgp_validation_t *res, 142 pgp_keyring_t *ring) 143 { 144 const pgp_key_t *key; 145 pgp_pubkey_t *sigkey; 146 unsigned from; 147 unsigned i; 148 time_t t; 149 char id[MAX_ID_LENGTH + 1]; 150 151 for (i = 0; i < res->validc; i++) { 152 (void) fprintf(io->res, 153 "Good signature for %s made %s", 154 (f) ? f : "<stdin>", 155 ctime(&res->valid_sigs[i].birthtime)); 156 if (res->duration > 0) { 157 t = res->birthtime + res->duration; 158 (void) fprintf(io->res, "Valid until %s", ctime(&t)); 159 } 160 (void) fprintf(io->res, 161 "using %s key %s\n", 162 pgp_show_pka(res->valid_sigs[i].key_alg), 163 userid_to_id(res->valid_sigs[i].signer_id, id)); 164 from = 0; 165 key = pgp_getkeybyid(io, ring, 166 (const uint8_t *) res->valid_sigs[i].signer_id, 167 &from, &sigkey); 168 if (sigkey == &key->enckey) { 169 (void) fprintf(io->res, 170 "WARNING: signature for %s made with encryption key\n", 171 (f) ? f : "<stdin>"); 172 } 173 pgp_print_keydata(io, ring, key, "signature ", &key->key.pubkey, 0); 174 } 175 } 176 177 /* check there's enough space in the arrays */ 178 static int 179 size_arrays(netpgp_t *netpgp, unsigned needed) 180 { 181 char **temp; 182 183 if (netpgp->size == 0) { 184 /* only get here first time around */ 185 netpgp->size = needed; 186 if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) { 187 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 188 return 0; 189 } 190 if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) { 191 free(netpgp->name); 192 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 193 return 0; 194 } 195 } else if (netpgp->c == netpgp->size) { 196 /* only uses 'needed' when filled array */ 197 netpgp->size += needed; 198 temp = realloc(netpgp->name, sizeof(char *) * needed); 199 if (temp == NULL) { 200 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 201 return 0; 202 } 203 netpgp->name = temp; 204 temp = realloc(netpgp->value, sizeof(char *) * needed); 205 if (temp == NULL) { 206 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 207 return 0; 208 } 209 netpgp->value = temp; 210 } 211 return 1; 212 } 213 214 /* find the name in the array */ 215 static int 216 findvar(netpgp_t *netpgp, const char *name) 217 { 218 unsigned i; 219 220 for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) { 221 } 222 return (i == netpgp->c) ? -1 : (int)i; 223 } 224 225 /* read a keyring and return it */ 226 static void * 227 readkeyring(netpgp_t *netpgp, const char *name) 228 { 229 pgp_keyring_t *keyring; 230 const unsigned noarmor = 0; 231 char f[MAXPATHLEN]; 232 char *filename; 233 char *homedir; 234 235 homedir = netpgp_getvar(netpgp, "homedir"); 236 if ((filename = netpgp_getvar(netpgp, name)) == NULL) { 237 (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name); 238 filename = f; 239 } 240 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 241 (void) fprintf(stderr, "readkeyring: bad alloc\n"); 242 return NULL; 243 } 244 if (!pgp_keyring_fileread(keyring, noarmor, filename)) { 245 free(keyring); 246 (void) fprintf(stderr, "Can't read %s %s\n", name, filename); 247 return NULL; 248 } 249 netpgp_setvar(netpgp, name, filename); 250 return keyring; 251 } 252 253 /* read keys from ssh key files */ 254 static int 255 readsshkeys(netpgp_t *netpgp, char *homedir, const char *needseckey) 256 { 257 pgp_keyring_t *pubring; 258 pgp_keyring_t *secring; 259 struct stat st; 260 unsigned hashtype; 261 char *hash; 262 char f[MAXPATHLEN]; 263 char *filename; 264 265 if ((filename = netpgp_getvar(netpgp, "sshkeyfile")) == NULL) { 266 /* set reasonable default for RSA key */ 267 (void) snprintf(f, sizeof(f), "%s/id_rsa.pub", homedir); 268 filename = f; 269 } else if (strcmp(&filename[strlen(filename) - 4], ".pub") != 0) { 270 /* got ssh keys, check for pub file name */ 271 (void) snprintf(f, sizeof(f), "%s.pub", filename); 272 filename = f; 273 } 274 /* check the pub file exists */ 275 if (stat(filename, &st) != 0) { 276 (void) fprintf(stderr, "readsshkeys: bad pubkey filename '%s'\n", filename); 277 return 0; 278 } 279 if ((pubring = calloc(1, sizeof(*pubring))) == NULL) { 280 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 281 return 0; 282 } 283 /* openssh2 keys use md5 by default */ 284 hashtype = PGP_HASH_MD5; 285 if ((hash = netpgp_getvar(netpgp, "hash")) != NULL) { 286 /* openssh 2 hasn't really caught up to anything else yet */ 287 if (netpgp_strcasecmp(hash, "md5") == 0) { 288 hashtype = PGP_HASH_MD5; 289 } else if (netpgp_strcasecmp(hash, "sha1") == 0) { 290 hashtype = PGP_HASH_SHA1; 291 } else if (netpgp_strcasecmp(hash, "sha256") == 0) { 292 hashtype = PGP_HASH_SHA256; 293 } 294 } 295 if (!pgp_ssh2_readkeys(netpgp->io, pubring, NULL, filename, NULL, hashtype)) { 296 free(pubring); 297 (void) fprintf(stderr, "readsshkeys: can't read %s\n", 298 filename); 299 return 0; 300 } 301 if (netpgp->pubring == NULL) { 302 netpgp->pubring = pubring; 303 } else { 304 pgp_append_keyring(netpgp->pubring, pubring); 305 } 306 if (needseckey) { 307 netpgp_setvar(netpgp, "sshpubfile", filename); 308 /* try to take the ".pub" off the end */ 309 if (filename == f) { 310 f[strlen(f) - 4] = 0x0; 311 } else { 312 (void) snprintf(f, sizeof(f), "%.*s", 313 (int)strlen(filename) - 4, filename); 314 filename = f; 315 } 316 if ((secring = calloc(1, sizeof(*secring))) == NULL) { 317 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 318 return 0; 319 } 320 if (!pgp_ssh2_readkeys(netpgp->io, pubring, secring, NULL, filename, hashtype)) { 321 (void) fprintf(stderr, "readsshkeys: can't read sec %s\n", filename); 322 return 0; 323 } 324 netpgp->secring = secring; 325 netpgp_setvar(netpgp, "sshsecfile", filename); 326 } 327 return 1; 328 } 329 330 /* get the uid of the first key in the keyring */ 331 static int 332 get_first_ring(pgp_keyring_t *ring, char *id, size_t len, int last) 333 { 334 uint8_t *src; 335 int i; 336 int n; 337 338 if (ring == NULL) { 339 return 0; 340 } 341 (void) memset(id, 0x0, len); 342 src = ring->keys[(last) ? ring->keyc - 1 : 0].sigid; 343 for (i = 0, n = 0 ; i < PGP_KEY_ID_SIZE ; i += 2) { 344 n += snprintf(&id[n], len - n, "%02x%02x", src[i], src[i + 1]); 345 } 346 id[n] = 0x0; 347 return 1; 348 } 349 350 /* find the time - in a specific %Y-%m-%d format - using a regexp */ 351 static int 352 grabdate(char *s, int64_t *t) 353 { 354 static regex_t r; 355 static int compiled; 356 regmatch_t matches[10]; 357 struct tm tm; 358 359 if (!compiled) { 360 compiled = 1; 361 (void) regcomp(&r, "([0-9][0-9][0-9][0-9])[-/]([0-9][0-9])[-/]([0-9][0-9])", REG_EXTENDED); 362 } 363 if (regexec(&r, s, 10, matches, 0) == 0) { 364 (void) memset(&tm, 0x0, sizeof(tm)); 365 tm.tm_year = (int)strtol(&s[(int)matches[1].rm_so], NULL, 10); 366 tm.tm_mon = (int)strtol(&s[(int)matches[2].rm_so], NULL, 10) - 1; 367 tm.tm_mday = (int)strtol(&s[(int)matches[3].rm_so], NULL, 10); 368 *t = mktime(&tm); 369 return 1; 370 } 371 return 0; 372 } 373 374 /* get expiration in seconds */ 375 static uint64_t 376 get_duration(char *s) 377 { 378 uint64_t now; 379 int64_t t; 380 char *mult; 381 382 if (s == NULL) { 383 return 0; 384 } 385 now = (uint64_t)strtoull(s, NULL, 10); 386 if ((mult = strchr("hdwmy", s[strlen(s) - 1])) != NULL) { 387 switch(*mult) { 388 case 'h': 389 return now * 60 * 60; 390 case 'd': 391 return now * 60 * 60 * 24; 392 case 'w': 393 return now * 60 * 60 * 24 * 7; 394 case 'm': 395 return now * 60 * 60 * 24 * 31; 396 case 'y': 397 return now * 60 * 60 * 24 * 365; 398 } 399 } 400 if (grabdate(s, &t)) { 401 return t; 402 } 403 return (uint64_t)strtoll(s, NULL, 10); 404 } 405 406 /* get birthtime in seconds */ 407 static int64_t 408 get_birthtime(char *s) 409 { 410 int64_t t; 411 412 if (s == NULL) { 413 return time(NULL); 414 } 415 if (grabdate(s, &t)) { 416 return t; 417 } 418 return (uint64_t)strtoll(s, NULL, 10); 419 } 420 421 /* resolve the userid */ 422 static const pgp_key_t * 423 resolve_userid(netpgp_t *netpgp, const pgp_keyring_t *keyring, const char *userid) 424 { 425 const pgp_key_t *key; 426 pgp_io_t *io; 427 428 if (userid == NULL) { 429 userid = netpgp_getvar(netpgp, "userid"); 430 if (userid == NULL) 431 return NULL; 432 } else if (userid[0] == '0' && userid[1] == 'x') { 433 userid += 2; 434 } 435 io = netpgp->io; 436 if ((key = pgp_getkeybyname(io, keyring, userid)) == NULL) { 437 (void) fprintf(io->errs, "Can't find key '%s'\n", userid); 438 } 439 return key; 440 } 441 442 /* append a key to a keyring */ 443 static int 444 appendkey(pgp_io_t *io, pgp_key_t *key, char *ringfile) 445 { 446 pgp_output_t *create; 447 const unsigned noarmor = 0; 448 int fd; 449 450 if ((fd = pgp_setup_file_append(&create, ringfile)) < 0) { 451 fd = pgp_setup_file_write(&create, ringfile, 0); 452 } 453 if (fd < 0) { 454 (void) fprintf(io->errs, "can't open pubring '%s'\n", ringfile); 455 return 0; 456 } 457 if (!pgp_write_xfer_pubkey(create, key, noarmor)) { 458 (void) fprintf(io->errs, "Cannot write pubkey\n"); 459 return 0; 460 } 461 pgp_teardown_file_write(create, fd); 462 return 1; 463 } 464 465 /* return 1 if the file contains ascii-armoured text */ 466 static unsigned 467 isarmoured(pgp_io_t *io, const char *f, const void *memory, const char *text) 468 { 469 regmatch_t matches[10]; 470 unsigned armoured; 471 regex_t r; 472 FILE *fp; 473 char buf[BUFSIZ]; 474 475 armoured = 0; 476 (void) regcomp(&r, text, REG_EXTENDED); 477 if (f) { 478 if ((fp = fopen(f, "r")) == NULL) { 479 (void) fprintf(io->errs, "isarmoured: can't open '%s'\n", f); 480 regfree(&r); 481 return 0; 482 } 483 if (fgets(buf, (int)sizeof(buf), fp) != NULL) { 484 if (regexec(&r, buf, 10, matches, 0) == 0) { 485 armoured = 1; 486 } 487 } 488 (void) fclose(fp); 489 } else { 490 if (regexec(&r, memory, 10, matches, 0) == 0) { 491 armoured = 1; 492 } 493 } 494 regfree(&r); 495 return armoured; 496 } 497 498 /* vararg print function */ 499 static void 500 p(FILE *fp, const char *s, ...) 501 { 502 va_list args; 503 504 va_start(args, s); 505 while (s != NULL) { 506 (void) fprintf(fp, "%s", s); 507 s = va_arg(args, char *); 508 } 509 va_end(args); 510 } 511 512 /* print a JSON object to the FILE stream */ 513 static void 514 pobj(FILE *fp, mj_t *obj, int depth) 515 { 516 unsigned i; 517 char *s; 518 519 if (obj == NULL) { 520 (void) fprintf(stderr, "No object found\n"); 521 return; 522 } 523 for (i = 0 ; i < (unsigned)depth ; i++) { 524 p(fp, " ", NULL); 525 } 526 switch(obj->type) { 527 case MJ_NULL: 528 case MJ_FALSE: 529 case MJ_TRUE: 530 p(fp, (obj->type == MJ_NULL) ? "null" : (obj->type == MJ_FALSE) ? "false" : "true", NULL); 531 break; 532 case MJ_NUMBER: 533 p(fp, obj->value.s, NULL); 534 break; 535 case MJ_STRING: 536 if ((i = mj_asprint(&s, obj, MJ_HUMAN)) > 2) { 537 (void) fprintf(fp, "%.*s", (int)i - 2, &s[1]); 538 free(s); 539 } 540 break; 541 case MJ_ARRAY: 542 for (i = 0 ; i < obj->c ; i++) { 543 pobj(fp, &obj->value.v[i], depth + 1); 544 if (i < obj->c - 1) { 545 (void) fprintf(fp, ", "); 546 } 547 } 548 (void) fprintf(fp, "\n"); 549 break; 550 case MJ_OBJECT: 551 for (i = 0 ; i < obj->c ; i += 2) { 552 pobj(fp, &obj->value.v[i], depth + 1); 553 p(fp, ": ", NULL); 554 pobj(fp, &obj->value.v[i + 1], 0); 555 if (i < obj->c - 1) { 556 p(fp, ", ", NULL); 557 } 558 } 559 p(fp, "\n", NULL); 560 break; 561 default: 562 break; 563 } 564 } 565 566 /* return the time as a string */ 567 static char * 568 ptimestr(char *dest, size_t size, time_t t) 569 { 570 struct tm *tm; 571 572 tm = gmtime(&t); 573 (void) snprintf(dest, size, "%04d-%02d-%02d", 574 tm->tm_year + 1900, 575 tm->tm_mon + 1, 576 tm->tm_mday); 577 return dest; 578 } 579 580 /* format a JSON object */ 581 static void 582 format_json_key(FILE *fp, mj_t *obj, const int psigs) 583 { 584 int64_t birthtime; 585 int64_t duration; 586 time_t now; 587 char tbuf[32]; 588 char *s; 589 mj_t *sub; 590 int i; 591 592 if (pgp_get_debug_level(__FILE__)) { 593 mj_asprint(&s, obj, MJ_HUMAN); 594 (void) fprintf(stderr, "formatobj: json is '%s'\n", s); 595 free(s); 596 } 597 if (obj->c == 2 && obj->value.v[1].type == MJ_STRING && 598 strcmp(obj->value.v[1].value.s, "[REVOKED]") == 0) { 599 /* whole key has been rovoked - just return */ 600 return; 601 } 602 pobj(fp, &obj->value.v[mj_object_find(obj, "header", 0, 2) + 1], 0); 603 p(fp, " ", NULL); 604 pobj(fp, &obj->value.v[mj_object_find(obj, "key bits", 0, 2) + 1], 0); 605 p(fp, "/", NULL); 606 pobj(fp, &obj->value.v[mj_object_find(obj, "pka", 0, 2) + 1], 0); 607 p(fp, " ", NULL); 608 pobj(fp, &obj->value.v[mj_object_find(obj, "key id", 0, 2) + 1], 0); 609 birthtime = (int64_t)strtoll(obj->value.v[mj_object_find(obj, "birthtime", 0, 2) + 1].value.s, NULL, 10); 610 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), birthtime), NULL); 611 duration = (int64_t)strtoll(obj->value.v[mj_object_find(obj, "duration", 0, 2) + 1].value.s, NULL, 10); 612 if (duration > 0) { 613 now = time(NULL); 614 p(fp, " ", (birthtime + duration < now) ? "[EXPIRED " : "[EXPIRES ", 615 ptimestr(tbuf, sizeof(tbuf), birthtime + duration), "]", NULL); 616 } 617 p(fp, "\n", "Key fingerprint: ", NULL); 618 pobj(fp, &obj->value.v[mj_object_find(obj, "fingerprint", 0, 2) + 1], 0); 619 p(fp, "\n", NULL); 620 /* go to field after \"duration\" */ 621 for (i = mj_object_find(obj, "duration", 0, 2) + 2; i < mj_arraycount(obj) ; i += 2) { 622 if (strcmp(obj->value.v[i].value.s, "uid") == 0) { 623 sub = &obj->value.v[i + 1]; 624 p(fp, "uid", NULL); 625 pobj(fp, &sub->value.v[0], (psigs) ? 4 : 14); /* human name */ 626 pobj(fp, &sub->value.v[1], 1); /* any revocation */ 627 p(fp, "\n", NULL); 628 } else if (strcmp(obj->value.v[i].value.s, "encryption") == 0) { 629 sub = &obj->value.v[i + 1]; 630 p(fp, "encryption", NULL); 631 pobj(fp, &sub->value.v[0], 1); /* size */ 632 p(fp, "/", NULL); 633 pobj(fp, &sub->value.v[1], 0); /* alg */ 634 p(fp, " ", NULL); 635 pobj(fp, &sub->value.v[2], 0); /* id */ 636 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), 637 (time_t)strtoll(sub->value.v[3].value.s, NULL, 10)), 638 "\n", NULL); 639 } else if (strcmp(obj->value.v[i].value.s, "sig") == 0) { 640 sub = &obj->value.v[i + 1]; 641 p(fp, "sig", NULL); 642 pobj(fp, &sub->value.v[0], 8); /* size */ 643 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), 644 (time_t)strtoll(sub->value.v[1].value.s, NULL, 10)), 645 " ", NULL); /* time */ 646 pobj(fp, &sub->value.v[2], 0); /* human name */ 647 p(fp, "\n", NULL); 648 } else { 649 fprintf(stderr, "weird '%s'\n", obj->value.v[i].value.s); 650 pobj(fp, &obj->value.v[i], 0); /* human name */ 651 } 652 } 653 p(fp, "\n", NULL); 654 } 655 656 /* save a pgp pubkey to a temp file */ 657 static int 658 savepubkey(char *res, char *f, size_t size) 659 { 660 size_t len; 661 int cc; 662 int wc; 663 int fd; 664 665 (void) snprintf(f, size, "/tmp/pgp2ssh.XXXXXXX"); 666 if ((fd = mkstemp(f)) < 0) { 667 (void) fprintf(stderr, "can't create temp file '%s'\n", f); 668 return 0; 669 } 670 len = strlen(res); 671 for (cc = 0 ; (wc = (int)write(fd, &res[cc], len - (size_t)cc)) > 0 ; cc += wc) { 672 } 673 (void) close(fd); 674 return 1; 675 } 676 677 /* format a uint32_t */ 678 static int 679 formatu32(uint8_t *buffer, uint32_t value) 680 { 681 buffer[0] = (uint8_t)(value >> 24) & 0xff; 682 buffer[1] = (uint8_t)(value >> 16) & 0xff; 683 buffer[2] = (uint8_t)(value >> 8) & 0xff; 684 buffer[3] = (uint8_t)value & 0xff; 685 return sizeof(uint32_t); 686 } 687 688 /* format a string as (len, string) */ 689 static int 690 formatstring(char *buffer, const uint8_t *s, size_t len) 691 { 692 int cc; 693 694 cc = formatu32((uint8_t *)buffer, (uint32_t)len); 695 (void) memcpy(&buffer[cc], s, len); 696 return cc + (int)len; 697 } 698 699 /* format a bignum, checking for "interesting" high bit values */ 700 static int 701 formatbignum(char *buffer, BIGNUM *bn) 702 { 703 size_t len; 704 uint8_t *cp; 705 int cc; 706 707 len = (size_t) BN_num_bytes(bn); 708 if ((cp = calloc(1, len + 1)) == NULL) { 709 (void) fprintf(stderr, "calloc failure in formatbignum\n"); 710 return 0; 711 } 712 (void) BN_bn2bin(bn, cp + 1); 713 cp[0] = 0x0; 714 cc = (cp[1] & 0x80) ? formatstring(buffer, cp, len + 1) : formatstring(buffer, &cp[1], len); 715 free(cp); 716 return cc; 717 } 718 719 #define MAX_PASSPHRASE_ATTEMPTS 3 720 #define INFINITE_ATTEMPTS -1 721 722 /* get the passphrase from the user */ 723 static int 724 find_passphrase(FILE *passfp, const char *id, char *passphrase, size_t size, int attempts) 725 { 726 char prompt[BUFSIZ]; 727 char buf[128]; 728 char *cp; 729 int cc; 730 int i; 731 732 if (passfp) { 733 if (fgets(passphrase, (int)size, passfp) == NULL) { 734 return 0; 735 } 736 return (int)strlen(passphrase); 737 } 738 for (i = 0 ; i < attempts ; i++) { 739 (void) snprintf(prompt, sizeof(prompt), "Enter passphrase for %.16s: ", id); 740 if ((cp = getpass(prompt)) == NULL) { 741 break; 742 } 743 cc = snprintf(buf, sizeof(buf), "%s", cp); 744 (void) snprintf(prompt, sizeof(prompt), "Repeat passphrase for %.16s: ", id); 745 if ((cp = getpass(prompt)) == NULL) { 746 break; 747 } 748 cc = snprintf(passphrase, size, "%s", cp); 749 if (strcmp(buf, passphrase) == 0) { 750 (void) memset(buf, 0x0, sizeof(buf)); 751 return cc; 752 } 753 } 754 (void) memset(buf, 0x0, sizeof(buf)); 755 (void) memset(passphrase, 0x0, size); 756 return 0; 757 } 758 759 /***************************************************************************/ 760 /* exported functions start here */ 761 /***************************************************************************/ 762 763 /* initialise a netpgp_t structure */ 764 int 765 netpgp_init(netpgp_t *netpgp) 766 { 767 pgp_io_t *io; 768 time_t t; 769 char id[MAX_ID_LENGTH]; 770 char *homedir; 771 char *userid; 772 char *stream; 773 char *passfd; 774 char *results; 775 int coredumps; 776 int last; 777 778 #ifdef HAVE_SYS_RESOURCE_H 779 struct rlimit limit; 780 781 coredumps = netpgp_getvar(netpgp, "coredumps") != NULL; 782 if (!coredumps) { 783 (void) memset(&limit, 0x0, sizeof(limit)); 784 if (setrlimit(RLIMIT_CORE, &limit) != 0) { 785 (void) fprintf(stderr, 786 "netpgp: warning - can't turn off core dumps\n"); 787 coredumps = 1; 788 } 789 } 790 #else 791 coredumps = 1; 792 #endif 793 if ((io = calloc(1, sizeof(*io))) == NULL) { 794 (void) fprintf(stderr, "netpgp_init: bad alloc\n"); 795 return 0; 796 } 797 io->outs = stdout; 798 if ((stream = netpgp_getvar(netpgp, "outs")) != NULL && 799 strcmp(stream, "<stderr>") == 0) { 800 io->outs = stderr; 801 } 802 io->errs = stderr; 803 if ((stream = netpgp_getvar(netpgp, "errs")) != NULL && 804 strcmp(stream, "<stdout>") == 0) { 805 io->errs = stdout; 806 } 807 if ((results = netpgp_getvar(netpgp, "res")) == NULL) { 808 io->res = io->errs; 809 } else if (strcmp(results, "<stdout>") == 0) { 810 io->res = stdout; 811 } else if (strcmp(results, "<stderr>") == 0) { 812 io->res = stderr; 813 } else { 814 if ((io->res = fopen(results, "w")) == NULL) { 815 (void) fprintf(io->errs, "Can't open results %s for writing\n", 816 results); 817 free(io); 818 return 0; 819 } 820 } 821 netpgp->io = io; 822 /* get passphrase from an fd */ 823 if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL && 824 (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) { 825 (void) fprintf(io->errs, "Can't open fd %s for reading\n", 826 passfd); 827 return 0; 828 } 829 /* warn if core dumps are enabled */ 830 if (coredumps) { 831 (void) fprintf(io->errs, 832 "netpgp: warning: core dumps enabled\n"); 833 } 834 /* get home directory - where keyrings are in a subdir */ 835 if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) { 836 (void) fprintf(io->errs, "netpgp: bad homedir\n"); 837 return 0; 838 } 839 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 840 /* read from ordinary pgp keyrings */ 841 netpgp->pubring = readkeyring(netpgp, "pubring"); 842 if (netpgp->pubring == NULL) { 843 (void) fprintf(io->errs, "Can't read pub keyring\n"); 844 return 0; 845 } 846 /* if a userid has been given, we'll use it */ 847 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 848 /* also search in config file for default id */ 849 (void) memset(id, 0x0, sizeof(id)); 850 (void) conffile(netpgp, homedir, id, sizeof(id)); 851 if (id[0] != 0x0) { 852 netpgp_setvar(netpgp, "userid", userid = id); 853 } 854 } 855 /* only read secret keys if we need to */ 856 if (netpgp_getvar(netpgp, "need seckey")) { 857 /* read the secret ring */ 858 netpgp->secring = readkeyring(netpgp, "secring"); 859 if (netpgp->secring == NULL) { 860 (void) fprintf(io->errs, "Can't read sec keyring\n"); 861 return 0; 862 } 863 /* now, if we don't have a valid user, use the first in secring */ 864 if (!userid && netpgp_getvar(netpgp, "need userid") != NULL) { 865 /* signing - need userid and sec key */ 866 (void) memset(id, 0x0, sizeof(id)); 867 if (get_first_ring(netpgp->secring, id, sizeof(id), 0)) { 868 netpgp_setvar(netpgp, "userid", userid = id); 869 } 870 } 871 } else if (netpgp_getvar(netpgp, "need userid") != NULL) { 872 /* encrypting - get first in pubring */ 873 if (!userid && get_first_ring(netpgp->pubring, id, sizeof(id), 0)) { 874 (void) netpgp_setvar(netpgp, "userid", userid = id); 875 } 876 } 877 if (!userid && netpgp_getvar(netpgp, "need userid")) { 878 /* if we don't have a user id, and we need one, fail */ 879 (void) fprintf(io->errs, "Cannot find user id\n"); 880 return 0; 881 } 882 } else { 883 /* read from ssh keys */ 884 last = (netpgp->pubring != NULL); 885 if (!readsshkeys(netpgp, homedir, netpgp_getvar(netpgp, "need seckey"))) { 886 (void) fprintf(io->errs, "Can't read ssh keys\n"); 887 return 0; 888 } 889 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 890 get_first_ring(netpgp->pubring, id, sizeof(id), last); 891 netpgp_setvar(netpgp, "userid", userid = id); 892 } 893 if (userid == NULL) { 894 if (netpgp_getvar(netpgp, "need userid") != NULL) { 895 (void) fprintf(io->errs, 896 "Cannot find user id\n"); 897 return 0; 898 } 899 } else { 900 (void) netpgp_setvar(netpgp, "userid", userid); 901 } 902 } 903 t = time(NULL); 904 netpgp_setvar(netpgp, "initialised", ctime(&t)); 905 return 1; 906 } 907 908 /* finish off with the netpgp_t struct */ 909 int 910 netpgp_end(netpgp_t *netpgp) 911 { 912 unsigned i; 913 914 for (i = 0 ; i < netpgp->c ; i++) { 915 if (netpgp->name[i] != NULL) { 916 free(netpgp->name[i]); 917 } 918 if (netpgp->value[i] != NULL) { 919 free(netpgp->value[i]); 920 } 921 } 922 if (netpgp->name != NULL) { 923 free(netpgp->name); 924 } 925 if (netpgp->value != NULL) { 926 free(netpgp->value); 927 } 928 if (netpgp->pubring != NULL) { 929 pgp_keyring_free(netpgp->pubring); 930 } 931 if (netpgp->secring != NULL) { 932 pgp_keyring_free(netpgp->secring); 933 } 934 free(netpgp->io); 935 return 1; 936 } 937 938 /* list the keys in a keyring */ 939 int 940 netpgp_list_keys(netpgp_t *netpgp, const int psigs) 941 { 942 if (netpgp->pubring == NULL) { 943 (void) fprintf(stderr, "No keyring\n"); 944 return 0; 945 } 946 return pgp_keyring_list(netpgp->io, netpgp->pubring, psigs); 947 } 948 949 /* list the keys in a keyring, returning a JSON encoded string */ 950 int 951 netpgp_list_keys_json(netpgp_t *netpgp, char **json, const int psigs) 952 { 953 mj_t obj; 954 int ret; 955 956 if (netpgp->pubring == NULL) { 957 (void) fprintf(stderr, "No keyring\n"); 958 return 0; 959 } 960 (void) memset(&obj, 0x0, sizeof(obj)); 961 if (!pgp_keyring_json(netpgp->io, netpgp->pubring, &obj, psigs)) { 962 (void) fprintf(stderr, "No keys in keyring\n"); 963 return 0; 964 } 965 ret = mj_asprint(json, &obj, MJ_JSON_ENCODE); 966 mj_delete(&obj); 967 return ret; 968 } 969 970 DEFINE_ARRAY(strings_t, char *); 971 972 #ifndef HKP_VERSION 973 #define HKP_VERSION 1 974 #endif 975 976 /* find and list some keys in a keyring */ 977 int 978 netpgp_match_keys(netpgp_t *netpgp, char *name, const char *fmt, void *vp, const int psigs) 979 { 980 const pgp_key_t *key; 981 unsigned k; 982 strings_t pubs; 983 FILE *fp = (FILE *)vp; 984 985 if (name[0] == '0' && name[1] == 'x') { 986 name += 2; 987 } 988 (void) memset(&pubs, 0x0, sizeof(pubs)); 989 k = 0; 990 do { 991 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, 992 name, &k); 993 if (key != NULL) { 994 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, 995 "netpgp_match_keys", return 0); 996 if (strcmp(fmt, "mr") == 0) { 997 pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 998 key, &pubs.v[pubs.c], 999 &key->key.pubkey, psigs); 1000 } else { 1001 pgp_sprint_keydata(netpgp->io, netpgp->pubring, 1002 key, &pubs.v[pubs.c], 1003 "signature ", 1004 &key->key.pubkey, psigs); 1005 } 1006 if (pubs.v[pubs.c] != NULL) { 1007 pubs.c += 1; 1008 } 1009 k += 1; 1010 } 1011 } while (key != NULL); 1012 if (strcmp(fmt, "mr") == 0) { 1013 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); 1014 } else { 1015 (void) fprintf(fp, "%d key%s found\n", pubs.c, 1016 (pubs.c == 1) ? "" : "s"); 1017 } 1018 for (k = 0 ; k < pubs.c ; k++) { 1019 (void) fprintf(fp, "%s%s", pubs.v[k], (k < pubs.c - 1) ? "\n" : ""); 1020 free(pubs.v[k]); 1021 } 1022 free(pubs.v); 1023 return pubs.c; 1024 } 1025 1026 /* find and list some keys in a keyring - return JSON string */ 1027 int 1028 netpgp_match_keys_json(netpgp_t *netpgp, char **json, char *name, const char *fmt, const int psigs) 1029 { 1030 const pgp_key_t *key; 1031 unsigned k; 1032 mj_t id_array; 1033 int ret; 1034 1035 if (name[0] == '0' && name[1] == 'x') { 1036 name += 2; 1037 } 1038 (void) memset(&id_array, 0x0, sizeof(id_array)); 1039 k = 0; 1040 *json = NULL; 1041 mj_create(&id_array, "array"); 1042 do { 1043 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, 1044 name, &k); 1045 if (key != NULL) { 1046 if (strcmp(fmt, "mr") == 0) { 1047 #if 0 1048 pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 1049 key, &pubs.v[pubs.c], 1050 &key->key.pubkey, psigs); 1051 #endif 1052 } else { 1053 ALLOC(mj_t, id_array.value.v, id_array.size, 1054 id_array.c, 10, 10, "netpgp_match_keys_json", return 0); 1055 pgp_sprint_mj(netpgp->io, netpgp->pubring, 1056 key, &id_array.value.v[id_array.c++], 1057 "signature ", 1058 &key->key.pubkey, psigs); 1059 } 1060 k += 1; 1061 } 1062 } while (key != NULL); 1063 ret = mj_asprint(json, &id_array, MJ_JSON_ENCODE); 1064 mj_delete(&id_array); 1065 return ret; 1066 } 1067 1068 /* find and list some public keys in a keyring */ 1069 int 1070 netpgp_match_pubkeys(netpgp_t *netpgp, char *name, void *vp) 1071 { 1072 const pgp_key_t *key; 1073 unsigned k; 1074 strings_t pubs; 1075 FILE *fp = (FILE *)vp; 1076 1077 (void) memset(&pubs, 0x0, sizeof(pubs)); 1078 do { 1079 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, 1080 name, &k); 1081 if (key != NULL) { 1082 char out[1024 * 64]; 1083 1084 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, 1085 "netpgp_match_pubkeys", return 0); 1086 (void) pgp_sprint_pubkey(key, out, sizeof(out)); 1087 pubs.v[pubs.c++] = netpgp_strdup(out); 1088 k += 1; 1089 } 1090 } while (key != NULL); 1091 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); 1092 for (k = 0 ; k < pubs.c ; k++) { 1093 (void) fprintf(fp, "%s", pubs.v[k]); 1094 free(pubs.v[k]); 1095 } 1096 free(pubs.v); 1097 return pubs.c; 1098 } 1099 1100 /* find a key in a keyring */ 1101 int 1102 netpgp_find_key(netpgp_t *netpgp, char *id) 1103 { 1104 pgp_io_t *io; 1105 1106 io = netpgp->io; 1107 if (id == NULL) { 1108 (void) fprintf(io->errs, "NULL id to search for\n"); 1109 return 0; 1110 } 1111 return pgp_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL; 1112 } 1113 1114 /* get a key in a keyring */ 1115 char * 1116 netpgp_get_key(netpgp_t *netpgp, const char *name, const char *fmt) 1117 { 1118 const pgp_key_t *key; 1119 char *newkey; 1120 1121 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { 1122 return NULL; 1123 } 1124 if (strcmp(fmt, "mr") == 0) { 1125 return (pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 1126 key, &newkey, 1127 &key->key.pubkey, 1128 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; 1129 } 1130 return (pgp_sprint_keydata(netpgp->io, netpgp->pubring, 1131 key, &newkey, "signature", 1132 &key->key.pubkey, 1133 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; 1134 } 1135 1136 /* export a given key */ 1137 char * 1138 netpgp_export_key(netpgp_t *netpgp, char *name) 1139 { 1140 const pgp_key_t *key; 1141 pgp_io_t *io; 1142 1143 io = netpgp->io; 1144 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { 1145 return NULL; 1146 } 1147 return pgp_export_key(io, key, NULL); 1148 } 1149 1150 #define IMPORT_ARMOR_HEAD "-----BEGIN PGP PUBLIC KEY BLOCK-----" 1151 1152 /* import a key into our keyring */ 1153 int 1154 netpgp_import_key(netpgp_t *netpgp, char *f) 1155 { 1156 pgp_io_t *io; 1157 unsigned realarmor; 1158 int done; 1159 1160 io = netpgp->io; 1161 realarmor = isarmoured(io, f, NULL, IMPORT_ARMOR_HEAD); 1162 done = pgp_keyring_fileread(netpgp->pubring, realarmor, f); 1163 if (!done) { 1164 (void) fprintf(io->errs, "Cannot import key from file %s\n", f); 1165 return 0; 1166 } 1167 return pgp_keyring_list(io, netpgp->pubring, 0); 1168 } 1169 1170 #define ID_OFFSET 38 1171 1172 /* generate a new key */ 1173 int 1174 netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits) 1175 { 1176 pgp_output_t *create; 1177 const unsigned noarmor = 0; 1178 pgp_key_t *key; 1179 pgp_io_t *io; 1180 uint8_t *uid; 1181 char passphrase[128]; 1182 char newid[1024]; 1183 char filename[MAXPATHLEN]; 1184 char dir[MAXPATHLEN]; 1185 char *cp; 1186 char *ringfile; 1187 char *numtries; 1188 int attempts; 1189 int passc; 1190 int fd; 1191 int cc; 1192 1193 uid = NULL; 1194 io = netpgp->io; 1195 /* generate a new key */ 1196 if (id) { 1197 (void) snprintf(newid, sizeof(newid), "%s", id); 1198 } else { 1199 (void) snprintf(newid, sizeof(newid), 1200 "RSA %d-bit key <%s@localhost>", numbits, getenv("LOGNAME")); 1201 } 1202 uid = (uint8_t *)newid; 1203 key = pgp_rsa_new_selfsign_key(numbits, 65537UL, uid, 1204 netpgp_getvar(netpgp, "hash"), 1205 netpgp_getvar(netpgp, "cipher")); 1206 if (key == NULL) { 1207 (void) fprintf(io->errs, "Cannot generate key\n"); 1208 return 0; 1209 } 1210 cp = NULL; 1211 pgp_sprint_keydata(netpgp->io, NULL, key, &cp, "signature ", &key->key.seckey.pubkey, 0); 1212 (void) fprintf(stdout, "%s", cp); 1213 /* write public key */ 1214 cc = snprintf(dir, sizeof(dir), "%s/%.16s", netpgp_getvar(netpgp, "homedir"), &cp[ID_OFFSET]); 1215 netpgp_setvar(netpgp, "generated userid", &dir[cc - 16]); 1216 if (mkdir(dir, 0700) < 0) { 1217 (void) fprintf(io->errs, "can't mkdir '%s'\n", dir); 1218 return 0; 1219 } 1220 (void) fprintf(io->errs, "netpgp: generated keys in directory %s\n", dir); 1221 (void) snprintf(ringfile = filename, sizeof(filename), "%s/pubring.gpg", dir); 1222 if (!appendkey(io, key, ringfile)) { 1223 (void) fprintf(io->errs, "Cannot write pubkey to '%s'\n", ringfile); 1224 return 0; 1225 } 1226 if (netpgp->pubring != NULL) { 1227 pgp_keyring_free(netpgp->pubring); 1228 } 1229 /* write secret key */ 1230 (void) snprintf(ringfile = filename, sizeof(filename), "%s/secring.gpg", dir); 1231 if ((fd = pgp_setup_file_append(&create, ringfile)) < 0) { 1232 fd = pgp_setup_file_write(&create, ringfile, 0); 1233 } 1234 if (fd < 0) { 1235 (void) fprintf(io->errs, "can't append secring '%s'\n", ringfile); 1236 return 0; 1237 } 1238 /* get the passphrase */ 1239 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1240 (attempts = atoi(numtries)) <= 0) { 1241 attempts = MAX_PASSPHRASE_ATTEMPTS; 1242 } else if (strcmp(numtries, "unlimited") == 0) { 1243 attempts = INFINITE_ATTEMPTS; 1244 } 1245 passc = find_passphrase(netpgp->passfp, &cp[ID_OFFSET], passphrase, sizeof(passphrase), attempts); 1246 if (!pgp_write_xfer_seckey(create, key, (uint8_t *)passphrase, (const unsigned)passc, noarmor)) { 1247 (void) fprintf(io->errs, "Cannot write seckey\n"); 1248 return 0; 1249 } 1250 pgp_teardown_file_write(create, fd); 1251 if (netpgp->secring != NULL) { 1252 pgp_keyring_free(netpgp->secring); 1253 } 1254 pgp_keydata_free(key); 1255 free(cp); 1256 return 1; 1257 } 1258 1259 /* encrypt a file */ 1260 int 1261 netpgp_encrypt_file(netpgp_t *netpgp, 1262 const char *userid, 1263 const char *f, 1264 char *out, 1265 int armored) 1266 { 1267 const pgp_key_t *key; 1268 const unsigned overwrite = 1; 1269 const char *suffix; 1270 pgp_io_t *io; 1271 char outname[MAXPATHLEN]; 1272 1273 io = netpgp->io; 1274 if (f == NULL) { 1275 (void) fprintf(io->errs, 1276 "netpgp_encrypt_file: no filename specified\n"); 1277 return 0; 1278 } 1279 suffix = (armored) ? ".asc" : ".gpg"; 1280 /* get key with which to sign */ 1281 if ((key = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { 1282 return 0; 1283 } 1284 if (out == NULL) { 1285 (void) snprintf(outname, sizeof(outname), "%s%s", f, suffix); 1286 out = outname; 1287 } 1288 return (int)pgp_encrypt_file(io, f, out, key, (unsigned)armored, 1289 overwrite, netpgp_getvar(netpgp, "cipher")); 1290 } 1291 1292 #define ARMOR_HEAD "-----BEGIN PGP MESSAGE-----" 1293 1294 /* decrypt a file */ 1295 int 1296 netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored) 1297 { 1298 const unsigned overwrite = 1; 1299 pgp_io_t *io; 1300 unsigned realarmor; 1301 unsigned sshkeys; 1302 char *numtries; 1303 int attempts; 1304 1305 __PGP_USED(armored); 1306 io = netpgp->io; 1307 if (f == NULL) { 1308 (void) fprintf(io->errs, 1309 "netpgp_decrypt_file: no filename specified\n"); 1310 return 0; 1311 } 1312 realarmor = isarmoured(io, f, NULL, ARMOR_HEAD); 1313 sshkeys = (unsigned)(netpgp_getvar(netpgp, "ssh keys") != NULL); 1314 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1315 (attempts = atoi(numtries)) <= 0) { 1316 attempts = MAX_PASSPHRASE_ATTEMPTS; 1317 } else if (strcmp(numtries, "unlimited") == 0) { 1318 attempts = INFINITE_ATTEMPTS; 1319 } 1320 return pgp_decrypt_file(netpgp->io, f, out, netpgp->secring, 1321 netpgp->pubring, 1322 realarmor, overwrite, sshkeys, 1323 netpgp->passfp, attempts, get_passphrase_cb); 1324 } 1325 1326 /* sign a file */ 1327 int 1328 netpgp_sign_file(netpgp_t *netpgp, 1329 const char *userid, 1330 const char *f, 1331 char *out, 1332 int armored, 1333 int cleartext, 1334 int detached) 1335 { 1336 const pgp_key_t *keypair; 1337 const pgp_key_t *pubkey; 1338 const unsigned overwrite = 1; 1339 pgp_seckey_t *seckey; 1340 const char *hashalg; 1341 pgp_io_t *io; 1342 char *numtries; 1343 int attempts; 1344 int ret; 1345 int i; 1346 1347 io = netpgp->io; 1348 if (f == NULL) { 1349 (void) fprintf(io->errs, 1350 "netpgp_sign_file: no filename specified\n"); 1351 return 0; 1352 } 1353 /* get key with which to sign */ 1354 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { 1355 return 0; 1356 } 1357 ret = 1; 1358 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1359 (attempts = atoi(numtries)) <= 0) { 1360 attempts = MAX_PASSPHRASE_ATTEMPTS; 1361 } else if (strcmp(numtries, "unlimited") == 0) { 1362 attempts = INFINITE_ATTEMPTS; 1363 } 1364 for (i = 0, seckey = NULL ; !seckey && (i < attempts || attempts == INFINITE_ATTEMPTS) ; i++) { 1365 if (netpgp->passfp == NULL) { 1366 /* print out the user id */ 1367 pubkey = pgp_getkeybyname(io, netpgp->pubring, userid); 1368 if (pubkey == NULL) { 1369 (void) fprintf(io->errs, 1370 "netpgp: warning - using pubkey from secring\n"); 1371 pgp_print_keydata(io, netpgp->pubring, keypair, "signature ", 1372 &keypair->key.seckey.pubkey, 0); 1373 } else { 1374 pgp_print_keydata(io, netpgp->pubring, pubkey, "signature ", 1375 &pubkey->key.pubkey, 0); 1376 } 1377 } 1378 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 1379 /* now decrypt key */ 1380 seckey = pgp_decrypt_seckey(keypair, netpgp->passfp); 1381 if (seckey == NULL) { 1382 (void) fprintf(io->errs, "Bad passphrase\n"); 1383 } 1384 } else { 1385 pgp_keyring_t *secring; 1386 1387 secring = netpgp->secring; 1388 seckey = &secring->keys[0].key.seckey; 1389 } 1390 } 1391 if (seckey == NULL) { 1392 (void) fprintf(io->errs, "Bad passphrase\n"); 1393 return 0; 1394 } 1395 /* sign file */ 1396 hashalg = netpgp_getvar(netpgp, "hash"); 1397 if (seckey->pubkey.alg == PGP_PKA_DSA) { 1398 hashalg = "sha1"; 1399 } 1400 if (detached) { 1401 ret = pgp_sign_detached(io, f, out, seckey, hashalg, 1402 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1403 get_duration(netpgp_getvar(netpgp, "duration")), 1404 (unsigned)armored, 1405 overwrite); 1406 } else { 1407 ret = pgp_sign_file(io, f, out, seckey, hashalg, 1408 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1409 get_duration(netpgp_getvar(netpgp, "duration")), 1410 (unsigned)armored, (unsigned)cleartext, 1411 overwrite); 1412 } 1413 pgp_forget(seckey, (unsigned)sizeof(*seckey)); 1414 return ret; 1415 } 1416 1417 #define ARMOR_SIG_HEAD "-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----" 1418 1419 /* verify a file */ 1420 int 1421 netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored) 1422 { 1423 pgp_validation_t result; 1424 pgp_io_t *io; 1425 unsigned realarmor; 1426 1427 __PGP_USED(armored); 1428 (void) memset(&result, 0x0, sizeof(result)); 1429 io = netpgp->io; 1430 if (in == NULL) { 1431 (void) fprintf(io->errs, 1432 "netpgp_verify_file: no filename specified\n"); 1433 return 0; 1434 } 1435 realarmor = isarmoured(io, in, NULL, ARMOR_SIG_HEAD); 1436 if (pgp_validate_file(io, &result, in, out, (const int)realarmor, netpgp->pubring)) { 1437 resultp(io, in, &result, netpgp->pubring); 1438 return 1; 1439 } 1440 if (result.validc + result.invalidc + result.unknownc == 0) { 1441 (void) fprintf(io->errs, 1442 "\"%s\": No signatures found - is this a signed file?\n", 1443 in); 1444 } else if (result.invalidc == 0 && result.unknownc == 0) { 1445 (void) fprintf(io->errs, 1446 "\"%s\": file verification failure: invalid signature time\n", in); 1447 } else { 1448 (void) fprintf(io->errs, 1449 "\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n", 1450 in, result.invalidc, result.unknownc); 1451 } 1452 return 0; 1453 } 1454 1455 /* sign some memory */ 1456 int 1457 netpgp_sign_memory(netpgp_t *netpgp, 1458 const char *userid, 1459 char *mem, 1460 size_t size, 1461 char *out, 1462 size_t outsize, 1463 const unsigned armored, 1464 const unsigned cleartext) 1465 { 1466 const pgp_key_t *keypair; 1467 const pgp_key_t *pubkey; 1468 pgp_seckey_t *seckey; 1469 pgp_memory_t *signedmem; 1470 const char *hashalg; 1471 pgp_io_t *io; 1472 char *numtries; 1473 int attempts; 1474 int ret; 1475 int i; 1476 1477 io = netpgp->io; 1478 if (mem == NULL) { 1479 (void) fprintf(io->errs, 1480 "netpgp_sign_memory: no memory to sign\n"); 1481 return 0; 1482 } 1483 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { 1484 return 0; 1485 } 1486 ret = 1; 1487 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1488 (attempts = atoi(numtries)) <= 0) { 1489 attempts = MAX_PASSPHRASE_ATTEMPTS; 1490 } else if (strcmp(numtries, "unlimited") == 0) { 1491 attempts = INFINITE_ATTEMPTS; 1492 } 1493 for (i = 0, seckey = NULL ; !seckey && (i < attempts || attempts == INFINITE_ATTEMPTS) ; i++) { 1494 if (netpgp->passfp == NULL) { 1495 /* print out the user id */ 1496 pubkey = pgp_getkeybyname(io, netpgp->pubring, userid); 1497 if (pubkey == NULL) { 1498 (void) fprintf(io->errs, 1499 "netpgp: warning - using pubkey from secring\n"); 1500 pgp_print_keydata(io, netpgp->pubring, keypair, "signature ", 1501 &keypair->key.seckey.pubkey, 0); 1502 } else { 1503 pgp_print_keydata(io, netpgp->pubring, pubkey, "signature ", 1504 &pubkey->key.pubkey, 0); 1505 } 1506 } 1507 /* now decrypt key */ 1508 seckey = pgp_decrypt_seckey(keypair, netpgp->passfp); 1509 if (seckey == NULL) { 1510 (void) fprintf(io->errs, "Bad passphrase\n"); 1511 } 1512 } 1513 if (seckey == NULL) { 1514 (void) fprintf(io->errs, "Bad passphrase\n"); 1515 return 0; 1516 } 1517 /* sign file */ 1518 (void) memset(out, 0x0, outsize); 1519 hashalg = netpgp_getvar(netpgp, "hash"); 1520 if (seckey->pubkey.alg == PGP_PKA_DSA) { 1521 hashalg = "sha1"; 1522 } 1523 signedmem = pgp_sign_buf(io, mem, size, seckey, 1524 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1525 get_duration(netpgp_getvar(netpgp, "duration")), 1526 hashalg, armored, cleartext); 1527 if (signedmem) { 1528 size_t m; 1529 1530 m = MIN(pgp_mem_len(signedmem), outsize); 1531 (void) memcpy(out, pgp_mem_data(signedmem), m); 1532 pgp_memory_free(signedmem); 1533 ret = (int)m; 1534 } else { 1535 ret = 0; 1536 } 1537 pgp_forget(seckey, (unsigned)sizeof(*seckey)); 1538 return ret; 1539 } 1540 1541 /* verify memory */ 1542 int 1543 netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size, 1544 void *out, size_t outsize, const int armored) 1545 { 1546 pgp_validation_t result; 1547 pgp_memory_t *signedmem; 1548 pgp_memory_t *cat; 1549 pgp_io_t *io; 1550 size_t m; 1551 int ret; 1552 1553 (void) memset(&result, 0x0, sizeof(result)); 1554 io = netpgp->io; 1555 if (in == NULL) { 1556 (void) fprintf(io->errs, 1557 "netpgp_verify_memory: no memory to verify\n"); 1558 return 0; 1559 } 1560 signedmem = pgp_memory_new(); 1561 pgp_memory_add(signedmem, in, size); 1562 if (out) { 1563 cat = pgp_memory_new(); 1564 } 1565 ret = pgp_validate_mem(io, &result, signedmem, 1566 (out) ? &cat : NULL, 1567 armored, netpgp->pubring); 1568 /* signedmem is freed from pgp_validate_mem */ 1569 if (ret) { 1570 resultp(io, "<stdin>", &result, netpgp->pubring); 1571 if (out) { 1572 m = MIN(pgp_mem_len(cat), outsize); 1573 (void) memcpy(out, pgp_mem_data(cat), m); 1574 pgp_memory_free(cat); 1575 } else { 1576 m = 1; 1577 } 1578 return (int)m; 1579 } 1580 if (result.validc + result.invalidc + result.unknownc == 0) { 1581 (void) fprintf(io->errs, 1582 "No signatures found - is this memory signed?\n"); 1583 } else if (result.invalidc == 0 && result.unknownc == 0) { 1584 (void) fprintf(io->errs, 1585 "memory verification failure: invalid signature time\n"); 1586 } else { 1587 (void) fprintf(io->errs, 1588 "memory verification failure: %u invalid signatures, %u unknown signatures\n", 1589 result.invalidc, result.unknownc); 1590 } 1591 return 0; 1592 } 1593 1594 /* encrypt some memory */ 1595 int 1596 netpgp_encrypt_memory(netpgp_t *netpgp, 1597 const char *userid, 1598 void *in, 1599 const size_t insize, 1600 char *out, 1601 size_t outsize, 1602 int armored) 1603 { 1604 const pgp_key_t *keypair; 1605 pgp_memory_t *enc; 1606 pgp_io_t *io; 1607 size_t m; 1608 1609 io = netpgp->io; 1610 if (in == NULL) { 1611 (void) fprintf(io->errs, 1612 "netpgp_encrypt_buf: no memory to encrypt\n"); 1613 return 0; 1614 } 1615 if ((keypair = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { 1616 return 0; 1617 } 1618 if (in == out) { 1619 (void) fprintf(io->errs, 1620 "netpgp_encrypt_buf: input and output bufs need to be different\n"); 1621 return 0; 1622 } 1623 if (outsize < insize) { 1624 (void) fprintf(io->errs, 1625 "netpgp_encrypt_buf: input size is larger than output size\n"); 1626 return 0; 1627 } 1628 enc = pgp_encrypt_buf(io, in, insize, keypair, (unsigned)armored, 1629 netpgp_getvar(netpgp, "cipher")); 1630 m = MIN(pgp_mem_len(enc), outsize); 1631 (void) memcpy(out, pgp_mem_data(enc), m); 1632 pgp_memory_free(enc); 1633 return (int)m; 1634 } 1635 1636 /* decrypt a chunk of memory */ 1637 int 1638 netpgp_decrypt_memory(netpgp_t *netpgp, const void *input, const size_t insize, 1639 char *out, size_t outsize, const int armored) 1640 { 1641 pgp_memory_t *mem; 1642 pgp_io_t *io; 1643 unsigned realarmour; 1644 unsigned sshkeys; 1645 size_t m; 1646 char *numtries; 1647 int attempts; 1648 1649 __PGP_USED(armored); 1650 io = netpgp->io; 1651 if (input == NULL) { 1652 (void) fprintf(io->errs, 1653 "netpgp_decrypt_memory: no memory\n"); 1654 return 0; 1655 } 1656 realarmour = isarmoured(io, NULL, input, ARMOR_HEAD); 1657 sshkeys = (unsigned)(netpgp_getvar(netpgp, "ssh keys") != NULL); 1658 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1659 (attempts = atoi(numtries)) <= 0) { 1660 attempts = MAX_PASSPHRASE_ATTEMPTS; 1661 } else if (strcmp(numtries, "unlimited") == 0) { 1662 attempts = INFINITE_ATTEMPTS; 1663 } 1664 mem = pgp_decrypt_buf(netpgp->io, input, insize, netpgp->secring, 1665 netpgp->pubring, 1666 realarmour, sshkeys, 1667 netpgp->passfp, 1668 attempts, 1669 get_passphrase_cb); 1670 if (mem == NULL) { 1671 return -1; 1672 } 1673 m = MIN(pgp_mem_len(mem), outsize); 1674 (void) memcpy(out, pgp_mem_data(mem), m); 1675 pgp_memory_free(mem); 1676 return (int)m; 1677 } 1678 1679 /* wrappers for the ops_debug_level functions we added to openpgpsdk */ 1680 1681 /* set the debugging level per filename */ 1682 int 1683 netpgp_set_debug(const char *f) 1684 { 1685 return pgp_set_debug_level(f); 1686 } 1687 1688 /* get the debugging level per filename */ 1689 int 1690 netpgp_get_debug(const char *f) 1691 { 1692 return pgp_get_debug_level(f); 1693 } 1694 1695 /* return the version for the library */ 1696 const char * 1697 netpgp_get_info(const char *type) 1698 { 1699 return pgp_get_info(type); 1700 } 1701 1702 /* list all the packets in a file */ 1703 int 1704 netpgp_list_packets(netpgp_t *netpgp, char *f, int armor, char *pubringname) 1705 { 1706 pgp_keyring_t *keyring; 1707 const unsigned noarmor = 0; 1708 struct stat st; 1709 pgp_io_t *io; 1710 char ringname[MAXPATHLEN]; 1711 char *homedir; 1712 int ret; 1713 1714 io = netpgp->io; 1715 if (f == NULL) { 1716 (void) fprintf(io->errs, "No file containing packets\n"); 1717 return 0; 1718 } 1719 if (stat(f, &st) < 0) { 1720 (void) fprintf(io->errs, "No such file '%s'\n", f); 1721 return 0; 1722 } 1723 homedir = netpgp_getvar(netpgp, "homedir"); 1724 if (pubringname == NULL) { 1725 (void) snprintf(ringname, sizeof(ringname), 1726 "%s/pubring.gpg", homedir); 1727 pubringname = ringname; 1728 } 1729 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 1730 (void) fprintf(io->errs, "netpgp_list_packets: bad alloc\n"); 1731 return 0; 1732 } 1733 if (!pgp_keyring_fileread(keyring, noarmor, pubringname)) { 1734 free(keyring); 1735 (void) fprintf(io->errs, "Cannot read pub keyring %s\n", 1736 pubringname); 1737 return 0; 1738 } 1739 netpgp->pubring = keyring; 1740 netpgp_setvar(netpgp, "pubring", pubringname); 1741 ret = pgp_list_packets(io, f, (unsigned)armor, 1742 netpgp->secring, 1743 netpgp->pubring, 1744 netpgp->passfp, 1745 get_passphrase_cb); 1746 free(keyring); 1747 return ret; 1748 } 1749 1750 /* set a variable */ 1751 int 1752 netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value) 1753 { 1754 char *newval; 1755 int i; 1756 1757 /* protect against the case where 'value' is netpgp->value[i] */ 1758 newval = netpgp_strdup(value); 1759 if ((i = findvar(netpgp, name)) < 0) { 1760 /* add the element to the array */ 1761 if (size_arrays(netpgp, netpgp->size + 15)) { 1762 netpgp->name[i = netpgp->c++] = netpgp_strdup(name); 1763 } 1764 } else { 1765 /* replace the element in the array */ 1766 if (netpgp->value[i]) { 1767 free(netpgp->value[i]); 1768 netpgp->value[i] = NULL; 1769 } 1770 } 1771 /* sanity checks for range of values */ 1772 if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) { 1773 if (pgp_str_to_hash_alg(newval) == PGP_HASH_UNKNOWN) { 1774 free(newval); 1775 return 0; 1776 } 1777 } 1778 netpgp->value[i] = newval; 1779 return 1; 1780 } 1781 1782 /* unset a variable */ 1783 int 1784 netpgp_unsetvar(netpgp_t *netpgp, const char *name) 1785 { 1786 int i; 1787 1788 if ((i = findvar(netpgp, name)) >= 0) { 1789 if (netpgp->value[i]) { 1790 free(netpgp->value[i]); 1791 netpgp->value[i] = NULL; 1792 } 1793 netpgp->value[i] = NULL; 1794 return 1; 1795 } 1796 return 0; 1797 } 1798 1799 /* get a variable's value (NULL if not set) */ 1800 char * 1801 netpgp_getvar(netpgp_t *netpgp, const char *name) 1802 { 1803 int i; 1804 1805 return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i]; 1806 } 1807 1808 /* increment a value */ 1809 int 1810 netpgp_incvar(netpgp_t *netpgp, const char *name, const int delta) 1811 { 1812 char *cp; 1813 char num[16]; 1814 int val; 1815 1816 val = 0; 1817 if ((cp = netpgp_getvar(netpgp, name)) != NULL) { 1818 val = atoi(cp); 1819 } 1820 (void) snprintf(num, sizeof(num), "%d", val + delta); 1821 netpgp_setvar(netpgp, name, num); 1822 return 1; 1823 } 1824 1825 /* set the home directory value to "home/subdir" */ 1826 int 1827 netpgp_set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet) 1828 { 1829 struct stat st; 1830 char d[MAXPATHLEN]; 1831 1832 if (home == NULL) { 1833 if (!quiet) { 1834 (void) fprintf(stderr, "NULL HOME directory\n"); 1835 } 1836 return 0; 1837 } 1838 (void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : ""); 1839 if (stat(d, &st) == 0) { 1840 if ((st.st_mode & S_IFMT) == S_IFDIR) { 1841 netpgp_setvar(netpgp, "homedir", d); 1842 return 1; 1843 } 1844 (void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n", 1845 d); 1846 return 0; 1847 } 1848 if (!quiet) { 1849 (void) fprintf(stderr, 1850 "netpgp: warning homedir \"%s\" not found\n", d); 1851 } 1852 netpgp_setvar(netpgp, "homedir", d); 1853 return 1; 1854 } 1855 1856 /* validate all sigs in the pub keyring */ 1857 int 1858 netpgp_validate_sigs(netpgp_t *netpgp) 1859 { 1860 pgp_validation_t result; 1861 1862 return (int)pgp_validate_all_sigs(&result, netpgp->pubring, NULL); 1863 } 1864 1865 /* print the json out on 'fp' */ 1866 int 1867 netpgp_format_json(void *vp, const char *json, const int psigs) 1868 { 1869 mj_t ids; 1870 FILE *fp; 1871 int from; 1872 int idc; 1873 int tok; 1874 int to; 1875 int i; 1876 1877 if ((fp = (FILE *)vp) == NULL || json == NULL) { 1878 return 0; 1879 } 1880 /* ids is an array of strings, each containing 1 entry */ 1881 (void) memset(&ids, 0x0, sizeof(ids)); 1882 from = to = tok = 0; 1883 /* convert from string into an mj structure */ 1884 (void) mj_parse(&ids, json, &from, &to, &tok); 1885 if ((idc = mj_arraycount(&ids)) == 1 && strchr(json, '{') == NULL) { 1886 idc = 0; 1887 } 1888 (void) fprintf(fp, "%d key%s found\n", idc, (idc == 1) ? "" : "s"); 1889 for (i = 0 ; i < idc ; i++) { 1890 format_json_key(fp, &ids.value.v[i], psigs); 1891 } 1892 /* clean up */ 1893 mj_delete(&ids); 1894 return idc; 1895 } 1896 1897 /* find a key in keyring, and write it in ssh format */ 1898 int 1899 netpgp_write_sshkey(netpgp_t *netpgp, char *s, const char *userid, char *out, size_t size) 1900 { 1901 const pgp_key_t *key; 1902 pgp_keyring_t *keyring; 1903 pgp_io_t *io; 1904 unsigned k; 1905 size_t cc; 1906 char f[MAXPATHLEN]; 1907 1908 if ((io = calloc(1, sizeof(pgp_io_t))) == NULL) { 1909 (void) fprintf(stderr, "netpgp_save_sshpub: bad alloc 1\n"); 1910 return 0; 1911 } 1912 io->outs = stdout; 1913 io->errs = stderr; 1914 io->res = stderr; 1915 netpgp->io = io; 1916 /* write new to temp file */ 1917 savepubkey(s, f, sizeof(f)); 1918 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 1919 (void) fprintf(stderr, "netpgp_save_sshpub: bad alloc 2\n"); 1920 return 0; 1921 } 1922 if (!pgp_keyring_fileread(netpgp->pubring = keyring, 1, f)) { 1923 (void) fprintf(stderr, "can't import key\n"); 1924 return 0; 1925 } 1926 /* get rsa key */ 1927 k = 0; 1928 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, userid, &k); 1929 if (key == NULL) { 1930 (void) fprintf(stderr, "no key found for '%s'\n", userid); 1931 return 0; 1932 } 1933 if (key->key.pubkey.alg != PGP_PKA_RSA) { 1934 /* we're not interested in supporting DSA either :-) */ 1935 (void) fprintf(stderr, "key not RSA '%s'\n", userid); 1936 return 0; 1937 } 1938 /* XXX - check trust sigs */ 1939 /* XXX - check expiry */ 1940 /* XXX - check start */ 1941 /* XXX - check not weak key */ 1942 /* get rsa e and n */ 1943 (void) memset(out, 0x0, size); 1944 cc = formatstring((char *)out, (const uint8_t *)"ssh-rsa", 7); 1945 cc += formatbignum((char *)&out[cc], key->key.pubkey.key.rsa.e); 1946 cc += formatbignum((char *)&out[cc], key->key.pubkey.key.rsa.n); 1947 free(io); 1948 free(keyring); 1949 return (int)cc; 1950 } 1951