diff options
author | Moritz Poldrack <git@moritz.sh> | 2023-03-04 10:56:47 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-03-07 00:13:03 +0100 |
commit | d3dea73aa53791a94f86c31689a10880fabeb84c (patch) | |
tree | ae815295162ff7431d47fd16a2e74d0cb8465222 | |
parent | c6a08b1003a2cb02d86002541ead0f9b38db1beb (diff) | |
download | aerc-d3dea73aa53791a94f86c31689a10880fabeb84c.tar.gz |
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 <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | config/general.go | 1 | ||||
-rw-r--r-- | doc/aerc-config.5.scd | 5 | ||||
-rw-r--r-- | doc/aerc.1.scd | 4 | ||||
-rw-r--r-- | lib/ipc/handler.go | 1 | ||||
-rw-r--r-- | lib/ipc/receive.go | 14 | ||||
-rw-r--r-- | widgets/aerc.go | 6 |
7 files changed, 34 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 42c41de5..b81765bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - New column-based status line format with `status-columns`. - Inline user-defined styles can be inserted in UI templates via the `{{.Style "name" string}}` function. +- Add the ability to run arbitrary commands over the socket. This can be + disabled using the `disable-ipc` setting. + ### Changed diff --git a/config/general.go b/config/general.go index 0968976b..a2c5e765 100644 --- a/config/general.go +++ b/config/general.go @@ -16,6 +16,7 @@ type GeneralConfig struct { UnsafeAccountsConf bool `ini:"unsafe-accounts-conf"` LogFile string `ini:"log-file"` LogLevel log.LogLevel `ini:"log-level" default:"info" parse:"ParseLogLevel"` + DisableIPC bool `ini:"disable-ipc"` } var General = new(GeneralConfig) diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index a04f3be9..4d64a6f4 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -62,6 +62,11 @@ These options are configured in the *[general]* section of _aerc.conf_. Default: _info_ +*disable-ipc* = _true_|_false_ + Disable the execution of commands over IPC. + + Default: _false_ + # UI OPTIONS These options are configured in the *[ui]* section of _aerc.conf_. diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd index 57d290cc..0dbf5f2a 100644 --- a/doc/aerc.1.scd +++ b/doc/aerc.1.scd @@ -45,6 +45,10 @@ from your terminal. Note that reserved characters in the queries must be percent encoded. +\:*command* [...] + Run an aerc-internal command as you would in Ex-Mode. See *RUNTIME + COMMANDS* below. + # RUNTIME COMMANDS To execute a command, press *:* to bring up the command interface. Commands may 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"} } diff --git a/widgets/aerc.go b/widgets/aerc.go index 572a123c..70083860 100644 --- a/widgets/aerc.go +++ b/widgets/aerc.go @@ -782,6 +782,12 @@ func (aerc *Aerc) Mbox(source string) error { return nil } +func (aerc *Aerc) Command(args []string) error { + defer ui.QueueRedraw() + defer ui.Invalidate() + return aerc.cmd(args, nil, nil) +} + func (aerc *Aerc) CloseBackends() error { var returnErr error for _, acct := range aerc.accounts { |