Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Updates to comments. Use size_t instead of int where appropriate. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | althttpd-scgi |
Files: | files | file ages | folders |
SHA3-256: |
5faf086850b3c47ead8e9e09b0a07001 |
User & Date: | drh 2019-02-15 20:27:54.271 |
Context
2019-02-15
| ||
20:31 | Mention the use of SCGI in the althttpd.md file. (Closed-Leaf check-in: d2ad0c8ca6 user: drh tags: althttpd-scgi) | |
20:27 | Updates to comments. Use size_t instead of int where appropriate. (check-in: 5faf086850 user: drh tags: althttpd-scgi) | |
20:14 | Preliminary support for SCGI in althttpd. (check-in: b3aaed91ba user: drh tags: althttpd-scgi) | |
Changes
Changes to misc/althttpd.c.
1 2 3 4 5 6 7 | /* ** A small, simple HTTP server. ** ** Features: ** ** * Launched from inetd/xinetd/stunnel4, or as a stand-alone server ** * One process per request | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /* ** A small, simple HTTP server. ** ** Features: ** ** * Launched from inetd/xinetd/stunnel4, or as a stand-alone server ** * One process per request ** * Deliver static content or run CGI or SCGI ** * Virtual sites based on the "Host:" property of the HTTP header ** * Runs in a chroot jail ** * Unified log file in a CSV format ** * Small code base (this 1 file) to facilitate security auditing ** * Simple setup - no configuration files to misconfigure ** ** This file implements a small and simple but secure and effective web |
︙ | ︙ | |||
38 39 40 41 42 43 44 | ** RFC-5785 to allow letsencrypt or certbot to generate a TSL cert ** using webroot. ** ** (4) Characters other than [0-9a-zA-Z,-./:_~] and any %HH characters ** escapes in the filename are all translated into "_". This is ** a defense against cross-site scripting attacks and other mischief. ** | | | > > > > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | ** RFC-5785 to allow letsencrypt or certbot to generate a TSL cert ** using webroot. ** ** (4) Characters other than [0-9a-zA-Z,-./:_~] and any %HH characters ** escapes in the filename are all translated into "_". This is ** a defense against cross-site scripting attacks and other mischief. ** ** (5) Executable files are run as CGI. Files whose name ends with ".scgi"**** trigger and SCGI request (see item 10 below). All other files ** are delivered as is. ** ** (6) For SSL support use stunnel and add the -https 1 option on the ** httpd command-line. ** ** (7) If a file named "-auth" exists in the same directory as the file to ** be run as CGI or to be delivered, then it contains information ** for HTTP Basic authorization. See file format details below. ** ** (8) To run as a stand-alone server, simply add the "-port N" command-line ** option to define which TCP port to listen on. ** ** (9) For static content, the mimetype is determined by the file suffix ** using a table built into the source code below. If you have ** unusual content files, you might need to extend this table. ** ** (10) Content files that end with ".scgi" and that contain text of the ** form "SCGI hostname port" will format an SCGI request and send it ** to hostname:port, the relay back the reply. ** ** Command-line Options: ** ** --root DIR Defines the directory that contains the various ** $HOST.website subdirectories, each containing web content ** for a single virtual host. If launched as root and if ** "--user USER" also appears on the command-line and if |
︙ | ︙ | |||
302 303 304 305 306 307 308 | }; /* ** Double any double-quote characters in a string. */ static char *Escape(char *z){ | | | | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | }; /* ** Double any double-quote characters in a string. */ static char *Escape(char *z){ size_t i, j; size_t n; char c; char *zOut; for(i=0; (c=z[i])!=0 && c!='"'; i++){} if( c==0 ) return z; n = 1; for(i++; (c=z[i])!=0; i++){ if( c=='"' ) n++; } zOut = malloc( i+n+1 ); |
︙ | ︙ | |||
423 424 425 426 427 428 429 | } statusSent = 0; } /* ** Allocate memory safely */ | | | | 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 | } statusSent = 0; } /* ** Allocate memory safely */ static char *SafeMalloc( size_t size ){ char *p; p = (char*)malloc(size); if( p==0 ){ strcpy(zReplyStatus, "998"); MakeLogEntry(1,100); /* LOG: Malloc() failed */ exit(1); } return p; } /* ** Set the value of environment variable zVar to zValue. */ static void SetEnv(const char *zVar, const char *zValue){ char *z; size_t len; if( zValue==0 ) zValue=""; /* Disable an attempted bashdoor attack */ if( strncmp(zValue,"() {",4)==0 ) zValue = ""; len = strlen(zVar) + strlen(zValue) + 2; z = SafeMalloc(len); sprintf(z,"%s=%s",zVar,zValue); putenv(z); |
︙ | ︙ | |||
478 479 480 481 482 483 484 | } /* ** Make a copy of a string into memory obtained from malloc. */ static char *StrDup(const char *zSrc){ char *zDest; | | | | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | } /* ** Make a copy of a string into memory obtained from malloc. */ static char *StrDup(const char *zSrc){ char *zDest; size_t size; if( zSrc==0 ) return 0; size = strlen(zSrc) + 1; zDest = (char*)SafeMalloc( size ); strcpy(zDest,zSrc); return zDest; } static char *StrAppend(char *zPrior, const char *zSep, const char *zSrc){ char *zDest; size_t size; int n1, n2; if( zSrc==0 ) return 0; if( zPrior==0 ) return StrDup(zSrc); size = (n1=strlen(zSrc)) + (n2=strlen(zSep)) + strlen(zPrior) + 1; zDest = (char*)SafeMalloc( size ); strcpy(zDest,zPrior); |
︙ | ︙ | |||
1182 1183 1184 1185 1186 1187 1188 | ** A CGI or SCGI script has run and is sending its reply back across ** the channel "in". Process this reply into an appropriate HTTP reply. ** Close the "in" channel when done. */ static void CgiHandleReply(FILE *in){ int seenContentLength = 0; /* True if Content-length: header seen */ int contentLength = 0; /* The content length */ | | | | 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 | ** A CGI or SCGI script has run and is sending its reply back across ** the channel "in". Process this reply into an appropriate HTTP reply. ** Close the "in" channel when done. */ static void CgiHandleReply(FILE *in){ int seenContentLength = 0; /* True if Content-length: header seen */ int contentLength = 0; /* The content length */ size_t nRes = 0; /* Bytes of payload */ size_t nMalloc = 0; /* Bytes of space allocated to aRes */ char *aRes = 0; /* Payload */ int c; /* Next character from in */ char *z; /* Pointer to something inside of zLine */ char zLine[1000]; /* One line of reply from the CGI script */ if( useTimeout ) alarm(15); while( fgets(zLine,sizeof(zLine),in) && !isspace(zLine[0]) ){ |
︙ | ︙ | |||
1241 1242 1243 1244 1245 1246 1247 | if( aRes==0 ){ Malfunction(610, "Out of memory: %d bytes", nMalloc); } } aRes[nRes++] = c; } aRes[nRes] = 0; | | | 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 | if( aRes==0 ){ Malfunction(610, "Out of memory: %d bytes", nMalloc); } } aRes[nRes++] = c; } aRes[nRes] = 0; nOut += printf("Content-length: %d\r\n\r\n%s", (int)nRes, aRes); free(aRes); } fclose(in); } /* ** Send an SCGI request to a host identified by zFile and process the |
︙ | ︙ | |||
1263 1264 1265 1266 1267 1268 1269 | char *zPort = 0; int rc; int iSocket = -1; struct addrinfo hints; struct addrinfo *ai = 0; struct addrinfo *p; char *zHdr; | | | | 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 | char *zPort = 0; int rc; int iSocket = -1; struct addrinfo hints; struct addrinfo *ai = 0; struct addrinfo *p; char *zHdr; size_t nHdr = 0; size_t nHdrAlloc; int i; char zLine[1000]; in = fopen(zFile, "rb"); if( in==0 ){ Malfunction(700, "cannot open \"%s\"\n", zFile); } if( fgets(zLine, sizeof(zLine)-1, in)==0 ){ |
︙ | ︙ | |||
1311 1312 1313 1314 1315 1316 1317 | if( s==0 ){ Malfunction(706, "could not turn the socket into a FILE\n"); } nHdrAlloc = 0; zHdr = 0; if( zContentLength==0 ) zContentLength = "0"; | | | | 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 | if( s==0 ){ Malfunction(706, "could not turn the socket into a FILE\n"); } nHdrAlloc = 0; zHdr = 0; if( zContentLength==0 ) zContentLength = "0"; for(i=0; i<(int)(sizeof(cgienv)/sizeof(cgienv[0])); i++){ int n1, n2; if( cgienv[i].pzEnvValue[0]==0 ) continue; n1 = (int)strlen(cgienv[i].zEnvName); n2 = (int)strlen(*cgienv[i].pzEnvValue); if( n1+n2+2+nHdr >= nHdrAlloc ){ nHdrAlloc = nHdr + n1 + n2 + 1000; zHdr = realloc(zHdr, nHdrAlloc); if( zHdr==0 ){ Malfunction(706, "out of memory"); } } memcpy(zHdr+nHdr, cgienv[i].zEnvName, n1); nHdr += n1; zHdr[nHdr++] = 0; memcpy(zHdr+nHdr, *cgienv[i].pzEnvValue, n2); nHdr += n2; zHdr[nHdr++] = 0; } fprintf(s,"%d:",(int)nHdr); fwrite(zHdr, 1, nHdr, s); fprintf(s,","); free(zHdr); if( zMethod[0]=='P' && atoi(zContentLength)>0 && (in = fopen(zTmpNam,"r"))!=0 ){ size_t n; |
︙ | ︙ | |||
1583 1584 1585 1586 1587 1588 1589 | /* Create a file to hold the POST query data, if any. We have to ** do it this way. We can't just pass the file descriptor down to ** the child process because the fgets() function may have already ** read part of the POST data into its internal buffer. */ if( zMethod[0]=='P' && zContentLength!=0 ){ | | | 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 | /* Create a file to hold the POST query data, if any. We have to ** do it this way. We can't just pass the file descriptor down to ** the child process because the fgets() function may have already ** read part of the POST data into its internal buffer. */ if( zMethod[0]=='P' && zContentLength!=0 ){ size_t len = atoi(zContentLength); FILE *out; char *zBuf; int n; if( len>MAX_CONTENT_LENGTH ){ StartResponse("500 Request too large"); nOut += printf( |
︙ | ︙ |