/* * wrapper functions around the usign executable * Copyright (C) 2018 Daniel Golle * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * as published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include "usign.h" #ifdef UCERT_HOST_BUILD #define USIGN_EXEC "usign" #else #define USIGN_EXEC "/usr/bin/usign" #endif /* * check for revoker deadlink in pubkeydir * return true if a revoker exists, false otherwise */ int _usign_key_is_revoked(const char *fingerprint, const char *pubkeydir) { char tml[64] = {0}; char rfname[256] = {0}; snprintf(rfname, sizeof(rfname)-1, "%s/%s", pubkeydir, fingerprint); if (readlink(rfname, tml, sizeof(tml)) > 0 && !strcmp(tml, ".revoked.")) { return true; }; return false; } #ifdef UCERT_FULL /* * call usign -S ... * return WEXITSTATUS or -1 if fork fails */ int usign_s(const char *msgfile, const char *seckeyfile, const char *sigfile, bool quiet) { pid_t pid; int status; const char *usign_argv[16] = {0}; unsigned int usign_argc = 0; usign_argv[usign_argc++] = USIGN_EXEC; usign_argv[usign_argc++] = "-S"; usign_argv[usign_argc++] = "-m"; usign_argv[usign_argc++] = msgfile; usign_argv[usign_argc++] = "-s"; usign_argv[usign_argc++] = seckeyfile; usign_argv[usign_argc++] = "-x"; usign_argv[usign_argc++] = sigfile; if (quiet) usign_argv[usign_argc++] = "-q"; pid = fork(); switch (pid) { case -1: return -1; case 0: execvp(usign_argv[0], (char *const *)usign_argv); if (!quiet) perror("Failed to execute usign"); _exit(1); } waitpid(pid, &status, 0); return WIFEXITED(status) ? WEXITSTATUS(status) : -1; } #else int usign_s(const char *msgfile, const char *seckeyfile, const char *sigfile, bool quiet) { return -1; }; #endif /* * call usign -F ... and set fingerprint returned * return WEXITSTATUS or -1 if fork fails */ static int usign_f(char fingerprint[17], const char *pubkeyfile, const char *seckeyfile, const char *sigfile, bool quiet) { int fds[2]; FILE *f; pid_t pid; int status; const char *usign_argv[16] = {0}; unsigned int usign_argc = 0; if (pipe(fds)) return -1; usign_argv[usign_argc++] = USIGN_EXEC; usign_argv[usign_argc++] = "-F"; if (pubkeyfile) { usign_argv[usign_argc++] = "-p"; usign_argv[usign_argc++] = pubkeyfile; } if (seckeyfile) { usign_argv[usign_argc++] = "-s"; usign_argv[usign_argc++] = seckeyfile; } if (sigfile) { usign_argv[usign_argc++] = "-x"; usign_argv[usign_argc++] = sigfile; } pid = fork(); switch (pid) { case -1: return -1; case 0: dup2(fds[1], 1); close(fds[0]); close(fds[1]); execvp(usign_argv[0], (char *const *)usign_argv); if (!quiet) perror("Failed to execute usign"); _exit(1); } close(fds[1]); waitpid(pid, &status, 0); status = WIFEXITED(status) ? WEXITSTATUS(status) : -1; if (!fingerprint || status) { close(fds[0]); return status; } f = fdopen(fds[0], "r"); if (fread(fingerprint, 1, 16, f) != 16) status = -1; fclose(f); if (status) return status; fingerprint[16] = '\0'; if (strspn(fingerprint, "0123456789abcdefABCDEF") != 16) status = -1; return status; } /* * call usign -F -p ... */ int usign_f_pubkey(char fingerprint[17], const char *pubkeyfile, bool quiet) { return usign_f(fingerprint, pubkeyfile, NULL, NULL, quiet); } /* * call usign -F -s ... */ int usign_f_seckey(char fingerprint[17], const char *seckeyfile, bool quiet) { return usign_f(fingerprint, NULL, seckeyfile, NULL, quiet); } /* * call usign -F -x ... */ int usign_f_sig(char fingerprint[17], const char *sigfile, bool quiet) { return usign_f(fingerprint, NULL, NULL, sigfile, quiet); } /* * call usign -V ... * return WEXITSTATUS or -1 if fork fails */ int usign_v(const char *msgfile, const char *pubkeyfile, const char *pubkeydir, const char *sigfile, bool quiet) { pid_t pid; int status; const char *usign_argv[16] = {0}; unsigned int usign_argc = 0; char fingerprint[17]; if (usign_f_sig(fingerprint, sigfile, quiet)) { if (!quiet) fprintf(stderr, "cannot get signing key fingerprint\n"); return 1; } if (pubkeydir && _usign_key_is_revoked(fingerprint, pubkeydir)) { if (!quiet) fprintf(stderr, "key %s has been revoked!\n", fingerprint); return 1; } usign_argv[usign_argc++] = USIGN_EXEC; usign_argv[usign_argc++] = "-V"; usign_argv[usign_argc++] = "-m"; usign_argv[usign_argc++] = msgfile; if (quiet) usign_argv[usign_argc++] = "-q"; if (pubkeyfile) { usign_argv[usign_argc++] = "-p"; usign_argv[usign_argc++] = pubkeyfile; } if (pubkeydir) { usign_argv[usign_argc++] = "-P"; usign_argv[usign_argc++] = pubkeydir; } if (sigfile) { usign_argv[usign_argc++] = "-x"; usign_argv[usign_argc++] = sigfile; } pid = fork(); switch (pid) { case -1: return -1; case 0: execvp(usign_argv[0], (char *const *)usign_argv); if (!quiet) perror("Failed to execute usign"); _exit(1); } waitpid(pid, &status, 0); return WIFEXITED(status) ? WEXITSTATUS(status) : -1; }