Update libuweave/macaroon code

Added delegation time stamp into access token to match changed
validation logic of macaroons.

BUG: 26728665
Change-Id: I131b92b0e0b1b2274d80bdc0b5790a8c05071ec5
Reviewed-on: https://weave-review.googlesource.com/2467
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/src/privet/auth_manager.cc b/src/privet/auth_manager.cc
index 0b8a981..c82887e 100644
--- a/src/privet/auth_manager.cc
+++ b/src/privet/auth_manager.cc
@@ -321,6 +321,8 @@
 
 std::vector<uint8_t> AuthManager::CreateAccessToken(const UserInfo& user_info,
                                                     base::TimeDelta ttl) const {
+  const base::Time now = Now();
+  TimestampCaveat issued{now};
   ScopeCaveat scope{ToMacaroonScope(user_info.scope())};
   // Macaroons have no caveats for auth type. So we just append the type to the
   // user ID.
@@ -328,13 +330,14 @@
   id_with_type.push_back(static_cast<uint8_t>(user_info.id().type));
   UserIdCaveat user{id_with_type};
   AppIdCaveat app{user_info.id().app};
-  const base::Time now = Now();
   ExpirationCaveat expiration{now + ttl};
-  return CreateMacaroonToken(access_secret_, now,
-                             {
-                                 &scope.GetCaveat(), &user.GetCaveat(),
-                                 &app.GetCaveat(), &expiration.GetCaveat(),
-                             });
+  return CreateMacaroonToken(
+      access_secret_, now,
+      {
+
+          &issued.GetCaveat(), &scope.GetCaveat(), &user.GetCaveat(),
+          &app.GetCaveat(), &expiration.GetCaveat(),
+      });
 }
 
 bool AuthManager::ParseAccessToken(const std::vector<uint8_t>& token,
@@ -346,7 +349,7 @@
   UwMacaroonValidationResult result{};
   const base::Time now = Now();
   if (!LoadMacaroon(token, &buffer, &macaroon, error) ||
-      macaroon.num_caveats != 4 ||
+      macaroon.num_caveats != 5 ||
       !VerifyMacaroon(access_secret_, macaroon, now, &result, error)) {
     return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthorization,
                         "Invalid token");
diff --git a/src/privet/auth_manager_unittest.cc b/src/privet/auth_manager_unittest.cc
index a0a0d01..294aefa 100644
--- a/src/privet/auth_manager_unittest.cc
+++ b/src/privet/auth_manager_unittest.cc
@@ -70,18 +70,18 @@
 }
 
 TEST_F(AuthManagerTest, CreateAccessToken) {
-  EXPECT_EQ("WCaEQgEURglEMjM0AEIKQEYFGhudoQBQaML7svgzFKDXI+/geUUn0w==",
+  EXPECT_EQ("WC2FRggaG52hAEIBFEYJRDIzNABCCkBGBRobnaEAUFAF46oQlMmXgnLstt7wU2w=",
             Base64Encode(auth_.CreateAccessToken(
                 UserInfo{AuthScope::kViewer, TestUserId{"234"}}, {})));
-  EXPECT_EQ("WCaEQgEIRglEMjU3AEIKQEYFGhudoQBQ0f4NfEW7KDC1QnbExFbf9w==",
+  EXPECT_EQ("WC2FRggaG52hAEIBCEYJRDI1NwBCCkBGBRobnaEAUEdWRNHcu/0mA6c3e0tgDrk=",
             Base64Encode(auth_.CreateAccessToken(
                 UserInfo{AuthScope::kManager, TestUserId{"257"}}, {})));
-  EXPECT_EQ("WCaEQgECRglENDU2AEIKQEYFGhudoQBQtgk1ZlsGqs5gF7m+UpwxmQ==",
+  EXPECT_EQ("WC2FRggaG52hAEIBAkYJRDQ1NgBCCkBGBRobnaEAUH2ZLgUPdTtjNRa+PoDkMW4=",
             Base64Encode(auth_.CreateAccessToken(
                 UserInfo{AuthScope::kOwner, TestUserId{"456"}}, {})));
   auto new_time = clock_.Now() + base::TimeDelta::FromDays(11);
   EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time));
-  EXPECT_EQ("WCaEQgEORglEMzQ1AEIKQEYFGhusIYBQl3SG1De+fl2qTquwTl1uRA==",
+  EXPECT_EQ("WC2FRggaG6whgEIBDkYJRDM0NQBCCkBGBRobrCGAUDAFptj7bbYmbpaa6Wpb1Wo=",
             Base64Encode(auth_.CreateAccessToken(
                 UserInfo{AuthScope::kUser, TestUserId{"345"}}, {})));
 }
diff --git a/third_party/libuweave/src/macaroon.c b/third_party/libuweave/src/macaroon.c
index 80e5933..c823804 100644
--- a/third_party/libuweave/src/macaroon.c
+++ b/third_party/libuweave/src/macaroon.c
@@ -124,29 +124,32 @@
 
 static void init_validation_result(UwMacaroonValidationResult* result) {
   // Start from the largest scope
-  result->granted_scope = kUwMacaroonCaveatScopeTypeOwner;
-  result->expiration_time = UINT32_MAX;
-  result->weave_app_restricted = false;
-  result->lan_session_id = NULL;
-  result->lan_session_id_len = 0;
-  result->num_delegatees = 0;
+  *result = (UwMacaroonValidationResult){
+      .granted_scope = kUwMacaroonCaveatScopeTypeOwner,
+      .expiration_time = UINT32_MAX,
+  };
 }
 
 /** Reset the result object to the lowest scope when encountering errors */
 static void reset_validation_result(UwMacaroonValidationResult* result) {
-  // Start from the largest scope or highest privilege
-  result->granted_scope = 0;
-  result->expiration_time = 0;
-  result->weave_app_restricted = true;
-  result->lan_session_id = NULL;
-  result->lan_session_id_len = 0;
+  *result = (UwMacaroonValidationResult){
+      .weave_app_restricted = true,
+      .granted_scope = UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE};
+}
 
-  result->num_delegatees = 0;
-  for (size_t i = 0; i < MAX_NUM_DELEGATEES; i++) {
-    result->delegatees[i].id = NULL;
-    result->delegatees[i].id_len = 0;
-    result->delegatees[i].type = kUwMacaroonDelegateeTypeNone;
+/** Get the next closest scope (to the narrower side). */
+static UwMacaroonCaveatScopeType get_closest_scope(
+    UwMacaroonCaveatScopeType scope) {
+  if (scope <= kUwMacaroonCaveatScopeTypeOwner) {
+    return kUwMacaroonCaveatScopeTypeOwner;
+  } else if (scope <= kUwMacaroonCaveatScopeTypeManager) {
+    return kUwMacaroonCaveatScopeTypeManager;
+  } else if (scope <= kUwMacaroonCaveatScopeTypeUser) {
+    return kUwMacaroonCaveatScopeTypeUser;
+  } else if (scope <= kUwMacaroonCaveatScopeTypeViewer) {
+    return kUwMacaroonCaveatScopeTypeViewer;
   }
+  return scope;
 }
 
 bool uw_macaroon_validate_(const UwMacaroon* macaroon,
@@ -178,6 +181,7 @@
     }
   }
 
+  result->granted_scope = get_closest_scope(result->granted_scope);
   return true;
 }
 
diff --git a/third_party/libuweave/src/macaroon.h b/third_party/libuweave/src/macaroon.h
index c93bbb2..c739bca 100644
--- a/third_party/libuweave/src/macaroon.h
+++ b/third_party/libuweave/src/macaroon.h
@@ -36,6 +36,7 @@
   const uint8_t* id;
   size_t id_len;
   UwMacaroonDelegateeType type;
+  uint32_t timestamp;
 } UwMacaroonDelegateeInfo;
 
 #define MAX_NUM_DELEGATEES 10
@@ -67,7 +68,8 @@
 
 /**
  * Verify and validate the Macaroon, and put relevant information into the
- * result object.
+ * result object. Note that the resulting granted_scope will be the closest
+ * valid scope type (to the narrower side) defined in macaroon_caveat.h.
  */
 bool uw_macaroon_validate_(
     const UwMacaroon* macaroon,
diff --git a/third_party/libuweave/src/macaroon_caveat.c b/third_party/libuweave/src/macaroon_caveat.c
index 85d8bbb..dc4ee3b 100644
--- a/third_party/libuweave/src/macaroon_caveat.c
+++ b/third_party/libuweave/src/macaroon_caveat.c
@@ -12,9 +12,6 @@
 #include "src/macaroon_context.h"
 #include "src/macaroon_encoding.h"
 
-// For security sanity checks
-#define UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE 127
-
 static bool is_valid_caveat_type_(UwMacaroonCaveatType type) {
   switch (type) {
     case kUwMacaroonCaveatTypeNonce:
@@ -403,8 +400,9 @@
 
 static bool update_delegatee_list(UwMacaroonCaveatType caveat_type,
                                   const UwMacaroonCaveat* caveat,
+                                  uint32_t issued_time,
                                   UwMacaroonValidationResult* result) {
-  if (result->num_delegatees >= MAX_NUM_DELEGATEES) {
+  if (result->num_delegatees >= MAX_NUM_DELEGATEES || issued_time == 0) {
     return false;
   }
 
@@ -441,6 +439,7 @@
     return false;
   }
   result->delegatees[result->num_delegatees].type = delegatee_type;
+  result->delegatees[result->num_delegatees].timestamp = issued_time;
   result->num_delegatees++;
   return true;
 }
@@ -471,22 +470,22 @@
       return true;
 
     case kUwMacaroonCaveatTypeDelegationTimestamp:
-      state->has_issued_time = true;
-      if (!uw_macaroon_caveat_get_value_uint_(caveat, &issued_time)) {
+      if (!uw_macaroon_caveat_get_value_uint_(caveat, &issued_time) ||
+          issued_time < state->issued_time) {
         return false;
       }
       state->issued_time = issued_time;
       return true;
 
     case kUwMacaroonCaveatTypeTTL1Hour:
-      if (!(state->has_issued_time)) {
+      if (state->issued_time == 0) {
         return false;
       }
       return update_and_check_expiration_time(
           context->current_time, state->issued_time + 60 * 60, result);
 
     case kUwMacaroonCaveatTypeTTL24Hour:
-      if (!(state->has_issued_time)) {
+      if (state->issued_time == 0) {
         return false;
       }
       return update_and_check_expiration_time(
@@ -496,7 +495,8 @@
     case kUwMacaroonCaveatTypeDelegateeUser:
     case kUwMacaroonCaveatTypeDelegateeApp:
     case kUwMacaroonCaveatTypeDelegateeService:
-      return update_delegatee_list(caveat_type, caveat, result);
+      return update_delegatee_list(caveat_type, caveat, state->issued_time,
+                                   result);
 
     // Time related caveats
     case kUwMacaroonCaveatTypeExpirationAbsolute:
@@ -596,7 +596,6 @@
     return false;
   }
 
-  state->has_issued_time = false;
   state->issued_time = 0;
   return true;
 }
diff --git a/third_party/libuweave/src/macaroon_caveat.h b/third_party/libuweave/src/macaroon_caveat.h
index 33f9d24..4905667 100644
--- a/third_party/libuweave/src/macaroon_caveat.h
+++ b/third_party/libuweave/src/macaroon_caveat.h
@@ -40,6 +40,9 @@
   kUwMacaroonCaveatScopeTypeViewer = 20,
 } UwMacaroonCaveatScopeType;
 
+// For security sanity checks
+#define UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE 127
+
 /** Compute the buffer sizes that are enough for caveat creation functions. */
 size_t uw_macaroon_caveat_creation_get_buffsize_(UwMacaroonCaveatType type,
                                                  size_t str_len);
diff --git a/third_party/libuweave/src/macaroon_caveat_internal.h b/third_party/libuweave/src/macaroon_caveat_internal.h
index 46a72fb..d6e7b07 100644
--- a/third_party/libuweave/src/macaroon_caveat_internal.h
+++ b/third_party/libuweave/src/macaroon_caveat_internal.h
@@ -20,8 +20,7 @@
                               size_t mac_tag_size);
 
 typedef struct {
-  bool has_issued_time;
-  uint32_t issued_time;
+  uint32_t issued_time;  // 0 when invalid or not set.
 } UwMacaroonValidationState;
 
 bool uw_macaroon_caveat_init_validation_state_(