Skip to content

Commit

Permalink
internal/zedhook: store *peercred.Creds in context rather than net.Conn
Browse files Browse the repository at this point in the history
Signed-off-by: Matt Layher <mdlayher@gmail.com>
  • Loading branch information
mdlayher committed Apr 1, 2022
1 parent e43a1a5 commit 333d2b6
Showing 1 changed file with 10 additions and 15 deletions.
25 changes: 10 additions & 15 deletions internal/zedhook/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ func NewServer(handler http.Handler, ll *log.Logger) *Server {
// to figure out how to get read-only access to a net.Conn; or maybe
// just its file descriptor?
ConnContext: func(ctx context.Context, c net.Conn) context.Context {
ctx = context.WithValue(ctx, keyNetConn, c)
// Best effort; connection may be UNIX or TCP.
if creds, err := peercred.Get(c); err == nil {
ctx = context.WithValue(ctx, keyCreds, creds)
}

return ctx
},
},
Expand All @@ -57,8 +61,8 @@ func NewServer(handler http.Handler, ll *log.Logger) *Server {
// A contextKey is an opaque structure used as a key for context.Context values.
type contextKey struct{ name string }

// keyNetConn stores a net.Conn in a context.Context Value.
var keyNetConn = &contextKey{"netconn"}
// keyCreds stores *peercred.Creds in a context.Context Value.
var keyCreds = &contextKey{"peercred"}

// Serve serves the zedhookd receiver and blocks until the context is canceled.
func (s *Server) Serve(ctx context.Context) error {
Expand Down Expand Up @@ -153,23 +157,14 @@ func (h *handler) push(w http.ResponseWriter, r *http.Request) {
return
}

// DANGER YOLO: we _must_ treat any use of the net.Conn from request context
// as read-only, and cannot invoke methods like Read, Write, Close, etc.
// because the net/http.Server ultimately owns this net.Conn. We just want
// to get access to the underlying local address and file descriptor for
// SO_PEERCRED.
var (
// Fetch data stored in the request context. For UNIX sockets, creds
// will be non-nil as well.
ctx = r.Context()
local = ctx.Value(http.LocalAddrContextKey).(net.Addr)
creds = ctx.Value(keyCreds).(*peercred.Creds)
)

creds, err := peercred.Get(ctx.Value(keyNetConn).(net.Conn))
if err != nil && !errors.Is(err, peercred.ErrUnsupportedConnType) {
h.ll.Printf("%s: failed to get peer credentials: %v", r.RemoteAddr, err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}

if creds != nil {
h.ll.Printf("local: %s, peer: %s, creds: %+v", local, r.RemoteAddr, creds)
} else {
Expand Down

0 comments on commit 333d2b6

Please sign in to comment.