From: Stephen D. <sd...@us...> - 2005-06-13 01:55:24
|
Update of /cvsroot/naviserver/naviserver/nsd In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26438/nsd Modified Files: conn.c driver.c nsd.h pathname.c server.c str.c Log Message: * nsd/str.c: Add new function Ns_StrIsHost. * include/ns.h: * nsd/nsd.h: * nsd/driver.c: Save the protocol seperate from the location in the driver structure and ensure the location always begins with a "protocol://" string. * nsd/server.c: * nsd/conn.c: * nsd/pathname.c: Simplify code by using protocol direct from driver structure and checking Host header with Ns_StrIsHost. Index: nsd.h =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/nsd.h,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** nsd.h 11 Jun 2005 18:40:31 -0000 1.16 --- nsd.h 13 Jun 2005 01:55:14 -0000 1.17 *************** *** 356,360 **** char *name; /* Driver name. */ char *location; /* Location, e.g, "http://foo:9090" */ ! char *address; /* Address in location. */ int sendwait; /* send() I/O timeout. */ int recvwait; /* recv() I/O timeout. */ --- 356,361 ---- char *name; /* Driver name. */ char *location; /* Location, e.g, "http://foo:9090" */ ! char *address; /* Address in location, e.g. "foo" */ ! char *protocol; /* Protocol in location, e.g, "http" */ int sendwait; /* send() I/O timeout. */ int recvwait; /* recv() I/O timeout. */ *************** *** 888,892 **** extern int NsUrlToFile(Ns_DString *dsPtr, NsServer *servPtr, char *url); ! extern char *NsPageRoot(Ns_DString *dest, NsServer *servPtr, char *host); /* --- 889,893 ---- extern int NsUrlToFile(Ns_DString *dsPtr, NsServer *servPtr, char *url); ! extern char *NsPageRoot(Ns_DString *dest, NsServer *servPtr, CONST char *host); /* Index: str.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/str.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** str.c 10 Jun 2005 17:58:39 -0000 1.2 --- str.c 13 Jun 2005 01:55:14 -0000 1.3 *************** *** 297,298 **** --- 297,333 ---- return NULL; } + + + /* + *---------------------------------------------------------------------- + * + * Ns_StrIsHost -- + * + * Does the given string contain only characters permitted in a + * Host header? Letters, digits, single periods and the colon port + * seperator are valid. + * + * Results: + * NS_TRUE or NS_FALSE. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + + int + Ns_StrIsHost(CONST char *string) + { + register CONST char *p; + + for (p = string; *p != '\0'; p++) { + if (!isalnum(*p) && *p != ':' + && (*p != '.' || (p[0] == '.' && p[1] == '.'))) { + + return NS_FALSE; + } + } + + return NS_TRUE; + } Index: pathname.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/pathname.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** pathname.c 10 Jun 2005 20:53:13 -0000 1.4 --- pathname.c 13 Jun 2005 01:55:14 -0000 1.5 *************** *** 48,52 **** Tcl_Obj *CONST objv[], int cmd); static char *MakePath(Ns_DString *dest, va_list *pap); ! static char *ServerRoot(Ns_DString *dest, NsServer *servPtr, char *host); --- 48,52 ---- Tcl_Obj *CONST objv[], int cmd); static char *MakePath(Ns_DString *dest, va_list *pap); ! static char *ServerRoot(Ns_DString *dest, NsServer *servPtr, CONST char *host); *************** *** 231,235 **** { CONST char *p = string; ! int i; for (i = 0; i < levels; ++i) { --- 231,235 ---- { CONST char *p = string; ! int i; for (i = 0; i < levels; ++i) { *************** *** 476,480 **** char * ! NsPageRoot(Ns_DString *dest, NsServer *servPtr, char *host) { char *path; --- 476,480 ---- char * ! NsPageRoot(Ns_DString *dest, NsServer *servPtr, CONST char *host) { char *path; *************** *** 702,706 **** char * ! NsTclServerRoot(Ns_DString *dest, char *host, void *arg) { Ns_TclCallback *cbPtr = arg; --- 702,706 ---- char * ! NsTclServerRoot(Ns_DString *dest, CONST char *host, void *arg) { Ns_TclCallback *cbPtr = arg; *************** *** 782,790 **** static char * ! ServerRoot(Ns_DString *dest, NsServer *servPtr, char *host) { ! char *p, *path, *port = NULL; ! Ns_Conn *conn; ! Ns_Set *headers; if (servPtr->vhost.serverRootProc != NULL) { --- 782,791 ---- static char * ! ServerRoot(Ns_DString *dest, NsServer *servPtr, CONST char *rawhost) { ! char *safehost, *path, *p; ! Ns_Conn *conn; ! Ns_Set *headers; ! Ns_DString ds; if (servPtr->vhost.serverRootProc != NULL) { *************** *** 794,798 **** */ ! path = (servPtr->vhost.serverRootProc)(dest, host, servPtr->vhost.serverRootArg); if (path == NULL) { goto defpath; --- 795,799 ---- */ ! path = (servPtr->vhost.serverRootProc)(dest, rawhost, servPtr->vhost.serverRootArg); if (path == NULL) { goto defpath; *************** *** 800,842 **** } else if (servPtr->vhost.enabled ! && (host != NULL || ((conn = Ns_GetConn()) != NULL && (headers = Ns_ConnHeaders(conn)) != NULL ! && (host = Ns_SetIGet(headers, "Host")) != NULL)) ! && *host != '\0') { /* ! * Bail out if there are suspicious characters. */ ! for (p = host; *p != '\0'; p++) { ! if (isslash(*p) || isspace(*p) || (p[0] == '.' && p[1] == '.')) { ! goto defpath; ! } } - host = Ns_StrToLower(host); ! path = Ns_MakePath(dest, servPtr->fastpath.serverdir, ! servPtr->vhost.hostprefix, NULL); ! if (servPtr->vhost.opts & NSD_STRIP_WWW) { ! if (strncmp(host, "www.", 4) == 0) { ! host = &host[4]; ! } } ! if (servPtr->vhost.opts & NSD_STRIP_PORT) { ! if ((port = strrchr(host, ':')) != NULL) { ! *port = '\0'; ! } } ! if (servPtr->vhost.hosthashlevel > 0) { ! Ns_HashPath(dest, host, servPtr->vhost.hosthashlevel); ! } ! Ns_NormalizePath(dest, host); ! if (port != NULL) { ! *port = ':'; } } else { --- 801,846 ---- } else if (servPtr->vhost.enabled ! && (rawhost != NULL || ((conn = Ns_GetConn()) != NULL && (headers = Ns_ConnHeaders(conn)) != NULL ! && (rawhost = Ns_SetIGet(headers, "Host")) != NULL)) ! && *rawhost != '\0') { /* ! * Bail out if there are suspicious characters in the unprocessed Host. */ ! if (!Ns_StrIsHost(rawhost)) { ! goto defpath; } ! /* ! * Normalize the Host string. ! */ ! Ns_DStringInit(&ds); ! safehost = Ns_DStringAppend(&ds, rawhost); ! ! Ns_StrToLower(safehost); ! if (servPtr->vhost.opts & NSD_STRIP_WWW ! && strncmp(safehost, "www.", 4) == 0) { ! safehost = &safehost[4]; } ! if (servPtr->vhost.opts & NSD_STRIP_PORT ! && (p = strrchr(safehost, ':')) != NULL) { ! *p = '\0'; } ! /* ! * Build the final path. ! */ ! path = Ns_MakePath(dest, servPtr->fastpath.serverdir, ! servPtr->vhost.hostprefix, NULL); ! if (servPtr->vhost.hosthashlevel > 0) { ! Ns_HashPath(dest, safehost, servPtr->vhost.hosthashlevel); } + Ns_NormalizePath(dest, safehost); + Ns_DStringFree(&ds); } else { Index: server.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/server.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** server.c 10 Jun 2005 20:53:13 -0000 1.5 --- server.c 13 Jun 2005 01:55:14 -0000 1.6 *************** *** 439,443 **** } if (servPtr->vhost.enabled) { ! NsPageRoot(&ds, servPtr, ns_strdup("www.example.com:80")); Ns_Log(Notice, "vhost[%s]: www.example.com:80 -> %s", server, ds.string); --- 439,443 ---- } if (servPtr->vhost.enabled) { ! NsPageRoot(&ds, servPtr, "www.example.com:80"); Ns_Log(Notice, "vhost[%s]: www.example.com:80 -> %s", server, ds.string); Index: driver.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/driver.c,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** driver.c 11 Jun 2005 10:00:18 -0000 1.10 --- driver.c 13 Jun 2005 01:55:14 -0000 1.11 *************** *** 1,2 **** --- 1,3 ---- + /* * The contents of this file are subject to the AOLserver Public License *************** *** 252,260 **** if (init->opts & NS_DRIVER_SSL) { ! defproto = "https"; ! defport = 443; } else { ! defproto = "http"; ! defport = 80; } --- 253,261 ---- if (init->opts & NS_DRIVER_SSL) { ! defproto = "https"; ! defport = 443; } else { ! defproto = "http"; ! defport = 80; } *************** *** 347,367 **** * Determine the port and then set the HTTP location string either * as specified in the config file or constructed from the ! * hostname and port. */ drvPtr->address = ns_strdup(address); if (!Ns_ConfigGetInt(path, "port", &drvPtr->port)) { ! drvPtr->port = defport; } drvPtr->location = Ns_ConfigGetValue(path, "location"); ! if (drvPtr->location != NULL) { ! drvPtr->location = ns_strdup(drvPtr->location); } else { ! Ns_DStringInit(&ds); ! Ns_DStringVarAppend(&ds, defproto, "://", host, NULL); ! if (drvPtr->port != defport) { ! Ns_DStringPrintf(&ds, ":%d", drvPtr->port); ! } ! drvPtr->location = Ns_DStringExport(&ds); } drvPtr->nextPtr = firstDrvPtr; firstDrvPtr = drvPtr; --- 348,371 ---- * Determine the port and then set the HTTP location string either * as specified in the config file or constructed from the ! * protocol, hostname and port. */ + + drvPtr->protocol = ns_strdup(defproto); drvPtr->address = ns_strdup(address); if (!Ns_ConfigGetInt(path, "port", &drvPtr->port)) { ! drvPtr->port = defport; } drvPtr->location = Ns_ConfigGetValue(path, "location"); ! if (drvPtr->location != NULL && strstr(drvPtr->location, "://")) { ! drvPtr->location = ns_strdup(drvPtr->location); } else { ! Ns_DStringInit(&ds); ! Ns_DStringVarAppend(&ds, drvPtr->protocol, "://", host, NULL); ! if (drvPtr->port != defport) { ! Ns_DStringPrintf(&ds, ":%d", drvPtr->port); ! } ! drvPtr->location = Ns_DStringExport(&ds); } + drvPtr->nextPtr = firstDrvPtr; firstDrvPtr = drvPtr; *************** *** 392,396 **** Ns_Log(Error, "%s: duplicate host map: %s", module, host); } else { ! Ns_DStringVarAppend(&ds, defproto, "://", host, NULL); mapPtr = ns_malloc(sizeof(ServerMap) + ds.length); mapPtr->servPtr = servPtr; --- 396,400 ---- Ns_Log(Error, "%s: duplicate host map: %s", module, host); } else { ! Ns_DStringVarAppend(&ds, drvPtr->protocol, "://", host, NULL); mapPtr = ns_malloc(sizeof(ServerMap) + ds.length); mapPtr->servPtr = servPtr; Index: conn.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/conn.c,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** conn.c 12 Jun 2005 14:42:44 -0000 1.16 --- conn.c 13 Jun 2005 01:55:13 -0000 1.17 *************** *** 484,489 **** NsServer *servPtr = connPtr->servPtr; Ns_Set *headers; ! Ns_DString ds; ! char *location, *host, *p; if (servPtr->vhost.connLocationProc != NULL) { --- 484,488 ---- NsServer *servPtr = connPtr->servPtr; Ns_Set *headers; ! char *location, *host; if (servPtr->vhost.connLocationProc != NULL) { *************** *** 518,551 **** /* * Construct a location string from the HTTP host header. - * - * We do not trust the contents of the Host header, so we scan - * it for new lines which may be a reponse splitting attack when - * used as the target of a redirect reponse, and the HTML open - * tag character which may be a cross-site scripting attack when - * embedded within HTML. */ ! for (p = host; *p != '\0'; ++p) { ! if (*p == '\n' || *p == '\r' || *p == '<') { ! return NULL; ! } } ! /* ! * Get the scheme from the driver location, default to http://. ! */ ! ! Ns_DStringInit(&ds); ! Ns_DStringAppend(&ds, connPtr->location); ! location = strstr(ds.string, "://"); ! if (location != NULL) { ! Ns_DStringTrunc(&ds, (location - ds.string) + 3); ! Ns_DStringNAppend(dest, ds.string, ds.length); ! } else { ! /* server missconfiguration, should begin: SCHEME:// */ ! Ns_DStringAppend(dest, "http://"); ! } ! Ns_DStringFree(&ds); ! location = Ns_DStringAppend(dest, host); } else { --- 517,528 ---- /* * Construct a location string from the HTTP host header. */ ! if (!Ns_StrIsHost(host)) { ! goto deflocation; } ! location = Ns_DStringVarAppend(dest, ! connPtr->drvPtr->protocol, "://", host, NULL); } else { |