From 1a3ec70d3f0b7d62e570f3b85aa7e0e034a2cc7b Mon Sep 17 00:00:00 2001 From: tjpcc Date: Tue, 31 Oct 2023 11:11:53 -0600 Subject: [PATCH] move 'auth' to a modifier fixes #12 --- README.gmi | 6 ++++++ README.md | 6 ++++++ example.conf | 4 ++-- gemini.go | 6 +++--- parse.go | 60 ++++++++++++++++++++++++++++++---------------------- types.go | 5 ++--- 6 files changed, 54 insertions(+), 33 deletions(-) diff --git a/README.gmi b/README.gmi index 2a2de46..18d9e63 100644 --- a/README.gmi +++ b/README.gmi @@ -312,6 +312,12 @@ The "autoatom" modifier customizes routing to recognize ". Allowed contexts: static, cgi directives (no git), gemini and spartan servers (no gopher or finger). +### auth + +The "auth" modifier takes the name of an auth (defined in a global "auth" directive) and sets it as a requirement to access the modified route. All the supported auth mechanisms are based on client TLS certificates, so they only work in servers with a "servertls" directive. + +Allowed contexts: static, cgi, git directives, gemini, gopher, and finger servers (no spartan, and gopher or finger only with "servertls"). + ### titan The "titan" modifier takes an auth name (defined in a global "auth" directive) and enables the titan file upload protocol in a static route. Titan requests specifically will have to pass the named auth mechanism. diff --git a/README.md b/README.md index 0c00004..f65ae78 100644 --- a/README.md +++ b/README.md @@ -318,6 +318,12 @@ The "autoatom" modifier customizes routing to recognize ". Allowed contexts: static, cgi directives (no git), gemini and spartan servers (no gopher or finger). +### auth + +The "auth" modifier takes the name of an auth (defined in a global "auth" directive) and sets it as a requirement to access the modified route. All the supported auth mechanisms are based on client TLS certificates, so they only work in servers with a "servertls" directive. + +Allowed contexts: static, cgi, git directives, gemini, gopher, and finger servers (no spartan, and gopher or finger only with "servertls"). + ### titan The "titan" modifier takes an auth name (defined in a global "auth" directive) and enables the titan file upload protocol in a static route. Titan requests specifically will have to pass the named auth mechanism. diff --git a/example.conf b/example.conf index 66b39fb..070805e 100644 --- a/example.conf +++ b/example.conf @@ -105,8 +105,8 @@ gemini 0.0.0.0:1965 { static ~/public_gemini at /~ with dirdefault index.gmi, dirlist, exec, autoatom, titan private_gemini cgi ~/public_gemini/cgi-bin at /~/cgi-bin - # "static", "cgi", and "git" directives support an "auth " clause which requires an authentication to pass. - cgi ~/public_gemini/cgi-bin/private at /~/cgi-bin/private auth private_gemini + # "static", "cgi", and "git" directives support an "auth " modifier which requires an authentication to pass. + cgi ~/public_gemini/cgi-bin/private at /~/cgi-bin/private with auth private_gemini # The "templates" modifier can be used on "git" directives and provide a directory with template files in it. # These can be used to customize the presentation of git repositories. diff --git a/gemini.go b/gemini.go index cbf3e79..fc99e5e 100644 --- a/gemini.go +++ b/gemini.go @@ -99,7 +99,7 @@ func addGeminiRoute(router *sr.Router, route RouteDirective) { if route.Modifiers.AutoAtom { handler = atomconv.Auto(handler) } - return GeminiAuthMiddleware(route.Auth)(handler) + return GeminiAuthMiddleware(route.Modifiers.Auth)(handler) }) case "git": addGeminiGitRoute(router, route) @@ -133,7 +133,7 @@ func addGeminiStaticRoute(router *sr.Router, route RouteDirective) { handler = atomconv.Auto(handler) } - handler = GeminiAuthMiddleware(route.Auth)(handler) + handler = GeminiAuthMiddleware(route.Modifiers.Auth)(handler) if route.Modifiers.Titan != nil { titan := fs.TitanUpload(route.FsPath, route.URLPath, route.Modifiers.Titan.Strategy.Approve)(handler) @@ -163,6 +163,6 @@ func addGeminiGitRoute(router *sr.Router, route RouteDirective) { if route.Modifiers.AutoAtom { handler = atomconv.Auto(handler) } - return GeminiAuthMiddleware(route.Auth)(handler) + return GeminiAuthMiddleware(route.Modifiers.Auth)(handler) }) } diff --git a/parse.go b/parse.go index c93e33e..f97cf83 100644 --- a/parse.go +++ b/parse.go @@ -120,12 +120,12 @@ func Parse(input io.ReadCloser) (*Configuration, error) { for i := range servers { for j := range servers[i].Routes { - if name := servers[i].Routes[j].authName; name != "" { + if name := servers[i].Routes[j].Modifiers.authName; name != "" { auth, ok := auths[name] if !ok { return nil, fmt.Errorf("auth '%s' not found", name) } - servers[i].Routes[j].Auth = auth + servers[i].Routes[j].Modifiers.Auth = auth } if name := servers[i].Routes[j].Modifiers.titanName; name != "" { @@ -312,7 +312,7 @@ func validateRoute(serverType string, dir *RouteDirective) error { if serverType == "finger" && dir.Type != "static" && dir.Type != "cgi" { return fmt.Errorf("finger servers don't support '%s' directives", dir.Type) } - if serverType == "finger" && dir.authName != "" { + if serverType == "finger" && dir.Modifiers.authName != "" { return errors.New("finger servers don't support 'auth' clauses") } if serverType != "finger" && dir.URLPath == "" { @@ -381,33 +381,28 @@ func parseRouteDirective(line string) (RouteDirective, error) { return dir, nil } - word, rest, found := strings.Cut(rest, " ") - if found && word == "at" { - var urlpath string - urlpath, rest, _ = strings.Cut(rest, " ") - dir.URLPath = urlpath - } else if found { - rest = word + " " + rest - } - - for rest != "" { + var word string + for { word, rest, found = strings.Cut(rest, " ") if !found { + return dir, nil + } + + switch word { + case "at": + var urlpath string + urlpath, rest, _ = strings.Cut(rest, " ") + dir.URLPath = urlpath + case "with": + var err error + dir.Modifiers, rest, err = parseModifiers(rest) + if err != nil { + return dir, err + } + default: return dir, fmt.Errorf("invalid '%s' directive", tag) } - - var err error - if word == "with" { - dir.Modifiers, rest, err = parseModifiers(rest) - } else if word == "auth" { - dir.authName, rest, err = parseAuth(rest) - } - if err != nil { - return dir, err - } } - - return dir, nil } func parseModifiers(text string) (Modifiers, string, error) { @@ -471,6 +466,21 @@ func parseModifiers(text string) (Modifiers, string, error) { mod.ExtendedGophermap = true case "autoatom": mod.AutoAtom = true + case "auth": + if sep != " " { + return mod, "", errors.New("invalid 'auth' clause") + } + text = strings.TrimLeft(text, " \t") + idx = strings.IndexAny(text, " \t,") + if idx == 0 { + return mod, "", errors.New("invalid 'auth' clause") + } else if idx < 0 { + mod.authName = text + text = "" + } else { + mod.authName = text[0:idx] + text = text[idx+1:] + } case "titan": if sep != " " { return mod, "", errors.New("invalid 'titan' clause") diff --git a/types.go b/types.go index af7f30f..76f89ac 100644 --- a/types.go +++ b/types.go @@ -18,9 +18,11 @@ type Modifiers struct { ExecCmd string ExtendedGophermap bool AutoAtom bool + Auth *Auth Titan *Auth Templates *template.Template + authName string titanName string } @@ -46,9 +48,6 @@ type RouteDirective struct { // "with ..." Modifiers Modifiers - - Auth *Auth - authName string } type Server struct {