Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / bsd / pkg_install / dist / lib / gpgsig.c
blob6f9aa1bdf214f8756fab49f4e28214d051c7922c
1 /* $NetBSD: gpgsig.c,v 1.3 2009/08/02 17:56:45 joerg Exp $ */
2 #if HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 #include <nbcompat.h>
6 #if HAVE_SYS_CDEFS_H
7 #include <sys/cdefs.h>
8 #endif
10 __RCSID("$NetBSD: gpgsig.c,v 1.3 2009/08/02 17:56:45 joerg Exp $");
12 /*-
13 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
14 * All rights reserved.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in
24 * the documentation and/or other materials provided with the
25 * distribution.
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
33 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
35 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
37 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
41 #include <sys/wait.h>
42 #ifndef NETBSD
43 #include <nbcompat/err.h>
44 #else
45 #include <err.h>
46 #endif
47 #ifndef NETBSD
48 #include <nbcompat/stdlib.h>
49 #else
50 #include <stdlib.h>
51 #endif
53 #include "lib.h"
55 static void
56 verify_signature(const char *input, size_t input_len, const char *keyring,
57 const char *detached_signature)
59 const char *argv[8], **argvp;
60 pid_t child;
61 int fd[2], status;
63 if (pipe(fd) == -1)
64 err(EXIT_FAILURE, "cannot create input pipes");
66 child = vfork();
67 if (child == -1)
68 err(EXIT_FAILURE, "cannot fork GPG process");
69 if (child == 0) {
70 close(fd[1]);
71 close(STDIN_FILENO);
72 if (dup2(fd[0], STDIN_FILENO) == -1) {
73 static const char err_msg[] =
74 "cannot redirect stdin of GPG process\n";
75 write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1);
76 _exit(255);
78 close(fd[0]);
79 argvp = argv;
80 *argvp++ = gpg_cmd;
81 *argvp++ = "--verify";
82 if (keyring != NULL) {
83 *argvp++ = "--no-default-keyring";
84 *argvp++ = "--keyring";
85 *argvp++ = keyring;
88 if (detached_signature != NULL)
89 *argvp++ = detached_signature;
90 *argvp++ = "-";
92 *argvp = NULL;
94 execvp(gpg_cmd, __UNCONST(argv));
95 _exit(255);
97 close(fd[0]);
98 if (write(fd[1], input, input_len) != (ssize_t)input_len)
99 errx(EXIT_FAILURE, "Short read from GPG");
100 close(fd[1]);
101 waitpid(child, &status, 0);
102 if (status)
103 errx(EXIT_FAILURE, "GPG could not verify the signature");
107 inline_gpg_verify(const char *content, size_t len, const char *keyring)
109 verify_signature(content, len, keyring, NULL);
111 return 0;
115 detached_gpg_verify(const char *content, size_t len,
116 const char *signature, size_t signature_len, const char *keyring)
118 int fd;
119 const char *tmpdir;
120 char *tempsig;
121 ssize_t ret;
123 if (gpg_cmd == NULL) {
124 warnx("GPG variable not set, failing signature check");
125 return -1;
128 if ((tmpdir = getenv("TMPDIR")) == NULL)
129 tmpdir = "/tmp";
130 tempsig = xasprintf("%s/pkg_install.XXXXXX", tmpdir);
132 fd = mkstemp(tempsig);
133 if (fd == -1) {
134 warnx("Creating temporary file for GPG signature failed");
135 return -1;
138 while (signature_len) {
139 ret = write(fd, signature, signature_len);
140 if (ret == -1)
141 err(EXIT_FAILURE, "Write to GPG failed");
142 if (ret == 0)
143 errx(EXIT_FAILURE, "Short write to GPG");
144 signature_len -= ret;
145 signature += ret;
148 verify_signature(content, len, keyring, tempsig);
150 unlink(tempsig);
151 close(fd);
152 free(tempsig);
154 return 0;
158 detached_gpg_sign(const char *content, size_t len, char **sig, size_t *sig_len,
159 const char *keyring, const char *user)
161 const char *argv[12], **argvp;
162 pid_t child;
163 int fd_in[2], fd_out[2], status;
164 size_t allocated;
165 ssize_t ret;
167 if (gpg_cmd == NULL)
168 errx(EXIT_FAILURE, "GPG variable not set");
170 if (pipe(fd_in) == -1)
171 err(EXIT_FAILURE, "cannot create input pipes");
172 if (pipe(fd_out) == -1)
173 err(EXIT_FAILURE, "cannot create output pipes");
175 child = fork();
176 if (child == -1)
177 err(EXIT_FAILURE, "cannot fork GPG process");
178 if (child == 0) {
179 close(fd_in[1]);
180 close(STDIN_FILENO);
181 if (dup2(fd_in[0], STDIN_FILENO) == -1) {
182 static const char err_msg[] =
183 "cannot redirect stdin of GPG process\n";
184 write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1);
185 _exit(255);
187 close(fd_in[0]);
189 close(fd_out[0]);
190 close(STDOUT_FILENO);
191 if (dup2(fd_out[1], STDOUT_FILENO) == -1) {
192 static const char err_msg[] =
193 "cannot redirect stdout of GPG process\n";
194 write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1);
195 _exit(255);
197 close(fd_out[1]);
199 argvp = argv;
200 *argvp++ = gpg_cmd;
201 *argvp++ = "--detach-sign";
202 *argvp++ = "--armor";
203 *argvp++ = "--output";
204 *argvp++ = "-";
205 if (user != NULL) {
206 *argvp++ = "--local-user";
207 *argvp++ = user;
209 if (keyring != NULL) {
210 *argvp++ = "--no-default-keyring";
211 *argvp++ = "--secret-keyring";
212 *argvp++ = keyring;
215 *argvp++ = "-";
216 *argvp = NULL;
218 execvp(gpg_cmd, __UNCONST(argv));
219 _exit(255);
221 close(fd_in[0]);
222 if (write(fd_in[1], content, len) != (ssize_t)len)
223 errx(EXIT_FAILURE, "Short read from GPG");
224 close(fd_in[1]);
226 allocated = 1024;
227 *sig = xmalloc(allocated);
228 *sig_len = 0;
230 close(fd_out[1]);
232 while ((ret = read(fd_out[0], *sig + *sig_len,
233 allocated - *sig_len)) > 0) {
234 *sig_len += ret;
235 if (*sig_len == allocated) {
236 allocated *= 2;
237 *sig = xrealloc(*sig, allocated);
241 close(fd_out[0]);
243 waitpid(child, &status, 0);
244 if (status)
245 errx(EXIT_FAILURE, "GPG could not create signature");
247 return 0;