Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | some fixes + make cgipattern in configuration |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
a3939c5c55a16b7ace96ac48373371cc |
User & Date: | bapt@FreeBSD.org 2010-10-05 00:51:04.000 |
Context
2010-10-05
| ||
00:51 | Merge branch 'master' of git://repo.bsdsx.fr/zhttpd check-in: 55fac5a901 user: bapt@FreeBSD.org tags: trunk | |
00:51 | some fixes + make cgipattern in configuration check-in: a3939c5c55 user: bapt@FreeBSD.org tags: trunk | |
2010-09-27
| ||
16:06 | Make vhost work correctly check-in: 702893a660 user: bapt@FreeBSD.org tags: trunk | |
Changes
Changes to mini_httpd.c.
︙ | ︙ | |||
173 174 175 176 177 178 179 | static void do_file(struct client *, char *); static void do_dir(struct client *, char *); static char *file_details(const char *dir, const char *name, const char *script_name); static void strencode(char *to, size_t tosize, const char *from); static void do_cgi(struct client *, char *); static void cgi_interpose_input(struct client *cl, int wfd); static void cgi_interpose_output(struct client *cl, int rfd, int parse_headers); | | | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | static void do_file(struct client *, char *); static void do_dir(struct client *, char *); static char *file_details(const char *dir, const char *name, const char *script_name); static void strencode(char *to, size_t tosize, const char *from); static void do_cgi(struct client *, char *); static void cgi_interpose_input(struct client *cl, int wfd); static void cgi_interpose_output(struct client *cl, int rfd, int parse_headers); static char **make_argp(char *, char *); static char **make_envp(struct client *); static char *build_env(char *fmt, char *arg); static void auth_check(struct client *, char *dirname); static void send_authenticate(struct client *cl, char *realm); static void send_error(struct client *, int s, char *title, char *extra_header, char *text); static void send_error_body(struct client *, int s, char *title, char *text); static int send_error_file(struct client *, char *filename); |
︙ | ︙ | |||
518 519 520 521 522 523 524 525 526 527 528 529 530 531 | cl->protocol = NULL; cl->status = 0; cl->bytes = -1; sz = sizeof(cl->ss); cl->fd = accept(ke.ident, (struct sockaddr *)&cl->ss, &sz); if (cl->fd < 0) { if (errno == EINTR || errno == EAGAIN) continue; /* try again */ #ifdef EPROTO if (errno == EPROTO) | > | 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 | cl->protocol = NULL; cl->status = 0; cl->bytes = -1; sz = sizeof(cl->ss); cl->fd = accept(ke.ident, (struct sockaddr *)&cl->ss, &sz); cl->remote_addr = ntop(&cl->ss); if (cl->fd < 0) { if (errno == EINTR || errno == EAGAIN) continue; /* try again */ #ifdef EPROTO if (errno == EPROTO) |
︙ | ︙ | |||
779 780 781 782 783 784 785 | /* Check authorization for this directory. */ auth_check(cl, dirname(filepath)); filename = basename(filepath); /* Check if the filename is the AUTH_FILE itself - that's verboten. */ if (strcmp(filename, AUTH_FILE) == 0) { | | | | | 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 | /* Check authorization for this directory. */ auth_check(cl, dirname(filepath)); filename = basename(filepath); /* Check if the filename is the AUTH_FILE itself - that's verboten. */ if (strcmp(filename, AUTH_FILE) == 0) { syslog(LOG_NOTICE, "%.80s URL \"%.80s\" tried to retrieve an auth file", cl->remote_addr, cl->script_name); send_error(cl, 403, "Forbidden", "", "File is protected."); return; } /* Is it CGI? */ if (conf.cgi_pattern != NULL && fnmatch(conf.cgi_pattern, filename, FNM_CASEFOLD) == 0) { do_cgi(cl, filepath); return; } fd = open(filepath, O_RDONLY); if (fd < 0) { syslog(LOG_INFO, "%.80s File \"%.80s\" is protected", cl->remote_addr, cl->script_name); send_error(cl, 403, "Forbidden", "", "File is protected."); return; } mime_type = figure_mime(filepath, mime_encodings, sizeof(mime_encodings)); snprintf(fixed_mime_type, sizeof(fixed_mime_type), mime_type, conf.charset); if (cl->if_modified_since != -1 && |
︙ | ︙ | |||
843 844 845 846 847 848 849 | char *name_info; /* Check authorization for this directory. */ auth_check(cl, path); n = scandir(path, &dl, NULL, alphasort); if (n < 0) { | | | 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 | char *name_info; /* Check authorization for this directory. */ auth_check(cl, path); n = scandir(path, &dl, NULL, alphasort); if (n < 0) { syslog(LOG_INFO, "%.80s Directory \"%.80s\" is protected", cl->remote_addr, cl->script_name); send_error(cl, 403, "Forbidden", "", "Directory is protected."); return; } buflen = snprintf(buf, sizeof(buf), "\ <HTML>\n\ <HEAD><TITLE>Index of %s</TITLE></HEAD>\n\ |
︙ | ︙ | |||
954 955 956 957 958 959 960 | */ } /* Make the environment vector. */ envp = make_envp(cl); /* Make the argument vector. */ | | | | | 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 | */ } /* Make the environment vector. */ envp = make_envp(cl); /* Make the argument vector. */ argp = make_argp(cl->query_string, filepath); /* Set up stdin. For POSTs we may have to set up a pipe from an ** interposer process, depending on if we've read some of the data ** into our buffer. We also have to do this for all SSL CGIs. */ #ifdef USE_SSL if ((cl->method == METHOD_POST) || do_ssl) #else /* USE_SSL */ if (cl->method == METHOD_POST) #endif /* USE_SSL */ { int p[2]; int r; if (pipe(p) < 0) send_error(cl, 500, "Internal Error", "", "Something unexpected went wrong making a pipe."); |
︙ | ︙ | |||
1016 1017 1018 1019 1020 1021 1022 | int r; if (pipe(p) < 0) send_error(cl, 500, "Internal Error", "", "Something unexpected went wrong making a pipe."); r = fork(); if (r < 0) send_error(cl, 500, "Internal Error", "", "Something unexpected went wrong forking an interposer."); | < | > | | | | | | < | < | | | | < | | > | < > | 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 | int r; if (pipe(p) < 0) send_error(cl, 500, "Internal Error", "", "Something unexpected went wrong making a pipe."); r = fork(); if (r < 0) send_error(cl, 500, "Internal Error", "", "Something unexpected went wrong forking an interposer."); if (r == 0) { /* Interposer process. */ close(p[1]); cgi_interpose_output(cl, p[0], parse_headers); return; } close(p[0]); if (p[1] != STDOUT_FILENO) dup2(p[1], STDOUT_FILENO); if (p[1] != STDERR_FILENO) dup2(p[1], STDERR_FILENO); if (p[1] != STDOUT_FILENO && p[1] != STDERR_FILENO) close(p[1]); } else { /* Otherwise, the request socket is stdout/stderr. */ if (cl->fd != STDOUT_FILENO) (void) dup2(cl->fd, STDOUT_FILENO); if (cl->fd != STDERR_FILENO) (void) dup2(cl->fd, STDERR_FILENO); } /* At this point we would like to set conn_fd to be close-on-exec. ** Unfortunately there seems to be a Linux problem here - if we ** do this close-on-exec in Linux, the socket stays open but stderr ** gets closed - the last fd duped from the socket. What a mess. ** So we'll just leave the socket as is, which under other OSs means ** an extra file descriptor gets passed to the child process. Since ** the child probably already has that file open via stdin stdout ** and/or stderr, this is not a problem. */ /* (void) fcntl(conn_fd, F_SETFD, 1); */ /* Close syslog. */ /*closelog();*/ /* Set priority. */ nice(CGI_NICE); /* Split the program into directory and binary, so we can chdir() ** to the program's own directory. This isn't in the CGI 1.1 ** spec, but it's what other HTTP servers do. */ directory = strdup(filepath); binary = strrchr(directory, '/'); if (binary == (char*) 0) binary = file; else { *binary++ = '\0'; chdir(directory); /* ignore errors */ } /* Default behavior for SIGPIPE. */ sigset(SIGPIPE, SIG_DFL); syslog(LOG_ERR,"kikoo %s %s", filepath, binary); /* Run the program. */ execve( binary, argp, envp ); send_error(cl, 500, "Internal Error", "", "Something unexpected went wrong running a CGI program."); exit (1); } /* This routine is used only for POST requests. It reads the data ** from the request and sends it to the child process. The only reason ** we need to do it this way instead of just letting the child read ** directly is that we have already read part of the data into our ** buffer. |
︙ | ︙ | |||
1140 1141 1142 1143 1144 1145 1146 | char buf[1024]; if (! parse_headers) { /* If we're not parsing headers, write out the default status line ** and proceed to the echo phase. */ | | | 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 | char buf[1024]; if (! parse_headers) { /* If we're not parsing headers, write out the default status line ** and proceed to the echo phase. */ char http_head[] = "HTTP/1.0 200 OK\r\n"; zhttpd_write(cl->fd, http_head, sizeof(http_head)); } else { /* Header parsing. The idea here is that the CGI can return special ** headers such as "Status:" and "Location:" which change the return ** status of the response. Since the return status has to be the very |
︙ | ︙ | |||
1257 1258 1259 1260 1261 1262 1263 | } /* Set up CGI argument vector. We don't have to worry about freeing ** stuff since we're a sub-process. This gets done after make_envp() because ** we scribble on query. */ static char** | | > > > > > > | | | | | | | < | < | < | < | 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 | } /* Set up CGI argument vector. We don't have to worry about freeing ** stuff since we're a sub-process. This gets done after make_envp() because ** we scribble on query. */ static char** make_argp(char *query, char *filepath) { char** argp; int argn; char *cp1; char *cp2; size_t len; if (query == NULL) len = 2; else len = strlen(query) + 2; /* By allocating an arg slot for every character in the query, plus ** one for the filename and one for the NULL, we are guaranteed to ** have enough. We could actually use strlen/2. */ argp = malloc(len * sizeof(char*)); if (argp == NULL) return NULL; argp[0] = strrchr(filepath, '/'); if (argp[0] != NULL) ++argp[0]; else argp[0] = filepath; argn = 1; /* According to the CGI spec at http://hoohoo.ncsa.uiuc.edu/cgi/cl.html, ** "The server should search the query information for a non-encoded = ** character to determine if the command line is to be used, if it finds ** one, the command line is not to be used." */ if (query != NULL && strchr(query, '=') == NULL) { for (cp1 = cp2 = query; *cp2 != '\0'; ++cp2) { if (*cp2 == '+') { *cp2 = '\0'; strdecode(cp1, cp1); argp[argn++] = cp1; cp1 = cp2 + 1; } } if (cp2 != cp1) { strdecode(cp1, cp1); argp[argn++] = cp1; } } argp[argn] = NULL; return argp; |
︙ | ︙ | |||
1342 1343 1344 1345 1346 1347 1348 | envp[envn++] = build_env("SCRIPT_NAME=%s", cl->script_name); if (cl->path_info != NULL) { envp[envn++] = build_env("PATH_INFO=/%s", cl->path_info); (void) snprintf(buf, sizeof(buf), "/%s", cl->path_info); envp[envn++] = build_env("PATH_TRANSLATED=%s", buf); } | | | | | | 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 | envp[envn++] = build_env("SCRIPT_NAME=%s", cl->script_name); if (cl->path_info != NULL) { envp[envn++] = build_env("PATH_INFO=/%s", cl->path_info); (void) snprintf(buf, sizeof(buf), "/%s", cl->path_info); envp[envn++] = build_env("PATH_TRANSLATED=%s", buf); } if (cl->query_string != NULL) envp[envn++] = build_env("QUERY_STRING=%s", cl->query_string); envp[envn++] = build_env("REMOTE_ADDR=%s", cl->remote_addr); if (cl->referer != NULL) envp[envn++] = build_env("HTTP_REFERER=%s", cl->referer); if (cl->user_agent != NULL) envp[envn++] = build_env("HTTP_USER_AGENT=%s", cl->user_agent); if (cl->cookie != NULL) envp[envn++] = build_env("HTTP_COOKIE=%s", cl->cookie); if (cl->host != NULL) envp[envn++] = build_env("HTTP_HOST=%s", cl->host); if (cl->content_type != NULL) envp[envn++] = build_env("CONTENT_TYPE=%s", cl->content_type); |
︙ | ︙ | |||
1452 1453 1454 1455 1456 1457 1458 | /* Open the password file. */ fp = fopen(authpath, "r"); if (fp == (FILE*) 0) { /* The file exists but we can't open it? Disallow access. */ syslog( LOG_ERR, "%.80s auth file %.80s could not be opened - %m", | | | 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 | /* Open the password file. */ fp = fopen(authpath, "r"); if (fp == (FILE*) 0) { /* The file exists but we can't open it? Disallow access. */ syslog( LOG_ERR, "%.80s auth file %.80s could not be opened - %m", cl->remote_addr, authpath); send_error(cl, 403, "Forbidden", "", "File is protected."); } /* Read it. */ while (fgets(line, sizeof(line), fp) != (char*) 0) { /* Nuke newline. */ |
︙ | ︙ |
Changes to parse.y.
︙ | ︙ | |||
134 135 136 137 138 139 140 | TAILQ_INSERT_HEAD(&conf.vhosts, vh, entry); } ; set : SET STRING STRING { if (!strcmp($2, "servername")) { conf.servername = $3; | | | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | TAILQ_INSERT_HEAD(&conf.vhosts, vh, entry); } ; set : SET STRING STRING { if (!strcmp($2, "servername")) { conf.servername = $3; } else if (!strcmp($2, "cgipattern")) { conf.cgi_pattern = $3; } else if (!strcmp($2, "charset")) { conf.charset = $3; } else if (!strcmp($2, "logfile")) { conf.logfile = $3; } else if (!strcmp($2, "chroot")) { conf.chroot = $3; |
︙ | ︙ |
Changes to zhttpd.conf.
1 2 3 4 5 6 7 | #set cgi_pattern *.cgi #set chroot #set debug set rootdir /tmp listen on 127.0.0.1 port 7777 listen on :: port 8888 | > | 1 2 3 4 5 6 7 8 | set cgipattern *.cgi #set cgi_pattern *.cgi #set chroot #set debug set rootdir /tmp listen on 127.0.0.1 port 7777 listen on :: port 8888 |
︙ | ︙ |
Changes to zhttpd.h.
︙ | ︙ | |||
34 35 36 37 38 39 40 41 42 43 44 45 46 47 | char *user; int debug; int maxage; }; struct client { int fd; struct sockaddr_storage ss; int method; char *response; char *request; char *body; char *script_name; char *query_string;; | > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | char *user; int debug; int maxage; }; struct client { int fd; char *remote_addr; struct sockaddr_storage ss; int method; char *response; char *request; char *body; char *script_name; char *query_string;; |
︙ | ︙ |