Only respond to RPC calls from the same user as the daemon process

This commit is contained in:
2025-04-02 00:28:48 -04:00
parent e3d5c83968
commit 3767db2575
+7 -4
View File
@@ -75,7 +75,8 @@ func (h *RCWService) GetPass(request string, reply *string) error {
// handleConn verifies the identity of the client. // handleConn verifies the identity of the client.
// It uses the file descriptor of the connection to get the PID of the client, // It uses the file descriptor of the connection to get the PID of the client,
// which is then used to get the path of the client's executable and calculate its hash. // which is then used to get the path of the client's executable and calculate its hash.
// The passphrase is only returned if the client's executable hash matches the daemon's hash. // The passphrase is only returned if the client's executable hash matches the daemon's hash
// and if the request is coming from the same user.
// This ensures that only the binary the daemon is embedded in can retrieve the passphrase. // This ensures that only the binary the daemon is embedded in can retrieve the passphrase.
func handleConn(conn net.Conn) { func handleConn(conn net.Conn) {
// ensure access to the underlying file descriptor // ensure access to the underlying file descriptor
@@ -94,6 +95,7 @@ func handleConn(conn net.Conn) {
} }
var callingPID int32 var callingPID int32
var callingUID int
_ = rawConn.Control(func(fd uintptr) { _ = rawConn.Control(func(fd uintptr) {
// use syscall.GetsockoptUcred to fetch credentials // use syscall.GetsockoptUcred to fetch credentials
ucred, err := syscall.GetsockoptUcred(int(fd), syscall.SOL_SOCKET, syscall.SO_PEERCRED) ucred, err := syscall.GetsockoptUcred(int(fd), syscall.SOL_SOCKET, syscall.SO_PEERCRED)
@@ -102,18 +104,19 @@ func handleConn(conn net.Conn) {
return return
} }
callingPID = ucred.Pid callingPID = ucred.Pid
callingUID = int(ucred.Uid)
}) })
// check if the RPC call is coming from an identical binary // check if the RPC call is coming from an identical binary and from the same user
callingBinPath := pidToPath(callingPID) callingBinPath := pidToPath(callingPID)
if bytes.Equal(getFileHash(callingBinPath), daemonHash) { if callingUID == os.Getuid() && bytes.Equal(getFileHash(callingBinPath), daemonHash) {
// valid client; hand off the connection to the RPC server // valid client; hand off the connection to the RPC server
rpc.ServeConn(conn) rpc.ServeConn(conn)
} else { } else {
// invalid client; close the connection w/o a response, // invalid client; close the connection w/o a response,
// log the client's path, and kill the daemon // log the client's path, and kill the daemon
conn.Close() conn.Close()
log.Printf("Request received from invalid client: %s", callingBinPath) // TODO log to file log.Printf("Request received from invalid client: PID(%d), UID(%d), Path(%s)", callingPID, callingUID, callingBinPath) // TODO log to file
os.Exit(2) os.Exit(2)
} }
} }