diff --git a/core/c/mpw-marshall.c b/core/c/mpw-marshall.c index e54ae06f..f843a57b 100644 --- a/core/c/mpw-marshall.c +++ b/core/c/mpw-marshall.c @@ -228,7 +228,6 @@ bool mpw_marshall_write_json( time_t now = time( NULL ); if (strftime( dateString, dateSize, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", gmtime( &now ) )) json_object_object_add( json_export, "date", json_object_new_string( dateString ) ); - json_object_put( json_export ); // Section: "user" json_object *json_user = json_object_new_object(); @@ -242,7 +241,6 @@ bool mpw_marshall_write_json( json_object_object_add( json_user, "algorithm", json_object_new_int( marshalledUser->algorithm ) ); json_object_object_add( json_user, "default_type", json_object_new_int( marshalledUser->defaultType ) ); - json_object_put( json_user ); // Section "sites" json_object *json_sites = json_object_new_object(); @@ -272,8 +270,8 @@ bool mpw_marshall_write_json( json_object_object_add( json_site, "algorithm", json_object_new_int( site.algorithm ) ); if (content) json_object_object_add( json_site, "password", json_object_new_string( content ) ); - - json_object_object_add( json_site, "login_name", json_object_new_string( site.loginName?: "" ) ); + if (site.loginName) + json_object_object_add( json_site, "login_name", json_object_new_string( site.loginName ) ); json_object_object_add( json_site, "login_generated", json_object_new_boolean( site.loginGenerated ) ); json_object_object_add( json_site, "uses", json_object_new_int( site.uses ) ); @@ -292,21 +290,17 @@ bool mpw_marshall_write_json( json_object_object_add( json_site_question, "answer", json_object_new_string( mpw_passwordForSite( masterKey, site.name, MPSiteTypeGeneratedPhrase, 1, MPSiteVariantAnswer, question.keyword, site.algorithm ) ) ); - json_object_put( json_site_question ); } - json_object_put( json_site_questions ); json_object *json_site_mpw = json_object_new_object(); json_object_object_add( json_site, "_ext_mpw", json_site_mpw ); - json_object_object_add( json_site_mpw, "url", json_object_new_string( site.url ) ); - json_object_put( json_site_mpw ); - json_object_put( json_site ); + if (site.url) + json_object_object_add( json_site_mpw, "url", json_object_new_string( site.url ) ); } - json_object_put( json_sites ); - try_asprintf( out, "%s\n", json_object_to_json_string_ext( json_out, JSON_C_TO_STRING_PRETTY ) ); - json_object_put( json_out ); + try_asprintf( out, "%s\n", json_object_to_json_string_ext( json_out, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED ) ); mpw_free( masterKey, MPMasterKeySize ); + json_object_put( json_out ); return true; } @@ -405,8 +399,8 @@ MPMarshalledUser *mpw_marshall_read_flat( if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, importAlgorithm, importUserName, masterPassword )) return false; - if (importKeyID && strcmp( importKeyID, mpw_id_buf( masterKey, MPMasterKeySize ) ) != 0) { - err( "Incorrect master password for user import file.\n" ); + if (importKeyID && !mpw_id_buf_equals( importKeyID, mpw_id_buf( masterKey, MPMasterKeySize ) )) { + err( "Incorrect master password for user import file: %s != %s\n", importKeyID, mpw_id_buf( masterKey, MPMasterKeySize ) ); return false; } if (!(user = mpw_marshall_user( importUserName, masterPassword, importAlgorithm ))) { diff --git a/core/c/mpw-util.c b/core/c/mpw-util.c index fd67d490..3bef5b29 100644 --- a/core/c/mpw-util.c +++ b/core/c/mpw-util.c @@ -19,6 +19,7 @@ #include #include #include +#include #if MPW_COLOR #include @@ -80,7 +81,7 @@ bool mpw_free(const void *buffer, const size_t bufferSize) { bool mpw_free_string(const char *string) { - return mpw_free( string, strlen( string ) ); + return string && mpw_free( string, strlen( string ) ); } uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize, @@ -141,14 +142,25 @@ const char *mpw_id_buf(const void *buf, size_t length) { #if HAS_CPERCIVA uint8_t hash[32]; SHA256_Buf( buf, length, hash ); - - return mpw_hex( hash, 32 ); #elif HAS_SODIUM uint8_t hash[crypto_hash_sha256_BYTES]; crypto_hash_sha256( hash, buf, length ); - - return mpw_hex( hash, crypto_hash_sha256_BYTES ); #endif + + return mpw_hex( hash, sizeof( hash ) / sizeof( uint8_t ) ); +} + +bool mpw_id_buf_equals(const char *id1, const char *id2) { + + size_t size = strlen( id1 ); + if (size != strlen( id2 )) + return false; + + for (int c = 0; c < size; ++c) + if (tolower(id1[c]) != tolower(id2[c])) + return false; + + return true; } static char **mpw_hex_buf = NULL; diff --git a/core/c/mpw-util.h b/core/c/mpw-util.h index 122d9ef5..0f4b754c 100644 --- a/core/c/mpw-util.h +++ b/core/c/mpw-util.h @@ -122,6 +122,9 @@ const char *mpw_hex_l(uint32_t number); /** Encode a fingerprint for a buffer. * @return A C-string in a reused buffer, do not free or store it. */ const char *mpw_id_buf(const void *buf, size_t length); +/** Compare two fingerprints for equality. + * @return true if the buffers represent identical fingerprints. */ +bool mpw_id_buf_equals(const char *id1, const char *id2); /** Encode a visual fingerprint for a user. * @return A newly allocated string. */ const char *mpw_identicon(const char *fullName, const char *masterPassword);