More flexible API for providing marshalling master key.
This commit is contained in:
		@@ -29,6 +29,7 @@
 | 
			
		||||
#include "mpw-algorithm.h"
 | 
			
		||||
#include "mpw-util.h"
 | 
			
		||||
#include "mpw-marshal.h"
 | 
			
		||||
#include "mpw-marshal-util.h"
 | 
			
		||||
 | 
			
		||||
/** Output the program's usage documentation. */
 | 
			
		||||
static void usage() {
 | 
			
		||||
@@ -182,6 +183,9 @@ void cli_sitesRedacted(Arguments *args, Operation *operation);
 | 
			
		||||
void cli_mpw(Arguments *args, Operation *operation);
 | 
			
		||||
void cli_save(Arguments *args, Operation *operation);
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_op(Operation *operation);
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_str(const char *masterPassword);
 | 
			
		||||
 | 
			
		||||
/** ========================================================================
 | 
			
		||||
 *  MAIN                                                                     */
 | 
			
		||||
int main(const int argc, char *const argv[]) {
 | 
			
		||||
@@ -230,7 +234,6 @@ int main(const int argc, char *const argv[]) {
 | 
			
		||||
    dbg( "-----------------" );
 | 
			
		||||
    if (operation.user) {
 | 
			
		||||
        dbg( "fullName         : %s", operation.user->fullName );
 | 
			
		||||
        trc( "masterPassword   : %s", operation.user->masterPassword );
 | 
			
		||||
        dbg( "identicon        : %s", operation.identicon );
 | 
			
		||||
        dbg( "sitesFormat      : %s%s", mpw_nameForFormat( operation.sitesFormat ), operation.sitesFormatFixed? " (fixed)": "" );
 | 
			
		||||
        dbg( "sitesPath        : %s", operation.sitesPath );
 | 
			
		||||
@@ -247,11 +250,11 @@ int main(const int argc, char *const argv[]) {
 | 
			
		||||
    dbg( "-----------------" );
 | 
			
		||||
 | 
			
		||||
    // Finally ready to perform the actual operation.
 | 
			
		||||
    cli_mpw( &args, &operation );
 | 
			
		||||
    cli_mpw( NULL, &operation );
 | 
			
		||||
 | 
			
		||||
    // Save changes and clean up.
 | 
			
		||||
    cli_save( &args, &operation );
 | 
			
		||||
    cli_free( &args, &operation );
 | 
			
		||||
    cli_save( NULL, &operation );
 | 
			
		||||
    cli_free( NULL, &operation );
 | 
			
		||||
 | 
			
		||||
    return EX_OK;
 | 
			
		||||
}
 | 
			
		||||
@@ -487,7 +490,7 @@ void cli_user(Arguments *args, Operation *operation) {
 | 
			
		||||
        MPMarshalError marshalError = { .type = MPMarshalSuccess };
 | 
			
		||||
        mpw_marshal_info_free( &sitesInputInfo );
 | 
			
		||||
        mpw_marshal_free( &operation->user );
 | 
			
		||||
        operation->user = mpw_marshal_read( sitesInputData, sitesInputFormat, operation->masterPassword, &marshalError );
 | 
			
		||||
        operation->user = mpw_marshal_read( sitesInputData, sitesInputFormat, cli_masterKeyProvider_op( operation ), &marshalError );
 | 
			
		||||
        if (marshalError.type == MPMarshalErrorMasterPassword && operation->allowPasswordUpdate) {
 | 
			
		||||
            // Update master password in mpsites.
 | 
			
		||||
            while (marshalError.type == MPMarshalErrorMasterPassword) {
 | 
			
		||||
@@ -499,12 +502,10 @@ void cli_user(Arguments *args, Operation *operation) {
 | 
			
		||||
                    importMasterPassword = mpw_getpass( "Old master password: " );
 | 
			
		||||
 | 
			
		||||
                mpw_marshal_free( &operation->user );
 | 
			
		||||
                operation->user = mpw_marshal_read( sitesInputData, sitesInputFormat, importMasterPassword, &marshalError );
 | 
			
		||||
                operation->user = mpw_marshal_read( sitesInputData, sitesInputFormat, cli_masterKeyProvider_str( importMasterPassword ), &marshalError );
 | 
			
		||||
                mpw_free_string( &importMasterPassword );
 | 
			
		||||
            }
 | 
			
		||||
            if (operation->user) {
 | 
			
		||||
                mpw_free_string( &operation->user->masterPassword );
 | 
			
		||||
                operation->user->masterPassword = mpw_strdup( operation->masterPassword );
 | 
			
		||||
                
 | 
			
		||||
                operation->user->masterKeyProvider = cli_masterKeyProvider_op( operation );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        mpw_free_string( &sitesInputData );
 | 
			
		||||
@@ -527,7 +528,7 @@ void cli_user(Arguments *args, Operation *operation) {
 | 
			
		||||
    // If no user from mpsites, create a new one.
 | 
			
		||||
    if (!operation->user)
 | 
			
		||||
        operation->user = mpw_marshal_user(
 | 
			
		||||
                operation->fullName, operation->masterPassword, MPAlgorithmVersionCurrent );
 | 
			
		||||
                operation->fullName, cli_masterKeyProvider_op( operation ), MPAlgorithmVersionCurrent );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_site(Arguments *args, Operation *operation) {
 | 
			
		||||
@@ -572,7 +573,7 @@ void cli_question(Arguments *args, Operation *operation) {
 | 
			
		||||
void cli_operation(Arguments *args, Operation *operation) {
 | 
			
		||||
 | 
			
		||||
    mpw_free_string( &operation->identicon );
 | 
			
		||||
    operation->identicon = mpw_identicon_str( mpw_identicon( operation->user->fullName, operation->user->masterPassword ) );
 | 
			
		||||
    operation->identicon = mpw_identicon_str( mpw_identicon( operation->user->fullName, operation->masterPassword ) );
 | 
			
		||||
 | 
			
		||||
    if (!operation->site)
 | 
			
		||||
        abort();
 | 
			
		||||
@@ -702,8 +703,7 @@ void cli_mpw(Arguments *args, Operation *operation) {
 | 
			
		||||
                operation->user->fullName, operation->purposeResult, operation->site->name, operation->identicon );
 | 
			
		||||
 | 
			
		||||
    // Determine master key.
 | 
			
		||||
    MPMasterKey masterKey = mpw_masterKey(
 | 
			
		||||
            operation->user->fullName, operation->user->masterPassword, operation->site->algorithm );
 | 
			
		||||
    MPMasterKey masterKey = operation->user->masterKeyProvider( operation->site->algorithm, operation->user->fullName );
 | 
			
		||||
    if (!masterKey) {
 | 
			
		||||
        ftl( "Couldn't derive master key." );
 | 
			
		||||
        cli_free( args, operation );
 | 
			
		||||
@@ -799,3 +799,32 @@ void cli_save(Arguments *args, Operation *operation) {
 | 
			
		||||
    mpw_free_string( &buf );
 | 
			
		||||
    fclose( sitesFile );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MPMasterKey __cli_masterKeyProvider_currentKey;
 | 
			
		||||
static MPAlgorithmVersion __cli_masterKeyProvider_currentAlgorithm;
 | 
			
		||||
static const char *__cli_masterKeyProvider_currentPassword;
 | 
			
		||||
static Operation *__cli_masterKeyProvider_currentOperation;
 | 
			
		||||
static MPMasterKey __cli_masterKeyProvider_op(MPAlgorithmVersion algorithm, const char *fullName) {
 | 
			
		||||
    if (mpw_update_masterKey(&__cli_masterKeyProvider_currentKey, &__cli_masterKeyProvider_currentAlgorithm,
 | 
			
		||||
                             algorithm, fullName, __cli_masterKeyProvider_currentOperation->masterPassword))
 | 
			
		||||
        return __cli_masterKeyProvider_currentKey;
 | 
			
		||||
    
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
static MPMasterKey __cli_masterKeyProvider_str(MPAlgorithmVersion algorithm, const char *fullName) {
 | 
			
		||||
    if (mpw_update_masterKey(&__cli_masterKeyProvider_currentKey, &__cli_masterKeyProvider_currentAlgorithm,
 | 
			
		||||
                             algorithm, fullName, __cli_masterKeyProvider_currentPassword))
 | 
			
		||||
        return __cli_masterKeyProvider_currentKey;
 | 
			
		||||
    
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_op(Operation *operation) {
 | 
			
		||||
    __cli_masterKeyProvider_currentOperation = operation;
 | 
			
		||||
    return __cli_masterKeyProvider_op;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_str(const char *masterPassword) {
 | 
			
		||||
    __cli_masterKeyProvider_currentPassword = masterPassword;
 | 
			
		||||
    return __cli_masterKeyProvider_str;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -106,7 +106,7 @@ bool mpw_get_json_boolean(
 | 
			
		||||
bool mpw_update_masterKey(MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, MPAlgorithmVersion targetKeyAlgorithm,
 | 
			
		||||
        const char *fullName, const char *masterPassword) {
 | 
			
		||||
 | 
			
		||||
    if (*masterKeyAlgorithm != targetKeyAlgorithm) {
 | 
			
		||||
    if (masterKey && (!*masterKey || *masterKeyAlgorithm != targetKeyAlgorithm)) {
 | 
			
		||||
        mpw_free( masterKey, MPMasterKeySize );
 | 
			
		||||
        *masterKeyAlgorithm = targetKeyAlgorithm;
 | 
			
		||||
        *masterKey = mpw_masterKey( fullName, masterPassword, *masterKeyAlgorithm );
 | 
			
		||||
 
 | 
			
		||||
@@ -26,15 +26,15 @@
 | 
			
		||||
#include "mpw-marshal-util.h"
 | 
			
		||||
 | 
			
		||||
MPMarshalledUser *mpw_marshal_user(
 | 
			
		||||
        const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) {
 | 
			
		||||
        const char *fullName, MPMasterKeyProvider masterKeyProvider, const MPAlgorithmVersion algorithmVersion) {
 | 
			
		||||
 | 
			
		||||
    MPMarshalledUser *user;
 | 
			
		||||
    if (!fullName || !masterPassword || !(user = malloc( sizeof( MPMarshalledUser ) )))
 | 
			
		||||
    if (!fullName || !masterKeyProvider || !(user = malloc( sizeof( MPMarshalledUser ) )))
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    *user = (MPMarshalledUser){
 | 
			
		||||
            .fullName = mpw_strdup( fullName ),
 | 
			
		||||
            .masterPassword = mpw_strdup( masterPassword ),
 | 
			
		||||
            .masterKeyProvider = masterKeyProvider,
 | 
			
		||||
            .algorithm = algorithmVersion,
 | 
			
		||||
            .redacted = true,
 | 
			
		||||
 | 
			
		||||
@@ -113,7 +113,7 @@ bool mpw_marshal_free(
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    bool success = true;
 | 
			
		||||
    success &= mpw_free_strings( &(*user)->fullName, &(*user)->masterPassword, NULL );
 | 
			
		||||
    success &= mpw_free_strings( &(*user)->fullName, NULL );
 | 
			
		||||
 | 
			
		||||
    for (size_t s = 0; s < (*user)->sites_count; ++s) {
 | 
			
		||||
        MPMarshalledSite *site = &(*user)->sites[s];
 | 
			
		||||
@@ -140,13 +140,8 @@ static bool mpw_marshal_write_flat(
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorMissing, "Missing full name." };
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (!user->masterPassword || !strlen( user->masterPassword )) {
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorMasterPassword, "Missing master password." };
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    MPMasterKey masterKey = NULL;
 | 
			
		||||
    MPAlgorithmVersion masterKeyAlgorithm = user->algorithm - 1;
 | 
			
		||||
    if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, user->algorithm, user->fullName, user->masterPassword )) {
 | 
			
		||||
    MPMasterKey masterKey = user->masterKeyProvider( user->algorithm, user->fullName );
 | 
			
		||||
    if (!masterKey) {
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
@@ -185,7 +180,8 @@ static bool mpw_marshal_write_flat(
 | 
			
		||||
        const char *content = NULL, *loginContent = NULL;
 | 
			
		||||
        if (!user->redacted) {
 | 
			
		||||
            // Clear Text
 | 
			
		||||
            if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, user->fullName, user->masterPassword )) {
 | 
			
		||||
            mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
            if (!(masterKey = user->masterKeyProvider( user->algorithm, user->fullName ))) {
 | 
			
		||||
                *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
@@ -224,13 +220,8 @@ static bool mpw_marshal_write_json(
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorMissing, "Missing full name." };
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (!user->masterPassword || !strlen( user->masterPassword )) {
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorMasterPassword, "Missing master password." };
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    MPMasterKey masterKey = NULL;
 | 
			
		||||
    MPAlgorithmVersion masterKeyAlgorithm = user->algorithm - 1;
 | 
			
		||||
    if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, user->algorithm, user->fullName, user->masterPassword )) {
 | 
			
		||||
    MPMasterKey masterKey = user->masterKeyProvider( user->algorithm, user->fullName );
 | 
			
		||||
    if (!masterKey) {
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
@@ -271,7 +262,8 @@ static bool mpw_marshal_write_json(
 | 
			
		||||
        const char *content = NULL, *loginContent = NULL;
 | 
			
		||||
        if (!user->redacted) {
 | 
			
		||||
            // Clear Text
 | 
			
		||||
            if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, user->fullName, user->masterPassword )) {
 | 
			
		||||
            mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
            if (!(masterKey = user->masterKeyProvider( user->algorithm, user->fullName ))) {
 | 
			
		||||
                *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
@@ -341,8 +333,8 @@ static bool mpw_marshal_write_json(
 | 
			
		||||
 | 
			
		||||
    mpw_string_pushf( out, "%s\n", json_object_to_json_string_ext( json_file,
 | 
			
		||||
            JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_NOSLASHESCAPE ) );
 | 
			
		||||
    mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
    json_object_put( json_file );
 | 
			
		||||
    mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
 | 
			
		||||
    *error = (MPMarshalError){ .type = MPMarshalSuccess };
 | 
			
		||||
    return true;
 | 
			
		||||
@@ -416,7 +408,7 @@ static void mpw_marshal_read_flat_info(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MPMarshalledUser *mpw_marshal_read_flat(
 | 
			
		||||
        const char *in, const char *masterPassword, MPMarshalError *error) {
 | 
			
		||||
        const char *in, MPMasterKeyProvider masterKeyProvider, MPMarshalError *error) {
 | 
			
		||||
 | 
			
		||||
    *error = (MPMarshalError){ MPMarshalErrorInternal, "Unexpected internal error." };
 | 
			
		||||
    if (!in || !strlen( in )) {
 | 
			
		||||
@@ -430,7 +422,7 @@ static MPMarshalledUser *mpw_marshal_read_flat(
 | 
			
		||||
    MPMarshalledUser *user = NULL;
 | 
			
		||||
    unsigned int format = 0, avatar = 0;
 | 
			
		||||
    char *fullName = NULL, *keyID = NULL;
 | 
			
		||||
    MPAlgorithmVersion algorithm = MPAlgorithmVersionCurrent, masterKeyAlgorithm = (MPAlgorithmVersion)-1;
 | 
			
		||||
    MPAlgorithmVersion algorithm = MPAlgorithmVersionCurrent;
 | 
			
		||||
    MPResultType defaultType = MPResultTypeDefault;
 | 
			
		||||
    bool headerStarted = false, headerEnded = false, importRedacted = false;
 | 
			
		||||
    for (const char *endOfLine, *positionInLine = in; (endOfLine = strstr( positionInLine, "\n" )); positionInLine = endOfLine + 1) {
 | 
			
		||||
@@ -504,7 +496,8 @@ static MPMarshalledUser *mpw_marshal_read_flat(
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        if (!user) {
 | 
			
		||||
            if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, algorithm, fullName, masterPassword )) {
 | 
			
		||||
            mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
            if (!(masterKey = masterKeyProvider( algorithm, fullName ))) {
 | 
			
		||||
                *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
                return NULL;
 | 
			
		||||
            }
 | 
			
		||||
@@ -512,7 +505,7 @@ static MPMarshalledUser *mpw_marshal_read_flat(
 | 
			
		||||
                *error = (MPMarshalError){ MPMarshalErrorMasterPassword, "Master password doesn't match key ID." };
 | 
			
		||||
                return NULL;
 | 
			
		||||
            }
 | 
			
		||||
            if (!(user = mpw_marshal_user( fullName, masterPassword, algorithm ))) {
 | 
			
		||||
            if (!(user = mpw_marshal_user( fullName, masterKeyProvider, algorithm ))) {
 | 
			
		||||
                *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't allocate a new user." };
 | 
			
		||||
                return NULL;
 | 
			
		||||
            }
 | 
			
		||||
@@ -597,7 +590,8 @@ static MPMarshalledUser *mpw_marshal_read_flat(
 | 
			
		||||
            site->lastUsed = siteLastUsed;
 | 
			
		||||
            if (!user->redacted) {
 | 
			
		||||
                // Clear Text
 | 
			
		||||
                if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, fullName, masterPassword )) {
 | 
			
		||||
                mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
                if (!(masterKey = masterKeyProvider( user->algorithm, user->fullName ))) {
 | 
			
		||||
                    *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
                    return NULL;
 | 
			
		||||
                }
 | 
			
		||||
@@ -661,7 +655,7 @@ static void mpw_marshal_read_json_info(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MPMarshalledUser *mpw_marshal_read_json(
 | 
			
		||||
        const char *in, const char *masterPassword, MPMarshalError *error) {
 | 
			
		||||
        const char *in, MPMasterKeyProvider masterKeyProvider, MPMarshalError *error) {
 | 
			
		||||
 | 
			
		||||
    *error = (MPMarshalError){ MPMarshalErrorInternal, "Unexpected internal error." };
 | 
			
		||||
    if (!in || !strlen( in )) {
 | 
			
		||||
@@ -680,7 +674,6 @@ static MPMarshalledUser *mpw_marshal_read_json(
 | 
			
		||||
 | 
			
		||||
    // Parse import data.
 | 
			
		||||
    MPMasterKey masterKey = NULL;
 | 
			
		||||
    MPAlgorithmVersion masterKeyAlgorithm = (MPAlgorithmVersion)-1;
 | 
			
		||||
    MPMarshalledUser *user = NULL;
 | 
			
		||||
 | 
			
		||||
    // Section: "export"
 | 
			
		||||
@@ -716,7 +709,7 @@ static MPMarshalledUser *mpw_marshal_read_json(
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorMissing, "Missing value for full name." };
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, algorithm, fullName, masterPassword )) {
 | 
			
		||||
    if (!(masterKey = masterKeyProvider( user->algorithm, user->fullName ))) {
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
@@ -724,7 +717,7 @@ static MPMarshalledUser *mpw_marshal_read_json(
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorMasterPassword, "Master password doesn't match key ID." };
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (!(user = mpw_marshal_user( fullName, masterPassword, algorithm ))) {
 | 
			
		||||
    if (!(user = mpw_marshal_user( fullName, masterKeyProvider, algorithm ))) {
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't allocate a new user." };
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
@@ -781,7 +774,8 @@ static MPMarshalledUser *mpw_marshal_read_json(
 | 
			
		||||
        site->lastUsed = siteLastUsed;
 | 
			
		||||
        if (!user->redacted) {
 | 
			
		||||
            // Clear Text
 | 
			
		||||
            if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, fullName, masterPassword )) {
 | 
			
		||||
            mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
            if (!(masterKey = masterKeyProvider( user->algorithm, user->fullName ))) {
 | 
			
		||||
                *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
                return NULL;
 | 
			
		||||
            }
 | 
			
		||||
@@ -824,6 +818,7 @@ static MPMarshalledUser *mpw_marshal_read_json(
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    json_object_put( json_file );
 | 
			
		||||
    mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
 | 
			
		||||
    *error = (MPMarshalError){ .type = MPMarshalSuccess };
 | 
			
		||||
    return user;
 | 
			
		||||
@@ -853,17 +848,17 @@ MPMarshalInfo *mpw_marshal_read_info(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MPMarshalledUser *mpw_marshal_read(
 | 
			
		||||
        const char *in, const MPMarshalFormat inFormat, const char *masterPassword, MPMarshalError *error) {
 | 
			
		||||
        const char *in, const MPMarshalFormat inFormat, MPMasterKeyProvider masterKeyProvider, MPMarshalError *error) {
 | 
			
		||||
 | 
			
		||||
    switch (inFormat) {
 | 
			
		||||
        case MPMarshalFormatNone:
 | 
			
		||||
            *error = (MPMarshalError){ .type = MPMarshalSuccess };
 | 
			
		||||
            return false;
 | 
			
		||||
        case MPMarshalFormatFlat:
 | 
			
		||||
            return mpw_marshal_read_flat( in, masterPassword, error );
 | 
			
		||||
            return mpw_marshal_read_flat( in, masterKeyProvider, error );
 | 
			
		||||
#if MPW_JSON
 | 
			
		||||
        case MPMarshalFormatJSON:
 | 
			
		||||
            return mpw_marshal_read_json( in, masterPassword, error );
 | 
			
		||||
            return mpw_marshal_read_json( in, masterKeyProvider, error );
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
            *error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported input format: %u", inFormat ) };
 | 
			
		||||
 
 | 
			
		||||
@@ -56,6 +56,9 @@ typedef mpw_enum( unsigned int, MPMarshalErrorType ) {
 | 
			
		||||
    /** An internal system error interrupted marshalling. */
 | 
			
		||||
            MPMarshalErrorInternal,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef MPMasterKey (*MPMasterKeyProvider)(MPAlgorithmVersion algorithm, const char *fullName);
 | 
			
		||||
 | 
			
		||||
typedef struct MPMarshalError {
 | 
			
		||||
    MPMarshalErrorType type;
 | 
			
		||||
    const char *description;
 | 
			
		||||
@@ -87,7 +90,7 @@ typedef struct MPMarshalledSite {
 | 
			
		||||
 | 
			
		||||
typedef struct MPMarshalledUser {
 | 
			
		||||
    const char *fullName;
 | 
			
		||||
    const char *masterPassword;
 | 
			
		||||
    MPMasterKeyProvider masterKeyProvider;
 | 
			
		||||
    MPAlgorithmVersion algorithm;
 | 
			
		||||
    bool redacted;
 | 
			
		||||
 | 
			
		||||
@@ -118,13 +121,13 @@ MPMarshalInfo *mpw_marshal_read_info(
 | 
			
		||||
        const char *in);
 | 
			
		||||
/** Unmarshall sites in the given input buffer by parsing it using the given marshalling format. */
 | 
			
		||||
MPMarshalledUser *mpw_marshal_read(
 | 
			
		||||
        const char *in, const MPMarshalFormat inFormat, const char *masterPassword, MPMarshalError *error);
 | 
			
		||||
        const char *in, const MPMarshalFormat inFormat, MPMasterKeyProvider masterKeyProvider, MPMarshalError *error);
 | 
			
		||||
 | 
			
		||||
//// Utilities.
 | 
			
		||||
 | 
			
		||||
/** Create a new user object ready for marshalling. */
 | 
			
		||||
MPMarshalledUser *mpw_marshal_user(
 | 
			
		||||
        const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion);
 | 
			
		||||
        const char *fullName, MPMasterKeyProvider masterKeyProvider, const MPAlgorithmVersion algorithmVersion);
 | 
			
		||||
/** Create a new site attached to the given user object, ready for marshalling. */
 | 
			
		||||
MPMarshalledSite *mpw_marshal_site(
 | 
			
		||||
        MPMarshalledUser *user,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user