2
0

Persist unknown JSON properties, expose to API, safety improvements.

This commit is contained in:
Maarten Billemont 2019-07-27 09:24:39 -04:00
parent fc1e86f0ca
commit ddb786c332
7 changed files with 317 additions and 133 deletions

View File

@ -489,7 +489,7 @@ void cli_user(Arguments *args, Operation *operation) {
mpw_free_string( &operation->sitesPath ); mpw_free_string( &operation->sitesPath );
mpw_marshal_free( &operation->file ); mpw_marshal_free( &operation->file );
operation->file = mpw_marshal_file( mpw_marshal_user( operation->file = mpw_marshal_file( mpw_marshal_user(
operation->fullName, cli_masterKeyProvider_op( operation ), MPAlgorithmVersionCurrent ) ); operation->fullName, cli_masterKeyProvider_op( operation ), MPAlgorithmVersionCurrent ), NULL );
} }
else { else {
@ -550,7 +550,7 @@ void cli_site(Arguments *args, Operation *operation) {
// Load the site object from mpsites. // Load the site object from mpsites.
MPMarshalledUser *user = operation->file->user; MPMarshalledUser *user = operation->file->user;
for (size_t s = 0; !operation->site && s < user->sites_count; ++s) for (size_t s = 0; !operation->site && s < user->sites_count; ++s)
if (strcmp( operation->siteName, (&user->sites[s])->siteName ) == 0) if (strcmp( operation->siteName, (&user->sites[s])->siteName ) == OK)
operation->site = &user->sites[s]; operation->site = &user->sites[s];
// If no site from mpsites, create a new one. // If no site from mpsites, create a new one.
@ -571,8 +571,11 @@ void cli_question(Arguments *args, Operation *operation) {
break; break;
case MPKeyPurposeRecovery: case MPKeyPurposeRecovery:
for (size_t q = 0; !operation->question && q < operation->site->questions_count; ++q) for (size_t q = 0; !operation->question && q < operation->site->questions_count; ++q)
if ((!operation->keyContext && !strlen( (&operation->site->questions[q])->keyword )) || if (operation->keyContext == (&operation->site->questions[q])->keyword ||
(operation->keyContext && strcmp( (&operation->site->questions[q])->keyword, operation->keyContext ) == 0)) (!operation->keyContext && !strlen( (&operation->site->questions[q])->keyword )) ||
(!(&operation->site->questions[q])->keyword && !strlen( operation->keyContext )) ||
((operation->keyContext && (&operation->site->questions[q])->keyword) &&
strcmp( (&operation->site->questions[q])->keyword, operation->keyContext ) == OK))
operation->question = &operation->site->questions[q]; operation->question = &operation->site->questions[q];
// If no question from mpsites, create a new one. // If no question from mpsites, create a new one.
@ -700,7 +703,7 @@ void cli_algorithmVersion(Arguments *args, Operation *operation) {
void cli_sitesRedacted(Arguments *args, Operation *operation) { void cli_sitesRedacted(Arguments *args, Operation *operation) {
if (args->sitesRedacted) if (args->sitesRedacted)
operation->file->user->redacted = strcmp( args->sitesRedacted, "1" ) == 0; operation->file->user->redacted = strcmp( args->sitesRedacted, "1" ) == OK;
else if (!operation->file->user->redacted) else if (!operation->file->user->redacted)
wrn( "Sites configuration is not redacted. Use -R 1 to change this." ); wrn( "Sites configuration is not redacted. Use -R 1 to change this." );

View File

@ -45,18 +45,21 @@ static xmlChar const *mpw_xmlPath(xmlNodePtr context) {
xmlNodePtr mpw_xmlTestCaseNode(xmlNodePtr testCaseNode, const char *nodeName) { xmlNodePtr mpw_xmlTestCaseNode(xmlNodePtr testCaseNode, const char *nodeName) {
if (!nodeName)
return NULL;
// Try to find an attribute node. // Try to find an attribute node.
for (xmlAttrPtr child = testCaseNode->properties; child; child = child->next) for (xmlAttrPtr child = testCaseNode->properties; child; child = child->next)
if (xmlStrcmp( child->name, BAD_CAST nodeName ) == 0) if (xmlStrcmp( child->name, BAD_CAST nodeName ) == OK)
return (xmlNodePtr)child; return (xmlNodePtr)child;
// Try to find an element node. // Try to find an element node.
for (xmlNodePtr child = testCaseNode->children; child; child = child->next) for (xmlNodePtr child = testCaseNode->children; child; child = child->next)
if (xmlStrcmp( child->name, BAD_CAST nodeName ) == 0) if (xmlStrcmp( child->name, BAD_CAST nodeName ) == OK)
return child; return child;
// Missing content, try to find parent case. // Missing content, try to find parent case.
if (strcmp( nodeName, "parent" ) == 0) if (strcmp( nodeName, "parent" ) == OK)
// Was just searching for testCaseNode's parent, none found. // Was just searching for testCaseNode's parent, none found.
return NULL; return NULL;
xmlChar *parentId = mpw_xmlTestCaseString( testCaseNode, "parent" ); xmlChar *parentId = mpw_xmlTestCaseString( testCaseNode, "parent" );
@ -66,7 +69,7 @@ xmlNodePtr mpw_xmlTestCaseNode(xmlNodePtr testCaseNode, const char *nodeName) {
for (xmlNodePtr otherTestCaseNode = testCaseNode->parent->children; otherTestCaseNode; otherTestCaseNode = otherTestCaseNode->next) { for (xmlNodePtr otherTestCaseNode = testCaseNode->parent->children; otherTestCaseNode; otherTestCaseNode = otherTestCaseNode->next) {
xmlChar *id = mpw_xmlTestCaseString( otherTestCaseNode, "id" ); xmlChar *id = mpw_xmlTestCaseString( otherTestCaseNode, "id" );
int foundParent = id && xmlStrcmp( id, parentId ) == 0; int foundParent = id && xmlStrcmp( id, parentId ) == OK;
xmlFree( id ); xmlFree( id );
if (foundParent) { if (foundParent) {
@ -81,12 +84,18 @@ xmlNodePtr mpw_xmlTestCaseNode(xmlNodePtr testCaseNode, const char *nodeName) {
xmlChar *mpw_xmlTestCaseString(xmlNodePtr context, const char *nodeName) { xmlChar *mpw_xmlTestCaseString(xmlNodePtr context, const char *nodeName) {
if (!nodeName)
return NULL;
xmlNodePtr child = mpw_xmlTestCaseNode( context, nodeName ); xmlNodePtr child = mpw_xmlTestCaseNode( context, nodeName );
return child? xmlNodeGetContent( child ): NULL; return child? xmlNodeGetContent( child ): NULL;
} }
uint32_t mpw_xmlTestCaseInteger(xmlNodePtr context, const char *nodeName) { uint32_t mpw_xmlTestCaseInteger(xmlNodePtr context, const char *nodeName) {
if (!nodeName)
return 0;
xmlChar *string = mpw_xmlTestCaseString( context, nodeName ); xmlChar *string = mpw_xmlTestCaseString( context, nodeName );
uint32_t integer = string? (uint32_t)atol( (char *)string ): 0; uint32_t integer = string? (uint32_t)atol( (char *)string ): 0;
xmlFree( string ); xmlFree( string );

View File

@ -58,26 +58,27 @@ time_t mpw_timegm(const char *time) {
} }
#if MPW_JSON #if MPW_JSON
json_object *mpw_get_json_section(
json_object *obj, const char *section) {
json_object *json_value = obj; json_object *mpw_get_json_object(
char *sectionTokenizer = mpw_strdup( section ), *sectionToken = sectionTokenizer; json_object *obj, const char *key, bool create) {
for (sectionToken = strtok( sectionToken, "." ); sectionToken; sectionToken = strtok( NULL, "." ))
if (!json_object_object_get_ex( json_value, sectionToken, &json_value ) || !json_value) { if (!obj)
trc( "While resolving: %s: Missing value for: %s", section, sectionToken ); return NULL;
json_object *json_value = NULL;
if (!json_object_object_get_ex( obj, key, &json_value ) || !json_value)
if (!create || json_object_object_add( obj, key, json_value = json_object_new_object() ) != OK) {
trc( "Missing value for: %s", key );
json_value = NULL; json_value = NULL;
break;
} }
free( sectionTokenizer );
return json_value; return json_value;
} }
const char *mpw_get_json_string( const char *mpw_get_json_string(
json_object *obj, const char *section, const char *defaultValue) { json_object *obj, const char *key, const char *defaultValue) {
json_object *json_value = mpw_get_json_section( obj, section ); json_object *json_value = mpw_get_json_object( obj, key, false );
if (!json_value) if (!json_value)
return defaultValue; return defaultValue;
@ -85,9 +86,9 @@ const char *mpw_get_json_string(
} }
int64_t mpw_get_json_int( int64_t mpw_get_json_int(
json_object *obj, const char *section, int64_t defaultValue) { json_object *obj, const char *key, int64_t defaultValue) {
json_object *json_value = mpw_get_json_section( obj, section ); json_object *json_value = mpw_get_json_object( obj, key, false );
if (!json_value) if (!json_value)
return defaultValue; return defaultValue;
@ -95,14 +96,15 @@ int64_t mpw_get_json_int(
} }
bool mpw_get_json_boolean( bool mpw_get_json_boolean(
json_object *obj, const char *section, bool defaultValue) { json_object *obj, const char *key, bool defaultValue) {
json_object *json_value = mpw_get_json_section( obj, section ); json_object *json_value = mpw_get_json_object( obj, key, false );
if (!json_value) if (!json_value)
return defaultValue; return defaultValue;
return json_object_get_boolean( json_value ) == true; return json_object_get_boolean( json_value ) == true;
} }
#endif #endif
bool mpw_update_master_key(MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, MPAlgorithmVersion targetKeyAlgorithm, bool mpw_update_master_key(MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, MPAlgorithmVersion targetKeyAlgorithm,

View File

@ -43,26 +43,27 @@ time_t mpw_timegm(
/// JSON parsing. /// JSON parsing.
#if MPW_JSON #if MPW_JSON
/** Search for a JSON child object in a JSON object tree. /** Search for an object in a JSON object tree.
* @param section A dot-delimited list of JSON object keys to walk toward the child object. * @param key A JSON object key for the child in this object.
* @return A JSON object (shared) or NULL if one of the section's object keys was not found in the source object's tree. */ * @param create If true, create and insert new objects for any missing path components.
json_object *mpw_get_json_section( * @return An object (shared) or a new object (shared) installed in the tree if the path's object path was not found. */
json_object *obj, const char *section); json_object *mpw_get_json_object(
json_object *obj, const char *key, bool create);
/** Search for a string in a JSON object tree. /** Search for a string in a JSON object tree.
* @param section A dot-delimited list of JSON object keys to walk toward the child object. * @param key A dot-delimited list of JSON object keys to walk toward the child object.
* @return A string (shared) or defaultValue if one of the section's object keys was not found in the source object's tree. */ * @return A string (shared) or defaultValue if one of the path's object keys was not found in the source object's tree. */
const char *mpw_get_json_string( const char *mpw_get_json_string(
json_object *obj, const char *section, const char *defaultValue); json_object *obj, const char *key, const char *defaultValue);
/** Search for an integer in a JSON object tree. /** Search for an integer in a JSON object tree.
* @param section A dot-delimited list of JSON object keys to walk toward the child object. * @param key A dot-delimited list of JSON object keys to walk toward the child object.
* @return The integer value or defaultValue if one of the section's object keys was not found in the source object's tree. */ * @return The integer value or defaultValue if one of the path's object keys was not found in the source object's tree. */
int64_t mpw_get_json_int( int64_t mpw_get_json_int(
json_object *obj, const char *section, int64_t defaultValue); json_object *obj, const char *key, int64_t defaultValue);
/** Search for a boolean in a JSON object tree. /** Search for a boolean in a JSON object tree.
* @param section A dot-delimited list of JSON object keys to walk toward the child object. * @param key A dot-delimited list of JSON object keys to walk toward the child object.
* @return The boolean value or defaultValue if one of the section's object keys was not found in the source object's tree. */ * @return The boolean value or defaultValue if one of the path's object keys was not found in the source object's tree. */
bool mpw_get_json_boolean( bool mpw_get_json_boolean(
json_object *obj, const char *section, bool defaultValue); json_object *obj, const char *key, bool defaultValue);
#endif #endif
/// mpw. /// mpw.

View File

@ -25,6 +25,7 @@ MP_LIBS_BEGIN
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <math.h>
MP_LIBS_END MP_LIBS_END
MPMarshalledUser *mpw_marshal_user( MPMarshalledUser *mpw_marshal_user(
@ -56,8 +57,12 @@ MPMarshalledSite *mpw_marshal_site(
MPMarshalledUser *user, const char *siteName, const MPResultType resultType, MPMarshalledUser *user, const char *siteName, const MPResultType resultType,
const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion) { const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion) {
if (!siteName || !mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count )) if (!siteName)
return NULL; return NULL;
if (!mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count )) {
user->sites_count--;
return NULL;
}
MPMarshalledSite *site = &user->sites[user->sites_count - 1]; MPMarshalledSite *site = &user->sites[user->sites_count - 1];
*site = (MPMarshalledSite){ *site = (MPMarshalledSite){
@ -84,8 +89,10 @@ MPMarshalledSite *mpw_marshal_site(
MPMarshalledQuestion *mpw_marshal_question( MPMarshalledQuestion *mpw_marshal_question(
MPMarshalledSite *site, const char *keyword) { MPMarshalledSite *site, const char *keyword) {
if (!mpw_realloc( &site->questions, NULL, sizeof( MPMarshalledQuestion ) * ++site->questions_count )) if (!mpw_realloc( &site->questions, NULL, sizeof( MPMarshalledQuestion ) * ++site->questions_count )) {
site->questions_count--;
return NULL; return NULL;
}
if (!keyword) if (!keyword)
keyword = ""; keyword = "";
@ -151,16 +158,20 @@ static bool mpw_marshal_user_free(
return success; return success;
} }
static bool mpw_marshal_data_free( static bool mpw_marshal_data_null(
MPMarshalledData **data) { MPMarshalledData *data) {
if (!data || !*data) if (!data)
return true; return true;
bool success = mpw_free_strings( &(*data)->key, &(*data)->str_value, NULL ); bool success = mpw_free_strings( &data->key, &data->str_value, NULL );
for (unsigned int c = 0; c < (*data)->obj_children_count; ++c) for (unsigned int c = 0; c < data->children_count; ++c)
success &= mpw_marshal_data_free( &(*data)->obj_children[c] ); success &= mpw_marshal_data_null( &data->children[c] );
success &= mpw_free( data, sizeof( MPMarshalledData ) ); success &= mpw_free( &data->children, sizeof( MPMarshalledData ) * data->children_count );
data->children_count = 0;
data->num_value = NAN;
data->is_bool = false;
data->is_null = true;
return success; return success;
} }
@ -175,7 +186,8 @@ bool mpw_marshal_free(
success &= mpw_marshal_info_free( &(*file)->info ); success &= mpw_marshal_info_free( &(*file)->info );
success &= mpw_marshal_user_free( &(*file)->user ); success &= mpw_marshal_user_free( &(*file)->user );
success &= mpw_marshal_data_free( &(*file)->data ); success &= mpw_marshal_data_null( (*file)->data );
success &= mpw_free( &(*file)->data, sizeof( MPMarshalledData ) );
success &= mpw_free( file, sizeof( MPMarshalledFile ) ); success &= mpw_free( file, sizeof( MPMarshalledFile ) );
return success; return success;
@ -272,6 +284,37 @@ static const char *mpw_marshal_write_flat(
#if MPW_JSON #if MPW_JSON
static json_object *mpw_get_json_data(
MPMarshalledData *data) {
if (!data || data->is_null)
return NULL;
if (data->is_bool)
return json_object_new_boolean( data->num_value != false );
if (!isnan( data->num_value ))
return json_object_new_double_s( data->num_value, data->str_value );
if (data->str_value)
return json_object_new_string( data->str_value );
json_object *obj = NULL;
for (size_t index = 0; index < data->children_count; ++index) {
MPMarshalledData *child = &data->children[index];
if (!obj) {
if (child->key)
obj = json_object_new_object();
else
obj = json_object_new_array();
}
if (child->key)
json_object_object_add( obj, child->key, mpw_get_json_data( child ) );
else
json_object_array_add( obj, mpw_get_json_data( child ) );
}
return obj;
}
static const char *mpw_marshal_write_json( static const char *mpw_marshal_write_json(
const MPMarshalledFile *file, MPMarshalError *error) { const MPMarshalledFile *file, MPMarshalError *error) {
@ -290,9 +333,10 @@ static const char *mpw_marshal_write_json(
masterKey = user->masterKeyProvider( user->algorithm, user->fullName ); masterKey = user->masterKeyProvider( user->algorithm, user->fullName );
// Section: "export" // Section: "export"
json_object *json_file = json_object_new_object(); json_object *json_file = mpw_get_json_data( file->data );
json_object *json_export = json_object_new_object(); if (!json_file)
json_object_object_add( json_file, "export", json_export ); json_file = json_object_new_object();
json_object *json_export = mpw_get_json_object( json_file, "export", true );
json_object_object_add( json_export, "format", json_object_new_int( 1 ) ); json_object_object_add( json_export, "format", json_object_new_int( 1 ) );
json_object_object_add( json_export, "redacted", json_object_new_boolean( user->redacted ) ); json_object_object_add( json_export, "redacted", json_object_new_boolean( user->redacted ) );
@ -302,8 +346,7 @@ static const char *mpw_marshal_write_json(
json_object_object_add( json_export, "date", json_object_new_string( dateString ) ); json_object_object_add( json_export, "date", json_object_new_string( dateString ) );
// Section: "user" // Section: "user"
json_object *json_user = json_object_new_object(); json_object *json_user = mpw_get_json_object( json_file, "user", true );
json_object_object_add( json_file, "user", json_user );
json_object_object_add( json_user, "avatar", json_object_new_int( (int32_t)user->avatar ) ); json_object_object_add( json_user, "avatar", json_object_new_int( (int32_t)user->avatar ) );
json_object_object_add( json_user, "full_name", json_object_new_string( user->fullName ) ); json_object_object_add( json_user, "full_name", json_object_new_string( user->fullName ) );
@ -318,8 +361,7 @@ static const char *mpw_marshal_write_json(
json_object_object_add( json_user, "default_type", json_object_new_int( (int32_t)user->defaultType ) ); json_object_object_add( json_user, "default_type", json_object_new_int( (int32_t)user->defaultType ) );
// Section "sites" // Section "sites"
json_object *json_sites = json_object_new_object(); json_object *json_sites = mpw_get_json_object( json_file, "sites", true );
json_object_object_add( json_file, "sites", json_sites );
for (size_t s = 0; s < user->sites_count; ++s) { for (size_t s = 0; s < user->sites_count; ++s) {
MPMarshalledSite *site = &user->sites[s]; MPMarshalledSite *site = &user->sites[s];
if (!site->siteName || !strlen( site->siteName )) if (!site->siteName || !strlen( site->siteName ))
@ -348,8 +390,7 @@ static const char *mpw_marshal_write_json(
loginState = mpw_strdup( site->loginState ); loginState = mpw_strdup( site->loginState );
} }
json_object *json_site = json_object_new_object(); json_object *json_site = mpw_get_json_object( json_sites, site->siteName, true );
json_object_object_add( json_sites, site->siteName, json_site );
json_object_object_add( json_site, "type", json_object_new_int( (int32_t)site->resultType ) ); json_object_object_add( json_site, "type", json_object_new_int( (int32_t)site->resultType ) );
json_object_object_add( json_site, "counter", json_object_new_int( (int32_t)site->counter ) ); json_object_object_add( json_site, "counter", json_object_new_int( (int32_t)site->counter ) );
json_object_object_add( json_site, "algorithm", json_object_new_int( (int32_t)site->algorithm ) ); json_object_object_add( json_site, "algorithm", json_object_new_int( (int32_t)site->algorithm ) );
@ -364,15 +405,13 @@ static const char *mpw_marshal_write_json(
json_object_object_add( json_site, "last_used", json_object_new_string( dateString ) ); json_object_object_add( json_site, "last_used", json_object_new_string( dateString ) );
if (site->questions_count) { if (site->questions_count) {
json_object *json_site_questions = json_object_new_object(); json_object *json_site_questions = mpw_get_json_object( json_site, "questions", true );
json_object_object_add( json_site, "questions", json_site_questions );
for (size_t q = 0; q < site->questions_count; ++q) { for (size_t q = 0; q < site->questions_count; ++q) {
MPMarshalledQuestion *question = &site->questions[q]; MPMarshalledQuestion *question = &site->questions[q];
if (!question->keyword) if (!question->keyword)
continue; continue;
json_object *json_site_question = json_object_new_object(); json_object *json_site_question = mpw_get_json_object( json_site_questions, question->keyword, true );
json_object_object_add( json_site_questions, question->keyword, json_site_question );
json_object_object_add( json_site_question, "type", json_object_new_int( (int32_t)question->type ) ); json_object_object_add( json_site_question, "type", json_object_new_int( (int32_t)question->type ) );
if (!user->redacted) { if (!user->redacted) {
@ -389,11 +428,11 @@ static const char *mpw_marshal_write_json(
} }
} }
json_object *json_site_mpw = json_object_new_object(); json_object *json_site_mpw = mpw_get_json_object( json_site, "_ext_mpw", true );
if (site->url) if (site->url)
json_object_object_add( json_site_mpw, "url", json_object_new_string( site->url ) ); json_object_object_add( json_site_mpw, "url", json_object_new_string( site->url ) );
if (json_object_object_length( json_site_mpw )) if (!json_object_object_length( json_site_mpw ))
json_object_object_add( json_site, "_ext_mpw", json_site_mpw ); json_object_object_del( json_site, "_ext_mpw" );
mpw_free_strings( &resultState, &loginState, NULL ); mpw_free_strings( &resultState, &loginState, NULL );
} }
@ -414,22 +453,31 @@ static const char *mpw_marshal_write_json(
#endif #endif
const char *mpw_marshal_write( const char *mpw_marshal_write(
const MPMarshalFormat outFormat, const MPMarshalledFile *file, MPMarshalError *error) { const MPMarshalFormat outFormat, MPMarshalledFile *file, MPMarshalError *error) {
const char *out = NULL;
switch (outFormat) { switch (outFormat) {
case MPMarshalFormatNone: case MPMarshalFormatNone:
*error = (MPMarshalError){ .type = MPMarshalSuccess }; *error = (MPMarshalError){ .type = MPMarshalSuccess };
return NULL; break;
case MPMarshalFormatFlat: case MPMarshalFormatFlat:
return mpw_marshal_write_flat( file, error ); out = mpw_marshal_write_flat( file, error );
break;
#if MPW_JSON #if MPW_JSON
case MPMarshalFormatJSON: case MPMarshalFormatJSON:
return mpw_marshal_write_json( file, error ); out = mpw_marshal_write_json( file, error );
break;
#endif #endif
default: default:
*error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported output format: %u", outFormat ) }; *error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported output format: %u", outFormat ) };
return NULL; break;
} }
if (file) {
mpw_marshal_info_free( &file->info );
file->info = mpw_marshal_read_info( out );
}
return out;
} }
static void mpw_marshal_read_flat_info( static void mpw_marshal_read_flat_info(
@ -462,19 +510,19 @@ static void mpw_marshal_read_flat_info(
if (!headerName || !headerValue) if (!headerName || !headerValue)
continue; continue;
if (strcmp( headerName, "Date" ) == 0) if (strcmp( headerName, "Date" ) == OK)
info->exportDate = info->lastUsed = mpw_timegm( headerValue ); info->exportDate = info->lastUsed = mpw_timegm( headerValue );
if (strcmp( headerName, "Passwords" ) == 0) if (strcmp( headerName, "Passwords" ) == OK)
info->redacted = strcmp( headerValue, "VISIBLE" ) != 0; info->redacted = strcmp( headerValue, "VISIBLE" ) != OK;
if (strcmp( headerName, "Algorithm" ) == 0) if (strcmp( headerName, "Algorithm" ) == OK)
info->algorithm = (MPAlgorithmVersion)atoi( headerValue ); info->algorithm = (MPAlgorithmVersion)atoi( headerValue );
if (strcmp( headerName, "Avatar" ) == 0) if (strcmp( headerName, "Avatar" ) == OK)
info->avatar = (unsigned int)atoi( headerValue ); info->avatar = (unsigned int)atoi( headerValue );
if (strcmp( headerName, "Full Name" ) == 0 || strcmp( headerName, "User Name" ) == 0) if (strcmp( headerName, "Full Name" ) == OK || strcmp( headerName, "User Name" ) == OK)
info->fullName = mpw_strdup( headerValue ); info->fullName = mpw_strdup( headerValue );
if (strcmp( headerName, "Identicon" ) == 0) if (strcmp( headerName, "Identicon" ) == OK)
info->identicon = mpw_identicon_encoded( headerValue ); info->identicon = mpw_identicon_encoded( headerValue );
if (strcmp( headerName, "Key ID" ) == 0) if (strcmp( headerName, "Key ID" ) == OK)
info->keyID = mpw_strdup( headerValue ); info->keyID = mpw_strdup( headerValue );
mpw_free_strings( &headerName, &headerValue, NULL ); mpw_free_strings( &headerName, &headerValue, NULL );
@ -569,13 +617,13 @@ static MPMarshalledFile *mpw_marshal_read_flat(
return NULL; return NULL;
} }
if (strcmp( headerName, "Format" ) == 0) if (strcmp( headerName, "Format" ) == OK)
format = (unsigned int)atoi( headerValue ); format = (unsigned int)atoi( headerValue );
if (strcmp( headerName, "Date" ) == 0) if (strcmp( headerName, "Date" ) == OK)
exportDate = mpw_timegm( headerValue ); exportDate = mpw_timegm( headerValue );
if (strcmp( headerName, "Passwords" ) == 0) if (strcmp( headerName, "Passwords" ) == OK)
importRedacted = strcmp( headerValue, "VISIBLE" ) != 0; importRedacted = strcmp( headerValue, "VISIBLE" ) != OK;
if (strcmp( headerName, "Algorithm" ) == 0) { if (strcmp( headerName, "Algorithm" ) == OK) {
int value = atoi( headerValue ); int value = atoi( headerValue );
if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) { if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) {
*error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user algorithm version: %s", headerValue ) }; *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user algorithm version: %s", headerValue ) };
@ -587,15 +635,15 @@ static MPMarshalledFile *mpw_marshal_read_flat(
} }
algorithm = (MPAlgorithmVersion)value; algorithm = (MPAlgorithmVersion)value;
} }
if (strcmp( headerName, "Avatar" ) == 0) if (strcmp( headerName, "Avatar" ) == OK)
avatar = (unsigned int)atoi( headerValue ); avatar = (unsigned int)atoi( headerValue );
if (strcmp( headerName, "Full Name" ) == 0 || strcmp( headerName, "User Name" ) == 0) if (strcmp( headerName, "Full Name" ) == OK || strcmp( headerName, "User Name" ) == OK)
fullName = mpw_strdup( headerValue ); fullName = mpw_strdup( headerValue );
if (strcmp( headerName, "Identicon" ) == 0) if (strcmp( headerName, "Identicon" ) == OK)
identicon = mpw_identicon_encoded( headerValue ); identicon = mpw_identicon_encoded( headerValue );
if (strcmp( headerName, "Key ID" ) == 0) if (strcmp( headerName, "Key ID" ) == OK)
keyID = mpw_strdup( headerValue ); keyID = mpw_strdup( headerValue );
if (strcmp( headerName, "Default Type" ) == 0) { if (strcmp( headerName, "Default Type" ) == OK) {
int value = atoi( headerValue ); int value = atoi( headerValue );
if (!mpw_type_short_name( (MPResultType)value )) { if (!mpw_type_short_name( (MPResultType)value )) {
*error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user default type: %s", headerValue ) }; *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user default type: %s", headerValue ) };
@ -783,6 +831,110 @@ static MPMarshalledFile *mpw_marshal_read_flat(
#if MPW_JSON #if MPW_JSON
static void mpw_set_json_data(
MPMarshalledData *data, json_object *obj) {
json_type type = json_object_get_type( obj );
data->is_null = type == json_type_null;
data->is_bool = type == json_type_boolean;
if (type == json_type_boolean)
data->num_value = json_object_get_boolean( obj );
else if (type == json_type_double)
data->num_value = json_object_get_double( obj );
else if (type == json_type_int)
data->num_value = json_object_get_int64( obj );
else
data->num_value = NAN;
const char *str = NULL;
if (type == json_type_string || !isnan( data->num_value ))
str = json_object_get_string( obj );
if (!str || !data->str_value || strcmp( str, data->str_value ) != OK) {
mpw_free_string( &data->str_value );
data->str_value = mpw_strdup( str );
}
// Clean up children
MPMarshalledData *newChildren = NULL;
size_t newChildrenCount = 0;
for (size_t c = 0; c < data->children_count; ++c) {
MPMarshalledData *child = &data->children[c];
if ((type != json_type_object && type != json_type_array) ||
(child->key && type != json_type_object) || (!isnan( child->index ) && type != json_type_array)) {
mpw_marshal_data_null( child );
if (!newChildren) {
newChildren = malloc( sizeof( MPMarshalledData ) * newChildrenCount );
if (newChildren)
memcpy( newChildren, data->children, sizeof( MPMarshalledData ) * newChildrenCount );
}
}
else {
++newChildrenCount;
if (newChildren) {
if (!mpw_realloc( &newChildren, NULL, sizeof( MPMarshalledData ) * newChildrenCount )) {
--newChildrenCount;
continue;
}
child->index = newChildrenCount - 1;
newChildren[child->index] = *child;
}
}
}
if (newChildren) {
mpw_free( &data->children, sizeof( MPMarshalledData ) * data->children_count );
data->children = newChildren;
data->children_count = newChildrenCount;
}
// Object
if (type == json_type_object) {
json_object_iter entry;
json_object_object_foreachC( obj, entry ) {
MPMarshalledData *child = NULL;
// Find existing child.
for (size_t c = 0; c < data->children_count; ++c)
if (data->children[c].key == entry.key ||
(data->children[c].key && entry.key && strcmp( data->children[c].key, entry.key )) == OK) {
child = &data->children[c];
break;
}
// Create new child.
if (!child) {
if (!mpw_realloc( &data->children, NULL, sizeof( MPMarshalledData ) * ++data->children_count )) {
--data->children_count;
continue;
}
*(child = &data->children[data->children_count - 1]) = (MPMarshalledData){ .key = mpw_strdup( entry.key ) };
}
mpw_set_json_data( child, entry.val );
}
}
// Array
if (type == json_type_array) {
for (size_t index = 0; index < json_object_array_length( obj ); ++index) {
MPMarshalledData *child = NULL;
if (index < data->children_count)
child = &data->children[index];
else {
if (!mpw_realloc( &data->children, NULL, sizeof( MPMarshalledData ) * ++data->children_count )) {
--data->children_count;
continue;
}
*(child = &data->children[data->children_count - 1]) = (MPMarshalledData){ .index = index };
}
mpw_set_json_data( child, json_object_array_get_idx( obj, index ) );
}
}
}
static void mpw_marshal_read_json_info( static void mpw_marshal_read_json_info(
const char *in, MPMarshalInfo *info) { const char *in, MPMarshalInfo *info) {
@ -793,19 +945,21 @@ static void mpw_marshal_read_json_info(
return; return;
// Section: "export" // Section: "export"
int64_t fileFormat = mpw_get_json_int( json_file, "export.format", 0 ); json_object *json_export = mpw_get_json_object( json_file, "export", false );
int64_t fileFormat = mpw_get_json_int( json_export, "format", 0 );
if (fileFormat < 1) if (fileFormat < 1)
return; return;
info->exportDate = mpw_timegm( mpw_get_json_string( json_file, "export.date", NULL ) ); info->exportDate = mpw_timegm( mpw_get_json_string( json_export, "date", NULL ) );
info->redacted = mpw_get_json_boolean( json_file, "export.redacted", true ); info->redacted = mpw_get_json_boolean( json_export, "redacted", true );
// Section: "user" // Section: "user"
info->algorithm = (MPAlgorithmVersion)mpw_get_json_int( json_file, "user.algorithm", MPAlgorithmVersionCurrent ); json_object *json_user = mpw_get_json_object( json_file, "user", false );
info->avatar = (unsigned int)mpw_get_json_int( json_file, "user.avatar", 0 ); info->algorithm = (MPAlgorithmVersion)mpw_get_json_int( json_user, "algorithm", MPAlgorithmVersionCurrent );
info->fullName = mpw_strdup( mpw_get_json_string( json_file, "user.full_name", NULL ) ); info->avatar = (unsigned int)mpw_get_json_int( json_user, "avatar", 0 );
info->identicon = mpw_identicon_encoded( mpw_get_json_string( json_file, "user.identicon", NULL ) ); info->fullName = mpw_strdup( mpw_get_json_string( json_user, "full_name", NULL ) );
info->keyID = mpw_strdup( mpw_get_json_string( json_file, "user.key_id", NULL ) ); info->identicon = mpw_identicon_encoded( mpw_get_json_string( json_user, "identicon", NULL ) );
info->lastUsed = mpw_timegm( mpw_get_json_string( json_file, "user.last_used", NULL ) ); info->keyID = mpw_strdup( mpw_get_json_string( json_user, "key_id", NULL ) );
info->lastUsed = mpw_timegm( mpw_get_json_string( json_user, "last_used", NULL ) );
json_object_put( json_file ); json_object_put( json_file );
} }
@ -830,38 +984,40 @@ static MPMarshalledFile *mpw_marshal_read_json(
} }
// Section: "export" // Section: "export"
int64_t fileFormat = mpw_get_json_int( json_file, "export.format", 0 ); json_object *json_export = mpw_get_json_object( json_file, "export", false );
int64_t fileFormat = mpw_get_json_int( json_export, "format", 0 );
if (fileFormat < 1) { if (fileFormat < 1) {
*error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported format: %u", fileFormat ) }; *error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported format: %u", fileFormat ) };
json_object_put( json_file ); json_object_put( json_file );
return NULL; return NULL;
} }
bool fileRedacted = mpw_get_json_boolean( json_file, "export.redacted", true ); bool fileRedacted = mpw_get_json_boolean( json_export, "redacted", true );
// Section: "user" // Section: "user"
int64_t value = mpw_get_json_int( json_file, "user.algorithm", MPAlgorithmVersionCurrent ); json_object *json_user = mpw_get_json_object( json_file, "user", false );
int64_t value = mpw_get_json_int( json_user, "algorithm", MPAlgorithmVersionCurrent );
if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) { if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) {
*error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user algorithm version: %u", value ) }; *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user algorithm version: %u", value ) };
json_object_put( json_file ); json_object_put( json_file );
return NULL; return NULL;
} }
MPAlgorithmVersion algorithm = (MPAlgorithmVersion)value; MPAlgorithmVersion algorithm = (MPAlgorithmVersion)value;
unsigned int avatar = (unsigned int)mpw_get_json_int( json_file, "user.avatar", 0 ); unsigned int avatar = (unsigned int)mpw_get_json_int( json_user, "avatar", 0 );
const char *fullName = mpw_get_json_string( json_file, "user.full_name", NULL ); const char *fullName = mpw_get_json_string( json_user, "full_name", NULL );
if (!fullName || !strlen( fullName )) { if (!fullName || !strlen( fullName )) {
*error = (MPMarshalError){ MPMarshalErrorMissing, "Missing value for full name." }; *error = (MPMarshalError){ MPMarshalErrorMissing, "Missing value for full name." };
json_object_put( json_file ); json_object_put( json_file );
return NULL; return NULL;
} }
MPIdenticon identicon = mpw_identicon_encoded( mpw_get_json_string( json_file, "user.identicon", NULL ) ); MPIdenticon identicon = mpw_identicon_encoded( mpw_get_json_string( json_user, "identicon", NULL ) );
const char *keyID = mpw_get_json_string( json_file, "user.key_id", NULL ); const char *keyID = mpw_get_json_string( json_user, "key_id", NULL );
MPResultType defaultType = (MPResultType)mpw_get_json_int( json_file, "user.default_type", MPResultTypeDefault ); MPResultType defaultType = (MPResultType)mpw_get_json_int( json_user, "default_type", MPResultTypeDefault );
if (!mpw_type_short_name( defaultType )) { if (!mpw_type_short_name( defaultType )) {
*error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user default type: %u", defaultType ) }; *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user default type: %u", defaultType ) };
json_object_put( json_file ); json_object_put( json_file );
return NULL; return NULL;
} }
const char *str_lastUsed = mpw_get_json_string( json_file, "user.last_used", NULL ); const char *str_lastUsed = mpw_get_json_string( json_user, "last_used", NULL );
time_t lastUsed = mpw_timegm( str_lastUsed ); time_t lastUsed = mpw_timegm( str_lastUsed );
if (!lastUsed) { if (!lastUsed) {
*error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user last used: %s", str_lastUsed ) }; *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user last used: %s", str_lastUsed ) };
@ -901,7 +1057,7 @@ static MPMarshalledFile *mpw_marshal_read_json(
// Section "sites" // Section "sites"
json_object_iter json_site; json_object_iter json_site;
json_object *json_sites = mpw_get_json_section( json_file, "sites" ); json_object *json_sites = mpw_get_json_object( json_file, "sites", false );
json_object_object_foreachC( json_sites, json_site ) { json_object_object_foreachC( json_sites, json_site ) {
const char *siteName = json_site.key; const char *siteName = json_site.key;
value = mpw_get_json_int( json_site.val, "algorithm", (int32_t)user->algorithm ); value = mpw_get_json_int( json_site.val, "algorithm", (int32_t)user->algorithm );
@ -951,7 +1107,7 @@ static MPMarshalledFile *mpw_marshal_read_json(
return NULL; return NULL;
} }
json_object *json_site_mpw = mpw_get_json_section( json_site.val, "_ext_mpw" ); json_object *json_site_mpw = mpw_get_json_object( json_site.val, "_ext_mpw", false );
const char *siteURL = mpw_get_json_string( json_site_mpw, "url", NULL ); const char *siteURL = mpw_get_json_string( json_site_mpw, "url", NULL );
MPMarshalledSite *site = mpw_marshal_site( user, siteName, siteType, siteCounter, siteAlgorithm ); MPMarshalledSite *site = mpw_marshal_site( user, siteName, siteType, siteCounter, siteAlgorithm );
@ -993,7 +1149,7 @@ static MPMarshalledFile *mpw_marshal_read_json(
site->loginState = mpw_strdup( siteLoginState ); site->loginState = mpw_strdup( siteLoginState );
} }
json_object *json_site_questions = mpw_get_json_section( json_site.val, "questions" ); json_object *json_site_questions = mpw_get_json_object( json_site.val, "questions", false );
if (json_site_questions) { if (json_site_questions) {
json_object_iter json_site_question; json_object_iter json_site_question;
json_object_object_foreachC( json_site_questions, json_site_question ) { json_object_object_foreachC( json_site_questions, json_site_question ) {
@ -1016,9 +1172,15 @@ static MPMarshalledFile *mpw_marshal_read_json(
} }
} }
mpw_free( &masterKey, MPMasterKeySize ); mpw_free( &masterKey, MPMasterKeySize );
MPMarshalledData *data = malloc( sizeof( MPMarshalledData ) );
if (data) {
*data = (MPMarshalledData){};
mpw_set_json_data( data, json_file );
}
json_object_put( json_file ); json_object_put( json_file );
MPMarshalledFile *file = mpw_marshal_file( user, NULL ); MPMarshalledFile *file = mpw_marshal_file( user, data );
if (!file) { if (!file) {
*error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't allocate a new marshal file." }; *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't allocate a new marshal file." };
mpw_marshal_user_free( &user ); mpw_marshal_user_free( &user );
@ -1064,6 +1226,9 @@ MPMarshalledFile *mpw_marshal_read(
const char *in, MPMasterKeyProvider masterKeyProvider, MPMarshalError *error) { const char *in, MPMasterKeyProvider masterKeyProvider, MPMarshalError *error) {
MPMarshalInfo *info = mpw_marshal_read_info( in ); MPMarshalInfo *info = mpw_marshal_read_info( in );
if (!info)
return NULL;
MPMarshalledFile *file = NULL; MPMarshalledFile *file = NULL;
switch (info->format) { switch (info->format) {
case MPMarshalFormatNone: case MPMarshalFormatNone:
@ -1081,8 +1246,10 @@ MPMarshalledFile *mpw_marshal_read(
*error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported input format: %u", info->format ) }; *error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported input format: %u", info->format ) };
break; break;
} }
if (file) if (file) {
mpw_marshal_info_free( &(file->info) );
file->info = info; file->info = info;
}
return file; return file;
} }
@ -1093,11 +1260,11 @@ const MPMarshalFormat mpw_format_named(
if (!formatName || !strlen( formatName )) if (!formatName || !strlen( formatName ))
return MPMarshalFormatNone; return MPMarshalFormatNone;
if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatNone ), formatName, strlen( formatName ) ) == 0) if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatNone ), formatName, strlen( formatName ) ) == OK)
return MPMarshalFormatNone; return MPMarshalFormatNone;
if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatFlat ), formatName, strlen( formatName ) ) == 0) if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatFlat ), formatName, strlen( formatName ) ) == OK)
return MPMarshalFormatFlat; return MPMarshalFormatFlat;
if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatJSON ), formatName, strlen( formatName ) ) == 0) if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatJSON ), formatName, strlen( formatName ) ) == OK)
return MPMarshalFormatJSON; return MPMarshalFormatJSON;
dbg( "Not a format name: %s", formatName ); dbg( "Not a format name: %s", formatName );

View File

@ -126,18 +126,20 @@ typedef struct MPMarshalledData {
// If data is held in a parent object. // If data is held in a parent object.
const char *key; const char *key;
// If data is held in a parent array. // If data is held in a parent array.
unsigned int index; size_t index;
// If data is a null.
bool is_null;
// If data is a boolean.
bool is_bool;
// If data is a string. // If data is a string.
const char *str_value; const char *str_value;
// If data is a boolean.
bool bool_value;
// If data is a number. // If data is a number.
double num_value; double num_value;
// If data is an object or array. // If data is an object or array.
struct MPMarshalledData **obj_children; size_t children_count;
size_t obj_children_count; struct MPMarshalledData *children;
} MPMarshalledData; } MPMarshalledData;
typedef struct MPMarshalledFile { typedef struct MPMarshalledFile {
@ -151,7 +153,7 @@ typedef struct MPMarshalledFile {
/** Write the user and all associated data out using the given marshalling format. /** Write the user and all associated data out using the given marshalling format.
* @return A string (allocated), or NULL if the format is unrecognized, does not support marshalling or a format error occurred. */ * @return A string (allocated), or NULL if the format is unrecognized, does not support marshalling or a format error occurred. */
const char *mpw_marshal_write( const char *mpw_marshal_write(
const MPMarshalFormat outFormat, const MPMarshalledFile *file, MPMarshalError *error); const MPMarshalFormat outFormat, MPMarshalledFile *file, MPMarshalError *error);
/** Best effort parse of metadata on the sites in the input buffer. Fields that could not be parsed remain at their type's initial value. /** Best effort parse of metadata on the sites in the input buffer. Fields that could not be parsed remain at their type's initial value.
* @return A metadata object (allocated); NULL if the object could not be allocated or the format was not understood. */ * @return A metadata object (allocated); NULL if the object could not be allocated or the format was not understood. */
MPMarshalInfo *mpw_marshal_read_info( MPMarshalInfo *mpw_marshal_read_info(

View File

@ -63,27 +63,27 @@ const MPResultType mpw_type_named(const char *typeName) {
} }
// Find what password type is represented by the type name. // Find what password type is represented by the type name.
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateMaximum ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateMaximum ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeTemplateMaximum; return MPResultTypeTemplateMaximum;
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateLong ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateLong ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeTemplateLong; return MPResultTypeTemplateLong;
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateMedium ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateMedium ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeTemplateMedium; return MPResultTypeTemplateMedium;
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateBasic ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateBasic ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeTemplateBasic; return MPResultTypeTemplateBasic;
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateShort ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateShort ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeTemplateShort; return MPResultTypeTemplateShort;
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplatePIN ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplatePIN ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeTemplatePIN; return MPResultTypeTemplatePIN;
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateName ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateName ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeTemplateName; return MPResultTypeTemplateName;
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplatePhrase ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplatePhrase ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeTemplatePhrase; return MPResultTypeTemplatePhrase;
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeStatefulPersonal ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeStatefulPersonal ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeStatefulPersonal; return MPResultTypeStatefulPersonal;
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeStatefulDevice ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeStatefulDevice ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeStatefulDevice; return MPResultTypeStatefulDevice;
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeDeriveKey ), typeName, strlen( typeName ) ) == 0) if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeDeriveKey ), typeName, strlen( typeName ) ) == OK)
return MPResultTypeDeriveKey; return MPResultTypeDeriveKey;
dbg( "Not a generated type name: %s", typeName ); dbg( "Not a generated type name: %s", typeName );
@ -243,11 +243,11 @@ const char *mpw_type_template(MPResultType type, uint8_t templateIndex) {
const MPKeyPurpose mpw_purpose_named(const char *purposeName) { const MPKeyPurpose mpw_purpose_named(const char *purposeName) {
if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeAuthentication ), purposeName, strlen( purposeName ) ) == 0) if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeAuthentication ), purposeName, strlen( purposeName ) ) == OK)
return MPKeyPurposeAuthentication; return MPKeyPurposeAuthentication;
if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeIdentification ), purposeName, strlen( purposeName ) ) == 0) if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeIdentification ), purposeName, strlen( purposeName ) ) == OK)
return MPKeyPurposeIdentification; return MPKeyPurposeIdentification;
if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeRecovery ), purposeName, strlen( purposeName ) ) == 0) if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeRecovery ), purposeName, strlen( purposeName ) ) == OK)
return MPKeyPurposeRecovery; return MPKeyPurposeRecovery;
dbg( "Not a purpose name: %s", purposeName ); dbg( "Not a purpose name: %s", purposeName );