Skip to content
This repository has been archived by the owner on Aug 6, 2023. It is now read-only.

Commit

Permalink
Use salt when generating ids from ips
Browse files Browse the repository at this point in the history
Implements #6
  • Loading branch information
jdpage committed Mar 2, 2021
1 parent 293b250 commit ffe54c1
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 0 deletions.
1 change: 1 addition & 0 deletions add-comment/add_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ func getId(ip string) string {
ip = strings.ReplaceAll(ip, "_", ":") // Use real IP address, not sanitized
h := sha256.New()
h.Write([]byte(ip))
shared.WriteIPSalt(h)
// First 8 chars
return fmt.Sprintf("%x", h.Sum(nil))[:8]
}
Expand Down
12 changes: 12 additions & 0 deletions example-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ data = "/home/username/.local/share/gemlikes"
# It must be accessible to the user that the CGI script runs under.
# Directories will be created as needed, don't create them yourself.

# Where to store IP salt:
ip_salt = "auto" # default
#ip_salt = "disabled" # disable IP salting (old behavior)
#ip_salt = "/usr/local/etc/gemlikes/ip_salt" # use existing salt
# If unset, the default is "auto", which places the salt in the data directory,
# generating it the first time if needed. "disabled" restores the old behavior,
# which can potentially expose IP addresses to sufficiently-motivated attackers.
# Specifying an absolute path uses the contents of the given file as a salt,
# which must already exist. This allows multiple instances of gemlikes (e.g. in
# a shared environment) to present identical identifiers for the same IP. The
# path should be somewhere the server won't serve.

# The list of directories where files exist that can be liked and commented on:
dirs = ["/var/gemini", "/var/gemini/my_gemlog"]
# IMPORTANT: There can't be any files with same name in any of these directories,
Expand Down
40 changes: 40 additions & 0 deletions shared/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
package shared

import (
"crypto/rand"
"errors"
"fmt"
"io"
"io/ioutil"
"net/url"
"os"
"path/filepath"
Expand All @@ -15,6 +18,8 @@ import (
var ErrConfigDir = errors.New("config dir invalid or not set")
var LikesDisabled = false

var ipSaltValue []byte

func PathExists(path string) bool {
_, err := os.Stat(path)
if err == nil {
Expand Down Expand Up @@ -93,6 +98,12 @@ func SafeInit() error {
if config.Get("disable_likes") != nil {
LikesDisabled = config.Get("disable_likes").(bool)
}
// Load IP->ID salt
ipSaltValue, err = loadIPSalt(config, data.(string))
if err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -176,6 +187,35 @@ func GetTmpDir() string {
return filepath.Join(getDataDir(), "tmp")
}

func WriteIPSalt(w io.Writer) (int, error) {
return w.Write(ipSaltValue)
}

func loadIPSalt(config *toml.Tree, dataDir string) ([]byte, error) {
ipSaltMethod := "auto"
if key := config.Get("ip_salt"); key != nil {
ipSaltMethod = key.(string)
}

ipSaltPath := ipSaltMethod
switch ipSaltMethod {
case "disabled":
return nil, nil
case "auto":
ipSaltPath = filepath.Join(dataDir, "ip_salt")
f, err := os.OpenFile(ipSaltPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o644)
if err == nil {
// First time, create random data
defer f.Close()
if _, err := io.CopyN(f, rand.Reader, 16); err != nil {
return nil, err
}
}
}

return ioutil.ReadFile(ipSaltPath)
}

func getConfigDir() string {
e, _ := os.Executable()
return filepath.Dir(e)
Expand Down

0 comments on commit ffe54c1

Please sign in to comment.