Annotation of pkgsrc/pkgtools/pkg_install/files/lib/gpgsig.c, Revision 1.3
1.3 ! joerg 1: /* $NetBSD: gpgsig.c,v 1.2 2009/02/02 12:35:01 joerg Exp $ */
1.2 joerg 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
9:
1.3 ! joerg 10: __RCSID("$NetBSD: gpgsig.c,v 1.2 2009/02/02 12:35:01 joerg Exp $");
1.2 joerg 11:
12: /*-
13: * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
14: * All rights reserved.
15: *
16: * Redistribution and use in source and binary forms, with or without
17: * modification, are permitted provided that the following conditions
18: * are met:
19: *
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.
26: *
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.
39: */
40:
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
52:
53: #include "lib.h"
54:
55: static void
56: verify_signature(const char *input, size_t input_len, const char *keyring,
57: const char *detached_signature)
58: {
59: const char *argv[8], **argvp;
60: pid_t child;
61: int fd[2], status;
62:
63: if (pipe(fd) == -1)
64: err(EXIT_FAILURE, "cannot create input pipes");
65:
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);
77: }
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;
86: }
87:
88: if (detached_signature != NULL)
89: *argvp++ = detached_signature;
90: *argvp++ = "-";
91:
92: *argvp = NULL;
93:
94: execvp(gpg_cmd, __UNCONST(argv));
95: _exit(255);
96: }
97: close(fd[0]);
1.3 ! joerg 98: if (write(fd[1], input, input_len) != (ssize_t)input_len)
1.2 joerg 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");
104: }
105:
106: int
107: inline_gpg_verify(const char *content, size_t len, const char *keyring)
108: {
109: verify_signature(content, len, keyring, NULL);
110:
111: return 0;
112: }
113:
114: int
115: detached_gpg_verify(const char *content, size_t len,
116: const char *signature, size_t signature_len, const char *keyring)
117: {
118: int fd;
119: const char *tmpdir;
120: char *tempsig;
121: ssize_t ret;
122:
123: if (gpg_cmd == NULL) {
124: warnx("GPG variable not set, failing signature check");
125: return -1;
126: }
127:
128: if ((tmpdir = getenv("TMPDIR")) == NULL)
129: tmpdir = "/tmp";
130: tempsig = xasprintf("%s/pkg_install.XXXXXX", tmpdir);
131:
132: fd = mkstemp(tempsig);
133: if (fd == -1) {
134: warnx("Creating temporary file for GPG signature failed");
135: return -1;
136: }
137:
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;
146: }
147:
148: verify_signature(content, len, keyring, tempsig);
149:
150: unlink(tempsig);
151: close(fd);
152: free(tempsig);
153:
154: return 0;
155: }
156:
157: int
158: detached_gpg_sign(const char *content, size_t len, char **sig, size_t *sig_len,
159: const char *keyring, const char *user)
160: {
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;
166:
167: if (gpg_cmd == NULL)
168: errx(EXIT_FAILURE, "GPG variable not set");
169:
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");
174:
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);
186: }
187: close(fd_in[0]);
188:
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);
196: }
197: close(fd_out[1]);
198:
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;
208: }
209: if (keyring != NULL) {
210: *argvp++ = "--no-default-keyring";
211: *argvp++ = "--secret-keyring";
212: *argvp++ = keyring;
213: }
214:
215: *argvp++ = "-";
216: *argvp = NULL;
217:
218: execvp(gpg_cmd, __UNCONST(argv));
219: _exit(255);
220: }
221: close(fd_in[0]);
1.3 ! joerg 222: if (write(fd_in[1], content, len) != (ssize_t)len)
1.2 joerg 223: errx(EXIT_FAILURE, "Short read from GPG");
224: close(fd_in[1]);
225:
226: allocated = 1024;
227: *sig = xmalloc(allocated);
228: *sig_len = 0;
229:
230: close(fd_out[1]);
231:
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);
238: }
239: }
240:
241: close(fd_out[0]);
242:
243: waitpid(child, &status, 0);
244: if (status)
245: errx(EXIT_FAILURE, "GPG could not create signature");
246:
247: return 0;
248: }
CVSweb <webmaster@jp.NetBSD.org>