Skip to content

Commit

Permalink
Fork of store into another process
Browse files Browse the repository at this point in the history
First working prototype of an own process serving the store over the
previously implemented RPC. So far no privilege separation was
performed, but now it can be build on top of it.
  • Loading branch information
oxzi committed Sep 22, 2023
1 parent 292529b commit 804805b
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 15 deletions.
93 changes: 92 additions & 1 deletion gosh.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package main

import (
"bufio"
"flag"
"net"
"net/http"
"net/http/fcgi"
"os"
"os/exec"
"os/signal"
"strings"
"time"

Expand Down Expand Up @@ -50,10 +53,40 @@ func serveHttpd(server *Server) {
}
}

func mainStore(storePath string) {
log.WithField("store", storePath).Info("Starting store child")

store, err := NewStore(storePath, true)
if err != nil {
log.Fatal(err)
}

rpcConn, err := UnixConnFromFile(os.NewFile(3, ""))
if err != nil {
log.Fatal(err)
}
fdConn, err := UnixConnFromFile(os.NewFile(4, ""))
if err != nil {
log.Fatal(err)
}

rpcStore := NewStoreRpcServer(store, rpcConn, fdConn)

sigint := make(chan os.Signal, 1)
signal.Notify(sigint, os.Interrupt)
<-sigint

err = rpcStore.Close()
if err != nil {
log.Fatal(err)
}
}

func main() {
log.SetFormatter(&log.TextFormatter{DisableTimestamp: true})

var (
forkStore bool
maxLifetimeStr string
maxFilesizeStr string
mimeMapStr string
Expand All @@ -62,7 +95,10 @@ func main() {
verbose bool
)

log.WithField("args", os.Args).Info("args")

flag.StringVar(&storePath, "store", "", "Path to the store")
flag.BoolVar(&forkStore, "fork-store", false, "Start the store sub")
flag.StringVar(&maxFilesizeStr, "max-filesize", "10MiB", "Maximum file size in bytes")
flag.StringVar(&maxLifetimeStr, "max-lifetime", "24h", "Maximum lifetime")
flag.StringVar(&contactMail, "contact", "", "Contact E-Mail for abuses")
Expand All @@ -79,6 +115,11 @@ func main() {
log.SetLevel(log.DebugLevel)
}

if forkStore {
mainStore(storePath)
return
}

if lt, err := ParseDuration(maxLifetimeStr); err != nil {
log.WithError(err).Fatal("Failed to parse lifetime")
} else {
Expand All @@ -98,6 +139,56 @@ func main() {
log.Fatal("Contact information must be set, see `--help`")
}

logParent, logStore, err := Socketpair()
if err != nil {
log.Fatal(err)
}
rpcParent, rpcStore, err := Socketpair()
if err != nil {
log.Fatal(err)
}
fdParent, fdStore, err := Socketpair()
if err != nil {
log.Fatal(err)
}

go func() {
scanner := bufio.NewScanner(logParent)
for scanner.Scan() {
log.Printf("[store] %s", scanner.Text())
if err := scanner.Err(); err != nil {
log.Printf("scanner failed: %v", err)
}
}
}()

cmd := &exec.Cmd{
Path: os.Args[0],
Args: append(os.Args, "-fork-store"),

Env: []string{},

Stdin: nil,
Stdout: logStore,
Stderr: logStore,
ExtraFiles: []*os.File{rpcStore, fdStore},
}
err = cmd.Start()
if err != nil {
log.Fatal(err)
}

rpcConn, err := UnixConnFromFile(rpcParent)
if err != nil {
log.Fatal(err)
}
fdConn, err := UnixConnFromFile(fdParent)
if err != nil {
log.Fatal(err)
}

storeClient := NewStoreRpcClient(rpcConn, fdConn)

hardeningOpts := &HardeningOpts{
StoreDir: &storePath,
}
Expand Down Expand Up @@ -131,7 +222,7 @@ func main() {
}
}

server, err := NewServer(storePath, maxFilesize, maxLifetime, contactMail, mimeMap, urlPrefix)
server, err := NewServer(storeClient, maxFilesize, maxLifetime, contactMail, mimeMap, urlPrefix)
if err != nil {
log.WithError(err).Fatal("Failed to start Store")
}
Expand Down
23 changes: 9 additions & 14 deletions server.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"context"
"fmt"
"io"
"net/http"
Expand Down Expand Up @@ -171,7 +172,7 @@ const (

// Server implements an http.Handler for up- and download.
type Server struct {
store *Store
store *StoreRpcClient
maxSize int64
maxLifetime time.Duration
contactMail string
Expand All @@ -181,14 +182,8 @@ type Server struct {

// NewServer creates a new Server with a given database directory, and
// configuration values. The Server must be started as an http.Handler.
func NewServer(storeDirectory string, maxSize int64, maxLifetime time.Duration,
func NewServer(store *StoreRpcClient, maxSize int64, maxLifetime time.Duration,
contactMail string, mimeMap MimeMap, urlPrefix string) (s *Server, err error) {
store, storeErr := NewStore(storeDirectory, true)
if storeErr != nil {
err = storeErr
return
}

s = &Server{
store: store,
maxSize: maxSize,
Expand Down Expand Up @@ -292,7 +287,7 @@ func (serv *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
return
}

itemId, err := serv.store.Put(item, f)
itemId, err := serv.store.Put(item, f, context.Background())
if err != nil {
log.WithError(err).Error("Failed to store Item")

Expand Down Expand Up @@ -333,7 +328,7 @@ func (serv *Server) hasClientCachedRequest(r *http.Request, item Item) bool {

// handleRequestServe is called from handleRequest when a valid Item should be served.
func (serv *Server) handleRequestServe(w http.ResponseWriter, r *http.Request, item Item) error {
f, err := serv.store.GetFile(item.ID)
f, err := serv.store.GetFile(item.ID, context.Background())
if err != nil {
return fmt.Errorf("reading file failed: %v", err)
}
Expand Down Expand Up @@ -371,7 +366,7 @@ func (serv *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
_, reqId, _ := strings.Cut(r.URL.Path, serv.urlPrefix)
reqId = strings.TrimLeft(reqId, "/")

item, err := serv.store.Get(reqId)
item, err := serv.store.Get(reqId, context.Background())
if err == ErrNotFound {
log.WithField("ID", reqId).Debug("Requested non-existing ID")

Expand Down Expand Up @@ -401,7 +396,7 @@ func (serv *Server) handleRequest(w http.ResponseWriter, r *http.Request) {

if item.BurnAfterReading {
log.WithField("ID", item.ID).Info("Item will be burned")
if err := serv.store.Delete(item.ID); err != nil {
if err := serv.store.Delete(item.ID, context.Background()); err != nil {
log.WithError(err).WithField("ID", item.ID).Error("Deletion failed")
}
}
Expand All @@ -428,7 +423,7 @@ func (serv *Server) handleDeletion(w http.ResponseWriter, r *http.Request) {

reqId, delKey := reqParts[1], reqParts[2]

item, err := serv.store.Get(reqId)
item, err := serv.store.Get(reqId, context.Background())
if err == ErrNotFound {
log.WithField("ID", reqId).Debug("Requested non-existing ID")

Expand All @@ -448,7 +443,7 @@ func (serv *Server) handleDeletion(w http.ResponseWriter, r *http.Request) {
return
}

if err := serv.store.Delete(item.ID); err != nil {
if err := serv.store.Delete(item.ID, context.Background()); err != nil {
log.WithError(err).WithField("ID", reqId).Error("Requested deletion failed")

http.Error(w, msgGenericError, http.StatusBadRequest)
Expand Down

0 comments on commit 804805b

Please sign in to comment.