From aee8d909b3925df17f5e0c82348a2597bc3457ac Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 4 Mar 2024 15:24:15 +0000 Subject: [PATCH] onedrive: fix "unauthenticated: Unauthenticated" errors when downloading Before this change we would pass the Authorization header on to the download server. This is allowed according to the docs, but on some onedrive servers this sometimes causes an error with the text "unauthenticated: Unauthenticated". This is a similar fix to dedad9f071d81a2b onedrive: fix "unauthenticated: Unauthenticated" errors when uploading See: https://forum.rclone.org/t/cryptcheck-on-encrypted-onedrive-personal-failed-with-unauthenticated-error/44581/ --- backend/onedrive/onedrive.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/backend/onedrive/onedrive.go b/backend/onedrive/onedrive.go index 450e0e527..5ce26f6f9 100644 --- a/backend/onedrive/onedrive.go +++ b/backend/onedrive/onedrive.go @@ -2254,9 +2254,23 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (in io.Read if o.fs.opt.AVOverride { opts.Parameters = url.Values{"AVOverride": {"1"}} } + // Make a note of the redirect target as we need to call it without Auth + var redirectReq *http.Request + opts.CheckRedirect = func(req *http.Request, via []*http.Request) error { + if len(via) >= 10 { + return errors.New("stopped after 10 redirects") + } + req.Header.Del("Authorization") // remove Auth header + redirectReq = req + return http.ErrUseLastResponse + } err = o.fs.pacer.Call(func() (bool, error) { resp, err = o.fs.srv.Call(ctx, &opts) + if redirectReq != nil { + // It is a redirect which we are expecting + err = nil + } return shouldRetry(ctx, resp, err) }) if err != nil { @@ -2267,6 +2281,20 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (in io.Read } return nil, err } + if redirectReq != nil { + err = o.fs.pacer.Call(func() (bool, error) { + resp, err = o.fs.unAuth.Do(redirectReq) + return shouldRetry(ctx, resp, err) + }) + if err != nil { + if resp != nil { + if virus := resp.Header.Get("X-Virus-Infected"); virus != "" { + err = fmt.Errorf("server reports this file is infected with a virus - use --onedrive-av-override to download anyway: %s: %w", virus, err) + } + } + return nil, err + } + } if resp.StatusCode == http.StatusOK && resp.ContentLength > 0 && resp.Header.Get("Content-Range") == "" { // Overwrite size with actual size since size readings from Onedrive is unreliable.