aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMoritz Poldrack <git@moritz.sh>2023-03-04 10:56:47 +0100
committerRobin Jarry <robin@jarry.cc>2023-03-07 00:13:03 +0100
commitd3dea73aa53791a94f86c31689a10880fabeb84c (patch)
treeae815295162ff7431d47fd16a2e74d0cb8465222
parentc6a08b1003a2cb02d86002541ead0f9b38db1beb (diff)
downloadaerc-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.md3
-rw-r--r--config/general.go1
-rw-r--r--doc/aerc-config.5.scd5
-rw-r--r--doc/aerc.1.scd4
-rw-r--r--lib/ipc/handler.go1
-rw-r--r--lib/ipc/receive.go14
-rw-r--r--widgets/aerc.go6
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 {