void bozo_daemon_init(bozohttpd_t *httpd) { struct addrinfo h, *r, *r0; const char *portnum; int e, i, on = 1; if (!httpd->background) return; portnum = (httpd->bindport) ? httpd->bindport : "http"; memset(&h, 0, sizeof(h)); h.ai_family = PF_UNSPEC; h.ai_socktype = SOCK_STREAM; h.ai_flags = AI_PASSIVE; e = getaddrinfo(httpd->bindaddress, portnum, &h, &r0); if (e) bozo_err(httpd, 1, "getaddrinfo([%s]:%s): %s", httpd->bindaddress ? httpd->bindaddress : "*", portnum, gai_strerror(e)); for (r = r0; r != NULL; r = r->ai_next) httpd->nsock++; httpd->sock = bozomalloc(httpd, httpd->nsock * sizeof(*httpd->sock)); httpd->fds = bozomalloc(httpd, httpd->nsock * sizeof(*httpd->fds)); for (i = 0, r = r0; r != NULL; r = r->ai_next) { httpd->sock[i] = socket(r->ai_family, SOCK_STREAM, 0); if (httpd->sock[i] == -1) continue; if (setsockopt(httpd->sock[i], SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) bozo_warn(httpd, "setsockopt SO_REUSEADDR: %s", strerror(errno)); if (bind(httpd->sock[i], r->ai_addr, r->ai_addrlen) == -1) continue; if (listen(httpd->sock[i], SOMAXCONN) == -1) continue; httpd->fds[i].events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND | POLLERR; httpd->fds[i].fd = httpd->sock[i]; i++; } if (i == 0) bozo_err(httpd, 1, "could not find any addresses to bind"); httpd->nsock = i; freeaddrinfo(r0); if (httpd->foreground == 0) daemon(1, 0); create_pidfile(httpd); bozo_warn(httpd, "started in daemon mode as `%s' port `%s' root `%s'", httpd->virthostname, portnum, httpd->slashdir); signal(SIGHUP, controlled_exit); signal(SIGINT, controlled_exit); signal(SIGTERM, controlled_exit); signal(SIGCHLD, sigchild); }
/* * bozo_user_transform does this: * - chdir's /~user/public_html * - returns the rest of the file, index.html appended if required * - returned malloced file to serve in request->hr_file, * ala transform_request(). * * transform_request() is supposed to check that we have user support * enabled. */ int bozo_user_transform(bozo_httpreq_t *request, int *isindex) { bozohttpd_t *httpd = request->hr_httpd; char c, *s, *file = NULL; struct passwd *pw; *isindex = 0; if ((s = strchr(request->hr_file + 2, '/')) != NULL) { *s++ = '\0'; c = s[strlen(s)-1]; *isindex = (c == '/' || c == '\0'); } debug((httpd, DEBUG_OBESE, "looking for user %s", request->hr_file + 2)); pw = getpwnam(request->hr_file + 2); /* fix this up immediately */ if (s) s[-1] = '/'; if (pw == NULL) { (void)bozo_http_error(httpd, 404, request, "no such user"); return 0; } debug((httpd, DEBUG_OBESE, "user %s dir %s/%s uid %d gid %d", pw->pw_name, pw->pw_dir, httpd->public_html, pw->pw_uid, pw->pw_gid)); if (chdir(pw->pw_dir) < 0) { bozo_warn(httpd, "chdir1 error: %s: %s", pw->pw_dir, strerror(errno)); (void)bozo_http_error(httpd, 404, request, "can't chdir to homedir"); return 0; } if (chdir(httpd->public_html) < 0) { bozo_warn(httpd, "chdir2 error: %s: %s", httpd->public_html, strerror(errno)); (void)bozo_http_error(httpd, 404, request, "can't chdir to public_html"); return 0; } if (s == NULL || *s == '\0') { file = bozostrdup(httpd, httpd->index_html); } else { file = bozomalloc(httpd, strlen(s) + (*isindex ? strlen(httpd->index_html) + 1 : 1)); strcpy(file, s); if (*isindex) strcat(file, httpd->index_html); } /* see transform_request() */ if (*file == '/' || strcmp(file, "..") == 0 || strstr(file, "/..") || strstr(file, "../")) { (void)bozo_http_error(httpd, 403, request, "illegal request"); free(file); return 0; } if (bozo_auth_check(request, file)) { free(file); return 0; } free(request->hr_file); request->hr_file = file; debug((httpd, DEBUG_FAT, "transform_user returning %s under %s", file, pw->pw_dir)); return 1; }