From d3dea73aa53791a94f86c31689a10880fabeb84c Mon Sep 17 00:00:00 2001 From: Moritz Poldrack Date: Sat, 4 Mar 2023 10:56:47 +0100 Subject: ipc: allow triggering internal commands via IPC In order to make automation easier, it's useful to be able to send commands to aerc via IPC. This can be done by calling the aerc binary followed by a colon and the command to run. For example: aerc :read && aerc :remark && aerc :archive month Security to ensure no malicious commands are run is deferred to the user. By default the socket is only writable by the user. This is considered sufficient as the potential harm an attacker gaining write-access to a user's session can cause is significantly greater than "can delete some emails". To ensure users with an according threat model, it is possible to disable command IPC. mailto-handling is unaffected even though it works over IPC as it is absolutely non-destructive. Signed-off-by: Moritz Poldrack Acked-by: Robin Jarry --- lib/ipc/handler.go | 1 + lib/ipc/receive.go | 14 ++++++++++++++ 2 files changed, 15 insertions(+) (limited to 'lib') diff --git a/lib/ipc/handler.go b/lib/ipc/handler.go index fb8f0e06..c00acd63 100644 --- a/lib/ipc/handler.go +++ b/lib/ipc/handler.go @@ -5,4 +5,5 @@ import "net/url" type Handler interface { Mailto(addr *url.URL) error Mbox(source string) error + Command(args []string) error } diff --git a/lib/ipc/receive.go b/lib/ipc/receive.go index 0745e3d6..12df3411 100644 --- a/lib/ipc/receive.go +++ b/lib/ipc/receive.go @@ -11,6 +11,7 @@ import ( "sync/atomic" "time" + "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/log" "github.com/kyoh86/xdg" ) @@ -116,6 +117,19 @@ func (as *AercServer) handleMessage(req *Request) *Response { if err != nil { return &Response{Error: err.Error()} } + case strings.HasPrefix(req.Arguments[0], ":"): + if config.General.DisableIPC { + return &Response{ + Error: "command rejected: IPC is disabled", + } + } + + req.Arguments[0] = strings.TrimPrefix(req.Arguments[0], ":") + err := as.handler.Command(req.Arguments) + if err != nil { + return &Response{Error: err.Error()} + } + default: return &Response{Error: "command not understood"} } -- cgit