DIR * opendir(const char *name) { DIR *dir = NULL; char path[FILENAME_MAX]; wchar_t wpath[FILENAME_MAX]; if (name == NULL || name[0] == '\0') { errno = EINVAL; } else if ((dir = malloc(sizeof(*dir))) == NULL) { errno = ENOMEM; } else { _shttpd_snprintf(path, sizeof(path), "%s/*", name); fix_directory_separators(path); MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, sizeof(wpath)); dir->handle = FindFirstFileW(wpath, &dir->info); if (dir->handle != INVALID_HANDLE_VALUE) { dir->result.d_name[0] = '\0'; } else { free(dir); dir = NULL; } } return (dir); }
int _shttpd_rename(const char *path1, const char *path2) { char buf1[FILENAME_MAX]; char buf2[FILENAME_MAX]; wchar_t wbuf1[FILENAME_MAX]; wchar_t wbuf2[FILENAME_MAX]; _shttpd_strlcpy(buf1, path1, sizeof(buf1)); _shttpd_strlcpy(buf2, path2, sizeof(buf2)); fix_directory_separators(buf1); fix_directory_separators(buf2); MultiByteToWideChar(CP_UTF8, 0, buf1, -1, wbuf1, sizeof(wbuf1)); MultiByteToWideChar(CP_UTF8, 0, buf2, -1, wbuf2, sizeof(wbuf2)); return (_wrename(wbuf1, wbuf2)); }
int _shttpd_remove(const char *path) { char buf[FILENAME_MAX]; wchar_t wbuf[FILENAME_MAX]; _shttpd_strlcpy(buf, path, sizeof(buf)); fix_directory_separators(buf); MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf)); return (_wremove(wbuf)); }
int _shttpd_open(const char *path, int flags, int mode) { char buf[FILENAME_MAX]; wchar_t wbuf[FILENAME_MAX]; _shttpd_strlcpy(buf, path, sizeof(buf)); fix_directory_separators(buf); MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf)); if (protect_against_code_disclosure(wbuf) == FALSE) return (-1); return (_wopen(wbuf, flags)); }
int _shttpd_stat(const char *path, struct stat *stp) { char buf[FILENAME_MAX], *p; wchar_t wbuf[FILENAME_MAX]; _shttpd_strlcpy(buf, path, sizeof(buf)); fix_directory_separators(buf); p = buf + strlen(buf) - 1; while (p > buf && *p == '\\' && p[-1] != ':') *p-- = '\0'; MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf)); return (_wstat(wbuf, (struct _stat *) stp)); }
static void test_fix_directory_separators(void) { const char *in[] = {"\\\\server\\\\dir/file.txt", "//\\///a", "c:/a//\\\\//////b", NULL}; const char *out[] = {"\\\\server\\dir\\file.txt", "\\\\a", "c:\\a\\b"}; char buf[FILENAME_MAX]; int i; for (i = 0; in[i] != NULL; i++) { mg_strlcpy(buf, in[i], sizeof(buf)); fix_directory_separators(buf); if (strcmp(buf, out[i]) != 0) fail("%s(%s): expected [%s], got [%s]", __func__, in[i], out[i], buf); } }
int _shttpd_spawn_process(struct conn *c, const char *prog, char *envblk, char *envp[], int sock, const char *dir) { HANDLE a[2], b[2], h[2], me; DWORD flags; char *p, *interp, cmdline[FILENAME_MAX], line[FILENAME_MAX]; FILE *fp; STARTUPINFOA si; PROCESS_INFORMATION pi; me = GetCurrentProcess(); flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS; /* FIXME add error checking code here */ CreatePipe(&a[0], &a[1], NULL, 0); CreatePipe(&b[0], &b[1], NULL, 0); DuplicateHandle(me, a[0], me, &h[0], 0, TRUE, flags); DuplicateHandle(me, b[1], me, &h[1], 0, TRUE, flags); (void) memset(&si, 0, sizeof(si)); (void) memset(&pi, 0, sizeof(pi)); /* XXX redirect CGI errors to the error log file */ si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.hStdOutput = h[1]; si.hStdInput = h[0]; /* If CGI file is a script, try to read the interpreter line */ interp = c->ctx->options[OPT_CGI_INTERPRETER]; if (interp == NULL) { if ((fp = fopen(prog, "r")) != NULL) { (void) fgets(line, sizeof(line), fp); if (memcmp(line, "#!", 2) != 0) line[2] = '\0'; /* Trim whitespaces from interpreter name */ for (p = &line[strlen(line) - 1]; p > line && isspace(*p); p--) *p = '\0'; (void) fclose(fp); } interp = line + 2; (void) _shttpd_snprintf(cmdline, sizeof(cmdline), "%s%s%s", line + 2, line[2] == '\0' ? "" : " ", prog); } if ((p = strrchr(prog, '/')) != NULL) prog = p + 1; (void) _shttpd_snprintf(cmdline, sizeof(cmdline), "%s %s", interp, prog); (void) _shttpd_snprintf(line, sizeof(line), "%s", dir); fix_directory_separators(line); fix_directory_separators(cmdline); /* * Spawn reader & writer threads before we create CGI process. * Otherwise CGI process may die too quickly, loosing the data */ spawn_stdio_thread(sock, b[0], stdinput, 0); spawn_stdio_thread(sock, a[1], stdoutput, c->rem.content_len); if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, envblk, line, &si, &pi) == 0) { _shttpd_elog(E_LOG, c, "redirect: CreateProcess(%s): %d", cmdline, ERRNO); return (-1); } else { CloseHandle(h[0]); CloseHandle(h[1]); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } return (0); }