+static inline void open_auth_filter(struct cgit_context *ctx, const char *function)
+{
+ cgit_open_filter(ctx->cfg.auth_filter, function,
+ ctx->env.http_cookie ? ctx->env.http_cookie : "",
+ ctx->env.request_method ? ctx->env.request_method : "",
+ ctx->env.query_string ? ctx->env.query_string : "",
+ ctx->env.http_referer ? ctx->env.http_referer : "",
+ ctx->env.path_info ? ctx->env.path_info : "",
+ ctx->env.http_host ? ctx->env.http_host : "",
+ ctx->env.https ? ctx->env.https : "",
+ ctx->qry.repo ? ctx->qry.repo : "",
+ ctx->qry.page ? ctx->qry.page : "",
+ ctx->qry.url ? ctx->qry.url : "");
+}
+
+#define MAX_AUTHENTICATION_POST_BYTES 4096
+static inline void authenticate_post(struct cgit_context *ctx)
+{
+ if (ctx->env.http_referer && strlen(ctx->env.http_referer) > 0) {
+ html("Status: 302 Redirect\n");
+ html("Cache-Control: no-cache, no-store\n");
+ htmlf("Location: %s\n", ctx->env.http_referer);
+ } else {
+ html("Status: 501 Missing Referer\n");
+ html("Cache-Control: no-cache, no-store\n\n");
+ exit(0);
+ }
+
+ open_auth_filter(ctx, "authenticate-post");
+ char buffer[MAX_AUTHENTICATION_POST_BYTES];
+ int len;
+ len = ctx->env.content_length;
+ if (len > MAX_AUTHENTICATION_POST_BYTES)
+ len = MAX_AUTHENTICATION_POST_BYTES;
+ if (read(STDIN_FILENO, buffer, len) < 0)
+ die_errno("Could not read POST from stdin");
+ if (write(STDOUT_FILENO, buffer, len) < 0)
+ die_errno("Could not write POST to stdout");
+ /* The filter may now spit out a Set-Cookie: ... */
+ cgit_close_filter(ctx->cfg.auth_filter);
+
+ html("\n");
+ exit(0);
+}
+
+static inline void authenticate_cookie(struct cgit_context *ctx)
+{
+ /* If we don't have an auth_filter, consider all cookies valid, and thus return early. */
+ if (!ctx->cfg.auth_filter) {
+ ctx->env.authenticated = 1;
+ return;
+ }
+
+ /* If we're having something POST'd to /login, we're authenticating POST,
+ * instead of the cookie, so call authenticate_post and bail out early.
+ * This pattern here should match /?p=login with POST. */
+ if (ctx->env.request_method && ctx->qry.page && !ctx->repo && \
+ !strcmp(ctx->env.request_method, "POST") && !strcmp(ctx->qry.page, "login")) {
+ authenticate_post(ctx);
+ return;
+ }
+
+ /* If we've made it this far, we're authenticating the cookie for real, so do that. */
+ open_auth_filter(ctx, "authenticate-cookie");
+ ctx->env.authenticated = cgit_close_filter(ctx->cfg.auth_filter);
+}
+