X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=usign-exec.c;h=482e51057124a883805c02aa72799233464acad2;hb=HEAD;hp=91129883d25ad332ed519b0c50e526709b1fc75c;hpb=4fc3c57bb0a1c4699e09d576ce23ad809b038106;p=project%2Fucert.git diff --git a/usign-exec.c b/usign-exec.c index 9112988..482e510 100644 --- a/usign-exec.c +++ b/usign-exec.c @@ -1,66 +1,60 @@ +/* + * 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" -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; - - usign_argv[usign_argc++] = "/usr/bin/usign"; - 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: - if (execv(usign_argv[0], usign_argv)) - return -1; - - break; - - default: - waitpid(pid, &status, 0); - return WEXITSTATUS(status); - } - - return -1; +#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++] = "/usr/bin/usign"; + usign_argv[usign_argc++] = USIGN_EXEC; usign_argv[usign_argc++] = "-S"; usign_argv[usign_argc++] = "-m"; usign_argv[usign_argc++] = msgfile; @@ -78,21 +72,28 @@ int usign_s(const char *msgfile, const char *seckeyfile, const char *sigfile, bo return -1; case 0: - if (execv(usign_argv[0], usign_argv)) - return -1; - - break; - - default: - waitpid(pid, &status, 0); - return WEXITSTATUS(status); + execvp(usign_argv[0], (char *const *)usign_argv); + if (!quiet) + perror("Failed to execute usign"); + _exit(1); } - return -1; + waitpid(pid, &status, 0); + return WIFEXITED(status) ? WEXITSTATUS(status) : -1; } - -static int usign_f(char *fingerprint, const char *pubkeyfile, const char *seckeyfile, const char *sigfile) { +#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}; @@ -101,7 +102,7 @@ static int usign_f(char *fingerprint, const char *pubkeyfile, const char *seckey if (pipe(fds)) return -1; - usign_argv[usign_argc++] = "/usr/bin/usign"; + usign_argv[usign_argc++] = USIGN_EXEC; usign_argv[usign_argc++] = "-F"; if (pubkeyfile) { @@ -127,39 +128,119 @@ static int usign_f(char *fingerprint, const char *pubkeyfile, const char *seckey case 0: dup2(fds[1], 1); - close(0); - close(2); close(fds[0]); close(fds[1]); - if (execv(usign_argv[0], usign_argv)) - return -1; + execvp(usign_argv[0], (char *const *)usign_argv); + if (!quiet) + perror("Failed to execute usign"); + _exit(1); + } + + close(fds[1]); - break; + waitpid(pid, &status, 0); + status = WIFEXITED(status) ? WEXITSTATUS(status) : -1; - default: - waitpid(pid, &status, 0); - if (fingerprint && !WEXITSTATUS(status)) { - memset(fingerprint, 0, 16); - read(fds[0], fingerprint, 16); - fingerprint[16] = '\0'; - } + if (!fingerprint || status) { close(fds[0]); - close(fds[1]); - return WEXITSTATUS(status); + return status; } - return -1; + 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); } -int usign_f_pubkey(char *fingerprint, const char *pubkeyfile) { - return usign_f(fingerprint, pubkeyfile, NULL, NULL); +/* + * call usign -F -s ... + */ +int usign_f_seckey(char fingerprint[17], const char *seckeyfile, bool quiet) { + return usign_f(fingerprint, NULL, seckeyfile, NULL, quiet); } -int usign_f_seckey(char *fingerprint, const char *seckeyfile) { - return usign_f(fingerprint, NULL, seckeyfile, NULL); +/* + * call usign -F -x ... + */ +int usign_f_sig(char fingerprint[17], const char *sigfile, bool quiet) { + return usign_f(fingerprint, NULL, NULL, sigfile, quiet); } -int usign_f_sig(char *fingerprint, const char *sigfile) { - return usign_f(fingerprint, NULL, NULL, sigfile); + +/* + * 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; }