Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelog/unreleased/fix-ocm-weddav.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Bugfix: Fix the OCM WebDAV protocol entity mismatch

Fixed the OCM WebDAV protocol entity mismatch

https://github.com/owncloud/reva/pull/425
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ func (s *service) getWebdavProtocol(ctx context.Context, share *ocm.Share, m *oc

return &ocmd.WebDAV{
Permissions: perms,
URL: s.webdavURL(ctx, share),
URI: s.webdavURL(ctx, share),
SharedSecret: share.Token,
}
}
Expand Down
34 changes: 32 additions & 2 deletions internal/http/services/ocmd/protocols.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,37 @@ type Protocol interface {
type WebDAV struct {
SharedSecret string `json:"sharedSecret" validate:"required"`
Permissions []string `json:"permissions" validate:"required,dive,required,oneof=read write share"`
URL string `json:"url" validate:"required"`
URI string `json:"uri" validate:"required"`
}

// UnmarshalJSON implements custom JSON unmarshaling for backward compatibility.
// It supports both "url" (legacy) and "uri" (new) field names.
func (w *WebDAV) UnmarshalJSON(data []byte) error {
// Define a temporary struct with both url and uri fields
type WebDAVAlias struct {
SharedSecret string `json:"sharedSecret"`
Permissions []string `json:"permissions"`
URL string `json:"url"`
URI string `json:"uri"`
}

var alias WebDAVAlias
if err := json.Unmarshal(data, &alias); err != nil {
return err
}

// Copy common fields
w.SharedSecret = alias.SharedSecret
w.Permissions = alias.Permissions

// Use URI if present, otherwise fall back to URL for backward compatibility
if alias.URI != "" {
w.URI = alias.URI
} else {
w.URI = alias.URL
}

return nil
}

// ToOCMProtocol convert the protocol to a ocm Protocol struct.
Expand All @@ -73,7 +103,7 @@ func (w *WebDAV) ToOCMProtocol() *ocm.Protocol {
}
}

return ocmshare.NewWebDAVProtocol(w.URL, w.SharedSecret, perms)
return ocmshare.NewWebDAVProtocol(w.URI, w.SharedSecret, perms)
}

// Webapp contains the parameters for the Webapp protocol.
Expand Down
40 changes: 34 additions & 6 deletions internal/http/services/ocmd/protocols_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,23 @@ func TestUnmarshalProtocol(t *testing.T) {
raw: `{"unsupported":{}}`,
err: "protocol unsupported not recognised",
},
{
raw: `{"name":"multi","options":{},"webdav":{"sharedSecret":"secret","permissions":["read","write"],"uri":"http://example.org"}}`,
expected: []Protocol{
&WebDAV{
SharedSecret: "secret",
Permissions: []string{"read", "write"},
URI: "http://example.org",
},
},
},
{
raw: `{"name":"multi","options":{},"webdav":{"sharedSecret":"secret","permissions":["read","write"],"url":"http://example.org"}}`,
expected: []Protocol{
&WebDAV{
SharedSecret: "secret",
Permissions: []string{"read", "write"},
URL: "http://example.org",
URI: "http://example.org",
},
},
},
Expand Down Expand Up @@ -82,7 +92,25 @@ func TestUnmarshalProtocol(t *testing.T) {
&WebDAV{
SharedSecret: "secret",
Permissions: []string{"read", "write"},
URL: "http://example.org",
URI: "http://example.org",
},
&Webapp{
URITemplate: "http://example.org/{test}",
},
&Datatx{
SharedSecret: "secret",
SourceURI: "http://example.org",
Size: 10,
},
},
},
{
raw: `{"name":"multi","options":{},"webdav":{"sharedSecret":"secret","permissions":["read","write"],"uri":"http://example.org"},"webapp":{"uriTemplate":"http://example.org/{test}"},"datatx":{"sharedSecret":"secret","srcUri":"http://example.org","size":10}}`,
expected: []Protocol{
&WebDAV{
SharedSecret: "secret",
Permissions: []string{"read", "write"},
URI: "http://example.org",
},
&Webapp{
URITemplate: "http://example.org/{test}",
Expand Down Expand Up @@ -145,7 +173,7 @@ func TestMarshalProtocol(t *testing.T) {
&WebDAV{
SharedSecret: "secret",
Permissions: []string{"read"},
URL: "http://example.org",
URI: "http://example.org",
},
},
expected: map[string]any{
Expand All @@ -154,7 +182,7 @@ func TestMarshalProtocol(t *testing.T) {
"webdav": map[string]any{
"sharedSecret": "secret",
"permissions": []any{"read"},
"url": "http://example.org",
"uri": "http://example.org",
},
},
},
Expand Down Expand Up @@ -197,7 +225,7 @@ func TestMarshalProtocol(t *testing.T) {
&WebDAV{
SharedSecret: "secret",
Permissions: []string{"read"},
URL: "http://example.org",
URI: "http://example.org",
},
&Webapp{
URITemplate: "http://example.org",
Expand All @@ -215,7 +243,7 @@ func TestMarshalProtocol(t *testing.T) {
"webdav": map[string]any{
"sharedSecret": "secret",
"permissions": []any{"read"},
"url": "http://example.org",
"uri": "http://example.org",
},
"webapp": map[string]any{
"uriTemplate": "http://example.org",
Expand Down
5 changes: 5 additions & 0 deletions internal/http/services/ocmd/shares.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package ocmd

import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -213,6 +214,10 @@ func getIDAndMeshProvider(user string) (string, string, error) {
if len(split) < 2 {
return "", "", errors.New("not in the form <id>@<provider>")
}
candidate := split[0]
if b, err := base64.StdEncoding.DecodeString(candidate); err == nil {
split = strings.Split(string(b), "@")
}
return strings.Join(split[:len(split)-1], "@"), split[len(split)-1], nil
}

Expand Down
6 changes: 4 additions & 2 deletions pkg/ocm/provider/authorizer/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,12 @@ func (a *authorizer) IsProviderAllowed(ctx context.Context, pi *ocmprovider.Prov
}

switch {
case !providerAuthorized:
return errtypes.NotFound(pi.GetDomain())
case !a.conf.VerifyRequestHostname:
log.Info().Msg("VerifyRequestHostname is disabled. any provider is allowed")
return nil
case !providerAuthorized:
log.Info().Msg("providerAuthorized is false")
return errtypes.NotFound(pi.GetDomain())
case len(pi.Services) == 0:
return ErrNoIP
}
Expand Down
6 changes: 4 additions & 2 deletions pkg/ocm/provider/authorizer/json/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ func TestAuthorizer_IsProviderAllowed(t *testing.T) {
providerInfo: &ocmprovider.ProviderInfo{
Domain: "some.unknown.domain",
},
expectedError: errtypes.NotFound("some.unknown.domain"),
verifyRequestHostname: true,
expectedError: errtypes.NotFound("some.unknown.domain"),
},
"authorized without host name verification": {
providerInfo: &ocmprovider.ProviderInfo{
Expand All @@ -65,7 +66,8 @@ func TestAuthorizer_IsProviderAllowed(t *testing.T) {
providerInfo: &ocmprovider.ProviderInfo{
Domain: "server-two",
},
expectedError: error(errtypes.NotFound("server-two")),
verifyRequestHostname: true,
expectedError: error(errtypes.NotFound("server-two")),
},
} {
t.Run(name, func(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/ocm/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
// 1. stripping the protocol from the domain and
// 2. base64 encoding the opaque id with the domain to get a unique identifier that cannot collide with other users
func FederatedID(id *userpb.UserId, domain string) *userpb.UserId {
opaqueId := base64.URLEncoding.EncodeToString([]byte(id.OpaqueId + "@" + id.Idp))
opaqueId := base64.StdEncoding.EncodeToString([]byte(id.OpaqueId + "@" + id.Idp))
return &userpb.UserId{
Type: userpb.UserType_USER_TYPE_FEDERATED,
Idp: domain,
Expand All @@ -29,7 +29,7 @@ func RemoteID(id *userpb.UserId) *userpb.UserId {
Idp: id.Idp,
OpaqueId: id.OpaqueId,
}
bytes, err := base64.URLEncoding.DecodeString(id.GetOpaqueId())
bytes, err := base64.StdEncoding.DecodeString(id.GetOpaqueId())
if err != nil {
return remoteId
}
Expand Down