/* allocates and initializes an error response */ HttpReply * errorBuildReply(ErrorState * err) { HttpReply *rep = httpReplyCreate(); const char *name = errorPageName(err->page_id); /* no LMT for error pages; error pages expire immediately */ if (strchr(name, ':')) { /* Redirection */ httpReplySetHeaders(rep, HTTP_MOVED_TEMPORARILY, NULL, "text/html", 0, -1, -1); if (err->request) { char *quoted_url = rfc1738_escape_part(urlCanonical(err->request)); httpHeaderPutStrf(&rep->header, HDR_LOCATION, name, quoted_url); } httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%d %s", err->http_status, "Access Denied"); } else { MemBuf content = errorBuildContent(err); httpReplySetHeaders(rep, err->http_status, NULL, "text/html", content.size, -1, -1); /* * include some information for downstream caches. Implicit * replaceable content. This isn't quite sufficient. xerrno is not * necessarily meaningful to another system, so we really should * expand it. Additionally, we should identify ourselves. Someone * might want to know. Someone _will_ want to know OTOH, the first * X-CACHE-MISS entry should tell us who. */ httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%s %d", name, err->xerrno); httpBodySet(&rep->body, &content); /* do not memBufClean() the content, it was absorbed by httpBody */ } return rep; }
/* * Send the authenticate error header(s). Note: IE has a bug and the Negotiate header * must be first. To ensure that, the configure use --enable-auth=negotiate, anything * else. */ static void authenticateNegotiateFixErrorHeader(auth_user_request_t * auth_user_request, HttpReply * rep, http_hdr_type type, request_t * request) { negotiate_request_t *negotiate_request; if (!negotiateConfig->authenticate) return; if (!request->flags.proxy_keepalive && request->flags.must_keepalive) return; /* New request, no user details */ if (auth_user_request == NULL) { debug(29, 9) ("authenticateNegotiateFixErrorHeader: Sending type:%d header: 'Negotiate'\n", type); httpHeaderPutStrf(&rep->header, type, "Negotiate"); if (!negotiateConfig->keep_alive) { /* drop the connection */ httpHeaderDelByName(&rep->header, "keep-alive"); request->flags.proxy_keepalive = 0; } return; } negotiate_request = auth_user_request->scheme_data; switch (negotiate_request->auth_state) { case AUTHENTICATE_STATE_NONE: case AUTHENTICATE_STATE_FAILED: debug(29, 9) ("authenticateNegotiateFixErrorHeader: Sending type:%d header: 'Negotiate'\n", type); httpHeaderPutStrf(&rep->header, type, "Negotiate"); /* drop the connection */ httpHeaderDelByName(&rep->header, "keep-alive"); request->flags.proxy_keepalive = 0; break; case AUTHENTICATE_STATE_NEGOTIATE: /* we are 'waiting' for a response from the client */ /* pass the blob to the client */ debug(29, 9) ("authenticateNegotiateFixErrorHeader: Sending type:%d header: 'Negotiate %s'\n", type, negotiate_request->server_blob); httpHeaderPutStrf(&rep->header, type, "Negotiate %s", negotiate_request->server_blob); safe_free(negotiate_request->server_blob); break; case AUTHENTICATE_STATE_DONE: /* Special case when authentication finished, but not allowed by ACL */ if (negotiate_request->server_blob) { debug(29, 9) ("authenticateNegotiateFixErrorHeader: Sending type:%d header: 'Negotiate %s'\n", type, negotiate_request->server_blob); httpHeaderPutStrf(&rep->header, type, "Negotiate %s", negotiate_request->server_blob); safe_free(negotiate_request->server_blob); } else { debug(29, 9) ("authenticateNegotiateFixErrorHeader: Connection authenticated\n"); httpHeaderPutStrf(&rep->header, type, "Negotiate"); } break; default: debug(29, 0) ("authenticateNegotiateFixErrorHeader: state %d.\n", negotiate_request->auth_state); fatal("unexpected state in AuthenticateNegotiateFixErrorHeader.\n"); } }
/* add the [proxy]authorisation header */ static void authDigestAddHeader(auth_user_request_t * auth_user_request, HttpReply * rep, int accel) { int type; digest_request_h *digest_request; if (!auth_user_request) return; digest_request = auth_user_request->scheme_data; if (!digest_request) return; /* don't add to authentication error pages */ if ((!accel && rep->sline.status == HTTP_PROXY_AUTHENTICATION_REQUIRED) || (accel && rep->sline.status == HTTP_UNAUTHORIZED)) return; type = accel ? HDR_AUTHENTICATION_INFO : HDR_PROXY_AUTHENTICATION_INFO; #if WAITING_FOR_TE /* test for http/1.1 transfer chunked encoding */ if (chunkedtest) return; #endif if ((digestConfig->authenticate) && authDigestNonceLastRequest(digest_request->nonce)) { digest_request->flags.authinfo_sent = 1; debug(29, 9) ("authDigestAddHead: Sending type:%d header: 'nextnonce=\"%s\"", type, authenticateDigestNonceNonceb64(digest_request->nonce)); httpHeaderPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(digest_request->nonce)); } }
void authenticateBasicFixErrorHeader(auth_user_request_t * auth_user_request, HttpReply * rep, http_hdr_type type, request_t * request) { if (basicConfig->authenticate) { debug(29, 9) ("authenticateFixErrorHeader: Sending type:%d header: 'Basic realm=\"%s\"'\n", type, basicConfig->basicAuthRealm); httpHeaderPutStrf(&rep->header, type, "Basic realm=\"%s\"", basicConfig->basicAuthRealm); } }
/* add the [www-|Proxy-]authenticate header on a 407 or 401 reply */ void authenticateDigestFixHeader(auth_user_request_t * auth_user_request, HttpReply * rep, http_hdr_type type, request_t * request) { digest_request_h *digest_request; int stale = 0; digest_nonce_h *nonce = authenticateDigestNonceNew(); if (auth_user_request && auth_user_request->scheme_data) { digest_request = auth_user_request->scheme_data; stale = digest_request->flags.nonce_stale; } if (digestConfig->authenticate) { debug(29, 9) ("authenticateFixHeader: Sending type:%d header: 'Digest realm=\"%s\", nonce=\"%s\", qop=\"%s\", stale=%s\n", type, digestConfig->digestAuthRealm, authenticateDigestNonceNonceb64(nonce), QOP_AUTH, stale ? "true" : "false"); /* in the future, for WWW auth we may want to support the domain entry */ httpHeaderPutStrf(&rep->header, type, "Digest realm=\"%s\", nonce=\"%s\", qop=\"%s\", stale=%s", digestConfig->digestAuthRealm, authenticateDigestNonceNonceb64(nonce), QOP_AUTH, stale ? "true" : "false"); } }
/* add the [proxy]authorisation header */ static void authNegotiateAddHeader(auth_user_request_t * auth_user_request, HttpReply * rep, int accel) { int type; negotiate_request_t *negotiate_request; if (!auth_user_request) return; negotiate_request = auth_user_request->scheme_data; if (!negotiate_request->server_blob) return; type = accel ? HDR_WWW_AUTHENTICATE : HDR_PROXY_AUTHENTICATE; debug(29, 9) ("authenticateNegotiateAddHeader: Sending type:%d header: 'Negotiate %s'\n", type, negotiate_request->server_blob); httpHeaderPutStrf(&rep->header, type, "Negotiate %s", negotiate_request->server_blob); safe_free(negotiate_request->server_blob); }
void httpHeaderPutAuth(HttpHeader * hdr, const char *auth_scheme, const char *realm) { assert(hdr && auth_scheme && realm); httpHeaderPutStrf(hdr, HDR_WWW_AUTHENTICATE, "%s realm=\"%s\"", auth_scheme, realm); }