Define type for siteCounter, add support for saving hybrid passwords.
This commit is contained in:
parent
b26f5a82d7
commit
ee50a4d025
@ -46,7 +46,7 @@ MPMasterKey mpw_masterKey(const char *fullName, const char *masterPassword, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
MPSiteKey mpw_siteKey(
|
MPSiteKey mpw_siteKey(
|
||||||
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
|
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||||
const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion) {
|
const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion) {
|
||||||
|
|
||||||
trc( "-- mpw_siteKey (algorithm: %u)\n", algorithmVersion );
|
trc( "-- mpw_siteKey (algorithm: %u)\n", algorithmVersion );
|
||||||
|
@ -45,7 +45,7 @@ MPMasterKey mpw_masterKey(
|
|||||||
/** Derive the site key for a user's site from the given master key and site parameters.
|
/** Derive the site key for a user's site from the given master key and site parameters.
|
||||||
* @return A new MPSiteKeySize-byte allocated buffer or NULL if an error occurred. */
|
* @return A new MPSiteKeySize-byte allocated buffer or NULL if an error occurred. */
|
||||||
MPSiteKey mpw_siteKey(
|
MPSiteKey mpw_siteKey(
|
||||||
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
|
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||||
const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion);
|
const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion);
|
||||||
|
|
||||||
/** Encode a password for the site from the given site key.
|
/** Encode a password for the site from the given site key.
|
||||||
|
@ -82,12 +82,14 @@ static MPMasterKey mpw_masterKey_v0(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static MPSiteKey mpw_siteKey_v0(
|
static MPSiteKey mpw_siteKey_v0(
|
||||||
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
|
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||||
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||||
|
|
||||||
const char *keyScope = mpw_scopeForPurpose( keyPurpose );
|
const char *keyScope = mpw_scopeForPurpose( keyPurpose );
|
||||||
trc( "keyScope: %s\n", keyScope );
|
trc( "keyScope: %s\n", keyScope );
|
||||||
|
|
||||||
|
// TODO: Implement MPCounterValueTOTP
|
||||||
|
|
||||||
// Calculate the site seed.
|
// Calculate the site seed.
|
||||||
trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s\n",
|
trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s\n",
|
||||||
keyScope, mpw_hex_l( htonl( mpw_utf8_strlen( siteName ) ) ), siteName, mpw_hex_l( htonl( siteCounter ) ),
|
keyScope, mpw_hex_l( htonl( mpw_utf8_strlen( siteName ) ) ), siteName, mpw_hex_l( htonl( siteCounter ) ),
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
MPMasterKey mpw_masterKey_v0(
|
MPMasterKey mpw_masterKey_v0(
|
||||||
const char *fullName, const char *masterPassword);
|
const char *fullName, const char *masterPassword);
|
||||||
MPSiteKey mpw_siteKey_v0(
|
MPSiteKey mpw_siteKey_v0(
|
||||||
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
|
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||||
const MPKeyPurpose keyPurpose, const char *keyContext);
|
const MPKeyPurpose keyPurpose, const char *keyContext);
|
||||||
const char *mpw_encrypt_v0(
|
const char *mpw_encrypt_v0(
|
||||||
MPMasterKey masterKey, const char *plainText);
|
MPMasterKey masterKey, const char *plainText);
|
||||||
@ -46,7 +46,7 @@ static MPMasterKey mpw_masterKey_v1(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static MPSiteKey mpw_siteKey_v1(
|
static MPSiteKey mpw_siteKey_v1(
|
||||||
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
|
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||||
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||||
|
|
||||||
return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );
|
return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );
|
||||||
|
@ -45,12 +45,14 @@ static MPMasterKey mpw_masterKey_v2(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static MPSiteKey mpw_siteKey_v2(
|
static MPSiteKey mpw_siteKey_v2(
|
||||||
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
|
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||||
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||||
|
|
||||||
const char *keyScope = mpw_scopeForPurpose( keyPurpose );
|
const char *keyScope = mpw_scopeForPurpose( keyPurpose );
|
||||||
trc( "keyScope: %s\n", keyScope );
|
trc( "keyScope: %s\n", keyScope );
|
||||||
|
|
||||||
|
// TODO: Implement MPCounterValueTOTP
|
||||||
|
|
||||||
// Calculate the site seed.
|
// Calculate the site seed.
|
||||||
trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s\n",
|
trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s\n",
|
||||||
keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, mpw_hex_l( htonl( siteCounter ) ),
|
keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, mpw_hex_l( htonl( siteCounter ) ),
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
// Inherited functions.
|
// Inherited functions.
|
||||||
MPSiteKey mpw_siteKey_v2(
|
MPSiteKey mpw_siteKey_v2(
|
||||||
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
|
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||||
const MPKeyPurpose keyPurpose, const char *keyContext);
|
const MPKeyPurpose keyPurpose, const char *keyContext);
|
||||||
const char *mpw_sitePassword_v2(
|
const char *mpw_sitePassword_v2(
|
||||||
MPSiteKey siteKey, const MPPasswordType passwordType);
|
MPSiteKey siteKey, const MPPasswordType passwordType);
|
||||||
@ -73,7 +73,7 @@ static MPMasterKey mpw_masterKey_v3(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static MPSiteKey mpw_siteKey_v3(
|
static MPSiteKey mpw_siteKey_v3(
|
||||||
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
|
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||||
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||||
|
|
||||||
return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext );
|
return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext );
|
||||||
|
@ -50,7 +50,7 @@ MPMarshalledUser *mpw_marshall_user(
|
|||||||
|
|
||||||
MPMarshalledSite *mpw_marshall_site(
|
MPMarshalledSite *mpw_marshall_site(
|
||||||
MPMarshalledUser *user, const char *siteName, const MPPasswordType passwordType,
|
MPMarshalledUser *user, const char *siteName, const MPPasswordType passwordType,
|
||||||
const uint32_t siteCounter, const MPAlgorithmVersion algorithmVersion) {
|
const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion) {
|
||||||
|
|
||||||
if (!siteName || !mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count ))
|
if (!siteName || !mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count ))
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -294,7 +294,8 @@ static bool mpw_marshall_write_json(
|
|||||||
|
|
||||||
if (!user->redacted) {
|
if (!user->redacted) {
|
||||||
// Clear Text
|
// Clear Text
|
||||||
MPSiteKey siteKey = mpw_siteKey( masterKey, site->name, 1, MPKeyPurposeRecovery, question->keyword, site->algorithm );
|
MPSiteKey siteKey = mpw_siteKey( masterKey, site->name,
|
||||||
|
MPCounterValueInitial, MPKeyPurposeRecovery, question->keyword, site->algorithm );
|
||||||
const char *answer = mpw_sitePassword( siteKey, MPPasswordTypeGeneratedPhrase, site->algorithm );
|
const char *answer = mpw_sitePassword( siteKey, MPPasswordTypeGeneratedPhrase, site->algorithm );
|
||||||
mpw_free( siteKey, MPSiteKeySize );
|
mpw_free( siteKey, MPSiteKeySize );
|
||||||
if (answer)
|
if (answer)
|
||||||
@ -482,11 +483,11 @@ static MPMarshalledUser *mpw_marshall_read_flat(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
long long int value = atoll( str_counter );
|
long long int value = atoll( str_counter );
|
||||||
if (value < 0 || value > UINT32_MAX) {
|
if (value < MPCounterValueFirst || value > MPCounterValueLast) {
|
||||||
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site counter: %s: %s", siteName, str_counter ) };
|
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site counter: %s: %s", siteName, str_counter ) };
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
uint32_t siteCounter = (uint32_t)value;
|
MPCounterValue siteCounter = (MPCounterValue)value;
|
||||||
value = atoll( str_algorithm );
|
value = atoll( str_algorithm );
|
||||||
if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) {
|
if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) {
|
||||||
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site algorithm: %s: %s", siteName, str_algorithm ) };
|
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site algorithm: %s: %s", siteName, str_algorithm ) };
|
||||||
@ -634,11 +635,11 @@ static MPMarshalledUser *mpw_marshall_read_json(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
value = mpw_get_json_int( json_site.val, "counter", 1 );
|
value = mpw_get_json_int( json_site.val, "counter", 1 );
|
||||||
if (value < 0 || value > UINT32_MAX) {
|
if (value < MPCounterValueFirst || value > MPCounterValueLast) {
|
||||||
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site counter: %s: %d", siteName, value ) };
|
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site counter: %s: %d", siteName, value ) };
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
uint32_t siteCounter = (uint32_t)value;
|
MPCounterValue siteCounter = (MPCounterValue)value;
|
||||||
const char *siteContent = mpw_get_json_string( json_site.val, "password", NULL );
|
const char *siteContent = mpw_get_json_string( json_site.val, "password", NULL );
|
||||||
const char *siteLoginName = mpw_get_json_string( json_site.val, "login_name", NULL );
|
const char *siteLoginName = mpw_get_json_string( json_site.val, "login_name", NULL );
|
||||||
bool siteLoginGenerated = mpw_get_json_boolean( json_site.val, "login_generated", false );
|
bool siteLoginGenerated = mpw_get_json_boolean( json_site.val, "login_generated", false );
|
||||||
|
@ -63,7 +63,7 @@ typedef struct MPMarshalledSite {
|
|||||||
const char *name;
|
const char *name;
|
||||||
const char *content;
|
const char *content;
|
||||||
MPPasswordType type;
|
MPPasswordType type;
|
||||||
uint32_t counter;
|
MPCounterValue counter;
|
||||||
MPAlgorithmVersion algorithm;
|
MPAlgorithmVersion algorithm;
|
||||||
|
|
||||||
const char *loginName;
|
const char *loginName;
|
||||||
@ -104,7 +104,7 @@ MPMarshalledUser *mpw_marshall_user(
|
|||||||
const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion);
|
const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion);
|
||||||
MPMarshalledSite *mpw_marshall_site(
|
MPMarshalledSite *mpw_marshall_site(
|
||||||
MPMarshalledUser *user,
|
MPMarshalledUser *user,
|
||||||
const char *siteName, const MPPasswordType passwordType, const uint32_t siteCounter, const MPAlgorithmVersion algorithmVersion);
|
const char *siteName, const MPPasswordType passwordType, const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion);
|
||||||
MPMarshalledQuestion *mpw_marshal_question(
|
MPMarshalledQuestion *mpw_marshal_question(
|
||||||
MPMarshalledSite *site, const char *keyword);
|
MPMarshalledSite *site, const char *keyword);
|
||||||
bool mpw_marshal_free(
|
bool mpw_marshal_free(
|
||||||
|
@ -31,6 +31,28 @@
|
|||||||
|
|
||||||
const MPPasswordType mpw_typeWithName(const char *typeName) {
|
const MPPasswordType mpw_typeWithName(const char *typeName) {
|
||||||
|
|
||||||
|
// Find what password type is represented by the type letter.
|
||||||
|
if (strlen( typeName ) == 1) {
|
||||||
|
if ('x' == typeName[0])
|
||||||
|
return MPPasswordTypeGeneratedMaximum;
|
||||||
|
if ('l' == typeName[0])
|
||||||
|
return MPPasswordTypeGeneratedLong;
|
||||||
|
if ('m' == typeName[0])
|
||||||
|
return MPPasswordTypeGeneratedMedium;
|
||||||
|
if ('b' == typeName[0])
|
||||||
|
return MPPasswordTypeGeneratedBasic;
|
||||||
|
if ('s' == typeName[0])
|
||||||
|
return MPPasswordTypeGeneratedShort;
|
||||||
|
if ('i' == typeName[0])
|
||||||
|
return MPPasswordTypeGeneratedPIN;
|
||||||
|
if ('n' == typeName[0])
|
||||||
|
return MPPasswordTypeGeneratedName;
|
||||||
|
if ('P' == typeName[0])
|
||||||
|
return MPPasswordTypeStoredPersonal;
|
||||||
|
if ('D' == typeName[0])
|
||||||
|
return MPPasswordTypeStoredDevice;
|
||||||
|
}
|
||||||
|
|
||||||
// Lower-case and trim optionally leading "Generated" string from typeName to standardize it.
|
// Lower-case and trim optionally leading "Generated" string from typeName to standardize it.
|
||||||
size_t stdTypeNameOffset = 0;
|
size_t stdTypeNameOffset = 0;
|
||||||
size_t stdTypeNameSize = strlen( typeName );
|
size_t stdTypeNameSize = strlen( typeName );
|
||||||
@ -42,29 +64,23 @@ const MPPasswordType mpw_typeWithName(const char *typeName) {
|
|||||||
stdTypeName[stdTypeNameSize] = '\0';
|
stdTypeName[stdTypeNameSize] = '\0';
|
||||||
|
|
||||||
// Find what password type is represented by the type name.
|
// Find what password type is represented by the type name.
|
||||||
if (0 == strcmp( "x", stdTypeName )
|
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||||
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
return MPPasswordTypeGeneratedPhrase;
|
||||||
|
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||||
return MPPasswordTypeGeneratedMaximum;
|
return MPPasswordTypeGeneratedMaximum;
|
||||||
if (0 == strcmp( "l", stdTypeName )
|
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedLong ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||||
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedLong ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
|
||||||
return MPPasswordTypeGeneratedLong;
|
return MPPasswordTypeGeneratedLong;
|
||||||
if (0 == strcmp( "m", stdTypeName )
|
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedMedium ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||||
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedMedium ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
|
||||||
return MPPasswordTypeGeneratedMedium;
|
return MPPasswordTypeGeneratedMedium;
|
||||||
if (0 == strcmp( "b", stdTypeName )
|
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedBasic ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||||
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedBasic ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
|
||||||
return MPPasswordTypeGeneratedBasic;
|
return MPPasswordTypeGeneratedBasic;
|
||||||
if (0 == strcmp( "s", stdTypeName )
|
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedShort ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||||
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedShort ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
|
||||||
return MPPasswordTypeGeneratedShort;
|
return MPPasswordTypeGeneratedShort;
|
||||||
if (0 == strcmp( "i", stdTypeName )
|
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPIN ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||||
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedPIN ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
|
||||||
return MPPasswordTypeGeneratedPIN;
|
return MPPasswordTypeGeneratedPIN;
|
||||||
if (0 == strcmp( "n", stdTypeName )
|
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedName ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||||
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedName ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
|
||||||
return MPPasswordTypeGeneratedName;
|
return MPPasswordTypeGeneratedName;
|
||||||
if (0 == strcmp( "p", stdTypeName )
|
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||||
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedPhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
|
||||||
return MPPasswordTypeGeneratedPhrase;
|
return MPPasswordTypeGeneratedPhrase;
|
||||||
|
|
||||||
dbg( "Not a generated type name: %s\n", stdTypeName );
|
dbg( "Not a generated type name: %s\n", stdTypeName );
|
||||||
|
@ -31,13 +31,13 @@
|
|||||||
|
|
||||||
//// Types.
|
//// Types.
|
||||||
|
|
||||||
#define MPMasterKeySize 64
|
#define MPMasterKeySize 64 /* bytes */
|
||||||
typedef const uint8_t *MPMasterKey;
|
typedef const uint8_t *MPMasterKey;
|
||||||
#define MPSiteKeySize 256 / 8 // Bytes in HMAC-SHA-256
|
#define MPSiteKeySize (256 / 8) /* bytes */ // Size of HMAC-SHA-256
|
||||||
typedef const uint8_t *MPSiteKey;
|
typedef const uint8_t *MPSiteKey;
|
||||||
typedef const char *MPKeyID;
|
typedef const char *MPKeyID;
|
||||||
|
|
||||||
typedef enum( unsigned int, MPKeyPurpose ) {
|
typedef enum( uint8_t, MPKeyPurpose ) {
|
||||||
/** Generate a key for authentication. */
|
/** Generate a key for authentication. */
|
||||||
MPKeyPurposeAuthentication,
|
MPKeyPurposeAuthentication,
|
||||||
/** Generate a name for identification. */
|
/** Generate a name for identification. */
|
||||||
@ -46,21 +46,24 @@ typedef enum( unsigned int, MPKeyPurpose ) {
|
|||||||
MPKeyPurposeRecovery,
|
MPKeyPurposeRecovery,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum( unsigned int, MPPasswordTypeClass ) {
|
// bit 4 - 9
|
||||||
|
typedef enum( uint16_t, MPPasswordTypeClass ) {
|
||||||
/** Generate the password. */
|
/** Generate the password. */
|
||||||
MPPasswordTypeClassGenerated = 1 << 4,
|
MPPasswordTypeClassGenerated = 1 << 4,
|
||||||
/** Store the password. */
|
/** Store the password. */
|
||||||
MPPasswordTypeClassStored = 1 << 5,
|
MPPasswordTypeClassStored = 1 << 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum( unsigned int, MPSiteFeature ) {
|
// bit 10 - 15
|
||||||
|
typedef enum( uint16_t, MPSiteFeature ) {
|
||||||
/** Export the key-protected content data. */
|
/** Export the key-protected content data. */
|
||||||
MPSiteFeatureExportContent = 1 << 10,
|
MPSiteFeatureExportContent = 1 << 10,
|
||||||
/** Never export content. */
|
/** Never export content. */
|
||||||
MPSiteFeatureDevicePrivate = 1 << 11,
|
MPSiteFeatureDevicePrivate = 1 << 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum( unsigned int, MPPasswordType ) {
|
// bit 0-3 | MPPasswordTypeClass | MPSiteFeature
|
||||||
|
typedef enum( uint32_t, MPPasswordType ) {
|
||||||
/** pg^VMAUBk5x3p%HP%i4= */
|
/** pg^VMAUBk5x3p%HP%i4= */
|
||||||
MPPasswordTypeGeneratedMaximum = 0x0 | MPPasswordTypeClassGenerated | 0x0,
|
MPPasswordTypeGeneratedMaximum = 0x0 | MPPasswordTypeClassGenerated | 0x0,
|
||||||
/** BiroYena8:Kixa */
|
/** BiroYena8:Kixa */
|
||||||
@ -86,6 +89,17 @@ typedef enum( unsigned int, MPPasswordType ) {
|
|||||||
MPPasswordTypeDefault = MPPasswordTypeGeneratedLong,
|
MPPasswordTypeDefault = MPPasswordTypeGeneratedLong,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum ( uint32_t, MPCounterValue ) {
|
||||||
|
/** Use a time-based counter value, resulting in a TOTP generator. */
|
||||||
|
MPCounterValueTOTP = 0,
|
||||||
|
/** The initial value for a site's counter. */
|
||||||
|
MPCounterValueInitial = 1,
|
||||||
|
|
||||||
|
MPCounterValueDefault = MPCounterValueInitial,
|
||||||
|
MPCounterValueFirst = MPCounterValueTOTP,
|
||||||
|
MPCounterValueLast = UINT32_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
//// Type utilities.
|
//// Type utilities.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,7 +49,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
const char *fullName = "Robert Lee Mitchel";
|
const char *fullName = "Robert Lee Mitchel";
|
||||||
const char *masterPassword = "banana colored duckling";
|
const char *masterPassword = "banana colored duckling";
|
||||||
const char *siteName = "masterpasswordapp.com";
|
const char *siteName = "masterpasswordapp.com";
|
||||||
const uint32_t siteCounter = 1;
|
const MPCounterValue siteCounter = MPCounterValueDefault;
|
||||||
const MPPasswordType passwordType = MPPasswordTypeDefault;
|
const MPPasswordType passwordType = MPPasswordTypeDefault;
|
||||||
const MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
|
const MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
|
||||||
const char *keyContext = NULL;
|
const char *keyContext = NULL;
|
||||||
|
@ -22,45 +22,50 @@
|
|||||||
static void usage() {
|
static void usage() {
|
||||||
|
|
||||||
inf( ""
|
inf( ""
|
||||||
"Usage: mpw [-u|-U name] [-t type] [-c counter] [-a algorithm] [-p purpose]"
|
"Usage:\n"
|
||||||
" [-C context] [-f|-F format] [-R 0|1] [-v|-q] [-h] site-name\n\n" );
|
" mpw [-u|-U full-name] [-t pw-type] [-c counter] [-a algorithm] [-s value]\n"
|
||||||
|
" [-p purpose] [-C context] [-f|-F format] [-R 0|1] [-v|-q] [-h] site-name\n\n" );
|
||||||
inf( ""
|
inf( ""
|
||||||
" -u name Specify the full name of the user.\n"
|
" -u full-name Specify the full name of the user.\n"
|
||||||
" -u checks the master password against the config,"
|
" -u checks the master password against the config,\n"
|
||||||
" -U allows updating to a new master password.\n"
|
" -U allows updating to a new master password.\n"
|
||||||
" Defaults to %s in env or prompts.\n\n", MP_env_fullName );
|
" Defaults to %s in env or prompts.\n\n", MP_env_fullName );
|
||||||
inf( ""
|
inf( ""
|
||||||
" -t type Specify the password's template.\n"
|
" -t pw-type Specify the password's template.\n"
|
||||||
" Defaults to 'long' (auth), 'name' (ident) or 'phrase'(recovery).\n"
|
" Defaults to 'long' (-p a), 'name' (-p i) or 'phrase' (-p r).\n"
|
||||||
" x, max, maximum | 20 characters, contains symbols.\n"
|
" x, maximum | 20 characters, contains symbols.\n"
|
||||||
" l, long | Copy-friendly, 14 characters, symbols.\n"
|
" l, long | Copy-friendly, 14 characters, symbols.\n"
|
||||||
" m, med, medium | Copy-friendly, 8 characters, symbols.\n"
|
" m, medium | Copy-friendly, 8 characters, symbols.\n"
|
||||||
" b, basic | 8 characters, no symbols.\n"
|
" b, basic | 8 characters, no symbols.\n"
|
||||||
" s, short | Copy-friendly, 4 characters, no symbols.\n"
|
" s, short | Copy-friendly, 4 characters, no symbols.\n"
|
||||||
" i, pin | 4 numbers.\n"
|
" i, pin | 4 numbers.\n"
|
||||||
" n, name | 9 letter name.\n"
|
" n, name | 9 letter name.\n"
|
||||||
" p, phrase | 20 character sentence.\n\n" );
|
" p, phrase | 20 character sentence.\n"
|
||||||
|
" P, personal | saved personal password (see -s).\n\n" );
|
||||||
inf( ""
|
inf( ""
|
||||||
" -c counter The value of the counter.\n"
|
" -c counter The value of the counter.\n"
|
||||||
" Defaults to 1.\n\n" );
|
" Defaults to 1.\n\n" );
|
||||||
inf( ""
|
inf( ""
|
||||||
" -a version The algorithm version to use.\n"
|
" -a version The algorithm version to use, %d - %d.\n"
|
||||||
" Defaults to %s in env or %d.\n\n", MP_env_algorithm, MPAlgorithmVersionCurrent );
|
" Defaults to %s in env or %d.\n\n",
|
||||||
|
MPAlgorithmVersionFirst, MPAlgorithmVersionLast, MP_env_algorithm, MPAlgorithmVersionCurrent );
|
||||||
|
inf( ""
|
||||||
|
" -s value The value to save for -t P or -p i.\n\n" );
|
||||||
inf( ""
|
inf( ""
|
||||||
" -p purpose The purpose of the generated token.\n"
|
" -p purpose The purpose of the generated token.\n"
|
||||||
" Defaults to 'password'.\n"
|
" Defaults to 'auth'.\n"
|
||||||
" a, auth | An authentication token such as a password.\n"
|
" a, auth | An authentication token such as a password.\n"
|
||||||
" i, ident | An identification token such as a username.\n"
|
" i, ident | An identification token such as a username.\n"
|
||||||
" r, rec | A recovery token such as a security answer.\n\n" );
|
" r, rec | A recovery token such as a security answer.\n\n" );
|
||||||
inf( ""
|
inf( ""
|
||||||
" -C context A purpose-specific context.\n"
|
" -C context A purpose-specific context.\n"
|
||||||
" Defaults to empty.\n"
|
" Defaults to empty.\n"
|
||||||
" -p a, auth | -\n"
|
" -p a | -\n"
|
||||||
" -p i, ident | -\n"
|
" -p i | -\n"
|
||||||
" -p r, rec | Most significant word in security question.\n\n" );
|
" -p r | Most significant word in security question.\n\n" );
|
||||||
inf( ""
|
inf( ""
|
||||||
" -f|F format The mpsites format to use for reading/writing site parameters.\n"
|
" -f|F format The mpsites format to use for reading/writing site parameters.\n"
|
||||||
" -F forces the use of the given format,"
|
" -F forces the use of the given format,\n"
|
||||||
" -f allows fallback/migration.\n"
|
" -f allows fallback/migration.\n"
|
||||||
" Defaults to json, falls back to plain.\n"
|
" Defaults to json, falls back to plain.\n"
|
||||||
" f, flat | ~/.mpw.d/Full Name.%s\n"
|
" f, flat | ~/.mpw.d/Full Name.%s\n"
|
||||||
@ -80,6 +85,40 @@ static void usage() {
|
|||||||
exit( 0 );
|
exit( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *mpw_getenv(const char *variableName) {
|
||||||
|
|
||||||
|
char *envBuf = getenv( variableName );
|
||||||
|
return envBuf? strdup( envBuf ): NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *mpw_getline(const char *prompt) {
|
||||||
|
|
||||||
|
fprintf( stderr, "%s ", prompt );
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
size_t bufSize = 0;
|
||||||
|
ssize_t lineSize = getline( &buf, &bufSize, stdin );
|
||||||
|
if (lineSize <= 1) {
|
||||||
|
free( buf );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the newline.
|
||||||
|
buf[lineSize - 1] = '\0';
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *mpw_getpass(const char *prompt) {
|
||||||
|
|
||||||
|
char *passBuf = getpass( prompt );
|
||||||
|
if (!passBuf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char *buf = strdup( passBuf );
|
||||||
|
bzero( passBuf, strlen( passBuf ) );
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
static char *mpw_path(const char *prefix, const char *extension) {
|
static char *mpw_path(const char *prefix, const char *extension) {
|
||||||
|
|
||||||
char *homedir = NULL;
|
char *homedir = NULL;
|
||||||
@ -102,39 +141,11 @@ static char *mpw_path(const char *prefix, const char *extension) {
|
|||||||
return mpwPath;
|
return mpwPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *mpw_getline(const char *prompt) {
|
|
||||||
|
|
||||||
fprintf( stderr, "%s ", prompt );
|
|
||||||
|
|
||||||
char *buf = NULL;
|
|
||||||
size_t bufSize = 0;
|
|
||||||
ssize_t lineSize = getline( &buf, &bufSize, stdin );
|
|
||||||
if (lineSize <= 1) {
|
|
||||||
free( buf );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the newline.
|
|
||||||
buf[lineSize - 1] = '\0';
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *mpw_getpass(const char *prompt) {
|
|
||||||
|
|
||||||
char *passBuf = getpass( prompt );
|
|
||||||
if (!passBuf)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
char *buf = strdup( passBuf );
|
|
||||||
bzero( passBuf, strlen( passBuf ) );
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *const argv[]) {
|
int main(int argc, char *const argv[]) {
|
||||||
|
|
||||||
// Master Password defaults.
|
// Master Password defaults.
|
||||||
const char *fullName = NULL, *masterPassword = NULL, *siteName = NULL, *keyContext = NULL;
|
const char *fullName = NULL, *masterPassword = NULL, *siteName = NULL, *saveValue = NULL, *keyContext = NULL;
|
||||||
uint32_t siteCounter = 1;
|
MPCounterValue siteCounter = MPCounterValueDefault;
|
||||||
MPPasswordType passwordType = MPPasswordTypeDefault;
|
MPPasswordType passwordType = MPPasswordTypeDefault;
|
||||||
MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
|
MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
|
||||||
MPAlgorithmVersion algorithmVersion = MPAlgorithmVersionCurrent;
|
MPAlgorithmVersion algorithmVersion = MPAlgorithmVersionCurrent;
|
||||||
@ -142,50 +153,55 @@ int main(int argc, char *const argv[]) {
|
|||||||
bool allowPasswordUpdate = false, sitesFormatFixed = false, sitesRedacted = true;
|
bool allowPasswordUpdate = false, sitesFormatFixed = false, sitesRedacted = true;
|
||||||
|
|
||||||
// Read the environment.
|
// Read the environment.
|
||||||
const char *fullNameArg = getenv( MP_env_fullName ), *masterPasswordArg = NULL, *siteNameArg = NULL;
|
const char *fullNameArg = NULL, *masterPasswordArg = NULL, *siteNameArg = NULL;
|
||||||
const char *passwordTypeArg = NULL, *siteCounterArg = NULL, *algorithmVersionArg = getenv( MP_env_algorithm );
|
const char *passwordTypeArg = NULL, *siteCounterArg = NULL, *algorithmVersionArg = NULL, *saveValueArg = NULL;
|
||||||
const char *keyPurposeArg = NULL, *keyContextArg = NULL, *sitesFormatArg = NULL, *sitesRedactedArg = NULL;
|
const char *keyPurposeArg = NULL, *keyContextArg = NULL, *sitesFormatArg = NULL, *sitesRedactedArg = NULL;
|
||||||
|
fullNameArg = mpw_getenv( MP_env_fullName );
|
||||||
|
algorithmVersionArg = mpw_getenv( MP_env_algorithm );
|
||||||
|
|
||||||
// Read the command-line options.
|
// Read the command-line options.
|
||||||
for (int opt; (opt = getopt( argc, argv, "u:U:P:t:c:a:p:C:f:F:R:vqh" )) != EOF;)
|
for (int opt; (opt = getopt( argc, argv, "u:U:P:t:c:a:s:p:C:f:F:R:vqh" )) != EOF;)
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'u':
|
case 'u':
|
||||||
fullNameArg = optarg;
|
fullNameArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
allowPasswordUpdate = false;
|
allowPasswordUpdate = false;
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
fullNameArg = optarg;
|
fullNameArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
allowPasswordUpdate = true;
|
allowPasswordUpdate = true;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
// Passing your master password via the command-line is insecure. Testing purposes only.
|
// Passing your master password via the command-line is insecure. Testing purposes only.
|
||||||
masterPasswordArg = optarg;
|
masterPasswordArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
passwordTypeArg = optarg;
|
passwordTypeArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
siteCounterArg = optarg;
|
siteCounterArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
algorithmVersionArg = optarg;
|
algorithmVersionArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
saveValueArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
keyPurposeArg = optarg;
|
keyPurposeArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
keyContextArg = optarg;
|
keyContextArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
sitesFormatArg = optarg;
|
sitesFormatArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
sitesFormatFixed = false;
|
sitesFormatFixed = false;
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
sitesFormatArg = optarg;
|
sitesFormatArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
sitesFormatFixed = true;
|
sitesFormatFixed = true;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
sitesRedactedArg = optarg;
|
sitesRedactedArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
++mpw_verbosity;
|
++mpw_verbosity;
|
||||||
@ -216,19 +232,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
return EX_USAGE;
|
return EX_USAGE;
|
||||||
}
|
}
|
||||||
if (optind < argc)
|
if (optind < argc)
|
||||||
siteNameArg = argv[optind];
|
siteNameArg = strdup( argv[optind] );
|
||||||
|
|
||||||
// Empty strings unset the argument.
|
|
||||||
fullNameArg = fullNameArg && strlen( fullNameArg )? fullNameArg: NULL;
|
|
||||||
masterPasswordArg = masterPasswordArg && strlen( masterPasswordArg )? masterPasswordArg: NULL;
|
|
||||||
passwordTypeArg = passwordTypeArg && strlen( passwordTypeArg )? passwordTypeArg: NULL;
|
|
||||||
siteCounterArg = siteCounterArg && strlen( siteCounterArg )? siteCounterArg: NULL;
|
|
||||||
algorithmVersionArg = algorithmVersionArg && strlen( algorithmVersionArg )? algorithmVersionArg: NULL;
|
|
||||||
keyPurposeArg = keyPurposeArg && strlen( keyPurposeArg )? keyPurposeArg: NULL;
|
|
||||||
keyContextArg = keyContextArg && strlen( keyContextArg )? keyContextArg: NULL;
|
|
||||||
sitesFormatArg = sitesFormatArg && strlen( sitesFormatArg )? sitesFormatArg: NULL;
|
|
||||||
sitesRedactedArg = sitesRedactedArg && strlen( sitesRedactedArg )? sitesRedactedArg: NULL;
|
|
||||||
siteNameArg = siteNameArg && strlen( siteNameArg )? siteNameArg: NULL;
|
|
||||||
|
|
||||||
// Determine fullName, siteName & masterPassword.
|
// Determine fullName, siteName & masterPassword.
|
||||||
if (!(fullNameArg && (fullName = strdup( fullNameArg ))) &&
|
if (!(fullNameArg && (fullName = strdup( fullNameArg ))) &&
|
||||||
@ -246,7 +250,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
masterPassword = mpw_getpass( "Your master password: " );
|
masterPassword = mpw_getpass( "Your master password: " );
|
||||||
if (sitesFormatArg) {
|
if (sitesFormatArg) {
|
||||||
sitesFormat = mpw_formatWithName( sitesFormatArg );
|
sitesFormat = mpw_formatWithName( sitesFormatArg );
|
||||||
if (ERR == sitesFormat) {
|
if (ERR == (int)sitesFormat) {
|
||||||
ftl( "Invalid sites format: %s\n", sitesFormatArg );
|
ftl( "Invalid sites format: %s\n", sitesFormatArg );
|
||||||
return EX_USAGE;
|
return EX_USAGE;
|
||||||
}
|
}
|
||||||
@ -304,7 +308,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
inf( "Given master password does not match configuration.\n" );
|
inf( "Given master password does not match configuration.\n" );
|
||||||
inf( "To update the configuration with this new master password, first confirm the old master password.\n" );
|
inf( "To update the configuration with this new master password, first confirm the old master password.\n" );
|
||||||
|
|
||||||
char *importMasterPassword = NULL;
|
const char *importMasterPassword = NULL;
|
||||||
while (!importMasterPassword || !strlen( importMasterPassword ))
|
while (!importMasterPassword || !strlen( importMasterPassword ))
|
||||||
importMasterPassword = mpw_getpass( "Old master password: " );
|
importMasterPassword = mpw_getpass( "Old master password: " );
|
||||||
|
|
||||||
@ -345,6 +349,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mpw_free_string( saveValue );
|
||||||
passwordType = site->type;
|
passwordType = site->type;
|
||||||
siteCounter = site->counter;
|
siteCounter = site->counter;
|
||||||
algorithmVersion = site->algorithm;
|
algorithmVersion = site->algorithm;
|
||||||
@ -358,11 +363,11 @@ int main(int argc, char *const argv[]) {
|
|||||||
sitesRedacted = strcmp( sitesRedactedArg, "1" ) == 0;
|
sitesRedacted = strcmp( sitesRedactedArg, "1" ) == 0;
|
||||||
if (siteCounterArg) {
|
if (siteCounterArg) {
|
||||||
long long int siteCounterInt = atoll( siteCounterArg );
|
long long int siteCounterInt = atoll( siteCounterArg );
|
||||||
if (siteCounterInt < 0 || siteCounterInt > UINT32_MAX) {
|
if (siteCounterInt < MPCounterValueFirst || siteCounterInt > MPCounterValueLast) {
|
||||||
ftl( "Invalid site counter: %s\n", siteCounterArg );
|
ftl( "Invalid site counter: %s\n", siteCounterArg );
|
||||||
return EX_USAGE;
|
return EX_USAGE;
|
||||||
}
|
}
|
||||||
siteCounter = (uint32_t)siteCounterInt;
|
siteCounter = (MPCounterValue)siteCounterInt;
|
||||||
}
|
}
|
||||||
if (algorithmVersionArg) {
|
if (algorithmVersionArg) {
|
||||||
int algorithmVersionInt = atoi( algorithmVersionArg );
|
int algorithmVersionInt = atoi( algorithmVersionArg );
|
||||||
@ -372,9 +377,13 @@ int main(int argc, char *const argv[]) {
|
|||||||
}
|
}
|
||||||
algorithmVersion = (MPAlgorithmVersion)algorithmVersionInt;
|
algorithmVersion = (MPAlgorithmVersion)algorithmVersionInt;
|
||||||
}
|
}
|
||||||
|
if (saveValueArg) {
|
||||||
|
mpw_free_string( saveValue );
|
||||||
|
saveValue = strdup( saveValueArg );
|
||||||
|
}
|
||||||
if (keyPurposeArg) {
|
if (keyPurposeArg) {
|
||||||
keyPurpose = mpw_purposeWithName( keyPurposeArg );
|
keyPurpose = mpw_purposeWithName( keyPurposeArg );
|
||||||
if (ERR == keyPurpose) {
|
if (ERR == (int)keyPurpose) {
|
||||||
ftl( "Invalid purpose: %s\n", keyPurposeArg );
|
ftl( "Invalid purpose: %s\n", keyPurposeArg );
|
||||||
return EX_USAGE;
|
return EX_USAGE;
|
||||||
}
|
}
|
||||||
@ -396,13 +405,26 @@ int main(int argc, char *const argv[]) {
|
|||||||
}
|
}
|
||||||
if (passwordTypeArg) {
|
if (passwordTypeArg) {
|
||||||
passwordType = mpw_typeWithName( passwordTypeArg );
|
passwordType = mpw_typeWithName( passwordTypeArg );
|
||||||
if (ERR == passwordType) {
|
if (ERR == (int)passwordType) {
|
||||||
ftl( "Invalid type: %s\n", passwordTypeArg );
|
ftl( "Invalid type: %s\n", passwordTypeArg );
|
||||||
return EX_USAGE;
|
return EX_USAGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (keyContextArg)
|
if (keyContextArg) {
|
||||||
|
mpw_free_string( keyContext );
|
||||||
keyContext = strdup( keyContextArg );
|
keyContext = strdup( keyContextArg );
|
||||||
|
}
|
||||||
|
mpw_free_string( fullNameArg );
|
||||||
|
mpw_free_string( masterPasswordArg );
|
||||||
|
mpw_free_string( siteNameArg );
|
||||||
|
mpw_free_string( passwordTypeArg );
|
||||||
|
mpw_free_string( siteCounterArg );
|
||||||
|
mpw_free_string( algorithmVersionArg );
|
||||||
|
mpw_free_string( saveValueArg );
|
||||||
|
mpw_free_string( keyPurposeArg );
|
||||||
|
mpw_free_string( keyContextArg );
|
||||||
|
mpw_free_string( sitesFormatArg );
|
||||||
|
mpw_free_string( sitesRedactedArg );
|
||||||
|
|
||||||
// Operation summary.
|
// Operation summary.
|
||||||
const char *identicon = mpw_identicon( fullName, masterPassword );
|
const char *identicon = mpw_identicon( fullName, masterPassword );
|
||||||
@ -416,6 +438,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
dbg( "sitesPath : %s\n", sitesPath );
|
dbg( "sitesPath : %s\n", sitesPath );
|
||||||
dbg( "siteName : %s\n", siteName );
|
dbg( "siteName : %s\n", siteName );
|
||||||
dbg( "siteCounter : %u\n", siteCounter );
|
dbg( "siteCounter : %u\n", siteCounter );
|
||||||
|
dbg( "saveValue : %s\n", saveValue );
|
||||||
dbg( "keyPurpose : %s (%u)\n", mpw_nameForPurpose( keyPurpose ), keyPurpose );
|
dbg( "keyPurpose : %s (%u)\n", mpw_nameForPurpose( keyPurpose ), keyPurpose );
|
||||||
dbg( "keyContext : %s\n", keyContext );
|
dbg( "keyContext : %s\n", keyContext );
|
||||||
dbg( "passwordType : %s (%u)\n", mpw_nameForType( passwordType ), passwordType );
|
dbg( "passwordType : %s (%u)\n", mpw_nameForType( passwordType ), passwordType );
|
||||||
@ -453,25 +476,42 @@ int main(int argc, char *const argv[]) {
|
|||||||
fprintf( stdout, "%s\n", sitePassword );
|
fprintf( stdout, "%s\n", sitePassword );
|
||||||
mpw_free_string( sitePassword );
|
mpw_free_string( sitePassword );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
const char *content = NULL;
|
||||||
|
if (saveValue) {
|
||||||
|
content = strdup( saveValue );
|
||||||
|
if (site) {
|
||||||
|
// TODO: Doesn't save content for newly created sites.
|
||||||
|
mpw_free_string( site->content );
|
||||||
|
if (!(site->content = mpw_encrypt( masterKey, saveValue, algorithmVersion )))
|
||||||
|
err( "Couldn't encrypt site content.\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else if (site && site->content) {
|
else if (site && site->content) {
|
||||||
const char *sitePassword = mpw_decrypt( masterKey, site->content, algorithmVersion );
|
content = mpw_decrypt( masterKey, site->content, algorithmVersion );
|
||||||
if (!sitePassword) {
|
if (!content) {
|
||||||
ftl( "Couldn't decrypt site password.\n" );
|
ftl( "Couldn't decrypt site content.\n" );
|
||||||
mpw_free( masterKey, MPMasterKeySize );
|
mpw_free( masterKey, MPMasterKeySize );
|
||||||
return EX_SOFTWARE;
|
return EX_SOFTWARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf( stdout, "%s\n", sitePassword );
|
|
||||||
mpw_free_string( sitePassword );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf( stdout, "%s\n", content );
|
||||||
|
mpw_free_string( content );
|
||||||
|
}
|
||||||
|
|
||||||
if (site && site->url)
|
if (site && site->url)
|
||||||
inf( "See: %s\n", site->url );
|
inf( "See: %s\n", site->url );
|
||||||
mpw_free( masterKey, MPMasterKeySize );
|
mpw_free( masterKey, MPMasterKeySize );
|
||||||
mpw_free_string( siteName );
|
mpw_free_string( siteName );
|
||||||
|
mpw_free_string( saveValue );
|
||||||
mpw_free_string( keyContext );
|
mpw_free_string( keyContext );
|
||||||
|
|
||||||
// Update the mpsites file.
|
// Update the mpsites file.
|
||||||
if (user) {
|
if (user) {
|
||||||
|
// TODO: Move this up above the summary and replace the mpw lvars by user/site accessors.
|
||||||
if (keyPurpose == MPKeyPurposeAuthentication) {
|
if (keyPurpose == MPKeyPurposeAuthentication) {
|
||||||
if (!site)
|
if (!site)
|
||||||
site = mpw_marshall_site( user, siteName, passwordType, siteCounter, algorithmVersion );
|
site = mpw_marshall_site( user, siteName, passwordType, siteCounter, algorithmVersion );
|
||||||
|
@ -29,7 +29,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
xmlChar *masterPassword = mpw_xmlTestCaseString( testCase, "masterPassword" );
|
xmlChar *masterPassword = mpw_xmlTestCaseString( testCase, "masterPassword" );
|
||||||
xmlChar *keyID = mpw_xmlTestCaseString( testCase, "keyID" );
|
xmlChar *keyID = mpw_xmlTestCaseString( testCase, "keyID" );
|
||||||
xmlChar *siteName = mpw_xmlTestCaseString( testCase, "siteName" );
|
xmlChar *siteName = mpw_xmlTestCaseString( testCase, "siteName" );
|
||||||
uint32_t siteCounter = mpw_xmlTestCaseInteger( testCase, "siteCounter" );
|
MPCounterValue siteCounter = (MPCounterValue)mpw_xmlTestCaseInteger( testCase, "siteCounter" );
|
||||||
xmlChar *passwordTypeString = mpw_xmlTestCaseString( testCase, "passwordType" );
|
xmlChar *passwordTypeString = mpw_xmlTestCaseString( testCase, "passwordType" );
|
||||||
xmlChar *keyPurposeString = mpw_xmlTestCaseString( testCase, "keyPurpose" );
|
xmlChar *keyPurposeString = mpw_xmlTestCaseString( testCase, "keyPurpose" );
|
||||||
xmlChar *keyContext = mpw_xmlTestCaseString( testCase, "keyContext" );
|
xmlChar *keyContext = mpw_xmlTestCaseString( testCase, "keyContext" );
|
||||||
|
Loading…
Reference in New Issue
Block a user