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
This commit is contained in:
Nick Craig-Wood
2026-04-19 13:31:27 +01:00
parent c5df1ddf4b
commit f191448b0d
20 changed files with 194 additions and 221 deletions
+4 -3
View File
@@ -563,9 +563,10 @@ Eg
}) })
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "cache/stats", Path: "cache/stats",
Fn: f.httpStats, NoAuth: true,
Title: "Get cache stats", Fn: f.httpStats,
Title: "Get cache stats",
Help: ` Help: `
Show statistics for the cache remote. Show statistics for the cache remote.
`, `,
@@ -4,4 +4,4 @@
//go:build plan9 || solaris //go:build plan9 || solaris
// Package iclouddrive implements the iCloud Drive backend // Package iclouddrive implements the iCloud Drive backend
package iclouddrive package iclouddrive
+4 -5
View File
@@ -18,11 +18,10 @@ import (
func addRC() { func addRC() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "sync/bisync", Path: "sync/bisync",
AuthRequired: true, Fn: rcBisync,
Fn: rcBisync, Title: shortHelp,
Title: shortHelp, Help: rcHelp,
Help: rcHelp,
}) })
} }
+15 -20
View File
@@ -46,10 +46,9 @@ func AddRc(mountUtilName string, mountFunction MountFn) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "mount/mount", Path: "mount/mount",
AuthRequired: true, Fn: mountRc,
Fn: mountRc, Title: "Create a new mount point",
Title: "Create a new mount point",
Help: `rclone allows Linux, FreeBSD, macOS and Windows to mount any of Help: `rclone allows Linux, FreeBSD, macOS and Windows to mount any of
Rclone's cloud storage systems as a file system with FUSE. 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "mount/unmount", Path: "mount/unmount",
AuthRequired: true, Fn: unMountRc,
Fn: unMountRc, Title: "Unmount selected active mount",
Title: "Unmount selected active mount",
Help: ` Help: `
rclone allows Linux, FreeBSD, macOS and Windows to rclone allows Linux, FreeBSD, macOS and Windows to
mount any of Rclone's cloud storage systems as a file system with 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "mount/types", Path: "mount/types",
AuthRequired: true, Fn: mountTypesRc,
Fn: mountTypesRc, Title: "Show all possible mount types",
Title: "Show all possible mount types",
Help: `This shows all possible mount types and returns them as a list. Help: `This shows all possible mount types and returns them as a list.
This takes no parameters and returns This takes no parameters and returns
@@ -224,10 +221,9 @@ func mountTypesRc(_ context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "mount/listmounts", Path: "mount/listmounts",
AuthRequired: true, Fn: listMountsRc,
Fn: listMountsRc, Title: "Show current mount points",
Title: "Show current mount points",
Help: `This shows currently mounted points, which can be used for performing an unmount. Help: `This shows currently mounted points, which can be used for performing an unmount.
This takes no parameters and returns This takes no parameters and returns
@@ -274,10 +270,9 @@ func listMountsRc(_ context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "mount/unmountall", Path: "mount/unmountall",
AuthRequired: true, Fn: unmountAll,
Fn: unmountAll, Title: "Unmount all active mounts",
Title: "Unmount all active mounts",
Help: ` Help: `
rclone allows Linux, FreeBSD, macOS and Windows to rclone allows Linux, FreeBSD, macOS and Windows to
mount any of Rclone's cloud storage systems as a file system with mount any of Rclone's cloud storage systems as a file system with
+2 -4
View File
@@ -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: %s {#%s}\n\n", info["Path"], info["Title"], strings.ReplaceAll(info["Path"].(string), "/", "-"))
fmt.Printf("%s\n\n", info["Help"]) fmt.Printf("%s\n\n", info["Help"])
if authRequired := info["AuthRequired"]; authRequired != nil { if noAuth, ok := info["NoAuth"]; ok && noAuth.(bool) {
if authRequired.(bool) { fmt.Printf("**Authentication is not required for this call.**\n\n")
fmt.Printf("**Authentication is required for this call.**\n\n")
}
} }
} }
return nil return nil
+15 -20
View File
@@ -67,10 +67,9 @@ func q(s string) string {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "serve/start", Path: "serve/start",
AuthRequired: true, Fn: startRc,
Fn: startRc, Title: "Create a new server",
Title: "Create a new server",
Help: q(`Create a new server with the specified parameters. Help: q(`Create a new server with the specified parameters.
This takes the following 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "serve/stop", Path: "serve/stop",
AuthRequired: true, Fn: stopRc,
Fn: stopRc, Title: "Unserve selected active serve",
Title: "Unserve selected active serve",
Help: q(`Stops a running |serve| instance by ID. Help: q(`Stops a running |serve| instance by ID.
This takes the following parameters: This takes the following parameters:
@@ -216,10 +214,9 @@ func stopRc(_ context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "serve/types", Path: "serve/types",
AuthRequired: true, Fn: serveTypesRc,
Fn: serveTypesRc, Title: "Show all possible serve types",
Title: "Show all possible serve types",
Help: q(`This shows all possible serve types and returns them as a list. Help: q(`This shows all possible serve types and returns them as a list.
This takes no parameters and returns This takes no parameters and returns
@@ -264,10 +261,9 @@ func serveTypesRc(_ context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "serve/list", Path: "serve/list",
AuthRequired: true, Fn: listRc,
Fn: listRc, Title: "Show running servers",
Title: "Show running servers",
Help: q(`Show running servers with IDs. Help: q(`Show running servers with IDs.
This takes no parameters and returns This takes no parameters and returns
@@ -328,10 +324,9 @@ func listRc(_ context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "serve/stopall", Path: "serve/stopall",
AuthRequired: true, Fn: stopAll,
Fn: stopAll, Title: "Stop all active servers",
Title: "Stop all active servers",
Help: q(`Stop all active servers. Help: q(`Stop all active servers.
This will stop all active servers. This will stop all active servers.
+12 -9
View File
@@ -29,9 +29,10 @@ func rcListStats(ctx context.Context, in rc.Params) (rc.Params, error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "core/group-list", Path: "core/group-list",
Fn: rcListStats, NoAuth: true,
Title: "Returns list of stats.", Fn: rcListStats,
Title: "Returns list of stats.",
Help: ` Help: `
This returns list of stats groups currently in memory. 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "core/stats", Path: "core/stats",
Fn: rcRemoteStats, NoAuth: true,
Title: "Returns stats about current transfers.", Fn: rcRemoteStats,
Title: "Returns stats about current transfers.",
Help: ` Help: `
This returns all available stats: This returns all available stats:
@@ -150,9 +152,10 @@ func rcTransferredStats(ctx context.Context, in rc.Params) (rc.Params, error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "core/transferred", Path: "core/transferred",
Fn: rcTransferredStats, NoAuth: true,
Title: "Returns stats about completed transfers.", Fn: rcTransferredStats,
Title: "Returns stats about completed transfers.",
Help: ` Help: `
This returns stats about completed transfers: This returns stats about completed transfers:
+25 -34
View File
@@ -11,10 +11,9 @@ import (
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "config/unlock", Path: "config/unlock",
Fn: rcConfigPassword, Fn: rcConfigPassword,
Title: "Unlock the config file.", Title: "Unlock the config file.",
AuthRequired: true,
Help: ` Help: `
Unlocks the config file if it is locked. 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "config/dump", Path: "config/dump",
Fn: rcDump, Fn: rcDump,
Title: "Dumps the config file.", Title: "Dumps the config file.",
AuthRequired: true,
Help: ` Help: `
Returns a JSON object: Returns a JSON object:
- key: value - key: value
@@ -68,10 +66,9 @@ func rcDump(ctx context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "config/get", Path: "config/get",
Fn: rcGet, Fn: rcGet,
Title: "Get a remote in the config file.", Title: "Get a remote in the config file.",
AuthRequired: true,
Help: ` Help: `
Parameters: Parameters:
@@ -93,10 +90,9 @@ func rcGet(ctx context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "config/listremotes", Path: "config/listremotes",
Fn: rcListRemotes, Fn: rcListRemotes,
Title: "Lists the remotes in the config file and defined in environment variables.", Title: "Lists the remotes in the config file and defined in environment variables.",
AuthRequired: true,
Help: ` Help: `
Returns Returns
- remotes - array of remote names - remotes - array of remote names
@@ -121,10 +117,9 @@ func rcListRemotes(ctx context.Context, in rc.Params) (out rc.Params, err error)
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "config/providers", Path: "config/providers",
Fn: rcProviders, Fn: rcProviders,
Title: "Shows how providers are configured in the config file.", Title: "Shows how providers are configured in the config file.",
AuthRequired: true,
Help: ` Help: `
Returns a JSON object: Returns a JSON object:
- providers - array of objects - providers - array of objects
@@ -166,8 +161,7 @@ func init() {
` `
} }
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "config/" + name, Path: "config/" + name,
AuthRequired: true,
Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) { Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) {
return rcConfig(ctx, in, name) 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "config/delete", Path: "config/delete",
Fn: rcDelete, Fn: rcDelete,
Title: "Delete a remote in the config file.", Title: "Delete a remote in the config file.",
AuthRequired: true,
Help: ` Help: `
Parameters: Parameters:
@@ -265,10 +258,9 @@ func rcDelete(ctx context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "config/setpath", Path: "config/setpath",
Fn: rcSetPath, Fn: rcSetPath,
Title: "Set the path of the config file", Title: "Set the path of the config file",
AuthRequired: true,
Help: ` Help: `
Parameters: Parameters:
@@ -289,10 +281,9 @@ func rcSetPath(ctx context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "config/paths", Path: "config/paths",
Fn: rcPaths, Fn: rcPaths,
Title: "Reads the config file path and other important paths.", Title: "Reads the config file path and other important paths.",
AuthRequired: true,
Help: ` Help: `
Returns a JSON object with the following keys: Returns a JSON object with the following keys:
+35 -46
View File
@@ -21,10 +21,9 @@ import (
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/list", Path: "operations/list",
AuthRequired: true, Fn: rcList,
Fn: rcList, Title: "List the given remote and path in JSON format",
Title: "List the given remote and path in JSON format",
Help: `This takes the following parameters: Help: `This takes the following parameters:
- fs - a remote name string e.g. "drive:" - 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/stat", Path: "operations/stat",
AuthRequired: true, Fn: rcStat,
Fn: rcStat, Title: "Give information about the supplied file or directory",
Title: "Give information about the supplied file or directory",
Help: `This takes the following parameters Help: `This takes the following parameters
- fs - a remote name string eg "drive:" - 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/about", Path: "operations/about",
AuthRequired: true, Fn: rcAbout,
Fn: rcAbout, Title: "Return the space used on the remote",
Title: "Return the space used on the remote",
Help: `This takes the following parameters: Help: `This takes the following parameters:
- fs - a remote name string e.g. "drive:" - fs - a remote name string e.g. "drive:"
@@ -165,8 +162,7 @@ func init() {
name = "Copy" name = "Copy"
} }
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/" + strings.ToLower(name) + "file", Path: "operations/" + strings.ToLower(name) + "file",
AuthRequired: true,
Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) { Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) {
return rcMoveOrCopyFile(ctx, in, copy) return rcMoveOrCopyFile(ctx, in, copy)
}, },
@@ -225,7 +221,6 @@ func init() {
} }
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/" + op.name, Path: "operations/" + op.name,
AuthRequired: true,
NeedsRequest: op.needsRequest, NeedsRequest: op.needsRequest,
Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) { Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) {
return rcSingleCommand(ctx, in, op.name, op.noRemote) 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/size", Path: "operations/size",
AuthRequired: true, Fn: rcSize,
Fn: rcSize, Title: "Count the number of bytes and files in remote",
Title: "Count the number of bytes and files in remote",
Help: `This takes the following parameters: Help: `This takes the following parameters:
- fs - a remote name string e.g. "drive:path/to/dir" - 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/publiclink", Path: "operations/publiclink",
AuthRequired: true, Fn: rcPublicLink,
Fn: rcPublicLink, Title: "Create or retrieve a public link to the given file or folder.",
Title: "Create or retrieve a public link to the given file or folder.",
Help: `This takes the following parameters: Help: `This takes the following parameters:
- fs - a remote name string e.g. "drive:" - 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/fsinfo", Path: "operations/fsinfo",
AuthRequired: true, Fn: rcFsInfo,
Fn: rcFsInfo, Title: "Return information about the remote",
Title: "Return information about the remote",
Help: `This takes the following parameters: Help: `This takes the following parameters:
- fs - a remote name string e.g. "drive:" - 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "backend/command", Path: "backend/command",
AuthRequired: true, Fn: rcBackend,
Fn: rcBackend, Title: "Runs a backend command.",
Title: "Runs a backend command.",
Help: `This takes the following parameters: Help: `This takes the following parameters:
- command - a string with the command name - 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. // to a circular dependency on config.
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "core/du", Path: "core/du",
Fn: rcDu, NoAuth: true,
Title: "Returns disk usage of a locally attached disk.", Fn: rcDu,
Title: "Returns disk usage of a locally attached disk.",
Help: ` Help: `
This returns the disk usage for the local directory passed in as dir. 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/check", Path: "operations/check",
AuthRequired: true, Fn: rcCheck,
Fn: rcCheck, Title: "check the source and destination are the same",
Title: "check the source and destination are the same",
Help: `Checks the files in the source and destination match. It compares Help: `Checks the files in the source and destination match. It compares
sizes and hashes and logs a report of files that don't sizes and hashes and logs a report of files that don't
match. It doesn't alter the source or destination. 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/hashsum", Path: "operations/hashsum",
AuthRequired: true, Fn: rcHashsum,
Fn: rcHashsum, Title: "Produces a hashsum file for all the objects in the path.",
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 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 named. The output is in the same format as the standard
md5sum/sha1sum tool. md5sum/sha1sum tool.
@@ -957,10 +947,9 @@ func rcHashsum(ctx context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "operations/hashsumfile", Path: "operations/hashsumfile",
AuthRequired: true, Fn: rcHashsumFile,
Fn: rcHashsumFile, Title: "Produces a hash for a single file.",
Title: "Produces a hash for a single file.",
Help: `Produces a hash for a single file using the hash named. Help: `Produces a hash for a single file using the hash named.
This takes the following parameters: This takes the following parameters:
+6 -8
View File
@@ -133,10 +133,9 @@ func GetFsAndRemote(ctx context.Context, in Params) (f fs.Fs, remote string, err
func init() { func init() {
Add(Call{ Add(Call{
Path: "fscache/clear", Path: "fscache/clear",
Fn: rcCacheClear, Fn: rcCacheClear,
Title: "Clear the Fs cache.", Title: "Clear the Fs cache.",
AuthRequired: true,
Help: ` Help: `
This clears the fs cache. This is where remotes created from backends 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. 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() { func init() {
Add(Call{ Add(Call{
Path: "fscache/entries", Path: "fscache/entries",
Fn: rcCacheEntries, Fn: rcCacheEntries,
Title: "Returns the number of entries in the fs cache.", Title: "Returns the number of entries in the fs cache.",
AuthRequired: true,
Help: ` Help: `
This returns the number of entries in the fs cache. This returns the number of entries in the fs cache.
+3 -4
View File
@@ -146,10 +146,9 @@ func rcOptionsLocal(ctx context.Context, in Params) (out Params, err error) {
func init() { func init() {
Add(Call{ Add(Call{
Path: "options/set", Path: "options/set",
AuthRequired: true, Fn: rcOptionsSet,
Fn: rcOptionsSet, Title: "Set an option",
Title: "Set an option",
Help: `Parameters: Help: `Parameters:
- option block name containing an object with - option block name containing an object with
+19 -17
View File
@@ -23,19 +23,19 @@ import (
func init() { func init() {
Add(Call{ Add(Call{
Path: "rc/noopauth", Path: "rc/noopauth",
AuthRequired: true, Fn: rcNoop,
Fn: rcNoop, Title: "Echo the input to the output parameters requiring auth",
Title: "Echo the input to the output parameters requiring auth",
Help: ` Help: `
This echoes the input parameters to the output parameters for testing 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 purposes. It can be used to check that rclone is still alive and to
check that parameter passing is working properly.`, check that parameter passing is working properly.`,
}) })
Add(Call{ Add(Call{
Path: "rc/noop", Path: "rc/noop",
Fn: rcNoop, NoAuth: true,
Title: "Echo the input to the output parameters", Fn: rcNoop,
Title: "Echo the input to the output parameters",
Help: ` Help: `
This echoes the input parameters to the output parameters for testing 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 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() { func init() {
Add(Call{ Add(Call{
Path: "rc/error", Path: "rc/error",
Fn: rcError, NoAuth: true,
Title: "This returns an error", Fn: rcError,
Title: "This returns an error",
Help: ` Help: `
This returns an error with the input as part of its error string. This returns an error with the input as part of its error string.
Useful for testing error handling.`, Useful for testing error handling.`,
@@ -99,9 +100,10 @@ func rcFatal(ctx context.Context, in Params) (out Params, err error) {
func init() { func init() {
Add(Call{ Add(Call{
Path: "rc/list", Path: "rc/list",
Fn: rcList, NoAuth: true,
Title: "List all the registered remote control commands", Fn: rcList,
Title: "List all the registered remote control commands",
Help: ` Help: `
This lists all the registered remote control commands as a JSON map in This lists all the registered remote control commands as a JSON map in
the commands response.`, the commands response.`,
@@ -201,9 +203,10 @@ func rcGc(ctx context.Context, in Params) (out Params, err error) {
func init() { func init() {
Add(Call{ Add(Call{
Path: "core/version", Path: "core/version",
Fn: rcVersion, NoAuth: true,
Title: "Shows the current version of rclone, Go and the OS.", Fn: rcVersion,
Title: "Shows the current version of rclone, Go and the OS.",
Help: ` Help: `
This shows the current versions of rclone, Go and the OS: 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() { func init() {
Add(Call{ Add(Call{
Path: "core/command", Path: "core/command",
AuthRequired: true,
Fn: rcRunCommand, Fn: rcRunCommand,
NeedsRequest: true, NeedsRequest: true,
NeedsResponse: true, NeedsResponse: true,
+11 -10
View File
@@ -375,9 +375,10 @@ func GetJobID(ctx context.Context) (jobID int64, ok bool) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "job/status", Path: "job/status",
Fn: rcJobStatus, NoAuth: true,
Title: "Reads the status of the job ID", Fn: rcJobStatus,
Title: "Reads the status of the job ID",
Help: `Parameters: Help: `Parameters:
- jobid - id of the job (integer). - 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "job/list", Path: "job/list",
Fn: rcJobList, NoAuth: true,
Title: "Lists the IDs of the running jobs", Fn: rcJobList,
Title: "Lists the IDs of the running jobs",
Help: `Parameters: None. Help: `Parameters: None.
Results: Results:
@@ -588,10 +590,9 @@ func NewJobFromBytes(ctx context.Context, inBuf []byte) (outBuf []byte) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "job/batch", Path: "job/batch",
AuthRequired: true, // require auth always since sub commands may require it Fn: rcBatch,
Fn: rcBatch, Title: "Run a batch of rclone rc commands concurrently.",
Title: "Run a batch of rclone rc commands concurrently.",
Help: strings.ReplaceAll(` Help: strings.ReplaceAll(`
This takes the following parameters: This takes the following parameters:
+1 -1
View File
@@ -110,7 +110,7 @@ type Options struct {
Files string `config:"rc_files"` // set to enable serving files locally Files string `config:"rc_files"` // set to enable serving files locally
Serve bool `config:"rc_serve"` // set to serve files from remotes Serve bool `config:"rc_serve"` // set to serve files from remotes
ServeNoModTime bool `config:"rc_serve_no_modtime"` // don't read the modification time 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 WebUI bool `config:"rc_web_gui"` // set to launch the web ui
WebGUIUpdate bool `config:"rc_web_gui_update"` // set to check new update 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 WebGUIForceUpdate bool `config:"rc_web_gui_force_update"` // set to force download new update
+1 -1
View File
@@ -265,7 +265,7 @@ func (s *Server) handlePost(w http.ResponseWriter, r *http.Request, path string)
} }
// Check to see if it requires authorisation // 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) 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 return
} }
+11 -5
View File
@@ -403,11 +403,17 @@ func TestRC(t *testing.T) {
} }
`, `,
}, { }, {
Name: "core-gc", Name: "core-gc",
URL: "core/gc", // returns nil, nil so check it is made into {} URL: "core/gc", // now requires auth
Method: "POST", Method: "POST",
Status: http.StatusOK, Status: http.StatusForbidden,
Expected: "{}\n", 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", Name: "url-params",
URL: "rc/noop?param1=potato&param2=sausage", URL: "rc/noop?param1=potato&param2=sausage",
+1 -1
View File
@@ -18,7 +18,7 @@ type Call struct {
Path string // path to activate this RC Path string // path to activate this RC
Fn Func `json:"-"` // function to call Fn Func `json:"-"` // function to call
Title string // help for the function 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 Help string // multi-line markdown formatted help
NeedsRequest bool // if set then this call will be passed the original request object as _request 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 NeedsResponse bool // if set then this call will be passed the original response object as _response
+18 -24
View File
@@ -12,10 +12,9 @@ import (
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "pluginsctl/listTestPlugins", Path: "pluginsctl/listTestPlugins",
AuthRequired: true, Fn: rcListTestPlugins,
Fn: rcListTestPlugins, Title: "Show currently loaded test plugins",
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. 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: This takes no parameters and returns:
@@ -41,10 +40,9 @@ func rcListTestPlugins(_ context.Context, _ rc.Params) (out rc.Params, err error
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "pluginsctl/removeTestPlugin", Path: "pluginsctl/removeTestPlugin",
AuthRequired: true, Fn: rcRemoveTestPlugin,
Fn: rcRemoveTestPlugin, Title: "Remove a test plugin",
Title: "Remove a test plugin",
Help: `This allows you to remove a plugin using it's name. Help: `This allows you to remove a plugin using it's name.
This takes the following parameters: This takes the following parameters:
@@ -75,10 +73,9 @@ func rcRemoveTestPlugin(_ context.Context, in rc.Params) (out rc.Params, err err
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "pluginsctl/addPlugin", Path: "pluginsctl/addPlugin",
AuthRequired: true, Fn: rcAddPlugin,
Fn: rcAddPlugin, Title: "Add a plugin using url",
Title: "Add a plugin using url",
Help: `Used for adding a plugin to the webgui. Help: `Used for adding a plugin to the webgui.
This takes the following parameters: This takes the following parameters:
@@ -185,10 +182,9 @@ func rcAddPlugin(_ context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "pluginsctl/listPlugins", Path: "pluginsctl/listPlugins",
AuthRequired: true, Fn: rcGetPlugins,
Fn: rcGetPlugins, Title: "Get the list of currently loaded plugins",
Title: "Get the list of currently loaded plugins",
Help: `This allows you to get the currently enabled plugins and their details. Help: `This allows you to get the currently enabled plugins and their details.
This takes no parameters and returns: This takes no parameters and returns:
@@ -220,10 +216,9 @@ func rcGetPlugins(_ context.Context, _ rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "pluginsctl/removePlugin", Path: "pluginsctl/removePlugin",
AuthRequired: true, Fn: rcRemovePlugin,
Fn: rcRemovePlugin, Title: "Remove a loaded plugin",
Title: "Remove a loaded plugin",
Help: `This allows you to remove a plugin using it's name. Help: `This allows you to remove a plugin using it's name.
This takes parameters: This takes parameters:
@@ -256,10 +251,9 @@ func rcRemovePlugin(_ context.Context, in rc.Params) (out rc.Params, err error)
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "pluginsctl/getPluginsForType", Path: "pluginsctl/getPluginsForType",
AuthRequired: true, Fn: rcGetPluginsForType,
Fn: rcGetPluginsForType, Title: "Get plugins with type criteria",
Title: "Get plugins with type criteria",
Help: `This shows all possible plugins by a mime type. Help: `This shows all possible plugins by a mime type.
This takes the following parameters: This takes the following parameters:
+1 -2
View File
@@ -13,8 +13,7 @@ func init() {
moveHelp = "- deleteEmptySrcDirs - delete empty src directories if set\n" moveHelp = "- deleteEmptySrcDirs - delete empty src directories if set\n"
} }
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "sync/" + name, Path: "sync/" + name,
AuthRequired: true,
Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) { Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) {
return rcSyncCopyMove(ctx, in, name) return rcSyncCopyMove(ctx, in, name)
}, },
+9 -6
View File
@@ -361,8 +361,9 @@ func rcPollInterval(ctx context.Context, in rc.Params) (out rc.Params, err error
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "vfs/list", Path: "vfs/list",
Title: "List active VFSes.", NoAuth: true,
Title: "List active VFSes.",
Help: ` Help: `
This lists the active VFSes. This lists the active VFSes.
@@ -393,8 +394,9 @@ func rcList(ctx context.Context, in rc.Params) (out rc.Params, err error) {
func init() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "vfs/stats", Path: "vfs/stats",
Title: "Stats for a VFS.", NoAuth: true,
Title: "Stats for a VFS.",
Help: ` Help: `
This returns stats for the selected VFS. 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() { func init() {
rc.Add(rc.Call{ rc.Add(rc.Call{
Path: "vfs/queue", Path: "vfs/queue",
Title: "Queue info for a VFS.", NoAuth: true,
Title: "Queue info for a VFS.",
Help: strings.ReplaceAll(` Help: strings.ReplaceAll(`
This returns info about the upload queue for the selected VFS. This returns info about the upload queue for the selected VFS.