imain.c - geomyidae - A small C-based gopherd. Err bitreich.org 70 hgit clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ URL:git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ bitreich.org 70 1Log /scm/geomyidae/log.gph bitreich.org 70 1Files /scm/geomyidae/files.gph bitreich.org 70 1Refs /scm/geomyidae/refs.gph bitreich.org 70 1Tags /scm/geomyidae/tag bitreich.org 70 1README /scm/geomyidae/file/README.gph bitreich.org 70 1LICENSE /scm/geomyidae/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 imain.c (28355B) Err bitreich.org 70 i--- Err bitreich.org 70 i 1 /* Err bitreich.org 70 i 2 * Copy me if you can. Err bitreich.org 70 i 3 * by 20h Err bitreich.org 70 i 4 */ Err bitreich.org 70 i 5 Err bitreich.org 70 i 6 #include Err bitreich.org 70 i 7 #include Err bitreich.org 70 i 8 #include Err bitreich.org 70 i 9 #include Err bitreich.org 70 i 10 #include Err bitreich.org 70 i 11 #include Err bitreich.org 70 i 12 #include Err bitreich.org 70 i 13 #include Err bitreich.org 70 i 14 #include Err bitreich.org 70 i 15 #include Err bitreich.org 70 i 16 #include Err bitreich.org 70 i 17 #include Err bitreich.org 70 i 18 #include Err bitreich.org 70 i 19 #include Err bitreich.org 70 i 20 #include Err bitreich.org 70 i 21 #include Err bitreich.org 70 i 22 #include Err bitreich.org 70 i 23 #include Err bitreich.org 70 i 24 #include Err bitreich.org 70 i 25 #include Err bitreich.org 70 i 26 #include Err bitreich.org 70 i 27 #include Err bitreich.org 70 i 28 #include Err bitreich.org 70 i 29 #include Err bitreich.org 70 i 30 #include Err bitreich.org 70 i 31 Err bitreich.org 70 i 32 #ifdef ENABLE_TLS Err bitreich.org 70 i 33 #include Err bitreich.org 70 i 34 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 35 Err bitreich.org 70 i 36 #include "ind.h" Err bitreich.org 70 i 37 #include "handlr.h" Err bitreich.org 70 i 38 #include "arg.h" Err bitreich.org 70 i 39 Err bitreich.org 70 i 40 enum { Err bitreich.org 70 i 41 NOLOG = 0, Err bitreich.org 70 i 42 FILES = 1, Err bitreich.org 70 i 43 DIRS = 2, Err bitreich.org 70 i 44 HTTP = 4, Err bitreich.org 70 i 45 ERRORS = 8, Err bitreich.org 70 i 46 CONN = 16, Err bitreich.org 70 i 47 GPLUS = 32 Err bitreich.org 70 i 48 }; Err bitreich.org 70 i 49 Err bitreich.org 70 i 50 int glfd = -1; Err bitreich.org 70 i 51 int dosyslog = 0; Err bitreich.org 70 i 52 int logpriority = LOG_INFO|LOG_DAEMON; Err bitreich.org 70 i 53 int loglvl = 47; Err bitreich.org 70 i 54 int revlookup = 0; Err bitreich.org 70 i 55 char *logfile = NULL; Err bitreich.org 70 i 56 Err bitreich.org 70 i 57 int *listfds = NULL; Err bitreich.org 70 i 58 int nlistfds = 0; Err bitreich.org 70 i 59 Err bitreich.org 70 i 60 char *argv0; Err bitreich.org 70 i 61 char stdbase[] = "/var/gopher"; Err bitreich.org 70 i 62 char *stdport = "70"; Err bitreich.org 70 i 63 char *indexf[] = {"index.gph", "index.cgi", "index.dcgi", "index.bob", "index.bin"}; Err bitreich.org 70 i 64 Err bitreich.org 70 i 65 char *nocgierr = "3Sorry, execution of the token '%s' was requested, but this " Err bitreich.org 70 i 66 "is disabled in the server configuration.\tErr" Err bitreich.org 70 i 67 "\tlocalhost\t70\r\n"; Err bitreich.org 70 i 68 Err bitreich.org 70 i 69 char *notfounderr = "3Sorry, but the requested token '%s' could not be found.\tErr" Err bitreich.org 70 i 70 "\tlocalhost\t70\r\n"; Err bitreich.org 70 i 71 Err bitreich.org 70 i 72 char *toolongerr = "3Sorry, but the requested token '%s' is a too long path.\tErr" Err bitreich.org 70 i 73 "\tlocalhost\t70\r\n"; Err bitreich.org 70 i 74 Err bitreich.org 70 i 75 char *tlserr = "3Sorry, but the requested token '%s' requires an encrypted connection.\tErr" Err bitreich.org 70 i 76 "\tlocalhost\t70\r\n"; Err bitreich.org 70 i 77 Err bitreich.org 70 i 78 /* TODO: Transform gopherspace to not need this anymore. See sacc(1). */ Err bitreich.org 70 i 79 char *htredir = "\n" Err bitreich.org 70 i 80 "gopher redirect\n" Err bitreich.org 70 i 81 "\n" Err bitreich.org 70 i 82 "\n" Err bitreich.org 70 i 83 "Please consider using native gopher 'w' type.\n" Err bitreich.org 70 i 84 "HTML is insecure and bloated.
\n" Err bitreich.org 70 i 85 "You will be redirected to: %s.\n" Err bitreich.org 70 i 86 "\n"; Err bitreich.org 70 i 87 Err bitreich.org 70 i 88 char *htescape = "3Happy helping ☃ here: " Err bitreich.org 70 i 89 "Sorry, your URI was not properly escaped." Err bitreich.org 70 i 90 "\tErr\tlocalhost\t70\r\n.\r\n\r\n"; Err bitreich.org 70 i 91 Err bitreich.org 70 i 92 char *selinval = "3Happy helping ☃ here: " Err bitreich.org 70 i 93 "Sorry, your selector does contains '..'. " Err bitreich.org 70 i 94 "That's illegal here.\tErr\tlocalhost\t70\r\n.\r\n\r\n"; Err bitreich.org 70 i 95 Err bitreich.org 70 i 96 int Err bitreich.org 70 i 97 dropprivileges(struct group *gr, struct passwd *pw) Err bitreich.org 70 i 98 { Err bitreich.org 70 i 99 if (gr != NULL) Err bitreich.org 70 i 100 if (setgroups(1, &gr->gr_gid) != 0 || setgid(gr->gr_gid) != 0) Err bitreich.org 70 i 101 return -1; Err bitreich.org 70 i 102 if (pw != NULL) { Err bitreich.org 70 i 103 if (gr == NULL) { Err bitreich.org 70 i 104 if (setgroups(1, &pw->pw_gid) != 0 || Err bitreich.org 70 i 105 setgid(pw->pw_gid) != 0) Err bitreich.org 70 i 106 return -1; Err bitreich.org 70 i 107 } Err bitreich.org 70 i 108 if (setuid(pw->pw_uid) != 0) Err bitreich.org 70 i 109 return -1; Err bitreich.org 70 i 110 } Err bitreich.org 70 i 111 Err bitreich.org 70 i 112 return 0; Err bitreich.org 70 i 113 } Err bitreich.org 70 i 114 Err bitreich.org 70 i 115 void Err bitreich.org 70 i 116 logentry(char *host, char *port, char *qry, char *status) Err bitreich.org 70 i 117 { Err bitreich.org 70 i 118 time_t tim; Err bitreich.org 70 i 119 struct tm *ptr; Err bitreich.org 70 i 120 char timstr[128], *ahost; Err bitreich.org 70 i 121 Err bitreich.org 70 i 122 if (glfd >= 0 || dosyslog) { Err bitreich.org 70 i 123 ahost = revlookup ? reverselookup(host) : host; Err bitreich.org 70 i 124 if (dosyslog) { Err bitreich.org 70 i 125 syslog(logpriority, "[%s|%s|%s] %s\n", ahost, port, Err bitreich.org 70 i 126 status, qry); Err bitreich.org 70 i 127 } else { Err bitreich.org 70 i 128 tim = time(0); Err bitreich.org 70 i 129 ptr = gmtime(&tim); Err bitreich.org 70 i 130 strftime(timstr, sizeof(timstr), "%F %T %z", ptr); Err bitreich.org 70 i 131 dprintf(glfd, "[%s|%s|%s|%s] %s\n", Err bitreich.org 70 i 132 timstr, ahost, port, status, qry); Err bitreich.org 70 i 133 } Err bitreich.org 70 i 134 if (revlookup) Err bitreich.org 70 i 135 free(ahost); Err bitreich.org 70 i 136 } Err bitreich.org 70 i 137 Err bitreich.org 70 i 138 return; Err bitreich.org 70 i 139 } Err bitreich.org 70 i 140 Err bitreich.org 70 i 141 void Err bitreich.org 70 i 142 handlerequest(int sock, char *req, int rlen, char *base, char *ohost, Err bitreich.org 70 i 143 char *port, char *clienth, char *clientp, char *serverh, Err bitreich.org 70 i 144 char *serverp, int nocgi, int istls) Err bitreich.org 70 i 145 { Err bitreich.org 70 i 146 struct stat dir; Err bitreich.org 70 i 147 char recvc[1025], recvb[1025], path[PATH_MAX+1], args[1025], Err bitreich.org 70 i 148 argsc[1025], traverse[1025], traversec[1025], Err bitreich.org 70 i 149 *sear, *sep, *recvbp, *c; Err bitreich.org 70 i 150 int len = 0, fd, i, maxrecv, pathfallthrough = 0; Err bitreich.org 70 i 151 filetype *type; Err bitreich.org 70 i 152 Err bitreich.org 70 i 153 if (!istls) { Err bitreich.org 70 i 154 /* Err bitreich.org 70 i 155 * If sticky bit is set on base dir and encryption is not Err bitreich.org 70 i 156 * used, do not serve. Err bitreich.org 70 i 157 */ Err bitreich.org 70 i 158 if (stat(*base? base : "/", &dir) == -1) Err bitreich.org 70 i 159 return; Err bitreich.org 70 i 160 if (dir.st_mode & S_ISVTX) { Err bitreich.org 70 i 161 dprintf(sock, tlserr, recvc); Err bitreich.org 70 i 162 if (loglvl & ERRORS) { Err bitreich.org 70 i 163 logentry(clienth, clientp, recvc, Err bitreich.org 70 i 164 "encryption only"); Err bitreich.org 70 i 165 } Err bitreich.org 70 i 166 return; Err bitreich.org 70 i 167 } Err bitreich.org 70 i 168 } Err bitreich.org 70 i 169 Err bitreich.org 70 i 170 memset(&dir, 0, sizeof(dir)); Err bitreich.org 70 i 171 memset(recvb, 0, sizeof(recvb)); Err bitreich.org 70 i 172 memset(recvc, 0, sizeof(recvc)); Err bitreich.org 70 i 173 memset(args, 0, sizeof(args)); Err bitreich.org 70 i 174 memset(argsc, 0, sizeof(argsc)); Err bitreich.org 70 i 175 memset(traverse, 0, sizeof(traverse)); Err bitreich.org 70 i 176 memset(traversec, 0, sizeof(traversec)); Err bitreich.org 70 i 177 Err bitreich.org 70 i 178 maxrecv = sizeof(recvb) - 1; Err bitreich.org 70 i 179 if (rlen > maxrecv || rlen < 0) Err bitreich.org 70 i 180 return; Err bitreich.org 70 i 181 memcpy(recvb, req, rlen); Err bitreich.org 70 i 182 Err bitreich.org 70 i 183 c = strchr(recvb, '\r'); Err bitreich.org 70 i 184 if (c) Err bitreich.org 70 i 185 c[0] = '\0'; Err bitreich.org 70 i 186 c = strchr(recvb, '\n'); Err bitreich.org 70 i 187 if (c) Err bitreich.org 70 i 188 c[0] = '\0'; Err bitreich.org 70 i 189 Err bitreich.org 70 i 190 memmove(recvc, recvb, rlen+1); Err bitreich.org 70 i 191 /* Err bitreich.org 70 i 192 * Try to guess if we have some HTTP-like protocol compatibility Err bitreich.org 70 i 193 * mode. Err bitreich.org 70 i 194 */ Err bitreich.org 70 i 195 if (!nocgi && recvb[0] != '/' && (c = strchr(recvb, ' '))) { Err bitreich.org 70 i 196 *c = '\0'; Err bitreich.org 70 i 197 if (strchr(recvb, '/')) Err bitreich.org 70 i 198 goto dothegopher; Err bitreich.org 70 i 199 if (snprintf(path, sizeof(path), "%s/%s", base, recvb) <= sizeof(path)) { Err bitreich.org 70 i 200 if (stat(path, &dir) == 0) { Err bitreich.org 70 i 201 if (loglvl & FILES) Err bitreich.org 70 i 202 logentry(clienth, clientp, recvc, "compatibility serving"); Err bitreich.org 70 i 203 Err bitreich.org 70 i 204 handlecgi(sock, path, port, base, "", "", ohost, Err bitreich.org 70 i 205 clienth, serverh, istls, req, ""); Err bitreich.org 70 i 206 return; Err bitreich.org 70 i 207 } Err bitreich.org 70 i 208 } Err bitreich.org 70 i 209 dothegopher: Err bitreich.org 70 i 210 *c = ' '; Err bitreich.org 70 i 211 } Err bitreich.org 70 i 212 Err bitreich.org 70 i 213 /* Do not allow requests including "..". */ Err bitreich.org 70 i 214 if (strstr(recvb, "..")) { Err bitreich.org 70 i 215 dprintf(sock, "%s", selinval); Err bitreich.org 70 i 216 return; Err bitreich.org 70 i 217 } Err bitreich.org 70 i 218 Err bitreich.org 70 i 219 sear = strchr(recvb, '\t'); Err bitreich.org 70 i 220 if (sear != NULL) { Err bitreich.org 70 i 221 *sear++ = '\0'; Err bitreich.org 70 i 222 Err bitreich.org 70 i 223 /* Err bitreich.org 70 i 224 * This is a compatibility layer to geomyidae for users using Err bitreich.org 70 i 225 * the original gopher(1) client. Gopher+ is by default Err bitreich.org 70 i 226 * requesting the metadata. We are using a trick in the Err bitreich.org 70 i 227 * gopher(1) parsing code to jump back to gopher compatibility Err bitreich.org 70 i 228 * mode. DO NOT ADD ANY OTHER GOPHER+ SUPPORT. GOPHER+ IS Err bitreich.org 70 i 229 * CRAP. Err bitreich.org 70 i 230 */ Err bitreich.org 70 i 231 if ((sear[0] == '+' && sear[1] == '\0') Err bitreich.org 70 i 232 || (sear[0] == '$' && sear[1] == '\0') Err bitreich.org 70 i 233 || (sear[0] == '!' && sear[1] == '\0') Err bitreich.org 70 i 234 || sear[0] == '\0') { Err bitreich.org 70 i 235 if (loglvl & GPLUS) Err bitreich.org 70 i 236 logentry(clienth, clientp, recvb, "gopher+ redirect"); Err bitreich.org 70 i 237 dprintf(sock, "+-2\r\n"); Err bitreich.org 70 i 238 dprintf(sock, "+INFO: 1gopher+\t\t%s\t%s\r\n", Err bitreich.org 70 i 239 ohost, port); Err bitreich.org 70 i 240 dprintf(sock, "+ADMIN:\r\n Admin: Me\r\n"); Err bitreich.org 70 i 241 return; Err bitreich.org 70 i 242 } Err bitreich.org 70 i 243 } Err bitreich.org 70 i 244 Err bitreich.org 70 i 245 memmove(recvc, recvb, rlen+1); Err bitreich.org 70 i 246 Err bitreich.org 70 i 247 /* Redirect to HTML redirecting to the specified URI. */ Err bitreich.org 70 i 248 /* TODO: Fix gopherspace to not require this. */ Err bitreich.org 70 i 249 if (!strncmp(recvb, "URL:", 4)) { Err bitreich.org 70 i 250 for (i = 4; i < sizeof(recvb)-1; i++) { Err bitreich.org 70 i 251 switch (recvb[i]) { Err bitreich.org 70 i 252 case '\0': Err bitreich.org 70 i 253 i = sizeof(recvb); Err bitreich.org 70 i 254 break; Err bitreich.org 70 i 255 case '"': Err bitreich.org 70 i 256 case '&': Err bitreich.org 70 i 257 case '>': Err bitreich.org 70 i 258 case '<': Err bitreich.org 70 i 259 case ' ': Err bitreich.org 70 i 260 case '\'': Err bitreich.org 70 i 261 case '\\': Err bitreich.org 70 i 262 write(sock, htescape, strlen(htescape)); Err bitreich.org 70 i 263 if (loglvl & ERRORS) Err bitreich.org 70 i 264 logentry(clienth, clientp, recvc, "Unescaped HTTP redirect"); Err bitreich.org 70 i 265 return; Err bitreich.org 70 i 266 } Err bitreich.org 70 i 267 } Err bitreich.org 70 i 268 len = snprintf(path, sizeof(path), htredir, Err bitreich.org 70 i 269 recvb + 4, recvb + 4, recvb + 4); Err bitreich.org 70 i 270 if (len > sizeof(path)) Err bitreich.org 70 i 271 len = sizeof(path); Err bitreich.org 70 i 272 write(sock, path, len); Err bitreich.org 70 i 273 if (loglvl & HTTP) Err bitreich.org 70 i 274 logentry(clienth, clientp, recvc, "HTTP redirect"); Err bitreich.org 70 i 275 return; Err bitreich.org 70 i 276 } Err bitreich.org 70 i 277 Err bitreich.org 70 i 278 /* Strip off the arguments of req?args style. */ Err bitreich.org 70 i 279 c = strchr(recvb, '?'); Err bitreich.org 70 i 280 if (c != NULL) { Err bitreich.org 70 i 281 *c++ = '\0'; Err bitreich.org 70 i 282 snprintf(args, sizeof(args), "%s", c); Err bitreich.org 70 i 283 } Err bitreich.org 70 i 284 Err bitreich.org 70 i 285 /* Strip '/' at the end of the request. */ Err bitreich.org 70 i 286 for (c = recvb + strlen(recvb) - 1; c >= recvb && c[0] == '/'; c--) { Err bitreich.org 70 i 287 memmove(traversec, traverse, strlen(traverse)); Err bitreich.org 70 i 288 /* Prepend to traverse. */ Err bitreich.org 70 i 289 snprintf(traverse, sizeof(traverse), "/%s", traversec); Err bitreich.org 70 i 290 c[0] = '\0'; Err bitreich.org 70 i 291 } Err bitreich.org 70 i 292 Err bitreich.org 70 i 293 /* path is now always at least '/' */ Err bitreich.org 70 i 294 if (snprintf(path, sizeof(path), "%s%s%s", base, Err bitreich.org 70 i 295 (*recvb != '/')? "/" : "", Err bitreich.org 70 i 296 recvb) > sizeof(path)) { Err bitreich.org 70 i 297 if (loglvl & ERRORS) { Err bitreich.org 70 i 298 logentry(clienth, clientp, recvc, Err bitreich.org 70 i 299 "path truncation occurred"); Err bitreich.org 70 i 300 } Err bitreich.org 70 i 301 dprintf(sock, toolongerr, recvc); Err bitreich.org 70 i 302 return; Err bitreich.org 70 i 303 } Err bitreich.org 70 i 304 Err bitreich.org 70 i 305 fd = -1; Err bitreich.org 70 i 306 /* Err bitreich.org 70 i 307 * If path could not be found, do: Err bitreich.org 70 i 308 * 1.) Traverse from base directory one dir by dir. Err bitreich.org 70 i 309 * 2.) If one path element, separated by "/", is not found, stop. Err bitreich.org 70 i 310 * 3.) Prepare new args string: Err bitreich.org 70 i 311 * Err bitreich.org 70 i 312 * $args = $rest_of_path + "?" + $args Err bitreich.org 70 i 313 */ Err bitreich.org 70 i 314 if (stat(path, &dir) == -1) { Err bitreich.org 70 i 315 memmove(traversec, traverse, strlen(traverse)); Err bitreich.org 70 i 316 snprintf(path, sizeof(path), "%s", base); Err bitreich.org 70 i 317 recvbp = recvb; Err bitreich.org 70 i 318 Err bitreich.org 70 i 319 /* Err bitreich.org 70 i 320 * Walk into the selector until some directory or file Err bitreich.org 70 i 321 * does not exist. Then reconstruct the args, selector Err bitreich.org 70 i 322 * etc. Err bitreich.org 70 i 323 */ Err bitreich.org 70 i 324 while (recvbp != NULL) { Err bitreich.org 70 i 325 /* Traverse multiple empty / in selector. */ Err bitreich.org 70 i 326 while(recvbp[0] == '/') Err bitreich.org 70 i 327 recvbp++; Err bitreich.org 70 i 328 sep = strchr(recvbp, '/'); Err bitreich.org 70 i 329 if (sep != NULL) Err bitreich.org 70 i 330 *sep++ = '\0'; Err bitreich.org 70 i 331 Err bitreich.org 70 i 332 snprintf(path+strlen(path), sizeof(path)-strlen(path), Err bitreich.org 70 i 333 "/%s", recvbp); Err bitreich.org 70 i 334 /* path is now always at least '/' */ Err bitreich.org 70 i 335 if (stat(path, &dir) == -1) { Err bitreich.org 70 i 336 path[strlen(path)-strlen(recvbp)-1] = '\0'; Err bitreich.org 70 i 337 snprintf(traverse, sizeof(traverse), Err bitreich.org 70 i 338 "/%s%s%s%s", Err bitreich.org 70 i 339 recvbp, Err bitreich.org 70 i 340 (sep != NULL)? "/" : "", Err bitreich.org 70 i 341 (sep != NULL)? sep : "", Err bitreich.org 70 i 342 (traversec[0] != '\0')? traversec : "" Err bitreich.org 70 i 343 ); Err bitreich.org 70 i 344 /* path fallthrough */ Err bitreich.org 70 i 345 pathfallthrough = 1; Err bitreich.org 70 i 346 break; Err bitreich.org 70 i 347 } Err bitreich.org 70 i 348 /* Append found directory to path. */ Err bitreich.org 70 i 349 recvbp = sep; Err bitreich.org 70 i 350 } Err bitreich.org 70 i 351 } Err bitreich.org 70 i 352 Err bitreich.org 70 i 353 if (stat(path, &dir) != -1) { Err bitreich.org 70 i 354 /* Err bitreich.org 70 i 355 * If sticky bit is set, only serve if this is encrypted. Err bitreich.org 70 i 356 */ Err bitreich.org 70 i 357 if ((dir.st_mode & S_ISVTX) && !istls) { Err bitreich.org 70 i 358 dprintf(sock, tlserr, recvc); Err bitreich.org 70 i 359 if (loglvl & ERRORS) { Err bitreich.org 70 i 360 logentry(clienth, clientp, recvc, Err bitreich.org 70 i 361 "encryption only"); Err bitreich.org 70 i 362 } Err bitreich.org 70 i 363 return; Err bitreich.org 70 i 364 } Err bitreich.org 70 i 365 Err bitreich.org 70 i 366 if (S_ISDIR(dir.st_mode)) { Err bitreich.org 70 i 367 for (i = 0; i < sizeof(indexf)/sizeof(indexf[0]); Err bitreich.org 70 i 368 i++) { Err bitreich.org 70 i 369 len = strlen(path); Err bitreich.org 70 i 370 if (len + strlen(indexf[i]) + ((path[len-1] == '/')? 0 : 1) Err bitreich.org 70 i 371 >= sizeof(path)) { Err bitreich.org 70 i 372 if (loglvl & ERRORS) { Err bitreich.org 70 i 373 logentry(clienth, clientp, Err bitreich.org 70 i 374 recvc, Err bitreich.org 70 i 375 "path truncation occurred"); Err bitreich.org 70 i 376 } Err bitreich.org 70 i 377 return; Err bitreich.org 70 i 378 } Err bitreich.org 70 i 379 /* Err bitreich.org 70 i 380 * The size check for strcat to work is Err bitreich.org 70 i 381 * calculated above this comment. Err bitreich.org 70 i 382 * Err bitreich.org 70 i 383 * Until strlcat isn't properly in all Err bitreich.org 70 i 384 * linux libcs, we keep to this. OpenBSD Err bitreich.org 70 i 385 * will complain about strcat and Err bitreich.org 70 i 386 * smart-ass gcc will cmplain about Err bitreich.org 70 i 387 * strncat of one char static char array Err bitreich.org 70 i 388 * is an overflow. Err bitreich.org 70 i 389 */ Err bitreich.org 70 i 390 if (path[len-1] != '/') Err bitreich.org 70 i 391 strcat(path, "/"); Err bitreich.org 70 i 392 strcat(path, indexf[i]); Err bitreich.org 70 i 393 fd = open(path, O_RDONLY); Err bitreich.org 70 i 394 if (fd >= 0) Err bitreich.org 70 i 395 break; Err bitreich.org 70 i 396 Err bitreich.org 70 i 397 /* Not found. Clear path from indexf. */ Err bitreich.org 70 i 398 path[len] = '\0'; Err bitreich.org 70 i 399 } Err bitreich.org 70 i 400 } else { Err bitreich.org 70 i 401 fd = open(path, O_RDONLY); Err bitreich.org 70 i 402 if (fd < 0) { Err bitreich.org 70 i 403 dprintf(sock, notfounderr, recvc); Err bitreich.org 70 i 404 if (loglvl & ERRORS) { Err bitreich.org 70 i 405 logentry(clienth, clientp, recvc, Err bitreich.org 70 i 406 strerror(errno)); Err bitreich.org 70 i 407 } Err bitreich.org 70 i 408 return; Err bitreich.org 70 i 409 } Err bitreich.org 70 i 410 } Err bitreich.org 70 i 411 } Err bitreich.org 70 i 412 Err bitreich.org 70 i 413 /* Some file was opened. Serve it. */ Err bitreich.org 70 i 414 if (fd >= 0) { Err bitreich.org 70 i 415 close(fd); Err bitreich.org 70 i 416 Err bitreich.org 70 i 417 c = strrchr(path, '/'); Err bitreich.org 70 i 418 if (c == NULL) Err bitreich.org 70 i 419 c = path; Err bitreich.org 70 i 420 type = gettype(c); Err bitreich.org 70 i 421 Err bitreich.org 70 i 422 /* Err bitreich.org 70 i 423 * If we had to traverse the path to find some, only Err bitreich.org 70 i 424 * allow index.dcgi and index.cgi as handlers. Err bitreich.org 70 i 425 */ Err bitreich.org 70 i 426 if (pathfallthrough && Err bitreich.org 70 i 427 !(type->f == handledcgi || type->f == handlecgi)) { Err bitreich.org 70 i 428 dprintf(sock, notfounderr, recvc); Err bitreich.org 70 i 429 if (loglvl & ERRORS) { Err bitreich.org 70 i 430 logentry(clienth, clientp, recvc, Err bitreich.org 70 i 431 "handler in path fallthrough not allowed"); Err bitreich.org 70 i 432 } Err bitreich.org 70 i 433 return; Err bitreich.org 70 i 434 } Err bitreich.org 70 i 435 Err bitreich.org 70 i 436 if (nocgi && (type->f == handledcgi || type->f == handlecgi)) { Err bitreich.org 70 i 437 dprintf(sock, nocgierr, recvc); Err bitreich.org 70 i 438 if (loglvl & ERRORS) Err bitreich.org 70 i 439 logentry(clienth, clientp, recvc, "nocgi error"); Err bitreich.org 70 i 440 } else { Err bitreich.org 70 i 441 if (loglvl & FILES) Err bitreich.org 70 i 442 logentry(clienth, clientp, recvc, "serving"); Err bitreich.org 70 i 443 Err bitreich.org 70 i 444 type->f(sock, path, port, base, args, sear, ohost, Err bitreich.org 70 i 445 clienth, serverh, istls, recvc, traverse); Err bitreich.org 70 i 446 } Err bitreich.org 70 i 447 } else { Err bitreich.org 70 i 448 if (pathfallthrough && S_ISDIR(dir.st_mode)) { Err bitreich.org 70 i 449 dprintf(sock, notfounderr, recvc); Err bitreich.org 70 i 450 if (loglvl & ERRORS) { Err bitreich.org 70 i 451 logentry(clienth, clientp, recvc, Err bitreich.org 70 i 452 "directory listing in traversal not allowed"); Err bitreich.org 70 i 453 } Err bitreich.org 70 i 454 return; Err bitreich.org 70 i 455 } Err bitreich.org 70 i 456 Err bitreich.org 70 i 457 if (!pathfallthrough && S_ISDIR(dir.st_mode)) { Err bitreich.org 70 i 458 handledir(sock, path, port, base, args, sear, ohost, Err bitreich.org 70 i 459 clienth, serverh, istls, recvc, traverse); Err bitreich.org 70 i 460 if (loglvl & DIRS) { Err bitreich.org 70 i 461 logentry(clienth, clientp, recvc, Err bitreich.org 70 i 462 "dir listing"); Err bitreich.org 70 i 463 } Err bitreich.org 70 i 464 return; Err bitreich.org 70 i 465 } Err bitreich.org 70 i 466 Err bitreich.org 70 i 467 dprintf(sock, notfounderr, recvc); Err bitreich.org 70 i 468 if (loglvl & ERRORS) Err bitreich.org 70 i 469 logentry(clienth, clientp, recvc, "not found"); Err bitreich.org 70 i 470 } Err bitreich.org 70 i 471 Err bitreich.org 70 i 472 return; Err bitreich.org 70 i 473 } Err bitreich.org 70 i 474 Err bitreich.org 70 i 475 void Err bitreich.org 70 i 476 sighandler(int sig) Err bitreich.org 70 i 477 { Err bitreich.org 70 i 478 int i; Err bitreich.org 70 i 479 Err bitreich.org 70 i 480 switch (sig) { Err bitreich.org 70 i 481 case SIGCHLD: Err bitreich.org 70 i 482 while (waitpid(-1, NULL, WNOHANG) > 0); Err bitreich.org 70 i 483 break; Err bitreich.org 70 i 484 case SIGINT: Err bitreich.org 70 i 485 case SIGQUIT: Err bitreich.org 70 i 486 case SIGABRT: Err bitreich.org 70 i 487 case SIGTERM: Err bitreich.org 70 i 488 if (dosyslog) { Err bitreich.org 70 i 489 closelog(); Err bitreich.org 70 i 490 } else if (logfile != NULL && glfd != -1) { Err bitreich.org 70 i 491 close(glfd); Err bitreich.org 70 i 492 glfd = -1; Err bitreich.org 70 i 493 } Err bitreich.org 70 i 494 Err bitreich.org 70 i 495 for (i = 0; i < nlistfds; i++) { Err bitreich.org 70 i 496 shutdown(listfds[i], SHUT_RDWR); Err bitreich.org 70 i 497 close(listfds[i]); Err bitreich.org 70 i 498 } Err bitreich.org 70 i 499 free(listfds); Err bitreich.org 70 i 500 exit(0); Err bitreich.org 70 i 501 break; Err bitreich.org 70 i 502 default: Err bitreich.org 70 i 503 break; Err bitreich.org 70 i 504 } Err bitreich.org 70 i 505 } Err bitreich.org 70 i 506 Err bitreich.org 70 i 507 void Err bitreich.org 70 i 508 initsignals(void) Err bitreich.org 70 i 509 { Err bitreich.org 70 i 510 signal(SIGCHLD, sighandler); Err bitreich.org 70 i 511 signal(SIGHUP, sighandler); Err bitreich.org 70 i 512 signal(SIGINT, sighandler); Err bitreich.org 70 i 513 signal(SIGQUIT, sighandler); Err bitreich.org 70 i 514 signal(SIGABRT, sighandler); Err bitreich.org 70 i 515 signal(SIGTERM, sighandler); Err bitreich.org 70 i 516 Err bitreich.org 70 i 517 signal(SIGPIPE, SIG_IGN); Err bitreich.org 70 i 518 } Err bitreich.org 70 i 519 Err bitreich.org 70 i 520 /* Err bitreich.org 70 i 521 * TODO: Move Linux and BSD to Plan 9 socket and bind handling, so we do not Err bitreich.org 70 i 522 * need the inconsistent return and exit on getaddrinfo. Err bitreich.org 70 i 523 */ Err bitreich.org 70 i 524 int * Err bitreich.org 70 i 525 getlistenfd(struct addrinfo *hints, char *bindip, char *port, int *rlfdnum) Err bitreich.org 70 i 526 { Err bitreich.org 70 i 527 char addstr[INET6_ADDRSTRLEN]; Err bitreich.org 70 i 528 struct addrinfo *ai, *rp; Err bitreich.org 70 i 529 void *sinaddr; Err bitreich.org 70 i 530 int on, *listenfds, *listenfd, aierr, errno_save; Err bitreich.org 70 i 531 Err bitreich.org 70 i 532 if ((aierr = getaddrinfo(bindip, port, hints, &ai)) || ai == NULL) { Err bitreich.org 70 i 533 fprintf(stderr, "getaddrinfo (%s:%s): %s\n", bindip, port, Err bitreich.org 70 i 534 gai_strerror(aierr)); Err bitreich.org 70 i 535 exit(1); Err bitreich.org 70 i 536 } Err bitreich.org 70 i 537 Err bitreich.org 70 i 538 *rlfdnum = 0; Err bitreich.org 70 i 539 listenfds = NULL; Err bitreich.org 70 i 540 on = 1; Err bitreich.org 70 i 541 for (rp = ai; rp != NULL; rp = rp->ai_next) { Err bitreich.org 70 i 542 listenfds = xrealloc(listenfds, Err bitreich.org 70 i 543 sizeof(*listenfds) * (++*rlfdnum)); Err bitreich.org 70 i 544 listenfd = &listenfds[*rlfdnum-1]; Err bitreich.org 70 i 545 Err bitreich.org 70 i 546 *listenfd = socket(rp->ai_family, rp->ai_socktype, Err bitreich.org 70 i 547 rp->ai_protocol); Err bitreich.org 70 i 548 if (*listenfd < 0) Err bitreich.org 70 i 549 continue; Err bitreich.org 70 i 550 if (setsockopt(*listenfd, SOL_SOCKET, SO_REUSEADDR, &on, Err bitreich.org 70 i 551 sizeof(on)) < 0) { Err bitreich.org 70 i 552 close(*listenfd); Err bitreich.org 70 i 553 (*rlfdnum)--; Err bitreich.org 70 i 554 continue; Err bitreich.org 70 i 555 } Err bitreich.org 70 i 556 Err bitreich.org 70 i 557 if (rp->ai_family == AF_INET6 && (setsockopt(*listenfd, Err bitreich.org 70 i 558 IPPROTO_IPV6, IPV6_V6ONLY, &on, Err bitreich.org 70 i 559 sizeof(on)) < 0)) { Err bitreich.org 70 i 560 close(*listenfd); Err bitreich.org 70 i 561 (*rlfdnum)--; Err bitreich.org 70 i 562 continue; Err bitreich.org 70 i 563 } Err bitreich.org 70 i 564 Err bitreich.org 70 i 565 sinaddr = (rp->ai_family == AF_INET) ? Err bitreich.org 70 i 566 (void *)&((struct sockaddr_in *)rp->ai_addr)->sin_addr : Err bitreich.org 70 i 567 (void *)&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr; Err bitreich.org 70 i 568 Err bitreich.org 70 i 569 if (bind(*listenfd, rp->ai_addr, rp->ai_addrlen) == 0) { Err bitreich.org 70 i 570 if (loglvl & CONN && inet_ntop(rp->ai_family, sinaddr, Err bitreich.org 70 i 571 addstr, sizeof(addstr))) { Err bitreich.org 70 i 572 /* Do not revlookup here. */ Err bitreich.org 70 i 573 on = revlookup; Err bitreich.org 70 i 574 revlookup = 0; Err bitreich.org 70 i 575 logentry(addstr, port, "-", "listening"); Err bitreich.org 70 i 576 revlookup = on; Err bitreich.org 70 i 577 } Err bitreich.org 70 i 578 continue; Err bitreich.org 70 i 579 } Err bitreich.org 70 i 580 Err bitreich.org 70 i 581 /* Save errno, because fprintf in logentry overwrites it. */ Err bitreich.org 70 i 582 errno_save = errno; Err bitreich.org 70 i 583 close(*listenfd); Err bitreich.org 70 i 584 (*rlfdnum)--; Err bitreich.org 70 i 585 if (loglvl & CONN && inet_ntop(rp->ai_family, sinaddr, Err bitreich.org 70 i 586 addstr, sizeof(addstr))) { Err bitreich.org 70 i 587 /* Do not revlookup here. */ Err bitreich.org 70 i 588 on = revlookup; Err bitreich.org 70 i 589 revlookup = 0; Err bitreich.org 70 i 590 logentry(addstr, port, "-", "could not bind"); Err bitreich.org 70 i 591 revlookup = on; Err bitreich.org 70 i 592 } Err bitreich.org 70 i 593 errno = errno_save; Err bitreich.org 70 i 594 } Err bitreich.org 70 i 595 freeaddrinfo(ai); Err bitreich.org 70 i 596 if (*rlfdnum < 1) { Err bitreich.org 70 i 597 free(listenfds); Err bitreich.org 70 i 598 return NULL; Err bitreich.org 70 i 599 } Err bitreich.org 70 i 600 Err bitreich.org 70 i 601 return listenfds; Err bitreich.org 70 i 602 } Err bitreich.org 70 i 603 Err bitreich.org 70 i 604 void Err bitreich.org 70 i 605 usage(void) Err bitreich.org 70 i 606 { Err bitreich.org 70 i 607 dprintf(2, "usage: %s [-46cdensy] [-l logfile] " Err bitreich.org 70 i 608 #ifdef ENABLE_TLS Err bitreich.org 70 i 609 "[-t keyfile certfile] " Err bitreich.org 70 i 610 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 611 "[-v loglvl] [-b base] [-p port] [-o sport] " Err bitreich.org 70 i 612 "[-u user] [-g group] [-h host] [-i interface ...]\n", Err bitreich.org 70 i 613 argv0); Err bitreich.org 70 i 614 exit(1); Err bitreich.org 70 i 615 } Err bitreich.org 70 i 616 Err bitreich.org 70 i 617 int Err bitreich.org 70 i 618 main(int argc, char *argv[]) Err bitreich.org 70 i 619 { Err bitreich.org 70 i 620 struct addrinfo hints; Err bitreich.org 70 i 621 struct sockaddr_storage clt, slt; Err bitreich.org 70 i 622 socklen_t cltlen, sltlen; Err bitreich.org 70 i 623 int sock, dofork = 1, inetf = AF_UNSPEC, usechroot = 0, Err bitreich.org 70 i 624 nocgi = 0, errno_save, nbindips = 0, i, j, Err bitreich.org 70 i 625 nlfdret, *lfdret, listfd, maxlfd, istls = 0, Err bitreich.org 70 i 626 dotls = 0, dohaproxy = 0, tcpver = -1, haret = 0, Err bitreich.org 70 i 627 #ifdef ENABLE_TLS Err bitreich.org 70 i 628 tlssocks[2], shufbuf[1025], Err bitreich.org 70 i 629 shuflen, wlen, shufpos, tlsclientreader, Err bitreich.org 70 i 630 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 631 maxrecv, retl, Err bitreich.org 70 i 632 rlen = 0; Err bitreich.org 70 i 633 fd_set rfd; Err bitreich.org 70 i 634 char *port, *base, clienth[NI_MAXHOST], clientp[NI_MAXSERV], Err bitreich.org 70 i 635 *user = NULL, *group = NULL, **bindips = NULL, Err bitreich.org 70 i 636 *ohost = NULL, *sport = NULL, *p; Err bitreich.org 70 i 637 /* Must be as large as recvb, due to scanf restrictions. */ Err bitreich.org 70 i 638 char hachost[1025], hashost[1025], hacport[1025], hasport[1025], Err bitreich.org 70 i 639 #ifdef ENABLE_TLS Err bitreich.org 70 i 640 *certfile = NULL, *keyfile = NULL, Err bitreich.org 70 i 641 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 642 byte0, recvb[1025], serverh[NI_MAXHOST], serverp[NI_MAXSERV]; Err bitreich.org 70 i 643 struct passwd *us = NULL; Err bitreich.org 70 i 644 struct group *gr = NULL; Err bitreich.org 70 i 645 #ifdef ENABLE_TLS Err bitreich.org 70 i 646 struct tls_config *tlsconfig = NULL; Err bitreich.org 70 i 647 struct tls *tlsctx = NULL, *tlsclientctx; Err bitreich.org 70 i 648 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 649 Err bitreich.org 70 i 650 base = stdbase; Err bitreich.org 70 i 651 port = stdport; Err bitreich.org 70 i 652 Err bitreich.org 70 i 653 ARGBEGIN { Err bitreich.org 70 i 654 case '4': Err bitreich.org 70 i 655 inetf = AF_INET; Err bitreich.org 70 i 656 tcpver = 4; Err bitreich.org 70 i 657 break; Err bitreich.org 70 i 658 case '6': Err bitreich.org 70 i 659 inetf = AF_INET6; Err bitreich.org 70 i 660 tcpver = 6; Err bitreich.org 70 i 661 break; Err bitreich.org 70 i 662 case 'b': Err bitreich.org 70 i 663 base = EARGF(usage()); Err bitreich.org 70 i 664 break; Err bitreich.org 70 i 665 case 'c': Err bitreich.org 70 i 666 usechroot = 1; Err bitreich.org 70 i 667 break; Err bitreich.org 70 i 668 case 'd': Err bitreich.org 70 i 669 dofork = 0; Err bitreich.org 70 i 670 break; Err bitreich.org 70 i 671 case 'e': Err bitreich.org 70 i 672 nocgi = 1; Err bitreich.org 70 i 673 break; Err bitreich.org 70 i 674 case 'g': Err bitreich.org 70 i 675 group = EARGF(usage()); Err bitreich.org 70 i 676 break; Err bitreich.org 70 i 677 case 'h': Err bitreich.org 70 i 678 ohost = EARGF(usage()); Err bitreich.org 70 i 679 break; Err bitreich.org 70 i 680 case 'i': Err bitreich.org 70 i 681 bindips = xrealloc(bindips, sizeof(*bindips) * (++nbindips)); Err bitreich.org 70 i 682 bindips[nbindips-1] = EARGF(usage()); Err bitreich.org 70 i 683 break; Err bitreich.org 70 i 684 case 'l': Err bitreich.org 70 i 685 logfile = EARGF(usage()); Err bitreich.org 70 i 686 break; Err bitreich.org 70 i 687 case 'n': Err bitreich.org 70 i 688 revlookup = 1; Err bitreich.org 70 i 689 break; Err bitreich.org 70 i 690 case 'o': Err bitreich.org 70 i 691 sport = EARGF(usage()); Err bitreich.org 70 i 692 break; Err bitreich.org 70 i 693 case 'p': Err bitreich.org 70 i 694 port = EARGF(usage()); Err bitreich.org 70 i 695 if (sport == NULL) Err bitreich.org 70 i 696 sport = port; Err bitreich.org 70 i 697 break; Err bitreich.org 70 i 698 case 's': Err bitreich.org 70 i 699 dosyslog = 1; Err bitreich.org 70 i 700 break; Err bitreich.org 70 i 701 #ifdef ENABLE_TLS Err bitreich.org 70 i 702 case 't': Err bitreich.org 70 i 703 dotls = 1; Err bitreich.org 70 i 704 keyfile = EARGF(usage()); Err bitreich.org 70 i 705 certfile = EARGF(usage()); Err bitreich.org 70 i 706 break; Err bitreich.org 70 i 707 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 708 case 'u': Err bitreich.org 70 i 709 user = EARGF(usage()); Err bitreich.org 70 i 710 break; Err bitreich.org 70 i 711 case 'v': Err bitreich.org 70 i 712 loglvl = atoi(EARGF(usage())); Err bitreich.org 70 i 713 break; Err bitreich.org 70 i 714 case 'y': Err bitreich.org 70 i 715 dohaproxy = 1; Err bitreich.org 70 i 716 break; Err bitreich.org 70 i 717 default: Err bitreich.org 70 i 718 usage(); Err bitreich.org 70 i 719 } ARGEND; Err bitreich.org 70 i 720 Err bitreich.org 70 i 721 if (sport == NULL) Err bitreich.org 70 i 722 sport = port; Err bitreich.org 70 i 723 Err bitreich.org 70 i 724 if (argc != 0) Err bitreich.org 70 i 725 usage(); Err bitreich.org 70 i 726 Err bitreich.org 70 i 727 #ifdef ENABLE_TLS Err bitreich.org 70 i 728 if (dotls) { Err bitreich.org 70 i 729 if (tls_init() < 0) { Err bitreich.org 70 i 730 perror("tls_init"); Err bitreich.org 70 i 731 return 1; Err bitreich.org 70 i 732 } Err bitreich.org 70 i 733 if ((tlsconfig = tls_config_new()) == NULL) { Err bitreich.org 70 i 734 perror("tls_config_new"); Err bitreich.org 70 i 735 return 1; Err bitreich.org 70 i 736 } Err bitreich.org 70 i 737 if ((tlsctx = tls_server()) == NULL) { Err bitreich.org 70 i 738 perror("tls_server"); Err bitreich.org 70 i 739 return 1; Err bitreich.org 70 i 740 } Err bitreich.org 70 i 741 if (tls_config_set_key_file(tlsconfig, keyfile) < 0) { Err bitreich.org 70 i 742 perror("tls_config_set_key_file"); Err bitreich.org 70 i 743 return 1; Err bitreich.org 70 i 744 } Err bitreich.org 70 i 745 if (tls_config_set_cert_file(tlsconfig, certfile) < 0) { Err bitreich.org 70 i 746 perror("tls_config_set_cert_file"); Err bitreich.org 70 i 747 return 1; Err bitreich.org 70 i 748 } Err bitreich.org 70 i 749 if (tls_configure(tlsctx, tlsconfig) < 0) { Err bitreich.org 70 i 750 perror("tls_configure"); Err bitreich.org 70 i 751 return 1; Err bitreich.org 70 i 752 } Err bitreich.org 70 i 753 } Err bitreich.org 70 i 754 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 755 Err bitreich.org 70 i 756 if (ohost == NULL) { Err bitreich.org 70 i 757 /* Do not use HOST_NAME_MAX, it is not defined on NetBSD. */ Err bitreich.org 70 i 758 ohost = xcalloc(1, 256+1); Err bitreich.org 70 i 759 if (gethostname(ohost, 256) < 0) { Err bitreich.org 70 i 760 perror("gethostname"); Err bitreich.org 70 i 761 free(ohost); Err bitreich.org 70 i 762 return 1; Err bitreich.org 70 i 763 } Err bitreich.org 70 i 764 } else { Err bitreich.org 70 i 765 ohost = xstrdup(ohost); Err bitreich.org 70 i 766 } Err bitreich.org 70 i 767 Err bitreich.org 70 i 768 if (group != NULL) { Err bitreich.org 70 i 769 errno = 0; Err bitreich.org 70 i 770 if ((gr = getgrnam(group)) == NULL) { Err bitreich.org 70 i 771 if (errno == 0) { Err bitreich.org 70 i 772 fprintf(stderr, "no such group '%s'\n", group); Err bitreich.org 70 i 773 } else { Err bitreich.org 70 i 774 perror("getgrnam"); Err bitreich.org 70 i 775 } Err bitreich.org 70 i 776 return 1; Err bitreich.org 70 i 777 } Err bitreich.org 70 i 778 } Err bitreich.org 70 i 779 Err bitreich.org 70 i 780 if (user != NULL) { Err bitreich.org 70 i 781 errno = 0; Err bitreich.org 70 i 782 if ((us = getpwnam(user)) == NULL) { Err bitreich.org 70 i 783 if (errno == 0) { Err bitreich.org 70 i 784 fprintf(stderr, "no such user '%s'\n", user); Err bitreich.org 70 i 785 } else { Err bitreich.org 70 i 786 perror("getpwnam"); Err bitreich.org 70 i 787 } Err bitreich.org 70 i 788 return 1; Err bitreich.org 70 i 789 } Err bitreich.org 70 i 790 } Err bitreich.org 70 i 791 Err bitreich.org 70 i 792 if (dofork) { Err bitreich.org 70 i 793 switch (fork()) { Err bitreich.org 70 i 794 case -1: Err bitreich.org 70 i 795 perror("fork"); Err bitreich.org 70 i 796 return 1; Err bitreich.org 70 i 797 case 0: Err bitreich.org 70 i 798 break; Err bitreich.org 70 i 799 default: Err bitreich.org 70 i 800 return 0; Err bitreich.org 70 i 801 } Err bitreich.org 70 i 802 } Err bitreich.org 70 i 803 Err bitreich.org 70 i 804 if (dosyslog) { Err bitreich.org 70 i 805 openlog("geomyidae", dofork? LOG_NDELAY|LOG_PID \ Err bitreich.org 70 i 806 : LOG_CONS|LOG_PERROR, logpriority); Err bitreich.org 70 i 807 } else if (logfile != NULL) { Err bitreich.org 70 i 808 glfd = open(logfile, O_APPEND | O_WRONLY | O_CREAT, 0644); Err bitreich.org 70 i 809 if (glfd < 0) { Err bitreich.org 70 i 810 perror("log"); Err bitreich.org 70 i 811 return 1; Err bitreich.org 70 i 812 } Err bitreich.org 70 i 813 } else if (!dofork) { Err bitreich.org 70 i 814 glfd = 1; Err bitreich.org 70 i 815 } Err bitreich.org 70 i 816 Err bitreich.org 70 i 817 if (bindips == NULL) { Err bitreich.org 70 i 818 if (inetf == AF_INET || inetf == AF_UNSPEC) { Err bitreich.org 70 i 819 bindips = xrealloc(bindips, sizeof(*bindips) * (++nbindips)); Err bitreich.org 70 i 820 bindips[nbindips-1] = "0.0.0.0"; Err bitreich.org 70 i 821 } Err bitreich.org 70 i 822 if (inetf == AF_INET6 || inetf == AF_UNSPEC) { Err bitreich.org 70 i 823 bindips = xrealloc(bindips, sizeof(*bindips) * (++nbindips)); Err bitreich.org 70 i 824 bindips[nbindips-1] = "::"; Err bitreich.org 70 i 825 } Err bitreich.org 70 i 826 } Err bitreich.org 70 i 827 Err bitreich.org 70 i 828 for (i = 0; i < nbindips; i++) { Err bitreich.org 70 i 829 memset(&hints, 0, sizeof(hints)); Err bitreich.org 70 i 830 hints.ai_family = inetf; Err bitreich.org 70 i 831 hints.ai_flags = AI_PASSIVE; Err bitreich.org 70 i 832 hints.ai_socktype = SOCK_STREAM; Err bitreich.org 70 i 833 if (bindips[i]) Err bitreich.org 70 i 834 hints.ai_flags |= AI_CANONNAME; Err bitreich.org 70 i 835 Err bitreich.org 70 i 836 nlfdret = 0; Err bitreich.org 70 i 837 lfdret = getlistenfd(&hints, bindips[i], port, &nlfdret); Err bitreich.org 70 i 838 if (nlfdret < 1) { Err bitreich.org 70 i 839 errno_save = errno; Err bitreich.org 70 i 840 fprintf(stderr, "Unable to get a binding socket for " Err bitreich.org 70 i 841 "%s:%s\n", bindips[i], port); Err bitreich.org 70 i 842 errno = errno_save; Err bitreich.org 70 i 843 perror("getlistenfd"); Err bitreich.org 70 i 844 } Err bitreich.org 70 i 845 Err bitreich.org 70 i 846 for (j = 0; j < nlfdret; j++) { Err bitreich.org 70 i 847 if (listen(lfdret[j], 4096) < 0) { Err bitreich.org 70 i 848 perror("listen"); Err bitreich.org 70 i 849 close(lfdret[j]); Err bitreich.org 70 i 850 continue; Err bitreich.org 70 i 851 } Err bitreich.org 70 i 852 listfds = xrealloc(listfds, Err bitreich.org 70 i 853 sizeof(*listfds) * ++nlistfds); Err bitreich.org 70 i 854 listfds[nlistfds-1] = lfdret[j]; Err bitreich.org 70 i 855 } Err bitreich.org 70 i 856 free(lfdret); Err bitreich.org 70 i 857 } Err bitreich.org 70 i 858 free(bindips); Err bitreich.org 70 i 859 Err bitreich.org 70 i 860 if (nlistfds < 1) Err bitreich.org 70 i 861 return 1; Err bitreich.org 70 i 862 Err bitreich.org 70 i 863 if (usechroot) { Err bitreich.org 70 i 864 if (chdir(base) < 0) { Err bitreich.org 70 i 865 perror("chdir"); Err bitreich.org 70 i 866 return 1; Err bitreich.org 70 i 867 } Err bitreich.org 70 i 868 base = ""; Err bitreich.org 70 i 869 if (chroot(".") < 0) { Err bitreich.org 70 i 870 perror("chroot"); Err bitreich.org 70 i 871 return 1; Err bitreich.org 70 i 872 } Err bitreich.org 70 i 873 } else if (*base != '/' && !(base = realpath(base, NULL))) { Err bitreich.org 70 i 874 perror("realpath"); Err bitreich.org 70 i 875 return 1; Err bitreich.org 70 i 876 } Err bitreich.org 70 i 877 Err bitreich.org 70 i 878 /* strip / at the end of base */ Err bitreich.org 70 i 879 for (p = base + strlen(base) - 1; p >= base && p[0] == '/'; --p) Err bitreich.org 70 i 880 p[0] = '\0'; Err bitreich.org 70 i 881 Err bitreich.org 70 i 882 if (dropprivileges(gr, us) < 0) { Err bitreich.org 70 i 883 perror("dropprivileges"); Err bitreich.org 70 i 884 Err bitreich.org 70 i 885 for (i = 0; i < nlistfds; i++) { Err bitreich.org 70 i 886 shutdown(listfds[i], SHUT_RDWR); Err bitreich.org 70 i 887 close(listfds[i]); Err bitreich.org 70 i 888 } Err bitreich.org 70 i 889 free(listfds); Err bitreich.org 70 i 890 return 1; Err bitreich.org 70 i 891 } Err bitreich.org 70 i 892 Err bitreich.org 70 i 893 initsignals(); Err bitreich.org 70 i 894 Err bitreich.org 70 i 895 #ifdef HOT_COMPUTER Err bitreich.org 70 i 896 #warning "I love you too." Err bitreich.org 70 i 897 #endif Err bitreich.org 70 i 898 Err bitreich.org 70 i 899 #ifdef __OpenBSD__ Err bitreich.org 70 i 900 char promises[31]; /* check the size needed in the fork too */ Err bitreich.org 70 i 901 snprintf(promises, sizeof(promises), "rpath inet stdio proc exec %s", Err bitreich.org 70 i 902 revlookup ? "dns" : ""); Err bitreich.org 70 i 903 if (pledge(promises, NULL) == -1) { Err bitreich.org 70 i 904 perror("pledge"); Err bitreich.org 70 i 905 exit(1); Err bitreich.org 70 i 906 } Err bitreich.org 70 i 907 #endif /* __OpenBSD__ */ Err bitreich.org 70 i 908 Err bitreich.org 70 i 909 while (1) { Err bitreich.org 70 i 910 FD_ZERO(&rfd); Err bitreich.org 70 i 911 maxlfd = 0; Err bitreich.org 70 i 912 for (i = 0; i < nlistfds; i++) { Err bitreich.org 70 i 913 FD_SET(listfds[i], &rfd); Err bitreich.org 70 i 914 if (listfds[i] > maxlfd) Err bitreich.org 70 i 915 maxlfd = listfds[i]; Err bitreich.org 70 i 916 } Err bitreich.org 70 i 917 Err bitreich.org 70 i 918 if (pselect(maxlfd+1, &rfd, NULL, NULL, NULL, NULL) < 0) { Err bitreich.org 70 i 919 if (errno == EINTR) Err bitreich.org 70 i 920 continue; Err bitreich.org 70 i 921 perror("pselect"); Err bitreich.org 70 i 922 break; Err bitreich.org 70 i 923 } Err bitreich.org 70 i 924 Err bitreich.org 70 i 925 listfd = -1; Err bitreich.org 70 i 926 for (i = 0; i < nlistfds; i++) { Err bitreich.org 70 i 927 if (FD_ISSET(listfds[i], &rfd)) { Err bitreich.org 70 i 928 listfd = listfds[i]; Err bitreich.org 70 i 929 break; Err bitreich.org 70 i 930 } Err bitreich.org 70 i 931 } Err bitreich.org 70 i 932 if (listfd < 0) Err bitreich.org 70 i 933 continue; Err bitreich.org 70 i 934 Err bitreich.org 70 i 935 cltlen = sizeof(clt); Err bitreich.org 70 i 936 sock = accept(listfd, (struct sockaddr *)&clt, &cltlen); Err bitreich.org 70 i 937 if (sock < 0) { Err bitreich.org 70 i 938 switch (errno) { Err bitreich.org 70 i 939 case ECONNABORTED: Err bitreich.org 70 i 940 case EINTR: Err bitreich.org 70 i 941 continue; Err bitreich.org 70 i 942 default: Err bitreich.org 70 i 943 perror("accept"); Err bitreich.org 70 i 944 close(listfd); Err bitreich.org 70 i 945 return 1; Err bitreich.org 70 i 946 } Err bitreich.org 70 i 947 } Err bitreich.org 70 i 948 Err bitreich.org 70 i 949 sltlen = sizeof(slt); Err bitreich.org 70 i 950 serverh[0] = serverp[0] = '\0'; Err bitreich.org 70 i 951 if (getsockname(sock, (struct sockaddr *)&slt, &sltlen) == 0) { Err bitreich.org 70 i 952 getnameinfo((struct sockaddr *)&slt, sltlen, serverh, Err bitreich.org 70 i 953 sizeof(serverh), serverp, sizeof(serverp), Err bitreich.org 70 i 954 NI_NUMERICHOST|NI_NUMERICSERV); Err bitreich.org 70 i 955 } Err bitreich.org 70 i 956 if (!strncmp(serverh, "::ffff:", 7)) Err bitreich.org 70 i 957 memmove(serverh, serverh+7, strlen(serverh)-6); Err bitreich.org 70 i 958 Err bitreich.org 70 i 959 if (getnameinfo((struct sockaddr *)&clt, cltlen, clienth, Err bitreich.org 70 i 960 sizeof(clienth), clientp, sizeof(clientp), Err bitreich.org 70 i 961 NI_NUMERICHOST|NI_NUMERICSERV)) { Err bitreich.org 70 i 962 clienth[0] = clientp[0] = '\0'; Err bitreich.org 70 i 963 } Err bitreich.org 70 i 964 Err bitreich.org 70 i 965 if (!strncmp(clienth, "::ffff:", 7)) Err bitreich.org 70 i 966 memmove(clienth, clienth+7, strlen(clienth)-6); Err bitreich.org 70 i 967 Err bitreich.org 70 i 968 if (loglvl & CONN) Err bitreich.org 70 i 969 logentry(clienth, clientp, "-", "connected"); Err bitreich.org 70 i 970 Err bitreich.org 70 i 971 switch (fork()) { Err bitreich.org 70 i 972 case -1: Err bitreich.org 70 i 973 perror("fork"); Err bitreich.org 70 i 974 shutdown(sock, SHUT_RDWR); Err bitreich.org 70 i 975 break; Err bitreich.org 70 i 976 case 0: Err bitreich.org 70 i 977 close(listfd); Err bitreich.org 70 i 978 Err bitreich.org 70 i 979 signal(SIGHUP, SIG_DFL); Err bitreich.org 70 i 980 signal(SIGQUIT, SIG_DFL); Err bitreich.org 70 i 981 signal(SIGINT, SIG_DFL); Err bitreich.org 70 i 982 signal(SIGTERM, SIG_DFL); Err bitreich.org 70 i 983 signal(SIGALRM, SIG_DFL); Err bitreich.org 70 i 984 Err bitreich.org 70 i 985 #ifdef __OpenBSD__ Err bitreich.org 70 i 986 snprintf(promises, sizeof(promises), Err bitreich.org 70 i 987 "rpath inet stdio %s %s %s", Err bitreich.org 70 i 988 !nocgi || dotls ? "proc" : "", Err bitreich.org 70 i 989 nocgi ? "" : "exec", Err bitreich.org 70 i 990 revlookup ? "dns" : ""); Err bitreich.org 70 i 991 if (pledge(promises, NULL) == -1) { Err bitreich.org 70 i 992 perror("pledge"); Err bitreich.org 70 i 993 exit(1); Err bitreich.org 70 i 994 } Err bitreich.org 70 i 995 #endif /* __OpenBSD__ */ Err bitreich.org 70 i 996 Err bitreich.org 70 i 997 read_selector_again: Err bitreich.org 70 i 998 rlen = 0; Err bitreich.org 70 i 999 memset(recvb, 0, sizeof(recvb)); Err bitreich.org 70 i 1000 Err bitreich.org 70 i 1001 if (recv(sock, &byte0, 1, MSG_PEEK) < 1) Err bitreich.org 70 i 1002 return 1; Err bitreich.org 70 i 1003 Err bitreich.org 70 i 1004 #ifdef ENABLE_TLS Err bitreich.org 70 i 1005 /* Err bitreich.org 70 i 1006 * First byte is 0x16 == 22, which is the TLS Err bitreich.org 70 i 1007 * Handshake first byte. Err bitreich.org 70 i 1008 */ Err bitreich.org 70 i 1009 istls = 0; Err bitreich.org 70 i 1010 if (byte0 == 0x16 && dotls) { Err bitreich.org 70 i 1011 istls = 1; Err bitreich.org 70 i 1012 if (tls_accept_socket(tlsctx, &tlsclientctx, sock) < 0) Err bitreich.org 70 i 1013 return 1; Err bitreich.org 70 i 1014 wlen = TLS_WANT_POLLIN; Err bitreich.org 70 i 1015 while (wlen == TLS_WANT_POLLIN \ Err bitreich.org 70 i 1016 || wlen == TLS_WANT_POLLOUT) { Err bitreich.org 70 i 1017 wlen = tls_handshake(tlsclientctx); Err bitreich.org 70 i 1018 } Err bitreich.org 70 i 1019 if (wlen == -1) Err bitreich.org 70 i 1020 return 1; Err bitreich.org 70 i 1021 } Err bitreich.org 70 i 1022 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 1023 /* Err bitreich.org 70 i 1024 * Some TLS request. Help them determine we only Err bitreich.org 70 i 1025 * serve plaintext. Err bitreich.org 70 i 1026 */ Err bitreich.org 70 i 1027 if (byte0 == 0x16 && !dotls) { Err bitreich.org 70 i 1028 if (loglvl & CONN) { Err bitreich.org 70 i 1029 logentry(clienth, clientp, "-", Err bitreich.org 70 i 1030 "disconnected"); Err bitreich.org 70 i 1031 } Err bitreich.org 70 i 1032 Err bitreich.org 70 i 1033 shutdown(sock, SHUT_RDWR); Err bitreich.org 70 i 1034 close(sock); Err bitreich.org 70 i 1035 Err bitreich.org 70 i 1036 return 1; Err bitreich.org 70 i 1037 } Err bitreich.org 70 i 1038 Err bitreich.org 70 i 1039 maxrecv = sizeof(recvb) - 1; Err bitreich.org 70 i 1040 do { Err bitreich.org 70 i 1041 #ifdef ENABLE_TLS Err bitreich.org 70 i 1042 if (istls) { Err bitreich.org 70 i 1043 retl = tls_read(tlsclientctx, Err bitreich.org 70 i 1044 recvb+rlen, 1); Err bitreich.org 70 i 1045 if (retl < 0) Err bitreich.org 70 i 1046 fprintf(stderr, "tls_read failed: %s\n", tls_error(tlsclientctx)); Err bitreich.org 70 i 1047 } else Err bitreich.org 70 i 1048 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 1049 { Err bitreich.org 70 i 1050 retl = read(sock, recvb+rlen, Err bitreich.org 70 i 1051 1); Err bitreich.org 70 i 1052 if (retl < 0) Err bitreich.org 70 i 1053 perror("read"); Err bitreich.org 70 i 1054 } Err bitreich.org 70 i 1055 if (retl <= 0) Err bitreich.org 70 i 1056 break; Err bitreich.org 70 i 1057 rlen += retl; Err bitreich.org 70 i 1058 } while (recvb[rlen-1] != '\n' Err bitreich.org 70 i 1059 && --maxrecv > 0); Err bitreich.org 70 i 1060 if (rlen <= 0) Err bitreich.org 70 i 1061 return 1; Err bitreich.org 70 i 1062 Err bitreich.org 70 i 1063 /* Err bitreich.org 70 i 1064 * HAProxy v1 protocol support. Err bitreich.org 70 i 1065 * TODO: Add other protocol version support. Err bitreich.org 70 i 1066 */ Err bitreich.org 70 i 1067 if (dohaproxy && !strncmp(recvb, "PROXY TCP", 9)) { Err bitreich.org 70 i 1068 if (p[-1] == '\r') Err bitreich.org 70 i 1069 p[-1] = '\0'; Err bitreich.org 70 i 1070 *p++ = '\0'; Err bitreich.org 70 i 1071 Err bitreich.org 70 i 1072 /* Err bitreich.org 70 i 1073 * Be careful, we are using scanf. Err bitreich.org 70 i 1074 * TODO: Use some better parsing. Err bitreich.org 70 i 1075 */ Err bitreich.org 70 i 1076 memset(hachost, 0, sizeof(hachost)); Err bitreich.org 70 i 1077 memset(hashost, 0, sizeof(hashost)); Err bitreich.org 70 i 1078 memset(hacport, 0, sizeof(hacport)); Err bitreich.org 70 i 1079 memset(hasport, 0, sizeof(hasport)); Err bitreich.org 70 i 1080 Err bitreich.org 70 i 1081 haret = sscanf(recvb, "PROXY TCP%d %s %s %s %s", Err bitreich.org 70 i 1082 &tcpver, hachost, hashost, hacport, Err bitreich.org 70 i 1083 hasport); Err bitreich.org 70 i 1084 if (haret != 5) Err bitreich.org 70 i 1085 return 1; Err bitreich.org 70 i 1086 Err bitreich.org 70 i 1087 /* Err bitreich.org 70 i 1088 * Be careful. Everything could be Err bitreich.org 70 i 1089 * malicious. Err bitreich.org 70 i 1090 */ Err bitreich.org 70 i 1091 memset(clienth, 0, sizeof(clienth)); Err bitreich.org 70 i 1092 memmove(clienth, hachost, sizeof(clienth)-1); Err bitreich.org 70 i 1093 memset(serverh, 0, sizeof(serverh)); Err bitreich.org 70 i 1094 memmove(serverh, hashost, sizeof(serverh)-1); Err bitreich.org 70 i 1095 memset(clientp, 0, sizeof(clientp)); Err bitreich.org 70 i 1096 memmove(clientp, hacport, sizeof(clientp)-1); Err bitreich.org 70 i 1097 memset(serverp, 0, sizeof(serverp)); Err bitreich.org 70 i 1098 memmove(serverp, hasport, sizeof(serverp)-1); Err bitreich.org 70 i 1099 Err bitreich.org 70 i 1100 if (!strncmp(serverh, "::ffff:", 7)) { Err bitreich.org 70 i 1101 memmove(serverh, serverh+7, Err bitreich.org 70 i 1102 strlen(serverh)-6); Err bitreich.org 70 i 1103 } Err bitreich.org 70 i 1104 if (!strncmp(clienth, "::ffff:", 7)) { Err bitreich.org 70 i 1105 memmove(clienth, clienth+7, Err bitreich.org 70 i 1106 strlen(clienth)-6); Err bitreich.org 70 i 1107 } Err bitreich.org 70 i 1108 if (loglvl & CONN) { Err bitreich.org 70 i 1109 logentry(clienth, clientp, "-", Err bitreich.org 70 i 1110 "haproxy connection"); Err bitreich.org 70 i 1111 } Err bitreich.org 70 i 1112 Err bitreich.org 70 i 1113 goto read_selector_again; Err bitreich.org 70 i 1114 } Err bitreich.org 70 i 1115 Err bitreich.org 70 i 1116 #ifdef ENABLE_TLS Err bitreich.org 70 i 1117 if (istls) { Err bitreich.org 70 i 1118 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, tlssocks) < 0) { Err bitreich.org 70 i 1119 perror("tls_socketpair"); Err bitreich.org 70 i 1120 return 1; Err bitreich.org 70 i 1121 } Err bitreich.org 70 i 1122 Err bitreich.org 70 i 1123 switch(fork()) { Err bitreich.org 70 i 1124 case 0: Err bitreich.org 70 i 1125 sock = tlssocks[1]; Err bitreich.org 70 i 1126 close(tlssocks[0]); Err bitreich.org 70 i 1127 break; Err bitreich.org 70 i 1128 case -1: Err bitreich.org 70 i 1129 perror("fork"); Err bitreich.org 70 i 1130 return 1; Err bitreich.org 70 i 1131 default: Err bitreich.org 70 i 1132 tlsclientreader = 1; Err bitreich.org 70 i 1133 switch(fork()) { Err bitreich.org 70 i 1134 case 0: Err bitreich.org 70 i 1135 break; Err bitreich.org 70 i 1136 case -1: Err bitreich.org 70 i 1137 perror("fork"); Err bitreich.org 70 i 1138 return 1; Err bitreich.org 70 i 1139 default: Err bitreich.org 70 i 1140 tlsclientreader = 0; Err bitreich.org 70 i 1141 } Err bitreich.org 70 i 1142 Err bitreich.org 70 i 1143 close(tlssocks[tlsclientreader? 1 : 0]); Err bitreich.org 70 i 1144 do { Err bitreich.org 70 i 1145 if (tlsclientreader) { Err bitreich.org 70 i 1146 shuflen = read(tlssocks[0], Err bitreich.org 70 i 1147 shufbuf, Err bitreich.org 70 i 1148 sizeof(shufbuf)-1); Err bitreich.org 70 i 1149 } else { Err bitreich.org 70 i 1150 shuflen = tls_read(tlsclientctx, Err bitreich.org 70 i 1151 shufbuf, Err bitreich.org 70 i 1152 sizeof(shufbuf)-1); Err bitreich.org 70 i 1153 if (shuflen == TLS_WANT_POLLIN \ Err bitreich.org 70 i 1154 || shuflen == TLS_WANT_POLLOUT) { Err bitreich.org 70 i 1155 continue; Err bitreich.org 70 i 1156 } Err bitreich.org 70 i 1157 } Err bitreich.org 70 i 1158 if (shuflen == -1 && errno == EINTR) Err bitreich.org 70 i 1159 continue; Err bitreich.org 70 i 1160 for (shufpos = 0; shufpos < shuflen; Err bitreich.org 70 i 1161 shufpos += wlen) { Err bitreich.org 70 i 1162 if (tlsclientreader) { Err bitreich.org 70 i 1163 wlen = tls_write(tlsclientctx, Err bitreich.org 70 i 1164 shufbuf+shufpos, Err bitreich.org 70 i 1165 shuflen-shufpos); Err bitreich.org 70 i 1166 if (wlen == TLS_WANT_POLLIN Err bitreich.org 70 i 1167 || wlen == TLS_WANT_POLLOUT) { Err bitreich.org 70 i 1168 wlen = 0; Err bitreich.org 70 i 1169 continue; Err bitreich.org 70 i 1170 } Err bitreich.org 70 i 1171 if (wlen < 0) { Err bitreich.org 70 i 1172 fprintf(stderr, Err bitreich.org 70 i 1173 "tls_write failed: %s\n", Err bitreich.org 70 i 1174 tls_error(tlsclientctx)); Err bitreich.org 70 i 1175 return 1; Err bitreich.org 70 i 1176 } Err bitreich.org 70 i 1177 } else { Err bitreich.org 70 i 1178 wlen = write(tlssocks[1], Err bitreich.org 70 i 1179 shufbuf+shufpos, Err bitreich.org 70 i 1180 shuflen-shufpos); Err bitreich.org 70 i 1181 if (wlen < 0) { Err bitreich.org 70 i 1182 perror("write"); Err bitreich.org 70 i 1183 return 1; Err bitreich.org 70 i 1184 } Err bitreich.org 70 i 1185 } Err bitreich.org 70 i 1186 } Err bitreich.org 70 i 1187 } while (shuflen > 0); Err bitreich.org 70 i 1188 Err bitreich.org 70 i 1189 if (tlsclientreader) { Err bitreich.org 70 i 1190 wlen = TLS_WANT_POLLIN; Err bitreich.org 70 i 1191 while (wlen == TLS_WANT_POLLIN \ Err bitreich.org 70 i 1192 || wlen == TLS_WANT_POLLOUT) { Err bitreich.org 70 i 1193 wlen = tls_close(tlsclientctx); Err bitreich.org 70 i 1194 } Err bitreich.org 70 i 1195 tls_free(tlsclientctx); Err bitreich.org 70 i 1196 } Err bitreich.org 70 i 1197 Err bitreich.org 70 i 1198 lingersock(tlssocks[tlsclientreader? 0 : 1]); Err bitreich.org 70 i 1199 shutdown(tlssocks[tlsclientreader? 0 : 1], Err bitreich.org 70 i 1200 tlsclientreader? SHUT_WR : SHUT_RD); Err bitreich.org 70 i 1201 close(tlssocks[tlsclientreader? 0 : 1]); Err bitreich.org 70 i 1202 Err bitreich.org 70 i 1203 if (tlsclientreader) { Err bitreich.org 70 i 1204 lingersock(sock); Err bitreich.org 70 i 1205 close(sock); Err bitreich.org 70 i 1206 } Err bitreich.org 70 i 1207 return 0; Err bitreich.org 70 i 1208 } Err bitreich.org 70 i 1209 } Err bitreich.org 70 i 1210 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 1211 Err bitreich.org 70 i 1212 handlerequest(sock, recvb, rlen, base, Err bitreich.org 70 i 1213 (dohaproxy)? serverh : ohost, Err bitreich.org 70 i 1214 (dohaproxy)? serverp : sport, Err bitreich.org 70 i 1215 clienth, clientp, serverh, serverp, Err bitreich.org 70 i 1216 nocgi, istls); Err bitreich.org 70 i 1217 Err bitreich.org 70 i 1218 lingersock(sock); Err bitreich.org 70 i 1219 shutdown(sock, SHUT_RDWR); Err bitreich.org 70 i 1220 close(sock); Err bitreich.org 70 i 1221 Err bitreich.org 70 i 1222 if (loglvl & CONN) { Err bitreich.org 70 i 1223 logentry(clienth, clientp, "-", Err bitreich.org 70 i 1224 "disconnected"); Err bitreich.org 70 i 1225 } Err bitreich.org 70 i 1226 Err bitreich.org 70 i 1227 return 0; Err bitreich.org 70 i 1228 default: Err bitreich.org 70 i 1229 break; Err bitreich.org 70 i 1230 } Err bitreich.org 70 i 1231 close(sock); Err bitreich.org 70 i 1232 } Err bitreich.org 70 i 1233 Err bitreich.org 70 i 1234 if (dosyslog) { Err bitreich.org 70 i 1235 closelog(); Err bitreich.org 70 i 1236 } else if (logfile != NULL && glfd != -1) { Err bitreich.org 70 i 1237 close(glfd); Err bitreich.org 70 i 1238 glfd = -1; Err bitreich.org 70 i 1239 } Err bitreich.org 70 i 1240 free(ohost); Err bitreich.org 70 i 1241 Err bitreich.org 70 i 1242 for (i = 0; i < nlistfds; i++) { Err bitreich.org 70 i 1243 shutdown(listfds[i], SHUT_RDWR); Err bitreich.org 70 i 1244 close(listfds[i]); Err bitreich.org 70 i 1245 } Err bitreich.org 70 i 1246 free(listfds); Err bitreich.org 70 i 1247 Err bitreich.org 70 i 1248 #ifdef ENABLE_TLS Err bitreich.org 70 i 1249 if (dotls) { Err bitreich.org 70 i 1250 tls_close(tlsctx); Err bitreich.org 70 i 1251 tls_free(tlsctx); Err bitreich.org 70 i 1252 tls_config_free(tlsconfig); Err bitreich.org 70 i 1253 } Err bitreich.org 70 i 1254 #endif /* ENABLE_TLS */ Err bitreich.org 70 i 1255 Err bitreich.org 70 i 1256 return 0; Err bitreich.org 70 i 1257 } Err bitreich.org 70 i 1258 Err bitreich.org 70 .