From b79b82378c21f24d4fe129a1fe1e8c9796eca072 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 2 Feb 2024 10:06:27 +0200 Subject: [PATCH] WIP: Add temporary file when changing htpasswd password --- pkg/api/htpasswd.go | 33 ++++++++++++++++++++++++++------- pkg/api/routes.go | 4 +++- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/pkg/api/htpasswd.go b/pkg/api/htpasswd.go index ea0aff9b89..5551eec5ed 100644 --- a/pkg/api/htpasswd.go +++ b/pkg/api/htpasswd.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "os" + "path/filepath" "strings" "sync" @@ -110,10 +111,7 @@ func (hc *HtpasswdClient) ChangePassword(login, supposedOldPassword, newPassword return zerr.ErrPasswordIsEmpty } - hc.credMap.rw.RLock() - oldPassphrase, ok := hc.credMap.m[login] - hc.credMap.rw.RUnlock() - + oldPassphrase, ok := hc.credMap.Get(login) if !ok { return zerr.ErrBadUser } @@ -151,10 +149,31 @@ func (hc *HtpasswdClient) ChangePassword(login, supposedOldPassword, newPassword } } - // write new content to file - output := strings.Join(lines, "\n") + // write new content to temporary file + // and replace the old file with temporary, so the operation is atomic + output := []byte(strings.Join(lines, "\n")) + + tmpfile, err := os.CreateTemp(filepath.Dir(hc.filepath), "htpasswd-*.tmp") + if err != nil { + return fmt.Errorf("error occurred when creating temp htpasswd file: %w", err) + } + + if _, err := tmpfile.Write(output); err != nil { + tmpfile.Close() + os.Remove(tmpfile.Name()) + return fmt.Errorf("error occurred when writing to temp htpasswd file: %w", err) + } + + if err := tmpfile.Close(); err != nil { + os.Remove(tmpfile.Name()) + return fmt.Errorf("error occurred when closing temp htpasswd file: %w", err) + } + + if err := os.Rename(tmpfile.Name(), hc.filepath); err != nil { + return fmt.Errorf("error occurred while replacing htpasswd file with new file: %w", err) + } - err = os.WriteFile(hc.filepath, []byte(output), constants.DefaultDirPerms) + err = os.WriteFile(hc.filepath, output, constants.DefaultDirPerms) if err != nil { return fmt.Errorf("error occurred while writing to creds-file: %w", err) } diff --git a/pkg/api/routes.go b/pkg/api/routes.go index bdb8fb1dc5..678a5c84cc 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -2248,7 +2248,7 @@ func (rh *RouteHandler) ChangePassword(resp http.ResponseWriter, req *http.Reque userAc, err := reqCtx.UserAcFromContext(req.Context()) if err != nil { - resp.WriteHeader(http.StatusNotFound) + resp.WriteHeader(http.StatusInternalServerError) return } @@ -2256,6 +2256,8 @@ func (rh *RouteHandler) ChangePassword(resp http.ResponseWriter, req *http.Reque username := userAc.GetUsername() if username == "" { resp.WriteHeader(http.StatusNotFound) + + return } if err := rh.c.HtpasswdClient.ChangePassword(username, reqBody.OldPassword, reqBody.NewPassword); err != nil {