author | Alberto Bertogli
<albertito@blitiri.com.ar> 2023-07-29 21:49:50 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2023-07-30 12:21:07 UTC |
parent | ddd1b6d96ec942cc638ccae92be96c5fd6ef6f3a |
.gitignore | +3 | -0 |
cmd/chasquid-util/chasquid-util.go | +18 | -41 |
cmd/chasquid-util/test.sh | +9 | -18 |
cmd/chasquid-util/test_alias_resolve.cmy | +21 | -0 |
cmd/chasquid-util/test_domaininfo_remove.cmy | +19 | -0 |
cmd/dovecot-auth-cli/.gitignore | +0 | -3 |
docs/man/chasquid-util.1 | +4 | -4 |
docs/man/chasquid-util.1.pod | +2 | -2 |
test/t-04-aliases/chasquid-util.sh | +6 | -0 |
test/t-04-aliases/run.sh | +10 | -0 |
test/t-04-aliases/test_chasquid_util.cmy | +27 | -0 |
test/t-14-tls_tracking/run.sh | +14 | -0 |
test/util/lib.sh | +12 | -2 |
diff --git a/.gitignore b/.gitignore index ee09296..229362a 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,9 @@ test/util/minidns/minidns # Test binary, generated during coverage tests. chasquid.test +# chamuyero logs +*.cmy.log + # Exclude any .pem files, to prevent accidentally including test keys and # certificates. *.pem diff --git a/cmd/chasquid-util/chasquid-util.go b/cmd/chasquid-util/chasquid-util.go index 751bed5..75d9cce 100644 --- a/cmd/chasquid-util/chasquid-util.go +++ b/cmd/chasquid-util/chasquid-util.go @@ -9,9 +9,9 @@ package main import ( "bytes" "fmt" - "net/url" "os" "path/filepath" + "sort" "strconv" "strings" "syscall" @@ -19,6 +19,7 @@ import ( "blitiri.com.ar/go/chasquid/internal/aliases" "blitiri.com.ar/go/chasquid/internal/config" "blitiri.com.ar/go/chasquid/internal/envelope" + "blitiri.com.ar/go/chasquid/internal/localrpc" "blitiri.com.ar/go/chasquid/internal/normalize" "blitiri.com.ar/go/chasquid/internal/trace" "blitiri.com.ar/go/chasquid/internal/userdb" @@ -223,45 +224,26 @@ func aliasesResolve() { if err != nil { Fatalf("Error loading config: %v", err) } - _ = os.Chdir(configDir) - - r := aliases.NewResolver(allUsersExist) - r.SuffixSep = *conf.SuffixSeparators - r.DropChars = *conf.DropCharacters - domainDirs, err := os.ReadDir("domains/") + c := localrpc.NewClient(conf.DataDir + "/localrpc-v1") + vs, err := c.Call("AliasResolve", "Address", args["$2"]) if err != nil { - Fatalf("Error reading domains/ directory: %v", err) - } - if len(domainDirs) == 0 { - Fatalf("No domains found in config") + Fatalf("Error resolving: %v", err) } - for _, entry := range domainDirs { - name := entry.Name() - aliasfile := "domains/" + name + "/aliases" - r.AddDomain(name) - err := r.AddAliasesFile(name, aliasfile) - if err == nil { - fmt.Printf("%s: loaded %q\n", name, aliasfile) - } else if err != nil && os.IsNotExist(err) { - fmt.Printf("%s: no aliases file\n", name) - } else { - fmt.Printf("%s: error loading %q: %v\n", name, aliasfile, err) - } + // Result is a map of type -> []addresses. + // Sort the types for deterministic output. + ts := []string{} + for t := range vs { + ts = append(ts, t) } + sort.Strings(ts) - tr := trace.New("chasquid-util", "aliasesResolve") - defer tr.Finish() - - rcpts, err := r.Resolve(tr, args["$2"]) - if err != nil { - Fatalf("Error resolving: %v", err) - } - for _, rcpt := range rcpts { - fmt.Printf("%v %s\n", rcpt.Type, rcpt.Addr) + for _, t := range ts { + for _, a := range vs[t] { + fmt.Printf("%v %s\n", t, a) + } } - } // chasquid-util print-config @@ -276,20 +258,15 @@ func printConfig() { // chasquid-util domaininfo-remove <domain> func domaininfoRemove() { - domain := args["$2"] - conf, err := config.Load(configDir+"/chasquid.conf", "") if err != nil { Fatalf("Error loading config: %v", err) } - // File for the corresponding domain. - // Note this is making some assumptions about the data layout and - // protoio's storage structure, so it will need adjustment if they change. - file := conf.DataDir + "/domaininfo/s:" + url.QueryEscape(domain) - err = os.Remove(file) + c := localrpc.NewClient(conf.DataDir + "/localrpc-v1") + _, err = c.Call("DomaininfoClear", "Domain", args["$2"]) if err != nil { - Fatalf("Error removing file: %v", err) + Fatalf("Error removing domaininfo entry: %v", err) } } diff --git a/cmd/chasquid-util/test.sh b/cmd/chasquid-util/test.sh index d3c13e3..65cda22 100755 --- a/cmd/chasquid-util/test.sh +++ b/cmd/chasquid-util/test.sh @@ -71,24 +71,6 @@ if r authenticate user@domain --password=passwd > /dev/null; then exit 1 fi -touch '.data/domaininfo/s:dom%C3%A1in' -if ! r domaininfo-remove domáin; then - echo domaininfo-remove failed - exit 1 -fi -if [ -f '.data/domaininfo/s:dom%C3%A1in' ]; then - echo domaininfo-remove did not remove file - exit 1 -fi - -echo "alias: user@somewhere" > .config/domains/domain/aliases -A=$(r aliases-resolve alias@domain | grep somewhere) -if [ "$A" != "(email) user@somewhere" ]; then - echo aliases-resolve failed - echo output: "$A" - exit 1 -fi - C=$(r print-config | grep hostname) if ! ( echo "$C" | grep -E -q "hostname:.*\"$HOSTNAME\"" ); then echo print-config failed @@ -120,4 +102,13 @@ if r aliases-add alias4@domain > /dev/null; then exit 1 fi +# Run all the chamuyero tests. +for i in *.cmy; do + if ! chamuyero "$i" > "$i.log" 2>&1 ; then + echo "# Test $i failed, log follows" + cat "$i.log" + exit 1 + fi +done + success diff --git a/cmd/chasquid-util/test_alias_resolve.cmy b/cmd/chasquid-util/test_alias_resolve.cmy new file mode 100644 index 0000000..6d108f5 --- /dev/null +++ b/cmd/chasquid-util/test_alias_resolve.cmy @@ -0,0 +1,21 @@ +# Test success. +server unix_listen .data/localrpc-v1 +c = ./chasquid-util -C=.config aliases-resolve test@test.com + +server <- AliasResolve Address=test%40test.com +server -> 200 %28email%29=r1%40r1.com&%28pipe%29=cmd%20args + +c <- (email) r1@r1.com +c <- (pipe) cmd args +c wait 0 + + +# Test error. +server unix_listen .data/localrpc-v1 +c = ./chasquid-util -C=.config aliases-resolve test@test.com + +server <- AliasResolve Address=test%40test.com +server -> 500 This is a test error + +c <- Error resolving: This is a test error +c wait 1 diff --git a/cmd/chasquid-util/test_domaininfo_remove.cmy b/cmd/chasquid-util/test_domaininfo_remove.cmy new file mode 100644 index 0000000..c1ef077 --- /dev/null +++ b/cmd/chasquid-util/test_domaininfo_remove.cmy @@ -0,0 +1,19 @@ +# Test success. +server unix_listen .data/localrpc-v1 +c = ./chasquid-util -C=.config domaininfo-remove domain.com + +server <- DomaininfoClear Domain=domain.com +server -> 200 + +c wait 0 + + +# Test error. +server unix_listen .data/localrpc-v1 +c = ./chasquid-util -C=.config domaininfo-remove domain.com + +server <- DomaininfoClear Domain=domain.com +server -> 500 This is a test error + +c <- Error removing domaininfo entry: This is a test error +c wait 1 diff --git a/cmd/dovecot-auth-cli/.gitignore b/cmd/dovecot-auth-cli/.gitignore deleted file mode 100644 index d605cc4..0000000 --- a/cmd/dovecot-auth-cli/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.log -dovecot-auth-cli -dovecot-auth-cli.test diff --git a/docs/man/chasquid-util.1 b/docs/man/chasquid-util.1 index dd92586..9557874 100644 --- a/docs/man/chasquid-util.1 +++ b/docs/man/chasquid-util.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "chasquid-util 1" -.TH chasquid-util 1 "2018-05-20" "" "" +.TH chasquid-util 1 "2023-07-30" "" "" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -174,11 +174,11 @@ Check the user's password. Check the integrity of the domain's users database. .IP "\fBaliases-resolve\fR \fIaddr\fR" 8 .IX Item "aliases-resolve addr" -Resolve the given address. +Resolve the given address. Talks to the running chasquid instance. .IP "\fBdomaininfo-remove\fR \fIdomain\fR" 8 .IX Item "domaininfo-remove domain" Remove the domain information entry. This can be used to manually allow a -security level downgrade. +security level downgrade. Talks to the running chasquid instance. .IP "\fBprint-config\fR" 8 .IX Item "print-config" Parse and print the configuration in a human-readable way. diff --git a/docs/man/chasquid-util.1.pod b/docs/man/chasquid-util.1.pod index 2d90ac4..8976d1e 100644 --- a/docs/man/chasquid-util.1.pod +++ b/docs/man/chasquid-util.1.pod @@ -46,12 +46,12 @@ Check the integrity of the domain's users database. =item B<aliases-resolve> I<addr> -Resolve the given address. +Resolve the given address. Talks to the running chasquid instance. =item B<domaininfo-remove> I<domain> Remove the domain information entry. This can be used to manually allow a -security level downgrade. +security level downgrade. Talks to the running chasquid instance. =item B<print-config> diff --git a/test/t-04-aliases/chasquid-util.sh b/test/t-04-aliases/chasquid-util.sh new file mode 100755 index 0000000..576c67d --- /dev/null +++ b/test/t-04-aliases/chasquid-util.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Wrapper so chamuyero scripts can invoke chasquid-util for testing. + +# Run from the config directory because data_dir is relative. +cd config +go run ../../../cmd/chasquid-util/chasquid-util.go -C=. "$@" diff --git a/test/t-04-aliases/run.sh b/test/t-04-aliases/run.sh index dcfe5ba..c88711f 100755 --- a/test/t-04-aliases/run.sh +++ b/test/t-04-aliases/run.sh @@ -66,6 +66,16 @@ if run_msmtp nono@testserver < content 2> .logs/msmtp.out; then echo "expected delivery to nono@ to fail, but succeeded" fi +# Test chasquid-util's ability to do alias resolution talking to chasquid. +# We use chamuyero for convenience, so we can match the output exactly. +for i in *.cmy; do + if ! chamuyero "$i" > "$i.log" 2>&1 ; then + echo "$i failed, log follows" + cat "$i.log" + exit 1 + fi +done + # Remove the hooks, leave a clean state. rm -f config/hooks/alias-resolve diff --git a/test/t-04-aliases/test_chasquid_util.cmy b/test/t-04-aliases/test_chasquid_util.cmy new file mode 100644 index 0000000..204d001 --- /dev/null +++ b/test/t-04-aliases/test_chasquid_util.cmy @@ -0,0 +1,27 @@ +# Resolve an unknown user. +c = ./chasquid-util.sh aliases-resolve anunknownuser@blah +c <- (email) anunknownuser@blah +c wait 0 + +# Resolve a known alias. +c = ./chasquid-util.sh aliases-resolve a.ñi_l-blah@testserver +c <- (email) azul@testserver +c <- (email) índigo@testserver +c wait 0 + +# Resolve a pipe alias. +c = ./chasquid-util.sh aliases-resolve tubo@testserver +c <- (pipe) writemailto ../.data/pipe_alias_worked +c wait 0 + +# Resolve aliases that are exposed via the hook. +c = ./chasquid-util.sh aliases-resolve vicuña@testserver +c <- (email) jose@testserver +c <- (email) juan@testserver +c wait 0 + +# The hook for this alias exits with error. +c = ./chasquid-util.sh aliases-resolve roto@testserver +c <- Error resolving: exit status 1 +c wait 1 + diff --git a/test/t-14-tls_tracking/run.sh b/test/t-14-tls_tracking/run.sh index 1ecbe30..95af651 100755 --- a/test/t-14-tls_tracking/run.sh +++ b/test/t-14-tls_tracking/run.sh @@ -62,5 +62,19 @@ then fail "B is missing the domaininfo for srv-a" fi +# In A, remove domaininfo data about srv-B. +# Check that it was cleared successfully. +CONFDIR=A chasquid-util domaininfo-remove srv-b +if grep -q 'outgoing_sec_level:' ".data-A/domaininfo/s:srv-b"; +then + fail "Error clearing A's domaininfo about srv-b" +fi + +# While at it, check that a domaininfo-remove for an unknown domain results in +# an error. +if CONFDIR=A chasquid-util domaininfo-remove srv-X > .cdu-di-r-x.log 2>&1; then + fail "Expected error on chasquid-util domaininfo-remove srv-X" +fi + success diff --git a/test/util/lib.sh b/test/util/lib.sh index 008ea0e..5ed52bc 100644 --- a/test/util/lib.sh +++ b/test/util/lib.sh @@ -43,6 +43,17 @@ function chasquid() { "${TBASE}/../../chasquid" "$@" } +function chasquid-util() { + # Run chasquid-util from inside the config dir, since in our tests + # data_dir is relative to the config. + CONFDIR="${CONFDIR:-config}" + ( cd "$CONFDIR" && \ + go run "${TBASE}/../../cmd/chasquid-util/chasquid-util.go" \ + -C=. \ + "$@" \ + ) +} + # Add a user with chasquid-util. Because this is somewhat cryptographically # intensive, it can slow down the tests significantly, so most of the time we # use the simpler add_user (below) for testing purposes. @@ -50,8 +61,7 @@ function chasquid-util-user-add() { CONFDIR="${CONFDIR:-config}" DOMAIN=$(echo "$1" | cut -d @ -f 2) mkdir -p "${CONFDIR}/domains/$DOMAIN/" - go run "${TBASE}/../../cmd/chasquid-util/chasquid-util.go" \ - -C="${CONFDIR}" \ + chasquid-util \ user-add "$1" \ --password="$2" \ >> .add_user_logs