usign-exec.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * wrapper functions around the usign executable
  3. * Copyright (C) 2018 Daniel Golle <daniel@makrotopia.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 3
  7. * as published by the Free Software Foundation
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <stdbool.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include <sys/wait.h>
  19. #include "usign.h"
  20. #ifdef UCERT_HOST_BUILD
  21. #define USIGN_EXEC "usign"
  22. #else
  23. #define USIGN_EXEC "/usr/bin/usign"
  24. #endif
  25. /*
  26. * check for revoker deadlink in pubkeydir
  27. * return true if a revoker exists, false otherwise
  28. */
  29. int _usign_key_is_revoked(const char *fingerprint, const char *pubkeydir) {
  30. char tml[64] = {0};
  31. char rfname[256] = {0};
  32. snprintf(rfname, sizeof(rfname)-1, "%s/%s", pubkeydir, fingerprint);
  33. if (readlink(rfname, tml, sizeof(tml)) > 0 &&
  34. !strcmp(tml, ".revoked.")) {
  35. return true;
  36. };
  37. return false;
  38. }
  39. #ifdef UCERT_FULL
  40. /*
  41. * call usign -S ...
  42. * return WEXITSTATUS or -1 if fork or execv fails
  43. */
  44. int usign_s(const char *msgfile, const char *seckeyfile, const char *sigfile, bool quiet) {
  45. pid_t pid;
  46. int status;
  47. const char *usign_argv[16] = {0};
  48. unsigned int usign_argc = 0;
  49. usign_argv[usign_argc++] = USIGN_EXEC;
  50. usign_argv[usign_argc++] = "-S";
  51. usign_argv[usign_argc++] = "-m";
  52. usign_argv[usign_argc++] = msgfile;
  53. usign_argv[usign_argc++] = "-s";
  54. usign_argv[usign_argc++] = seckeyfile;
  55. usign_argv[usign_argc++] = "-x";
  56. usign_argv[usign_argc++] = sigfile;
  57. if (quiet)
  58. usign_argv[usign_argc++] = "-q";
  59. pid = fork();
  60. switch (pid) {
  61. case -1:
  62. return -1;
  63. case 0:
  64. if (
  65. #ifdef UCERT_HOST_BUILD
  66. execvp(usign_argv[0], (char *const *)usign_argv)
  67. #else
  68. execv(usign_argv[0], (char *const *)usign_argv)
  69. #endif
  70. )
  71. return -1;
  72. break;
  73. default:
  74. waitpid(pid, &status, 0);
  75. return WEXITSTATUS(status);
  76. }
  77. return -1;
  78. }
  79. #else
  80. int usign_s(const char *msgfile, const char *seckeyfile, const char *sigfile, bool quiet) {
  81. return -1;
  82. };
  83. #endif
  84. /*
  85. * call usign -F ... and set fingerprint returned
  86. * return WEXITSTATUS or -1 if fork or execv fails
  87. */
  88. static int usign_f(char *fingerprint, const char *pubkeyfile, const char *seckeyfile, const char *sigfile) {
  89. int fds[2];
  90. pid_t pid;
  91. int status;
  92. const char *usign_argv[16] = {0};
  93. unsigned int usign_argc = 0;
  94. if (pipe(fds))
  95. return -1;
  96. usign_argv[usign_argc++] = USIGN_EXEC;
  97. usign_argv[usign_argc++] = "-F";
  98. if (pubkeyfile) {
  99. usign_argv[usign_argc++] = "-p";
  100. usign_argv[usign_argc++] = pubkeyfile;
  101. }
  102. if (seckeyfile) {
  103. usign_argv[usign_argc++] = "-s";
  104. usign_argv[usign_argc++] = seckeyfile;
  105. }
  106. if (sigfile) {
  107. usign_argv[usign_argc++] = "-x";
  108. usign_argv[usign_argc++] = sigfile;
  109. }
  110. pid = fork();
  111. switch (pid) {
  112. case -1:
  113. return -1;
  114. case 0:
  115. dup2(fds[1], 1);
  116. close(0);
  117. close(2);
  118. close(fds[0]);
  119. close(fds[1]);
  120. if (
  121. #ifdef UCERT_HOST_BUILD
  122. execvp(usign_argv[0], (char *const *)usign_argv)
  123. #else
  124. execv(usign_argv[0], (char *const *)usign_argv)
  125. #endif
  126. )
  127. return -1;
  128. break;
  129. default:
  130. waitpid(pid, &status, 0);
  131. status = WEXITSTATUS(status);
  132. if (fingerprint && !WEXITSTATUS(status)) {
  133. ssize_t r;
  134. memset(fingerprint, 0, 17);
  135. r = read(fds[0], fingerprint, 17);
  136. if (r < 16)
  137. status = -1;
  138. fingerprint[16] = '\0';
  139. }
  140. close(fds[0]);
  141. close(fds[1]);
  142. return status;
  143. }
  144. return -1;
  145. }
  146. /*
  147. * call usign -F -p ...
  148. */
  149. int usign_f_pubkey(char *fingerprint, const char *pubkeyfile) {
  150. return usign_f(fingerprint, pubkeyfile, NULL, NULL);
  151. }
  152. /*
  153. * call usign -F -s ...
  154. */
  155. int usign_f_seckey(char *fingerprint, const char *seckeyfile) {
  156. return usign_f(fingerprint, NULL, seckeyfile, NULL);
  157. }
  158. /*
  159. * call usign -F -x ...
  160. */
  161. int usign_f_sig(char *fingerprint, const char *sigfile) {
  162. return usign_f(fingerprint, NULL, NULL, sigfile);
  163. }
  164. /*
  165. * call usign -V ...
  166. * return WEXITSTATUS or -1 if fork or execv fails
  167. */
  168. int usign_v(const char *msgfile, const char *pubkeyfile,
  169. const char *pubkeydir, const char *sigfile, bool quiet) {
  170. pid_t pid;
  171. int status;
  172. const char *usign_argv[16] = {0};
  173. unsigned int usign_argc = 0;
  174. char fingerprint[17];
  175. if (usign_f_sig(fingerprint, sigfile)) {
  176. if (!quiet)
  177. fprintf(stdout, "cannot get signing key fingerprint\n");
  178. return 1;
  179. }
  180. if (pubkeydir && _usign_key_is_revoked(fingerprint, pubkeydir)) {
  181. if (!quiet)
  182. fprintf(stdout, "key %s has been revoked!\n", fingerprint);
  183. return 1;
  184. }
  185. usign_argv[usign_argc++] = USIGN_EXEC;
  186. usign_argv[usign_argc++] = "-V";
  187. usign_argv[usign_argc++] = "-m";
  188. usign_argv[usign_argc++] = msgfile;
  189. if (quiet)
  190. usign_argv[usign_argc++] = "-q";
  191. if (pubkeyfile) {
  192. usign_argv[usign_argc++] = "-p";
  193. usign_argv[usign_argc++] = pubkeyfile;
  194. }
  195. if (pubkeydir) {
  196. usign_argv[usign_argc++] = "-P";
  197. usign_argv[usign_argc++] = pubkeydir;
  198. }
  199. if (sigfile) {
  200. usign_argv[usign_argc++] = "-x";
  201. usign_argv[usign_argc++] = sigfile;
  202. }
  203. pid = fork();
  204. switch (pid) {
  205. case -1:
  206. return -1;
  207. case 0:
  208. if (
  209. #ifdef UCERT_HOST_BUILD
  210. execvp(usign_argv[0], (char *const *)usign_argv)
  211. #else
  212. execv(usign_argv[0], (char *const *)usign_argv)
  213. #endif
  214. )
  215. return -1;
  216. break;
  217. default:
  218. waitpid(pid, &status, 0);
  219. return WEXITSTATUS(status);
  220. }
  221. return -1;
  222. }