diff options
Diffstat (limited to 'src/lib/anastasis_recovery.c')
-rw-r--r-- | src/lib/anastasis_recovery.c | 211 |
1 files changed, 117 insertions, 94 deletions
diff --git a/src/lib/anastasis_recovery.c b/src/lib/anastasis_recovery.c index c9f8c0e..41f35a5 100644 --- a/src/lib/anastasis_recovery.c +++ b/src/lib/anastasis_recovery.c @@ -612,23 +612,22 @@ ANASTASIS_challenge_abort (struct ANASTASIS_Challenge *c) * Function called with the results of a #ANASTASIS_policy_lookup() * * @param cls closure - * @param http_status HTTp status code. * @param dd details about the lookup operation */ static void policy_lookup_cb (void *cls, - unsigned int http_status, const struct ANASTASIS_DownloadDetails *dd) { struct ANASTASIS_Recovery *r = cls; void *plaintext; size_t size_plaintext; json_error_t json_error; - json_t *dec_policies; - json_t *esc_methods; + const json_t *dec_policies; + const json_t *esc_methods; + json_t *recovery_document; r->plo = NULL; - switch (http_status) + switch (dd->http_status) { case MHD_HTTP_OK: break; @@ -660,7 +659,7 @@ policy_lookup_cb (void *cls, default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u in %s:%u\n", - http_status, + dd->http_status, __FILE__, __LINE__); r->csc (r->csc_cls, @@ -670,7 +669,7 @@ policy_lookup_cb (void *cls, ANASTASIS_recovery_abort (r); return; } - if (NULL == dd->policy) + if (NULL == dd->details.ok.policy) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No recovery data available"); @@ -682,8 +681,8 @@ policy_lookup_cb (void *cls, return; } ANASTASIS_CRYPTO_recovery_document_decrypt (&r->id, - dd->policy, - dd->policy_size, + dd->details.ok.policy, + dd->details.ok.policy_size, &plaintext, &size_plaintext); if (size_plaintext < sizeof (uint32_t)) @@ -698,7 +697,6 @@ policy_lookup_cb (void *cls, return; } { - json_t *recovery_document; uint32_t be_size; uLongf pt_size; char *pt; @@ -761,10 +759,10 @@ policy_lookup_cb (void *cls, { const char *secret_name = NULL; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_json ("policies", - &dec_policies), - GNUNET_JSON_spec_json ("escrow_methods", - &esc_methods), + GNUNET_JSON_spec_array_const ("policies", + &dec_policies), + GNUNET_JSON_spec_array_const ("escrow_methods", + &esc_methods), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("secret_name", &secret_name), @@ -784,13 +782,11 @@ policy_lookup_cb (void *cls, json_dumpf (recovery_document, stderr, 0); - json_decref (recovery_document); r->csc (r->csc_cls, ANASTASIS_RS_POLICY_MALFORMED_JSON, NULL, 0); - ANASTASIS_recovery_abort (r); - return; + goto cleanup; } if (NULL != secret_name) { @@ -799,22 +795,39 @@ policy_lookup_cb (void *cls, r->ri.secret_name = r->secret_name; } } - json_decref (recovery_document); } - r->ri.version = dd->version; - r->ri.cs_len = json_array_size (esc_methods); - r->ri.dps_len = json_array_size (dec_policies); - r->ri.dps = GNUNET_new_array (r->ri.dps_len, - struct ANASTASIS_DecryptionPolicy *); - r->dps = GNUNET_new_array (r->ri.dps_len, - struct DecryptionPolicy); - r->solved_challenges = GNUNET_new_array (r->ri.cs_len, - struct ANASTASIS_Challenge *); - r->ri.cs = GNUNET_new_array (r->ri.cs_len, - struct ANASTASIS_Challenge *); - r->cs = GNUNET_new_array (r->ri.cs_len, - struct ANASTASIS_Challenge); + if ( (json_array_size (esc_methods) > UINT_MAX) || + (json_array_size (dec_policies) > UINT_MAX) ) + { + GNUNET_break_op (0); + r->csc (r->csc_cls, + ANASTASIS_RS_POLICY_DOWNLOAD_TOO_BIG, + NULL, + 0); + goto cleanup; + } + + r->ri.version = dd->details.ok.version; + r->ri.cs_len + = (unsigned int) json_array_size (esc_methods); + r->ri.dps_len + = (unsigned int) json_array_size (dec_policies); + r->ri.dps + = GNUNET_new_array (r->ri.dps_len, + struct ANASTASIS_DecryptionPolicy *); + r->dps + = GNUNET_new_array (r->ri.dps_len, + struct DecryptionPolicy); + r->solved_challenges + = GNUNET_new_array (r->ri.cs_len, + struct ANASTASIS_Challenge *); + r->ri.cs + = GNUNET_new_array (r->ri.cs_len, + struct ANASTASIS_Challenge *); + r->cs + = GNUNET_new_array (r->ri.cs_len, + struct ANASTASIS_Challenge); for (unsigned int i = 0; i < r->ri.cs_len; i++) { struct ANASTASIS_Challenge *cs = &r->cs[i]; @@ -824,7 +837,7 @@ policy_lookup_cb (void *cls, struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("uuid", &cs->ci.uuid), - GNUNET_JSON_spec_string ("url", + TALER_JSON_spec_web_url ("url", &url), GNUNET_JSON_spec_string ("instructions", &instructions), @@ -848,14 +861,11 @@ policy_lookup_cb (void *cls, NULL, NULL)) { GNUNET_break_op (0); - json_decref (esc_methods); - json_decref (dec_policies); r->csc (r->csc_cls, ANASTASIS_RS_POLICY_MALFORMED_JSON, NULL, 0); - ANASTASIS_recovery_abort (r); - return; + goto cleanup; } cs->url = GNUNET_strdup (url); cs->type = GNUNET_strdup (escrow_type); @@ -864,13 +874,11 @@ policy_lookup_cb (void *cls, cs->instructions = GNUNET_strdup (instructions); cs->ci.instructions = cs->instructions; } - json_decref (esc_methods); for (unsigned int j = 0; j < r->ri.dps_len; j++) { struct DecryptionPolicy *dp = &r->dps[j]; - - json_t *uuids = NULL; + const json_t *uuids; json_t *uuid; size_t n_index; struct GNUNET_JSON_Specification spec[] = { @@ -879,34 +887,40 @@ policy_lookup_cb (void *cls, &dp->emk_size), GNUNET_JSON_spec_fixed_auto ("master_salt", &dp->master_salt), - GNUNET_JSON_spec_json ("uuids", - &uuids), + GNUNET_JSON_spec_array_const ("uuids", + &uuids), GNUNET_JSON_spec_end () }; r->ri.dps[j] = &r->dps[j].pub_details; - if ( (GNUNET_OK != - GNUNET_JSON_parse (json_array_get (dec_policies, - j), - spec, - NULL, NULL)) || - (! json_is_array (uuids)) ) + if (GNUNET_OK != + GNUNET_JSON_parse (json_array_get (dec_policies, + j), + spec, + NULL, NULL)) { GNUNET_break_op (0); - json_decref (uuids); - json_decref (dec_policies); r->csc (r->csc_cls, ANASTASIS_RS_POLICY_MALFORMED_JSON, NULL, 0); - ANASTASIS_recovery_abort (r); - return; + goto cleanup; } GNUNET_assert (NULL != dp->emk); GNUNET_assert (dp->emk_size > 0); - dp->pub_details.challenges_length = json_array_size (uuids); + if (json_array_size (uuids) > UINT_MAX) + { + GNUNET_break_op (0); + r->csc (r->csc_cls, + ANASTASIS_RS_POLICY_MALFORMED_JSON, + NULL, + 0); + goto cleanup; + } + dp->pub_details.challenges_length + = (unsigned int) json_array_size (uuids); dp->pub_details.challenges = GNUNET_new_array (dp->pub_details.challenges_length, struct ANASTASIS_Challenge *); @@ -925,14 +939,11 @@ policy_lookup_cb (void *cls, sizeof (uuid))) ) { GNUNET_break_op (0); - json_decref (dec_policies); - json_decref (uuids); r->csc (r->csc_cls, ANASTASIS_RS_POLICY_MALFORMED_JSON, NULL, 0); - ANASTASIS_recovery_abort (r); - return; + goto cleanup; } for (unsigned int i = 0; i<r->ri.cs_len; i++) { @@ -947,21 +958,21 @@ policy_lookup_cb (void *cls, if (! found) { GNUNET_break_op (0); - json_decref (dec_policies); - json_decref (uuids); r->csc (r->csc_cls, ANASTASIS_RS_POLICY_MALFORMED_JSON, NULL, 0); - ANASTASIS_recovery_abort (r); - return; + goto cleanup; } } - json_decref (uuids); } - json_decref (dec_policies); r->pc (r->pc_cls, &r->ri); + json_decref (recovery_document); + return; +cleanup: + ANASTASIS_recovery_abort (r); + json_decref (recovery_document); } @@ -1134,19 +1145,26 @@ ANASTASIS_recovery_serialize (const struct ANASTASIS_Recovery *r) */ static enum GNUNET_GenericReturnValue parse_cs_array (struct ANASTASIS_Recovery *r, - json_t *cs_arr) + const json_t *cs_arr) { json_t *cs; - unsigned int n_index; + size_t n_index; if (! json_is_array (cs_arr)) { GNUNET_break_op (0); return GNUNET_SYSERR; } - r->ri.cs_len = json_array_size (cs_arr); - r->solved_challenges = GNUNET_new_array (r->ri.cs_len, - struct ANASTASIS_Challenge *); + if (json_array_size (cs_arr) > UINT_MAX) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + r->ri.cs_len + = (unsigned int) json_array_size (cs_arr); + r->solved_challenges + = GNUNET_new_array (r->ri.cs_len, + struct ANASTASIS_Challenge *); r->ri.cs = GNUNET_new_array (r->ri.cs_len, struct ANASTASIS_Challenge *); r->cs = GNUNET_new_array (r->ri.cs_len, @@ -1161,7 +1179,7 @@ parse_cs_array (struct ANASTASIS_Recovery *r, struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("uuid", &c->ci.uuid), - GNUNET_JSON_spec_string ("url", + TALER_JSON_spec_web_url ("url", &url), GNUNET_JSON_spec_string ("instructions", &instructions), @@ -1220,17 +1238,23 @@ parse_cs_array (struct ANASTASIS_Recovery *r, */ static enum GNUNET_GenericReturnValue parse_dps_array (struct ANASTASIS_Recovery *r, - json_t *dps_arr) + const json_t *dps_arr) { json_t *dps; - unsigned int n_index; + size_t n_index; if (! json_is_array (dps_arr)) { GNUNET_break_op (0); return GNUNET_SYSERR; } - r->ri.dps_len = json_array_size (dps_arr); + if (json_array_size (dps_arr) > UINT_MAX) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + r->ri.dps_len + = (unsigned int) json_array_size (dps_arr); r->dps = GNUNET_new_array (r->ri.dps_len, struct DecryptionPolicy); r->ri.dps = GNUNET_new_array (r->ri.dps_len, @@ -1239,15 +1263,15 @@ parse_dps_array (struct ANASTASIS_Recovery *r, json_array_foreach (dps_arr, n_index, dps) { struct DecryptionPolicy *dp = &r->dps[n_index]; - json_t *challenges; + const json_t *challenges; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_varsize ("encrypted_master_key", &dp->emk, &dp->emk_size), GNUNET_JSON_spec_fixed_auto ("master_salt", &dp->master_salt), - GNUNET_JSON_spec_json ("challenges", - &challenges), + GNUNET_JSON_spec_array_const ("challenges", + &challenges), GNUNET_JSON_spec_end () }; const char *err_json_name; @@ -1270,20 +1294,20 @@ parse_dps_array (struct ANASTASIS_Recovery *r, } GNUNET_assert (NULL != dp->emk); GNUNET_assert (dp->emk_size > 0); - if (! json_is_array (challenges)) + if (json_array_size (challenges) > UINT_MAX) { GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } - dp->pub_details.challenges_length = json_array_size (challenges); - dp->pub_details.challenges = GNUNET_new_array ( - dp->pub_details.challenges_length, - struct ANASTASIS_Challenge *); + dp->pub_details.challenges_length + = (unsigned int) json_array_size (challenges); + dp->pub_details.challenges + = GNUNET_new_array (dp->pub_details.challenges_length, + struct ANASTASIS_Challenge *); { json_t *challenge; - unsigned int c_index; + size_t c_index; json_array_foreach (challenges, c_index, challenge) { struct ANASTASIS_CRYPTO_TruthUUIDP uuid; @@ -1320,8 +1344,7 @@ parse_dps_array (struct ANASTASIS_Recovery *r, } } } - /* We don't free the spec, since we're still using dp->ems. */ - json_decref (challenges); + /* Do NOT free the spec: we are still using dp->ems. */ } return GNUNET_OK; } @@ -1363,9 +1386,9 @@ ANASTASIS_recovery_deserialize (struct GNUNET_CURL_Context *ctx, const char *err_json_name; unsigned int err_line; uint32_t version; - json_t *dps_arr; - json_t *cs_arr; - json_t *id_data; + const json_t *dps_arr; + const json_t *cs_arr; + const json_t *id_data; const char *provider_url; const char *secret_name; void *ecs; @@ -1373,7 +1396,7 @@ ANASTASIS_recovery_deserialize (struct GNUNET_CURL_Context *ctx, struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("id", &r->id), - GNUNET_JSON_spec_string ("provider_url", + TALER_JSON_spec_web_url ("provider_url", &provider_url), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("secret_name", @@ -1381,12 +1404,12 @@ ANASTASIS_recovery_deserialize (struct GNUNET_CURL_Context *ctx, NULL), GNUNET_JSON_spec_uint32 ("version", &version), - GNUNET_JSON_spec_json ("decryption_policies", - &dps_arr), - GNUNET_JSON_spec_json ("challenges", - &cs_arr), - GNUNET_JSON_spec_json ("id_data", - &id_data), + GNUNET_JSON_spec_array_const ("decryption_policies", + &dps_arr), + GNUNET_JSON_spec_array_const ("challenges", + &cs_arr), + GNUNET_JSON_spec_object_const ("id_data", + &id_data), GNUNET_JSON_spec_varsize ("encrypted_core_secret", &ecs, &ecs_size), @@ -1420,7 +1443,7 @@ ANASTASIS_recovery_deserialize (struct GNUNET_CURL_Context *ctx, GNUNET_JSON_parse_free (spec); return NULL; } - r->id_data = json_incref (id_data); + r->id_data = json_incref ((json_t *) id_data); r->provider_url = GNUNET_strdup (provider_url); if (NULL != secret_name) r->secret_name = GNUNET_strdup (secret_name); |