From a8949ca07e9c58f52137b87faa80d6d8b9a58850 Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Wed, 23 Aug 2017 00:01:23 -0400 Subject: [PATCH] NULL out free'ed references. --- core/c/mpw-algorithm_v0.c | 35 +++-- core/c/mpw-algorithm_v2.c | 5 +- core/c/mpw-algorithm_v3.c | 2 +- core/c/mpw-marshall-util.c | 5 +- core/c/mpw-marshall.c | 69 +++++----- core/c/mpw-marshall.h | 4 +- core/c/mpw-util.c | 54 ++++---- core/c/mpw-util.h | 35 +++-- platform-darwin/Source/MPAppDelegate_Store.m | 6 +- platform-darwin/Source/iOS/MPiOSAppDelegate.m | 2 +- platform-independent/cli-c/cli/mpw-cli.c | 122 +++++++++--------- platform-independent/cli-c/cli/mpw-tests.c | 4 +- 12 files changed, 171 insertions(+), 172 deletions(-) diff --git a/core/c/mpw-algorithm_v0.c b/core/c/mpw-algorithm_v0.c index cd2faa1c..79d21ff0 100644 --- a/core/c/mpw-algorithm_v0.c +++ b/core/c/mpw-algorithm_v0.c @@ -18,7 +18,6 @@ #include #include -#include #include "mpw-types.h" #include "mpw-util.h" @@ -71,7 +70,7 @@ static MPMasterKey mpw_masterKey_v0( // Calculate the master key. trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%lu, r=%u, p=%u )\n", MP_N, MP_r, MP_p ); MPMasterKey masterKey = mpw_kdf_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); - mpw_free( masterKeySalt, masterKeySaltSize ); + mpw_free( &masterKeySalt, masterKeySaltSize ); if (!masterKey) { err( "Could not allocate master key: %s\n", strerror( errno ) ); return NULL; @@ -104,9 +103,8 @@ static MPSiteKey mpw_siteKey_v0( mpw_push_int( &siteSalt, &siteSaltSize, htonl( mpw_utf8_strlen( keyContext ) ) ); mpw_push_string( &siteSalt, &siteSaltSize, keyContext ); } - if (!siteSalt || !siteSaltSize) { + if (!siteSalt) { err( "Could not allocate site salt: %s\n", strerror( errno ) ); - mpw_free( siteSalt, siteSaltSize ); return NULL; } trc( " => siteSalt.id: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) ); @@ -114,7 +112,7 @@ static MPSiteKey mpw_siteKey_v0( trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n", mpw_id_buf( masterKey, MPMasterKeySize ) ); MPSiteKey siteKey = mpw_hash_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); - mpw_free( siteSalt, siteSaltSize ); + mpw_free( &siteSalt, siteSaltSize ); if (!siteKey) { err( "Could not derive site key: %s\n", strerror( errno ) ); return NULL; @@ -163,19 +161,19 @@ static const char *mpw_sitePasswordFromCrypt_v0( size_t bufSize = (size_t)mpw_base64_decode( cipherBuf, cipherText ); if ((int)bufSize < 0) { err( "Base64 decoding error." ); - mpw_free( cipherBuf, mpw_base64_decode_max( cipherText ) ); + mpw_free( &cipherBuf, mpw_base64_decode_max( cipherText ) ); return NULL; } trc( "b64 decoded: %zu bytes = %s\n", bufSize, mpw_hex( cipherBuf, bufSize ) ); // Decrypt const uint8_t *plainBytes = mpw_aes_decrypt( masterKey, MPMasterKeySize, cipherBuf, bufSize ); + mpw_free( &cipherBuf, bufSize ); const char *plainText = strndup( (char *)plainBytes, bufSize ); - mpw_free( plainBytes, bufSize ); + mpw_free( &plainBytes, bufSize ); if (!plainText) err( "AES decryption error: %s\n", strerror( errno ) ); trc( "decrypted -> plainText: %s = %s\n", plainText, mpw_hex( plainText, sizeof( plainText ) ) ); - mpw_free( cipherBuf, bufSize ); return plainText; } @@ -206,15 +204,16 @@ static const char *mpw_sitePasswordFromDerive_v0( // Base64-encode size_t b64Max = mpw_base64_encode_max( keySize ); - char *sitePassword = calloc( 1, b64Max + 1 ); - if (mpw_base64_encode( sitePassword, resultKey, keySize ) < 0) { + char *b64Key = calloc( 1, b64Max + 1 ); + if (mpw_base64_encode( b64Key, resultKey, keySize ) < 0) { err( "Base64 encoding error." ); - mpw_free_string( sitePassword ); - sitePassword = NULL; + mpw_free_string( &b64Key ); } - trc( "b64 encoded -> key.id: %s\n", mpw_id_buf( sitePassword, strlen( sitePassword ) ) ); + else + trc( "b64 encoded -> key.id: %s\n", mpw_id_buf( b64Key, strlen( b64Key ) ) ); + mpw_free( &resultKey, keySize ); - return sitePassword; + return b64Key; } default: err( "Unsupported derived password type: %d\n", resultType ); @@ -239,11 +238,11 @@ static const char *mpw_siteState_v0( char *cipherText = calloc( 1, b64Max + 1 ); if (mpw_base64_encode( cipherText, cipherBuf, bufSize ) < 0) { err( "Base64 encoding error." ); - mpw_free_string( cipherText ); - cipherText = NULL; + mpw_free_string( &cipherText ); } - trc( "b64 encoded -> cipherText: %s = %s\n", cipherText, mpw_hex( cipherText, sizeof( cipherText ) ) ); - mpw_free( cipherBuf, bufSize ); + else + trc( "b64 encoded -> cipherText: %s = %s\n", cipherText, mpw_hex( cipherText, sizeof( cipherText ) ) ); + mpw_free( &cipherBuf, bufSize ); return cipherText; } diff --git a/core/c/mpw-algorithm_v2.c b/core/c/mpw-algorithm_v2.c index 574541cc..f6d875a6 100644 --- a/core/c/mpw-algorithm_v2.c +++ b/core/c/mpw-algorithm_v2.c @@ -69,9 +69,8 @@ static MPSiteKey mpw_siteKey_v2( mpw_push_int( &siteSalt, &siteSaltSize, htonl( strlen( keyContext ) ) ); mpw_push_string( &siteSalt, &siteSaltSize, keyContext ); } - if (!siteSalt || !siteSaltSize) { + if (!siteSalt) { err( "Could not allocate site salt: %s\n", strerror( errno ) ); - mpw_free( siteSalt, siteSaltSize ); return NULL; } trc( " => siteSalt.id: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) ); @@ -79,7 +78,7 @@ static MPSiteKey mpw_siteKey_v2( trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n", mpw_id_buf( masterKey, MPMasterKeySize ) ); MPSiteKey siteKey = mpw_hash_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); - mpw_free( siteSalt, siteSaltSize ); + mpw_free( &siteSalt, siteSaltSize ); if (!siteKey) { err( "Could not allocate site key: %s\n", strerror( errno ) ); return NULL; diff --git a/core/c/mpw-algorithm_v3.c b/core/c/mpw-algorithm_v3.c index a033fa3d..1afbe5d8 100644 --- a/core/c/mpw-algorithm_v3.c +++ b/core/c/mpw-algorithm_v3.c @@ -64,7 +64,7 @@ static MPMasterKey mpw_masterKey_v3( // Calculate the master key. trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%lu, r=%u, p=%u )\n", MP_N, MP_r, MP_p ); MPMasterKey masterKey = mpw_kdf_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); - mpw_free( masterKeySalt, masterKeySaltSize ); + mpw_free( &masterKeySalt, masterKeySaltSize ); if (!masterKey) { err( "Could not allocate master key: %s\n", strerror( errno ) ); return NULL; diff --git a/core/c/mpw-marshall-util.c b/core/c/mpw-marshall-util.c index 100592ee..60485158 100644 --- a/core/c/mpw-marshall-util.c +++ b/core/c/mpw-marshall-util.c @@ -100,10 +100,9 @@ bool mpw_update_masterKey(MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyA const char *fullName, const char *masterPassword) { if (*masterKeyAlgorithm != targetKeyAlgorithm) { - mpw_free( *masterKey, MPMasterKeySize ); + mpw_free( masterKey, MPMasterKeySize ); *masterKeyAlgorithm = targetKeyAlgorithm; - *masterKey = mpw_masterKey( - fullName, masterPassword, *masterKeyAlgorithm ); + *masterKey = mpw_masterKey( fullName, masterPassword, *masterKeyAlgorithm ); if (!*masterKey) { err( "Couldn't derive master key for user %s, algorithm %d.\n", fullName, *masterKeyAlgorithm ); return false; diff --git a/core/c/mpw-marshall.c b/core/c/mpw-marshall.c index cef5bcef..ce3acbdb 100644 --- a/core/c/mpw-marshall.c +++ b/core/c/mpw-marshall.c @@ -94,42 +94,39 @@ MPMarshalledQuestion *mpw_marshal_question( } bool mpw_marshal_info_free( - MPMarshallInfo *info) { + MPMarshallInfo **info) { - if (!info) + if (!info || !*info) return true; bool success = true; - success &= mpw_free_string( info->fullName ); - success &= mpw_free_string( info->keyID ); + success &= mpw_free_strings( &(*info)->fullName, &(*info)->keyID, NULL ); success &= mpw_free( info, sizeof( MPMarshallInfo ) ); return success; } bool mpw_marshal_free( - MPMarshalledUser *user) { + MPMarshalledUser **user) { if (!user) return true; bool success = true; - for (size_t s = 0; s < user->sites_count; ++s) { - MPMarshalledSite *site = &user->sites[s]; - success &= mpw_free_string( site->name ); - success &= mpw_free_string( site->content ); - success &= mpw_free_string( site->loginContent ); - success &= mpw_free_string( site->url ); + success &= mpw_free_strings( &(*user)->fullName, &(*user)->masterPassword, NULL ); + + for (size_t s = 0; s < (*user)->sites_count; ++s) { + MPMarshalledSite *site = &(*user)->sites[s]; + success &= mpw_free_strings( &site->name, &site->content, &site->loginContent, &site->url, NULL ); + for (size_t q = 0; q < site->questions_count; ++q) { MPMarshalledQuestion *question = &site->questions[q]; - success &= mpw_free_string( question->keyword ); - success &= mpw_free_string( question->content ); + success &= mpw_free_strings( &question->keyword, &question->content, NULL ); } - success &= mpw_free( site->questions, sizeof( MPMarshalledQuestion ) * site->questions_count ); + success &= mpw_free( &site->questions, sizeof( MPMarshalledQuestion ) * site->questions_count ); } - success &= mpw_free( user->sites, sizeof( MPMarshalledSite ) * user->sites_count ); - success &= mpw_free_string( user->fullName ); - success &= mpw_free_string( user->masterPassword ); + + success &= mpw_free( &(*user)->sites, sizeof( MPMarshalledSite ) * (*user)->sites_count ); success &= mpw_free( user, sizeof( MPMarshalledUser ) ); return success; @@ -210,10 +207,9 @@ static bool mpw_marshall_write_flat( mpw_string_pushf( out, "%s %8ld %lu:%lu:%lu %25s\t%25s\t%s\n", dateString, (long)site->uses, (long)site->type, (long)site->algorithm, (long)site->counter, loginContent?: "", site->name, content?: "" ); - mpw_free_string( content ); - mpw_free_string( loginContent ); + mpw_free_strings( &content, &loginContent, NULL ); } - mpw_free( masterKey, MPMasterKeySize ); + mpw_free( &masterKey, MPMasterKeySize ); *error = (MPMarshallError){ .type = MPMarshallSuccess }; return true; @@ -336,11 +332,11 @@ static bool mpw_marshall_write_json( if (site->url) json_object_object_add( json_site_mpw, "url", json_object_new_string( site->url ) ); - mpw_free_string( content ); + mpw_free_strings( &content, &loginContent ); } mpw_string_pushf( out, "%s\n", json_object_to_json_string_ext( json_file, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED ) ); - mpw_free( masterKey, MPMasterKeySize ); + mpw_free( &masterKey, MPMasterKeySize ); json_object_put( json_file ); *error = (MPMarshallError){ .type = MPMarshallSuccess }; @@ -405,8 +401,7 @@ static void mpw_marshall_read_flat_info( if (strcmp( headerName, "Date" ) == 0) info->date = mpw_mktime( headerValue ); - mpw_free_string( headerName ); - mpw_free_string( headerValue ); + mpw_free_strings( &headerName, &headerValue, NULL ); continue; } } @@ -488,8 +483,7 @@ static MPMarshalledUser *mpw_marshall_read_flat( if (strcmp( headerName, "Passwords" ) == 0) importRedacted = strcmp( headerValue, "VISIBLE" ) != 0; - mpw_free_string( headerName ); - mpw_free_string( headerValue ); + mpw_free_strings( &headerName, &headerValue, NULL ); continue; } if (!headerEnded) @@ -531,7 +525,7 @@ static MPMarshalledUser *mpw_marshall_read_flat( if (typeAndVersion) { str_type = strdup( strtok( typeAndVersion, ":" ) ); str_algorithm = strdup( strtok( NULL, "" ) ); - mpw_free_string( typeAndVersion ); + mpw_free_string( &typeAndVersion ); } str_counter = strdup( "1" ); siteLoginName = NULL; @@ -547,7 +541,7 @@ static MPMarshalledUser *mpw_marshall_read_flat( str_type = strdup( strtok( typeAndVersionAndCounter, ":" ) ); str_algorithm = strdup( strtok( NULL, ":" ) ); str_counter = strdup( strtok( NULL, "" ) ); - mpw_free_string( typeAndVersionAndCounter ); + mpw_free_string( &typeAndVersionAndCounter ); } siteLoginName = mpw_get_token( &positionInLine, endOfLine, "\t\n" ); siteName = mpw_get_token( &positionInLine, endOfLine, "\t\n" ); @@ -606,6 +600,7 @@ static MPMarshalledUser *mpw_marshall_read_flat( if (siteLoginName && strlen( siteLoginName )) site->loginContent = mpw_siteState( masterKey, site->name, MPCounterValueInitial, MPKeyPurposeIdentification, NULL, site->loginType, siteLoginName, site->algorithm ); + dbg( "site->content: %p\n", (void *)site->content ); } else { // Redacted @@ -613,6 +608,7 @@ static MPMarshalledUser *mpw_marshall_read_flat( site->content = strdup( siteContent ); if (siteLoginName && strlen( siteLoginName )) site->loginContent = strdup( siteLoginName ); + dbg( "site->content: %p\n", (void *)site->content ); } } else { @@ -623,18 +619,11 @@ static MPMarshalledUser *mpw_marshall_read_flat( return NULL; } - mpw_free_string( str_lastUsed ); - mpw_free_string( str_uses ); - mpw_free_string( str_type ); - mpw_free_string( str_algorithm ); - mpw_free_string( str_counter ); - mpw_free_string( siteLoginName ); - mpw_free_string( siteName ); - mpw_free_string( siteContent ); + mpw_free_strings( &str_lastUsed, &str_uses, &str_type, &str_algorithm, &str_counter, NULL ); + mpw_free_strings( &siteLoginName, &siteName, &siteContent, NULL ); } - mpw_free_string( fullName ); - mpw_free_string( keyID ); - mpw_free( masterKey, MPMasterKeySize ); + mpw_free_strings( &fullName, &keyID, NULL ); + mpw_free( &masterKey, MPMasterKeySize ); *error = (MPMarshallError){ .type = MPMarshallSuccess }; return user; @@ -796,6 +785,7 @@ static MPMarshalledUser *mpw_marshall_read_json( if (siteLoginName && strlen( siteLoginName )) site->loginContent = mpw_siteState( masterKey, site->name, MPCounterValueInitial, MPKeyPurposeIdentification, NULL, site->loginType, siteLoginName, site->algorithm ); + dbg( "site->content: %p\n", (void *)site->content ); } else { // Redacted @@ -803,6 +793,7 @@ static MPMarshalledUser *mpw_marshall_read_json( site->content = strdup( siteContent ); if (siteLoginName && strlen( siteLoginName )) site->loginContent = strdup( siteLoginName ); + dbg( "site->content: %p\n", (void *)site->content ); } json_object_iter json_site_question; diff --git a/core/c/mpw-marshall.h b/core/c/mpw-marshall.h index 6de5369d..1aaf23e1 100644 --- a/core/c/mpw-marshall.h +++ b/core/c/mpw-marshall.h @@ -130,9 +130,9 @@ MPMarshalledQuestion *mpw_marshal_question( MPMarshalledSite *site, const char *keyword); /** Free the given user object and all associated data. */ bool mpw_marshal_info_free( - MPMarshallInfo *info); + MPMarshallInfo **info); bool mpw_marshal_free( - MPMarshalledUser *user); + MPMarshalledUser **user); //// Format. diff --git a/core/c/mpw-util.c b/core/c/mpw-util.c index ea714f4c..f67f746c 100644 --- a/core/c/mpw-util.c +++ b/core/c/mpw-util.c @@ -39,7 +39,7 @@ int mpw_verbosity = inf_level; #endif -bool mpw_push_buf(uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize) { +bool mpw_push_buf(uint8_t **buffer, size_t *bufferSize, const void *pushBuffer, const size_t pushSize) { if (!buffer || !bufferSize || !pushBuffer || !pushSize) return false; @@ -49,9 +49,8 @@ bool mpw_push_buf(uint8_t **const buffer, size_t *const bufferSize, const void * if (!mpw_realloc( buffer, bufferSize, pushSize )) { // realloc failed, we can't push. Mark the buffer as broken. - mpw_free( *buffer, *bufferSize ); + mpw_free( buffer, *bufferSize ); *bufferSize = (size_t)ERR; - *buffer = NULL; return false; } @@ -60,12 +59,12 @@ bool mpw_push_buf(uint8_t **const buffer, size_t *const bufferSize, const void * return true; } -bool mpw_push_string(uint8_t **const buffer, size_t *const bufferSize, const char *pushString) { +bool mpw_push_string(uint8_t **buffer, size_t *bufferSize, const char *pushString) { return pushString && mpw_push_buf( buffer, bufferSize, pushString, strlen( pushString ) ); } -bool mpw_string_push(char **const string, const char *pushString) { +bool mpw_string_push(char **string, const char *pushString) { if (!*string) *string = calloc( 1, sizeof( char ) ); @@ -74,29 +73,29 @@ bool mpw_string_push(char **const string, const char *pushString) { return pushString && mpw_push_buf( (uint8_t **const)string, &stringLength, pushString, strlen( pushString ) + 1 ); } -bool mpw_string_pushf(char **const string, const char *pushFormat, ...) { +bool mpw_string_pushf(char **string, const char *pushFormat, ...) { va_list args; va_start( args, pushFormat ); char *pushString = NULL; bool success = vasprintf( &pushString, pushFormat, args ) >= 0 && mpw_string_push( string, pushString ); va_end( args ); - mpw_free_string( pushString ); + mpw_free_string( &pushString ); return success; } -bool mpw_push_int(uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt) { +bool mpw_push_int(uint8_t **buffer, size_t *bufferSize, const uint32_t pushInt) { return mpw_push_buf( buffer, bufferSize, &pushInt, sizeof( pushInt ) ); } -bool __mpw_realloc(void **buffer, size_t *bufferSize, const size_t deltaSize) { +bool __mpw_realloc(const void **buffer, size_t *bufferSize, const size_t deltaSize) { if (!buffer) return false; - void *newBuffer = realloc( *buffer, (bufferSize? *bufferSize: 0) + deltaSize ); + void *newBuffer = realloc( (void *)*buffer, (bufferSize? *bufferSize: 0) + deltaSize ); if (!newBuffer) return false; @@ -107,24 +106,31 @@ bool __mpw_realloc(void **buffer, size_t *bufferSize, const size_t deltaSize) { return true; } -bool mpw_free(const void *buffer, const size_t bufferSize) { +bool __mpw_free(const void **buffer, const size_t bufferSize) { - if (!buffer) + if (!buffer || !*buffer) return false; - memset( (void *)buffer, 0, bufferSize ); - free( (void *)buffer ); + memset( (void *)*buffer, 0, bufferSize ); + free( (void *)*buffer ); + *buffer = NULL; + return true; } -bool mpw_free_string(const char *strings, ...) { +bool __mpw_free_string(const char **string) { + + return *string && __mpw_free( (const void **)string, strlen( *string ) ); +} + +bool __mpw_free_strings(const char **strings, ...) { bool success = true; va_list args; va_start( args, strings ); - const char *string = va_arg( args, const char * ); - success &= string && mpw_free( string, strlen( string ) ); + for (const char **string; (string = va_arg( args, const char ** ));) + success &= mpw_free_string( string ); va_end( args ); return success; @@ -142,12 +148,12 @@ uint8_t const *mpw_kdf_scrypt(const size_t keySize, const char *secret, const ui #if HAS_CPERCIVA if (crypto_scrypt( (const uint8_t *)secret, strlen( secret ), salt, saltSize, N, r, p, key, keySize ) < 0) { - mpw_free( key, keySize ); + mpw_free( &key, keySize ); return NULL; } #elif HAS_SODIUM if (crypto_pwhash_scryptsalsa208sha256_ll( (const uint8_t *)secret, strlen( secret ), salt, saltSize, N, r, p, key, keySize ) != 0) { - mpw_free( key, keySize ); + mpw_free( &key, keySize ); return NULL; } #else @@ -192,7 +198,7 @@ uint8_t const *mpw_kdf_blake2b(const size_t subkeySize, const uint8_t *key, cons memcpy( personalBuf, personal, strlen( personal ) ); if (crypto_generichash_blake2b_salt_personal( subkey, subkeySize, context, contextSize, key, keySize, saltBuf, personalBuf ) != 0) { - mpw_free( subkey, subkeySize ); + mpw_free( &subkey, subkeySize ); return NULL; } #else @@ -222,7 +228,7 @@ uint8_t const *mpw_hash_hmac_sha256(const uint8_t *key, const size_t keySize, co if (crypto_auth_hmacsha256_init( &state, key, keySize ) != 0 || crypto_auth_hmacsha256_update( &state, message, messageSize ) != 0 || crypto_auth_hmacsha256_final( &state, mac ) != 0) { - mpw_free( mac, crypto_auth_hmacsha256_BYTES ); + mpw_free( &mac, crypto_auth_hmacsha256_BYTES ); return NULL; } #else @@ -248,7 +254,7 @@ static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t key if (encrypt) { uint8_t *const cipherBuf = malloc( bufSize ); if (crypto_stream_aes128ctr_xor( cipherBuf, buf, bufSize, nonce, key ) != 0) { - mpw_free( cipherBuf, bufSize ); + mpw_free( &cipherBuf, bufSize ); return NULL; } return cipherBuf; @@ -256,7 +262,7 @@ static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t key else { uint8_t *const plainBuf = malloc( bufSize ); if (crypto_stream_aes128ctr( plainBuf, bufSize, nonce, key ) != 0) { - mpw_free( plainBuf, bufSize ); + mpw_free( &plainBuf, bufSize ); return NULL; } for (size_t c = 0; c < bufSize; ++c) @@ -415,7 +421,7 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) { accessory[identiconSeed[3] % (sizeof( accessory ) / sizeof( accessory[0] ))], resetString ); - mpw_free( identiconSeed, 32 ); + mpw_free( &identiconSeed, 32 ); free( colorString ); free( resetString ); return identicon; diff --git a/core/c/mpw-util.h b/core/c/mpw-util.h index da101d6d..9f7d1cd6 100644 --- a/core/c/mpw-util.h +++ b/core/c/mpw-util.h @@ -106,18 +106,18 @@ extern int mpw_verbosity; /** Push a buffer onto a buffer. reallocs the given buffer and appends the given buffer. */ bool mpw_push_buf( - uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize); + uint8_t ** buffer, size_t *bufferSize, const void *pushBuffer, const size_t pushSize); /** Push a string onto a buffer. reallocs the given buffer and appends the given string. */ bool mpw_push_string( - uint8_t **buffer, size_t *const bufferSize, const char *pushString); + uint8_t **buffer, size_t *bufferSize, const char *pushString); /** Push a string onto another string. reallocs the target string and appends the source string. */ bool mpw_string_push( - char **const string, const char *pushString); + char **string, const char *pushString); bool mpw_string_pushf( - char **const string, const char *pushFormat, ...); + char **string, const char *pushFormat, ...); /** Push an integer onto a buffer. reallocs the given buffer and appends the given integer. */ bool mpw_push_int( - uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt); + uint8_t **buffer, size_t *bufferSize, const uint32_t pushInt); /** 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. @@ -128,14 +128,23 @@ bool mpw_push_int( * @return true if successful, false if reallocation failed. */ #define mpw_realloc(buffer, bufferSize, deltaSize) \ - __mpw_realloc( (void **)buffer, bufferSize, deltaSize ) -bool __mpw_realloc(void **buffer, size_t *bufferSize, const size_t deltaSize); -/** Free a buffer after zero'ing its contents. */ -bool mpw_free( - const void *buffer, const size_t bufferSize); -/** Free a string after zero'ing its contents. */ -bool mpw_free_string( - const char *strings, ...); + ({ typeof(buffer) _b = buffer; const void *__b = *_b; __mpw_realloc( (const void **)_b, bufferSize, deltaSize ); }) +bool __mpw_realloc(const void **buffer, size_t *bufferSize, const size_t deltaSize); +/** Free a buffer after zero'ing its contents, then set the reference to NULL. */ +#define mpw_free(buffer, bufferSize) \ + ({ typeof(buffer) _b = buffer; const void *__b = *_b; __mpw_free((const void **)_b, bufferSize); }) +bool __mpw_free( + const void **buffer, const size_t bufferSize); +/** Free a string after zero'ing its contents, then set the reference to NULL. */ +#define mpw_free_string(string) \ + ({ typeof(string) _s = string; const char *__s = *_s; __mpw_free_string((const char **)_s); }) +bool __mpw_free_string( + const char **string); +/** Free strings after zero'ing their contents, then set the references to NULL. Terminate the va_list with NULL. */ +#define mpw_free_strings(strings, ...) \ + ({ typeof(strings) _s = strings; const char *__s = *_s; __mpw_free_strings((const char **)strings, __VA_ARGS__); }) +bool __mpw_free_strings( + const char **strings, ...); //// Cryptographic functions. diff --git a/platform-darwin/Source/MPAppDelegate_Store.m b/platform-darwin/Source/MPAppDelegate_Store.m index c15240cc..375c8726 100644 --- a/platform-darwin/Source/MPAppDelegate_Store.m +++ b/platform-darwin/Source/MPAppDelegate_Store.m @@ -580,7 +580,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); importMasterPassword = askImportPassword( @(info->fullName) ); if (!importMasterPassword) { inf( @"Import cancelled." ); - mpw_marshal_info_free( info ); + mpw_marshal_info_free( &info ); return MPError( ([NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]), @"" ); } @@ -591,7 +591,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); // Parse import data. MPMarshallError importError = { .type = MPMarshallSuccess }; MPMarshalledUser *importUser = mpw_marshall_read( importData.UTF8String, info->format, importMasterPassword.UTF8String, &importError ); - mpw_marshal_info_free( info ); + mpw_marshal_info_free( &info ); @try { if (!importUser || importError.type != MPMarshallSuccess) @@ -677,7 +677,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); return nil; } @finally { - mpw_marshal_free( importUser ); + mpw_marshal_free( &importUser ); } } diff --git a/platform-darwin/Source/iOS/MPiOSAppDelegate.m b/platform-darwin/Source/iOS/MPiOSAppDelegate.m index 057e5267..07a4cc8a 100644 --- a/platform-darwin/Source/iOS/MPiOSAppDelegate.m +++ b/platform-darwin/Source/iOS/MPiOSAppDelegate.m @@ -248,7 +248,7 @@ [self importSites:importData]; [UIPasteboard generalPasteboard].string = @""; } cancelTitle:@"No" otherTitles:@"Import Sites", nil]; - mpw_marshal_info_free( importInfo ); + mpw_marshal_info_free( &importInfo ); } ); [super applicationDidBecomeActive:application]; diff --git a/platform-independent/cli-c/cli/mpw-cli.c b/platform-independent/cli-c/cli/mpw-cli.c index 43842530..dabfbfc4 100644 --- a/platform-independent/cli-c/cli/mpw-cli.c +++ b/platform-independent/cli-c/cli/mpw-cli.c @@ -242,7 +242,7 @@ int main(int argc, char *const argv[]) { ftl( "Unexpected option: %c\n", opt ); return EX_USAGE; } - if (optind < argc) + if (optind < argc && argv[optind]) siteNameArg = strdup( argv[optind] ); // Determine fullName, siteName & masterPassword. @@ -250,7 +250,7 @@ int main(int argc, char *const argv[]) { if (!(fullNameArg && (fullName = strdup( fullNameArg ))) && !(fullName = mpw_getline( "Your full name:" ))) { ftl( "Missing full name.\n" ); - mpw_free_string( fullName, masterPassword, siteName ); + mpw_free_strings( &fullName, &masterPassword, &siteName, NULL ); return EX_DATAERR; } if (!(masterPasswordArg && (masterPassword = strdup( masterPasswordArg )))) @@ -259,7 +259,7 @@ int main(int argc, char *const argv[]) { if (!(siteNameArg && (siteName = strdup( siteNameArg ))) && !(siteName = mpw_getline( "Site name:" ))) { ftl( "Missing site name.\n" ); - mpw_free_string( fullName, masterPassword, siteName ); + mpw_free_strings( &fullName, &masterPassword, &siteName, NULL ); return EX_DATAERR; } MPMarshallFormat sitesFormat = MPMarshallFormatDefault; @@ -267,7 +267,7 @@ int main(int argc, char *const argv[]) { sitesFormat = mpw_formatWithName( sitesFormatArg ); if (ERR == (int)sitesFormat) { ftl( "Invalid sites format: %s\n", sitesFormatArg ); - mpw_free_string( fullName, masterPassword, siteName ); + mpw_free_strings( &fullName, &masterPassword, &siteName, NULL ); return EX_USAGE; } } @@ -280,7 +280,7 @@ int main(int argc, char *const argv[]) { // Try to fall back to the flat format. if (!sitesFormatFixed) { - mpw_free_string( sitesPath ); + mpw_free_string( &sitesPath ); sitesPath = mpw_path( fullName, mpw_marshall_format_extension( MPMarshallFormatFlat ) ); if (sitesPath && (sitesFile = fopen( sitesPath, "r" ))) sitesFormat = MPMarshallFormatFlat; @@ -293,10 +293,9 @@ int main(int argc, char *const argv[]) { MPMarshalledUser *user = NULL; MPMarshalledSite *site = NULL; MPMarshalledQuestion *question = NULL; - if (!sitesFile) { - mpw_free_string( sitesPath ); - sitesPath = NULL; - } + if (!sitesFile) + mpw_free_string( &sitesPath ); + else { // Read file. size_t blockSize = 4096, bufSize = 0, bufOffset = 0, readSize = 0; @@ -312,15 +311,15 @@ int main(int argc, char *const argv[]) { MPMarshallInfo *sitesInputInfo = mpw_marshall_read_info( sitesInputData ); MPMarshallFormat sitesInputFormat = sitesFormatArg? sitesFormat: sitesInputInfo->format; MPMarshallError marshallError = { .type = MPMarshallSuccess }; - mpw_marshal_info_free( sitesInputInfo ); + mpw_marshal_info_free( &sitesInputInfo ); user = mpw_marshall_read( sitesInputData, sitesInputFormat, masterPassword, &marshallError ); if (marshallError.type == MPMarshallErrorMasterPassword) { // Incorrect master password. if (!allowPasswordUpdate) { ftl( "Incorrect master password according to configuration:\n %s: %s\n", sitesPath, marshallError.description ); - mpw_marshal_free( user ); - mpw_free( sitesInputData, bufSize ); - mpw_free_string( sitesPath, fullName, masterPassword, siteName ); + mpw_marshal_free( &user ); + mpw_free( &sitesInputData, bufSize ); + mpw_free_strings( &sitesPath, &fullName, &masterPassword, &siteName, NULL ); return EX_DATAERR; } @@ -333,27 +332,25 @@ int main(int argc, char *const argv[]) { while (!importMasterPassword || !strlen( importMasterPassword )) importMasterPassword = mpw_getpass( "Old master password: " ); - mpw_marshal_free( user ); + mpw_marshal_free( &user ); user = mpw_marshall_read( sitesInputData, sitesInputFormat, importMasterPassword, &marshallError ); - mpw_free_string( importMasterPassword ); + mpw_free_string( &importMasterPassword ); } if (user) { - mpw_free_string( user->masterPassword ); + mpw_free_string( &user->masterPassword ); user->masterPassword = strdup( masterPassword ); } } - mpw_free( sitesInputData, bufSize ); + mpw_free( &sitesInputData, bufSize ); if (!user || marshallError.type != MPMarshallSuccess) { err( "Couldn't parse configuration file:\n %s: %s\n", sitesPath, marshallError.description ); - mpw_marshal_free( user ); - user = NULL; - mpw_free_string( sitesPath ); - sitesPath = NULL; + mpw_marshal_free( &user ); + mpw_free_string( &sitesPath ); } } if (!user) user = mpw_marshall_user( fullName, masterPassword, MPAlgorithmVersionCurrent ); - mpw_free_string( fullName, masterPassword ); + mpw_free_strings( &fullName, &masterPassword, NULL ); // Load the site object. for (size_t s = 0; s < user->sites_count; ++s) { @@ -366,7 +363,7 @@ int main(int argc, char *const argv[]) { } if (!site) site = mpw_marshall_site( user, siteName, MPResultTypeDefault, MPCounterValueDefault, user->algorithm ); - mpw_free_string( siteName ); + mpw_free_string( &siteName ); // Load the purpose and context / question object. MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication; @@ -374,8 +371,8 @@ int main(int argc, char *const argv[]) { keyPurpose = mpw_purposeWithName( keyPurposeArg ); if (ERR == (int)keyPurpose) { ftl( "Invalid purpose: %s\n", keyPurposeArg ); - mpw_marshal_free( user ); - mpw_free_string( sitesPath ); + mpw_marshal_free( &user ); + mpw_free_string( &sitesPath ); return EX_USAGE; } } @@ -413,23 +410,23 @@ int main(int argc, char *const argv[]) { case MPKeyPurposeAuthentication: { purposeResult = "password"; resultType = site->type; - resultState = strdup( site->content ); + resultState = site->content? strdup( site->content ): NULL; siteCounter = site->counter; break; } case MPKeyPurposeIdentification: { purposeResult = "login"; resultType = site->loginType; - resultState = strdup( site->loginContent ); + resultState = site->loginContent? strdup( site->loginContent ): NULL; siteCounter = MPCounterValueInitial; break; } case MPKeyPurposeRecovery: { - mpw_free_string( keyContext ); + mpw_free_string( &keyContext ); purposeResult = "answer"; - keyContext = strdup( question->keyword ); + keyContext = question->keyword? strdup( question->keyword ): NULL; resultType = question->type; - resultState = strdup( question->content ); + resultState = question->content? strdup( question->content ): NULL; siteCounter = MPCounterValueInitial; break; } @@ -440,8 +437,8 @@ int main(int argc, char *const argv[]) { resultType = mpw_typeWithName( resultTypeArg ); if (ERR == (int)resultType) { ftl( "Invalid type: %s\n", resultTypeArg ); - mpw_marshal_free( user ); - mpw_free_string( sitesPath, resultState, keyContext ); + mpw_marshal_free( &user ); + mpw_free_strings( &sitesPath, &resultState, &keyContext, NULL ); return EX_USAGE; } @@ -463,8 +460,8 @@ int main(int argc, char *const argv[]) { long long int siteCounterInt = atoll( siteCounterArg ); if (siteCounterInt < MPCounterValueFirst || siteCounterInt > MPCounterValueLast) { ftl( "Invalid site counter: %s\n", siteCounterArg ); - mpw_marshal_free( user ); - mpw_free_string( sitesPath, resultState, keyContext ); + mpw_marshal_free( &user ); + mpw_free_strings( &sitesPath, &resultState, &keyContext, NULL ); return EX_USAGE; } @@ -485,8 +482,8 @@ int main(int argc, char *const argv[]) { int algorithmVersionInt = atoi( algorithmVersionArg ); if (algorithmVersionInt < MPAlgorithmVersionFirst || algorithmVersionInt > MPAlgorithmVersionLast) { ftl( "Invalid algorithm version: %s\n", algorithmVersionArg ); - mpw_marshal_free( user ); - mpw_free_string( sitesPath, resultState, keyContext, resultParam ); + mpw_marshal_free( &user ); + mpw_free_strings( &sitesPath, &resultState, &keyContext, &resultParam, NULL ); return EX_USAGE; } site->algorithm = (MPAlgorithmVersion)algorithmVersionInt; @@ -495,9 +492,9 @@ int main(int argc, char *const argv[]) { user->redacted = strcmp( sitesRedactedArg, "1" ) == 0; else if (!user->redacted) wrn( "Sites configuration is not redacted. Use -R 1 to change this.\n" ); - mpw_free_string( fullNameArg, masterPasswordArg, siteNameArg ); - mpw_free_string( resultTypeArg, resultParamArg, siteCounterArg, algorithmVersionArg); - mpw_free_string( keyPurposeArg, keyContextArg, sitesFormatArg, sitesRedactedArg ); + mpw_free_strings( &fullNameArg, &masterPasswordArg, &siteNameArg, NULL ); + mpw_free_strings( &resultTypeArg, &resultParamArg, &siteCounterArg, &algorithmVersionArg, NULL ); + mpw_free_strings( &keyPurposeArg, &keyContextArg, &sitesFormatArg, &sitesRedactedArg, NULL ); // Operation summary. const char *identicon = mpw_identicon( user->fullName, user->masterPassword ); @@ -518,75 +515,74 @@ int main(int argc, char *const argv[]) { dbg( "algorithmVersion : %u\n", site->algorithm ); dbg( "-----------------\n\n" ); inf( "%s's %s for %s:\n[ %s ]: ", user->fullName, purposeResult, site->name, identicon ); - mpw_free_string( identicon, sitesPath ); + mpw_free_strings( &identicon, &sitesPath, NULL ); // Determine master key. MPMasterKey masterKey = mpw_masterKey( user->fullName, user->masterPassword, site->algorithm ); if (!masterKey) { ftl( "Couldn't derive master key.\n" ); - mpw_marshal_free( user ); - mpw_free_string( resultState, keyContext, resultParam ); + mpw_marshal_free( &user ); + mpw_free_strings( &resultState, &keyContext, &resultParam, NULL ); return EX_SOFTWARE; } // Update state. if (resultParam && resultType & MPResultTypeClassStateful) { - mpw_free_string( resultState ); + mpw_free_string( &resultState ); if (!(resultState = mpw_siteState( masterKey, site->name, siteCounter, keyPurpose, keyContext, resultType, resultParam, site->algorithm ))) { ftl( "Couldn't encrypt site result.\n" ); - mpw_free( masterKey, MPMasterKeySize ); - mpw_marshal_free( user ); - mpw_free_string( resultState, keyContext, resultParam ); + mpw_free( &masterKey, MPMasterKeySize ); + mpw_marshal_free( &user ); + mpw_free_strings( &resultState, &keyContext, &resultParam, NULL ); return EX_SOFTWARE; } inf( "(state) %s => ", resultState ); switch (keyPurpose) { case MPKeyPurposeAuthentication: { - mpw_free_string( site->content ); - site->content = resultState; + mpw_free_string( &site->content ); + site->content = strdup( resultState ); + dbg( "site->content: %p", (void *)site->content ); break; } case MPKeyPurposeIdentification: { - mpw_free_string( site->loginContent ); - site->loginContent = resultState; + mpw_free_string( &site->loginContent ); + site->loginContent = strdup( resultState ); break; } case MPKeyPurposeRecovery: { - mpw_free_string( question->content ); - question->content = resultState; + mpw_free_string( &question->content ); + question->content = strdup( resultState ); break; } } // resultParam is consumed. - mpw_free_string( resultParam ); - resultParam = NULL; + mpw_free_string( &resultParam ); } // Second phase resultParam defaults to state. if (!resultParam && resultState) resultParam = strdup( resultState ); - mpw_free_string( resultState ); + mpw_free_string( &resultState ); // Generate result. const char *result = mpw_siteResult( masterKey, site->name, siteCounter, keyPurpose, keyContext, resultType, resultParam, site->algorithm ); + mpw_free( &masterKey, MPMasterKeySize ); + mpw_free_strings( &keyContext, &resultParam, NULL ); if (!result) { ftl( "Couldn't generate site result.\n" ); - mpw_free( masterKey, MPMasterKeySize ); - mpw_marshal_free( user ); - mpw_free_string( resultState, keyContext, resultParam ); + mpw_marshal_free( &user ); return EX_SOFTWARE; } fprintf( stdout, "%s\n", result ); if (site->url) inf( "See: %s\n", site->url ); - mpw_free( masterKey, MPMasterKeySize ); - mpw_free_string( keyContext, resultParam, result ); + mpw_free_string( &result ); // Update usage metadata. site->lastUsed = user->lastUsed = time( NULL ); @@ -611,12 +607,12 @@ int main(int argc, char *const argv[]) { else if (fwrite( buf, sizeof( char ), strlen( buf ), sitesFile ) != strlen( buf )) wrn( "Error while writing updated configuration file:\n %s: %d\n", sitesPath, ferror( sitesFile ) ); - mpw_free_string( buf ); + mpw_free_string( &buf ); fclose( sitesFile ); } - mpw_free_string( sitesPath ); + mpw_free_string( &sitesPath ); } - mpw_marshal_free( user ); + mpw_marshal_free( &user ); return 0; } diff --git a/platform-independent/cli-c/cli/mpw-tests.c b/platform-independent/cli-c/cli/mpw-tests.c index eada047c..47cb35b5 100644 --- a/platform-independent/cli-c/cli/mpw-tests.c +++ b/platform-independent/cli-c/cli/mpw-tests.c @@ -56,7 +56,7 @@ int main(int argc, char *const argv[]) { // 2. calculate the site password. const char *sitePassword = mpw_siteResult( masterKey, (char *)siteName, siteCounter, keyPurpose, (char *)keyContext, resultType, NULL, algorithm ); - mpw_free( masterKey, MPMasterKeySize ); + mpw_free( &masterKey, MPMasterKeySize ); if (!sitePassword) { ftl( "Couldn't derive site password.\n" ); continue; @@ -72,7 +72,7 @@ int main(int argc, char *const argv[]) { } // Free test case. - mpw_free_string( sitePassword ); + mpw_free_string( &sitePassword ); xmlFree( id ); xmlFree( fullName ); xmlFree( masterPassword );