static void processHeader(const char * const fieldName, char * const fieldValue, TSession * const sessionP, const char ** const errorP, uint16_t * const httpErrorCodeP) { /*---------------------------------------------------------------------------- We may modify *fieldValue, and we put pointers to *fieldValue and *fieldName into *sessionP. We must fix this some day. *sessionP should point to individual malloc'ed strings. -----------------------------------------------------------------------------*/ *errorP = NULL; /* initial assumption */ if (xmlrpc_streq(fieldName, "connection")) { if (xmlrpc_strcaseeq(fieldValue, "keep-alive")) sessionP->requestInfo.keepalive = TRUE; else sessionP->requestInfo.keepalive = FALSE; } else if (xmlrpc_streq(fieldName, "host")) { if (sessionP->requestInfo.host) { xmlrpc_strfree(sessionP->requestInfo.host); sessionP->requestInfo.host = NULL; } parseHostPort(fieldValue, &sessionP->requestInfo.host, &sessionP->requestInfo.port, errorP, httpErrorCodeP); } else if (xmlrpc_streq(fieldName, "from")) sessionP->requestInfo.from = fieldValue; else if (xmlrpc_streq(fieldName, "user-agent")) sessionP->requestInfo.useragent = fieldValue; else if (xmlrpc_streq(fieldName, "referer")) sessionP->requestInfo.referer = fieldValue; else if (xmlrpc_streq(fieldName, "range")) { if (xmlrpc_strneq(fieldValue, "bytes=", 6)) { bool succeeded; succeeded = ListAddFromString(&sessionP->ranges, &fieldValue[6]); if (!succeeded) { xmlrpc_asprintf(errorP, "ListAddFromString() failed for " "\"range: bytes=...\" header value '%s'", &fieldValue[6]); *httpErrorCodeP = 400; } } } else if (xmlrpc_streq(fieldName, "cookies")) { bool succeeded; succeeded = ListAddFromString(&sessionP->cookies, fieldValue); if (!succeeded) { xmlrpc_asprintf(errorP, "ListAddFromString() failed for " "cookies: header value '%s'", fieldValue); *httpErrorCodeP = 400; } } else if (xmlrpc_streq(fieldName, "expect")) { if (xmlrpc_strcaseeq(fieldValue, "100-continue")) sessionP->continueRequired = TRUE; } }
bool RequestAuth(TSession * const sessionP, const char * const credential, const char * const user, const char * const pass) { /*---------------------------------------------------------------------------- Authenticate requester, in a very simplistic fashion. If the request executing on session *sessionP specifies basic authentication (via Authorization header) with username 'user', password 'pass', then return TRUE. Else, return FALSE and set up an authorization failure response (HTTP response status 401) that says user must supply an identity in the 'credential' domain. When we return TRUE, we also set the username in the request info for the session to 'user' so that a future SessionGetRequestInfo can get it. -----------------------------------------------------------------------------*/ bool authorized; char * authHdrPtr; authHdrPtr = RequestHeaderValue(sessionP, "authorization"); if (authHdrPtr) { const char * authType; NextToken((const char **)&authHdrPtr); GetTokenConst(&authHdrPtr, &authType); authType = GetToken(&authHdrPtr); if (authType) { if (xmlrpc_strcaseeq(authType, "basic")) { const char * userPass; char userPassEncoded[80]; NextToken((const char **)&authHdrPtr); xmlrpc_asprintf(&userPass, "%s:%s", user, pass); xmlrpc_base64Encode(userPass, userPassEncoded); xmlrpc_strfree(userPass); if (xmlrpc_streq(authHdrPtr, userPassEncoded)) { sessionP->requestInfo.user = strdup(user); authorized = TRUE; } else authorized = FALSE; } else authorized = FALSE; } else authorized = FALSE; } else authorized = FALSE; if (!authorized) { const char * hdrValue; xmlrpc_asprintf(&hdrValue, "Basic realm=\"%s\"", credential); ResponseAddField(sessionP, "WWW-Authenticate", hdrValue); xmlrpc_strfree(hdrValue); ResponseStatus(sessionP, 401); } return authorized; }
static bool ConfReadBool(const char * const token, bool * const bP) { bool succeeded; if (xmlrpc_strcaseeq(token, "yes")) { *bP = TRUE; succeeded = TRUE; } else if (xmlrpc_strcaseeq(token, "no")) { *bP = FALSE; succeeded = TRUE; } else succeeded = FALSE; return succeeded; }
static bool ConfReadBool(const char * const token, bool * const bP) { bool succeeded; if (xmlrpc_strcaseeq(token, "yes")) { *bP = true; succeeded = true; } else if (xmlrpc_strcaseeq(token, "no")) { *bP = false; succeeded = true; } else succeeded = false; return succeeded; }
static void processHeader(const char * const fieldName, char * const fieldValue, TSession * const sessionP, uint16_t * const httpErrorCodeP) { /*---------------------------------------------------------------------------- We may modify *fieldValue, and we put pointers to *fieldValue and *fieldName into *sessionP. We must fix this some day. *sessionP should point to individual malloc'ed strings. -----------------------------------------------------------------------------*/ *httpErrorCodeP = 0; /* initial assumption */ if (xmlrpc_streq(fieldName, "connection")) { if (xmlrpc_strcaseeq(fieldValue, "keep-alive")) sessionP->request_info.keepalive = TRUE; else sessionP->request_info.keepalive = FALSE; } else if (xmlrpc_streq(fieldName, "host")) parseHostPort(fieldValue, &sessionP->request_info.host, &sessionP->request_info.port, httpErrorCodeP); else if (xmlrpc_streq(fieldName, "from")) sessionP->request_info.from = fieldValue; else if (xmlrpc_streq(fieldName, "user-agent")) sessionP->request_info.useragent = fieldValue; else if (xmlrpc_streq(fieldName, "referer")) sessionP->request_info.referer = fieldValue; else if (xmlrpc_streq(fieldName, "range")) { if (xmlrpc_strneq(fieldValue, "bytes=", 6)) { abyss_bool succeeded; succeeded = ListAddFromString(&sessionP->ranges, &fieldValue[6]); *httpErrorCodeP = succeeded ? 0 : 400; } } else if (xmlrpc_streq(fieldName, "cookies")) { abyss_bool succeeded; succeeded = ListAddFromString(&sessionP->cookies, fieldValue); *httpErrorCodeP = succeeded ? 0 : 400; } }
abyss_bool RequestAuth(TSession * const sessionP, const char * const credential, const char * const user, const char * const pass) { /*---------------------------------------------------------------------------- Authenticate requester, in a very simplistic fashion. If the request executing on session *sessionP specifies basic authentication (via Authorization header) with username 'user', password 'pass', then return true. Else, return false and set up an authorization failure response (HTTP response status 401) that says user must supply an identity in the 'credential' domain. When we return true, we also set the username in the request info for the session to 'user' so that a future SessionGetRequestInfo can get it. -----------------------------------------------------------------------------*/ bool authorized; const char * authValue; authValue = RequestHeaderValue(sessionP, "authorization"); if (authValue) { char * const valueBuffer = malloc(strlen(authValue)); /* A buffer we can mangle as we parse the authorization: value */ if (!authValue) /* Should return error, but we have no way to do that */ authorized = false; else { const char * authType; char * authHdrPtr; strcpy(valueBuffer, authValue); authHdrPtr = &valueBuffer[0]; NextToken((const char **)&authHdrPtr); GetTokenConst(&authHdrPtr, &authType); if (authType) { if (xmlrpc_strcaseeq(authType, "basic")) { const char * userPass; char userPassEncoded[80]; NextToken((const char **)&authHdrPtr); xmlrpc_asprintf(&userPass, "%s:%s", user, pass); xmlrpc_base64Encode(userPass, userPassEncoded); xmlrpc_strfree(userPass); if (xmlrpc_streq(authHdrPtr, userPassEncoded)) { sessionP->requestInfo.user = xmlrpc_strdupsol(user); authorized = true; } else authorized = false; } else authorized = false; } else authorized = false; free(valueBuffer); } } else authorized = false; if (!authorized) { const char * hdrValue; xmlrpc_asprintf(&hdrValue, "Basic realm=\"%s\"", credential); ResponseAddField(sessionP, "WWW-Authenticate", hdrValue); xmlrpc_strfree(hdrValue); ResponseStatus(sessionP, 401); } return authorized; }
abyss_bool ConfReadServerFile(const char * const filename, TServer * const serverP) { struct _TServer * const srvP = serverP->srvP; BIHandler * const handlerP = srvP->builtinHandlerP; TFile * fileP; char z[512]; char * p; unsigned int lineNum; TFileStat fs; if (!FileOpen(&fileP, filename, O_RDONLY)) return FALSE; lineNum = 0; while (ConfReadLine(fileP, z, 512)) { ++lineNum; p = z; if (ConfNextToken(&p)) { const char * const option = ConfGetToken(&p); if (option) { ConfNextToken(&p); if (xmlrpc_strcaseeq(option, "port")) { int32_t n; if (ConfReadInt(p, &n, 1, 65535)) srvP->port = n; else TraceExit("Invalid port '%s'", p); } else if (xmlrpc_strcaseeq(option, "serverroot")) { bool success; chdirx(p, &success); if (!success) TraceExit("Invalid server root '%s'",p); } else if (xmlrpc_strcaseeq(option, "path")) { if (FileStat(p, &fs)) if (fs.st_mode & S_IFDIR) { HandlerSetFilesPath(handlerP, p); continue; } TraceExit("Invalid path '%s'", p); } else if (xmlrpc_strcaseeq(option, "default")) { const char * filename; while ((filename = ConfGetToken(&p))) { HandlerAddDefaultFN(handlerP, filename); if (!ConfNextToken(&p)) break; } } else if (xmlrpc_strcaseeq(option, "keepalive")) { int32_t n; if (ConfReadInt(p, &n, 1, 65535)) srvP->keepalivemaxconn = n; else TraceExit("Invalid KeepAlive value '%s'", p); } else if (xmlrpc_strcaseeq(option, "timeout")) { int32_t n; if (ConfReadInt(p, &n, 1, 3600)) { srvP->keepalivetimeout = n; /* Must see what to do with that */ srvP->timeout = n; } else TraceExit("Invalid TimeOut value '%s'", p); } else if (xmlrpc_strcaseeq(option, "mimetypes")) { MIMEType * mimeTypeP; readMIMETypesFile(p, &mimeTypeP); if (!mimeTypeP) TraceExit("Can't read MIME Types file '%s'", p); else HandlerSetMimeType(handlerP, mimeTypeP); } else if (xmlrpc_strcaseeq(option,"logfile")) { srvP->logfilename = strdup(p); } else if (xmlrpc_strcaseeq(option,"user")) { parseUser(p, srvP); } else if (xmlrpc_strcaseeq(option, "pidfile")) { parsePidfile(p, srvP); } else if (xmlrpc_strcaseeq(option, "advertiseserver")) { if (!ConfReadBool(p, &srvP->advertise)) TraceExit("Invalid boolean value " "for AdvertiseServer option"); } else TraceExit("Invalid option '%s' at line %u", option, lineNum); } } } FileClose(fileP); return TRUE; }