From f191448b0dde8065430022ac8831cf81effe6b99 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 14 Apr 2026 17:17:58 +0100 Subject: [PATCH] rc: flip auth default so all endpoints require auth unless opted out Replace AuthRequired bool with NoAuth bool on the rc.Call struct and flip the auth check logic. Previously endpoints were unauthenticated by default and had to opt in with AuthRequired: true, which led to security vulnerabilities when developers forgot to set the flag. Now all endpoints require authentication by default. Only explicitly safe read-only endpoints are marked with NoAuth: true: - rc/noop - rc/error - rc/list - core/version - core/stats - core/group-list - core/transferred - core/du - cache/stats - vfs/list - vfs/stats - vfs/queue - job/status - job/list See GHSA-25qr-6mpr-f7qx, GHSA-jfwf-28xr-xw6q --- backend/cache/cache.go | 7 +- .../iclouddrive/iclouddrive_unsupported.go | 2 +- cmd/bisync/rc.go | 9 +-- cmd/mountlib/rc.go | 35 ++++---- cmd/rc/rc.go | 6 +- cmd/serve/rc.go | 35 ++++---- fs/accounting/stats_groups.go | 21 ++--- fs/config/rc.go | 59 ++++++-------- fs/operations/rc.go | 81 ++++++++----------- fs/rc/cache.go | 14 ++-- fs/rc/config.go | 7 +- fs/rc/internal.go | 36 +++++---- fs/rc/jobs/job.go | 21 ++--- fs/rc/rc.go | 2 +- fs/rc/rcserver/rcserver.go | 2 +- fs/rc/rcserver/rcserver_test.go | 16 ++-- fs/rc/registry.go | 2 +- fs/rc/webgui/rc.go | 42 +++++----- fs/sync/rc.go | 3 +- vfs/rc.go | 15 ++-- 20 files changed, 194 insertions(+), 221 deletions(-) diff --git a/backend/cache/cache.go b/backend/cache/cache.go index 81503a54e..06644b1be 100644 --- a/backend/cache/cache.go +++ b/backend/cache/cache.go @@ -563,9 +563,10 @@ Eg }) rc.Add(rc.Call{ - Path: "cache/stats", - Fn: f.httpStats, - Title: "Get cache stats", + Path: "cache/stats", + NoAuth: true, + Fn: f.httpStats, + Title: "Get cache stats", Help: ` Show statistics for the cache remote. `, diff --git a/backend/iclouddrive/iclouddrive_unsupported.go b/backend/iclouddrive/iclouddrive_unsupported.go index 2eeb6b639..5257e6b56 100644 --- a/backend/iclouddrive/iclouddrive_unsupported.go +++ b/backend/iclouddrive/iclouddrive_unsupported.go @@ -4,4 +4,4 @@ //go:build plan9 || solaris // Package iclouddrive implements the iCloud Drive backend -package iclouddrive \ No newline at end of file +package iclouddrive diff --git a/cmd/bisync/rc.go b/cmd/bisync/rc.go index 0cb677910..82be54185 100644 --- a/cmd/bisync/rc.go +++ b/cmd/bisync/rc.go @@ -18,11 +18,10 @@ import ( func addRC() { rc.Add(rc.Call{ - Path: "sync/bisync", - AuthRequired: true, - Fn: rcBisync, - Title: shortHelp, - Help: rcHelp, + Path: "sync/bisync", + Fn: rcBisync, + Title: shortHelp, + Help: rcHelp, }) } diff --git a/cmd/mountlib/rc.go b/cmd/mountlib/rc.go index b569153b5..9b96747df 100644 --- a/cmd/mountlib/rc.go +++ b/cmd/mountlib/rc.go @@ -46,10 +46,9 @@ func AddRc(mountUtilName string, mountFunction MountFn) { func init() { rc.Add(rc.Call{ - Path: "mount/mount", - AuthRequired: true, - Fn: mountRc, - Title: "Create a new mount point", + Path: "mount/mount", + Fn: mountRc, + Title: "Create a new mount point", Help: `rclone allows Linux, FreeBSD, macOS and Windows to mount any of Rclone's cloud storage systems as a file system with FUSE. @@ -147,10 +146,9 @@ func mountRc(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "mount/unmount", - AuthRequired: true, - Fn: unMountRc, - Title: "Unmount selected active mount", + Path: "mount/unmount", + Fn: unMountRc, + Title: "Unmount selected active mount", Help: ` rclone allows Linux, FreeBSD, macOS and Windows to mount any of Rclone's cloud storage systems as a file system with @@ -188,10 +186,9 @@ func unMountRc(_ context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "mount/types", - AuthRequired: true, - Fn: mountTypesRc, - Title: "Show all possible mount types", + Path: "mount/types", + Fn: mountTypesRc, + Title: "Show all possible mount types", Help: `This shows all possible mount types and returns them as a list. This takes no parameters and returns @@ -224,10 +221,9 @@ func mountTypesRc(_ context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "mount/listmounts", - AuthRequired: true, - Fn: listMountsRc, - Title: "Show current mount points", + Path: "mount/listmounts", + Fn: listMountsRc, + Title: "Show current mount points", Help: `This shows currently mounted points, which can be used for performing an unmount. This takes no parameters and returns @@ -274,10 +270,9 @@ func listMountsRc(_ context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "mount/unmountall", - AuthRequired: true, - Fn: unmountAll, - Title: "Unmount all active mounts", + Path: "mount/unmountall", + Fn: unmountAll, + Title: "Unmount all active mounts", Help: ` rclone allows Linux, FreeBSD, macOS and Windows to mount any of Rclone's cloud storage systems as a file system with diff --git a/cmd/rc/rc.go b/cmd/rc/rc.go index 328d5a75f..c01a58b75 100644 --- a/cmd/rc/rc.go +++ b/cmd/rc/rc.go @@ -334,10 +334,8 @@ func list(ctx context.Context) error { } fmt.Printf("### %s: %s {#%s}\n\n", info["Path"], info["Title"], strings.ReplaceAll(info["Path"].(string), "/", "-")) fmt.Printf("%s\n\n", info["Help"]) - if authRequired := info["AuthRequired"]; authRequired != nil { - if authRequired.(bool) { - fmt.Printf("**Authentication is required for this call.**\n\n") - } + if noAuth, ok := info["NoAuth"]; ok && noAuth.(bool) { + fmt.Printf("**Authentication is not required for this call.**\n\n") } } return nil diff --git a/cmd/serve/rc.go b/cmd/serve/rc.go index 47c46590a..cbc6e7e7b 100644 --- a/cmd/serve/rc.go +++ b/cmd/serve/rc.go @@ -67,10 +67,9 @@ func q(s string) string { func init() { rc.Add(rc.Call{ - Path: "serve/start", - AuthRequired: true, - Fn: startRc, - Title: "Create a new server", + Path: "serve/start", + Fn: startRc, + Title: "Create a new server", Help: q(`Create a new server with the specified parameters. This takes the following parameters: @@ -177,10 +176,9 @@ func startRc(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "serve/stop", - AuthRequired: true, - Fn: stopRc, - Title: "Unserve selected active serve", + Path: "serve/stop", + Fn: stopRc, + Title: "Unserve selected active serve", Help: q(`Stops a running |serve| instance by ID. This takes the following parameters: @@ -216,10 +214,9 @@ func stopRc(_ context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "serve/types", - AuthRequired: true, - Fn: serveTypesRc, - Title: "Show all possible serve types", + Path: "serve/types", + Fn: serveTypesRc, + Title: "Show all possible serve types", Help: q(`This shows all possible serve types and returns them as a list. This takes no parameters and returns @@ -264,10 +261,9 @@ func serveTypesRc(_ context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "serve/list", - AuthRequired: true, - Fn: listRc, - Title: "Show running servers", + Path: "serve/list", + Fn: listRc, + Title: "Show running servers", Help: q(`Show running servers with IDs. This takes no parameters and returns @@ -328,10 +324,9 @@ func listRc(_ context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "serve/stopall", - AuthRequired: true, - Fn: stopAll, - Title: "Stop all active servers", + Path: "serve/stopall", + Fn: stopAll, + Title: "Stop all active servers", Help: q(`Stop all active servers. This will stop all active servers. diff --git a/fs/accounting/stats_groups.go b/fs/accounting/stats_groups.go index ef71271b8..f14d6fed4 100644 --- a/fs/accounting/stats_groups.go +++ b/fs/accounting/stats_groups.go @@ -29,9 +29,10 @@ func rcListStats(ctx context.Context, in rc.Params) (rc.Params, error) { func init() { rc.Add(rc.Call{ - Path: "core/group-list", - Fn: rcListStats, - Title: "Returns list of stats.", + Path: "core/group-list", + NoAuth: true, + Fn: rcListStats, + Title: "Returns list of stats.", Help: ` This returns list of stats groups currently in memory. @@ -67,9 +68,10 @@ func rcRemoteStats(ctx context.Context, in rc.Params) (rc.Params, error) { func init() { rc.Add(rc.Call{ - Path: "core/stats", - Fn: rcRemoteStats, - Title: "Returns stats about current transfers.", + Path: "core/stats", + NoAuth: true, + Fn: rcRemoteStats, + Title: "Returns stats about current transfers.", Help: ` This returns all available stats: @@ -150,9 +152,10 @@ func rcTransferredStats(ctx context.Context, in rc.Params) (rc.Params, error) { func init() { rc.Add(rc.Call{ - Path: "core/transferred", - Fn: rcTransferredStats, - Title: "Returns stats about completed transfers.", + Path: "core/transferred", + NoAuth: true, + Fn: rcTransferredStats, + Title: "Returns stats about completed transfers.", Help: ` This returns stats about completed transfers: diff --git a/fs/config/rc.go b/fs/config/rc.go index 78c33ee5d..1f8e1b1d0 100644 --- a/fs/config/rc.go +++ b/fs/config/rc.go @@ -11,10 +11,9 @@ import ( func init() { rc.Add(rc.Call{ - Path: "config/unlock", - Fn: rcConfigPassword, - Title: "Unlock the config file.", - AuthRequired: true, + Path: "config/unlock", + Fn: rcConfigPassword, + Title: "Unlock the config file.", Help: ` Unlocks the config file if it is locked. @@ -46,10 +45,9 @@ func rcConfigPassword(ctx context.Context, in rc.Params) (out rc.Params, err err func init() { rc.Add(rc.Call{ - Path: "config/dump", - Fn: rcDump, - Title: "Dumps the config file.", - AuthRequired: true, + Path: "config/dump", + Fn: rcDump, + Title: "Dumps the config file.", Help: ` Returns a JSON object: - key: value @@ -68,10 +66,9 @@ func rcDump(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "config/get", - Fn: rcGet, - Title: "Get a remote in the config file.", - AuthRequired: true, + Path: "config/get", + Fn: rcGet, + Title: "Get a remote in the config file.", Help: ` Parameters: @@ -93,10 +90,9 @@ func rcGet(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "config/listremotes", - Fn: rcListRemotes, - Title: "Lists the remotes in the config file and defined in environment variables.", - AuthRequired: true, + Path: "config/listremotes", + Fn: rcListRemotes, + Title: "Lists the remotes in the config file and defined in environment variables.", Help: ` Returns - remotes - array of remote names @@ -121,10 +117,9 @@ func rcListRemotes(ctx context.Context, in rc.Params) (out rc.Params, err error) func init() { rc.Add(rc.Call{ - Path: "config/providers", - Fn: rcProviders, - Title: "Shows how providers are configured in the config file.", - AuthRequired: true, + Path: "config/providers", + Fn: rcProviders, + Title: "Shows how providers are configured in the config file.", Help: ` Returns a JSON object: - providers - array of objects @@ -166,8 +161,7 @@ func init() { ` } rc.Add(rc.Call{ - Path: "config/" + name, - AuthRequired: true, + Path: "config/" + name, Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) { return rcConfig(ctx, in, name) }, @@ -239,10 +233,9 @@ func rcConfig(ctx context.Context, in rc.Params, what string) (out rc.Params, er func init() { rc.Add(rc.Call{ - Path: "config/delete", - Fn: rcDelete, - Title: "Delete a remote in the config file.", - AuthRequired: true, + Path: "config/delete", + Fn: rcDelete, + Title: "Delete a remote in the config file.", Help: ` Parameters: @@ -265,10 +258,9 @@ func rcDelete(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "config/setpath", - Fn: rcSetPath, - Title: "Set the path of the config file", - AuthRequired: true, + Path: "config/setpath", + Fn: rcSetPath, + Title: "Set the path of the config file", Help: ` Parameters: @@ -289,10 +281,9 @@ func rcSetPath(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "config/paths", - Fn: rcPaths, - Title: "Reads the config file path and other important paths.", - AuthRequired: true, + Path: "config/paths", + Fn: rcPaths, + Title: "Reads the config file path and other important paths.", Help: ` Returns a JSON object with the following keys: diff --git a/fs/operations/rc.go b/fs/operations/rc.go index cb2eb4fe4..27a8d5c9e 100644 --- a/fs/operations/rc.go +++ b/fs/operations/rc.go @@ -21,10 +21,9 @@ import ( func init() { rc.Add(rc.Call{ - Path: "operations/list", - AuthRequired: true, - Fn: rcList, - Title: "List the given remote and path in JSON format", + Path: "operations/list", + Fn: rcList, + Title: "List the given remote and path in JSON format", Help: `This takes the following parameters: - fs - a remote name string e.g. "drive:" @@ -77,10 +76,9 @@ func rcList(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "operations/stat", - AuthRequired: true, - Fn: rcStat, - Title: "Give information about the supplied file or directory", + Path: "operations/stat", + Fn: rcStat, + Title: "Give information about the supplied file or directory", Help: `This takes the following parameters - fs - a remote name string eg "drive:" @@ -122,10 +120,9 @@ func rcStat(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "operations/about", - AuthRequired: true, - Fn: rcAbout, - Title: "Return the space used on the remote", + Path: "operations/about", + Fn: rcAbout, + Title: "Return the space used on the remote", Help: `This takes the following parameters: - fs - a remote name string e.g. "drive:" @@ -165,8 +162,7 @@ func init() { name = "Copy" } rc.Add(rc.Call{ - Path: "operations/" + strings.ToLower(name) + "file", - AuthRequired: true, + Path: "operations/" + strings.ToLower(name) + "file", Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) { return rcMoveOrCopyFile(ctx, in, copy) }, @@ -225,7 +221,6 @@ func init() { } rc.Add(rc.Call{ Path: "operations/" + op.name, - AuthRequired: true, NeedsRequest: op.needsRequest, Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) { return rcSingleCommand(ctx, in, op.name, op.noRemote) @@ -349,10 +344,9 @@ func rcSingleCommand(ctx context.Context, in rc.Params, name string, noRemote bo func init() { rc.Add(rc.Call{ - Path: "operations/size", - AuthRequired: true, - Fn: rcSize, - Title: "Count the number of bytes and files in remote", + Path: "operations/size", + Fn: rcSize, + Title: "Count the number of bytes and files in remote", Help: `This takes the following parameters: - fs - a remote name string e.g. "drive:path/to/dir" @@ -386,10 +380,9 @@ func rcSize(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "operations/publiclink", - AuthRequired: true, - Fn: rcPublicLink, - Title: "Create or retrieve a public link to the given file or folder.", + Path: "operations/publiclink", + Fn: rcPublicLink, + Title: "Create or retrieve a public link to the given file or folder.", Help: `This takes the following parameters: - fs - a remote name string e.g. "drive:" @@ -430,10 +423,9 @@ func rcPublicLink(ctx context.Context, in rc.Params) (out rc.Params, err error) func init() { rc.Add(rc.Call{ - Path: "operations/fsinfo", - AuthRequired: true, - Fn: rcFsInfo, - Title: "Return information about the remote", + Path: "operations/fsinfo", + Fn: rcFsInfo, + Title: "Return information about the remote", Help: `This takes the following parameters: - fs - a remote name string e.g. "drive:" @@ -566,10 +558,9 @@ func rcFsInfo(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "backend/command", - AuthRequired: true, - Fn: rcBackend, - Title: "Runs a backend command.", + Path: "backend/command", + Fn: rcBackend, + Title: "Runs a backend command.", Help: `This takes the following parameters: - command - a string with the command name @@ -652,9 +643,10 @@ func rcBackend(ctx context.Context, in rc.Params) (out rc.Params, err error) { // to a circular dependency on config. func init() { rc.Add(rc.Call{ - Path: "core/du", - Fn: rcDu, - Title: "Returns disk usage of a locally attached disk.", + Path: "core/du", + NoAuth: true, + Fn: rcDu, + Title: "Returns disk usage of a locally attached disk.", Help: ` This returns the disk usage for the local directory passed in as dir. @@ -700,10 +692,9 @@ func rcDu(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "operations/check", - AuthRequired: true, - Fn: rcCheck, - Title: "check the source and destination are the same", + Path: "operations/check", + Fn: rcCheck, + Title: "check the source and destination are the same", Help: `Checks the files in the source and destination match. It compares sizes and hashes and logs a report of files that don't match. It doesn't alter the source or destination. @@ -875,10 +866,9 @@ func rcCheck(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "operations/hashsum", - AuthRequired: true, - Fn: rcHashsum, - Title: "Produces a hashsum file for all the objects in the path.", + Path: "operations/hashsum", + Fn: rcHashsum, + Title: "Produces a hashsum file for all the objects in the path.", Help: `Produces a hash file for all the objects in the path using the hash named. The output is in the same format as the standard md5sum/sha1sum tool. @@ -957,10 +947,9 @@ func rcHashsum(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "operations/hashsumfile", - AuthRequired: true, - Fn: rcHashsumFile, - Title: "Produces a hash for a single file.", + Path: "operations/hashsumfile", + Fn: rcHashsumFile, + Title: "Produces a hash for a single file.", Help: `Produces a hash for a single file using the hash named. This takes the following parameters: diff --git a/fs/rc/cache.go b/fs/rc/cache.go index 6ed5e848b..4891e2259 100644 --- a/fs/rc/cache.go +++ b/fs/rc/cache.go @@ -133,10 +133,9 @@ func GetFsAndRemote(ctx context.Context, in Params) (f fs.Fs, remote string, err func init() { Add(Call{ - Path: "fscache/clear", - Fn: rcCacheClear, - Title: "Clear the Fs cache.", - AuthRequired: true, + Path: "fscache/clear", + Fn: rcCacheClear, + Title: "Clear the Fs cache.", Help: ` This clears the fs cache. This is where remotes created from backends are cached for a short while to make repeated rc calls more efficient. @@ -156,10 +155,9 @@ func rcCacheClear(ctx context.Context, in Params) (out Params, err error) { func init() { Add(Call{ - Path: "fscache/entries", - Fn: rcCacheEntries, - Title: "Returns the number of entries in the fs cache.", - AuthRequired: true, + Path: "fscache/entries", + Fn: rcCacheEntries, + Title: "Returns the number of entries in the fs cache.", Help: ` This returns the number of entries in the fs cache. diff --git a/fs/rc/config.go b/fs/rc/config.go index 65da945b6..7aa0c9fed 100644 --- a/fs/rc/config.go +++ b/fs/rc/config.go @@ -146,10 +146,9 @@ func rcOptionsLocal(ctx context.Context, in Params) (out Params, err error) { func init() { Add(Call{ - Path: "options/set", - AuthRequired: true, - Fn: rcOptionsSet, - Title: "Set an option", + Path: "options/set", + Fn: rcOptionsSet, + Title: "Set an option", Help: `Parameters: - option block name containing an object with diff --git a/fs/rc/internal.go b/fs/rc/internal.go index 93423dcf9..b32e155d6 100644 --- a/fs/rc/internal.go +++ b/fs/rc/internal.go @@ -23,19 +23,19 @@ import ( func init() { Add(Call{ - Path: "rc/noopauth", - AuthRequired: true, - Fn: rcNoop, - Title: "Echo the input to the output parameters requiring auth", + Path: "rc/noopauth", + Fn: rcNoop, + Title: "Echo the input to the output parameters requiring auth", Help: ` This echoes the input parameters to the output parameters for testing purposes. It can be used to check that rclone is still alive and to check that parameter passing is working properly.`, }) Add(Call{ - Path: "rc/noop", - Fn: rcNoop, - Title: "Echo the input to the output parameters", + Path: "rc/noop", + NoAuth: true, + Fn: rcNoop, + Title: "Echo the input to the output parameters", Help: ` This echoes the input parameters to the output parameters for testing purposes. It can be used to check that rclone is still alive and to @@ -50,9 +50,10 @@ func rcNoop(ctx context.Context, in Params) (out Params, err error) { func init() { Add(Call{ - Path: "rc/error", - Fn: rcError, - Title: "This returns an error", + Path: "rc/error", + NoAuth: true, + Fn: rcError, + Title: "This returns an error", Help: ` This returns an error with the input as part of its error string. Useful for testing error handling.`, @@ -99,9 +100,10 @@ func rcFatal(ctx context.Context, in Params) (out Params, err error) { func init() { Add(Call{ - Path: "rc/list", - Fn: rcList, - Title: "List all the registered remote control commands", + Path: "rc/list", + NoAuth: true, + Fn: rcList, + Title: "List all the registered remote control commands", Help: ` This lists all the registered remote control commands as a JSON map in the commands response.`, @@ -201,9 +203,10 @@ func rcGc(ctx context.Context, in Params) (out Params, err error) { func init() { Add(Call{ - Path: "core/version", - Fn: rcVersion, - Title: "Shows the current version of rclone, Go and the OS.", + Path: "core/version", + NoAuth: true, + Fn: rcVersion, + Title: "Shows the current version of rclone, Go and the OS.", Help: ` This shows the current versions of rclone, Go and the OS: @@ -480,7 +483,6 @@ func rcSetGCPercent(ctx context.Context, in Params) (out Params, err error) { func init() { Add(Call{ Path: "core/command", - AuthRequired: true, Fn: rcRunCommand, NeedsRequest: true, NeedsResponse: true, diff --git a/fs/rc/jobs/job.go b/fs/rc/jobs/job.go index e0a955efd..2497764ca 100644 --- a/fs/rc/jobs/job.go +++ b/fs/rc/jobs/job.go @@ -375,9 +375,10 @@ func GetJobID(ctx context.Context) (jobID int64, ok bool) { func init() { rc.Add(rc.Call{ - Path: "job/status", - Fn: rcJobStatus, - Title: "Reads the status of the job ID", + Path: "job/status", + NoAuth: true, + Fn: rcJobStatus, + Title: "Reads the status of the job ID", Help: `Parameters: - jobid - id of the job (integer). @@ -421,9 +422,10 @@ func rcJobStatus(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "job/list", - Fn: rcJobList, - Title: "Lists the IDs of the running jobs", + Path: "job/list", + NoAuth: true, + Fn: rcJobList, + Title: "Lists the IDs of the running jobs", Help: `Parameters: None. Results: @@ -588,10 +590,9 @@ func NewJobFromBytes(ctx context.Context, inBuf []byte) (outBuf []byte) { func init() { rc.Add(rc.Call{ - Path: "job/batch", - AuthRequired: true, // require auth always since sub commands may require it - Fn: rcBatch, - Title: "Run a batch of rclone rc commands concurrently.", + Path: "job/batch", + Fn: rcBatch, + Title: "Run a batch of rclone rc commands concurrently.", Help: strings.ReplaceAll(` This takes the following parameters: diff --git a/fs/rc/rc.go b/fs/rc/rc.go index 0442bd50d..ce58f1076 100644 --- a/fs/rc/rc.go +++ b/fs/rc/rc.go @@ -110,7 +110,7 @@ type Options struct { Files string `config:"rc_files"` // set to enable serving files locally Serve bool `config:"rc_serve"` // set to serve files from remotes ServeNoModTime bool `config:"rc_serve_no_modtime"` // don't read the modification time - NoAuth bool `config:"rc_no_auth"` // set to disable auth checks on AuthRequired methods + NoAuth bool `config:"rc_no_auth"` // set to disable auth checks on methods which require it WebUI bool `config:"rc_web_gui"` // set to launch the web ui WebGUIUpdate bool `config:"rc_web_gui_update"` // set to check new update WebGUIForceUpdate bool `config:"rc_web_gui_force_update"` // set to force download new update diff --git a/fs/rc/rcserver/rcserver.go b/fs/rc/rcserver/rcserver.go index 9c00afe95..6be026e18 100644 --- a/fs/rc/rcserver/rcserver.go +++ b/fs/rc/rcserver/rcserver.go @@ -265,7 +265,7 @@ func (s *Server) handlePost(w http.ResponseWriter, r *http.Request, path string) } // Check to see if it requires authorisation - if !s.noAuth && call.AuthRequired && !s.server.UsingAuth() { + if !s.noAuth && !call.NoAuth && !s.server.UsingAuth() { writeError(path, in, w, fmt.Errorf("authentication must be set up on the rc server to use %q or the --rc-no-auth flag must be in use", path), http.StatusForbidden) return } diff --git a/fs/rc/rcserver/rcserver_test.go b/fs/rc/rcserver/rcserver_test.go index 673aa4e69..11b21d5f5 100644 --- a/fs/rc/rcserver/rcserver_test.go +++ b/fs/rc/rcserver/rcserver_test.go @@ -403,11 +403,17 @@ func TestRC(t *testing.T) { } `, }, { - Name: "core-gc", - URL: "core/gc", // returns nil, nil so check it is made into {} - Method: "POST", - Status: http.StatusOK, - Expected: "{}\n", + Name: "core-gc", + URL: "core/gc", // now requires auth + Method: "POST", + Status: http.StatusForbidden, + Expected: `{ + "error": "authentication must be set up on the rc server to use \"core/gc\" or the --rc-no-auth flag must be in use", + "input": {}, + "path": "core/gc", + "status": 403 +} +`, }, { Name: "url-params", URL: "rc/noop?param1=potato¶m2=sausage", diff --git a/fs/rc/registry.go b/fs/rc/registry.go index 8cc11d526..8a0e9f511 100644 --- a/fs/rc/registry.go +++ b/fs/rc/registry.go @@ -18,7 +18,7 @@ type Call struct { Path string // path to activate this RC Fn Func `json:"-"` // function to call Title string // help for the function - AuthRequired bool // if set then this call requires authorisation to be set + NoAuth bool // if set then this call does not require authentication Help string // multi-line markdown formatted help NeedsRequest bool // if set then this call will be passed the original request object as _request NeedsResponse bool // if set then this call will be passed the original response object as _response diff --git a/fs/rc/webgui/rc.go b/fs/rc/webgui/rc.go index c3bada21f..66600174a 100644 --- a/fs/rc/webgui/rc.go +++ b/fs/rc/webgui/rc.go @@ -12,10 +12,9 @@ import ( func init() { rc.Add(rc.Call{ - Path: "pluginsctl/listTestPlugins", - AuthRequired: true, - Fn: rcListTestPlugins, - Title: "Show currently loaded test plugins", + Path: "pluginsctl/listTestPlugins", + Fn: rcListTestPlugins, + Title: "Show currently loaded test plugins", Help: `Allows listing of test plugins with the rclone.test set to true in package.json of the plugin. This takes no parameters and returns: @@ -41,10 +40,9 @@ func rcListTestPlugins(_ context.Context, _ rc.Params) (out rc.Params, err error func init() { rc.Add(rc.Call{ - Path: "pluginsctl/removeTestPlugin", - AuthRequired: true, - Fn: rcRemoveTestPlugin, - Title: "Remove a test plugin", + Path: "pluginsctl/removeTestPlugin", + Fn: rcRemoveTestPlugin, + Title: "Remove a test plugin", Help: `This allows you to remove a plugin using it's name. This takes the following parameters: @@ -75,10 +73,9 @@ func rcRemoveTestPlugin(_ context.Context, in rc.Params) (out rc.Params, err err func init() { rc.Add(rc.Call{ - Path: "pluginsctl/addPlugin", - AuthRequired: true, - Fn: rcAddPlugin, - Title: "Add a plugin using url", + Path: "pluginsctl/addPlugin", + Fn: rcAddPlugin, + Title: "Add a plugin using url", Help: `Used for adding a plugin to the webgui. This takes the following parameters: @@ -185,10 +182,9 @@ func rcAddPlugin(_ context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "pluginsctl/listPlugins", - AuthRequired: true, - Fn: rcGetPlugins, - Title: "Get the list of currently loaded plugins", + Path: "pluginsctl/listPlugins", + Fn: rcGetPlugins, + Title: "Get the list of currently loaded plugins", Help: `This allows you to get the currently enabled plugins and their details. This takes no parameters and returns: @@ -220,10 +216,9 @@ func rcGetPlugins(_ context.Context, _ rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "pluginsctl/removePlugin", - AuthRequired: true, - Fn: rcRemovePlugin, - Title: "Remove a loaded plugin", + Path: "pluginsctl/removePlugin", + Fn: rcRemovePlugin, + Title: "Remove a loaded plugin", Help: `This allows you to remove a plugin using it's name. This takes parameters: @@ -256,10 +251,9 @@ func rcRemovePlugin(_ context.Context, in rc.Params) (out rc.Params, err error) func init() { rc.Add(rc.Call{ - Path: "pluginsctl/getPluginsForType", - AuthRequired: true, - Fn: rcGetPluginsForType, - Title: "Get plugins with type criteria", + Path: "pluginsctl/getPluginsForType", + Fn: rcGetPluginsForType, + Title: "Get plugins with type criteria", Help: `This shows all possible plugins by a mime type. This takes the following parameters: diff --git a/fs/sync/rc.go b/fs/sync/rc.go index 6577e498b..52a2626e8 100644 --- a/fs/sync/rc.go +++ b/fs/sync/rc.go @@ -13,8 +13,7 @@ func init() { moveHelp = "- deleteEmptySrcDirs - delete empty src directories if set\n" } rc.Add(rc.Call{ - Path: "sync/" + name, - AuthRequired: true, + Path: "sync/" + name, Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) { return rcSyncCopyMove(ctx, in, name) }, diff --git a/vfs/rc.go b/vfs/rc.go index 186a2cb9d..02aff0c17 100644 --- a/vfs/rc.go +++ b/vfs/rc.go @@ -361,8 +361,9 @@ func rcPollInterval(ctx context.Context, in rc.Params) (out rc.Params, err error func init() { rc.Add(rc.Call{ - Path: "vfs/list", - Title: "List active VFSes.", + Path: "vfs/list", + NoAuth: true, + Title: "List active VFSes.", Help: ` This lists the active VFSes. @@ -393,8 +394,9 @@ func rcList(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "vfs/stats", - Title: "Stats for a VFS.", + Path: "vfs/stats", + NoAuth: true, + Title: "Stats for a VFS.", Help: ` This returns stats for the selected VFS. @@ -441,8 +443,9 @@ func rcStats(ctx context.Context, in rc.Params) (out rc.Params, err error) { func init() { rc.Add(rc.Call{ - Path: "vfs/queue", - Title: "Queue info for a VFS.", + Path: "vfs/queue", + NoAuth: true, + Title: "Queue info for a VFS.", Help: strings.ReplaceAll(` This returns info about the upload queue for the selected VFS.