| // Copyright 2015 The Weave Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/macaroon_caveat.h" | |
| #include "src/macaroon_caveat_internal.h" | |
| #include <string.h> | |
| #include "src/crypto_hmac.h" | |
| #include "src/macaroon.h" | |
| #include "src/macaroon_context.h" | |
| #include "src/macaroon_encoding.h" | |
| static bool is_valid_caveat_type_(UwMacaroonCaveatType type) { | |
| switch (type) { | |
| case kUwMacaroonCaveatTypeNonce: | |
| case kUwMacaroonCaveatTypeScope: | |
| case kUwMacaroonCaveatTypeExpirationAbsolute: | |
| case kUwMacaroonCaveatTypeTTL1Hour: | |
| case kUwMacaroonCaveatTypeTTL24Hour: | |
| case kUwMacaroonCaveatTypeDelegationTimestamp: | |
| case kUwMacaroonCaveatTypeDelegateeUser: | |
| case kUwMacaroonCaveatTypeDelegateeApp: | |
| case kUwMacaroonCaveatTypeAppCommandsOnly: | |
| case kUwMacaroonCaveatTypeDelegateeService: | |
| case kUwMacaroonCaveatTypeBleSessionID: | |
| case kUwMacaroonCaveatTypeLanSessionID: | |
| case kUwMacaroonCaveatTypeAuthenticationChallenge: | |
| case kUwMacaroonCaveatTypeClientAuthorizationTokenV1: | |
| case kUwMacaroonCaveatTypeServerAuthenticationTokenV1: | |
| return true; | |
| } | |
| return false; | |
| } | |
| static bool is_valid_scope_type_(UwMacaroonCaveatScopeType type) { | |
| switch (type) { | |
| case kUwMacaroonCaveatScopeTypeOwner: | |
| case kUwMacaroonCaveatScopeTypeManager: | |
| case kUwMacaroonCaveatScopeTypeUser: | |
| case kUwMacaroonCaveatScopeTypeViewer: | |
| return true; | |
| } | |
| return false; | |
| } | |
| static bool is_valid_service_id_(UwMacaroonCaveatCloudServiceId service_id) { | |
| switch (service_id) { | |
| case kUwMacaroonCaveatCloudServiceIdNotCloudRegistered: | |
| case kUwMacaroonCaveatCloudServiceIdGoogleWeave: | |
| return true; | |
| } | |
| return false; | |
| } | |
| static bool create_caveat_no_value_(UwMacaroonCaveatType type, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| // (buffer_size == 0 || get_buffsize_() > buffer_size) will conver the case | |
| // that get_buffer_size_() returns 0 (for errors), so there is no need to | |
| // check get_buffer_size_() == 0 again. | |
| if (buffer == NULL || buffer_size == 0 || new_caveat == NULL || | |
| uw_macaroon_caveat_creation_get_buffsize_(type, 0) > buffer_size) { | |
| return false; | |
| } | |
| size_t encoded_str_len = 0, total_str_len = 0; | |
| if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size, | |
| &encoded_str_len)) { | |
| return false; | |
| } | |
| total_str_len += encoded_str_len; | |
| new_caveat->bytes = buffer; | |
| new_caveat->num_bytes = total_str_len; | |
| return true; | |
| } | |
| static bool create_caveat_uint_value_(UwMacaroonCaveatType type, | |
| uint32_t unsigned_int, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| if (buffer == NULL || buffer_size == 0 || new_caveat == NULL || | |
| uw_macaroon_caveat_creation_get_buffsize_(type, 0) > buffer_size) { | |
| return false; | |
| } | |
| size_t encoded_str_len = 0, total_str_len = 0; | |
| if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size, | |
| &encoded_str_len)) { | |
| return false; | |
| } | |
| total_str_len += encoded_str_len; | |
| if (!uw_macaroon_encoding_encode_uint_(unsigned_int, buffer + total_str_len, | |
| buffer_size - total_str_len, | |
| &encoded_str_len)) { | |
| return false; | |
| } | |
| total_str_len += encoded_str_len; | |
| new_caveat->bytes = buffer; | |
| new_caveat->num_bytes = total_str_len; | |
| return true; | |
| } | |
| static bool create_caveat_bstr_value_(UwMacaroonCaveatType type, | |
| const uint8_t* str, | |
| size_t str_len, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| if ((str == NULL && str_len != 0) || buffer == NULL || buffer_size == 0 || | |
| new_caveat == NULL || | |
| uw_macaroon_caveat_creation_get_buffsize_(type, str_len) > buffer_size) { | |
| return false; | |
| } | |
| size_t encoded_str_len = 0, total_str_len = 0; | |
| if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size, | |
| &encoded_str_len)) { | |
| return false; | |
| } | |
| total_str_len += encoded_str_len; | |
| if (!uw_macaroon_encoding_encode_byte_str_( | |
| str, str_len, buffer + total_str_len, buffer_size - total_str_len, | |
| &encoded_str_len)) { | |
| return false; | |
| } | |
| total_str_len += encoded_str_len; | |
| new_caveat->bytes = buffer; | |
| new_caveat->num_bytes = total_str_len; | |
| return true; | |
| } | |
| size_t uw_macaroon_caveat_creation_get_buffsize_(UwMacaroonCaveatType type, | |
| size_t str_len) { | |
| switch (type) { | |
| // No values | |
| case kUwMacaroonCaveatTypeTTL1Hour: | |
| case kUwMacaroonCaveatTypeTTL24Hour: | |
| case kUwMacaroonCaveatTypeAppCommandsOnly: | |
| case kUwMacaroonCaveatTypeBleSessionID: | |
| case kUwMacaroonCaveatTypeAuthenticationChallenge: | |
| return UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN; | |
| // Unsigned integers | |
| case kUwMacaroonCaveatTypeScope: | |
| case kUwMacaroonCaveatTypeDelegateeService: | |
| case kUwMacaroonCaveatTypeExpirationAbsolute: | |
| case kUwMacaroonCaveatTypeDelegationTimestamp: | |
| return 2 * UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN; | |
| // Byte strings | |
| case kUwMacaroonCaveatTypeNonce: | |
| case kUwMacaroonCaveatTypeDelegateeUser: | |
| case kUwMacaroonCaveatTypeDelegateeApp: | |
| case kUwMacaroonCaveatTypeLanSessionID: | |
| case kUwMacaroonCaveatTypeClientAuthorizationTokenV1: | |
| case kUwMacaroonCaveatTypeServerAuthenticationTokenV1: | |
| return str_len + 2 * UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN; | |
| default: | |
| return 0; // For errors | |
| } | |
| } | |
| bool uw_macaroon_caveat_create_nonce_(const uint8_t* nonce, | |
| size_t nonce_size, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_bstr_value_(kUwMacaroonCaveatTypeNonce, nonce, | |
| nonce_size, buffer, buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_scope_(UwMacaroonCaveatScopeType scope, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| if (!is_valid_scope_type_(scope)) { | |
| return false; | |
| } | |
| return create_caveat_uint_value_(kUwMacaroonCaveatTypeScope, scope, buffer, | |
| buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_expiration_absolute_( | |
| uint32_t expiration_time, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_uint_value_(kUwMacaroonCaveatTypeExpirationAbsolute, | |
| expiration_time, buffer, buffer_size, | |
| new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_ttl_1_hour_(uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_no_value_(kUwMacaroonCaveatTypeTTL1Hour, buffer, | |
| buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_ttl_24_hour_(uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_no_value_(kUwMacaroonCaveatTypeTTL24Hour, buffer, | |
| buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_delegation_timestamp_( | |
| uint32_t timestamp, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_uint_value_(kUwMacaroonCaveatTypeDelegationTimestamp, | |
| timestamp, buffer, buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_delegatee_user_(const uint8_t* id_str, | |
| size_t id_str_len, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeUser, id_str, | |
| id_str_len, buffer, buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_delegatee_app_(const uint8_t* id_str, | |
| size_t id_str_len, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeApp, id_str, | |
| id_str_len, buffer, buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_app_commands_only_( | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_no_value_(kUwMacaroonCaveatTypeAppCommandsOnly, buffer, | |
| buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_delegatee_service_( | |
| UwMacaroonCaveatCloudServiceId service_id, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| if (!is_valid_service_id_(service_id)) { | |
| return false; | |
| } | |
| return create_caveat_uint_value_(kUwMacaroonCaveatTypeDelegateeService, | |
| (uint32_t)service_id, buffer, buffer_size, | |
| new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_ble_session_id_(uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_no_value_(kUwMacaroonCaveatTypeBleSessionID, buffer, | |
| buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_lan_session_id_(const uint8_t* session_id, | |
| size_t session_id_len, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_bstr_value_(kUwMacaroonCaveatTypeLanSessionID, | |
| session_id, session_id_len, buffer, | |
| buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_authentication_challenge_( | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| return create_caveat_no_value_(kUwMacaroonCaveatTypeAuthenticationChallenge, | |
| buffer, buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_client_authorization_token_( | |
| const uint8_t* str, | |
| size_t str_len, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| if (str_len == 0) { | |
| return create_caveat_no_value_( | |
| kUwMacaroonCaveatTypeClientAuthorizationTokenV1, buffer, buffer_size, | |
| new_caveat); | |
| } | |
| return create_caveat_bstr_value_( | |
| kUwMacaroonCaveatTypeClientAuthorizationTokenV1, str, str_len, buffer, | |
| buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_create_server_authentication_token_( | |
| const uint8_t* str, | |
| size_t str_len, | |
| uint8_t* buffer, | |
| size_t buffer_size, | |
| UwMacaroonCaveat* new_caveat) { | |
| if (str_len == 0) { | |
| return create_caveat_no_value_( | |
| kUwMacaroonCaveatTypeServerAuthenticationTokenV1, buffer, buffer_size, | |
| new_caveat); | |
| } | |
| return create_caveat_bstr_value_( | |
| kUwMacaroonCaveatTypeServerAuthenticationTokenV1, str, str_len, buffer, | |
| buffer_size, new_caveat); | |
| } | |
| bool uw_macaroon_caveat_get_type_(const UwMacaroonCaveat* caveat, | |
| UwMacaroonCaveatType* type) { | |
| if (caveat == NULL || type == NULL) { | |
| return false; | |
| } | |
| uint32_t unsigned_int; | |
| if (!uw_macaroon_encoding_decode_uint_(caveat->bytes, caveat->num_bytes, | |
| &unsigned_int)) { | |
| return false; | |
| } | |
| *type = (UwMacaroonCaveatType)unsigned_int; | |
| return is_valid_caveat_type_(*type); | |
| } | |
| /* === Some internal functions defined in macaroon_caveat_internal.h === */ | |
| bool uw_macaroon_caveat_sign_(const uint8_t* key, | |
| size_t key_len, | |
| const UwMacaroonContext* context, | |
| const UwMacaroonCaveat* caveat, | |
| uint8_t* mac_tag, | |
| size_t mac_tag_size) { | |
| if (key == NULL || key_len == 0 || context == NULL || caveat == NULL || | |
| mac_tag == NULL || mac_tag_size == 0) { | |
| return false; | |
| } | |
| UwMacaroonCaveatType caveat_type; | |
| if (!uw_macaroon_caveat_get_type_(caveat, &caveat_type) || | |
| !is_valid_caveat_type_(caveat_type)) { | |
| return false; | |
| } | |
| // Need to encode the whole caveat as a byte string and then sign it | |
| // If there is no additional value from the context, just compute the HMAC on | |
| // the current byte string. | |
| uint8_t caveat_cbor_prefix[UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN] = {0}; | |
| size_t caveat_cbor_prefix_len = 0; | |
| if (caveat_type != kUwMacaroonCaveatTypeBleSessionID && | |
| caveat_type != kUwMacaroonCaveatTypeAuthenticationChallenge) { | |
| if (!uw_macaroon_encoding_encode_byte_str_len_( | |
| (uint32_t)(caveat->num_bytes), caveat_cbor_prefix, | |
| sizeof(caveat_cbor_prefix), &caveat_cbor_prefix_len)) { | |
| return false; | |
| } | |
| UwCryptoHmacMsg messages[] = { | |
| {caveat_cbor_prefix, caveat_cbor_prefix_len}, | |
| {caveat->bytes, caveat->num_bytes}, | |
| }; | |
| return uw_crypto_hmac_(key, key_len, messages, | |
| sizeof(messages) / sizeof(messages[0]), mac_tag, | |
| mac_tag_size); | |
| } | |
| // If there is additional value from the context. | |
| const uint8_t* additional_value_str = NULL; | |
| size_t additional_value_str_len = 0; | |
| if (caveat_type == kUwMacaroonCaveatTypeBleSessionID) { | |
| if (context->ble_session_id == NULL || context->ble_session_id_len == 0) { | |
| return false; | |
| } | |
| additional_value_str = context->ble_session_id; | |
| additional_value_str_len = context->ble_session_id_len; | |
| } else { // kUwMacaroonCaveatTypeAuthenticationChallenge | |
| if (context->auth_challenge_str == NULL || | |
| context->auth_challenge_str_len == 0) { | |
| return false; | |
| } | |
| additional_value_str = context->auth_challenge_str; | |
| additional_value_str_len = context->auth_challenge_str_len; | |
| } | |
| uint8_t value_cbor_prefix[UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN] = {0}; | |
| size_t value_cbor_prefix_len = 0; | |
| if (!uw_macaroon_encoding_encode_byte_str_len_( | |
| (uint32_t)additional_value_str_len, value_cbor_prefix, | |
| sizeof(value_cbor_prefix), &value_cbor_prefix_len)) { | |
| return false; | |
| } | |
| // The length here includes: 1. the header for the whole byte string; 2. the | |
| // header for the addtional value part; 3. the additional value part. | |
| size_t total_length = | |
| caveat->num_bytes + value_cbor_prefix_len + additional_value_str_len; | |
| if (!uw_macaroon_encoding_encode_byte_str_len_( | |
| (uint32_t)total_length, caveat_cbor_prefix, | |
| sizeof(caveat_cbor_prefix), &caveat_cbor_prefix_len)) { | |
| return false; | |
| } | |
| UwCryptoHmacMsg messages[] = { | |
| {caveat_cbor_prefix, caveat_cbor_prefix_len}, | |
| {caveat->bytes, caveat->num_bytes}, | |
| {value_cbor_prefix, value_cbor_prefix_len}, | |
| {additional_value_str, additional_value_str_len}, | |
| }; | |
| return uw_crypto_hmac_(key, key_len, messages, | |
| sizeof(messages) / sizeof(messages[0]), mac_tag, | |
| mac_tag_size); | |
| } | |
| static bool update_and_check_expiration_time( | |
| uint32_t current_time, | |
| uint32_t new_expiration_time, | |
| UwMacaroonValidationResult* result) { | |
| if (result->expiration_time > new_expiration_time) { | |
| result->expiration_time = new_expiration_time; | |
| } | |
| return current_time <= result->expiration_time; | |
| } | |
| static bool update_delegatee_list(UwMacaroonCaveatType caveat_type, | |
| const UwMacaroonCaveat* caveat, | |
| uint32_t issued_time, | |
| UwMacaroonValidationResult* result) { | |
| if (result->num_delegatees >= MAX_NUM_DELEGATEES || issued_time == 0) { | |
| return false; | |
| } | |
| UwMacaroonDelegateeType delegatee_type = kUwMacaroonDelegateeTypeNone; | |
| switch (caveat_type) { | |
| case kUwMacaroonCaveatTypeDelegateeUser: | |
| delegatee_type = kUwMacaroonDelegateeTypeUser; | |
| break; | |
| case kUwMacaroonCaveatTypeDelegateeApp: | |
| delegatee_type = kUwMacaroonDelegateeTypeApp; | |
| break; | |
| case kUwMacaroonCaveatTypeDelegateeService: | |
| delegatee_type = kUwMacaroonDelegateeTypeService; | |
| break; | |
| default: | |
| return false; | |
| } | |
| if (caveat_type != kUwMacaroonCaveatTypeDelegateeUser) { | |
| for (size_t i = 0; i < result->num_delegatees; i++) { | |
| // There must have at most one DelegateeApp or DelegateeService | |
| if (result->delegatees[i].type == delegatee_type) { | |
| return false; | |
| } | |
| } | |
| } | |
| if (caveat_type != kUwMacaroonCaveatTypeDelegateeService) { | |
| if (!uw_macaroon_caveat_get_value_bstr_( | |
| caveat, &(result->delegatees[result->num_delegatees].id), | |
| &(result->delegatees[result->num_delegatees].id_len))) { | |
| return false; | |
| } | |
| result->delegatees[result->num_delegatees].service_id = | |
| kUwMacaroonCaveatCloudServiceIdNotCloudRegistered; // Default value | |
| } else { | |
| uint32_t service_id = 0; | |
| if (!uw_macaroon_caveat_get_value_uint_(caveat, &service_id)) { | |
| return false; | |
| } | |
| if (!is_valid_service_id_((UwMacaroonCaveatCloudServiceId)service_id)) { | |
| return false; | |
| } | |
| result->delegatees[result->num_delegatees].service_id = | |
| (UwMacaroonCaveatCloudServiceId)service_id; | |
| result->delegatees[result->num_delegatees].id = NULL; | |
| result->delegatees[result->num_delegatees].id_len = 0; | |
| } | |
| result->delegatees[result->num_delegatees].type = delegatee_type; | |
| result->delegatees[result->num_delegatees].timestamp = issued_time; | |
| result->num_delegatees++; | |
| return true; | |
| } | |
| bool uw_macaroon_caveat_validate_(const UwMacaroonCaveat* caveat, | |
| const UwMacaroonContext* context, | |
| UwMacaroonValidationState* state, | |
| UwMacaroonValidationResult* result) { | |
| if (caveat == NULL || context == NULL || state == NULL || result == NULL) { | |
| return false; | |
| } | |
| uint32_t expiration_time = 0; | |
| uint32_t issued_time = 0; | |
| uint32_t scope = UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE; | |
| UwMacaroonCaveatType caveat_type; | |
| if (!uw_macaroon_caveat_get_type_(caveat, &caveat_type)) { | |
| return false; | |
| } | |
| switch (caveat_type) { | |
| // The types that always validate | |
| case kUwMacaroonCaveatTypeClientAuthorizationTokenV1: | |
| case kUwMacaroonCaveatTypeServerAuthenticationTokenV1: | |
| case kUwMacaroonCaveatTypeNonce: | |
| case kUwMacaroonCaveatTypeBleSessionID: | |
| case kUwMacaroonCaveatTypeAuthenticationChallenge: | |
| return true; | |
| case kUwMacaroonCaveatTypeDelegationTimestamp: | |
| 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->issued_time == 0) { | |
| return false; | |
| } | |
| return update_and_check_expiration_time( | |
| context->current_time, state->issued_time + 60 * 60, result); | |
| case kUwMacaroonCaveatTypeTTL24Hour: | |
| if (state->issued_time == 0) { | |
| return false; | |
| } | |
| return update_and_check_expiration_time( | |
| context->current_time, state->issued_time + 24 * 60 * 60, result); | |
| // Need to create a list of delegatees | |
| case kUwMacaroonCaveatTypeDelegateeUser: | |
| case kUwMacaroonCaveatTypeDelegateeApp: | |
| case kUwMacaroonCaveatTypeDelegateeService: | |
| return update_delegatee_list(caveat_type, caveat, state->issued_time, | |
| result); | |
| // Time related caveats | |
| case kUwMacaroonCaveatTypeExpirationAbsolute: | |
| if (!uw_macaroon_caveat_get_value_uint_(caveat, &expiration_time)) { | |
| return false; | |
| } | |
| return update_and_check_expiration_time(context->current_time, | |
| expiration_time, result); | |
| // The caveats that update the values of the result object | |
| case kUwMacaroonCaveatTypeScope: | |
| if (!uw_macaroon_caveat_get_value_uint_(caveat, &scope) || | |
| // Larger value means less priviledge | |
| scope > UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE) { | |
| return false; | |
| } | |
| if (scope > (uint32_t)(result->granted_scope)) { | |
| result->granted_scope = (UwMacaroonCaveatScopeType)scope; | |
| } | |
| return true; | |
| case kUwMacaroonCaveatTypeAppCommandsOnly: | |
| result->weave_app_restricted = true; | |
| return true; | |
| case kUwMacaroonCaveatTypeLanSessionID: | |
| return uw_macaroon_caveat_get_value_bstr_( | |
| caveat, &(result->lan_session_id), &(result->lan_session_id_len)); | |
| } | |
| return false; | |
| } | |
| bool uw_macaroon_caveat_get_value_uint_(const UwMacaroonCaveat* caveat, | |
| uint32_t* unsigned_int) { | |
| if (caveat == NULL || unsigned_int == NULL) { | |
| return false; | |
| } | |
| UwMacaroonCaveatType type; | |
| if (!uw_macaroon_caveat_get_type_(caveat, &type)) { | |
| return false; | |
| } | |
| if (type != kUwMacaroonCaveatTypeScope && | |
| type != kUwMacaroonCaveatTypeDelegateeService && | |
| type != kUwMacaroonCaveatTypeExpirationAbsolute && | |
| type != kUwMacaroonCaveatTypeDelegationTimestamp) { | |
| // Wrong type | |
| return false; | |
| } | |
| // Skip the portion for CBOR type | |
| size_t offset; | |
| if (!uw_macaroon_encoding_get_item_len_(caveat->bytes, caveat->num_bytes, | |
| &offset)) { | |
| return false; | |
| } | |
| return uw_macaroon_encoding_decode_uint_( | |
| caveat->bytes + offset, caveat->num_bytes - offset, unsigned_int); | |
| } | |
| bool uw_macaroon_caveat_get_value_bstr_(const UwMacaroonCaveat* caveat, | |
| const uint8_t** str, | |
| size_t* str_len) { | |
| if (caveat == NULL || str == NULL || str_len == NULL) { | |
| return false; | |
| } | |
| UwMacaroonCaveatType type; | |
| if (!uw_macaroon_caveat_get_type_(caveat, &type)) { | |
| return false; | |
| } | |
| if (type != kUwMacaroonCaveatTypeNonce && | |
| type != kUwMacaroonCaveatTypeDelegateeUser && | |
| type != kUwMacaroonCaveatTypeDelegateeApp && | |
| type != kUwMacaroonCaveatTypeLanSessionID && | |
| type != kUwMacaroonCaveatTypeClientAuthorizationTokenV1 && | |
| type != kUwMacaroonCaveatTypeServerAuthenticationTokenV1) { | |
| // Wrong type | |
| return false; | |
| } | |
| size_t offset; | |
| if (!uw_macaroon_encoding_get_item_len_(caveat->bytes, caveat->num_bytes, | |
| &offset)) { | |
| return false; | |
| } | |
| return uw_macaroon_encoding_decode_byte_str_( | |
| caveat->bytes + offset, caveat->num_bytes - offset, str, str_len); | |
| } | |
| bool uw_macaroon_caveat_init_validation_state_( | |
| UwMacaroonValidationState* state) { | |
| if (state == NULL) { | |
| return false; | |
| } | |
| state->issued_time = 0; | |
| return true; | |
| } |