Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial OpenBSD client support. #148

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions client/erasure_openbsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

import (
"github.com/agl/pond/client/disk"
)

func (c *client) createErasureStorage(pw string, stateFile *disk.StateFile) error {
// No NVRAM support on OpenBSD yet.
return stateFile.Create(pw)
}
42 changes: 42 additions & 0 deletions client/main_openbsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package main

import (
"crypto/rand"
"flag"
"fmt"
"os"
"path/filepath"
"runtime"
)

func main() {
devFlag := flag.Bool("dev", false, "Is this a development environment?")
stateFile := flag.String("state-file", "", "File in which to save persistent state")
cliFlag := flag.Bool("cli", false, "If true, the CLI will be used, even if the GUI is available")
flag.Parse()

dev := os.Getenv("POND") == "dev" || *devFlag
runtime.GOMAXPROCS(runtime.NumCPU())

if len(*stateFile) == 0 && dev {
*stateFile = "state"
}

if len(*stateFile) == 0 {
home := os.Getenv("HOME")
if len(home) == 0 {
fmt.Fprintf(os.Stderr, "$HOME not set. Please export $HOME to set the directory for the state file.\n")
os.Exit(1)
}
*stateFile = filepath.Join(home, ".pond")
}

if !haveGUI || *cliFlag {
client := NewCLIClient(*stateFile, rand.Reader, false /* testing */, true /* autoFetch */)
client.disableV2Ratchet = true
client.dev = dev
client.Start()
} else {
fmt.Fprintf(os.Stderr, "GUI not supported on %s\n", runtime.GOOS)
}
}
124 changes: 124 additions & 0 deletions client/system/sys_openbsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package system

import (
"errors"
"os"
"os/exec"
"strings"
"sync"
"syscall"
)

// IsSafe checks to see whether the current OS appears to be safe. Specifically
// it checks that any swap is encrypted.
func IsSafe() error {
output, err := exec.Command("sysctl", "vm.swapencrypt.enable").Output()
if err != nil {
return errors.New("system: error when executing 'sysctl vm.swapencrypt.enable': " +
err.Error())
}
if strings.TrimRight(string(output), "\n") != "vm.swapencrypt.enable=1" {
return errors.New("system: swapping is not encrypted")
}

return nil
}

func stringFromInt8(s []int8) string {
b := make([]byte, 0, len(s))

for _, v := range s {
if v == 0 {
break
}
b = append(b, byte(v))
}

return string(b)
}

func processFilesystems(f func(fstype, path string) error) error {
n, err := syscall.Getfsstat(nil, 1 /* MNT_WAIT */)
if err != nil {
return errors.New("system: getfsstat error: " + err.Error())
}

filesystems := make([]syscall.Statfs_t, n)
n, err = syscall.Getfsstat(filesystems, 1 /* MNT_WAIT */)
if err != nil {
return errors.New("system: Getfsstat error: " + err.Error())
}

for _, fs := range filesystems[:n] {
fstype := stringFromInt8(fs.F_fstypename[:])
path := stringFromInt8(fs.F_mntonname[:])
if err := f(fstype, path); err != nil {
return err
}
}

return nil
}

var (
safeTempDir string
safeTempDirErr error
safeTempDirOnce sync.Once
)

func findSafeTempDir() {
var candidates []string

err := processFilesystems(func(fstype, path string) error {
if fstype == "tmpfs" &&
syscall.Access(path, 7 /* write ok */) == nil {
candidates = append(candidates, path)
}

return nil
})

if err == nil && len(candidates) == 0 {
err = errors.New("no writable tmpfs directories found")
}

if err != nil {
safeTempDirErr = errors.New("system: while checking filesystems: " + err.Error())
return
}

suggested := os.TempDir()
preferred := []string{suggested}
var otherOptions []string
if dir := os.Getenv("XDG_RUNTIME_DIR"); len(dir) > 0 {
otherOptions = append(otherOptions, dir)
}
otherOptions = append(otherOptions, "/tmp", "/var/tmp")
for _, d := range otherOptions {
if suggested != d {
preferred = append(preferred, d)
}
}

for _, d := range preferred {
for _, candidate := range candidates {
if candidate == d {
safeTempDir = candidate
return
}
}
}

safeTempDir = candidates[0]
}

// SafeTempDir returns the path of a writable directory which is mounted with
// tmpfs. As long as the swap is encrypted, then it should be safe to write
// there.
func SafeTempDir() (string, error) {
safeTempDirOnce.Do(findSafeTempDir)
if safeTempDirErr != nil {
return "", safeTempDirErr
}
return safeTempDir, nil
}