diff --git a/core/c/mpw-marshal-util.c b/core/c/mpw-marshal-util.c index 466f9f1f..1bd22538 100644 --- a/core/c/mpw-marshal-util.c +++ b/core/c/mpw-marshal-util.c @@ -55,7 +55,7 @@ json_object *mpw_get_json_section( json_object *obj, const char *section) { json_object *json_value = obj; - char *sectionTokenizer = strdup( section ), *sectionToken = sectionTokenizer; + char *sectionTokenizer = mpw_strdup( section ), *sectionToken = sectionTokenizer; for (sectionToken = strtok( sectionToken, "." ); sectionToken; sectionToken = strtok( NULL, "." )) if (!json_object_object_get_ex( json_value, sectionToken, &json_value ) || !json_value) { trc( "While resolving: %s: Missing value for: %s\n", section, sectionToken ); diff --git a/core/c/mpw-marshal.c b/core/c/mpw-marshal.c index c54bd13f..d1a287bf 100644 --- a/core/c/mpw-marshal.c +++ b/core/c/mpw-marshal.c @@ -33,8 +33,8 @@ MPMarshalledUser *mpw_marshal_user( return NULL; *user = (MPMarshalledUser){ - .fullName = strdup( fullName ), - .masterPassword = strdup( masterPassword ), + .fullName = mpw_strdup( fullName ), + .masterPassword = mpw_strdup( masterPassword ), .algorithm = algorithmVersion, .redacted = true, @@ -57,7 +57,7 @@ MPMarshalledSite *mpw_marshal_site( MPMarshalledSite *site = &user->sites[user->sites_count - 1]; *site = (MPMarshalledSite){ - .name = strdup( siteName ), + .name = mpw_strdup( siteName ), .content = NULL, .type = resultType, .counter = siteCounter, @@ -86,7 +86,7 @@ MPMarshalledQuestion *mpw_marshal_question( MPMarshalledQuestion *question = &site->questions[site->questions_count - 1]; *question = (MPMarshalledQuestion){ - .keyword = strdup( keyword ), + .keyword = mpw_strdup( keyword ), .content = NULL, .type = MPResultTypeTemplatePhrase, }; @@ -198,9 +198,9 @@ static bool mpw_marshal_write_flat( else { // Redacted if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content )) - content = strdup( site->content ); + content = mpw_strdup( site->content ); if (site->loginType & MPSiteFeatureExportContent && site->loginContent && strlen( site->loginContent )) - loginContent = strdup( site->loginContent ); + loginContent = mpw_strdup( site->loginContent ); } if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site->lastUsed ) )) @@ -284,9 +284,9 @@ static bool mpw_marshal_write_json( else { // Redacted if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content )) - content = strdup( site->content ); + content = mpw_strdup( site->content ); if (site->loginType & MPSiteFeatureExportContent && site->loginContent && strlen( site->loginContent )) - loginContent = strdup( site->loginContent ); + loginContent = mpw_strdup( site->loginContent ); } json_object *json_site = json_object_new_object(); @@ -397,9 +397,9 @@ static void mpw_marshal_read_flat_info( if (strcmp( headerName, "Algorithm" ) == 0) info->algorithm = (MPAlgorithmVersion)atoi( headerValue ); if (strcmp( headerName, "Full Name" ) == 0 || strcmp( headerName, "User Name" ) == 0) - info->fullName = strdup( headerValue ); + info->fullName = mpw_strdup( headerValue ); if (strcmp( headerName, "Key ID" ) == 0) - info->keyID = strdup( headerValue ); + info->keyID = mpw_strdup( headerValue ); if (strcmp( headerName, "Passwords" ) == 0) info->redacted = strcmp( headerValue, "VISIBLE" ) != 0; if (strcmp( headerName, "Date" ) == 0) @@ -463,11 +463,11 @@ static MPMarshalledUser *mpw_marshal_read_flat( if (strcmp( headerName, "Format" ) == 0) format = (unsigned int)atoi( headerValue ); if (strcmp( headerName, "Full Name" ) == 0 || strcmp( headerName, "User Name" ) == 0) - fullName = strdup( headerValue ); + fullName = mpw_strdup( headerValue ); if (strcmp( headerName, "Avatar" ) == 0) avatar = (unsigned int)atoi( headerValue ); if (strcmp( headerName, "Key ID" ) == 0) - keyID = strdup( headerValue ); + keyID = mpw_strdup( headerValue ); if (strcmp( headerName, "Algorithm" ) == 0) { int value = atoi( headerValue ); if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) { @@ -527,11 +527,11 @@ static MPMarshalledUser *mpw_marshal_read_flat( str_uses = mpw_get_token( &positionInLine, endOfLine, " \t\n" ); char *typeAndVersion = mpw_get_token( &positionInLine, endOfLine, " \t\n" ); if (typeAndVersion) { - str_type = strdup( strtok( typeAndVersion, ":" ) ); - str_algorithm = strdup( strtok( NULL, "" ) ); + str_type = mpw_strdup( strtok( typeAndVersion, ":" ) ); + str_algorithm = mpw_strdup( strtok( NULL, "" ) ); mpw_free_string( &typeAndVersion ); } - str_counter = strdup( "1" ); + str_counter = mpw_strdup( "1" ); siteLoginName = NULL; siteName = mpw_get_token( &positionInLine, endOfLine, "\t\n" ); siteContent = mpw_get_token( &positionInLine, endOfLine, "\n" ); @@ -542,9 +542,9 @@ static MPMarshalledUser *mpw_marshal_read_flat( str_uses = mpw_get_token( &positionInLine, endOfLine, " \t\n" ); char *typeAndVersionAndCounter = mpw_get_token( &positionInLine, endOfLine, " \t\n" ); if (typeAndVersionAndCounter) { - str_type = strdup( strtok( typeAndVersionAndCounter, ":" ) ); - str_algorithm = strdup( strtok( NULL, ":" ) ); - str_counter = strdup( strtok( NULL, "" ) ); + str_type = mpw_strdup( strtok( typeAndVersionAndCounter, ":" ) ); + str_algorithm = mpw_strdup( strtok( NULL, ":" ) ); + str_counter = mpw_strdup( strtok( NULL, "" ) ); mpw_free_string( &typeAndVersionAndCounter ); } siteLoginName = mpw_get_token( &positionInLine, endOfLine, "\t\n" ); @@ -608,9 +608,9 @@ static MPMarshalledUser *mpw_marshal_read_flat( else { // Redacted if (siteContent && strlen( siteContent )) - site->content = strdup( siteContent ); + site->content = mpw_strdup( siteContent ); if (siteLoginName && strlen( siteLoginName )) - site->loginContent = strdup( siteLoginName ); + site->loginContent = mpw_strdup( siteLoginName ); } } else { @@ -650,8 +650,8 @@ static void mpw_marshal_read_json_info( // Section: "user" info->algorithm = (MPAlgorithmVersion)mpw_get_json_int( json_file, "user.algorithm", MPAlgorithmVersionCurrent ); - info->fullName = strdup( mpw_get_json_string( json_file, "user.full_name", NULL ) ); - info->keyID = strdup( mpw_get_json_string( json_file, "user.key_id", NULL ) ); + info->fullName = mpw_strdup( mpw_get_json_string( json_file, "user.full_name", NULL ) ); + info->keyID = mpw_strdup( mpw_get_json_string( json_file, "user.key_id", NULL ) ); json_object_put( json_file ); } @@ -772,7 +772,7 @@ static MPMarshalledUser *mpw_marshal_read_json( } site->loginType = siteLoginType; - site->url = siteURL? strdup( siteURL ): NULL; + site->url = siteURL? mpw_strdup( siteURL ): NULL; site->uses = siteUses; site->lastUsed = siteLastUsed; if (!user->redacted) { @@ -792,9 +792,9 @@ static MPMarshalledUser *mpw_marshal_read_json( else { // Redacted if (siteContent && strlen( siteContent )) - site->content = strdup( siteContent ); + site->content = mpw_strdup( siteContent ); if (siteLoginName && strlen( siteLoginName )) - site->loginContent = strdup( siteLoginName ); + site->loginContent = mpw_strdup( siteLoginName ); } json_object_iter json_site_question; @@ -813,7 +813,7 @@ static MPMarshalledUser *mpw_marshal_read_json( else { // Redacted if (answerContent && strlen( answerContent )) - question->content = strdup( answerContent ); + question->content = mpw_strdup( answerContent ); } } } diff --git a/core/c/mpw-util.c b/core/c/mpw-util.c index 32e6aa68..b0034241 100644 --- a/core/c/mpw-util.c +++ b/core/c/mpw-util.c @@ -343,7 +343,7 @@ const char *mpw_hotp(const uint8_t *key, size_t keySize, uint64_t movingFactor, // Render the OTP as `digits` decimal digits. otp %= (int)pow(10, digits); - return strdup( mpw_str( "%0*d", digits, otp ) ); + return mpw_strdup( mpw_str( "%0*d", digits, otp ) ); } #endif @@ -567,6 +567,15 @@ const size_t mpw_utf8_strlen(const char *utf8String) { return charlen; } +char *mpw_strdup(const char *src) { + size_t len = strlen( src ); + char *dst = malloc( len + 1 ); + memcpy( dst, src, len ); + dst[len] = '\0'; + + return dst; +} + char *mpw_strndup(const char *src, size_t max) { size_t len = 0; for (; len < max && src[len] != '\0'; ++len); diff --git a/core/c/mpw-util.h b/core/c/mpw-util.h index c643026f..18bd1755 100644 --- a/core/c/mpw-util.h +++ b/core/c/mpw-util.h @@ -211,6 +211,8 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword); /** @return The amount of display characters in the given UTF-8 string. */ const size_t mpw_utf8_strlen(const char *utf8String); +/** Drop-in for non-standard strdup(3). */ +char *mpw_strdup(const char *src); /** Drop-in for non-standard strndup(3). */ char *mpw_strndup(const char *src, size_t max); diff --git a/platform-independent/cli-c/cli/mpw-cli-util.c b/platform-independent/cli-c/cli/mpw-cli-util.c index 87484e2a..47d3fd4b 100644 --- a/platform-independent/cli-c/cli/mpw-cli-util.c +++ b/platform-independent/cli-c/cli/mpw-cli-util.c @@ -35,7 +35,7 @@ const char *mpw_getenv(const char *variableName) { char *envBuf = getenv( variableName ); - return envBuf? strdup( envBuf ): NULL; + return envBuf? mpw_strdup( envBuf ): NULL; } /** Use the askpass program to prompt the user. @@ -129,7 +129,7 @@ const char *mpw_getpass(const char *prompt) { if (!answer) return NULL; - password = strdup( answer ); + password = mpw_strdup( answer ); mpw_zero( answer, strlen( answer ) ); return password; } @@ -144,25 +144,25 @@ const char *mpw_path(const char *prefix, const char *extension) { char *homeDir = NULL; if (!homeDir) if ((homeDir = getenv( "HOME" ))) - homeDir = strdup( homeDir ); + homeDir = mpw_strdup( homeDir ); if (!homeDir) if ((homeDir = getenv( "USERPROFILE" ))) - homeDir = strdup( homeDir ); + homeDir = mpw_strdup( homeDir ); if (!homeDir) { const char *homeDrive = getenv( "HOMEDRIVE" ), *homePath = getenv( "HOMEPATH" ); if (homeDrive && homePath) - homeDir = strdup( mpw_str( "%s%s", homeDrive, homePath ) ); + homeDir = mpw_strdup( mpw_str( "%s%s", homeDrive, homePath ) ); } if (!homeDir) { struct passwd *passwd = getpwuid( getuid() ); if (passwd) - homeDir = strdup( passwd->pw_dir ); + homeDir = mpw_strdup( passwd->pw_dir ); } if (!homeDir) homeDir = getcwd( NULL, 0 ); // Compose filename. - char *path = strdup( mpw_str( "%s.%s", prefix, extension ) ); + char *path = mpw_strdup( mpw_str( "%s.%s", prefix, extension ) ); // This is a filename, remove all potential directory separators. for (char *slash; (slash = strstr( path, "/" )); *slash = '_'); @@ -174,7 +174,7 @@ const char *mpw_path(const char *prefix, const char *extension) { free( path ); if (homePath) - path = strdup( homePath ); + path = mpw_strdup( homePath ); } return path; diff --git a/platform-independent/cli-c/cli/mpw-cli.c b/platform-independent/cli-c/cli/mpw-cli.c index a720552d..0704f32d 100644 --- a/platform-independent/cli-c/cli/mpw-cli.c +++ b/platform-independent/cli-c/cli/mpw-cli.c @@ -278,48 +278,48 @@ void cli_args(Arguments *args, Operation *operation, const int argc, char *const optarg? mpw_zero( optarg, strlen( optarg ) ): (void)0) switch (opt) { case 'u': - args->fullName = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->fullName = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; operation->allowPasswordUpdate = false; break; case 'U': - args->fullName = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->fullName = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; operation->allowPasswordUpdate = true; break; case 'm': - args->masterPasswordFD = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->masterPasswordFD = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; break; case 'M': // Passing your master password via the command-line is insecure. Testing purposes only. - args->masterPassword = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->masterPassword = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; break; case 't': - args->resultType = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->resultType = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; break; case 'P': - args->resultParam = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->resultParam = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; break; case 'c': - args->siteCounter = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->siteCounter = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; break; case 'a': - args->algorithmVersion = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->algorithmVersion = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; break; case 'p': - args->keyPurpose = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->keyPurpose = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; break; case 'C': - args->keyContext = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->keyContext = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; break; case 'f': - args->sitesFormat = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->sitesFormat = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; operation->sitesFormatFixed = false; break; case 'F': - args->sitesFormat = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->sitesFormat = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; operation->sitesFormatFixed = true; break; case 'R': - args->sitesRedacted = optarg && strlen( optarg )? strdup( optarg ): NULL; + args->sitesRedacted = optarg && strlen( optarg )? mpw_strdup( optarg ): NULL; break; case 'v': ++mpw_verbosity; @@ -351,13 +351,13 @@ void cli_args(Arguments *args, Operation *operation, const int argc, char *const } if (optind < argc && argv[optind]) - args->siteName = strdup( argv[optind] ); + args->siteName = mpw_strdup( argv[optind] ); } void cli_fullName(Arguments *args, Operation *operation) { if ((!operation->fullName || !strlen( operation->fullName )) && args->fullName) - operation->fullName = strdup( args->fullName ); + operation->fullName = mpw_strdup( args->fullName ); if (!operation->fullName || !strlen( operation->fullName )) do { @@ -380,7 +380,7 @@ void cli_masterPassword(Arguments *args, Operation *operation) { } if ((!operation->masterPassword || !strlen( operation->masterPassword )) && args->masterPassword) - operation->masterPassword = strdup( args->masterPassword ); + operation->masterPassword = mpw_strdup( args->masterPassword ); if (!operation->masterPassword || !strlen( operation->masterPassword )) do { @@ -397,7 +397,7 @@ void cli_masterPassword(Arguments *args, Operation *operation) { void cli_siteName(Arguments *args, Operation *operation) { if ((!operation->siteName || !strlen( operation->siteName )) && args->siteName) - operation->siteName = strdup( args->siteName ); + operation->siteName = mpw_strdup( args->siteName ); if (!operation->siteName || !strlen( operation->siteName )) do { operation->siteName = mpw_getline( "Site name:" ); @@ -441,7 +441,7 @@ void cli_keyContext(Arguments *args, Operation *operation) { if (!args->keyContext) return; - operation->keyContext = strdup( args->keyContext ); + operation->keyContext = mpw_strdup( args->keyContext ); } void cli_user(Arguments *args, Operation *operation) { @@ -497,7 +497,7 @@ void cli_user(Arguments *args, Operation *operation) { } if (operation->user) { mpw_free_string( &operation->user->masterPassword ); - operation->user->masterPassword = strdup( operation->masterPassword ); + operation->user->masterPassword = mpw_strdup( operation->masterPassword ); } } mpw_free_string( &sitesInputData ); @@ -573,23 +573,23 @@ void cli_operation(Arguments __unused *args, Operation *operation) { case MPKeyPurposeAuthentication: { operation->purposeResult = "password"; operation->resultType = operation->site->type; - operation->resultState = operation->site->content? strdup( operation->site->content ): NULL; + operation->resultState = operation->site->content? mpw_strdup( operation->site->content ): NULL; operation->siteCounter = operation->site->counter; break; } case MPKeyPurposeIdentification: { operation->purposeResult = "login"; operation->resultType = operation->site->loginType; - operation->resultState = operation->site->loginContent? strdup( operation->site->loginContent ): NULL; + operation->resultState = operation->site->loginContent? mpw_strdup( operation->site->loginContent ): NULL; operation->siteCounter = MPCounterValueInitial; break; } case MPKeyPurposeRecovery: { mpw_free_string( &operation->keyContext ); operation->purposeResult = "answer"; - operation->keyContext = operation->question->keyword? strdup( operation->question->keyword ): NULL; + operation->keyContext = operation->question->keyword? mpw_strdup( operation->question->keyword ): NULL; operation->resultType = operation->question->type; - operation->resultState = operation->question->content? strdup( operation->question->content ): NULL; + operation->resultState = operation->question->content? mpw_strdup( operation->question->content ): NULL; operation->siteCounter = MPCounterValueInitial; break; } @@ -655,7 +655,7 @@ void cli_resultParam(Arguments *args, Operation *operation) { if (!args->resultParam) return; - operation->resultParam = strdup( args->resultParam ); + operation->resultParam = mpw_strdup( args->resultParam ); } void cli_algorithmVersion(Arguments *args, Operation *operation) { @@ -715,18 +715,18 @@ void cli_mpw(Arguments *args, Operation *operation) { switch (operation->keyPurpose) { case MPKeyPurposeAuthentication: { mpw_free_string( &operation->site->content ); - operation->site->content = strdup( operation->resultState ); + operation->site->content = mpw_strdup( operation->resultState ); break; } case MPKeyPurposeIdentification: { mpw_free_string( &operation->site->loginContent ); - operation->site->loginContent = strdup( operation->resultState ); + operation->site->loginContent = mpw_strdup( operation->resultState ); break; } case MPKeyPurposeRecovery: { mpw_free_string( &operation->question->content ); - operation->question->content = strdup( operation->resultState ); + operation->question->content = mpw_strdup( operation->resultState ); break; } } @@ -737,7 +737,7 @@ void cli_mpw(Arguments *args, Operation *operation) { // resultParam defaults to state. if (!operation->resultParam && operation->resultState) - operation->resultParam = strdup( operation->resultState ); + operation->resultParam = mpw_strdup( operation->resultState ); // Generate result. const char *result = mpw_siteResult( masterKey, operation->site->name, operation->siteCounter,