| 432 | } |
| 433 | |
| 434 | func (s *Server) PassChallenge(w http.ResponseWriter, r *http.Request) { |
| 435 | lg := internal.GetRequestLogger(s.logger, r) |
| 436 | localizer := localization.GetLocalizer(r) |
| 437 | |
| 438 | redir := r.FormValue("redir") |
| 439 | redirURL, err := url.ParseRequestURI(redir) |
| 440 | if err != nil { |
| 441 | lg.Error("invalid redirect", "err", err) |
| 442 | s.respondWithStatus(w, r, localizer.T("invalid_redirect"), makeCode(err), http.StatusBadRequest) |
| 443 | return |
| 444 | } |
| 445 | |
| 446 | switch redirURL.Scheme { |
| 447 | case "", "http", "https": |
| 448 | // allowed |
| 449 | default: |
| 450 | lg.Error("XSS attempt blocked, invalid redirect scheme", "scheme", redirURL.Scheme) |
| 451 | s.respondWithStatus(w, r, localizer.T("invalid_redirect"), "", http.StatusBadRequest) |
| 452 | return |
| 453 | } |
| 454 | |
| 455 | // Adjust cookie path if base prefix is not empty |
| 456 | cookiePath := "/" |
| 457 | if anubis.BasePrefix != "" { |
| 458 | cookiePath = strings.TrimSuffix(anubis.BasePrefix, "/") + "/" |
| 459 | } |
| 460 | |
| 461 | if _, err := r.Cookie(anubis.TestCookieName); errors.Is(err, http.ErrNoCookie) { |
| 462 | s.ClearCookie(w, CookieOpts{Path: cookiePath, Host: r.Host}) |
| 463 | s.ClearCookie(w, CookieOpts{Name: anubis.TestCookieName, Host: r.Host}) |
| 464 | lg.Warn("user has cookies disabled, this is not an anubis bug") |
| 465 | s.respondWithError(w, r, localizer.T("cookies_disabled"), "") |
| 466 | return |
| 467 | } |
| 468 | |
| 469 | // used by the path checker rule |
| 470 | r.URL = redirURL |
| 471 | |
| 472 | urlParsed, err := r.URL.Parse(redir) |
| 473 | if err != nil { |
| 474 | s.respondWithError(w, r, localizer.T("redirect_not_parseable"), makeCode(err)) |
| 475 | return |
| 476 | } |
| 477 | if (len(urlParsed.Host) > 0 && len(s.opts.RedirectDomains) != 0 && !matchRedirectDomain(s.opts.RedirectDomains, urlParsed.Host)) || urlParsed.Host != r.URL.Host { |
| 478 | lg.Debug("domain not allowed", "domain", urlParsed.Host) |
| 479 | s.respondWithError(w, r, localizer.T("redirect_domain_not_allowed"), "") |
| 480 | return |
| 481 | } |
| 482 | |
| 483 | cr, rule, err := s.check(r, lg) |
| 484 | if err != nil { |
| 485 | lg.Error("check failed", "err", err) |
| 486 | s.respondWithError(w, r, fmt.Sprintf("%s \"passChallenge\"", localizer.T("internal_server_error")), makeCode(err)) |
| 487 | return |
| 488 | } |
| 489 | lg = lg.With("check_result", cr) |
| 490 | |
| 491 | chall, err := s.getChallenge(r) |