70319fa5809ee436511bfb14296ea1e7c0009146
[oweals/ucert.git] / usign-exec.c
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
15 #include <stdbool.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <sys/wait.h>
20
21 #include "usign.h"
22
23 /*
24  * check for revoker deadlink in pubkeydir
25  * return true if a revoker exists, false otherwise
26  */
27 int _usign_key_is_revoked(const char *fingerprint, const char *pubkeydir) {
28         char tml[64] = {0};
29         char rfname[256] = {0};
30
31         snprintf(rfname, sizeof(rfname)-1, "%s/%s", pubkeydir, fingerprint);
32         if (readlink(rfname, tml, sizeof(tml)) > 0 &&
33             !strcmp(tml, ".revoked.")) {
34                 return true;
35         };
36
37         return false;
38 }
39
40 #ifdef UCERT_FULL
41 /*
42  * call usign -S ...
43  * return WEXITSTATUS or -1 if fork or execv fails
44  */
45 int usign_s(const char *msgfile, const char *seckeyfile, const char *sigfile, bool quiet) {
46         pid_t pid;
47         int status;
48         const char *usign_argv[16] = {0};
49         unsigned int usign_argc = 0;
50
51         usign_argv[usign_argc++] = "/usr/bin/usign";
52         usign_argv[usign_argc++] = "-S";
53         usign_argv[usign_argc++] = "-m";
54         usign_argv[usign_argc++] = msgfile;
55         usign_argv[usign_argc++] = "-s";
56         usign_argv[usign_argc++] = seckeyfile;
57         usign_argv[usign_argc++] = "-x";
58         usign_argv[usign_argc++] = sigfile;
59
60         if (quiet)
61                 usign_argv[usign_argc++] = "-q";
62
63         pid = fork();
64         switch (pid) {
65         case -1:
66                 return -1;
67
68         case 0:
69                 if (execv(usign_argv[0], usign_argv))
70                         return -1;
71
72                 break;
73
74         default:
75                 waitpid(pid, &status, 0);
76                 return WEXITSTATUS(status);
77         }
78
79         return -1;
80 }
81 #else
82 int usign_s(const char *msgfile, const char *seckeyfile, const char *sigfile, bool quiet) {
83         return -1;
84 };
85 #endif
86
87 /*
88  * call usign -F ... and set fingerprint returned
89  * return WEXITSTATUS or -1 if fork or execv fails
90  */
91 static int usign_f(char *fingerprint, const char *pubkeyfile, const char *seckeyfile, const char *sigfile) {
92         int fds[2];
93         pid_t pid;
94         int status;
95         const char *usign_argv[16] = {0};
96         unsigned int usign_argc = 0;
97
98         if (pipe(fds))
99                 return -1;
100
101         usign_argv[usign_argc++] = "/usr/bin/usign";
102         usign_argv[usign_argc++] = "-F";
103
104         if (pubkeyfile) {
105                 usign_argv[usign_argc++] = "-p";
106                 usign_argv[usign_argc++] = pubkeyfile;
107         }
108
109         if (seckeyfile) {
110                 usign_argv[usign_argc++] = "-s";
111                 usign_argv[usign_argc++] = seckeyfile;
112         }
113
114         if (sigfile) {
115                 usign_argv[usign_argc++] = "-x";
116                 usign_argv[usign_argc++] = sigfile;
117         }
118
119         pid = fork();
120         switch (pid) {
121         case -1:
122                 return -1;
123
124         case 0:
125                 dup2(fds[1], 1);
126
127                 close(0);
128                 close(2);
129                 close(fds[0]);
130                 close(fds[1]);
131
132                 if (execv(usign_argv[0], usign_argv))
133                         return -1;
134
135                 break;
136
137         default:
138                 waitpid(pid, &status, 0);
139                 if (fingerprint && !WEXITSTATUS(status)) {
140                         memset(fingerprint, 0, 16);
141                         read(fds[0], fingerprint, 16);
142                         fingerprint[16] = '\0';
143                 }
144                 close(fds[0]);
145                 close(fds[1]);
146                 return WEXITSTATUS(status);
147         }
148
149         return -1;
150 }
151
152 /*
153  * call usign -F -p ...
154  */
155 int usign_f_pubkey(char *fingerprint, const char *pubkeyfile) {
156         return usign_f(fingerprint, pubkeyfile, NULL, NULL);
157 }
158
159 /*
160  * call usign -F -s ...
161  */
162 int usign_f_seckey(char *fingerprint, const char *seckeyfile) {
163         return usign_f(fingerprint, NULL, seckeyfile, NULL);
164 }
165
166 /*
167  * call usign -F -x ...
168  */
169 int usign_f_sig(char *fingerprint, const char *sigfile) {
170         return usign_f(fingerprint, NULL, NULL, sigfile);
171 }
172
173
174 /*
175  * call usign -V ...
176  * return WEXITSTATUS or -1 if fork or execv fails
177  */
178 int usign_v(const char *msgfile, const char *pubkeyfile,
179             const char *pubkeydir, const char *sigfile, bool quiet) {
180         pid_t pid;
181         int status;
182         const char *usign_argv[16] = {0};
183         unsigned int usign_argc = 0;
184         char fingerprint[17];
185
186         if (usign_f_sig(fingerprint, sigfile)) {
187                 if (!quiet)
188                         fprintf(stdout, "cannot get signing key fingerprint\n");
189                 return 1;
190         }
191
192         if (pubkeydir && _usign_key_is_revoked(fingerprint, pubkeydir)) {
193                 if (!quiet)
194                         fprintf(stdout, "key %s has been revoked!\n", fingerprint);
195                 return 1;
196         }
197         usign_argv[usign_argc++] = "/usr/bin/usign";
198         usign_argv[usign_argc++] = "-V";
199         usign_argv[usign_argc++] = "-m";
200         usign_argv[usign_argc++] = msgfile;
201
202         if (quiet)
203                 usign_argv[usign_argc++] = "-q";
204
205         if (pubkeyfile) {
206                 usign_argv[usign_argc++] = "-p";
207                 usign_argv[usign_argc++] = pubkeyfile;
208         }
209
210         if (pubkeydir) {
211                 usign_argv[usign_argc++] = "-P";
212                 usign_argv[usign_argc++] = pubkeydir;
213         }
214
215         if (sigfile) {
216                 usign_argv[usign_argc++] = "-x";
217                 usign_argv[usign_argc++] = sigfile;
218         }
219
220         pid = fork();
221         switch (pid) {
222         case -1:
223                 return -1;
224
225         case 0:
226                 if (execv(usign_argv[0], usign_argv))
227                         return -1;
228
229                 break;
230
231         default:
232                 waitpid(pid, &status, 0);
233                 return WEXITSTATUS(status);
234         }
235
236         return -1;
237 }