Fix masterKeyProvider args & mem bugs + multiple format extensions.
This commit is contained in:
		@@ -185,6 +185,7 @@ void cli_save(Arguments *args, Operation *operation);
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_op(Operation *operation);
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_str(const char *masterPassword);
 | 
			
		||||
void cli_masterKeyProvider_free();
 | 
			
		||||
 | 
			
		||||
/** ========================================================================
 | 
			
		||||
 *  MAIN                                                                     */
 | 
			
		||||
@@ -274,6 +275,7 @@ void cli_free(Arguments *args, Operation *operation) {
 | 
			
		||||
        mpw_marshal_free( &operation->user );
 | 
			
		||||
        operation->site = NULL;
 | 
			
		||||
        operation->question = NULL;
 | 
			
		||||
        cli_masterKeyProvider_free();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -457,22 +459,30 @@ void cli_user(Arguments *args, Operation *operation) {
 | 
			
		||||
 | 
			
		||||
    // Find mpsites file from parameters.
 | 
			
		||||
    FILE *sitesFile = NULL;
 | 
			
		||||
    mpw_free_string( &operation->sitesPath );
 | 
			
		||||
    operation->sitesPath = mpw_path( operation->fullName, mpw_marshal_format_extension( operation->sitesFormat ) );
 | 
			
		||||
    if (!operation->sitesPath || !(sitesFile = fopen( operation->sitesPath, "r" ))) {
 | 
			
		||||
        dbg( "Couldn't open configuration file:\n  %s: %s", operation->sitesPath, strerror( errno ) );
 | 
			
		||||
    const char **extensions = NULL;
 | 
			
		||||
    int count = mpw_marshal_format_extensions( operation->sitesFormat, &extensions );
 | 
			
		||||
    for (int e = 0; !sitesFile && e < count; ++e) {
 | 
			
		||||
        mpw_free_string( &operation->sitesPath );
 | 
			
		||||
        operation->sitesPath = mpw_path( operation->fullName, extensions[e] );
 | 
			
		||||
 | 
			
		||||
        // Try to fall back to the flat format.
 | 
			
		||||
        if (!operation->sitesFormatFixed) {
 | 
			
		||||
            mpw_free_string( &operation->sitesPath );
 | 
			
		||||
            operation->sitesPath = mpw_path( operation->fullName, mpw_marshal_format_extension( MPMarshalFormatFlat ) );
 | 
			
		||||
            if (operation->sitesPath && (sitesFile = fopen( operation->sitesPath, "r" )))
 | 
			
		||||
                operation->sitesFormat = MPMarshalFormatFlat;
 | 
			
		||||
            else
 | 
			
		||||
                dbg( "Couldn't open configuration file:\n  %s: %s", operation->sitesPath, strerror( errno ) );
 | 
			
		||||
        }
 | 
			
		||||
        if (!operation->sitesPath || !(sitesFile = fopen( operation->sitesPath, "r" )))
 | 
			
		||||
            dbg( "Couldn't open configuration file:\n  %s: %s", operation->sitesPath, strerror( errno ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!sitesFile && !operation->sitesFormatFixed)
 | 
			
		||||
        for (MPMarshalFormat format = MPMarshalFormatFirst; !sitesFile && format <= MPMarshalFormatLast; ++format) {
 | 
			
		||||
            count = mpw_marshal_format_extensions( operation->sitesFormat, &extensions );
 | 
			
		||||
 | 
			
		||||
            for (int e = 0; !sitesFile && e < count; ++e) {
 | 
			
		||||
                mpw_free_string( &operation->sitesPath );
 | 
			
		||||
                operation->sitesPath = mpw_path( operation->fullName, extensions[e] );
 | 
			
		||||
 | 
			
		||||
                if (!operation->sitesPath || !(sitesFile = fopen( operation->sitesPath, "r" )))
 | 
			
		||||
                    dbg( "Couldn't open configuration file:\n  %s: %s", operation->sitesPath, strerror( errno ) );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    free( extensions );
 | 
			
		||||
 | 
			
		||||
    // Load the user object from mpsites.
 | 
			
		||||
    if (!sitesFile)
 | 
			
		||||
        mpw_free_string( &operation->sitesPath );
 | 
			
		||||
@@ -490,7 +500,8 @@ 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, cli_masterKeyProvider_op( operation ), &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) {
 | 
			
		||||
@@ -498,14 +509,16 @@ void cli_user(Arguments *args, Operation *operation) {
 | 
			
		||||
                inf( "To update the configuration with this new master password, first confirm the old master password." );
 | 
			
		||||
 | 
			
		||||
                const char *importMasterPassword = NULL;
 | 
			
		||||
                while (!importMasterPassword || !strlen( importMasterPassword ))
 | 
			
		||||
                while (!importMasterPassword || !strlen( importMasterPassword )) {
 | 
			
		||||
                    mpw_free_string( &importMasterPassword );
 | 
			
		||||
                    importMasterPassword = mpw_getpass( "Old master password: " );
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                mpw_marshal_free( &operation->user );
 | 
			
		||||
                operation->user = mpw_marshal_read( sitesInputData, sitesInputFormat, cli_masterKeyProvider_str( importMasterPassword ), &marshalError );
 | 
			
		||||
                mpw_free_string( &importMasterPassword );
 | 
			
		||||
                
 | 
			
		||||
                operation->user = mpw_marshal_read( sitesInputData, sitesInputFormat,
 | 
			
		||||
                        cli_masterKeyProvider_str( importMasterPassword ), &marshalError );
 | 
			
		||||
                operation->user->masterKeyProvider = cli_masterKeyProvider_op( operation );
 | 
			
		||||
                mpw_free_string( &importMasterPassword );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        mpw_free_string( &sitesInputData );
 | 
			
		||||
@@ -772,15 +785,17 @@ void cli_mpw(Arguments *args, Operation *operation) {
 | 
			
		||||
 | 
			
		||||
void cli_save(Arguments *args, Operation *operation) {
 | 
			
		||||
 | 
			
		||||
    if (operation->sitesFormat == MPMarshalFormatNone)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (!operation->sitesFormatFixed)
 | 
			
		||||
        operation->sitesFormat = MPMarshalFormatDefault;
 | 
			
		||||
 | 
			
		||||
    const char **extensions = NULL;
 | 
			
		||||
    if (!mpw_marshal_format_extensions( operation->sitesFormat, &extensions ))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    mpw_free_string( &operation->sitesPath );
 | 
			
		||||
    operation->sitesPath = mpw_path( operation->user->fullName, mpw_marshal_format_extension( operation->sitesFormat ) );
 | 
			
		||||
    dbg( "Updating: %s (%s)", operation->sitesPath, mpw_nameForFormat( operation->sitesFormat ) );
 | 
			
		||||
    operation->sitesPath = mpw_path( operation->user->fullName, extensions[0] );
 | 
			
		||||
    dbg( "Updating: %s (%s)", operation->sitesPath, mpw_format_name( operation->sitesFormat ) );
 | 
			
		||||
    free( extensions );
 | 
			
		||||
 | 
			
		||||
    FILE *sitesFile = NULL;
 | 
			
		||||
    if (!operation->sitesPath || !mpw_mkdirs( operation->sitesPath ) || !(sitesFile = fopen( operation->sitesPath, "w" ))) {
 | 
			
		||||
@@ -800,31 +815,48 @@ void cli_save(Arguments *args, Operation *operation) {
 | 
			
		||||
    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_currentKey = NULL;
 | 
			
		||||
static MPAlgorithmVersion __cli_masterKeyProvider_currentAlgorithm = (MPAlgorithmVersion)-1;
 | 
			
		||||
static const char *__cli_masterKeyProvider_currentPassword = NULL;
 | 
			
		||||
static Operation *__cli_masterKeyProvider_currentOperation = NULL;
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
    if (mpw_update_master_key( &__cli_masterKeyProvider_currentKey, &__cli_masterKeyProvider_currentAlgorithm,
 | 
			
		||||
            algorithm, fullName, __cli_masterKeyProvider_currentOperation->masterPassword ))
 | 
			
		||||
        return mpw_memdup( __cli_masterKeyProvider_currentKey, MPMasterKeySize );
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    if (mpw_update_master_key( &__cli_masterKeyProvider_currentKey, &__cli_masterKeyProvider_currentAlgorithm,
 | 
			
		||||
            algorithm, fullName, __cli_masterKeyProvider_currentPassword ))
 | 
			
		||||
        return mpw_memdup( __cli_masterKeyProvider_currentKey, MPMasterKeySize );
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_op(Operation *operation) {
 | 
			
		||||
 | 
			
		||||
    mpw_free_string( &__cli_masterKeyProvider_currentPassword );
 | 
			
		||||
    __cli_masterKeyProvider_currentOperation = operation;
 | 
			
		||||
    return __cli_masterKeyProvider_op;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_str(const char *masterPassword) {
 | 
			
		||||
    __cli_masterKeyProvider_currentPassword = masterPassword;
 | 
			
		||||
 | 
			
		||||
    mpw_free_string( &__cli_masterKeyProvider_currentPassword );
 | 
			
		||||
    __cli_masterKeyProvider_currentPassword = mpw_strdup( masterPassword );
 | 
			
		||||
    return __cli_masterKeyProvider_str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_masterKeyProvider_free() {
 | 
			
		||||
 | 
			
		||||
    mpw_free( &__cli_masterKeyProvider_currentKey, MPMasterKeySize );
 | 
			
		||||
    __cli_masterKeyProvider_currentAlgorithm = (MPAlgorithmVersion)-1;
 | 
			
		||||
    mpw_free_string( &__cli_masterKeyProvider_currentPassword );
 | 
			
		||||
    __cli_masterKeyProvider_currentOperation = NULL;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -181,7 +181,7 @@ static bool mpw_marshal_write_flat(
 | 
			
		||||
        if (!user->redacted) {
 | 
			
		||||
            // Clear Text
 | 
			
		||||
            mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
            if (!(masterKey = user->masterKeyProvider( user->algorithm, user->fullName ))) {
 | 
			
		||||
            if (!(masterKey = user->masterKeyProvider( site->algorithm, user->fullName ))) {
 | 
			
		||||
                *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
@@ -212,6 +212,7 @@ static bool mpw_marshal_write_flat(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if MPW_JSON
 | 
			
		||||
 | 
			
		||||
static bool mpw_marshal_write_json(
 | 
			
		||||
        char **out, const MPMarshalledUser *user, MPMarshalError *error) {
 | 
			
		||||
 | 
			
		||||
@@ -263,7 +264,7 @@ static bool mpw_marshal_write_json(
 | 
			
		||||
        if (!user->redacted) {
 | 
			
		||||
            // Clear Text
 | 
			
		||||
            mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
            if (!(masterKey = user->masterKeyProvider( user->algorithm, user->fullName ))) {
 | 
			
		||||
            if (!(masterKey = user->masterKeyProvider( site->algorithm, user->fullName ))) {
 | 
			
		||||
                *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
@@ -339,6 +340,7 @@ static bool mpw_marshal_write_json(
 | 
			
		||||
    *error = (MPMarshalError){ .type = MPMarshalSuccess };
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool mpw_marshal_write(
 | 
			
		||||
@@ -593,7 +595,7 @@ static MPMarshalledUser *mpw_marshal_read_flat(
 | 
			
		||||
            if (!user->redacted) {
 | 
			
		||||
                // Clear Text
 | 
			
		||||
                mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
                if (!(masterKey = masterKeyProvider( user->algorithm, user->fullName ))) {
 | 
			
		||||
                if (!(masterKey = masterKeyProvider( site->algorithm, user->fullName ))) {
 | 
			
		||||
                    *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
                    return NULL;
 | 
			
		||||
                }
 | 
			
		||||
@@ -632,6 +634,7 @@ static MPMarshalledUser *mpw_marshal_read_flat(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if MPW_JSON
 | 
			
		||||
 | 
			
		||||
static void mpw_marshal_read_json_info(
 | 
			
		||||
        const char *in, MPMarshalInfo *info) {
 | 
			
		||||
 | 
			
		||||
@@ -713,7 +716,7 @@ static MPMarshalledUser *mpw_marshal_read_json(
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorMissing, "Missing value for full name." };
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (!(masterKey = masterKeyProvider( user->algorithm, user->fullName ))) {
 | 
			
		||||
    if (!(masterKey = masterKeyProvider( algorithm, fullName ))) {
 | 
			
		||||
        *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
@@ -779,7 +782,7 @@ static MPMarshalledUser *mpw_marshal_read_json(
 | 
			
		||||
        if (!user->redacted) {
 | 
			
		||||
            // Clear Text
 | 
			
		||||
            mpw_free( &masterKey, MPMasterKeySize );
 | 
			
		||||
            if (!(masterKey = masterKeyProvider( user->algorithm, user->fullName ))) {
 | 
			
		||||
            if (!(masterKey = masterKeyProvider( site->algorithm, user->fullName ))) {
 | 
			
		||||
                *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." };
 | 
			
		||||
                return NULL;
 | 
			
		||||
            }
 | 
			
		||||
@@ -827,6 +830,7 @@ static MPMarshalledUser *mpw_marshal_read_json(
 | 
			
		||||
    *error = (MPMarshalError){ .type = MPMarshalSuccess };
 | 
			
		||||
    return user;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
MPMarshalInfo *mpw_marshal_read_info(
 | 
			
		||||
@@ -913,10 +917,41 @@ const char *mpw_marshal_format_extension(
 | 
			
		||||
        case MPMarshalFormatFlat:
 | 
			
		||||
            return "mpsites";
 | 
			
		||||
        case MPMarshalFormatJSON:
 | 
			
		||||
            return "mpsites.json";
 | 
			
		||||
            return "mpjson";
 | 
			
		||||
        default: {
 | 
			
		||||
            dbg( "Unknown format: %d", format );
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mpw_marshal_format_extensions(
 | 
			
		||||
        const MPMarshalFormat format, const char ***extensions) {
 | 
			
		||||
 | 
			
		||||
    int count = 0;
 | 
			
		||||
    switch (format) {
 | 
			
		||||
        case MPMarshalFormatNone: {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case MPMarshalFormatFlat: {
 | 
			
		||||
            const char *array[3] = { mpw_marshal_format_extension( format ), "mpsites.txt", "txt" };
 | 
			
		||||
            count = sizeof( array ) / sizeof( *array );
 | 
			
		||||
            *extensions = realloc( *extensions, count * sizeof( const char * ) );
 | 
			
		||||
            memcpy( *extensions, array, count * sizeof( const char * ) );
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case MPMarshalFormatJSON: {
 | 
			
		||||
            const char *array[3] = { mpw_marshal_format_extension( format ), "mpsites.json", "json" };
 | 
			
		||||
            count = sizeof( array ) / sizeof( *array );
 | 
			
		||||
            *extensions = realloc( *extensions, sizeof( array ) );
 | 
			
		||||
            memcpy( *extensions, array, sizeof( array ) );
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        default: {
 | 
			
		||||
            dbg( "Unknown format: %d", format );
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return count;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,8 @@ typedef mpw_enum( unsigned int, MPMarshalFormat ) {
 | 
			
		||||
#else
 | 
			
		||||
    MPMarshalFormatDefault = MPMarshalFormatFlat,
 | 
			
		||||
#endif
 | 
			
		||||
    MPMarshalFormatFirst = MPMarshalFormatFlat,
 | 
			
		||||
    MPMarshalFormatLast = MPMarshalFormatJSON,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef mpw_enum( unsigned int, MPMarshalErrorType ) {
 | 
			
		||||
@@ -162,5 +164,12 @@ const char *mpw_nameForFormat(
 | 
			
		||||
 */
 | 
			
		||||
const char *mpw_marshal_format_extension(
 | 
			
		||||
        const MPMarshalFormat format);
 | 
			
		||||
/**
 | 
			
		||||
 * @param extensions An array of filename extensions that are used for files of this format,
 | 
			
		||||
 *        the first being the currently preferred/output extension.  Free after use.
 | 
			
		||||
 * @return The amount of filename extensions returned in the array.
 | 
			
		||||
 */
 | 
			
		||||
int mpw_marshal_format_extensions(
 | 
			
		||||
        const MPMarshalFormat format, const char ***extensions);
 | 
			
		||||
 | 
			
		||||
#endif // _MPW_MARSHAL_H
 | 
			
		||||
 
 | 
			
		||||
@@ -490,17 +490,25 @@ const size_t mpw_utf8_strlen(const char *utf8String) {
 | 
			
		||||
    return charlen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *mpw_memdup(const void *src, size_t len) {
 | 
			
		||||
 | 
			
		||||
    if (!src)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    char *dst = malloc( len );
 | 
			
		||||
    if (dst)
 | 
			
		||||
        memcpy( dst, src, len );
 | 
			
		||||
 | 
			
		||||
    return dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *mpw_strdup(const char *src) {
 | 
			
		||||
 | 
			
		||||
    if (!src)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    size_t len = strlen( src );
 | 
			
		||||
    char *dst = malloc( len + 1 );
 | 
			
		||||
    memcpy( dst, src, len );
 | 
			
		||||
    dst[len] = '\0';
 | 
			
		||||
 | 
			
		||||
    return dst;
 | 
			
		||||
    return mpw_memdup( src, len + 1 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *mpw_strndup(const char *src, size_t max) {
 | 
			
		||||
 
 | 
			
		||||
@@ -223,6 +223,8 @@ bool mpw_id_buf_equals(const char *id1, const char *id2);
 | 
			
		||||
 | 
			
		||||
/** @return The amount of display characters in the given UTF-8 string. */
 | 
			
		||||
const size_t mpw_utf8_strlen(const char *utf8String);
 | 
			
		||||
/** Drop-in for memdup(3). */
 | 
			
		||||
void *mpw_memdup(const void *src, size_t len);
 | 
			
		||||
/** Drop-in for POSIX strdup(3). */
 | 
			
		||||
char *mpw_strdup(const char *src);
 | 
			
		||||
/** Drop-in for POSIX strndup(3). */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user