Blame


1 d65a88a2 2021-09-05 stsp /*
2 d65a88a2 2021-09-05 stsp * Copyright (c) 2018, 2019 Ori Bernstein <ori@openbsd.org>
3 d65a88a2 2021-09-05 stsp * Copyright (c) 2021 Stefan Sperling <stsp@openbsd.org>
4 d65a88a2 2021-09-05 stsp *
5 d65a88a2 2021-09-05 stsp * Permission to use, copy, modify, and distribute this software for any
6 d65a88a2 2021-09-05 stsp * purpose with or without fee is hereby granted, provided that the above
7 d65a88a2 2021-09-05 stsp * copyright notice and this permission notice appear in all copies.
8 d65a88a2 2021-09-05 stsp *
9 d65a88a2 2021-09-05 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 d65a88a2 2021-09-05 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 d65a88a2 2021-09-05 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 d65a88a2 2021-09-05 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 d65a88a2 2021-09-05 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 d65a88a2 2021-09-05 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 d65a88a2 2021-09-05 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 d65a88a2 2021-09-05 stsp */
17 d65a88a2 2021-09-05 stsp
18 d65a88a2 2021-09-05 stsp #include <sys/types.h>
19 d65a88a2 2021-09-05 stsp #include <sys/socket.h>
20 d65a88a2 2021-09-05 stsp #include <netdb.h>
21 d65a88a2 2021-09-05 stsp
22 d65a88a2 2021-09-05 stsp #include <err.h>
23 d65a88a2 2021-09-05 stsp #include <stdio.h>
24 d65a88a2 2021-09-05 stsp #include <stdlib.h>
25 d65a88a2 2021-09-05 stsp #include <string.h>
26 d65a88a2 2021-09-05 stsp #include <unistd.h>
27 d65a88a2 2021-09-05 stsp
28 d65a88a2 2021-09-05 stsp #include "got_error.h"
29 d65a88a2 2021-09-05 stsp
30 d65a88a2 2021-09-05 stsp #include "got_lib_dial.h"
31 d65a88a2 2021-09-05 stsp
32 d65a88a2 2021-09-05 stsp #ifndef ssizeof
33 d65a88a2 2021-09-05 stsp #define ssizeof(_x) ((ssize_t)(sizeof(_x)))
34 d65a88a2 2021-09-05 stsp #endif
35 d65a88a2 2021-09-05 stsp
36 d65a88a2 2021-09-05 stsp #ifndef MIN
37 d65a88a2 2021-09-05 stsp #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
38 d65a88a2 2021-09-05 stsp #endif
39 d65a88a2 2021-09-05 stsp
40 d65a88a2 2021-09-05 stsp #ifndef GOT_DIAL_PATH_SSH
41 d65a88a2 2021-09-05 stsp #define GOT_DIAL_PATH_SSH "/usr/bin/ssh"
42 d65a88a2 2021-09-05 stsp #endif
43 d65a88a2 2021-09-05 stsp
44 d65a88a2 2021-09-05 stsp /* IANA assigned */
45 d65a88a2 2021-09-05 stsp #define GOT_DEFAULT_GIT_PORT 9418
46 d65a88a2 2021-09-05 stsp #define GOT_DEFAULT_GIT_PORT_STR "9418"
47 d65a88a2 2021-09-05 stsp
48 d65a88a2 2021-09-05 stsp const struct got_error *
49 d65a88a2 2021-09-05 stsp got_dial_apply_unveil(const char *proto)
50 d65a88a2 2021-09-05 stsp {
51 d65a88a2 2021-09-05 stsp if (strcmp(proto, "git+ssh") == 0 || strcmp(proto, "ssh") == 0) {
52 d65a88a2 2021-09-05 stsp if (unveil(GOT_DIAL_PATH_SSH, "x") != 0) {
53 d65a88a2 2021-09-05 stsp return got_error_from_errno2("unveil",
54 d65a88a2 2021-09-05 stsp GOT_DIAL_PATH_SSH);
55 d65a88a2 2021-09-05 stsp }
56 d65a88a2 2021-09-05 stsp }
57 d65a88a2 2021-09-05 stsp
58 d65a88a2 2021-09-05 stsp return NULL;
59 d65a88a2 2021-09-05 stsp }
60 d65a88a2 2021-09-05 stsp
61 d65a88a2 2021-09-05 stsp const struct got_error *
62 d65a88a2 2021-09-05 stsp got_dial_ssh(pid_t *newpid, int *newfd, const char *host,
63 d65a88a2 2021-09-05 stsp const char *port, const char *path, const char *direction, int verbosity)
64 d65a88a2 2021-09-05 stsp {
65 d65a88a2 2021-09-05 stsp const struct got_error *error = NULL;
66 d65a88a2 2021-09-05 stsp int pid, pfd[2];
67 d65a88a2 2021-09-05 stsp char cmd[64];
68 d65a88a2 2021-09-05 stsp char *argv[11];
69 d65a88a2 2021-09-05 stsp int i = 0, j;
70 d65a88a2 2021-09-05 stsp
71 d65a88a2 2021-09-05 stsp *newpid = -1;
72 d65a88a2 2021-09-05 stsp *newfd = -1;
73 d65a88a2 2021-09-05 stsp
74 d65a88a2 2021-09-05 stsp argv[i++] = GOT_DIAL_PATH_SSH;
75 d65a88a2 2021-09-05 stsp if (port != NULL) {
76 d65a88a2 2021-09-05 stsp argv[i++] = "-p";
77 d65a88a2 2021-09-05 stsp argv[i++] = (char *)port;
78 d65a88a2 2021-09-05 stsp }
79 d65a88a2 2021-09-05 stsp if (verbosity == -1) {
80 d65a88a2 2021-09-05 stsp argv[i++] = "-q";
81 d65a88a2 2021-09-05 stsp } else {
82 d65a88a2 2021-09-05 stsp /* ssh(1) allows up to 3 "-v" options. */
83 d65a88a2 2021-09-05 stsp for (j = 0; j < MIN(3, verbosity); j++)
84 d65a88a2 2021-09-05 stsp argv[i++] = "-v";
85 d65a88a2 2021-09-05 stsp }
86 d65a88a2 2021-09-05 stsp argv[i++] = "--";
87 d65a88a2 2021-09-05 stsp argv[i++] = (char *)host;
88 d65a88a2 2021-09-05 stsp argv[i++] = (char *)cmd;
89 d65a88a2 2021-09-05 stsp argv[i++] = (char *)path;
90 d65a88a2 2021-09-05 stsp argv[i++] = NULL;
91 d65a88a2 2021-09-05 stsp
92 d65a88a2 2021-09-05 stsp if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pfd) == -1)
93 d65a88a2 2021-09-05 stsp return got_error_from_errno("socketpair");
94 d65a88a2 2021-09-05 stsp
95 d65a88a2 2021-09-05 stsp pid = fork();
96 d65a88a2 2021-09-05 stsp if (pid == -1) {
97 d65a88a2 2021-09-05 stsp error = got_error_from_errno("fork");
98 d65a88a2 2021-09-05 stsp close(pfd[0]);
99 d65a88a2 2021-09-05 stsp close(pfd[1]);
100 d65a88a2 2021-09-05 stsp return error;
101 d65a88a2 2021-09-05 stsp } else if (pid == 0) {
102 d65a88a2 2021-09-05 stsp int n;
103 d65a88a2 2021-09-05 stsp if (close(pfd[1]) == -1)
104 d65a88a2 2021-09-05 stsp err(1, "close");
105 d65a88a2 2021-09-05 stsp if (dup2(pfd[0], 0) == -1)
106 d65a88a2 2021-09-05 stsp err(1, "dup2");
107 d65a88a2 2021-09-05 stsp if (dup2(pfd[0], 1) == -1)
108 d65a88a2 2021-09-05 stsp err(1, "dup2");
109 d65a88a2 2021-09-05 stsp n = snprintf(cmd, sizeof(cmd), "git-%s-pack", direction);
110 d65a88a2 2021-09-05 stsp if (n < 0 || n >= ssizeof(cmd))
111 d65a88a2 2021-09-05 stsp err(1, "snprintf");
112 d65a88a2 2021-09-05 stsp if (execv(GOT_DIAL_PATH_SSH, argv) == -1)
113 d65a88a2 2021-09-05 stsp err(1, "execv");
114 d65a88a2 2021-09-05 stsp abort(); /* not reached */
115 d65a88a2 2021-09-05 stsp } else {
116 d65a88a2 2021-09-05 stsp if (close(pfd[0]) == -1)
117 d65a88a2 2021-09-05 stsp return got_error_from_errno("close");
118 d65a88a2 2021-09-05 stsp *newpid = pid;
119 d65a88a2 2021-09-05 stsp *newfd = pfd[1];
120 d65a88a2 2021-09-05 stsp return NULL;
121 d65a88a2 2021-09-05 stsp }
122 d65a88a2 2021-09-05 stsp }
123 d65a88a2 2021-09-05 stsp
124 d65a88a2 2021-09-05 stsp const struct got_error *
125 d65a88a2 2021-09-05 stsp got_dial_git(int *newfd, const char *host, const char *port,
126 d65a88a2 2021-09-05 stsp const char *path, const char *direction)
127 d65a88a2 2021-09-05 stsp {
128 d65a88a2 2021-09-05 stsp const struct got_error *err = NULL;
129 d65a88a2 2021-09-05 stsp struct addrinfo hints, *servinfo, *p;
130 d65a88a2 2021-09-05 stsp char *cmd = NULL;
131 d65a88a2 2021-09-05 stsp int fd = -1, len, r, eaicode;
132 d65a88a2 2021-09-05 stsp
133 d65a88a2 2021-09-05 stsp *newfd = -1;
134 d65a88a2 2021-09-05 stsp
135 d65a88a2 2021-09-05 stsp if (port == NULL)
136 d65a88a2 2021-09-05 stsp port = GOT_DEFAULT_GIT_PORT_STR;
137 d65a88a2 2021-09-05 stsp
138 d65a88a2 2021-09-05 stsp memset(&hints, 0, sizeof hints);
139 d65a88a2 2021-09-05 stsp hints.ai_family = AF_UNSPEC;
140 d65a88a2 2021-09-05 stsp hints.ai_socktype = SOCK_STREAM;
141 d65a88a2 2021-09-05 stsp eaicode = getaddrinfo(host, port, &hints, &servinfo);
142 d65a88a2 2021-09-05 stsp if (eaicode) {
143 d65a88a2 2021-09-05 stsp char msg[512];
144 d65a88a2 2021-09-05 stsp snprintf(msg, sizeof(msg), "%s: %s", host,
145 d65a88a2 2021-09-05 stsp gai_strerror(eaicode));
146 d65a88a2 2021-09-05 stsp return got_error_msg(GOT_ERR_ADDRINFO, msg);
147 d65a88a2 2021-09-05 stsp }
148 d65a88a2 2021-09-05 stsp
149 d65a88a2 2021-09-05 stsp for (p = servinfo; p != NULL; p = p->ai_next) {
150 d65a88a2 2021-09-05 stsp if ((fd = socket(p->ai_family, p->ai_socktype,
151 d65a88a2 2021-09-05 stsp p->ai_protocol)) == -1)
152 d65a88a2 2021-09-05 stsp continue;
153 d65a88a2 2021-09-05 stsp if (connect(fd, p->ai_addr, p->ai_addrlen) == 0) {
154 d65a88a2 2021-09-05 stsp err = NULL;
155 d65a88a2 2021-09-05 stsp break;
156 d65a88a2 2021-09-05 stsp }
157 d65a88a2 2021-09-05 stsp err = got_error_from_errno("connect");
158 d65a88a2 2021-09-05 stsp close(fd);
159 d65a88a2 2021-09-05 stsp }
160 d65a88a2 2021-09-05 stsp if (p == NULL)
161 d65a88a2 2021-09-05 stsp goto done;
162 d65a88a2 2021-09-05 stsp
163 d65a88a2 2021-09-05 stsp if (asprintf(&cmd, "git-%s-pack %s", direction, path) == -1) {
164 d65a88a2 2021-09-05 stsp err = got_error_from_errno("asprintf");
165 d65a88a2 2021-09-05 stsp goto done;
166 d65a88a2 2021-09-05 stsp }
167 d65a88a2 2021-09-05 stsp len = 4 + strlen(cmd) + 1 + strlen("host=") + strlen(host) + 1;
168 d65a88a2 2021-09-05 stsp r = dprintf(fd, "%04x%s%chost=%s%c", len, cmd, '\0', host, '\0');
169 d65a88a2 2021-09-05 stsp if (r < 0)
170 d65a88a2 2021-09-05 stsp err = got_error_from_errno("dprintf");
171 d65a88a2 2021-09-05 stsp done:
172 d65a88a2 2021-09-05 stsp free(cmd);
173 d65a88a2 2021-09-05 stsp if (err) {
174 d65a88a2 2021-09-05 stsp if (fd != -1)
175 d65a88a2 2021-09-05 stsp close(fd);
176 d65a88a2 2021-09-05 stsp } else
177 d65a88a2 2021-09-05 stsp *newfd = fd;
178 d65a88a2 2021-09-05 stsp return err;
179 d65a88a2 2021-09-05 stsp }