Skip to content
Merged
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
1 change: 1 addition & 0 deletions common/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ var (
ErrInvalidQueryParams = fmt.Errorf("invalid query parameters")
ErrLowTrust = fmt.Errorf("token trust is lower than threshold")
ErrPending = fmt.Errorf("application_status pending")
ErrNoCapabilities = NoCapabilitiesError{}
)

type Http400Error struct {
Expand Down
2 changes: 1 addition & 1 deletion http/http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ func (c *HttpClient) Do(method string, url string, header http.Header, bbytes []
}

switch res.StatusCode {
case http.StatusForbidden, http.StatusBadRequest, http.StatusNotFound:
case http.StatusUnauthorized, http.StatusForbidden, http.StatusBadRequest, http.StatusNotFound:
return rbytes, nil, false, common.NewError(err)
}
return rbytes, nil, true, common.NewError(err)
Expand Down
16 changes: 15 additions & 1 deletion http/multipart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ func TestCpeMiddleware(t *testing.T) {
_, err = io.ReadAll(res.Body)
assert.NilError(t, err)
res.Body.Close()
assert.Equal(t, res.StatusCode, http.StatusForbidden)
assert.Equal(t, res.StatusCode, http.StatusUnauthorized)

// get a token
token := server1.Generate(cpeMac, 86400)
Expand All @@ -269,6 +269,20 @@ func TestCpeMiddleware(t *testing.T) {
res.Body.Close()
assert.Equal(t, res.StatusCode, http.StatusOK)

// XPC-43727 a real signed token for one cpeMac presented against a
// different mac's /config URL must be rejected as unauthorized, not
// treated as an authorization (403) failure
otherCpeMac := util.GenerateRandomCpeMac()
otherConfigUrl := fmt.Sprintf("/api/v1/device/%v/config", otherCpeMac)
req, err = http.NewRequest("GET", otherConfigUrl, nil)
assert.NilError(t, err)
req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", token))
res = ExecuteRequest(req, router1).Result()
_, err = io.ReadAll(res.Body)
assert.NilError(t, err)
res.Body.Close()
assert.Equal(t, res.StatusCode, http.StatusUnauthorized)

// change the min trust to 1000
server1.SetMinTrust(1000)
assert.Equal(t, 1000, server1.MinTrust())
Expand Down
2 changes: 1 addition & 1 deletion http/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func Error(w http.ResponseWriter, status int, err error) {
// calling WriteHeader() multiple times will cause errors in common.HeaderContentType
// ==> errors like 'superfluous response.WriteHeader call' in stderr
switch status {
case http.StatusNoContent, http.StatusNotModified, http.StatusForbidden:
case http.StatusNoContent, http.StatusNotModified, http.StatusUnauthorized, http.StatusForbidden:
w.WriteHeader(status)
case http.StatusAccepted:
SetAuditValue(w, "response", err)
Expand Down
31 changes: 25 additions & 6 deletions http/webconfig_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,8 @@ func (s *WebconfigServer) CpeMiddleware(next http.Handler) http.Handler {
params := mux.Vars(r)
mac, ok := params["mac"]
if !ok {
Error(xw, http.StatusForbidden, nil)
err := *common.NewHttp400Error("missing mac")
Error(xw, http.StatusBadRequest, common.NewError(err))
return
}
mac = strings.ToUpper(mac)
Expand Down Expand Up @@ -534,7 +535,11 @@ func (s *WebconfigServer) CpeMiddleware(next http.Handler) http.Handler {
next.ServeHTTP(xw, r)
} else {
s.LogToken(xw, authorization, token, tokenErr)
Error(xw, http.StatusForbidden, nil)
if errors.Is(tokenErr, common.ErrNoCapabilities) || errors.Is(tokenErr, common.ErrLowTrust) {
Error(xw, http.StatusForbidden, nil)
} else {
Error(xw, http.StatusUnauthorized, nil)
}
}
}
return http.HandlerFunc(fn)
Expand All @@ -547,6 +552,7 @@ func (s *WebconfigServer) ApiMiddleware(next http.Handler) http.Handler {
defer s.logRequestEnds(xw, r)

isValid := false
var verifyErr error
token := xw.Token()
if len(token) > 0 {
var kid string
Expand All @@ -562,6 +568,7 @@ func (s *WebconfigServer) ApiMiddleware(next http.Handler) http.Handler {
isValid = true
log.WithFields(tfields).Debug("valid")
} else {
verifyErr = err
tfields["error"] = fmt.Sprintf("ApiMiddleware::VerifyApiToken() %v", err)
log.WithFields(tfields).Debug("rejected")
}
Expand All @@ -572,7 +579,11 @@ func (s *WebconfigServer) ApiMiddleware(next http.Handler) http.Handler {
if isValid {
next.ServeHTTP(xw, r)
} else {
Error(xw, http.StatusForbidden, nil)
if errors.Is(verifyErr, common.ErrNoCapabilities) {
Error(xw, http.StatusForbidden, nil)
} else {
Error(xw, http.StatusUnauthorized, nil)
}
}
}
return http.HandlerFunc(fn)
Expand All @@ -591,23 +602,31 @@ func (s *WebconfigServer) TestingCpeMiddleware(next http.Handler) http.Handler {
}

isValid := false
var verifyErr error
if len(token) > 0 {
params := mux.Vars(r)
mac, ok := params["mac"]
if !ok || len(mac) != 12 {
Error(xw, http.StatusForbidden, nil)
err := *common.NewHttp400Error("invalid mac")
Error(xw, http.StatusBadRequest, common.NewError(err))
return
}

if ok, _, _, _ := s.VerifyCpeToken(token, strings.ToLower(mac)); ok {
if ok, _, _, err := s.VerifyCpeToken(token, strings.ToLower(mac)); ok {
isValid = true
} else {
verifyErr = err
}
}

if isValid {
next.ServeHTTP(xw, r)
} else {
Error(xw, http.StatusForbidden, nil)
if errors.Is(verifyErr, common.ErrNoCapabilities) {
Error(xw, http.StatusForbidden, nil)
} else {
Error(xw, http.StatusUnauthorized, nil)
}
}
}
return http.HandlerFunc(fn)
Expand Down
Loading
Loading