aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradnano <[email protected]>2020-09-27 20:20:59 -0400
committeradnano <[email protected]>2020-09-27 20:20:59 -0400
commit38fe1f21dc8d356157845bf7b930291d54879def (patch)
tree45024a1f6f5e95952a30f7111bc8e40d9208ebe7
parentAdd helper handler functions (diff)
downloadgo-gemini-38fe1f21dc8d356157845bf7b930291d54879def.tar.xz
go-gemini-38fe1f21dc8d356157845bf7b930291d54879def.zip
Change package name to gmi
-rw-r--r--README.md4
-rw-r--r--cert.go2
-rw-r--r--client.go2
-rw-r--r--examples/auth/auth.go62
-rw-r--r--examples/client/client.go30
-rw-r--r--examples/server/server.go6
-rw-r--r--gemini.go2
-rw-r--r--gemini_test.go2
-rw-r--r--server.go2
-rw-r--r--tofu.go2
-rw-r--r--verify.go18
11 files changed, 64 insertions, 68 deletions
diff --git a/README.md b/README.md
index 4847217..daa3ffb 100644
--- a/README.md
+++ b/README.md
@@ -59,7 +59,7 @@ gemini.Send(req)
Clients can also load their own list of known hosts:
```go
-client := &Client{}
+client := &gmi.Client{}
if err := client.KnownHosts.LoadFrom("path/to/my/known_hosts"); err != nil {
log.Fatal(err)
}
@@ -69,7 +69,7 @@ Clients can then specify how to trust certificates in the `TrustCertificate`
field:
```go
-client.TrustCertificate = func(hostname string, cert *x509.Certificate, knownHosts *gemini.KnownHosts) error {
+client.TrustCertificate = func(hostname string, cert *x509.Certificate, knownHosts *gmi.KnownHosts) error {
// If the certificate is in the known hosts list, allow the connection
return knownHosts.Lookup(hostname, cert)
}
diff --git a/cert.go b/cert.go
index e9c4863..8c82aa4 100644
--- a/cert.go
+++ b/cert.go
@@ -1,4 +1,4 @@
-package gemini
+package gmi
import (
"bytes"
diff --git a/client.go b/client.go
index c067dc2..960b7b1 100644
--- a/client.go
+++ b/client.go
@@ -1,5 +1,5 @@
// Package gemini implements the Gemini protocol.
-package gemini
+package gmi
import (
"bufio"
diff --git a/examples/auth/auth.go b/examples/auth/auth.go
index 0c99535..6abd0c8 100644
--- a/examples/auth/auth.go
+++ b/examples/auth/auth.go
@@ -39,12 +39,12 @@ func main() {
//
// go run -tags=example ../cert
//
- cert, err := tls.LoadX509KeyPair("examples/client/localhost.crt", "examples/client/localhost.key")
+ cert, err := tls.LoadX509KeyPair("examples/server/localhost.crt", "examples/server/localhost.key")
if err != nil {
log.Fatal(err)
}
- handler := &gemini.ServeMux{}
+ handler := &gmi.ServeMux{}
handler.HandleFunc("", welcome)
handler.HandleFunc("/login", login)
handler.HandleFunc("/login/password", loginPassword)
@@ -52,7 +52,7 @@ func main() {
handler.HandleFunc("/admin", admin)
handler.HandleFunc("/logout", logout)
- server := &gemini.Server{
+ server := &gmi.Server{
Certificate: cert,
Handler: handler,
}
@@ -63,102 +63,98 @@ func main() {
}
func getSession(crt *x509.Certificate) (*session, bool) {
- fingerprint := gemini.Fingerprint(crt)
+ fingerprint := gmi.Fingerprint(crt)
session, ok := sessions[fingerprint]
return session, ok
}
-func welcome(rw *gemini.ResponseWriter, req *gemini.Request) {
- rw.WriteHeader(gemini.StatusSuccess, "text/gemini")
+func welcome(rw *gmi.ResponseWriter, req *gmi.Request) {
+ rw.WriteHeader(gmi.StatusSuccess, "text/gemini")
rw.Write([]byte("Welcome to this example.\n=> /login Login\n"))
}
-func login(rw *gemini.ResponseWriter, req *gemini.Request) {
+func login(rw *gmi.ResponseWriter, req *gmi.Request) {
if len(req.TLS.PeerCertificates) > 0 {
if username := req.URL.RawQuery; username == "" {
- rw.WriteHeader(gemini.StatusInput, "Username")
+ rw.WriteHeader(gmi.StatusInput, "Username")
} else {
- fingerprint := gemini.Fingerprint(req.TLS.PeerCertificates[0])
+ fingerprint := gmi.Fingerprint(req.TLS.PeerCertificates[0])
sessions[fingerprint] = &session{
username: username,
}
// TODO: Remove scheme and host once example client can handle relative redirects
- rw.WriteHeader(gemini.StatusRedirectTemporary, "gemini://localhost/login/password")
+ rw.WriteHeader(gmi.StatusRedirect, "gemini://localhost/login/password")
}
} else {
- rw.WriteHeader(gemini.StatusClientCertificateRequired, "Certificate required")
+ rw.WriteHeader(gmi.StatusClientCertificateRequired, "Certificate required")
}
}
-func loginPassword(rw *gemini.ResponseWriter, req *gemini.Request) {
+func loginPassword(rw *gmi.ResponseWriter, req *gmi.Request) {
if len(req.TLS.PeerCertificates) > 0 {
session, ok := getSession(req.TLS.PeerCertificates[0])
if !ok {
- rw.WriteHeader(gemini.StatusCertificateNotAuthorised, "Not authorized")
+ rw.WriteHeader(gmi.StatusCertificateNotAuthorised, "Not authorized")
return
}
if password := req.URL.RawQuery; password == "" {
- rw.WriteHeader(gemini.StatusInput, "Password")
+ rw.WriteHeader(gmi.StatusInput, "Password")
} else {
expected := logins[session.username].password
if password == expected {
// TODO: Remove scheme and host once example client can handle relative redirects
session.authorized = true
- rw.WriteHeader(gemini.StatusRedirectTemporary, "gemini://localhost/profile")
+ rw.WriteHeader(gmi.StatusRedirect, "gemini://localhost/profile")
} else {
- rw.WriteHeader(gemini.StatusInput, "Wrong password. Please try again")
+ rw.WriteHeader(gmi.StatusInput, "Wrong password. Please try again")
}
}
} else {
- rw.WriteHeader(gemini.StatusClientCertificateRequired, "Certificate required")
+ rw.WriteHeader(gmi.StatusClientCertificateRequired, "Certificate required")
}
}
-func logout(rw *gemini.ResponseWriter, req *gemini.Request) {
+func logout(rw *gmi.ResponseWriter, req *gmi.Request) {
if len(req.TLS.PeerCertificates) > 0 {
- fingerprint := gemini.Fingerprint(req.TLS.PeerCertificates[0])
+ fingerprint := gmi.Fingerprint(req.TLS.PeerCertificates[0])
delete(sessions, fingerprint)
}
- rw.WriteHeader(gemini.StatusSuccess, "text/gemini")
+ rw.WriteHeader(gmi.StatusSuccess, "text/gemini")
rw.Write([]byte("Successfully logged out.\n"))
}
-func badLogin(rw *gemini.ResponseWriter, req *gemini.Request) {
-
-}
-
-func profile(rw *gemini.ResponseWriter, req *gemini.Request) {
+func profile(rw *gmi.ResponseWriter, req *gmi.Request) {
if len(req.TLS.PeerCertificates) > 0 {
session, ok := getSession(req.TLS.PeerCertificates[0])
if !ok {
- rw.WriteHeader(gemini.StatusCertificateNotAuthorised, "Certificate not authorized")
+ rw.WriteHeader(gmi.StatusCertificateNotAuthorised, "Certificate not authorized")
return
}
user := logins[session.username]
profile := fmt.Sprintf("Username: %s\nAdmin: %t\n=> /logout Logout", session.username, user.admin)
- rw.WriteHeader(gemini.StatusSuccess, "text/gemini")
+ rw.WriteHeader(gmi.StatusSuccess, "text/gemini")
rw.Write([]byte(profile))
} else {
- rw.WriteHeader(gemini.StatusClientCertificateRequired, "Certificate required")
+ rw.WriteHeader(gmi.StatusClientCertificateRequired, "Certificate required")
}
}
-func admin(rw *gemini.ResponseWriter, req *gemini.Request) {
+func admin(rw *gmi.ResponseWriter, req *gmi.Request) {
if len(req.TLS.PeerCertificates) > 0 {
session, ok := getSession(req.TLS.PeerCertificates[0])
if !ok {
- rw.WriteHeader(gemini.StatusCertificateNotAuthorised, "Certificate not authorized")
+ rw.WriteHeader(gmi.StatusCertificateNotAuthorised, "Certificate not authorized")
return
}
user := logins[session.username]
if !user.admin {
- rw.WriteHeader(gemini.StatusCertificateNotAuthorised, "Admins only!")
+ rw.WriteHeader(gmi.StatusCertificateNotAuthorised, "Admins only!")
return
}
- rw.WriteHeader(gemini.StatusSuccess, "text/gemini")
+ rw.WriteHeader(gmi.StatusSuccess, "text/gemini")
rw.Write([]byte("Welcome to the admin portal.\n"))
} else {
- rw.WriteHeader(gemini.StatusClientCertificateRequired, "Certificate required")
+ rw.WriteHeader(gmi.StatusClientCertificateRequired, "Certificate required")
}
}
diff --git a/examples/client/client.go b/examples/client/client.go
index 4c924a6..b209d0e 100644
--- a/examples/client/client.go
+++ b/examples/client/client.go
@@ -13,22 +13,22 @@ import (
var (
scanner = bufio.NewScanner(os.Stdin)
- client *gemini.Client
+ client *gmi.Client
)
func init() {
// Initialize the client
- client = &gemini.Client{}
+ client = &gmi.Client{}
client.KnownHosts.Load() // Load known hosts
- client.TrustCertificate = func(hostname string, cert *x509.Certificate, knownHosts *gemini.KnownHosts) error {
+ client.TrustCertificate = func(hostname string, cert *x509.Certificate, knownHosts *gmi.KnownHosts) error {
err := knownHosts.Lookup(hostname, cert)
if err != nil {
switch err {
- case gemini.ErrCertificateNotTrusted:
+ case gmi.ErrCertificateNotTrusted:
// Alert the user that the certificate is not trusted
fmt.Printf("Warning: Certificate for %s is not trusted!\n", hostname)
fmt.Println("This could indicate a Man-in-the-Middle attack.")
- case gemini.ErrUnknownCertificate:
+ case gmi.ErrUnknownCertificate:
// Prompt the user to trust the certificate
trust := trustCertificate(cert)
switch trust {
@@ -48,33 +48,33 @@ func init() {
}
// sendRequest sends a request to the given url.
-func sendRequest(req *gemini.Request) error {
+func sendRequest(req *gmi.Request) error {
resp, err := client.Send(req)
if err != nil {
return err
}
switch resp.Status / 10 {
- case gemini.StatusClassInput:
+ case gmi.StatusClassInput:
fmt.Printf("%s: ", resp.Meta)
scanner.Scan()
req.URL.RawQuery = scanner.Text()
return sendRequest(req)
- case gemini.StatusClassSuccess:
+ case gmi.StatusClassSuccess:
fmt.Print(string(resp.Body))
return nil
- case gemini.StatusClassRedirect:
+ case gmi.StatusClassRedirect:
fmt.Println("Redirecting to ", resp.Meta)
- req, err := gemini.NewRequest(resp.Meta)
+ req, err := gmi.NewRequest(resp.Meta)
if err != nil {
return err
}
return sendRequest(req)
- case gemini.StatusClassTemporaryFailure:
+ case gmi.StatusClassTemporaryFailure:
return fmt.Errorf("Temporary failure: %s", resp.Meta)
- case gemini.StatusClassPermanentFailure:
+ case gmi.StatusClassPermanentFailure:
return fmt.Errorf("Permanent failure: %s", resp.Meta)
- case gemini.StatusClassClientCertificateRequired:
+ case gmi.StatusClassClientCertificateRequired:
fmt.Println("Generating client certificate for", req.Hostname())
return nil // TODO: Generate and store client certificate
}
@@ -99,7 +99,7 @@ Otherwise, this should be safe to trust.
=> `
func trustCertificate(cert *x509.Certificate) trust {
- fmt.Printf(trustPrompt, gemini.Fingerprint(cert))
+ fmt.Printf(trustPrompt, gmi.Fingerprint(cert))
scanner.Scan()
switch scanner.Text() {
case "t":
@@ -118,7 +118,7 @@ func main() {
}
url := os.Args[1]
- req, err := gemini.NewRequest(url)
+ req, err := gmi.NewRequest(url)
if err != nil {
fmt.Println(err)
os.Exit(1)
diff --git a/examples/server/server.go b/examples/server/server.go
index e761cd0..09abf50 100644
--- a/examples/server/server.go
+++ b/examples/server/server.go
@@ -20,10 +20,10 @@ func main() {
log.Fatal(err)
}
- mux := &gemini.ServeMux{}
- mux.Handle("/", gemini.FileServer(gemini.Dir("/var/www")))
+ mux := &gmi.ServeMux{}
+ mux.Handle("/", gmi.FileServer(gmi.Dir("/var/www")))
- server := gemini.Server{
+ server := gmi.Server{
Handler: mux,
Certificate: cert,
}
diff --git a/gemini.go b/gemini.go
index bef4c68..957dd43 100644
--- a/gemini.go
+++ b/gemini.go
@@ -1,4 +1,4 @@
-package gemini
+package gmi
import (
"crypto/x509"
diff --git a/gemini_test.go b/gemini_test.go
index b118640..b92792b 100644
--- a/gemini_test.go
+++ b/gemini_test.go
@@ -1,4 +1,4 @@
-package gemini
+package gmi
import (
"math/rand"
diff --git a/server.go b/server.go
index 7eb3aaf..5a5db48 100644
--- a/server.go
+++ b/server.go
@@ -1,4 +1,4 @@
-package gemini
+package gmi
import (
"bufio"
diff --git a/tofu.go b/tofu.go
index 21384ab..81502d6 100644
--- a/tofu.go
+++ b/tofu.go
@@ -1,4 +1,4 @@
-package gemini
+package gmi
import (
"bufio"
diff --git a/verify.go b/verify.go
index 7abef8f..8a0fd5a 100644
--- a/verify.go
+++ b/verify.go
@@ -1,4 +1,12 @@
-package gemini
+// Hostname verification code from the crypto/x509 package.
+// Modified to allow Common Names in the short term, until new certificates
+// can be issued with SANs.
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gmi
import (
"crypto/x509"
@@ -9,14 +17,6 @@ import (
"unicode/utf8"
)
-// Hostname verification code from the crypto/x509 package.
-// Modified to allow Common Names in the short term, until new certificates
-// can be issued with SANs.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
var (
oidExtensionSubjectAltName = []int{2, 5, 29, 17}
)