diff --git a/MasterPassword/C/build b/MasterPassword/C/build index b9c02553..b2b48523 100755 --- a/MasterPassword/C/build +++ b/MasterPassword/C/build @@ -217,7 +217,8 @@ mpw() { (( mpw_color )) && CFLAGS+=( -DCOLOR ) LDFLAGS+=( -l"curses" ) cc "${CFLAGS[@]}" -c types.c -o types.o "$@" - cc "${CFLAGS[@]}" "${LDFLAGS[@]}" "types.o" mpw.c -o mpw "$@" + cc "${CFLAGS[@]}" -c mpw.c -o mpw.o "$@" + cc "${CFLAGS[@]}" "${LDFLAGS[@]}" "types.o" "mpw.o" mpw-cli.c -o mpw "$@" echo "done! Now run ./install or use ./mpw" } diff --git a/MasterPassword/C/mpw-cli.c b/MasterPassword/C/mpw-cli.c new file mode 100644 index 00000000..c7532176 --- /dev/null +++ b/MasterPassword/C/mpw-cli.c @@ -0,0 +1,207 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include "types.h" +#include "mpw.h" + +#if defined(READLINE) +#include +#elif defined(EDITLINE) +#include +#endif + +#define MP_env_fullname "MP_FULLNAME" +#define MP_env_sitetype "MP_SITETYPE" +#define MP_env_sitecounter "MP_SITECOUNTER" + +static void usage() { + + fprintf( stderr, "Usage: mpw [-u name] [-t type] [-c counter] site\n\n" ); + fprintf( stderr, " -u name Specify the full name of the user.\n" + " Defaults to %s in env.\n\n", MP_env_fullname ); + fprintf( stderr, " -t type Specify the password's template.\n" + " Defaults to %s in env or 'long' for password, 'name' for login.\n" + " x, max, maximum | 20 characters, contains symbols.\n" + " l, long | Copy-friendly, 14 characters, contains symbols.\n" + " m, med, medium | Copy-friendly, 8 characters, contains symbols.\n" + " b, basic | 8 characters, no symbols.\n" + " s, short | Copy-friendly, 4 characters, no symbols.\n" + " i, pin | 4 numbers.\n" + " n, name | 9 letter name.\n" + " p, phrase | 20 character sentence.\n\n", MP_env_sitetype ); + fprintf( stderr, " -c counter The value of the counter.\n" + " Defaults to %s in env or '1'.\n\n", MP_env_sitecounter ); + fprintf( stderr, " -v variant The kind of content to generate.\n" + " Defaults to 'password'.\n" + " p, password | The password to log in with.\n" + " l, login | The username to log in as.\n" + " a, answer | The answer to a security question.\n\n" ); + fprintf( stderr, " -C context A variant-specific context.\n" + " Defaults to empty.\n" + " -v p, password | Doesn't currently use a context.\n" + " -v l, login | Doesn't currently use a context.\n" + " -v a, answer | Empty for a universal site answer or\n" + " | the most significant word(s) of the question.\n\n" ); + fprintf( stderr, " ENVIRONMENT\n\n" + " MP_FULLNAME | The full name of the user.\n" + " MP_SITETYPE | The default password template.\n" + " MP_SITECOUNTER | The default counter value.\n\n" ); + exit( 0 ); +} + +static char *homedir(const char *filename) { + + char *homedir = NULL; + struct passwd *passwd = getpwuid( getuid() ); + if (passwd) + homedir = passwd->pw_dir; + if (!homedir) + homedir = getenv( "HOME" ); + if (!homedir) + homedir = getcwd( NULL, 0 ); + + char *homefile = NULL; + asprintf( &homefile, "%s/%s", homedir, filename ); + return homefile; +} + +static char *getlinep(const char *prompt) { + + char *buf = NULL; + size_t bufSize = 0; + ssize_t lineSize; + fprintf( stderr, "%s", prompt ); + fprintf( stderr, " " ); + if ((lineSize = getline( &buf, &bufSize, stdin )) < 0) { + free( buf ); + return NULL; + } + buf[lineSize - 1] = 0; + return buf; +} + +int main(int argc, char *const argv[]) { + + // Read the environment. + char *fullName = getenv( MP_env_fullname ); + const char *masterPassword = NULL; + const char *siteName = NULL; + MPSiteType siteType = MPSiteTypeGeneratedLong; + const char *siteTypeString = getenv( MP_env_sitetype ); + MPSiteVariant siteVariant = MPSiteVariantPassword; + const char *siteVariantString = NULL; + const char *siteContextString = NULL; + uint32_t siteCounter = 1; + const char *siteCounterString = getenv( MP_env_sitecounter ); + + // Read the options. + for (int opt; (opt = getopt( argc, argv, "u:t:c:v:C:h" )) != -1;) + switch (opt) { + case 'u': + fullName = optarg; + break; + case 't': + siteTypeString = optarg; + break; + case 'c': + siteCounterString = optarg; + break; + case 'v': + siteVariantString = optarg; + break; + case 'C': + siteContextString = optarg; + break; + case 'h': + usage(); + break; + case '?': + switch (optopt) { + case 'u': + fprintf( stderr, "Missing full name to option: -%c\n", optopt ); + break; + case 't': + fprintf( stderr, "Missing type name to option: -%c\n", optopt ); + break; + case 'c': + fprintf( stderr, "Missing counter value to option: -%c\n", optopt ); + break; + default: + fprintf( stderr, "Unknown option: -%c\n", optopt ); + } + return 1; + default: + abort(); + } + if (optind < argc) + siteName = argv[optind]; + + // Convert and validate input. + if (!fullName) { + if (!(fullName = getlinep( "Your full name:" ))) { + fprintf( stderr, "Missing full name.\n" ); + return 1; + } + } + if (!siteName) { + if (!(siteName = getlinep( "Site name:" ))) { + fprintf( stderr, "Missing site name.\n" ); + return 1; + } + } + if (siteCounterString) + siteCounter = atoi( siteCounterString ); + if (siteCounter < 1) { + fprintf( stderr, "Invalid site counter: %d\n", siteCounter ); + return 1; + } + if (siteVariantString) + siteVariant = VariantWithName( siteVariantString ); + if (siteVariant == MPSiteVariantLogin) + siteType = MPSiteTypeGeneratedName; + if (siteVariant == MPSiteVariantAnswer) + siteType = MPSiteTypeGeneratedPhrase; + if (siteTypeString) + siteType = TypeWithName( siteTypeString ); + + // Read the master password. + char *mpwConfigPath = homedir( ".mpw" ); + if (!mpwConfigPath) { + fprintf( stderr, "Couldn't resolve path for configuration file: %d\n", errno ); + return 1; + } + trc( "mpwConfigPath: %s\n", mpwConfigPath ); + FILE *mpwConfig = fopen( mpwConfigPath, "r" ); + free( mpwConfigPath ); + if (mpwConfig) { + char *line = NULL; + size_t linecap = 0; + while (getline( &line, &linecap, mpwConfig ) > 0) { + char *lineData = line; + if (strcmp( strsep( &lineData, ":" ), fullName ) == 0) { + masterPassword = strcpy( malloc( strlen( lineData ) ), strsep( &lineData, "\n" ) ); + break; + } + } + free( line ); + } + while (!masterPassword) + masterPassword = getpass( "Your master password: " ); + + // Summarize operation. + fprintf( stderr, "%s's password for %s:\n[ %s ]: ", fullName, siteName, Identicon( fullName, masterPassword ) ); + + // Output the password. + uint8_t *masterKey = mpw_masterKeyForUser( fullName, masterPassword ); + char *sitePassword = mpw_passwordForSite( masterKey, siteName, siteType, siteCounter, siteVariant, siteContextString ); + fprintf( stdout, "%s\n", sitePassword ); + + return 0; +} diff --git a/MasterPassword/C/mpw.c b/MasterPassword/C/mpw.c index 4aeaee48..e282698c 100644 --- a/MasterPassword/C/mpw.c +++ b/MasterPassword/C/mpw.c @@ -1,10 +1,7 @@ #define _GNU_SOURCE #include -#include #include -#include -#include #include #include #include @@ -13,300 +10,127 @@ #include #include "types.h" -#if defined(READLINE) -#include -#elif defined(EDITLINE) -#include -#endif - #define MP_N 32768 #define MP_r 8 #define MP_p 2 #define MP_dkLen 64 #define MP_hash PearlHashSHA256 -#define MP_env_fullname "MP_FULLNAME" -#define MP_env_sitetype "MP_SITETYPE" -#define MP_env_sitecounter "MP_SITECOUNTER" +void mpw_bufPush(void *buffer, size_t *bufferSize, void *pushBuffer, size_t pushSize) { -static void usage() { - fprintf(stderr, "Usage: mpw [-u name] [-t type] [-c counter] site\n\n"); - fprintf(stderr, " -u name Specify the full name of the user.\n" - " Defaults to %s in env.\n\n", MP_env_fullname); - fprintf(stderr, " -t type Specify the password's template.\n" - " Defaults to %s in env or 'long' for password, 'name' for login.\n" - " x, max, maximum | 20 characters, contains symbols.\n" - " l, long | Copy-friendly, 14 characters, contains symbols.\n" - " m, med, medium | Copy-friendly, 8 characters, contains symbols.\n" - " b, basic | 8 characters, no symbols.\n" - " s, short | Copy-friendly, 4 characters, no symbols.\n" - " i, pin | 4 numbers.\n" - " n, name | 9 letter name.\n" - " p, phrase | 20 character sentence.\n\n", MP_env_sitetype); - fprintf(stderr, " -c counter The value of the counter.\n" - " Defaults to %s in env or '1'.\n\n", MP_env_sitecounter); - fprintf(stderr, " -v variant The kind of content to generate.\n" - " Defaults to 'password'.\n" - " p, password | The password to log in with.\n" - " l, login | The username to log in as.\n" - " a, answer | The answer to a security question.\n\n"); - fprintf(stderr, " -C context A variant-specific context.\n" - " Defaults to empty.\n" - " -v p, password | Doesn't currently use a context.\n" - " -v l, login | Doesn't currently use a context.\n" - " -v a, answer | Empty for a universal site answer or\n" - " | the most significant word(s) of the question.\n\n"); - fprintf(stderr, " ENVIRONMENT\n\n" - " MP_FULLNAME | The full name of the user.\n" - " MP_SITETYPE | The default password template.\n" - " MP_SITECOUNTER | The default counter value.\n\n"); - exit(0); + void *pushDst = buffer + *bufferSize; + *bufferSize += pushSize; + realloc( buffer, *bufferSize ); + memcpy( pushDst, pushBuffer, pushSize ); } -static char *homedir(const char *filename) { - char *homedir = NULL; - struct passwd* passwd = getpwuid(getuid()); - if (passwd) - homedir = passwd->pw_dir; - if (!homedir) - homedir = getenv("HOME"); - if (!homedir) - homedir = getcwd(NULL, 0); - - char *homefile = NULL; - asprintf(&homefile, "%s/%s", homedir, filename); - return homefile; -} - -static char *getlinep(const char *prompt) { - char *buf = NULL; - size_t bufSize = 0; - ssize_t lineSize; - fprintf(stderr, "%s", prompt); - fprintf(stderr, " "); - if ((lineSize = getline(&buf, &bufSize, stdin)) < 0) { - free(buf); - return NULL; - } - buf[lineSize - 1]=0; - return buf; -} - -int main(int argc, char *const argv[]) { - - // Read the environment. - char *fullName = getenv( MP_env_fullname ); - const char *masterPassword = NULL; - const char *siteName = NULL; - MPSiteType siteType = MPSiteTypeGeneratedLong; - const char *siteTypeString = getenv( MP_env_sitetype ); - MPSiteVariant siteVariant = MPSiteVariantPassword; - const char *siteVariantString = NULL; - const char *siteContextString = NULL; - uint32_t siteCounter = 1; - const char *siteCounterString = getenv( MP_env_sitecounter ); - - // Read the options. - for (int opt; (opt = getopt(argc, argv, "u:t:c:v:C:h")) != -1;) - switch (opt) { - case 'u': - fullName = optarg; - break; - case 't': - siteTypeString = optarg; - break; - case 'c': - siteCounterString = optarg; - break; - case 'v': - siteVariantString = optarg; - break; - case 'C': - siteContextString = optarg; - break; - case 'h': - usage(); - break; - case '?': - switch (optopt) { - case 'u': - fprintf(stderr, "Missing full name to option: -%c\n", optopt); - break; - case 't': - fprintf(stderr, "Missing type name to option: -%c\n", optopt); - break; - case 'c': - fprintf(stderr, "Missing counter value to option: -%c\n", optopt); - break; - default: - fprintf(stderr, "Unknown option: -%c\n", optopt); - } - return 1; - default: - abort(); - } - if (optind < argc) - siteName = argv[optind]; - - // Convert and validate input. - if (!fullName) { - if (!(fullName = getlinep("Your full name:"))) { - fprintf(stderr, "Missing full name.\n"); - return 1; - } - } - trc("fullName: %s\n", fullName); - if (!siteName) { - if (!(siteName = getlinep("Site name:"))) { - fprintf(stderr, "Missing site name.\n"); - return 1; - } - } - if (siteCounterString) - siteCounter = atoi( siteCounterString ); - if (siteCounter < 1) { - fprintf(stderr, "Invalid site counter: %d\n", siteCounter); - return 1; - } - if (siteVariantString) - siteVariant = VariantWithName( siteVariantString ); - if (siteVariant == MPSiteVariantLogin) - siteType = MPSiteTypeGeneratedName; - if (siteVariant == MPSiteVariantAnswer) - siteType = MPSiteTypeGeneratedPhrase; - if (siteTypeString) - siteType = TypeWithName( siteTypeString ); - - // Read the master password. - char *mpwConfigPath = homedir(".mpw"); - if (!mpwConfigPath) { - fprintf(stderr, "Couldn't resolve path for configuration file: %d\n", errno); - return 1; - } - trc("mpwConfigPath: %s\n", mpwConfigPath); - FILE *mpwConfig = fopen(mpwConfigPath, "r"); - free(mpwConfigPath); - if (mpwConfig) { - char *line = NULL; - size_t linecap = 0; - while (getline(&line, &linecap, mpwConfig) > 0) { - char *lineData = line; - if (strcmp(strsep(&lineData, ":"), fullName) == 0) { - masterPassword = strcpy(malloc(strlen(lineData)), strsep(&lineData, "\n")); - break; - } - } - free(line); - } - while (!masterPassword) - masterPassword = getpass( "Your master password: " ); - trc("masterPassword: %s\n", masterPassword); - - // Summarize operation. - fprintf(stderr, "%s's password for %s:\n[ %s ]: ", fullName, siteName, Identicon( fullName, masterPassword )); - struct timeval startTime; - if (gettimeofday(&startTime, NULL) != 0) { - fprintf(stderr, "Could not get time: %d\n", errno); - return 1; - } +uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPassword) { // Calculate the master key salt. - const char *mpKeyScope = ScopeForVariant(MPSiteVariantPassword); - trc("key scope: %s\n", mpKeyScope); - const uint32_t n_fullNameLength = htonl(strlen(fullName)); - const size_t masterKeySaltLength = strlen(mpKeyScope) + sizeof(n_fullNameLength) + strlen(fullName); + const char *mpKeyScope = ScopeForVariant( MPSiteVariantPassword ); + const uint32_t n_fullNameLength = htonl( strlen( fullName ) ); + const size_t masterKeySaltLength = strlen( mpKeyScope ) + sizeof( n_fullNameLength ) + strlen( fullName ); char *masterKeySalt = (char *)malloc( masterKeySaltLength ); - if (!masterKeySalt) { - fprintf(stderr, "Could not allocate master key salt: %d\n", errno); - return 1; - } + if (!masterKeySalt) + ftl( "Could not allocate master key salt: %d\n", errno ); char *mKS = masterKeySalt; - memcpy(mKS, mpKeyScope, strlen(mpKeyScope)); mKS += strlen(mpKeyScope); - memcpy(mKS, &n_fullNameLength, sizeof(n_fullNameLength)); mKS += sizeof(n_fullNameLength); - memcpy(mKS, fullName, strlen(fullName)); mKS += strlen(fullName); + memcpy( mKS, mpKeyScope, strlen( mpKeyScope ) ); + mKS += strlen( mpKeyScope ); + memcpy( mKS, &n_fullNameLength, sizeof( n_fullNameLength ) ); + mKS += sizeof( n_fullNameLength ); + memcpy( mKS, fullName, strlen( fullName ) ); + mKS += strlen( fullName ); + + trc( "fullName: %s\n", fullName ); + trc( "masterPassword: %s\n", masterPassword ); + trc( "key scope: %s\n", mpKeyScope ); + trc( "masterKeySalt ID: %s\n", IDForBuf( masterKeySalt, masterKeySaltLength ) ); if (mKS - masterKeySalt != masterKeySaltLength) - abort(); - trc("masterKeySalt ID: %s\n", IDForBuf(masterKeySalt, masterKeySaltLength)); + ftl( "Unexpected master key salt length." ); // Calculate the master key. uint8_t *masterKey = (uint8_t *)malloc( MP_dkLen ); if (!masterKey) { - fprintf(stderr, "Could not allocate master key: %d\n", errno); - return 1; + fprintf( stderr, "Could not allocate master key: %d\n", errno ); + abort(); } - if (crypto_scrypt( (const uint8_t *)masterPassword, strlen(masterPassword), (const uint8_t *)masterKeySalt, masterKeySaltLength, MP_N, MP_r, MP_p, masterKey, MP_dkLen ) < 0) { - fprintf(stderr, "Could not generate master key: %d\n", errno); - return 1; + if (crypto_scrypt( (const uint8_t *)masterPassword, strlen( masterPassword ), (const uint8_t *)masterKeySalt, masterKeySaltLength, MP_N, + MP_r, MP_p, masterKey, MP_dkLen ) < 0) { + fprintf( stderr, "Could not generate master key: %d\n", errno ); + abort(); } - memset(masterKeySalt, 0, masterKeySaltLength); - free(masterKeySalt); - struct timeval endTime; - if (gettimeofday(&endTime, NULL) != 0) { - fprintf(stderr, "Could not get time: %d\n", errno); - return 1; - } - long long secs = (endTime.tv_sec - startTime.tv_sec); - long long usecs = (endTime.tv_usec - startTime.tv_usec); - double elapsed = secs + usecs / 1000000.0; - trc("masterKey ID: %s (derived in %.2fs)\n", IDForBuf(masterKey, MP_dkLen), elapsed); + memset( masterKeySalt, 0, masterKeySaltLength ); + free( masterKeySalt ); + trc( "masterKey ID: %s\n", IDForBuf( masterKey, MP_dkLen ) ); + + return masterKey; +} + +char *mpw_passwordForSite(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter, + const MPSiteVariant siteVariant, const char *siteContext) { // Calculate the site seed. - trc("siteName: %s\n", siteName); - trc("siteCounter: %d\n", siteCounter); - trc("siteVariant: %d (%s)\n", siteVariant, siteVariantString); - trc("siteType: %d (%s)\n", siteType, siteTypeString); - const char *siteScope = ScopeForVariant(siteVariant); - trc("site scope: %s, context: %s\n", siteScope, siteContextString == NULL? "": siteContextString); - const uint32_t n_siteNameLength = htonl(strlen(siteName)); - const uint32_t n_siteCounter = htonl(siteCounter); - const uint32_t n_siteContextLength = siteContextString == NULL? 0: htonl(strlen(siteContextString)); - size_t sitePasswordInfoLength = strlen(siteScope) + sizeof(n_siteNameLength) + strlen(siteName) + sizeof(n_siteCounter); - if (siteContextString) - sitePasswordInfoLength += sizeof(n_siteContextLength) + strlen(siteContextString); + trc( "siteName: %s\n", siteName ); + trc( "siteCounter: %d\n", siteCounter ); + trc( "siteVariant: %d\n", siteVariant ); + trc( "siteType: %d\n", siteType ); + const char *siteScope = ScopeForVariant( siteVariant ); + trc( "site scope: %s, context: %s\n", siteScope, siteContext == NULL? "": siteContext ); + const uint32_t n_siteNameLength = htonl( strlen( siteName ) ); + const uint32_t n_siteCounter = htonl( siteCounter ); + const uint32_t n_siteContextLength = siteContext == NULL? 0: htonl( strlen( siteContext ) ); + size_t sitePasswordInfoLength = strlen( siteScope ) + sizeof( n_siteNameLength ) + strlen( siteName ) + sizeof( n_siteCounter ); + if (siteContext) + sitePasswordInfoLength += sizeof( n_siteContextLength ) + strlen( siteContext ); char *sitePasswordInfo = (char *)malloc( sitePasswordInfoLength ); if (!sitePasswordInfo) { - fprintf(stderr, "Could not allocate site seed: %d\n", errno); - return 1; + fprintf( stderr, "Could not allocate site seed: %d\n", errno ); + abort(); } char *sPI = sitePasswordInfo; - memcpy(sPI, siteScope, strlen(siteScope)); sPI += strlen(siteScope); - memcpy(sPI, &n_siteNameLength, sizeof(n_siteNameLength)); sPI += sizeof(n_siteNameLength); - memcpy(sPI, siteName, strlen(siteName)); sPI += strlen(siteName); - memcpy(sPI, &n_siteCounter, sizeof(n_siteCounter)); sPI += sizeof(n_siteCounter); - if (siteContextString) { - memcpy(sPI, &n_siteContextLength, sizeof(n_siteContextLength)); sPI += sizeof(n_siteContextLength); - memcpy(sPI, siteContextString, strlen(siteContextString)); sPI += strlen(siteContextString); + memcpy( sPI, siteScope, strlen( siteScope ) ); + sPI += strlen( siteScope ); + memcpy( sPI, &n_siteNameLength, sizeof( n_siteNameLength ) ); + sPI += sizeof( n_siteNameLength ); + memcpy( sPI, siteName, strlen( siteName ) ); + sPI += strlen( siteName ); + memcpy( sPI, &n_siteCounter, sizeof( n_siteCounter ) ); + sPI += sizeof( n_siteCounter ); + if (siteContext) { + memcpy( sPI, &n_siteContextLength, sizeof( n_siteContextLength ) ); + sPI += sizeof( n_siteContextLength ); + memcpy( sPI, siteContext, strlen( siteContext ) ); + sPI += strlen( siteContext ); } if (sPI - sitePasswordInfo != sitePasswordInfoLength) abort(); - trc("seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", siteScope, Hex(&n_siteNameLength, sizeof(n_siteNameLength)), siteName, Hex(&n_siteCounter, sizeof(n_siteCounter)), Hex(&n_siteContextLength, sizeof(n_siteContextLength)), siteContextString); - trc("sitePasswordInfo ID: %s\n", IDForBuf(sitePasswordInfo, sitePasswordInfoLength)); + trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", siteScope, + Hex( &n_siteNameLength, sizeof( n_siteNameLength ) ), siteName, Hex( &n_siteCounter, sizeof( n_siteCounter ) ), + Hex( &n_siteContextLength, sizeof( n_siteContextLength ) ), siteContext ); + trc( "sitePasswordInfo ID: %s\n", IDForBuf( sitePasswordInfo, sitePasswordInfoLength ) ); uint8_t sitePasswordSeed[32]; - HMAC_SHA256_Buf(masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoLength, sitePasswordSeed); - memset(masterKey, 0, MP_dkLen); - memset(sitePasswordInfo, 0, sitePasswordInfoLength); - free(masterKey); - free(sitePasswordInfo); - trc("sitePasswordSeed ID: %s\n", IDForBuf(sitePasswordSeed, 32)); + HMAC_SHA256_Buf( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoLength, sitePasswordSeed ); + memset( sitePasswordInfo, 0, sitePasswordInfoLength ); + free( sitePasswordInfo ); + trc( "sitePasswordSeed ID: %s\n", IDForBuf( sitePasswordSeed, 32 ) ); // Determine the template. - const char *template = TemplateForType(siteType, sitePasswordSeed[0]); - trc("type %s, template: %s\n", siteTypeString, template); - if (strlen(template) > 32) + const char *template = TemplateForType( siteType, sitePasswordSeed[0] ); + trc( "type %d, template: %s\n", siteType, template ); + if (strlen( template ) > 32) abort(); // Encode the password from the seed using the template. - char *sitePassword = (char *)calloc(strlen(template) + 1, sizeof(char)); - for (int c = 0; c < strlen(template); ++c) { - sitePassword[c] = CharacterFromClass(template[c], sitePasswordSeed[c + 1]); - trc("class %c, index %u (0x%02X) -> character: %c\n", template[c], sitePasswordSeed[c + 1], sitePasswordSeed[c + 1], sitePassword[c]); + char *sitePassword = (char *)calloc( strlen( template ) + 1, sizeof( char ) ); + for (int c = 0; c < strlen( template ); ++c) { + sitePassword[c] = CharacterFromClass( template[c], sitePasswordSeed[c + 1] ); + trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], sitePasswordSeed[c + 1], sitePasswordSeed[c + 1], + sitePassword[c] ); } - memset(sitePasswordSeed, 0, sizeof(sitePasswordSeed)); + memset( sitePasswordSeed, 0, sizeof( sitePasswordSeed ) ); - // Output the password. - fprintf( stdout, "%s\n", sitePassword ); - return 0; + return sitePassword; } diff --git a/MasterPassword/C/mpw.h b/MasterPassword/C/mpw.h new file mode 100644 index 00000000..a9238599 --- /dev/null +++ b/MasterPassword/C/mpw.h @@ -0,0 +1,6 @@ +uint8_t *mpw_masterKeyForUser( + const char *fullName, const char *masterPassword); + +char *mpw_passwordForSite( + const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter, + const MPSiteVariant siteVariant, const char *siteContext); diff --git a/MasterPassword/C/types.h b/MasterPassword/C/types.h index f2d062cd..ec6bd83c 100644 --- a/MasterPassword/C/types.h +++ b/MasterPassword/C/types.h @@ -48,6 +48,7 @@ typedef enum { #else #define trc(...) do {} while (0) #endif +#define ftl(...) do { fprintf( stderr, "Could not allocate master key salt: %d\n", errno ); abort(); } while (0) const MPSiteVariant VariantWithName(const char *variantName); const char *ScopeForVariant(MPSiteVariant variant); diff --git a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj index 07515e2a..734e0eba 100644 --- a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj +++ b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ 93D39A5FF670957C0AF8298D /* MPPasswordCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */; }; 93D39A8EA1C49CE43B63F47B /* PearlUICollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D8A953779B35403AF6E /* PearlUICollectionView.m */; }; 93D39AA4A0BE66A872CCC02E /* NSPersistentStore+PearlMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D397F4BAFFF7CF3F1B21A4 /* NSPersistentStore+PearlMigration.h */; }; + 93D39B35D4B8E87ADEC05246 /* mpw-cli.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D398121C8F063A3637144E /* mpw-cli.c */; }; 93D39B429C67A62E29DC02DA /* MPRootSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */; }; 93D39B76DD5AB108BA8928E8 /* UIScrollView+PearlAdjustInsets.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */; }; 93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */; }; @@ -498,8 +499,10 @@ 93D3979016BF0C5B29D1340D /* distribute */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = distribute; sourceTree = ""; }; 93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogsViewController.m; sourceTree = ""; }; 93D397F4BAFFF7CF3F1B21A4 /* NSPersistentStore+PearlMigration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPersistentStore+PearlMigration.h"; sourceTree = ""; }; + 93D398121C8F063A3637144E /* mpw-cli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-cli.c"; sourceTree = ""; }; 93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlNavigationController.h; sourceTree = ""; }; 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+PearlFullDescription.h"; sourceTree = ""; }; + 93D3990D850D76A94C6B7A4D /* mpw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mpw.h; sourceTree = ""; }; 93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWebViewController.m; sourceTree = ""; }; 93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRootSegue.m; sourceTree = ""; }; 93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCoachmarkViewController.m; sourceTree = ""; }; @@ -1612,6 +1615,8 @@ 93D3979016BF0C5B29D1340D /* distribute */, 93D39245A478883C672818F3 /* mpw.bashrc */, 93D39B70138D0E28F7D5E86B /* mpw-bench.c */, + 93D398121C8F063A3637144E /* mpw-cli.c */, + 93D3990D850D76A94C6B7A4D /* mpw.h */, ); name = C; path = ../../C; @@ -3626,6 +3631,7 @@ 93D39B429C67A62E29DC02DA /* MPRootSegue.m in Sources */, 93D392FD5E2052F7D7DB3774 /* NSString+MPMarkDown.m in Sources */, 93D395B715D15F2B56F2A2EE /* types.c in Sources */, + 93D39B35D4B8E87ADEC05246 /* mpw-cli.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };