Repository: owncloud/ocis
Pull request #4117 (2022-07-06 13:18:56)

escape DN attribute values
<!--
Thanks for submitting a change to ownCloud!

This is the bug tracker for the oCIS component. Find other components at https://github.com/owncloud/core/blob/master/.github/CONTRIBUTING.md#guidelines

For fixing potential security issues please see https://owncloud.org/security/

To make it possible for us to get your change reviewed and merged please carefully fill out the requested information below.

Please note that any kind of change needs first be submitted to the master branch which holds the next version of oCIS.

Please set the following labels:

- Set label "Status:Needs-Review" for review or "Status:In-Progress" if the PR still has open tasks.
- Assignment: assign to self
- Reviewers: pick at least one
-->

## Description
<!--- Describe your changes in detail -->
Escape the DN when creating a user or a group.

## Motivation and Context
<!--- Why is this change required? What problem does it solve? -->
The DN can contain characters which need to be escaped. Otherwise some subsequent steps which involve parsing the DN will fail.

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [x] Bug fix (non-breaking change which fixes an issue)

## Checklist:
<!-- Tick the checkboxes when done. -->
<!-- Raise documentation ticket in owncloud.github.io/ -->
- [x] Code changes
- [x] Unit tests added



Patch:
diff --git a/.drone.env b/.drone.env
index 9e5e56a077e..cec85600398 100644
--- a/.drone.env
+++ b/.drone.env
@@ -1,5 +1,5 @@
 # The test runner source for API tests
-CORE_COMMITID=15758a077c65fed9a72ed4238a8912a9e39f4547
+CORE_COMMITID=7e9caa446346426de197b475e03be19dfe367a54
 CORE_BRANCH=master
 
 # The test runner source for UI tests
diff --git a/.drone.star b/.drone.star
index c6c42b88602..08a480bedac 100644
--- a/.drone.star
+++ b/.drone.star
@@ -201,7 +201,6 @@ def main(ctx):
 
     test_pipelines = \
         cancelPreviousBuilds() + \
-        yarnCache(ctx) + \
         [buildOcisBinaryForTesting(ctx)] + \
         testOcisModules(ctx) + \
         testPipelines(ctx)
@@ -250,47 +249,6 @@ def main(ctx):
     pipelineSanityChecks(ctx, pipelines)
     return pipelines
 
-def yarnCache(ctx):
-    return [{
-        "kind": "pipeline",
-        "type": "docker",
-        "name": "cache-yarn",
-        "steps": skipIfUnchanged(ctx, "cache") +
-                 installWebTestRunner() +
-                 yarnInstallUITests() +
-                 rebuildBuildArtifactCache(ctx, "tests-yarn", "webTestRunner/tests/acceptance/.yarn"),
-        "trigger": {
-            "ref": [
-                "refs/heads/master",
-                "refs/tags/**",
-                "refs/pull/**",
-            ],
-        },
-    }]
-
-def installWebTestRunner():
-    return [{
-        "name": "install-web-test-runner",
-        "image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
-        "commands": [
-            ". /drone/src/.drone.env",
-            "git clone -b $WEB_BRANCH --single-branch --no-tags https://github.com/owncloud/web.git webTestRunner",
-        ],
-    }]
-
-def yarnInstallUITests():
-    return [{
-        "name": "yarn-install",
-        "image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
-        "commands": [
-            ". /drone/src/.drone.env",
-            "cd webTestRunner",
-            "git checkout $WEB_COMMITID",
-            "cd tests/acceptance/",
-            "yarn install --immutable",
-        ],
-    }]
-
 def testOcisModules(ctx):
     pipelines = []
     for module in config["modules"]:
@@ -745,35 +703,38 @@ def uiTestPipeline(ctx, filterTags, early_fail, runPart = 1, numberOfParts = 1,
             "os": "linux",
             "arch": "amd64",
         },
-        "steps": skipIfUnchanged(ctx, "acceptance-tests") + restoreBuildArtifactCache(ctx, "ocis-binary-amd64", "ocis/bin/ocis") + installWebTestRunner() +
-                 restoreBuildArtifactCache(ctx, "tests-yarn", "webTestRunner/tests/acceptance/.yarn") + yarnInstallUITests() +
-                 ocisServer(storage, accounts_hash_difficulty, [stepVolumeOC10Tests]) + waitForSeleniumService() + waitForMiddlewareService() +
-                 [
-                     {
-                         "name": "webUITests",
-                         "image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
-                         "environment": {
-                             "SERVER_HOST": "https://ocis-server:9200",
-                             "BACKEND_HOST": "https://ocis-server:9200",
-                             "RUN_ON_OCIS": "true",
-                             "OCIS_REVA_DATA_ROOT": "/srv/app/tmp/ocis/owncloud/data",
-                             "TESTING_DATA_DIR": "/srv/app/testing/data",
-                             "WEB_UI_CONFIG": "/drone/src/tests/config/drone/ocis-config.json",
-                             "TEST_TAGS": finalFilterTags,
-                             "LOCAL_UPLOAD_DIR": "/uploads",
-                             "NODE_TLS_REJECT_UNAUTHORIZED": 0,
-                             "RUN_PART": runPart,
-                             "DIVIDE_INTO_NUM_PARTS": numberOfParts,
-                             "EXPECTED_FAILURES_FILE": "/drone/src/tests/acceptance/expected-failures-webUI-on-%s-storage%s.md" % (storage.upper(), expectedFailuresFileFilterTags),
-                             "MIDDLEWARE_HOST": "http://middleware:3000",
-                         },
-                         "commands": [
-                             "git clone -b master --depth=1 https://github.com/owncloud/testing.git /srv/app/testing",
-                             "cd webTestRunner/tests/acceptance",
-                             "./run.sh",
-                         ],
-                     },
-                 ] + failEarly(ctx, early_fail),
+        "steps": skipIfUnchanged(ctx, "acceptance-tests") + restoreBuildArtifactCache(ctx, "ocis-binary-amd64", "ocis/bin/ocis") +
+                 ocisServer(storage, accounts_hash_difficulty, [stepVolumeOC10Tests]) + waitForSeleniumService() + waitForMiddlewareService() + [
+            {
+                "name": "webUITests",
+                "image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
+                "environment": {
+                    "SERVER_HOST": "https://ocis-server:9200",
+                    "BACKEND_HOST": "https://ocis-server:9200",
+                    "RUN_ON_OCIS": "true",
+                    "OCIS_REVA_DATA_ROOT": "/srv/app/tmp/ocis/owncloud/data",
+                    "TESTING_DATA_DIR": "/srv/app/testing/data",
+                    "WEB_UI_CONFIG": "/drone/src/tests/config/drone/ocis-config.json",
+                    "TEST_TAGS": finalFilterTags,
+                    "LOCAL_UPLOAD_DIR": "/uploads",
+                    "NODE_TLS_REJECT_UNAUTHORIZED": 0,
+                    "RUN_PART": runPart,
+                    "DIVIDE_INTO_NUM_PARTS": numberOfParts,
+                    "EXPECTED_FAILURES_FILE": "/drone/src/tests/acceptance/expected-failures-webUI-on-%s-storage%s.md" % (storage.upper(), expectedFailuresFileFilterTags),
+                    "MIDDLEWARE_HOST": "http://middleware:3000",
+                },
+                "commands": [
+                    ". /drone/src/.drone.env",
+                    "git clone -b master --depth=1 https://github.com/owncloud/testing.git /srv/app/testing",
+                    "git clone -b $WEB_BRANCH --single-branch --no-tags https://github.com/owncloud/web.git /srv/app/web",
+                    "cd /srv/app/web",
+                    "git checkout $WEB_COMMITID",
+                    "cd tests/acceptance/",
+                    "yarn install --immutable",
+                    "./run.sh",
+                ],
+            },
+        ] + failEarly(ctx, early_fail),
         "services": selenium() + middlewareService(),
         "volumes": [pipelineVolumeOC10Tests] +
                    [{
@@ -1841,8 +1802,7 @@ def skipIfUnchanged(ctx, type):
         skip = base + acceptance
     if type == "build-binary" or type == "build-docker" or type == "litmus":
         skip = base + unit + acceptance
-    if type == "cache":
-        skip = base
+
     if len(skip) == 0:
         return []
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index de9a920e081..dfac0ade36b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,7 +11,6 @@ The following sections list the changes for unreleased.
 * Bugfix - Remove static ocs user backend config: [#4077](https://github.com/owncloud/ocis/pull/4077)
 * Bugfix - Fix make sensitive config values in the proxy's debug server: [#4086](https://github.com/owncloud/ocis/pull/4086)
 * Bugfix - Fix startup error logging: [#4093](https://github.com/owncloud/ocis/pull/4093)
-* Bugfix - Polish search: [#4094](https://github.com/owncloud/ocis/pull/4094)
 * Bugfix - Store user passwords hashed in idm: [#3778](https://github.com/owncloud/ocis/issues/3778)
 * Enhancement - Add capability for alias links: [#3983](https://github.com/owncloud/ocis/issues/3983)
 * Enhancement - Update IdP UI: [#3493](https://github.com/owncloud/ocis/issues/3493)
@@ -64,13 +63,6 @@ The following sections list the changes for unreleased.
 
    https://github.com/owncloud/ocis/pull/4093
 
-* Bugfix - Polish search: [#4094](https://github.com/owncloud/ocis/pull/4094)
-
-   We improved the feedback when providing invalid search queries and added support for limiting
-   the number of results returned.
-
-   https://github.com/owncloud/ocis/pull/4094
-
 * Bugfix - Store user passwords hashed in idm: [#3778](https://github.com/owncloud/ocis/issues/3778)
 
    Support for hashing user passwords was added to libregraph/idm. The graph API will now set
diff --git a/changelog/unreleased/ldap-escape-dn.md b/changelog/unreleased/ldap-escape-dn.md
new file mode 100644
index 00000000000..78e38cd5fde
--- /dev/null
+++ b/changelog/unreleased/ldap-escape-dn.md
@@ -0,0 +1,6 @@
+Bugfix: Escape DN attribute value
+
+Escaped the DN attribute value on creating users and groups.
+
+
+https://github.com/owncloud/ocis/pull/4117
diff --git a/changelog/unreleased/polish-search.md b/changelog/unreleased/polish-search.md
deleted file mode 100644
index 5993a17795a..00000000000
--- a/changelog/unreleased/polish-search.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix: Polish search
-
-We improved the feedback when providing invalid search queries and added support for limiting the number of results returned.
-
-https://github.com/owncloud/ocis/pull/4094
diff --git a/docs/helpers/adoc-generator.go.tmpl b/docs/helpers/adoc-generator.go.tmpl
index d091b047768..775c17ec724 100644
--- a/docs/helpers/adoc-generator.go.tmpl
+++ b/docs/helpers/adoc-generator.go.tmpl
@@ -89,9 +89,9 @@ func GetAnnotatedVariables(s interface{}) []ConfigField {
 			}
 			v := fmt.Sprintf("%v", value.Interface())			
 			td := strings.Split(env, ";")
-			// re := regexp.MustCompile(`^(https?:\/\/)`)
-			// v = re.ReplaceAllString(v,"\\$1")
-			re := regexp.MustCompile(`(https?:\/\/)`)
+			re := regexp.MustCompile(`^(https?:\/\/)`)
+			v = re.ReplaceAllString(v,"\\$1")
+			re = regexp.MustCompile(`(https?:\/\/)`)
 			desc = re.ReplaceAllString(desc, "\\$1")
 			re = regexp.MustCompile(`(\|)`)
 			v = re.ReplaceAllString(v, "\\$1")
diff --git a/docs/templates/ADOC.tmpl b/docs/templates/ADOC.tmpl
index 0028eafa222..cf5ecf13d3b 100644
--- a/docs/templates/ADOC.tmpl
+++ b/docs/templates/ADOC.tmpl
@@ -13,10 +13,9 @@
 {{ end -}}
 `{{- $value }}` 
 {{- end }}
+| {{.Type}}
 a| [subs=-attributes]
-+{{.Type}}+
-a| [subs=-attributes]
-pass:[{{.DefaultValue}}]
+{{.DefaultValue}} 
 a| [subs=-attributes]
 {{.Description}}
 
diff --git a/go.mod b/go.mod
index 6322e825369..129bf44b56f 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/blevesearch/bleve_index_api v1.0.2
 	github.com/coreos/go-oidc/v3 v3.2.0
 	github.com/cs3org/go-cs3apis v0.0.0-20220512100524-551800f020d8
-	github.com/cs3org/reva/v2 v2.6.2-0.20220705085406-20c332e3da17
+	github.com/cs3org/reva/v2 v2.6.1
 	github.com/disintegration/imaging v1.6.2
 	github.com/ggwhite/go-masker v1.0.9
 	github.com/go-chi/chi/v5 v5.0.7
diff --git a/go.sum b/go.sum
index b2eb46bb949..e84dcd7997b 100644
--- a/go.sum
+++ b/go.sum
@@ -297,8 +297,6 @@ github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD9
 github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
 github.com/cs3org/reva/v2 v2.6.1 h1:iVJlbKwUbjeTq17zZ8XGtD86yM+L64oHQ24r1HjzsQM=
 github.com/cs3org/reva/v2 v2.6.1/go.mod h1:zAHqzr36X4lIalonDQeNbwrIXjn66C38lp5A+MTRS1c=
-github.com/cs3org/reva/v2 v2.6.2-0.20220705085406-20c332e3da17 h1:xSAhpna63GSOs5NYue83xVYh5PR9um1LQgTv3eBGz08=
-github.com/cs3org/reva/v2 v2.6.2-0.20220705085406-20c332e3da17/go.mod h1:zAHqzr36X4lIalonDQeNbwrIXjn66C38lp5A+MTRS1c=
 github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
 github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
 github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
diff --git a/ocis-pkg/config/config.go b/ocis-pkg/config/config.go
index 8e9319a44de..59b88543ace 100644
--- a/ocis-pkg/config/config.go
+++ b/ocis-pkg/config/config.go
@@ -65,7 +65,7 @@ type Config struct {
 
 	Registry          string               `yaml:"registry"`
 	TokenManager      *shared.TokenManager `yaml:"token_manager"`
-	MachineAuthAPIKey string               `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."`
+	MachineAuthAPIKey string               `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used for accessing the 'auth-machine' service to impersonate users."`
 	TransferSecret    string               `yaml:"transfer_secret" env:"STORAGE_TRANSFER_SECRET"`
 	SystemUserID      string               `yaml:"system_user_id" env:"OCIS_SYSTEM_USER_ID" desc:"ID of the oCIS storage-system system user. Admins need to set the ID for the storage-system system user in this config option which is then used to reference the user. Any reasonable long string is possible, preferably this would be an UUIDv4 format."`
 	SystemUserAPIKey  string               `yaml:"system_user_api_key" env:"OCIS_SYSTEM_USER_API_KEY" desc:"API key for the storage-system system user."`
diff --git a/ocis-pkg/ldap/ldap.go b/ocis-pkg/ldap/ldap.go
index 8eceaf3cb94..cfa452f1a5d 100644
--- a/ocis-pkg/ldap/ldap.go
+++ b/ocis-pkg/ldap/ldap.go
@@ -5,6 +5,7 @@ import (
 	"errors"
 	"io/ioutil"
 	"os"
+	"strings"
 	"time"
 
 	"github.com/owncloud/ocis/v2/ocis-pkg/log"
@@ -15,6 +16,20 @@ const (
 	caCheckSleep   = 2
 )
 
+var (
+	dnEscaper = strings.NewReplacer(
+		"\\", "\\\\",
+		",", "\\,",
+		"+", "\\+",
+		`"`, `\\"`,
+		"<", "\\<",
+		">", "\\>",
+		";", "\\;",
+		"=", "\\=",
+		"\000", "\\00",
+	)
+)
+
 func WaitForCA(log log.Logger, insecure bool, caCert string) error {
 	if !insecure && caCert != "" {
 		for i := 0; i < caCheckRetries; i++ {
@@ -38,3 +53,20 @@ func WaitForCA(log log.Logger, insecure bool, caCert string) error {
 	}
 	return nil
 }
+
+// EscapeDNAttributeValue escapes special characters in an attribute value as [described in RFC4514](https://datatracker.ietf.org/doc/html/rfc4514).
+func EscapeDNAttributeValue(v string) string {
+	if v == "" {
+		return v
+	}
+
+	v = dnEscaper.Replace(v)
+
+	if strings.HasSuffix(v, " ") {
+		v = v[:len(v)-1] + "\\ "
+	}
+	if strings.HasPrefix(v, "#") || strings.HasPrefix(v, " ") {
+		v = "\\" + v
+	}
+	return v
+}
diff --git a/ocis-pkg/shared/shared_types.go b/ocis-pkg/shared/shared_types.go
index 942ab0a20dc..e171f6fe76f 100644
--- a/ocis-pkg/shared/shared_types.go
+++ b/ocis-pkg/shared/shared_types.go
@@ -42,7 +42,7 @@ type Commons struct {
 	OcisURL           string        `yaml:"ocis_url" env:"OCIS_URL" desc:"URL, where oCIS is reachable for users."`
 	TokenManager      *TokenManager `mask:"struct" yaml:"token_manager"`
 	Reva              *Reva         `yaml:"reva"`
-	MachineAuthAPIKey string        `mask:"password" yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."`
+	MachineAuthAPIKey string        `mask:"password" yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used for accessing the 'auth-machine' service to impersonate users."`
 	TransferSecret    string        `mask:"password" yaml:"transfer_secret,omitempty" env:"REVA_TRANSFER_SECRET"`
 	SystemUserID      string        `yaml:"system_user_id" env:"OCIS_SYSTEM_USER_ID" desc:"ID of the oCIS storage-system system user. Admins need to set the ID for the storage-system system user in this config option which is then used to reference the user. Any reasonable long string is possible, preferably this would be an UUIDv4 format."`
 	SystemUserAPIKey  string        `mask:"password" yaml:"system_user_api_key" env:"SYSTEM_USER_API_KEY"`
diff --git a/ocis/pkg/command/root.go b/ocis/pkg/command/root.go
index 2edf4a750f5..806e917421b 100644
--- a/ocis/pkg/command/root.go
+++ b/ocis/pkg/command/root.go
@@ -25,5 +25,10 @@ func Execute() error {
 		)
 	}
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
diff --git a/services/app-provider/pkg/command/root.go b/services/app-provider/pkg/command/root.go
index b981f0d823f..3db69a21ada 100644
--- a/services/app-provider/pkg/command/root.go
+++ b/services/app-provider/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/app-registry/pkg/command/root.go b/services/app-registry/pkg/command/root.go
index 3d20b9fd491..5f8362165ae 100644
--- a/services/app-registry/pkg/command/root.go
+++ b/services/app-registry/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/audit/pkg/command/root.go b/services/audit/pkg/command/root.go
index 025dc925d6e..ec1ef4d72b9 100644
--- a/services/audit/pkg/command/root.go
+++ b/services/audit/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/auth-basic/pkg/command/root.go b/services/auth-basic/pkg/command/root.go
index d7ba172deb9..d62b0d9e378 100644
--- a/services/auth-basic/pkg/command/root.go
+++ b/services/auth-basic/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/auth-bearer/pkg/command/root.go b/services/auth-bearer/pkg/command/root.go
index c923e706fb2..694500d4d63 100644
--- a/services/auth-bearer/pkg/command/root.go
+++ b/services/auth-bearer/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/auth-machine/pkg/command/root.go b/services/auth-machine/pkg/command/root.go
index fb01026af9e..29d9cdc8e34 100644
--- a/services/auth-machine/pkg/command/root.go
+++ b/services/auth-machine/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/auth-machine/pkg/config/config.go b/services/auth-machine/pkg/config/config.go
index ffb26a9fa71..4c4ade07a45 100644
--- a/services/auth-machine/pkg/config/config.go
+++ b/services/auth-machine/pkg/config/config.go
@@ -20,7 +20,7 @@ type Config struct {
 
 	SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token" env:"AUTH_MACHINE_SKIP_USER_GROUPS_IN_TOKEN" desc:"Disables the encoding of the user's group memberships in the reva access token. This reduces the token size, especially when users are members of a large number of groups."`
 
-	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;AUTH_MACHINE_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."`
+	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;AUTH_MACHINE_API_KEY" desc:"Machine auth API key used for validating requests from other services when impersonating users."`
 
 	Supervised bool            `yaml:"-"`
 	Context    context.Context `yaml:"-"`
diff --git a/services/frontend/pkg/command/root.go b/services/frontend/pkg/command/root.go
index 4feac04e0bf..313a134969b 100644
--- a/services/frontend/pkg/command/root.go
+++ b/services/frontend/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/frontend/pkg/config/config.go b/services/frontend/pkg/config/config.go
index a1f1fda5ab4..4393f6346ee 100644
--- a/services/frontend/pkg/config/config.go
+++ b/services/frontend/pkg/config/config.go
@@ -21,7 +21,7 @@ type Config struct {
 
 	TokenManager      *TokenManager `yaml:"token_manager"`
 	Reva              *Reva         `yaml:"reva"`
-	MachineAuthAPIKey string        `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;FRONTEND_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."`
+	MachineAuthAPIKey string        `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;FRONTEND_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used for accessing the 'auth-machine' service to impersonate users."`
 
 	SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token" env:"FRONTEND_SKIP_USER_GROUPS_IN_TOKEN" desc:"Disables the loading of user's group memberships from the reva access token."`
 
@@ -128,6 +128,6 @@ type CBOXDriver struct {
 }
 
 type Checksums struct {
-	SupportedTypes      []string `yaml:"supported_types" env:"FRONTEND_CHECKSUMS_SUPPORTED_TYPES" desc:"Supported checksum types to be announced to the client. You can provide multiple types separated by blank or comma."`
+	SupportedTypes      []string `yaml:"supported_types" env:"FRONTEND_CHECKSUMS_SUPPORTED_TYPES" desc:"Supported checksum types to be announced to the client (e.g. md5)"`
 	PreferredUploadType string   `yaml:"preferred_upload_type" env:"FRONTEND_CHECKSUMS_PREFERRED_UPLOAD_TYPES" desc:"Preferred checksum types to be announced to the client for uploads (e.g. md5)"`
 }
diff --git a/services/gateway/pkg/command/root.go b/services/gateway/pkg/command/root.go
index fe058b91793..41cddd994c8 100644
--- a/services/gateway/pkg/command/root.go
+++ b/services/gateway/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/graph-explorer/pkg/command/root.go b/services/graph-explorer/pkg/command/root.go
index 1649def9831..ad9e1be393e 100644
--- a/services/graph-explorer/pkg/command/root.go
+++ b/services/graph-explorer/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/graph/pkg/command/root.go b/services/graph/pkg/command/root.go
index 73b42c6d1aa..0e563e60e09 100644
--- a/services/graph/pkg/command/root.go
+++ b/services/graph/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Usage:    "Serve Graph API for oCIS",
 		Commands: GetCommands(cfg),
 	})
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/graph/pkg/identity/ldap.go b/services/graph/pkg/identity/ldap.go
index a801c9510b4..398fabaca63 100644
--- a/services/graph/pkg/identity/ldap.go
+++ b/services/graph/pkg/identity/ldap.go
@@ -11,6 +11,7 @@ import (
 	"github.com/gofrs/uuid"
 	ldapdn "github.com/libregraph/idm/pkg/ldapdn"
 	libregraph "github.com/owncloud/libre-graph-api-go"
+	oldap "github.com/owncloud/ocis/v2/ocis-pkg/ldap"
 	"github.com/owncloud/ocis/v2/ocis-pkg/log"
 	"github.com/owncloud/ocis/v2/services/graph/pkg/config"
 	"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
@@ -116,7 +117,7 @@ func (i *LDAP) CreateUser(ctx context.Context, user libregraph.User) (*libregrap
 		return nil, errReadOnly
 	}
 	ar := ldap.AddRequest{
-		DN: fmt.Sprintf("uid=%s,%s", *user.OnPremisesSamAccountName, i.userBaseDN),
+		DN: fmt.Sprintf("uid=%s,%s", oldap.EscapeDNAttributeValue(*user.OnPremisesSamAccountName), i.userBaseDN),
 		Attributes: []ldap.Attribute{
 			// inetOrgPerson requires "cn"
 			{
@@ -691,7 +692,7 @@ func (i *LDAP) CreateGroup(ctx context.Context, group libregraph.Group) (*libreg
 		return nil, errorcode.New(errorcode.NotAllowed, "server is configured read-only")
 	}
 	ar := ldap.AddRequest{
-		DN: fmt.Sprintf("cn=%s,%s", *group.DisplayName, i.groupBaseDN),
+		DN: fmt.Sprintf("cn=%s,%s", oldap.EscapeDNAttributeValue(*group.DisplayName), i.groupBaseDN),
 		Attributes: []ldap.Attribute{
 			{
 				Type: i.groupAttributeMap.name,
diff --git a/services/groups/pkg/command/root.go b/services/groups/pkg/command/root.go
index 4a7578fc591..c0de62dfd05 100644
--- a/services/groups/pkg/command/root.go
+++ b/services/groups/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/idm/pkg/command/root.go b/services/idm/pkg/command/root.go
index 84208cba848..4db8342e21d 100644
--- a/services/idm/pkg/command/root.go
+++ b/services/idm/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/idp/pkg/command/root.go b/services/idp/pkg/command/root.go
index 9b396057963..409c036f069 100644
--- a/services/idp/pkg/command/root.go
+++ b/services/idp/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/idp/pkg/config/config.go b/services/idp/pkg/config/config.go
index 1623f6062b2..5ce0481f990 100644
--- a/services/idp/pkg/config/config.go
+++ b/services/idp/pkg/config/config.go
@@ -20,7 +20,7 @@ type Config struct {
 
 	Reva *Reva `yaml:"reva"`
 
-	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;IDP_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."`
+	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;IDP_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used for accessing the 'auth-machine' service to impersonate users when looking up their userinfo via the 'cs3' backend."`
 
 	Asset   Asset    `yaml:"asset"`
 	IDP     Settings `yaml:"idp"`
diff --git a/services/nats/pkg/command/root.go b/services/nats/pkg/command/root.go
index 583d2658db5..b5167462842 100644
--- a/services/nats/pkg/command/root.go
+++ b/services/nats/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/notifications/pkg/command/root.go b/services/notifications/pkg/command/root.go
index 72c7dfda260..17d52afe638 100644
--- a/services/notifications/pkg/command/root.go
+++ b/services/notifications/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/notifications/pkg/config/config.go b/services/notifications/pkg/config/config.go
index 3345b566afc..f87d0f3c6f1 100644
--- a/services/notifications/pkg/config/config.go
+++ b/services/notifications/pkg/config/config.go
@@ -25,7 +25,7 @@ type Notifications struct {
 	SMTP              SMTP   `yaml:"SMTP"`
 	Events            Events `yaml:"events"`
 	RevaGateway       string `yaml:"reva_gateway" env:"REVA_GATEWAY;NOTIFICATIONS_REVA_GATEWAY" desc:"CS3 gateway used to look up user metadata"`
-	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;NOTIFICATIONS_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."`
+	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;NOTIFICATIONS_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used for accessing the 'auth-machine' service to look up their email."`
 }
 
 // SMTP combines the smtp configuration options.
diff --git a/services/ocdav/pkg/command/root.go b/services/ocdav/pkg/command/root.go
index 95de57e247a..b96cc01813a 100644
--- a/services/ocdav/pkg/command/root.go
+++ b/services/ocdav/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/ocdav/pkg/command/server.go b/services/ocdav/pkg/command/server.go
index d98d9e2f911..614a22b6c87 100644
--- a/services/ocdav/pkg/command/server.go
+++ b/services/ocdav/pkg/command/server.go
@@ -64,7 +64,6 @@ func Server(cfg *config.Config) *cli.Command {
 					ocdav.Version(cfg.Status.Version),
 					ocdav.VersionString(cfg.Status.VersionString),
 					ocdav.Edition(cfg.Status.Edition),
-					ocdav.MachineAuthAPIKey(cfg.MachineAuthAPIKey),
 					// ocdav.FavoriteManager() // FIXME needs a proper persistence implementation https://github.com/owncloud/ocis/issues/1228
 					// ocdav.LockSystem(), // will default to the CS3 lock system
 					// ocdav.TLSConfig() // tls config for the http server
diff --git a/services/ocdav/pkg/config/config.go b/services/ocdav/pkg/config/config.go
index ce3b4e1c958..cbd33b6ffc5 100644
--- a/services/ocdav/pkg/config/config.go
+++ b/services/ocdav/pkg/config/config.go
@@ -32,8 +32,6 @@ type Config struct {
 	Timeout    int64      `yaml:"gateway_request_timeout" env:"OCDAV_GATEWAY_REQUEST_TIMEOUT" desc:"Request timeout in seconds for requests from the oCDAV service to the gateway service."`
 	Middleware Middleware `yaml:"middleware"`
 
-	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;OCDAV_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."`
-
 	Context context.Context `yaml:"-"`
 	Status  Status          `yaml:"-"`
 }
diff --git a/services/ocdav/pkg/config/defaults/defaultconfig.go b/services/ocdav/pkg/config/defaults/defaultconfig.go
index b47fd98e6fc..804e565284e 100644
--- a/services/ocdav/pkg/config/defaults/defaultconfig.go
+++ b/services/ocdav/pkg/config/defaults/defaultconfig.go
@@ -43,7 +43,6 @@ func DefaultConfig() *config.Config {
 				CredentialsByUserAgent: map[string]string{},
 			},
 		},
-		MachineAuthAPIKey: "",
 		Status: config.Status{
 			Version:        version.Legacy,
 			VersionString:  version.LegacyString,
@@ -94,10 +93,6 @@ func EnsureDefaults(cfg *config.Config) {
 	} else if cfg.TokenManager == nil {
 		cfg.TokenManager = &config.TokenManager{}
 	}
-
-	if cfg.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" {
-		cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey
-	}
 }
 
 func Sanitize(cfg *config.Config) {
diff --git a/services/ocdav/pkg/config/parser/parse.go b/services/ocdav/pkg/config/parser/parse.go
index 545dfe45af8..6a1de96b28b 100644
--- a/services/ocdav/pkg/config/parser/parse.go
+++ b/services/ocdav/pkg/config/parser/parse.go
@@ -37,9 +37,6 @@ func Validate(cfg *config.Config) error {
 	if cfg.TokenManager.JWTSecret == "" {
 		return shared.MissingJWTTokenError(cfg.Service.Name)
 	}
-	if cfg.MachineAuthAPIKey == "" {
-		return shared.MissingMachineAuthApiKeyError(cfg.Service.Name)
-	}
 
 	return nil
 }
diff --git a/services/ocs/pkg/command/root.go b/services/ocs/pkg/command/root.go
index 6d87fb6f204..9e3436e0791 100644
--- a/services/ocs/pkg/command/root.go
+++ b/services/ocs/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/ocs/pkg/config/config.go b/services/ocs/pkg/config/config.go
index 2e550cca5e5..bf18ec276af 100644
--- a/services/ocs/pkg/config/config.go
+++ b/services/ocs/pkg/config/config.go
@@ -24,7 +24,7 @@ type Config struct {
 	IdentityManagement IdentityManagement `yaml:"identity_management"`
 
 	AccountBackend    string `yaml:"-"` // we only support cs3 backend, no need to have this configurable
-	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;OCS_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."`
+	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;OCS_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used for accessing the 'auth-machine' service to impersonate users."`
 
 	Context context.Context `yaml:"-"`
 }
diff --git a/services/proxy/pkg/command/root.go b/services/proxy/pkg/command/root.go
index 4c310fc6727..1f809d049fc 100644
--- a/services/proxy/pkg/command/root.go
+++ b/services/proxy/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/proxy/pkg/config/config.go b/services/proxy/pkg/config/config.go
index 236d407dfde..bab27484460 100644
--- a/services/proxy/pkg/config/config.go
+++ b/services/proxy/pkg/config/config.go
@@ -28,7 +28,7 @@ type Config struct {
 	AccountBackend        string          `yaml:"account_backend" env:"PROXY_ACCOUNT_BACKEND_TYPE" desc:"Account backend the proxy should use, currenly only 'cs3' is possible here."`
 	UserOIDCClaim         string          `yaml:"user_oidc_claim" env:"PROXY_USER_OIDC_CLAIM" desc:"The name of an OpenID Connect claim that should be used for resolving users with the account backend. Currently defaults to 'email'."`
 	UserCS3Claim          string          `yaml:"user_cs3_claim" env:"PROXY_USER_CS3_CLAIM" desc:"The name of a CS3 user attribute (claim) that should be mapped to the 'user_oidc_claim'. Currently defaults to 'mail' (other possible values are: 'username', 'displayname')"`
-	MachineAuthAPIKey     string          `mask:"password" yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;PROXY_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."`
+	MachineAuthAPIKey     string          `mask:"password" yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;PROXY_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used for accessing the 'auth-machine' service to impersonate users."`
 	AutoprovisionAccounts bool            `yaml:"auto_provision_accounts" env:"PROXY_AUTOPROVISION_ACCOUNTS" desc:"Set this to 'true' to automatically provsion users that do not yet exist in the users service on-demand upon first signin. To use this a write-enabled libregraph user backend needs to be setup an running."`
 	EnableBasicAuth       bool            `yaml:"enable_basic_auth" env:"PROXY_ENABLE_BASIC_AUTH" desc:"Set this to true to enable 'basic' (username/password) authentication."`
 	InsecureBackends      bool            `yaml:"insecure_backends" env:"PROXY_INSECURE_BACKENDS" desc:"Disable TLS certificate validation for all http backend connections."`
diff --git a/services/search/pkg/command/root.go b/services/search/pkg/command/root.go
index 9bed2b31589..204aab9f84e 100644
--- a/services/search/pkg/command/root.go
+++ b/services/search/pkg/command/root.go
@@ -34,6 +34,11 @@ func Execute(cfg *config.Config) error {
 		Usage:    "Serve search API for oCIS",
 		Commands: GetCommands(cfg),
 	})
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/search/pkg/config/config.go b/services/search/pkg/config/config.go
index ad851051f1f..7b72fab033e 100644
--- a/services/search/pkg/config/config.go
+++ b/services/search/pkg/config/config.go
@@ -22,7 +22,7 @@ type Config struct {
 	Reva     Reva   `yaml:"reva"`
 	Events   Events `yaml:"events"`
 
-	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;SEARCH_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."`
+	MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;SEARCH_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used for accessing the 'auth-machine' service to impersonate users."`
 
 	Context context.Context `yaml:"-"`
 }
diff --git a/services/search/pkg/search/index/index.go b/services/search/pkg/search/index/index.go
index 7ad01074087..8ce98b18b78 100644
--- a/services/search/pkg/search/index/index.go
+++ b/services/search/pkg/search/index/index.go
@@ -223,9 +223,6 @@ func (i *Index) Search(ctx context.Context, req *searchsvc.SearchIndexRequest) (
 	)
 	bleveReq := bleve.NewSearchRequest(query)
 	bleveReq.Size = 200
-	if req.PageSize > 0 {
-		bleveReq.Size = int(req.PageSize)
-	}
 	bleveReq.Fields = []string{"*"}
 	res, err := i.bleveIndex.Search(bleveReq)
 	if err != nil {
diff --git a/services/search/pkg/search/provider/searchprovider.go b/services/search/pkg/search/provider/searchprovider.go
index d82c7246397..310909021f3 100644
--- a/services/search/pkg/search/provider/searchprovider.go
+++ b/services/search/pkg/search/provider/searchprovider.go
@@ -67,7 +67,7 @@ func New(gwClient gateway.GatewayAPIClient, indexClient search.IndexClient, mach
 
 func (p *Provider) Search(ctx context.Context, req *searchsvc.SearchRequest) (*searchsvc.SearchResponse, error) {
 	if req.Query == "" {
-		return nil, errtypes.BadRequest("empty query provided")
+		return nil, errtypes.PreconditionFailed("empty query provided")
 	}
 	p.logger.Debug().Str("query", req.Query).Msg("performing a search")
 
@@ -144,7 +144,6 @@ func (p *Provider) Search(ctx context.Context, req *searchsvc.SearchRequest) (*s
 				},
 				Path: mountpointPrefix,
 			},
-			PageSize: req.PageSize,
 		})
 		if err != nil {
 			p.logger.Error().Err(err).Str("space", space.Id.OpaqueId).Msg("failed to search the index")
diff --git a/services/search/pkg/service/v0/service.go b/services/search/pkg/service/v0/service.go
index 9fd0da6d40d..d3fd24724a9 100644
--- a/services/search/pkg/service/v0/service.go
+++ b/services/search/pkg/service/v0/service.go
@@ -7,12 +7,10 @@ import (
 
 	"github.com/blevesearch/bleve/v2"
 	revactx "github.com/cs3org/reva/v2/pkg/ctx"
-	"github.com/cs3org/reva/v2/pkg/errtypes"
 	"github.com/cs3org/reva/v2/pkg/events"
 	"github.com/cs3org/reva/v2/pkg/events/server"
 	"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
 	"github.com/go-micro/plugins/v4/events/natsjs"
-	merrors "go-micro.dev/v4/errors"
 	"go-micro.dev/v4/metadata"
 	grpcmetadata "google.golang.org/grpc/metadata"
 
@@ -94,16 +92,10 @@ func (s Service) Search(ctx context.Context, in *searchsvc.SearchRequest, out *s
 	ctx = grpcmetadata.AppendToOutgoingContext(ctx, revactx.TokenHeader, t)
 
 	res, err := s.provider.Search(ctx, &searchsvc.SearchRequest{
-		Query:    in.Query,
-		PageSize: in.PageSize,
+		Query: in.Query,
 	})
 	if err != nil {
-		switch err.(type) {
-		case errtypes.BadRequest:
-			return merrors.BadRequest(s.id, err.Error())
-		default:
-			return merrors.InternalServerError(s.id, err.Error())
-		}
+		return err
 	}
 
 	out.Matches = res.Matches
diff --git a/services/settings/pkg/command/root.go b/services/settings/pkg/command/root.go
index 29812fe0585..dd53b3cae11 100644
--- a/services/settings/pkg/command/root.go
+++ b/services/settings/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/sharing/pkg/command/root.go b/services/sharing/pkg/command/root.go
index 406e09b6fdf..fae443c937e 100644
--- a/services/sharing/pkg/command/root.go
+++ b/services/sharing/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/storage-publiclink/pkg/command/root.go b/services/storage-publiclink/pkg/command/root.go
index 141d7ac6da7..831cb046ece 100644
--- a/services/storage-publiclink/pkg/command/root.go
+++ b/services/storage-publiclink/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/storage-shares/pkg/command/root.go b/services/storage-shares/pkg/command/root.go
index faf2066e6b9..5d8db7f5ec3 100644
--- a/services/storage-shares/pkg/command/root.go
+++ b/services/storage-shares/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/storage-system/pkg/command/root.go b/services/storage-system/pkg/command/root.go
index 0f1cde0b654..8e9847e6068 100644
--- a/services/storage-system/pkg/command/root.go
+++ b/services/storage-system/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/storage-users/pkg/command/root.go b/services/storage-users/pkg/command/root.go
index 5ae9e6e86f5..ae9dd94c0e9 100644
--- a/services/storage-users/pkg/command/root.go
+++ b/services/storage-users/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/store/pkg/command/root.go b/services/store/pkg/command/root.go
index 795a66a74cb..5396b1103e1 100644
--- a/services/store/pkg/command/root.go
+++ b/services/store/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/thumbnails/pkg/command/root.go b/services/thumbnails/pkg/command/root.go
index 28588a261f9..efa87a675e4 100644
--- a/services/thumbnails/pkg/command/root.go
+++ b/services/thumbnails/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/thumbnails/pkg/config/config.go b/services/thumbnails/pkg/config/config.go
index 20d66c72c78..bf851e49a50 100644
--- a/services/thumbnails/pkg/config/config.go
+++ b/services/thumbnails/pkg/config/config.go
@@ -31,7 +31,7 @@ type FileSystemStorage struct {
 
 // Thumbnail defines the available thumbnail related configuration.
 type Thumbnail struct {
-	Resolutions         []string          `yaml:"resolutions" env:"THUMBNAILS_RESOLUTIONS" desc:"The supported target resolutions in the format WidthxHeight e.g. 32x32. You can define any resolution as required and separate multiple resolutions by blank or comma."`
+	Resolutions         []string          `yaml:"resolutions" env:"THUMBNAILS_RESOLUTIONS" desc:"The supported target resolutions in the format WidthxHeight e.g. 32x32. You can provide multiple resolutions separated by a comma."`
 	FileSystemStorage   FileSystemStorage `yaml:"filesystem_storage"`
 	WebdavAllowInsecure bool              `yaml:"webdav_allow_insecure" env:"OCIS_INSECURE;THUMBNAILS_WEBDAVSOURCE_INSECURE" desc:"Ignore untrusted SSL certificates when connecting to the webdav source."`
 	CS3AllowInsecure    bool              `yaml:"cs3_allow_insecure" env:"OCIS_INSECURE;THUMBNAILS_CS3SOURCE_INSECURE" desc:"Ignore untrusted SSL certificates when connecting to the CS3 source."`
diff --git a/services/users/pkg/command/root.go b/services/users/pkg/command/root.go
index c84c93603bb..7ce50ddf076 100644
--- a/services/users/pkg/command/root.go
+++ b/services/users/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/web/pkg/command/root.go b/services/web/pkg/command/root.go
index 7dfe694e2c7..ef57b495663 100644
--- a/services/web/pkg/command/root.go
+++ b/services/web/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/webdav/pkg/command/root.go b/services/webdav/pkg/command/root.go
index fd125591194..c8f857ca2cb 100644
--- a/services/webdav/pkg/command/root.go
+++ b/services/webdav/pkg/command/root.go
@@ -33,6 +33,11 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
+	cli.HelpFlag = &cli.BoolFlag{
+		Name:  "help,h",
+		Usage: "Show the help",
+	}
+
 	return app.Run(os.Args)
 }
 
diff --git a/services/webdav/pkg/service/v0/search.go b/services/webdav/pkg/service/v0/search.go
index 084475ab937..7ba77db16f4 100644
--- a/services/webdav/pkg/service/v0/search.go
+++ b/services/webdav/pkg/service/v0/search.go
@@ -44,8 +44,7 @@ func (g Webdav) Search(w http.ResponseWriter, r *http.Request) {
 	ctx := revactx.ContextSetToken(r.Context(), t)
 	ctx = metadata.Set(ctx, revactx.TokenHeader, t)
 	rsp, err := g.searchClient.Search(ctx, &searchsvc.SearchRequest{
-		Query:    rep.SearchFiles.Search.Pattern,
-		PageSize: int32(rep.SearchFiles.Search.Limit),
+		Query: rep.SearchFiles.Search.Pattern,
 	})
 	if err != nil {
 		e := merrors.Parse(err.Error())


Test patch:
diff --git a/ocis-pkg/ldap/ldap_suite_test.go b/ocis-pkg/ldap/ldap_suite_test.go
new file mode 100644
index 00000000000..3eee47856d2
--- /dev/null
+++ b/ocis-pkg/ldap/ldap_suite_test.go
@@ -0,0 +1,13 @@
+package ldap_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+func TestLdap(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Ldap Suite")
+}
diff --git a/ocis-pkg/ldap/ldap_test.go b/ocis-pkg/ldap/ldap_test.go
new file mode 100644
index 00000000000..d3ee3152cfb
--- /dev/null
+++ b/ocis-pkg/ldap/ldap_test.go
@@ -0,0 +1,25 @@
+package ldap_test
+
+import (
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+	"github.com/owncloud/ocis/v2/ocis-pkg/ldap"
+)
+
+var _ = Describe("ldap", func() {
+	DescribeTable("EscapeDNAttributeValue should escape special characters",
+		func(input, expected string) {
+			escaped := ldap.EscapeDNAttributeValue(input)
+			Expect(escaped).To(Equal(expected))
+		},
+		Entry("normal dn", "foobar", "foobar"),
+		Entry("including comma", "foo,bar", "foo\\,bar"),
+		Entry("including equals", "foo=bar", "foo\\=bar"),
+		Entry("beginning with number sign", "#foobar", "\\#foobar"),
+		Entry("beginning with space", " foobar", "\\ foobar"),
+		Entry("only one space", " ", "\\ "),
+		Entry("two spaces", "  ", "\\ \\ "),
+		Entry("ending with space", "foobar ", "foobar\\ "),
+		Entry("containing multiple special chars", "f+o>o,b<a;r=\"\000", `f\+o\>o\,b\<a\;r\=\\"\00`),
+	)
+})
diff --git a/tests/acceptance/expected-failures-API-on-OCIS-storage.md b/tests/acceptance/expected-failures-API-on-OCIS-storage.md
index cc9d42b9688..b2bc3a85ac6 100644
--- a/tests/acceptance/expected-failures-API-on-OCIS-storage.md
+++ b/tests/acceptance/expected-failures-API-on-OCIS-storage.md
@@ -965,6 +965,10 @@ _ocdav: api compatibility, return correct status code_
 - [apiWebdavOperations/search.feature:264](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/search.feature#L264)
 - [apiWebdavOperations/search.feature:270](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/search.feature#L270)
 
+### [Different response status code while searching with empty pattern with new webdav](https://github.com/owncloud/ocis/issues/4016)
+
+- [apiWebdavOperations/search.feature:103](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/search.feature#L103)
+
 ### [No permisions propertry in response while searching for files and folders on ocis with new webdav](https://github.com/owncloud/ocis/issues/4009)
 
 - [apiWebdavOperations/search.feature:208](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/search.feature#L208)
@@ -1572,6 +1576,19 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers
 
 - [apiMain/checksums.feature:233](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiMain/checksums.feature#L233)
 
+#### public links without permission are allowed now
+
+- [apiShareUpdateToShares/updateShare.feature:113](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareUpdateToShares/updateShare.feature#L113)
+- [apiShareUpdateToShares/updateShare.feature:114](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareUpdateToShares/updateShare.feature#L114)
+- [apiShareCreateSpecialToShares2/createShareWithInvalidPermissions.feature:26](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares2/createShareWithInvalidPermissions.feature#L26)
+- [apiShareCreateSpecialToShares2/createShareWithInvalidPermissions.feature:27](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares2/createShareWithInvalidPermissions.feature#L27)
+- [apiShareCreateSpecialToShares2/createShareWithInvalidPermissions.feature:28](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares2/createShareWithInvalidPermissions.feature#L28)
+- [apiShareCreateSpecialToShares2/createShareWithInvalidPermissions.feature:29](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares2/createShareWithInvalidPermissions.feature#L29)
+- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:117](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L117)
+- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:118](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L118)
+- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:132](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L132)
+- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:133](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L133)
+
 ### [graph/users: enable/disable users](https://github.com/owncloud/ocis/issues/3064)
 
 - [apiWebdavOperations/refuseAccess.feature:35](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/refuseAccess.feature#L35)