/* * Format an authentication response. This is typically a 401 response code. */ static void formatAuthResponse(MaConn *conn, MaAuth *auth, int code, char *msg, char *logMsg) { MaRequest *req; #if BLD_FEATURE_AUTH_DIGEST char *qopClass, *nonceStr, *etag; #endif req = conn->request; if (logMsg == 0) { logMsg = msg; } mprLog(conn, 3, "formatAuthResponse: code %d, %s\n", code, logMsg); if (auth->type == MA_AUTH_BASIC) { maSetHeader(conn, 0, "WWW-Authenticate", "Basic realm=\"%s\"", auth->requiredRealm); #if BLD_FEATURE_AUTH_DIGEST } else if (auth->type == MA_AUTH_DIGEST) { qopClass = auth->qop; /* * Use the etag as our opaque string */ etag = conn->response->etag; if (etag == 0) { etag = ""; } if (etag[0] == '"') { etag = mprStrdup(req, etag); etag = mprStrTrim(etag, "\""); } mprCalcDigestNonce(req, &nonceStr, conn->host->secret, etag, auth->requiredRealm); if (strcmp(qopClass, "auth") == 0) { maSetHeader(conn, 0, "WWW-Authenticate", "Digest realm=\"%s\", domain=\"%s\", " "qop=\"auth\", nonce=\"%s\", opaque=\"%s\", algorithm=\"MD5\", stale=\"FALSE\"", auth->requiredRealm, conn->host->name, nonceStr, etag); } else if (strcmp(qopClass, "auth-int") == 0) { maSetHeader(conn, 0, "WWW-Authenticate", "Digest realm=\"%s\", domain=\"%s\", " "qop=\"auth\", nonce=\"%s\", opaque=\"%s\", algorithm=\"MD5\", stale=\"FALSE\"", auth->requiredRealm, conn->host->name, nonceStr, etag); } else { maSetHeader(conn, 0, "WWW-Authenticate", "Digest realm=\"%s\", nonce=\"%s\"", auth->requiredRealm, nonceStr); } mprFree(nonceStr); #endif } maFailRequest(conn, code, "Authentication Error: %s", msg); }
int MaSslModule::parseConfig(char *key, char *value, MaServer *server, MaHost *host, MaAuth *auth, MaDir *dir, MaLocation *location) { MaSslConfig *config; char pathBuf[MPR_MAX_FNAME], prefix[MPR_MAX_FNAME]; char *tok, *word, *enable, *provider; int protoMask, mask; mprStrcpy(prefix, sizeof(prefix), key); prefix[3] = '\0'; if (mprStrCmpAnyCase(prefix, "SSL") != 0) { return 0; } if (mprStrCmpAnyCase(key, "SSLEngine") == 0) { enable = mprStrTok(value, " \t", &tok); provider = mprStrTok(0, " \t", &tok); if (mprStrCmpAnyCase(value, "on") == 0) { if (sslProvider == 0) { mprError(MPR_L, MPR_LOG, "Missing an SSL Provider\n"); return MPR_ERR_BAD_SYNTAX; } config = (MaSslConfig*) sslConfigTable->lookup(host->getName()); if (config == 0) { config = sslProvider->newConfig(host); mprAssert(config); sslConfigTable->insert(config); } host->setSecure(1); host->server->setSslListeners(host, config); } return 1; } config = (MaSslConfig*) sslConfigTable->lookup(host->getName()); if (config == 0) { mprError(MPR_L, MPR_LOG, "Missing SSLEngine directive\n"); return MPR_ERR_BAD_SYNTAX; } if (host->makePath(pathBuf, sizeof(pathBuf), mprStrTrim(value, '\"')) == 0) { mprError(MPR_L, MPR_LOG, "SSL path is too long"); return MPR_ERR_BAD_SYNTAX; } if (mprStrCmpAnyCase(key, "SSLCACertificatePath") == 0) { config->setCaPath(pathBuf); return 1; } else if (mprStrCmpAnyCase(key, "SSLCACertificateFile") == 0) { config->setCaFile(pathBuf); return 1; } else if (mprStrCmpAnyCase(key, "SSLCertificateFile") == 0) { config->setCertFile(pathBuf); return 1; } else if (mprStrCmpAnyCase(key, "SSLCertificateKeyFile") == 0) { config->setKeyFile(pathBuf); return 1; } else if (mprStrCmpAnyCase(key, "SSLCipherSuite") == 0) { config->setCipherSuite(value); return 1; } else if (mprStrCmpAnyCase(key, "SSLVerifyClient") == 0) { if (mprStrCmpAnyCase(value, "require") == 0) { config->setVerifyClient(1); } else if (mprStrCmpAnyCase(value, "none") == 0) { config->setVerifyClient(0); } else { return -1; } return 1; } else if (mprStrCmpAnyCase(key, "SSLProtocol") == 0) { protoMask = 0; word = mprStrTok(value, " \t", &tok); while (word) { mask = -1; if (*word == '-') { word++; mask = 0; } else if (*word == '+') { word++; } if (mprStrCmpAnyCase(word, "SSLv2") == 0) { protoMask &= ~(MPR_HTTP_PROTO_SSLV2 & ~mask); protoMask |= (MPR_HTTP_PROTO_SSLV2 & mask); } else if (mprStrCmpAnyCase(word, "SSLv3") == 0) { protoMask &= ~(MPR_HTTP_PROTO_SSLV3 & ~mask); protoMask |= (MPR_HTTP_PROTO_SSLV3 & mask); } else if (mprStrCmpAnyCase(word, "TLSv1") == 0) { protoMask &= ~(MPR_HTTP_PROTO_TLSV1 & ~mask); protoMask |= (MPR_HTTP_PROTO_TLSV1 & mask); } else if (mprStrCmpAnyCase(word, "ALL") == 0) { protoMask &= ~(MPR_HTTP_PROTO_ALL & ~mask); protoMask |= (MPR_HTTP_PROTO_ALL & mask); } word = mprStrTok(0, " \t", &tok); } config->setSslProto(protoMask); return 1; } return 0; }
/* * Parse the appweb.conf directives for authorization */ static int parseAuth(MaHttp *http, cchar *key, char *value, MaConfigState *state) { MaServer *server; MaHost *host; MaAuth *auth; MaAcl acl; char *path, *names, *tok, *type, *aclSpec; server = state->server; host = state->host; auth = state->auth; if (mprStrcmpAnyCase(key, "AuthGroupFile") == 0) { path = maMakePath(host, mprStrTrim(value, "\"")); if (maReadGroupFile(server, auth, path) < 0) { mprError(http, "Can't open AuthGroupFile %s", path); return MPR_ERR_BAD_SYNTAX; } mprFree(path); return 1; } else if (mprStrcmpAnyCase(key, "AuthMethod") == 0) { value = mprStrTrim(value, "\""); if (mprStrcmpAnyCase(value, "pam") == 0) { auth->method = MA_AUTH_METHOD_PAM; return 1; } else if (mprStrcmpAnyCase(value, "file") == 0) { auth->method = MA_AUTH_METHOD_FILE; return 1; } else { return MPR_ERR_BAD_SYNTAX; } } else if (mprStrcmpAnyCase(key, "AuthName") == 0) { maSetAuthRealm(auth, mprStrTrim(value, "\"")); return 1; } else if (mprStrcmpAnyCase(key, "AuthType") == 0) { value = mprStrTrim(value, "\""); if (mprStrcmpAnyCase(value, "Basic") == 0) { auth->type = MA_AUTH_BASIC; } else if (mprStrcmpAnyCase(value, "None") == 0) { auth->type = 0; #if BLD_FEATURE_AUTH_DIGEST } else if (mprStrcmpAnyCase(value, "Digest") == 0) { auth->type = MA_AUTH_DIGEST; #endif } else { mprError(http, "Unsupported authorization protocol"); return MPR_ERR_BAD_SYNTAX; } return 1; } else if (mprStrcmpAnyCase(key, "AuthUserFile") == 0) { path = maMakePath(host, mprStrTrim(value, "\"")); if (maReadUserFile(server, auth, path) < 0) { mprError(http, "Can't open AuthUserFile %s", path); return MPR_ERR_BAD_SYNTAX; } mprFree(path); return 1; #if BLD_FEATURE_AUTH_DIGEST } else if (mprStrcmpAnyCase(key, "AuthDigestQop") == 0) { value = mprStrTrim(value, "\""); mprStrLower(value); if (strcmp(value, "none") != 0 && strcmp(value, "auth") != 0 && strcmp(value, "auth-int") != 0) { return MPR_ERR_BAD_SYNTAX; } maSetAuthQop(auth, value); return 1; } else if (mprStrcmpAnyCase(key, "AuthDigestAlgorithm") == 0) { return 1; } else if (mprStrcmpAnyCase(key, "AuthDigestDomain") == 0) { return 1; } else if (mprStrcmpAnyCase(key, "AuthDigestNonceLifetime") == 0) { return 1; #endif } else if (mprStrcmpAnyCase(key, "Require") == 0) { if (maGetConfigValue(http, &type, value, &tok, 1) < 0) { return MPR_ERR_BAD_SYNTAX; } if (mprStrcmpAnyCase(type, "acl") == 0) { aclSpec = mprStrTrim(tok, "\""); acl = maParseAcl(auth, aclSpec); maSetRequiredAcl(auth, acl); } else if (mprStrcmpAnyCase(type, "valid-user") == 0) { maSetAuthAnyValidUser(auth); } else { names = mprStrTrim(tok, "\""); if (mprStrcmpAnyCase(type, "user") == 0) { maSetAuthRequiredUsers(auth, names); } else if (mprStrcmpAnyCase(type, "group") == 0) { maSetAuthRequiredGroups(auth, names); } else { mprError(http, "Bad Require syntax: %s", type); return MPR_ERR_BAD_SYNTAX; } } return 1; } return 0; }
static int parseEjs(MaHttp *http, cchar *key, char *value, MaConfigState *state) { MaLocation *location; MaServer *server; MaHost *host; char *prefix, *path; int flags; host = state->host; server = state->server; location = state->location; flags = location->flags & (MA_LOC_BROWSER | MA_LOC_AUTO_SESSION); #if UNUSED MaStage *ejsHandler; EjsWebControl *web; if (mprStrcmpAnyCase(key, "Ejs") == 0) { path = mprStrTrim(value, "\""); mprCleanFilename(http, path); if (!mprAccess(http, path, X_OK)) { mprError(http, "Can't access Ejs path %s", path); return MPR_ERR_BAD_SYNTAX; } if ((ejsHandler = maLookupStage(http, "ejsHandler")) == 0) { mprError(http, "Ejscript module is not loaded"); return MPR_ERR_BAD_SYNTAX; } web = (EjsWebControl*) ejsHandler->stageData; web->ejsLibDir = path; } else #endif if (mprStrcmpAnyCase(key, "EjsApp") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_APP; } else { location->flags &= ~MA_LOC_APP; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppDir") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_APP_DIR; } else { location->flags &= ~MA_LOC_APP_DIR; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppAlias") == 0) { if (maSplitConfigValue(server, &prefix, &path, value, 1) < 0 || path == 0 || prefix == 0) { return MPR_ERR_BAD_SYNTAX; } location = maCreateLocationAlias(http, state, prefix, path, "ejsHandler", MA_LOC_APP | flags); if (location == 0) { return MPR_ERR_BAD_SYNTAX; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppDirAlias") == 0) { if (maSplitConfigValue(server, &prefix, &path, value, 1) < 0 || path == 0 || prefix == 0) { return MPR_ERR_BAD_SYNTAX; } location = maCreateLocationAlias(http, state, prefix, path, "ejsHandler", MA_LOC_APP_DIR | flags); if (location == 0) { return MPR_ERR_BAD_SYNTAX; } return 1; } else if (mprStrcmpAnyCase(key, "EjsErrors") == 0) { if (mprStrcmpAnyCase(value, "browser") == 0) { location->flags |= MA_LOC_BROWSER; } else { location->flags &= ~MA_LOC_BROWSER; } return 1; } else if (mprStrcmpAnyCase(key, "EjsSessionTimeout") == 0) { if (value == 0) { return MPR_ERR_BAD_SYNTAX; } if (! mprGetDebugMode(http)) { location->sessionTimeout = atoi(mprStrTrim(value, "\"")); } return 1; } else if (mprStrcmpAnyCase(key, "EjsSession") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_AUTO_SESSION; } else { location->flags &= ~MA_LOC_AUTO_SESSION; } return 1; } return 0; }
/* * When we come here, we've already matched either a location block or an extension */ static int run(request_rec *r) { EjsDirConfig *dir; EjsServerConfig *server; cchar *ext; MaRequest *req; MaResponse *resp; MaConn *conn; MaAlias *alias; MaLocation *location; EjsWeb *web; cchar *sep, *prefix; char *urlBase, *dir, *app, *url, *cp; int flags, locFlags; if (!r->handler || strcasecmp(r->handler, "ejs") != 0) { return DECLINED; } dir = getDir(r) server = getServer(r->XXX); // EjsAlias should probably be creating a directory block. These flags should probably be in a directory if (loc->flags & (MA_LOC_APP | MA_LOC_APP_DIR)) { /* * Send non-ejs content under web to another handler, typically the file handler. */ if (strncmp(&req->url[loc->prefixLen], "web/", 4) == 0) { if (!(ext && strcmp(ext, "ejs") == 0)) { return DECLINED; } } else { if (ext && strcmp(ext, "ejs") == 0) { maFormatBody(conn, "Bad Request", "Can't serve *.ejs files outside web directory"); maFailRequest(conn, MPR_HTTP_CODE_BAD_REQUEST, "Can't server *.ejs files outside web directory"); return HTTP_XXX; } } } flags = 0; url = 0; locFlags = location->flags; if (locFlags & MA_LOC_APP) { app = mprStrTrim(mprStrdup(q, prefix), "/"); url = &req->url[alias->prefixLen]; dir = mprStrdup(resp, alias->filename); if (*url != '/') { url--; } urlBase = mprStrdup(resp, prefix); } else if (locFlags & MA_LOC_APP_DIR) { url = &req->url[alias->prefixLen]; app = mprStrdup(resp, url); if ((cp = strchr(app, '/')) != 0) { url = mprStrdup(resp, cp); *cp = '\0'; } sep = prefix[strlen(prefix) - 1] == '/' ? "" : "/"; dir = mprStrcat(resp, &dir, alias->filename, sep, app, NULL); urlBase = mprStrcat(resp, prefix, sep, app, NULL); } else { app = 0; dir = mprStrdup(resp, alias->filename); url = &req->url[alias->prefixLen]; flags |= EJS_WEB_FLAG_SOLO; if (*url != '/') { url--; } urlBase = mprStrdup(resp, prefix); } mprStrTrim(urlBase, "/"); mprStrTrim(dir, "/"); if (location->flags & MA_LOC_BROWSER) { flags |= EJS_WEB_FLAG_BROWSER_ERRORS; } if (location->flags & MA_LOC_AUTO_SESSION) { flags |= EJS_WEB_FLAG_SESSION; } /* * Var Stand-Alone App AppDir * app 0 carmen carmen * dir /Users/mob/.... /Users/mob/hg/carmen /Users/mob/hg/carmen * urlBase /xg/carmen /carmen * url stock stock */ web = ejsCreateWebRequest(req, q->stage->stageData, conn, app, dir, urlBase, url, req->cookie, flags); if (web == 0) { maFailRequest(conn, MPR_HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't create Ejs web object for %s", req->url); return; } q->queueData = web; maSetHeader(conn, 0, "Last-Modified", req->host->currentDate); maDontCacheResponse(conn); if (r->method_number != M_GET) { return HTTP_METHOD_NOT_ALLOWED; } if (ejsProcessWebRequest((EjsWeb*) r, &msg) < 0) { if (web->flags & EJS_WEB_FLAG_BROWSER_ERRORS) { maFormatBody(conn, "Request Failed", "%s", msg); } maFailRequest(conn, MPR_HTTP_CODE_BAD_GATEWAY, msg); mprFree(msg); } ap_set_content_type(r, "text/html"); ap_rputs("<html><title>Hello World!</title><body><p>Hello World</p></body></html>\r\n", r); #if 0 if ((err = set_content_length(r, r->finfo.st_stize)) || (err = set_last_modified(r, r->finfo.st_mtime))) return err; if (r->finof.st_mode == 0) return NOT_FOUND; fopen(r->filename, "r"); if (!r->main) { /* Not internal redirect */ apr_table_set(r->headers_out, "X-ejs", "Under construction"); } register_timeout("send", r); send_http_header(r); if (!r->header_only) send_fd(f, r); pfclose(r->pool, f); #endif return OK; }
static int parseEjs(MaHttp *http, cchar *key, char *value, MaConfigState *state) { MaLocation *location; MaServer *server; MaHost *host; char *prefix, *path; int flags; host = state->host; server = state->server; location = state->location; flags = location->flags & (MA_LOC_BROWSER | MA_LOC_AUTO_SESSION); if (mprStrcmpAnyCase(key, "EjsApp") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_APP; } else { location->flags &= ~MA_LOC_APP; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppDir") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_APP_DIR; } else { location->flags &= ~MA_LOC_APP_DIR; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppAlias") == 0) { if (maSplitConfigValue(server, &prefix, &path, value, 1) < 0 || path == 0 || prefix == 0) { return MPR_ERR_BAD_SYNTAX; } location = maCreateLocationAlias(http, state, prefix, path, "ejsHandler", MA_LOC_APP | flags); if (location == 0) { return MPR_ERR_BAD_SYNTAX; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppDirAlias") == 0) { if (maSplitConfigValue(server, &prefix, &path, value, 1) < 0 || path == 0 || prefix == 0) { return MPR_ERR_BAD_SYNTAX; } location = maCreateLocationAlias(http, state, prefix, path, "ejsHandler", MA_LOC_APP_DIR | flags); if (location == 0) { return MPR_ERR_BAD_SYNTAX; } return 1; } else if (mprStrcmpAnyCase(key, "EjsErrors") == 0) { if (mprStrcmpAnyCase(value, "browser") == 0) { location->flags |= MA_LOC_BROWSER; } else { location->flags &= ~MA_LOC_BROWSER; } return 1; } else if (mprStrcmpAnyCase(key, "EjsSessionTimeout") == 0) { if (value == 0) { return MPR_ERR_BAD_SYNTAX; } if (! mprGetDebugMode(http)) { location->sessionTimeout = atoi(mprStrTrim(value, "\"")); } return 1; } else if (mprStrcmpAnyCase(key, "EjsSession") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_AUTO_SESSION; } else { location->flags &= ~MA_LOC_AUTO_SESSION; } return 1; } return 0; }