From: Sergey Matveev Date: Sat, 30 Oct 2021 13:03:55 +0000 (+0300) Subject: Various refactoring X-Git-Tag: v0.1.0~52 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;ds=sidebyside;h=aca0f719ffa95e51420a625813f2f4cbf1d5397c;p=tofuproxy.git Various refactoring --- diff --git a/README b/README index e767a42..07ac7e1 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates -manager, WARC/Gemini browser. +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU +manager, WARC/geminispace browser. Home page: http://www.tofuproxy.stargrave.org/ diff --git a/all.do b/all.do index db8bcbf..c4a5702 100644 --- a/all.do +++ b/all.do @@ -1,2 +1,2 @@ -redo-ifchange cert.pem tofuproxy.cmd fifos/ensure +redo-ifchange cert.pem tofuproxy.cmd fifos/ensure cmd/unzstd/unzstd mkdir -p certs ccerts diff --git a/cmd/.gitignore b/cmd/.gitignore new file mode 100644 index 0000000..895dab3 --- /dev/null +++ b/cmd/.gitignore @@ -0,0 +1 @@ +compile_flags.txt diff --git a/cmd/certgen/main.go b/cmd/certgen/main.go index 93b5e7f..d8f86e1 100644 --- a/cmd/certgen/main.go +++ b/cmd/certgen/main.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/cmd/enzstd/.gitignore b/cmd/enzstd/.gitignore index aaa4938..6fcec77 100644 --- a/cmd/enzstd/.gitignore +++ b/cmd/enzstd/.gitignore @@ -1,2 +1 @@ -/compile_flags.txt /enzstd diff --git a/cmd/enzstd/compile_flags.txt.do b/cmd/enzstd/compile_flags.txt.do deleted file mode 100644 index 13b13f1..0000000 --- a/cmd/enzstd/compile_flags.txt.do +++ /dev/null @@ -1 +0,0 @@ -printf "%s" "$CFLAGS $LDFLAGS" | tr " " "\n" | grep -v "^$" | sort | uniq diff --git a/cmd/enzstd/compile_flags.txt.do b/cmd/enzstd/compile_flags.txt.do new file mode 120000 index 0000000..0f4f6ff --- /dev/null +++ b/cmd/enzstd/compile_flags.txt.do @@ -0,0 +1 @@ +../unzstd/compile_flags.txt.do \ No newline at end of file diff --git a/cmd/enzstd/enzstd.c b/cmd/enzstd/enzstd.c index ee5e35a..b91ecb2 100644 --- a/cmd/enzstd/enzstd.c +++ b/cmd/enzstd/enzstd.c @@ -1,6 +1,5 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +enzstd -- .warc.zst compressor Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify @@ -74,7 +73,6 @@ main(int argc, char **argv) }; n = fread(src, 1, srcWantSize, stdin); if (n < srcWantSize) { - fprintf(stderr, "IS: %zu %zu\n", n, srcWantSize); fputs("insufficient data fed\n", stderr); return EXIT_FAILURE; }; diff --git a/cmd/tofuproxy/main.go b/cmd/tofuproxy/main.go index 941438d..b3f2a14 100644 --- a/cmd/tofuproxy/main.go +++ b/cmd/tofuproxy/main.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/cmd/ungzip/main.go b/cmd/ungzip/main.go index 64ec0f7..d382e36 100644 --- a/cmd/ungzip/main.go +++ b/cmd/ungzip/main.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/cmd/unzstd/.gitignore b/cmd/unzstd/.gitignore index d34d410..f2358dc 100644 --- a/cmd/unzstd/.gitignore +++ b/cmd/unzstd/.gitignore @@ -1,2 +1 @@ -/compile_flags.txt /unzstd diff --git a/cmd/unzstd/unzstd.c b/cmd/unzstd/unzstd.c index 4815251..ada11ea 100644 --- a/cmd/unzstd/unzstd.c +++ b/cmd/unzstd/unzstd.c @@ -1,6 +1,5 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +unzstd -- .warc.zst decompressor Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/cmd/warc-extract/main.go b/cmd/warc-extract/main.go index 85bc273..0dd56fd 100644 --- a/cmd/warc-extract/main.go +++ b/cmd/warc-extract/main.go @@ -1,6 +1,5 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +warc-extract -- WARC files data extractor Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/conn.go b/conn.go index d2a05a2..00c1721 100644 --- a/conn.go +++ b/conn.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/default.cmd.do b/default.cmd.do index 9473531..c2ee005 100644 --- a/default.cmd.do +++ b/default.cmd.do @@ -1,3 +1,10 @@ -redo-ifchange *.go cmd/*/*.go fifos/*.go rounds/*.go warc/*.go +redo-ifchange \ + *.go \ + caches/*.go \ + cmd/$2/*.go \ + fifos/*.go \ + rounds/*.go \ + tls/*.go \ + warc/*.go GO_LDFLAGS="${GO_LDFLAGS:--ldflags=-s}" ${GO:-go} build -o $3 $GO_LDFLAGS ./cmd/${1%.cmd} diff --git a/doc/certs.texi b/doc/certs.texi index b109dc8..9d66fa1 100644 --- a/doc/certs.texi +++ b/doc/certs.texi @@ -1,5 +1,5 @@ @node CertTrust -@section Certificate trust management +@unnumbered Certificate trust management When you encounter something requiring your attention and decision, you will be see Tk-dialog through the @command{wish} invocation. GnuTLS'es diff --git a/doc/gemini.texi b/doc/gemini.texi index 73acece..db44e60 100644 --- a/doc/gemini.texi +++ b/doc/gemini.texi @@ -1,14 +1,21 @@ @node Gemini -@section Geminispace +@unnumbered Geminispace You can browse @url{https://en.wikipedia.org/wiki/Gemini_(protocol), geminispace} by going to @url{https://gemini/HOST/PATH}, where @var{HOST} and @var{PATH} are taken from ordinary gemini URL. For example to browse @url{gemini://gemini.circumlunar.space/docs/}, you must go through @command{tofuproxy} to @url{https://gemini/gemini.circumlunar.space/docs/}. +Or you can go to @url{https://gemini/gemini://gemini.circumlunar.space/docs/} +and will be redirected to necessary URL. If you request @url{https://gemini/} URL with @code{Accept: text/gemini} HTTP header, then gemfiles (@file{.gmi} will be passed as-is without conversion to HTML. +@example +$ curl --proxy http://localhost:8080/ --header "Accept: text/gemini" \ + https://gemini/gemini.circumlunar.space/docs/ +@end example + No @code{INPUT} is supported currently. diff --git a/doc/httpauth.texi b/doc/httpauth.texi new file mode 100644 index 0000000..eb98721 --- /dev/null +++ b/doc/httpauth.texi @@ -0,0 +1,7 @@ +@node HTTPAuth +@unnumbered HTTP-based authentication + +HTTP authorization request is intercepted by @command{tofuproxy} and +dialogue window is shown. @file{~/.netrc} file is automatically read and +used for form inputs prefilling. You can override its path by +@env{$NETRC} environment variable. diff --git a/doc/index.texi b/doc/index.texi index 7d552be..84b29ba 100644 --- a/doc/index.texi +++ b/doc/index.texi @@ -9,137 +9,98 @@ Copyright @copyright{} 2021 @email{stargrave@@stargrave.org, Sergey Matveev} @node Top @top tofuproxy -@itemize - -@item I am tired that various HTTPS clients (like browsers and feed -aggregators) use various TLS libraries with different features. NSS, -GnuTLS, OpenSSL... All of them sucks, comparing to Go's @code{crypto/tls}. - -@item I tired that everyone provides very limited certificates trust -management capabilities, like either certificate or SPKI -@url{https://en.wikipedia.org/wiki/Certificate_pinning, pinning} with -@url{https://en.wikipedia.org/wiki/Trust_on_first_use, TOFU}. Even my -beloved @url{https://en.wikipedia.org/wiki/Xombrero, Xombrero} browser -still pins only the whole certificate, but its public key would be much -more sufficient and convenient to work with. - -@item I am tired that many clients provides very few information about -certificates and connections at all. - -@item I hate that hardly anyone can control (no automatic silent -transparent following) HTTP redirections. Although Firefox had proper -extensions for that. - -@item I am sick of tiny control on URLs. The best you can is to use some -kind of @url{https://en.wikipedia.org/wiki/Privoxy, Privoxy}, but it is -not friendly with TLS connections, obviously. - -@item Xombrero sometimes has problems with HTTP-based authorization. - -@item Hardly anyone does -@url{https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities, DANE} -checks. - -@item And there is insanity of downloading fonts. -Why the hell people just do not send PostScript documents instead!? - -@item And wonderful @url{http://jpegxl.info/, JPEG XL} image format is -not supported by most browsers. Even pretty old -@url{https://developers.google.com/speed/webp, WebP}, that has highest -compression ratio for lossless screenshots, is not supported everywhere. -@url{https://aomediacodec.github.io/av1-avif/, AVIF} could be useful too. - -@item None of web browsers support ability to view web archives -(@url{https://en.wikipedia.org/wiki/Web_ARChive, WARC}s). And most of -WARC-related software is written on Python, that nowadays is close to be -impossible to install and use with all its broken dependencies system. - -@item And yet another piece of software is needed for browsing the -@url{https://en.wikipedia.org/wiki/Gemini_(protocol), geminispace}? -Too many bicycles already! - -@end itemize - -That is why I wrote @command{tofuproxy} -- pure Go HTTP proxy, MitMing -all HTTPS connections on the fly. It is written for my personal needs -exclusively, so many features are just directly hard-coded, instead of -creating some kind of complex configuration framework. +@command{tofuproxy} is +@url{https://www.gnu.org/philosophy/free-sw.html, free software} +flexible HTTP/HTTPS proxy server, TLS terminator, X.509 TOFU manager, +@url{https://en.wikipedia.org/wiki/Web_ARChive, WARC} and +@url{https://en.wikipedia.org/wiki/Gemini_(protocol), geminispace} +browser, written on @url{https://golang.org/, Go} with following +capabilities: @itemize @item -@strong{Effective} responses proxying, without storing them in the memory first. +Full TLS connection termination between Web-servers and +@command{tofuproxy} itself. TLS 1.3, session resumption, GOST +cryptography (if built with @url{http://www.gostls13.cypherpunks.ru/, +gostls13}) support. Connection between @command{tofuproxy} and browser +itself uses ephemeral on-the-fly generated certificates with proper +domain name. @item -TLS connection between client and @command{tofuproxy} has the -@strong{proper hostname} set in ephemeral on-the-fly generated -certificate. +@url{https://http2.github.io/, HTTP/2} (if negotiated with ALPN) and +HTTP keep-alives are supported. @item -@code{HEAD} method is forbidden. +Default Go's @code{crypto/x509} checks are applied to all certificates. +If they pass, then certificate chain is saved on the disk (TOFU, +trust-on-first-use). Future connections are compared against it, warning +you about SPKI change (SPKI pinning) and waiting for your decision +either to accept new chain (possibly once per session), or reject it. +Even if native Go's checks are failed (for example domain still does not +use @code{SubjectAltName} extension), you can still make a decision to +forcefully trust the domain. @item -@code{www.reddit.com} is redirected to @code{old.reddit.com}. +Optional @url{https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities, DANE-EE} check. @item -@url{https://habr.com/ru/all/, Хабр}'s resolution reduced images are -redirected to their full size variants. +TLS client certificates are supported too. @item -Various @strong{spying} domains (advertisement, tracking counters) are denied. +HTTP-based authorization requests are intercepted and user/password +input dialogue is shown. It automatically loads initial form values from +@file{.netrc}. @item -Web @strong{fonts} downloads are forbidden. +Permanent HTTP redirects are replaces with non-refreshing HTML page with +the link, to make you explicitly allow that step. Temporary redirects +are followed if it is neither @url{https://newsboat.org/, Newsboat} +user-agent, not image paths. @item -@strong{Permanent} HTTP redirects are replaced with HTML page with the link. +JPEG XL, AVIF and WebP images are transparently transcoded to PNG, +giving it back to the browser, not requiring it to support modern +effective image formats. @item -@strong{Temporary} HTTP redirects are replaced with HTML too, if it is -neither @url{https://newsboat.org/, Newsboat} nor image paths. +Ability to load, index and browse WARC web archives, that are possibly +multi-segment/frame compressed with @command{gzip}/@command{zstd}. @item -@strong{WebP} images (if it is not Xombrero), @strong{JPEG XL} and -@strong{AVIF} are transcoded to PNG. +Ability to browse geminispace, transparently converting gemfiles to +HTMLs with URL rewriting. -@item -Default Go's checks are applied to all certificates. If they pass, then -certificate chain is saved on the disk (@strong{TOFU}). Future -connections are compared against it, warning you about SPKI change -(@strong{SPKI pinning}) and waiting for your decision either to accept -new chain (possibly once per session), or reject it. - -@item -Even when native Go's checks are failed, you can still make a decision -to forcefully trust the domain. +@end itemize -@item -@strong{HTTP-based authorization} requests are intercepted and -user/password input dialogue is shown. It automatically loads -@strong{initial form} values from @strong{@file{.netrc}}. +And additional personal preferences: -@item -TLS @strong{client certificates} supported: separate dialogue window for -certificate choice. +@itemize @item -Optional @strong{DANE-EE} check is also made for each domain you visit. +Various spying domains (advertisement, tracking counters) are denied. @item -TLS @strong{session resumption} and @strong{keep-alives} are also supported. +@code{HEAD} method is forbidden. Xombrero likes it too much. @item -And Go itself tries also to act as a @url{https://http2.github.io/, HTTP/2} -client too. +@code{www.reddit.com} is redirected to @code{old.reddit.com} (because it +works without JavaScript and looks nicer). @item -Ability to load and browse @url{https://en.wikipedia.org/wiki/Web_ARChive, -WARC} archives, possibly @command{gzip}/@command{zstd} compressed. +@url{https://habr.com/ru/all/, Хабр}'s resolution reduced images are +redirected to their full size variants. @item -Ability to browse geminispace, by transparent conversion to HTMLs with -URL rewriting. +Web @strong{fonts} downloads are forbidden. @end itemize +@include why.texi @include usage.texi +@include spies.texi +@include certs.texi +@include tlsauth.texi +@include httpauth.texi +@include warcs.texi +@include gemini.texi diff --git a/doc/spies.texi b/doc/spies.texi index afbb16a..6760132 100644 --- a/doc/spies.texi +++ b/doc/spies.texi @@ -1,5 +1,5 @@ @node Spies -@section Spies +@unnumbered Spies You can reject requests to the whole domains. As a rule some spying ones (for advertisements and better user experience, they say). diff --git a/doc/tlsauth.texi b/doc/tlsauth.texi new file mode 100644 index 0000000..31ea224 --- /dev/null +++ b/doc/tlsauth.texi @@ -0,0 +1,28 @@ +@node TLSAuth +@unnumbered TLS client authentication + +If you want to use TLS client certificates, then place them to +@file{-ccerts} directory. If server requests for the certificate, then +dialogue window will be shown with the subjects of known client +certificates. You can close that window to omit certificate sending +once. @code{NONE} (@code{n} hotkey) will remember that decision for long. + +To list currently saved host and certificate associations: + +@example +$ cat fifos/list-tls-auth +example.com CN=client.example.com +gemini.example.com NONE +@end example + +To delete one of them: + +@example +$ echo example.com > fifos/del-tls-auth +@end example + +To preadd: + +@example +$ echo example.com path/to/client.cert.pem > fifos/add-tls-auth +@end example diff --git a/doc/usage.texi b/doc/usage.texi index 6ff4cd3..828fe34 100644 --- a/doc/usage.texi +++ b/doc/usage.texi @@ -32,7 +32,7 @@ $ SSL_CERT_FILE=`pwd`/cert.pem GIT_SSL_CAINFO=`pwd`/cert.pem redo all @item Run @command{tofuproxy} itself. By default it will bind to -@code{[::1]:8080}, use @code{[::1]:53} DNS server for DANE requests +@code{[::1]:8080} and use @code{[::1]:53} DNS server for DANE requests (set to an empty string to disable DANE lookups): @example @@ -46,11 +46,7 @@ main.go:70: listening: [::1]:8080 dns: [::1]:53 certs: ./certs ccerts: ./ccerts # cat cert.pem >> /etc/ssl/cert.pem @end example -@item Point you HTTP/HTTPS clients to @code{http://localhost:8080}. - -@item -If you want to use TLS client certificates, then place them to -@file{-ccerts} directory. +@item Point you HTTP/HTTPS clients to @code{http://localhost:8080} proxy. @item Watch logs: @@ -61,8 +57,3 @@ $ ( cd fifos ; ./multitail.sh ) @image{logs,,,Example logs,.webp} @end itemize - -@include spies.texi -@include certs.texi -@include warcs.texi -@include gemini.texi diff --git a/doc/warcs.texi b/doc/warcs.texi index aba62ae..b20b120 100644 --- a/doc/warcs.texi +++ b/doc/warcs.texi @@ -1,5 +1,5 @@ @node WARCs -@section WARCs management +@unnumbered WARCs management To view WARC files, you have to load them in daemon. Responses will be transparently replaced from those WARCs for corresponding URIs. @@ -24,13 +24,13 @@ Zstandard compressed WARC, as in Multi-frame format is properly indexed. Dictionary at the beginning is also supported. -It is processed with with @command{unzstd} (@command{redo -cmd/unzstd/unzstd}) utility. It eats compressed stream from -@code{stdin}, outputs decompressed data to @code{stdout}, and prints -each frame size with corresponding decompressed data size to 3rd file -descriptor (if it is opened). You can adjust path to it with @code{-X -go.stargrave.org/tofuproxy/warc.UnZSTDPath} command line option during -building. +It is processed with with @command{unzstd} (@file{cmd/unzstd/unzstd}) +utility. It eats compressed stream from @code{stdin}, outputs +decompressed data to @code{stdout}, and prints each frame size with +corresponding decompressed data size to 3rd file descriptor (if it is +opened). You can adjust path to it with +@code{-X go.stargrave.org/tofuproxy/warc.UnZSTDPath} command line option +during building. @end table @@ -76,14 +76,14 @@ it contains continuation segmented records. Loading of WARC involves its whole reading and remembering where is each URI response is located. You can @code{echo SAVE > fifos/add-warcs} to -save in-memory index to the disk as @file{....idx.gob} file. During -the next load, if that file exists, it is used as index immediately, +save in-memory index to the disk as @file{....idx.gob} files. During +the next load, if those files exists, they are used as index immediately, without expensive WARC parsing. -@code{redo warc-extract.cmd} builds @command{warc-extract.cmd} utility, -that uses exactly the same code for parsing WARCs. It can be used to -check if WARCs can be successfully loaded, to list all URIs after, to -extract some specified URI and to pre-generate @file{.idx.gob} indexes. +@code{redo warc-extract.cmd} utility uses exactly the same code for +parsing WARCs. It can be used to check if WARCs can be successfully +loaded, to list all URIs after, to extract some specified URI and to +pre-generate @file{.idx.gob} indexes. @example $ warc-extract.cmd -idx \ @@ -98,7 +98,7 @@ $ warc-extract.cmd -uri http://some/uri \ Following example can be used to create multi-frame @file{.warc.zst} from any kind of already existing WARCs. It has better compression ratio -and much higher decompression speed. +and much higher decompression speed, than @file{.warc.gz}. @example $ redo cmd/enzstd/enzstd diff --git a/doc/why.texi b/doc/why.texi new file mode 100644 index 0000000..7e8aa24 --- /dev/null +++ b/doc/why.texi @@ -0,0 +1,60 @@ +@node Why +@unnumbered Why I created it? + +@itemize + +@item I am tired that various HTTPS clients (like browsers and feed +aggregators) use TLS libraries with different feature set. NSS, GnuTLS, +OpenSSL... All of them sucks, comparing to Go's @code{crypto/tls}. + +@item I am tired that everyone provides very limited certificates trust +management capabilities, like either certificate or SPKI +@url{https://en.wikipedia.org/wiki/Certificate_pinning, pinning} with +@url{https://en.wikipedia.org/wiki/Trust_on_first_use, TOFU}. Even my +beloved @url{https://en.wikipedia.org/wiki/Xombrero, Xombrero} browser +still pins only the whole certificate, but its public key would be much +more sufficient and convenient to work with. + +@item I am tired that many clients provides very few information about +certificates and connections at all. + +@item I hate that hardly anyone can control (no automatic silent +transparent following) HTTP redirections. Although Firefox (I used many +ears ago) had proper extensions for that. + +@item I am sick of tiny control on URLs. The best you can is to use some +kind of @url{https://en.wikipedia.org/wiki/Privoxy, Privoxy}, but it is +not friendly with TLS connections, obviously. Or use yet another +browser-specific plugin. + +@item Xombrero sometimes has problems with HTTP-based authorization. + +@item Hardly anyone does +@url{https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities, DANE} +checks. + +@item And there is insanity of fonts downloading. +Why the hell people just do not send PostScript documents instead!? + +@item And wonderful @url{http://jpegxl.info/, JPEG XL} image format is +not supported by most browsers. Even pretty old +@url{https://developers.google.com/speed/webp, WebP}, that has highest +compression ratio for lossless screenshots, is not supported everywhere, +especially on old browsers. +@url{https://aomediacodec.github.io/av1-avif/, AVIF} could be useful too. + +@item None of web browsers has ability to view web archives +(@url{https://en.wikipedia.org/wiki/Web_ARChive, WARC}s). And most of +WARC-related software is written on Python, that nowadays is close to be +impossible to install and use with all its broken dependencies system. + +@item And yet another piece of software is needed for browsing the +@url{https://en.wikipedia.org/wiki/Gemini_(protocol), geminispace}? +Too many bicycles already! + +@end itemize + +That is why I wrote @command{tofuproxy} -- pure Go HTTP proxy, MitMing +all HTTPS connections on the fly. It is written for my personal needs +exclusively, so many features are just directly hard-coded, instead of +creating some kind of complex configuration framework. diff --git a/fifos/add.go b/fifos/add.go new file mode 100644 index 0000000..14bc088 --- /dev/null +++ b/fifos/add.go @@ -0,0 +1,42 @@ +/* +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser +Copyright (C) 2021 Sergey Matveev + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +package fifos + +import ( + "bufio" + "log" + "os" +) + +func readLinesFromFIFO(p string) []string { + fd, err := os.OpenFile(p, os.O_RDONLY, os.FileMode(0666)) + if err != nil { + log.Fatalln(err) + } + var lines []string + scanner := bufio.NewScanner(fd) + for scanner.Scan() { + t := scanner.Text() + if len(t) > 0 { + lines = append(lines, t) + } + } + fd.Close() + return lines +} diff --git a/fifos/del.go b/fifos/del.go index 7700baf..097ddbf 100644 --- a/fifos/del.go +++ b/fifos/del.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/fifos/ensure.do b/fifos/ensure.do index 85a674b..1a961be 100644 --- a/fifos/ensure.do +++ b/fifos/ensure.do @@ -5,5 +5,6 @@ for f in accepted http-auth rejected spies tls-auth warcs ; do [ -p list-$f ] || mkfifo list-$f [ -p del-$f ] || mkfifo del-$f done -[ -p add-spies ] || mkfifo add-spies -[ -p add-warcs ] || mkfifo add-warcs +for f in spies tls-auth warcs ; do + [ -p add-$f ] || mkfifo add-$f +done diff --git a/fifos/list.go b/fifos/list.go index d8f77ad..1a18f58 100644 --- a/fifos/list.go +++ b/fifos/list.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/fifos/log.go b/fifos/log.go index b5308c8..c132cb4 100644 --- a/fifos/log.go +++ b/fifos/log.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/fifos/spies.go b/fifos/spies.go index 2428ba8..19d3c5e 100644 --- a/fifos/spies.go +++ b/fifos/spies.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify @@ -19,7 +19,6 @@ along with this program. If not, see . package fifos import ( - "bufio" "log" "os" @@ -45,19 +44,10 @@ func listSpies(p string) { func addSpy(p string) { for { - fd, err := os.OpenFile(p, os.O_RDONLY, os.FileMode(0666)) - if err != nil { - log.Fatalln(err) - } hosts := make(map[string]struct{}) - scanner := bufio.NewScanner(fd) - for scanner.Scan() { - t := scanner.Text() - if len(t) > 0 { - hosts[t] = struct{}{} - } + for _, line := range readLinesFromFIFO(p) { + hosts[line] = struct{}{} } - fd.Close() for host := range hosts { log.Printf("%s: adding host %s\n", p, host) } diff --git a/fifos/start.go b/fifos/start.go index 570f4bc..87fb617 100644 --- a/fifos/start.go +++ b/fifos/start.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify @@ -58,10 +58,6 @@ func Start(fifos string) { &caches.RejectedM, func(host string) { delete(caches.Rejected, host) }, filepath.Join(fifos, "del-rejected"), ) - go del( - &caches.TLSAuthCacheM, func(host string) { delete(caches.TLSAuthCache, host) }, - filepath.Join(fifos, "del-tls-auth"), - ) go addSpy(filepath.Join(fifos, "add-spies")) go del( @@ -85,4 +81,10 @@ func Start(fifos string) { }, filepath.Join(fifos, "del-warcs"), ) + + go addTLSAuth(filepath.Join(fifos, "add-tls-auth")) + go del( + &caches.TLSAuthCacheM, func(host string) { delete(caches.TLSAuthCache, host) }, + filepath.Join(fifos, "del-tls-auth"), + ) } diff --git a/fifos/tls.go b/fifos/tls.go new file mode 100644 index 0000000..285ed3a --- /dev/null +++ b/fifos/tls.go @@ -0,0 +1,62 @@ +/* +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser +Copyright (C) 2021 Sergey Matveev + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +package fifos + +import ( + "crypto/tls" + "log" + "strings" + + "go.cypherpunks.ru/ucspi" + "go.stargrave.org/tofuproxy/caches" +) + +func addTLSAuth(p string) { + for { + for _, line := range readLinesFromFIFO(p) { + cols := strings.SplitN(line, " ", 2) + if len(cols) != 2 { + log.Println("invalid add-tls-auth line format") + continue + } + if cols[1] == "NONE" { + caches.TLSAuthCacheM.Lock() + caches.TLSAuthCache[cols[0]] = &tls.Certificate{} + caches.TLSAuthCacheM.Unlock() + log.Printf("%s: added host %s: NONE\n", p, cols[0]) + continue + } + _, cert, err := ucspi.CertificateFromFile(cols[1]) + if err != nil { + log.Fatalln(err) + } + prv, err := ucspi.PrivateKeyFromFile(cols[1]) + if err != nil { + log.Fatalln(err) + } + caches.TLSAuthCacheM.Lock() + caches.TLSAuthCache[cols[0]] = &tls.Certificate{ + Certificate: [][]byte{cert.Raw}, + PrivateKey: prv, + } + caches.TLSAuthCacheM.Unlock() + log.Printf("%s: added host %s: %s\n", p, cols[0], cert.Subject) + } + } +} diff --git a/fifos/warcs.go b/fifos/warcs.go index ca8da6d..4f7dcc2 100644 --- a/fifos/warcs.go +++ b/fifos/warcs.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify @@ -19,7 +19,6 @@ along with this program. If not, see . package fifos import ( - "bufio" "fmt" "log" "os" @@ -47,22 +46,9 @@ func listWARCs(p string) { func addWARC(p string) { for { - fd, err := os.OpenFile(p, os.O_RDONLY, os.FileMode(0666)) - if err != nil { - log.Fatalln(err) - } - var warcPaths []string - scanner := bufio.NewScanner(fd) - for scanner.Scan() { - t := scanner.Text() - if len(t) > 0 { - warcPaths = append(warcPaths, t) - } - } - fd.Close() - for _, warcPath := range warcPaths { + for _, warcPath := range readLinesFromFIFO(p) { if warcPath == "SAVE" { - if err = warc.SaveIndexes(); err != nil { + if err := warc.SaveIndexes(); err != nil { log.Printf("%s: can not save index %s: %+v\n", p, warcPath, err) } continue @@ -71,8 +57,7 @@ func addWARC(p string) { continue } log.Printf("%s: adding WARC %s\n", p, warcPath) - err = warc.Add(warcPath) - if err != nil { + if err := warc.Add(warcPath); err != nil { log.Printf("%s: can not open %s: %+v\n", p, warcPath, err) break } diff --git a/httpauth.go b/httpauth.go index 025c42d..5b454ca 100644 --- a/httpauth.go +++ b/httpauth.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/rounds/denyFonts.go b/rounds/denyFonts.go index ea29361..a460c11 100644 --- a/rounds/denyFonts.go +++ b/rounds/denyFonts.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/rounds/gemini.go b/rounds/gemini.go index 43cf422..8d61848 100644 --- a/rounds/gemini.go +++ b/rounds/gemini.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify @@ -94,6 +94,12 @@ func RoundGemini( } paths := strings.Split(strings.TrimPrefix(req.URL.Path, "/"), "/") host, paths = paths[0], paths[1:] + if host == "gemini:" { + http.Redirect(w, req, strings.Join( + append([]string{GeminiEntrypoint}, paths[1:]...), "/", + ), http.StatusTemporaryRedirect) + return false, nil + } hostWithPort := host if !strings.Contains(hostWithPort, ":") { hostWithPort += GeminiPort diff --git a/rounds/habrImage.go b/rounds/habrImage.go index c9f6fe4..778fe76 100644 --- a/rounds/habrImage.go +++ b/rounds/habrImage.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/rounds/noHead.go b/rounds/noHead.go index e1e32fe..8116358 100644 --- a/rounds/noHead.go +++ b/rounds/noHead.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/rounds/reddit.go b/rounds/reddit.go index 8e7ecf3..b82e363 100644 --- a/rounds/reddit.go +++ b/rounds/reddit.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/rounds/redirectHTML.go b/rounds/redirectHTML.go index 6a7e1fb..291086d 100644 --- a/rounds/redirectHTML.go +++ b/rounds/redirectHTML.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/rounds/spy.go b/rounds/spy.go index fcb96f8..5b6cec8 100644 --- a/rounds/spy.go +++ b/rounds/spy.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/rounds/transcodeAVIF.go b/rounds/transcodeAVIF.go index a5cf4e2..921587d 100644 --- a/rounds/transcodeAVIF.go +++ b/rounds/transcodeAVIF.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/rounds/transcodeJXL.go b/rounds/transcodeJXL.go index 1d3a58e..07b4076 100644 --- a/rounds/transcodeJXL.go +++ b/rounds/transcodeJXL.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/rounds/transcodeWebP.go b/rounds/transcodeWebP.go index 82d3661..a3682ab 100644 --- a/rounds/transcodeWebP.go +++ b/rounds/transcodeWebP.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/rounds/warc.go b/rounds/warc.go index 0ca4777..16dee3c 100644 --- a/rounds/warc.go +++ b/rounds/warc.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/tls.go b/tls.go index ffd5084..4a4de46 100644 --- a/tls.go +++ b/tls.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/tls/dane.go b/tls/dane.go index 22fad5d..ac05a0c 100644 --- a/tls/dane.go +++ b/tls/dane.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/tls/dial.go b/tls/dial.go index a22dc5f..fe9ea75 100644 --- a/tls/dial.go +++ b/tls/dial.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/tls/tlsauth.go b/tls/tlsauth.go index 1d47670..71b30cd 100644 --- a/tls/tlsauth.go +++ b/tls/tlsauth.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/tls/verify.go b/tls/verify.go index 467dbb3..5857b84 100644 --- a/tls/verify.go +++ b/tls/verify.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/trip.go b/trip.go index 6026229..73807a7 100644 --- a/trip.go +++ b/trip.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/warc/compressed.go b/warc/compressed.go index 06fc53e..db37207 100644 --- a/warc/compressed.go +++ b/warc/compressed.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/warc/gzip.go b/warc/gzip.go index f68da5c..de1a863 100644 --- a/warc/gzip.go +++ b/warc/gzip.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/warc/header.go b/warc/header.go index 53a6d41..8511133 100644 --- a/warc/header.go +++ b/warc/header.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/warc/open.go b/warc/open.go index f802bbd..e742f9e 100644 --- a/warc/open.go +++ b/warc/open.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/warc/reader.go b/warc/reader.go index e734136..9e0c3d7 100644 --- a/warc/reader.go +++ b/warc/reader.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/warc/record.go b/warc/record.go index 3a98435..0398508 100644 --- a/warc/record.go +++ b/warc/record.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/warc/uncompressed.go b/warc/uncompressed.go index 5164e3d..9b54f33 100644 --- a/warc/uncompressed.go +++ b/warc/uncompressed.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/warc/uris.go b/warc/uris.go index 12bf70d..ea1ed31 100644 --- a/warc/uris.go +++ b/warc/uris.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify diff --git a/x509.go b/x509.go index f4e4e7f..96848cc 100644 --- a/x509.go +++ b/x509.go @@ -1,6 +1,6 @@ /* -tofuproxy -- flexible HTTP proxy, TLS terminator, X.509 certificates - manager, WARC/Gemini browser +tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU + manager, WARC/geminispace browser Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify