Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2013-2014 Baptiste Daroussin <bapt@FreeBSD.org>
3 : : * Copyright (c) 2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions
8 : : * are met:
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer
11 : : * in this position and unchanged.
12 : : * 2. Redistributions in binary form must reproduce the above copyright
13 : : * notice, this list of conditions and the following disclaimer in the
14 : : * documentation and/or other materials provided with the distribution.
15 : : *
16 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : : */
27 : :
28 : : #ifdef HAVE_CONFIG_H
29 : : #include "pkg_config.h"
30 : : #endif
31 : : #ifdef HAVE_CAPSICUM
32 : : #include <sys/capsicum.h>
33 : : #endif
34 : : #include <sys/types.h>
35 : : #include <sys/param.h>
36 : : #include <sys/stat.h>
37 : :
38 : : #include <ctype.h>
39 : : #include <stdlib.h>
40 : : #include <inttypes.h>
41 : : #include <stdio.h>
42 : : #include <string.h>
43 : : #include <unistd.h>
44 : : #include <fcntl.h>
45 : :
46 : : #include <bsd_compat.h>
47 : :
48 : : #include "pkg.h"
49 : : #include "private/event.h"
50 : :
51 : : int
52 : 0 : pkg_sshserve(int fd)
53 : : {
54 : : struct stat st;
55 : 0 : char *line = NULL;
56 : : char *file, *age;
57 : 0 : size_t linecap = 0, r;
58 : : ssize_t linelen;
59 : 0 : time_t mtime = 0;
60 : : const char *errstr;
61 : : int ffd;
62 : : char buf[32768];
63 : : char fpath[MAXPATHLEN];
64 : : char rpath[MAXPATHLEN];
65 : 0 : const char *restricted = NULL;
66 : :
67 : 0 : restricted = pkg_object_string(pkg_config_get("SSH_RESTRICT_DIR"));
68 : :
69 : 0 : printf("ok: pkg "PKGVERSION"\n");
70 : 0 : for (;;) {
71 [ # # ]: 0 : if ((linelen = getline(&line, &linecap, stdin)) < 0)
72 : 0 : break;
73 : :
74 [ # # ]: 0 : if (linelen == 0)
75 : 0 : continue;
76 : :
77 : : /* trim cr */
78 [ # # ]: 0 : if (line[linelen - 1] == '\n')
79 : 0 : line[linelen - 1] = '\0';
80 : :
81 [ # # ]: 0 : if (strcmp(line, "quit") == 0)
82 : 0 : return (EPKG_OK);
83 : :
84 [ # # ]: 0 : if (strncmp(line, "get ", 4) != 0) {
85 : 0 : printf("ko: unknown command '%s'\n", line);
86 : 0 : continue;
87 : : }
88 : :
89 : 0 : file = line + 4;
90 : :
91 [ # # ]: 0 : if (*file == '/')
92 : 0 : file++;
93 [ # # ]: 0 : else if (*file == '\0') {
94 : 0 : printf("ko: bad command get, expecting 'get file age'\n");
95 : 0 : continue;
96 : : }
97 : :
98 : 0 : pkg_debug(1, "SSH server> file requested: %s", file);
99 : :
100 : 0 : age = file;
101 [ # # ]: 0 : while (!isspace(*age)) {
102 [ # # ]: 0 : if (*age == '\0') {
103 : 0 : age = NULL;
104 : 0 : break;
105 : : }
106 : 0 : age++;
107 : : }
108 : :
109 [ # # ]: 0 : if (age == NULL) {
110 : 0 : printf("ko: bad command get, expecting 'get file age'\n");
111 : 0 : continue;
112 : : }
113 : :
114 : 0 : *age = '\0';
115 : 0 : age++;
116 : :
117 [ # # ]: 0 : while (isspace(*age)) {
118 [ # # ]: 0 : if (*age == '\0') {
119 : 0 : age = NULL;
120 : 0 : break;
121 : : }
122 : 0 : age++;
123 : : }
124 : :
125 [ # # ]: 0 : if (age == NULL) {
126 : 0 : printf("ko: bad command get, expecting 'get file age'\n");
127 : 0 : continue;
128 : : }
129 : :
130 : 0 : mtime = strtonum(age, 0, LONG_MAX, &errstr);
131 [ # # ]: 0 : if (errstr) {
132 : 0 : printf("ko: bad number %s: %s\n", age, errstr);
133 : 0 : continue;
134 : : }
135 : :
136 : : #ifdef HAVE_CAPSICUM
137 [ # # # # ]: 0 : if (!cap_sandboxed() && restricted != NULL) {
138 : : #else
139 : : if (restricted != NULL) {
140 : : #endif
141 [ # # ]: 0 : if (chdir(restricted)) {
142 : 0 : printf("ko: chdir failed (%s)\n", restricted);
143 : 0 : continue;
144 : : }
145 : :
146 [ # # # # ]: 0 : if (realpath(file, fpath) == NULL ||
147 [ # # ]: 0 : realpath(restricted, rpath) == NULL ||
148 : 0 : strncmp(fpath, rpath, strlen(rpath)) != 0) {
149 : 0 : printf("ko: file not found\n");
150 : 0 : continue;
151 : : }
152 : 0 : }
153 : :
154 [ # # ]: 0 : if (fstatat(fd, file, &st, 0) == -1) {
155 : 0 : pkg_debug(1, "SSH server> fstatat failed");
156 : 0 : printf("ko: file not found\n");
157 : 0 : continue;
158 : : }
159 : :
160 [ # # ]: 0 : if (!S_ISREG(st.st_mode)) {
161 : 0 : printf("ko: not a file\n");
162 : 0 : continue;
163 : : }
164 : :
165 [ # # ]: 0 : if (st.st_mtime <= mtime) {
166 : 0 : printf("ok: 0\n");
167 : 0 : continue;
168 : : }
169 : :
170 [ # # ]: 0 : if ((ffd = openat(fd, file, O_RDONLY)) == -1) {
171 : 0 : printf("ko: file not found\n");
172 : 0 : continue;
173 : : }
174 : :
175 : 0 : printf("ok: %" PRIdMAX "\n", (intmax_t)st.st_size);
176 : 0 : pkg_debug(1, "SSH server> sending ok: %" PRIdMAX "", (intmax_t)st.st_size);
177 : :
178 [ # # ]: 0 : while ((r = read(ffd, buf, sizeof(buf))) > 0) {
179 : 0 : pkg_debug(1, "SSH server> sending data");
180 : 0 : fwrite(buf, 1, r, stdout);
181 : : }
182 : :
183 : 0 : pkg_debug(1, "SSH server> finished");
184 : :
185 : 0 : close(ffd);
186 : : }
187 : :
188 : 0 : free(line);
189 : :
190 : 0 : return (EPKG_OK);
191 : 0 : }
|