2
0

Marshal data API & fixes.

This commit is contained in:
Maarten Billemont 2019-07-28 12:35:36 -04:00
parent ddb786c332
commit 4c6d7ac36c
11 changed files with 447 additions and 144 deletions

View File

@ -272,7 +272,7 @@ void cli_free(Arguments *args, Operation *operation) {
mpw_free_strings( &operation->fullName, &operation->masterPassword, &operation->siteName, NULL );
mpw_free_strings( &operation->keyContext, &operation->resultState, &operation->resultParam, NULL );
mpw_free_strings( &operation->identicon, &operation->sitesPath, NULL );
mpw_marshal_free( &operation->file );
mpw_marshal_file_free( &operation->file );
operation->site = NULL;
operation->question = NULL;
cli_masterKeyProvider_free();
@ -487,7 +487,7 @@ void cli_user(Arguments *args, Operation *operation) {
if (!sitesFile) {
// If no user from mpsites, create a new one.
mpw_free_string( &operation->sitesPath );
mpw_marshal_free( &operation->file );
mpw_marshal_file_free( &operation->file );
operation->file = mpw_marshal_file( mpw_marshal_user(
operation->fullName, cli_masterKeyProvider_op( operation ), MPAlgorithmVersionCurrent ), NULL );
}
@ -501,7 +501,7 @@ void cli_user(Arguments *args, Operation *operation) {
// Parse file.
MPMarshalError marshalError = { .type = MPMarshalSuccess };
mpw_marshal_free( &operation->file );
mpw_marshal_file_free( &operation->file );
operation->file = mpw_marshal_read( sitesInputData,
cli_masterKeyProvider_op( operation ), &marshalError );
if (marshalError.type == MPMarshalErrorMasterPassword && operation->allowPasswordUpdate) {
@ -516,7 +516,7 @@ void cli_user(Arguments *args, Operation *operation) {
importMasterPassword = mpw_getpass( "Old master password: " );
}
mpw_marshal_free( &operation->file );
mpw_marshal_file_free( &operation->file );
operation->file = mpw_marshal_read( sitesInputData,
cli_masterKeyProvider_str( importMasterPassword ), &marshalError );
if (operation->file && operation->file->user)

View File

@ -22,7 +22,7 @@
#include "mpw-algorithm_v2.c"
#include "mpw-algorithm_v3.c"
MPMasterKey mpw_master_key(const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) {
const MPMasterKey mpw_master_key(const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) {
if (fullName && !strlen( fullName ))
fullName = NULL;
@ -56,8 +56,8 @@ MPMasterKey mpw_master_key(const char *fullName, const char *masterPassword, con
}
}
MPSiteKey mpw_site_key(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPSiteKey mpw_site_key(
const MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion) {
if (keyContext && !strlen( keyContext ))
@ -93,7 +93,7 @@ MPSiteKey mpw_site_key(
}
const char *mpw_site_result(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext,
const MPResultType resultType, const char *resultParam,
const MPAlgorithmVersion algorithmVersion) {
@ -171,7 +171,7 @@ const char *mpw_site_result(
}
const char *mpw_site_state(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext,
const MPResultType resultType, const char *resultParam,
const MPAlgorithmVersion algorithmVersion) {
@ -223,7 +223,7 @@ static const char *mpw_identicon_accessories[] = {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
};
MPIdenticon mpw_identicon(const char *fullName, const char *masterPassword) {
const MPIdenticon mpw_identicon(const char *fullName, const char *masterPassword) {
const uint8_t *seed = NULL;
if (fullName && strlen( fullName ) && masterPassword && strlen( masterPassword ))
@ -246,7 +246,7 @@ MPIdenticon mpw_identicon(const char *fullName, const char *masterPassword) {
}
const char *mpw_identicon_encode(
MPIdenticon identicon) {
const MPIdenticon identicon) {
if (identicon.color == MPIdenticonColorUnset)
return "";
@ -255,7 +255,7 @@ const char *mpw_identicon_encode(
identicon.color, identicon.leftArm, identicon.body, identicon.rightArm, identicon.accessory );
}
MPIdenticon mpw_identicon_encoded(
const MPIdenticon mpw_identicon_encoded(
const char *encoding) {
MPIdenticon identicon = MPIdenticonUnset;

View File

@ -38,20 +38,20 @@ typedef mpw_enum( unsigned int, MPAlgorithmVersion ) {
/** Derive the master key for a user based on their name and master password.
* @return A buffer (allocated, MPMasterKeySize) or NULL if the fullName or masterPassword is missing, the algorithm is unknown, or an algorithm error occurred. */
MPMasterKey mpw_master_key(
const MPMasterKey mpw_master_key(
const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion);
/** Derive the site key for a user's site from the given master key and site parameters.
* @return A buffer (allocated, MPSiteKeySize) or NULL if the masterKey or siteName is missing, the algorithm is unknown, or an algorithm error occurred. */
MPSiteKey mpw_site_key(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPSiteKey mpw_site_key(
const MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion);
/** Generate a site result token from the given parameters.
* @param resultParam A parameter for the resultType. For stateful result types, the output of mpw_site_state.
* @return A string (allocated) or NULL if the masterKey or siteName is missing, the algorithm is unknown, or an algorithm error occurred. */
const char *mpw_site_result(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext,
const MPResultType resultType, const char *resultParam,
const MPAlgorithmVersion algorithmVersion);
@ -60,19 +60,19 @@ const char *mpw_site_result(
* @param resultParam A parameter for the resultType. For stateful result types, the desired mpw_site_result.
* @return A string (allocated) or NULL if the masterKey, siteName or resultParam is missing, the algorithm is unknown, or an algorithm error occurred. */
const char *mpw_site_state(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext,
const MPResultType resultType, const char *resultParam,
const MPAlgorithmVersion algorithmVersion);
/** @return An identicon (static) that represents the user's identity. */
MPIdenticon mpw_identicon(
const MPIdenticon mpw_identicon(
const char *fullName, const char *masterPassword);
/** @return An encoded representation (shared) of the given identicon or an empty string if the identicon is unset. */
const char *mpw_identicon_encode(
MPIdenticon identicon);
const MPIdenticon identicon);
/** @return An identicon (static) decoded from the given encoded identicon representation or an identicon with empty fields if the identicon could not be parsed. */
MPIdenticon mpw_identicon_encoded(
const MPIdenticon mpw_identicon_encoded(
const char *encoding);
#endif // _MPW_ALGORITHM_H

View File

@ -23,7 +23,7 @@ MP_LIBS_BEGIN
#include <string.h>
MP_LIBS_END
char *mpw_get_token(const char **in, const char *eol, char *delim) {
char *mpw_get_token(const char **in, const char *eol, const char *delim) {
// Skip leading spaces.
for (; **in == ' '; ++*in);
@ -60,7 +60,7 @@ time_t mpw_timegm(const char *time) {
#if MPW_JSON
json_object *mpw_get_json_object(
json_object *obj, const char *key, bool create) {
json_object *obj, const char *key, const bool create) {
if (!obj)
return NULL;
@ -86,7 +86,7 @@ const char *mpw_get_json_string(
}
int64_t mpw_get_json_int(
json_object *obj, const char *key, int64_t defaultValue) {
json_object *obj, const char *key, const int64_t defaultValue) {
json_object *json_value = mpw_get_json_object( obj, key, false );
if (!json_value)
@ -96,7 +96,7 @@ int64_t mpw_get_json_int(
}
bool mpw_get_json_boolean(
json_object *obj, const char *key, bool defaultValue) {
json_object *obj, const char *key, const bool defaultValue) {
json_object *json_value = mpw_get_json_object( obj, key, false );
if (!json_value)
@ -107,7 +107,7 @@ bool mpw_get_json_boolean(
#endif
bool mpw_update_master_key(MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, MPAlgorithmVersion targetKeyAlgorithm,
bool mpw_update_master_key(MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, const MPAlgorithmVersion targetKeyAlgorithm,
const char *fullName, const char *masterPassword) {
if (masterKey && (!*masterKey || *masterKeyAlgorithm != targetKeyAlgorithm)) {

View File

@ -34,7 +34,7 @@ MP_LIBS_END
* The input string reference is advanced beyond the token delimitor if one is found.
* @return A string (allocated) containing the token or NULL if the delim wasn't found before eol. */
char *mpw_get_token(
const char **in, const char *eol, char *delim);
const char **in, const char *eol, const char *delim);
/** Convert an RFC 3339 time string into epoch time.
* @return ERR if the string could not be parsed. */
time_t mpw_timegm(
@ -48,7 +48,7 @@ time_t mpw_timegm(
* @param create If true, create and insert new objects for any missing path components.
* @return An object (shared) or a new object (shared) installed in the tree if the path's object path was not found. */
json_object *mpw_get_json_object(
json_object *obj, const char *key, bool create);
json_object *obj, const char *key, const bool create);
/** Search for a string in a JSON object tree.
* @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 path's object keys was not found in the source object's tree. */
@ -58,12 +58,12 @@ const char *mpw_get_json_string(
* @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 path's object keys was not found in the source object's tree. */
int64_t mpw_get_json_int(
json_object *obj, const char *key, int64_t defaultValue);
json_object *obj, const char *key, const int64_t defaultValue);
/** Search for a boolean in a JSON object tree.
* @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 path's object keys was not found in the source object's tree. */
bool mpw_get_json_boolean(
json_object *obj, const char *key, bool defaultValue);
json_object *obj, const char *key, const bool defaultValue);
#endif
/// mpw.
@ -72,7 +72,7 @@ bool mpw_get_json_boolean(
* @param masterKey A buffer (allocated, MPMasterKeySize).
* @return false if an error occurred during the derivation of the master key. */
bool mpw_update_master_key(
MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, MPAlgorithmVersion targetKeyAlgorithm,
MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, const MPAlgorithmVersion targetKeyAlgorithm,
const char *fullName, const char *masterPassword);
#endif // _MPW_MARSHAL_UTIL_H

View File

@ -120,75 +120,309 @@ MPMarshalledFile *mpw_marshal_file(
return file;
}
bool mpw_marshal_info_free(
void mpw_marshal_info_free(
MPMarshalInfo **info) {
if (!info || !*info)
return true;
return;
bool success = true;
success &= mpw_free_strings( &(*info)->fullName, &(*info)->keyID, NULL );
success &= mpw_free( info, sizeof( MPMarshalInfo ) );
return success;
mpw_free_strings( &(*info)->fullName, &(*info)->keyID, NULL );
mpw_free( info, sizeof( MPMarshalInfo ) );
}
static bool mpw_marshal_user_free(
void mpw_marshal_user_free(
MPMarshalledUser **user) {
if (!user || !*user)
return true;
return;
bool success = mpw_free_strings( &(*user)->fullName, &(*user)->keyID, NULL );
mpw_free_strings( &(*user)->fullName, &(*user)->keyID, NULL );
for (size_t s = 0; s < (*user)->sites_count; ++s) {
MPMarshalledSite *site = &(*user)->sites[s];
success &= mpw_free_strings( &site->siteName, &site->resultState, &site->loginState, &site->url, NULL );
mpw_free_strings( &site->siteName, &site->resultState, &site->loginState, &site->url, NULL );
for (size_t q = 0; q < site->questions_count; ++q) {
MPMarshalledQuestion *question = &site->questions[q];
success &= mpw_free_strings( &question->keyword, &question->state, NULL );
mpw_free_strings( &question->keyword, &question->state, NULL );
}
success &= mpw_free( &site->questions, sizeof( MPMarshalledQuestion ) * site->questions_count );
mpw_free( &site->questions, sizeof( MPMarshalledQuestion ) * site->questions_count );
}
success &= mpw_free( &(*user)->sites, sizeof( MPMarshalledSite ) * (*user)->sites_count );
success &= mpw_free( user, sizeof( MPMarshalledUser ) );
return success;
mpw_free( &(*user)->sites, sizeof( MPMarshalledSite ) * (*user)->sites_count );
mpw_free( user, sizeof( MPMarshalledUser ) );
}
static bool mpw_marshal_data_null(
MPMarshalledData *data) {
if (!data)
return true;
bool success = mpw_free_strings( &data->key, &data->str_value, NULL );
for (unsigned int c = 0; c < data->children_count; ++c)
success &= mpw_marshal_data_null( &data->children[c] );
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;
}
bool mpw_marshal_free(
void mpw_marshal_file_free(
MPMarshalledFile **file) {
if (!file || !*file)
return true;
return;
bool success = true;
mpw_marshal_info_free( &(*file)->info );
mpw_marshal_user_free( &(*file)->user );
if ((*file)->data) {
mpw_marshal_data_set_null( (*file)->data, NULL );
mpw_free_string( &(*file)->data->key );
mpw_free( &(*file)->data, sizeof( MPMarshalledData ) );
}
mpw_free( file, sizeof( MPMarshalledFile ) );
}
success &= mpw_marshal_info_free( &(*file)->info );
success &= mpw_marshal_user_free( &(*file)->user );
success &= mpw_marshal_data_null( (*file)->data );
success &= mpw_free( &(*file)->data, sizeof( MPMarshalledData ) );
success &= mpw_free( file, sizeof( MPMarshalledFile ) );
MPMarshalledData *mpw_marshal_data_new() {
MPMarshalledData *data = malloc( sizeof( MPMarshalledData ) );
*data = (MPMarshalledData){};
mpw_marshal_data_set_null( data, NULL );
return data;
}
MPMarshalledData *mpw_marshal_data_vget(
MPMarshalledData *data, va_list nodes) {
MPMarshalledData *parent = data, *child;
for (const char *node; parent && (node = va_arg( nodes, const char * )); parent = child) {
child = NULL;
for (size_t c = 0; c < parent->children_count; ++c) {
const char *key = parent->children[c].key;
if (key && strcmp( node, key ) == OK) {
child = &parent->children[c];
break;
}
}
if (!child) {
if (!mpw_realloc( &parent->children, NULL, sizeof( MPMarshalledData ) * ++parent->children_count )) {
--parent->children_count;
break;
}
*(child = &parent->children[parent->children_count - 1]) = (MPMarshalledData){ .key = mpw_strdup( node ) };
mpw_marshal_data_set_null( child, NULL );
child->is_null = false;
}
}
return parent;
}
MPMarshalledData *mpw_marshal_data_get(
MPMarshalledData *data, ...) {
va_list nodes;
va_start( nodes, data );
MPMarshalledData *child = mpw_marshal_data_vget( data, nodes );
va_end( nodes );
return child;
}
const MPMarshalledData *mpw_marshal_data_vfind(
const MPMarshalledData *data, va_list nodes) {
const MPMarshalledData *parent = data, *child;
for (const char *node; parent && (node = va_arg( nodes, const char * )); parent = child) {
child = NULL;
for (size_t c = 0; c < parent->children_count; ++c) {
const char *key = parent->children[c].key;
if (key && strcmp( node, key ) == OK) {
child = &parent->children[c];
break;
}
}
if (!child)
break;
}
return parent;
}
const MPMarshalledData *mpw_marshal_data_find(
const MPMarshalledData *data, ...) {
va_list nodes;
va_start( nodes, data );
const MPMarshalledData *child = mpw_marshal_data_vfind( data, nodes );
va_end( nodes );
return child;
}
bool mpw_marshal_data_vis_null(
const MPMarshalledData *data, va_list nodes) {
const MPMarshalledData *child = mpw_marshal_data_vfind( data, nodes );
return !child || child->is_null;
}
bool mpw_marshal_data_is_null(
const MPMarshalledData *data, ...) {
va_list nodes;
va_start( nodes, data );
bool value = mpw_marshal_data_vis_null( data, nodes );
va_end( nodes );
return value;
}
bool mpw_marshal_data_vset_null(
MPMarshalledData *data, va_list nodes) {
MPMarshalledData *child = mpw_marshal_data_vget( data, nodes );
if (!child)
return false;
mpw_free_string( &child->str_value );
for (unsigned int c = 0; c < child->children_count; ++c) {
mpw_marshal_data_set_null( &child->children[c], NULL );
mpw_free_string( &child->children[c].key );
}
mpw_free( &child->children, sizeof( MPMarshalledData ) * child->children_count );
child->children_count = 0;
child->num_value = NAN;
child->is_bool = false;
child->is_null = true;
return true;
}
bool mpw_marshal_data_set_null(
MPMarshalledData *data, ...) {
va_list nodes;
va_start( nodes, data );
bool success = mpw_marshal_data_vset_null( data, nodes );
va_end( nodes );
return success;
}
bool mpw_marshal_data_vget_bool(
const MPMarshalledData *data, va_list nodes) {
const MPMarshalledData *child = mpw_marshal_data_vfind( data, nodes );
return child && child->is_bool && child->num_value != false;
}
bool mpw_marshal_data_get_bool(
const MPMarshalledData *data, ...) {
va_list nodes;
va_start( nodes, data );
bool value = mpw_marshal_data_vget_bool( data, nodes );
va_end( nodes );
return value;
}
bool mpw_marshal_data_vset_bool(
const bool value, MPMarshalledData *data, va_list nodes) {
MPMarshalledData *child = mpw_marshal_data_vget( data, nodes );
if (!child || !mpw_marshal_data_set_null( child, NULL ))
return false;
child->is_null = false;
child->is_bool = true;
child->num_value = value != false;
return true;
}
bool mpw_marshal_data_set_bool(
const bool value, MPMarshalledData *data, ...) {
va_list nodes;
va_start( nodes, data );
bool success = mpw_marshal_data_vset_bool( value, data, nodes );
va_end( nodes );
return success;
}
double mpw_marshal_data_vget_num(
const MPMarshalledData *data, va_list nodes) {
const MPMarshalledData *child = mpw_marshal_data_vfind( data, nodes );
return child == NULL? NAN: child->num_value;
}
double mpw_marshal_data_get_num(
const MPMarshalledData *data, ...) {
va_list nodes;
va_start( nodes, data );
double value = mpw_marshal_data_vget_num( data, nodes );
va_end( nodes );
return value;
}
bool mpw_marshal_data_vset_num(
const double value, MPMarshalledData *data, va_list nodes) {
MPMarshalledData *child = mpw_marshal_data_vget( data, nodes );
if (!child || !mpw_marshal_data_set_null( child, NULL ))
return false;
child->is_null = false;
child->num_value = value;
child->str_value = mpw_strdup( mpw_str( "%g", value ) );
return true;
}
bool mpw_marshal_data_set_num(
const double value, MPMarshalledData *data, ...) {
va_list nodes;
va_start( nodes, data );
bool success = mpw_marshal_data_vset_num( value, data, nodes );
va_end( nodes );
return success;
}
const char *mpw_marshal_data_vget_str(
const MPMarshalledData *data, va_list nodes) {
const MPMarshalledData *child = mpw_marshal_data_vfind( data, nodes );
return child == NULL? NULL: mpw_strdup( child->str_value );
}
const char *mpw_marshal_data_get_str(
const MPMarshalledData *data, ...) {
va_list nodes;
va_start( nodes, data );
const char *value = mpw_marshal_data_vget_str( data, nodes );
va_end( nodes );
return value;
}
bool mpw_marshal_data_vset_str(
const char *value, MPMarshalledData *data, va_list nodes) {
MPMarshalledData *child = mpw_marshal_data_vget( data, nodes );
if (!child || !mpw_marshal_data_set_null( child, NULL ))
return false;
if (value) {
child->is_null = false;
child->str_value = mpw_strdup( value );
}
return true;
}
bool mpw_marshal_data_set_str(
const char *value, MPMarshalledData *data, ...) {
va_list nodes;
va_start( nodes, data );
bool success = mpw_marshal_data_vset_str( value, data, nodes );
va_end( nodes );
return success;
}
@ -285,20 +519,24 @@ static const char *mpw_marshal_write_flat(
#if MPW_JSON
static json_object *mpw_get_json_data(
MPMarshalledData *data) {
const 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 (!isnan( data->num_value )) {
if (data->str_value)
return json_object_new_double_s( data->num_value, data->str_value );
else
return json_object_new_double( data->num_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];
for (size_t c = 0; c < data->children_count; ++c) {
MPMarshalledData *child = &data->children[c];
if (!obj) {
if (child->key)
obj = json_object_new_object();
@ -505,8 +743,8 @@ static void mpw_marshal_read_flat_info(
break;
// Header
char *headerName = mpw_get_token( &positionInLine, endOfLine, ":\n" );
char *headerValue = mpw_get_token( &positionInLine, endOfLine, "\n" );
const char *headerName = mpw_get_token( &positionInLine, endOfLine, ":\n" );
const char *headerValue = mpw_get_token( &positionInLine, endOfLine, "\n" );
if (!headerName || !headerValue)
continue;
@ -605,8 +843,8 @@ static MPMarshalledFile *mpw_marshal_read_flat(
}
// Header
char *headerName = mpw_get_token( &positionInLine, endOfLine, ":\n" );
char *headerValue = mpw_get_token( &positionInLine, endOfLine, "\n" );
const char *headerName = mpw_get_token( &positionInLine, endOfLine, ":\n" );
const char *headerValue = mpw_get_token( &positionInLine, endOfLine, "\n" );
if (!headerName || !headerValue) {
error->type = MPMarshalErrorStructure;
error->message = mpw_str( "Invalid header: %s", mpw_strndup( positionInLine, (size_t)(endOfLine - positionInLine) ) );
@ -672,8 +910,8 @@ static MPMarshalledFile *mpw_marshal_read_flat(
continue;
// Site
char *siteName = NULL, *siteResultState = NULL, *siteLoginState = NULL;
char *str_lastUsed = NULL, *str_uses = NULL, *str_type = NULL, *str_algorithm = NULL, *str_counter = NULL;
const char *siteName = NULL, *siteResultState = NULL, *siteLoginState = NULL;
const char *str_lastUsed = NULL, *str_uses = NULL, *str_type = NULL, *str_algorithm = NULL, *str_counter = NULL;
switch (format) {
case 0: {
str_lastUsed = mpw_get_token( &positionInLine, endOfLine, " \t\n" );
@ -834,6 +1072,9 @@ static MPMarshalledFile *mpw_marshal_read_flat(
static void mpw_set_json_data(
MPMarshalledData *data, json_object *obj) {
if (!data)
return;
json_type type = json_object_get_type( obj );
data->is_null = type == json_type_null;
data->is_bool = type == json_type_boolean;
@ -860,16 +1101,15 @@ static void mpw_set_json_data(
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 );
}
if ((type != json_type_object && type != json_type_array) || (child->key && type != json_type_object)) {
// Not a valid child in this object, remove it.
mpw_marshal_data_set_null( child, NULL );
mpw_free_string( &child->key );
if (!newChildren)
newChildren = mpw_memdup( data->children, sizeof( MPMarshalledData ) * newChildrenCount );
}
else {
// Valid child in this object, keep it.
++newChildrenCount;
if (newChildren) {
if (!mpw_realloc( &newChildren, NULL, sizeof( MPMarshalledData ) * newChildrenCount )) {
@ -896,7 +1136,7 @@ static void mpw_set_json_data(
// 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) {
(data->children[c].key && entry.key && strcmp( data->children[c].key, entry.key ) == OK)) {
child = &data->children[c];
break;
}
@ -965,7 +1205,7 @@ static void mpw_marshal_read_json_info(
}
static MPMarshalledFile *mpw_marshal_read_json(
const char *in, MPMasterKeyProvider masterKeyProvider, MPMarshalError *error) {
const char *in, const MPMasterKeyProvider masterKeyProvider, MPMarshalError *error) {
*error = (MPMarshalError){ MPMarshalErrorInternal, "Unexpected internal error." };
if (!in || !strlen( in )) {
@ -1173,11 +1413,8 @@ static MPMarshalledFile *mpw_marshal_read_json(
}
mpw_free( &masterKey, MPMasterKeySize );
MPMarshalledData *data = malloc( sizeof( MPMarshalledData ) );
if (data) {
*data = (MPMarshalledData){};
mpw_set_json_data( data, json_file );
}
MPMarshalledData *data = mpw_marshal_data_new();
mpw_set_json_data( data, json_file );
json_object_put( json_file );
MPMarshalledFile *file = mpw_marshal_file( user, data );
@ -1223,7 +1460,7 @@ MPMarshalInfo *mpw_marshal_read_info(
}
MPMarshalledFile *mpw_marshal_read(
const char *in, MPMasterKeyProvider masterKeyProvider, MPMarshalError *error) {
const char *in, const MPMasterKeyProvider masterKeyProvider, MPMarshalError *error) {
MPMarshalInfo *info = mpw_marshal_read_info( in );
if (!info)
@ -1314,10 +1551,10 @@ const char **mpw_marshal_format_extensions(
return NULL;
case MPMarshalFormatFlat:
return mpw_strings( count,
mpw_marshal_format_extension( format ), "mpsites.txt", "txt" );
mpw_marshal_format_extension( format ), "mpsites.txt", "txt", NULL );
case MPMarshalFormatJSON:
return mpw_strings( count,
mpw_marshal_format_extension( format ), "mpsites.json", "json" );
mpw_marshal_format_extension( format ), "mpsites.json", "json", NULL );
default: {
dbg( "Unknown format: %d", format );
return NULL;

View File

@ -23,6 +23,7 @@
MP_LIBS_BEGIN
#include <time.h>
#include <stdarg.h>
MP_LIBS_END
//// Types.
@ -161,14 +162,14 @@ MPMarshalInfo *mpw_marshal_read_info(
/** Unmarshall sites in the given input buffer by parsing it using the given marshalling format.
* @return A user object (allocated), or NULL if the format provides no marshalling or a format error occurred. */
MPMarshalledFile *mpw_marshal_read(
const char *in, MPMasterKeyProvider masterKeyProvider, MPMarshalError *error);
const char *in, const MPMasterKeyProvider masterKeyProvider, MPMarshalError *error);
//// Utilities.
//// Creating.
/** Create a new user object ready for marshalling.
* @return A user object (allocated), or NULL if the fullName is missing or the marshalled user couldn't be allocated. */
MPMarshalledUser *mpw_marshal_user(
const char *fullName, MPMasterKeyProvider masterKeyProvider, const MPAlgorithmVersion algorithmVersion);
const char *fullName, const MPMasterKeyProvider masterKeyProvider, const MPAlgorithmVersion algorithmVersion);
/** Create a new site attached to the given user object, ready for marshalling.
* @return A site object (allocated), or NULL if the siteName is missing or the marshalled site couldn't be allocated. */
MPMarshalledSite *mpw_marshal_site(
@ -183,11 +184,77 @@ MPMarshalledQuestion *mpw_marshal_question(
MPMarshalledFile *mpw_marshal_file(
MPMarshalledUser *user, MPMarshalledData *data);
//// Disposing.
/** Free the given user object and all associated data. */
bool mpw_marshal_info_free(
void mpw_marshal_info_free(
MPMarshalInfo **info);
bool mpw_marshal_free(
MPMarshalledFile **user);
void mpw_marshal_user_free(
MPMarshalledUser **user);
void mpw_marshal_file_free(
MPMarshalledFile **file);
//// Exploring.
/** Create a null value.
* @return A new data value (allocated), initialized to a null value, or NULL if the value couldn't be allocated. */
MPMarshalledData *mpw_marshal_data_new(void);
/** Get or create a value for the given path in the data store.
* @return The value at this path (shared), or NULL if the value didn't exist and couldn't be created. */
MPMarshalledData *mpw_marshal_data_get(
MPMarshalledData *data, ...);
MPMarshalledData *mpw_marshal_data_vget(
MPMarshalledData *data, va_list nodes);
/** Look up the value at the given path in the data store.
* @return The value at this path (shared), or NULL if there is no value at this path. */
const MPMarshalledData *mpw_marshal_data_find(
const MPMarshalledData *data, ...);
const MPMarshalledData *mpw_marshal_data_vfind(
const MPMarshalledData *data, va_list nodes);
/** Check if the data represents a NULL value.
* @return true if the value at this path is null or is missing, false if it is a non-null type. */
bool mpw_marshal_data_is_null(
const MPMarshalledData *data, ...);
bool mpw_marshal_data_vis_null(
const MPMarshalledData *data, va_list nodes);
/** Set a null value at the given path in the data store.
* @return true if the object was successfully modified. */
bool mpw_marshal_data_set_null(
MPMarshalledData *data, ...);
bool mpw_marshal_data_vset_null(
MPMarshalledData *data, va_list nodes);
/** Look up the boolean value at the given path in the data store.
* @return true if the value at this path is true, false if it is not or there is no boolean value at this path. */
bool mpw_marshal_data_get_bool(
const MPMarshalledData *data, ...);
bool mpw_marshal_data_vget_bool(
const MPMarshalledData *data, va_list nodes);
/** Set a boolean value at the given path in the data store.
* @return true if the object was successfully modified. */
bool mpw_marshal_data_set_bool(
const bool value, MPMarshalledData *data, ...);
bool mpw_marshal_data_vset_bool(
const bool value, MPMarshalledData *data, va_list nodes);
/** Look up the numeric value at the given path in the data store.
* @return A number or NAN if there is no numeric value at this path. */
double mpw_marshal_data_get_num(
const MPMarshalledData *data, ...);
double mpw_marshal_data_vget_num(
const MPMarshalledData *data, va_list nodes);
bool mpw_marshal_data_set_num(
const double value, MPMarshalledData *data, ...);
bool mpw_marshal_data_vset_num(
const double value, MPMarshalledData *data, va_list nodes);
/** Look up the string value at the given path in the data store.
* @return The string value (allocated) or string representation of the number at this path; NULL if there is no such value at this path. */
const char *mpw_marshal_data_get_str(
const MPMarshalledData *data, ...);
const char *mpw_marshal_data_vget_str(
const MPMarshalledData *data, va_list nodes);
bool mpw_marshal_data_set_str(
const char *value, MPMarshalledData *data, ...);
bool mpw_marshal_data_vset_str(
const char *value, MPMarshalledData *data, va_list nodes);
//// Format.

View File

@ -90,7 +90,7 @@ const MPResultType mpw_type_named(const char *typeName) {
return (MPResultType)ERR;
}
const char *mpw_type_abbreviation(MPResultType resultType) {
const char *mpw_type_abbreviation(const MPResultType resultType) {
switch (resultType) {
case MPResultTypeTemplateMaximum:
@ -122,7 +122,7 @@ const char *mpw_type_abbreviation(MPResultType resultType) {
}
}
const char *mpw_type_short_name(MPResultType resultType) {
const char *mpw_type_short_name(const MPResultType resultType) {
switch (resultType) {
case MPResultTypeTemplateMaximum:
@ -154,7 +154,7 @@ const char *mpw_type_short_name(MPResultType resultType) {
}
}
const char *mpw_type_long_name(MPResultType resultType) {
const char *mpw_type_long_name(const MPResultType resultType) {
switch (resultType) {
case MPResultTypeTemplateMaximum:
@ -186,7 +186,7 @@ const char *mpw_type_long_name(MPResultType resultType) {
}
}
const char **mpw_type_templates(MPResultType type, size_t *count) {
const char **mpw_type_templates(const MPResultType type, size_t *count) {
if (!(type & MPResultTypeClassTemplate)) {
dbg( "Not a generated type: %d", type );
@ -231,7 +231,7 @@ const char **mpw_type_templates(MPResultType type, size_t *count) {
}
}
const char *mpw_type_template(MPResultType type, uint8_t templateIndex) {
const char *mpw_type_template(const MPResultType type, const uint8_t templateIndex) {
size_t count = 0;
const char **templates = mpw_type_templates( type, &count );
@ -254,7 +254,7 @@ const MPKeyPurpose mpw_purpose_named(const char *purposeName) {
return (MPKeyPurpose)ERR;
}
const char *mpw_purpose_name(MPKeyPurpose purpose) {
const char *mpw_purpose_name(const MPKeyPurpose purpose) {
switch (purpose) {
case MPKeyPurposeAuthentication:
@ -270,7 +270,7 @@ const char *mpw_purpose_name(MPKeyPurpose purpose) {
}
}
const char *mpw_purpose_scope(MPKeyPurpose purpose) {
const char *mpw_purpose_scope(const MPKeyPurpose purpose) {
switch (purpose) {
case MPKeyPurposeAuthentication:
@ -286,7 +286,7 @@ const char *mpw_purpose_scope(MPKeyPurpose purpose) {
}
}
const char *mpw_class_characters(char characterClass) {
const char *mpw_class_characters(const char characterClass) {
switch (characterClass) {
case 'V':
@ -316,7 +316,7 @@ const char *mpw_class_characters(char characterClass) {
}
}
const char mpw_class_character(char characterClass, uint8_t seedByte) {
const char mpw_class_character(const char characterClass, const uint8_t seedByte) {
const char *classCharacters = mpw_class_characters( characterClass );
if (!classCharacters || !strlen( classCharacters ))

View File

@ -152,11 +152,11 @@ const MPKeyPurpose mpw_purpose_named(const char *purposeName);
/**
* @return The standard name (static) for the given purpose or NULL if the purpose is not known.
*/
const char *mpw_purpose_name(MPKeyPurpose purpose);
const char *mpw_purpose_name(const MPKeyPurpose purpose);
/**
* @return The scope identifier (static) to apply when encoding for the given purpose or NULL if the purpose is not known.
*/
const char *mpw_purpose_scope(MPKeyPurpose purpose);
const char *mpw_purpose_scope(const MPKeyPurpose purpose);
/**
* @return The password type represented by the given name or ERR if the name does not represent a known type.
@ -165,34 +165,34 @@ const MPResultType mpw_type_named(const char *typeName);
/**
* @return The standard identifying name (static) for the given password type or NULL if the type is not known.
*/
const char *mpw_type_abbreviation(MPResultType resultType);
const char *mpw_type_abbreviation(const MPResultType resultType);
/**
* @return The standard identifying name (static) for the given password type or NULL if the type is not known.
*/
const char *mpw_type_short_name(MPResultType resultType);
const char *mpw_type_short_name(const MPResultType resultType);
/**
* @return The descriptive name (static) for the given password type or NULL if the type is not known.
*/
const char *mpw_type_long_name(MPResultType resultType);
const char *mpw_type_long_name(const MPResultType resultType);
/**
* @return An array (allocated, count) of strings (static) that express the templates to use for the given type.
* NULL if the type is not known or is not a MPResultTypeClassTemplate.
*/
const char **mpw_type_templates(MPResultType type, size_t *count);
const char **mpw_type_templates(const MPResultType type, size_t *count);
/**
* @return A string (static) that contains the password encoding template of the given type for a seed that starts with the given byte.
* NULL if the type is not known or is not a MPResultTypeClassTemplate.
*/
const char *mpw_type_template(MPResultType type, uint8_t templateIndex);
const char *mpw_type_template(const MPResultType type, const uint8_t templateIndex);
/**
* @return An string (static) with all the characters in the given character class or NULL if the character class is not known.
*/
const char *mpw_class_characters(char characterClass);
const char *mpw_class_characters(const char characterClass);
/**
* @return A character from given character class that encodes the given byte or NUL if the character class is not known or is empty.
*/
const char mpw_class_character(char characterClass, uint8_t seedByte);
const char mpw_class_character(const char characterClass, const uint8_t seedByte);
#endif // _MPW_TYPES_H

View File

@ -175,7 +175,7 @@ bool __mpw_free(void **buffer, const size_t bufferSize) {
bool __mpw_free_string(char **string) {
return *string && __mpw_free( (void **)string, strlen( *string ) );
return string && *string && __mpw_free( (void **)string, strlen( *string ) );
}
bool __mpw_free_strings(char **strings, ...) {
@ -193,7 +193,7 @@ bool __mpw_free_strings(char **strings, ...) {
}
uint8_t const *mpw_kdf_scrypt(const size_t keySize, const uint8_t *secret, const size_t secretSize, const uint8_t *salt, const size_t saltSize,
uint64_t N, uint32_t r, uint32_t p) {
const uint64_t N, const uint32_t r, const uint32_t p) {
if (!secret || !salt || !secretSize || !saltSize)
return NULL;
@ -367,7 +367,7 @@ const char *mpw_hotp(const uint8_t *key, size_t keySize, uint64_t movingFactor,
}
#endif
MPKeyID mpw_id_buf(const void *buf, size_t length) {
const MPKeyID mpw_id_buf(const void *buf, const size_t length) {
if (!buf)
return NULL;
@ -443,7 +443,7 @@ const char *mpw_vstr(const char *format, va_list args) {
return str_str[str_str_i];
}
const char *mpw_hex(const void *buf, size_t length) {
const char *mpw_hex(const void *buf, const size_t length) {
if (!buf || !length)
return NULL;
@ -461,7 +461,7 @@ const char *mpw_hex(const void *buf, size_t length) {
return mpw_hex_buf[mpw_hex_buf_i];
}
const char *mpw_hex_l(uint32_t number) {
const char *mpw_hex_l(const uint32_t number) {
uint8_t buf[4 /* 32 / 8 */];
buf[0] = (uint8_t)((number >> 24) & UINT8_MAX);
@ -496,7 +496,7 @@ size_t mpw_utf8_strchars(const char *utf8String) {
return strchars;
}
void *mpw_memdup(const void *src, size_t len) {
void *mpw_memdup(const void *src, const size_t len) {
if (!src)
return NULL;
@ -517,7 +517,7 @@ char *mpw_strdup(const char *src) {
return mpw_memdup( src, len + 1 );
}
char *mpw_strndup(const char *src, size_t max) {
char *mpw_strndup(const char *src, const size_t max) {
if (!src)
return NULL;
@ -525,8 +525,7 @@ char *mpw_strndup(const char *src, size_t max) {
size_t len = 0;
for (; len < max && src[len] != '\0'; ++len);
char *dst = malloc( len + 1 );
memcpy( dst, src, len );
char *dst = mpw_memdup( src, len + 1 );
dst[len] = '\0';
return dst;

View File

@ -122,7 +122,7 @@ bool mpw_string_push(
bool mpw_string_pushf(
char **string, const char *pushFormat, ...);
// These defines merely exist to force the void** cast (& do type-checking), since void** casts are not automatic.
// These defines merely exist to do type-checking, force the void** cast & drop any const qualifier.
/** Reallocate the given buffer from the given size by adding the delta size.
* On success, the buffer size pointer will be updated to the buffer's new size
* and the buffer pointer may be updated to a new memory address.
@ -176,7 +176,7 @@ bool __mpw_free_string(
bool __mpw_free_strings(
char **strings, ...);
void mpw_zero(
void *buffer, size_t bufferSize);
void *buffer, const size_t bufferSize);
//// Cryptographic functions.
@ -184,7 +184,7 @@ void mpw_zero(
* @return A buffer (allocated, keySize) containing the key or NULL if secret or salt is missing, key could not be allocated or the KDF failed. */
uint8_t const *mpw_kdf_scrypt(
const size_t keySize, const uint8_t *secret, const size_t secretSize, const uint8_t *salt, const size_t saltSize,
uint64_t N, uint32_t r, uint32_t p);
const uint64_t N, const uint32_t r, const uint32_t p);
/** Derive a subkey from the given key using the blake2b KDF.
* @return A buffer (allocated, keySize) containing the key or NULL if the key or subkeySize is missing, the key sizes are out of bounds, the subkey could not be allocated or derived. */
uint8_t const *mpw_kdf_blake2b(
@ -217,11 +217,11 @@ const char *mpw_str(const char *format, ...);
const char *mpw_vstr(const char *format, va_list args);
/** Encode a buffer as a string of hexadecimal characters.
* @return A string (shared); or NULL if the buffer is missing or the result could not be allocated. */
const char *mpw_hex(const void *buf, size_t length);
const char *mpw_hex_l(uint32_t number);
const char *mpw_hex(const void *buf, const size_t length);
const char *mpw_hex_l(const uint32_t number);
/** Encode a fingerprint for a buffer.
* @return A string (shared); or NULL if the buffer is missing or the result could not be allocated. */
MPKeyID mpw_id_buf(const void *buf, size_t length);
const MPKeyID mpw_id_buf(const void *buf, const size_t length);
/** Compare two fingerprints for equality.
* @return true if the buffers represent identical fingerprints or are both NULL. */
bool mpw_id_buf_equals(const char *id1, const char *id2);
@ -234,14 +234,14 @@ size_t mpw_utf8_charlen(const char *utf8String);
size_t mpw_utf8_strchars(const char *utf8String);
/** Drop-in for memdup(3).
* @return A buffer (allocated, len) with len bytes copied from src or NULL if src is missing or the buffer could not be allocated. */
void *mpw_memdup(const void *src, size_t len);
void *mpw_memdup(const void *src, const size_t len);
/** Drop-in for POSIX strdup(3).
* @return A string (allocated) copied from src or NULL if src is missing or the buffer could not be allocated. */
char *mpw_strdup(const char *src);
/** Drop-in for POSIX strndup(3).
* @return A string (allocated) with no more than max bytes copied from src or NULL if src is missing or the buffer could not be allocated. */
char *mpw_strndup(const char *src, size_t max);
char *mpw_strndup(const char *src, const size_t max);
/** Drop-in for POSIX strncasecmp(3). */
int mpw_strncasecmp(const char *s1, const char *s2, size_t max);
int mpw_strncasecmp(const char *s1, const char *s2, const size_t max);
#endif // _MPW_UTIL_H