int libmail_gpg_checksign(const char *gpgdir, const char *content, const char *signature, int (*dump_func)(const char *, size_t, void *), void *voidarg) { char *argvec[10]; int rc; argvec[0]="gpg"; argvec[1]="--no-tty"; argvec[2]="--verify"; argvec[3]=(char *)signature; argvec[4]=(char *)content; argvec[5]=0; if (libmail_gpg_fork(&libmail_gpg_stdin, &libmail_gpg_stdout, &libmail_gpg_stderr, gpgdir, argvec) < 0) rc= -1; else { int rc2; rc=dochecksign(dump_func, voidarg); rc2=libmail_gpg_cleanup(); if (rc2) rc=rc2; } return (rc); }
static void checksign(struct mimestack **stack, int *iseof, struct header *h, FILE *fpin, FILE *fpout, int argc, char **argv) { char buf[BUFSIZ]; struct header *h2; char signed_content[TEMPNAMEBUFSIZE]; char signature[TEMPNAMEBUFSIZE]; int signed_file, signature_file; FILE *signed_file_fp, *signature_file_fp; int clos_flag; int need_nl, check_boundary; struct mimestack *b=0; struct mime_header *mh; int qpdecode=0; signed_file=mimegpg_tempfile(signed_content); if (signed_file < 0 || (signed_file_fp=fdopen(signed_file, "w+")) == 0) { if (signed_file > 0) { close(signed_file); unlink(signed_content); } perror("open"); exit(1); } noexec(signed_file_fp); find_boundary(stack, iseof, fpin, NULL, 0); if (*iseof) return; need_nl=0; check_boundary=1; while (!*iseof) { const char *p; if (fgets(buf, sizeof(buf), fpin) == NULL) { *iseof=1; continue; } if (check_boundary && (b=is_boundary(*stack, buf, &clos_flag)) != 0) break; if (need_nl) fprintf(signed_file_fp, "\r\n"); for (p=buf; *p && *p != '\n'; p++) putc(*p, signed_file_fp); need_nl=check_boundary= *p != 0; } if (my_rewind(signed_file_fp) < 0) { perror(signed_content); fclose(signed_file_fp); unlink(signed_content); exit(1); } if (clos_flag) { fclose(signed_file_fp); unlink(signed_content); if (b) pop_mimestack_to(stack, b); find_boundary(stack, iseof, fpin, fpout, 1); return; } h=read_headers(stack, iseof, fpin, fpout, 0); if (!h || !(h2=find_header(h, "content-type:"))) { fclose(signed_file_fp); unlink(signed_content); if (!*iseof) find_boundary(stack, iseof, fpin, fpout, 1); return; } mh=parse_mime_header(h2->header+sizeof("content-type:")-1); if (!mh) { perror("malloc"); free_header(h); fclose(signed_file_fp); unlink(signed_content); exit(1); } if (!mh || strcasecmp(mh->header_name, "application/pgp-signature")) { if (!mh) free_mime_header(mh); free_header(h); fclose(signed_file_fp); unlink(signed_content); if (!*iseof) find_boundary(stack, iseof, fpin, fpout, 1); return; } free_mime_header(mh); /* ** In rare instances, the signature is qp-encoded. */ if ((h2=find_header(h, "content-transfer-encoding:")) != NULL) { mh=parse_mime_header(h2->header +sizeof("content-transfer-encoding:")-1); if (!mh) { perror("malloc"); free_header(h); fclose(signed_file_fp); unlink(signed_content); exit(1); } if (strcasecmp(mh->header_name, "quoted-printable") == 0) qpdecode=1; free_mime_header(mh); } free_header(h); signature_file=mimegpg_tempfile(signature); if (signature_file < 0 || (signature_file_fp=fdopen(signature_file, "w+")) == 0) { if (signature_file > 0) { close(signature_file); unlink(signature); } fclose(signed_file_fp); unlink(signed_content); perror("open"); exit(1); } while (!*iseof) { const char *p; if (fgets(buf, sizeof(buf), fpin) == NULL) { *iseof=1; continue; } if ((b=is_boundary(*stack, buf, &clos_flag)) != 0) break; for (p=buf; *p; p++) { int n; if (!qpdecode) { putc(*p, signature_file_fp); continue; } if (*p == '=' && p[1] == '\n') break; if (*p == '=' && p[1] && p[2]) { n=nybble(p[1]) * 16 + nybble(p[2]); if ( (char)n ) { putc((char)n, signature_file_fp); p += 2; } p += 2; continue; } putc(*p, signature_file_fp); /* If some spits out qp-lines > BUFSIZ, they deserve ** this crap. */ } } fflush(signature_file_fp); if (ferror(signature_file_fp) || fclose(signature_file_fp)) { unlink(signature); fclose(signed_file_fp); unlink(signed_content); perror("open"); exit(1); } dochecksign(*stack, signed_file_fp, fpout, signed_content, signature, argc, argv); fclose(signed_file_fp); unlink(signature); unlink(signed_content); fprintf(fpout, "\n--%s--\n", b->boundary); while (!clos_flag) { if (fgets(buf, sizeof(buf), fpin) == NULL) { *iseof=1; break; } if (!(b=is_boundary(*stack, buf, &clos_flag))) clos_flag=0; } if (b) pop_mimestack_to(stack, b); if (iseof) return; }