WIP performing marshalling of sites in C.
This commit is contained in:
parent
738ad197b2
commit
560cb1a266
@ -27,7 +27,7 @@
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) {
|
||||
MPMasterKey mpw_masterKeyForUser(const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
if (!fullName || !masterPassword)
|
||||
return NULL;
|
||||
@ -47,7 +47,7 @@ const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPass
|
||||
}
|
||||
}
|
||||
|
||||
const char *mpw_passwordForSite(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const char *mpw_passwordForSite(MPMasterKey masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
if (!masterKey || !siteName)
|
||||
|
@ -19,7 +19,10 @@
|
||||
// NOTE: mpw is currently NOT thread-safe.
|
||||
#include "mpw-types.h"
|
||||
|
||||
typedef enum(unsigned int, MPAlgorithmVersion) {
|
||||
#ifndef _MPW_ALGORITHM_H
|
||||
#define _MPW_ALGORITHM_H
|
||||
|
||||
typedef enum( unsigned int, MPAlgorithmVersion ) {
|
||||
/** V0 did math with chars whose signedness was platform-dependent. */
|
||||
MPAlgorithmVersion0,
|
||||
/** V1 miscounted the byte-length of multi-byte site names. */
|
||||
@ -28,16 +31,20 @@ typedef enum(unsigned int, MPAlgorithmVersion) {
|
||||
MPAlgorithmVersion2,
|
||||
/** V3 is the current version. */
|
||||
MPAlgorithmVersion3,
|
||||
|
||||
MPAlgorithmVersionCurrent = MPAlgorithmVersion3,
|
||||
MPAlgorithmVersionLatest = MPAlgorithmVersion3,
|
||||
};
|
||||
#define MPAlgorithmVersionCurrent MPAlgorithmVersion3
|
||||
|
||||
/** Derive the master key for a user based on their name and master password.
|
||||
* @return A new MP_dkLen-byte allocated buffer or NULL if an allocation error occurred. */
|
||||
const uint8_t *mpw_masterKeyForUser(
|
||||
MPMasterKey mpw_masterKeyForUser(
|
||||
const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion);
|
||||
|
||||
/** Encode a password for the site from the given master key and site parameters.
|
||||
* @return A newly allocated string or NULL if an allocation error occurred. */
|
||||
const char *mpw_passwordForSite(
|
||||
const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
MPMasterKey masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext, const MPAlgorithmVersion algorithmVersion);
|
||||
|
||||
#endif // _MPW_ALGORITHM_H
|
||||
|
@ -43,7 +43,7 @@ static const char mpw_characterFromClass_v0(char characterClass, uint16_t seedBy
|
||||
return classCharacters[seedByte % strlen( classCharacters )];
|
||||
}
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v0(const char *fullName, const char *masterPassword) {
|
||||
static MPMasterKey mpw_masterKeyForUser_v0(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "algorithm: v%d\n", 0 );
|
||||
@ -66,18 +66,18 @@ static const uint8_t *mpw_masterKeyForUser_v0(const char *fullName, const char *
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
const uint8_t *masterKey = mpw_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MP_dkLen ) );
|
||||
trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v0(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
static const char *mpw_passwordForSite_v0(MPMasterKey masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
@ -110,7 +110,7 @@ static const char *mpw_passwordForSite_v0(const uint8_t *masterKey, const char *
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_id_buf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const char *sitePasswordSeed = (const char *)mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
const char *sitePasswordSeed = (const char *)mpw_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
|
@ -28,7 +28,7 @@
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v1(const char *fullName, const char *masterPassword) {
|
||||
static MPMasterKey mpw_masterKeyForUser_v1(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "algorithm: v%d\n", 1 );
|
||||
@ -51,18 +51,18 @@ static const uint8_t *mpw_masterKeyForUser_v1(const char *fullName, const char *
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
MPMasterKey masterKey = mpw_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MP_dkLen ) );
|
||||
trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v1(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
static const char *mpw_passwordForSite_v1(MPMasterKey masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
@ -95,7 +95,7 @@ static const char *mpw_passwordForSite_v1(const uint8_t *masterKey, const char *
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_id_buf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
|
@ -28,7 +28,7 @@
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v2(const char *fullName, const char *masterPassword) {
|
||||
static MPMasterKey mpw_masterKeyForUser_v2(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "algorithm: v%d\n", 2 );
|
||||
@ -51,18 +51,18 @@ static const uint8_t *mpw_masterKeyForUser_v2(const char *fullName, const char *
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
const uint8_t *masterKey = mpw_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MP_dkLen ) );
|
||||
trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v2(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
static const char *mpw_passwordForSite_v2(MPMasterKey masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
@ -95,7 +95,7 @@ static const char *mpw_passwordForSite_v2(const uint8_t *masterKey, const char *
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_id_buf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
|
@ -28,7 +28,7 @@
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v3(const char *fullName, const char *masterPassword) {
|
||||
static MPMasterKey mpw_masterKeyForUser_v3(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "algorithm: v%d\n", 3 );
|
||||
@ -51,18 +51,18 @@ static const uint8_t *mpw_masterKeyForUser_v3(const char *fullName, const char *
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
const uint8_t *masterKey = mpw_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MP_dkLen ) );
|
||||
trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v3(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
static const char *mpw_passwordForSite_v3(MPMasterKey masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
@ -95,7 +95,7 @@ static const char *mpw_passwordForSite_v3(const uint8_t *masterKey, const char *
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_id_buf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
|
522
core/c/mpw-marshall.c
Normal file
522
core/c/mpw-marshall.c
Normal file
@ -0,0 +1,522 @@
|
||||
//==============================================================================
|
||||
// This file is part of Master Password.
|
||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||
//
|
||||
// Master Password is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Master Password is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You can find a copy of the GNU General Public License in the
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <json-c/json.h>
|
||||
#include "mpw-marshall.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
MPMarshalledUser mpw_marshall_user(
|
||||
const char *fullName, MPMasterKey masterKey, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
return (MPMarshalledUser){
|
||||
.name = fullName,
|
||||
.key = masterKey,
|
||||
.version = algorithmVersion,
|
||||
|
||||
.avatar = 0,
|
||||
.defaultType = MPSiteTypeGeneratedLong,
|
||||
.lastUsed = 0,
|
||||
|
||||
.sites_count = 0,
|
||||
.sites = NULL,
|
||||
};
|
||||
};
|
||||
|
||||
MPMarshalledSite mpw_marshall_site(
|
||||
MPMarshalledUser *marshalledUser,
|
||||
const char *siteName, const MPSiteType siteType, const uint32_t siteCounter, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
marshalledUser->sites = realloc( marshalledUser->sites, marshalledUser->sites_count + 1 );
|
||||
return marshalledUser->sites[marshalledUser->sites_count++] = (MPMarshalledSite){
|
||||
.name = siteName,
|
||||
.type = siteType,
|
||||
.counter = siteCounter,
|
||||
.version = algorithmVersion,
|
||||
|
||||
.loginName = NULL,
|
||||
.loginGenerated = 0,
|
||||
|
||||
.url = NULL,
|
||||
.uses = 0,
|
||||
.lastUsed = 0,
|
||||
|
||||
.questions_count = 0,
|
||||
.questions = NULL,
|
||||
};
|
||||
};
|
||||
|
||||
MPMarshalledQuestion mpw_marshal_question(
|
||||
MPMarshalledSite *marshalledSite, const char *keyword) {
|
||||
|
||||
marshalledSite->questions = realloc( marshalledSite->questions, marshalledSite->questions_count + 1 );
|
||||
return marshalledSite->questions[marshalledSite->questions_count++] = (MPMarshalledQuestion){
|
||||
.keyword = keyword,
|
||||
};
|
||||
}
|
||||
|
||||
#define try_asprintf(...) ({ if (asprintf( __VA_ARGS__ ) < 0) return false; })
|
||||
|
||||
bool mpw_marshall_write_flat(
|
||||
char **out, bool redacted, const MPMarshalledUser *marshalledUser) {
|
||||
|
||||
try_asprintf( out, "# Master Password site export\n" );
|
||||
if (redacted)
|
||||
try_asprintf( out, "# Export of site names and passwords in clear-text.\n" );
|
||||
else
|
||||
try_asprintf( out, "# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n" );
|
||||
try_asprintf( out, "# \n" );
|
||||
try_asprintf( out, "##\n" );
|
||||
try_asprintf( out, "# Format: %d\n", 1 );
|
||||
|
||||
size_t dateSize = 21;
|
||||
char dateString[dateSize];
|
||||
time_t now = time( NULL );
|
||||
if (strftime( dateString, dateSize, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", gmtime( &now ) ))
|
||||
try_asprintf( out, "# Date: %s\n", dateString );
|
||||
try_asprintf( out, "# User Name: %s\n", marshalledUser->name );
|
||||
try_asprintf( out, "# Full Name: %s\n", marshalledUser->name );
|
||||
try_asprintf( out, "# Avatar: %u\n", marshalledUser->avatar );
|
||||
try_asprintf( out, "# Key ID: %s\n", mpw_id_buf( marshalledUser->key, MPMasterKeySize ) );
|
||||
try_asprintf( out, "# Algorithm: %d\n", marshalledUser->version );
|
||||
try_asprintf( out, "# Default Type: %d\n", marshalledUser->defaultType );
|
||||
try_asprintf( out, "# Passwords: %s\n", redacted? "PROTECTED": "VISIBLE" );
|
||||
try_asprintf( out, "##\n" );
|
||||
try_asprintf( out, "#\n" );
|
||||
try_asprintf( out, "# Last Times Password Login\t Site\tSite\n" );
|
||||
try_asprintf( out, "# used used type name\t name\tpassword\n" );
|
||||
|
||||
// Sites.
|
||||
for (int s = 0; s < marshalledUser->sites_count; ++s) {
|
||||
MPMarshalledSite site = marshalledUser->sites[s];
|
||||
|
||||
const char *content = NULL;
|
||||
if (!redacted && site.type & MPSiteTypeClassGenerated)
|
||||
content = mpw_passwordForSite( marshalledUser->key, site.name, site.type, site.counter,
|
||||
MPSiteVariantPassword, NULL, site.version );
|
||||
// TODO: Personal Passwords
|
||||
|
||||
if (strftime( dateString, dateSize, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", gmtime( &site.lastUsed ) ))
|
||||
try_asprintf( out, "%s %8ld %lu:%lu:%lu %25s\t%25s\t%s\n",
|
||||
dateString, (long)site.uses, (long)site.type, (long)site.version, (long)site.counter,
|
||||
site.loginName?: "", site.name, content?: "" );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mpw_marshall_write_json(
|
||||
char **out, bool redacted, const MPMarshalledUser *marshalledUser) {
|
||||
|
||||
json_object *json_out = json_object_new_object();
|
||||
|
||||
// Section: "export"
|
||||
json_object *json_export = json_object_new_object();
|
||||
json_object_object_add( json_out, "export", json_export );
|
||||
json_object_object_add( json_export, "format", json_object_new_int( 1 ) );
|
||||
json_object_object_add( json_export, "redacted", json_object_new_boolean( redacted ) );
|
||||
|
||||
size_t dateSize = 21;
|
||||
char dateString[dateSize];
|
||||
time_t now = time( NULL );
|
||||
if (strftime( dateString, dateSize, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", gmtime( &now ) ))
|
||||
json_object_object_add( json_export, "date", json_object_new_string( dateString ) );
|
||||
json_object_put( json_export );
|
||||
|
||||
// Section: "user"
|
||||
json_object *json_user = json_object_new_object();
|
||||
json_object_object_add( json_out, "user", json_user );
|
||||
json_object_object_add( json_user, "avatar", json_object_new_int( marshalledUser->avatar ) );
|
||||
json_object_object_add( json_user, "full_name", json_object_new_string( marshalledUser->name ) );
|
||||
|
||||
if (strftime( dateString, dateSize, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", gmtime( &marshalledUser->lastUsed ) ))
|
||||
json_object_object_add( json_user, "last_used", json_object_new_string( dateString ) );
|
||||
json_object_object_add( json_user, "key_id", json_object_new_string( mpw_id_buf( marshalledUser->key, MPMasterKeySize ) ) );
|
||||
|
||||
json_object_object_add( json_user, "algorithm", json_object_new_int( marshalledUser->version ) );
|
||||
json_object_object_add( json_user, "default_type", json_object_new_int( marshalledUser->defaultType ) );
|
||||
json_object_put( json_user );
|
||||
|
||||
// Section "sites"
|
||||
json_object *json_sites = json_object_new_object();
|
||||
json_object_object_add( json_out, "sites", json_sites );
|
||||
for (int s = 0; s < marshalledUser->sites_count; ++s) {
|
||||
MPMarshalledSite site = marshalledUser->sites[s];
|
||||
|
||||
const char *content = site.content;
|
||||
if (!redacted && site.type & MPSiteTypeClassGenerated)
|
||||
content = mpw_passwordForSite( marshalledUser->key, site.name, site.type, site.counter,
|
||||
MPSiteVariantPassword, NULL, site.version );
|
||||
// TODO: Personal Passwords
|
||||
//else if (redacted && content)
|
||||
// content = aes128_cbc( marshalledUser->key, content );
|
||||
|
||||
json_object *json_site = json_object_new_object();
|
||||
json_object_object_add( json_sites, site.name, json_site );
|
||||
json_object_object_add( json_site, "type", json_object_new_int( site.type ) );
|
||||
json_object_object_add( json_site, "counter", json_object_new_int( site.counter ) );
|
||||
json_object_object_add( json_site, "algorithm", json_object_new_int( site.version ) );
|
||||
if (content)
|
||||
json_object_object_add( json_site, "password", json_object_new_string( content ) );
|
||||
|
||||
json_object_object_add( json_site, "login_name", json_object_new_string( site.loginName?: "" ) );
|
||||
json_object_object_add( json_site, "login_generated", json_object_new_boolean( site.loginGenerated ) );
|
||||
|
||||
json_object_object_add( json_site, "uses", json_object_new_int( site.uses ) );
|
||||
if (strftime( dateString, dateSize, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", gmtime( &site.lastUsed ) ))
|
||||
json_object_object_add( json_site, "last_used", json_object_new_string( dateString ) );
|
||||
|
||||
json_object *json_site_questions = json_object_new_object();
|
||||
json_object_object_add( json_site, "questions", json_site_questions );
|
||||
for (int q = 0; q < site.questions_count; ++q) {
|
||||
MPMarshalledQuestion question = site.questions[q];
|
||||
|
||||
json_object *json_site_question = json_object_new_object();
|
||||
json_object_object_add( json_site_questions, question.keyword, json_site_question );
|
||||
|
||||
if (!redacted)
|
||||
json_object_object_add( json_site_question, "answer", json_object_new_string(
|
||||
mpw_passwordForSite( marshalledUser->key, site.name, MPSiteTypeGeneratedPhrase, 1,
|
||||
MPSiteVariantAnswer, question.keyword, site.version ) ) );
|
||||
json_object_put( json_site_question );
|
||||
}
|
||||
json_object_put( json_site_questions );
|
||||
|
||||
json_object *json_site_mpw = json_object_new_object();
|
||||
json_object_object_add( json_site, "_ext_mpw", json_site_mpw );
|
||||
json_object_object_add( json_site_mpw, "url", json_object_new_string( site.url ) );
|
||||
json_object_put( json_site_mpw );
|
||||
json_object_put( json_site );
|
||||
}
|
||||
json_object_put( json_sites );
|
||||
|
||||
try_asprintf( out, "%s\n", json_object_to_json_string_ext( json_out, JSON_C_TO_STRING_PRETTY ) );
|
||||
json_object_put( json_out );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mpw_marshall_write(
|
||||
char **out, const MPMarshallFormat outFormat, bool redacted,
|
||||
const MPMarshalledUser *marshalledUser) {
|
||||
|
||||
switch (outFormat) {
|
||||
case MPMarshallFormatFlat:
|
||||
return mpw_marshall_write_flat( out, redacted, marshalledUser );
|
||||
case MPMarshallFormatJSON:
|
||||
return mpw_marshall_write_json( out, redacted, marshalledUser );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MPMarshalledUser mpw_marshall_read_flat(
|
||||
char *in) {
|
||||
|
||||
// // Compile patterns.
|
||||
// static NSRegularExpression *headerPattern;
|
||||
// static NSArray *sitePatterns;
|
||||
// NSError *error = NULL;
|
||||
// if (!headerPattern) {
|
||||
// headerPattern = [[NSRegularExpression alloc]
|
||||
// initWithPattern:"^#[[:space:]]*([^:]+): (.*)"
|
||||
// options:(NSRegularExpressionOptions)0 error:&error];
|
||||
// if (error) {
|
||||
// MPError( error, "Error loading the header pattern." );
|
||||
// return MPImportResultInternalError;
|
||||
// }
|
||||
// }
|
||||
// if (!sitePatterns) {
|
||||
// sitePatterns = @[
|
||||
// [[NSRegularExpression alloc] // Format 0
|
||||
// initWithPattern:"^([^ ]+) +([[:digit:]]+) +([[:digit:]]+)(:[[:digit:]]+)? +([^\t]+)\t(.*)"
|
||||
// options:(NSRegularExpressionOptions)0 error:&error],
|
||||
// [[NSRegularExpression alloc] // Format 1
|
||||
// initWithPattern:"^([^ ]+) +([[:digit:]]+) +([[:digit:]]+)(:[[:digit:]]+)?(:[[:digit:]]+)? +([^\t]*)\t *([^\t]+)\t(.*)"
|
||||
// options:(NSRegularExpressionOptions)0 error:&error]
|
||||
// ];
|
||||
// if (error) {
|
||||
// MPError( error, "Error loading the site patterns." );
|
||||
// return MPImportResultInternalError;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Parse import data.
|
||||
int importFormat = 0;
|
||||
MPMarshalledUser user;
|
||||
int importAvatar = -1;
|
||||
int importKeyID;
|
||||
char *importUserName = NULL;
|
||||
MPAlgorithmVersion importAlgorithm = MPAlgorithmVersionCurrent;
|
||||
MPSiteType importDefaultType = (MPSiteType)0;
|
||||
bool headerStarted = false, headerEnded = false, clearText = false;
|
||||
// NSMutableSet *sitesToDelete = [NSMutableSet set];
|
||||
// NSMutableArray *importedSiteSites = [NSMutableArray arrayWithCapacity:[importedSiteLines count]];
|
||||
// NSFetchRequest *siteFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
|
||||
// for (NSString *importedSiteLine in importedSiteLines) {
|
||||
|
||||
// if ([importedSiteLine hasPrefix:"#"]) {
|
||||
// // Comment or header
|
||||
// if (!headerStarted) {
|
||||
// if ([importedSiteLine isEqualToString:"##"])
|
||||
// headerStarted = YES;
|
||||
// continue;
|
||||
// }
|
||||
// if (headerEnded)
|
||||
// continue;
|
||||
// if ([importedSiteLine isEqualToString:"##"]) {
|
||||
// headerEnded = YES;
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// // Header
|
||||
// if ([headerPattern numberOfMatchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
// range:NSMakeRange( 0, [importedSiteLine length] )] != 1) {
|
||||
// err( "Invalid header format in line: %", importedSiteLine );
|
||||
// return MPImportResultMalformedInput;
|
||||
// }
|
||||
// NSTextCheckingResult *headerSites = [[headerPattern matchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
// range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
|
||||
// NSString *headerName = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:1]];
|
||||
// NSString *headerValue = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:2]];
|
||||
//
|
||||
// if ([headerName isEqualToString:"Format"]) {
|
||||
// importFormat = (NSUInteger)[headerValue integerValue];
|
||||
// if (importFormat >= [sitePatterns count]) {
|
||||
// err( "Unsupported import format: %lu", (unsigned long)importFormat );
|
||||
// return MPImportResultInternalError;
|
||||
// }
|
||||
// }
|
||||
// if (([headerName isEqualToString:"User Name"] || [headerName isEqualToString:"Full Name"]) && !importUserName) {
|
||||
// importUserName = headerValue;
|
||||
//
|
||||
// NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
|
||||
// userFetchRequest.predicate = [NSPredicate predicateWithFormat:"name == %", importUserName];
|
||||
// NSArray *users = [context executeFetchRequest:userFetchRequest error:&error];
|
||||
// if (!users) {
|
||||
// MPError( error, "While looking for user: %@.", importUserName );
|
||||
// return MPImportResultInternalError;
|
||||
// }
|
||||
// if ([users count] > 1) {
|
||||
// err( "While looking for user: %@, found more than one: %lu", importUserName, (unsigned long)[users count] );
|
||||
// return MPImportResultInternalError;
|
||||
// }
|
||||
//
|
||||
// user = [users lastObject];
|
||||
// dbg( "Existing user? %", [user debugDescription] );
|
||||
// }
|
||||
// if ([headerName isEqualToString:"Avatar"])
|
||||
// importAvatar = (NSUInteger)[headerValue integerValue];
|
||||
// if ([headerName isEqualToString:"Key ID"])
|
||||
// importKeyID = [headerValue decodeHex];
|
||||
// if ([headerName isEqualToString:"Version"]) {
|
||||
// importBundleVersion = headerValue;
|
||||
// importAlgorithm = MPAlgorithmDefaultForBundleVersion( importBundleVersion );
|
||||
// }
|
||||
// if ([headerName isEqualToString:"Algorithm"])
|
||||
// importAlgorithm = MPAlgorithmForVersion( (MPAlgorithmVersion)[headerValue integerValue] );
|
||||
// if ([headerName isEqualToString:"Default Type"])
|
||||
// importDefaultType = (MPSiteType)[headerValue integerValue];
|
||||
// if ([headerName isEqualToString:"Passwords"]) {
|
||||
// if ([headerValue isEqualToString:"VISIBLE"])
|
||||
// clearText = YES;
|
||||
// }
|
||||
//
|
||||
// continue;
|
||||
// }
|
||||
// if (!headerEnded)
|
||||
// continue;
|
||||
// if (![importUserName length])
|
||||
// return MPImportResultMalformedInput;
|
||||
// if (![importedSiteLine length])
|
||||
// continue;
|
||||
//
|
||||
// // Site
|
||||
// NSRegularExpression *sitePattern = sitePatterns[importFormat];
|
||||
// if ([sitePattern numberOfMatchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
// range:NSMakeRange( 0, [importedSiteLine length] )] != 1) {
|
||||
// err( "Invalid site format in line: %", importedSiteLine );
|
||||
// return MPImportResultMalformedInput;
|
||||
// }
|
||||
// NSTextCheckingResult *siteElements = [[sitePattern matchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
// range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
|
||||
// NSString *lastUsed, *uses, *type, *version, *counter, *siteName, *loginName, *exportContent;
|
||||
// switch (importFormat) {
|
||||
// case 0:
|
||||
// lastUsed = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:1]];
|
||||
// uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
||||
// type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
||||
// version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]];
|
||||
// if ([version length])
|
||||
// version = [version substringFromIndex:1]; // Strip the leading colon.
|
||||
// counter = "";
|
||||
// loginName = "";
|
||||
// siteName = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]];
|
||||
// exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]];
|
||||
// break;
|
||||
// case 1:
|
||||
// lastUsed = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:1]];
|
||||
// uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
||||
// type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
||||
// version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]];
|
||||
// if ([version length])
|
||||
// version = [version substringFromIndex:1]; // Strip the leading colon.
|
||||
// counter = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]];
|
||||
// if ([counter length])
|
||||
// counter = [counter substringFromIndex:1]; // Strip the leading colon.
|
||||
// loginName = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]];
|
||||
// siteName = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:7]];
|
||||
// exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:8]];
|
||||
// break;
|
||||
// default:
|
||||
// err( "Unexpected import format: %lu", (unsigned long)importFormat );
|
||||
// return MPImportResultInternalError;
|
||||
// }
|
||||
//
|
||||
// // Find existing site.
|
||||
// if (user) {
|
||||
// siteFetchRequest.predicate = [NSPredicate predicateWithFormat:"name == %@ AND user == %", siteName, user];
|
||||
// NSArray *existingSites = [context executeFetchRequest:siteFetchRequest error:&error];
|
||||
// if (!existingSites) {
|
||||
// MPError( error, "Lookup of existing sites failed for site: %@, user: %@.", siteName, user.userID );
|
||||
// return MPImportResultInternalError;
|
||||
// }
|
||||
// if ([existingSites count]) {
|
||||
// dbg( "Existing sites: %", existingSites );
|
||||
// [sitesToDelete addObjectsFromArray:existingSites];
|
||||
// }
|
||||
// }
|
||||
// [importedSiteSites addObject:@[ lastUsed, uses, type, version, counter, loginName, siteName, exportContent ]];
|
||||
// dbg( "Will import site: lastUsed=%@, uses=%@, type=%@, version=%@, counter=%@, loginName=%@, siteName=%@, exportContent=%",
|
||||
// lastUsed, uses, type, version, counter, loginName, siteName, exportContent );
|
||||
// }
|
||||
//
|
||||
// // Ask for confirmation to import these sites and the master password of the user.
|
||||
// inf( "Importing %lu sites, deleting %lu sites, for user: %", (unsigned long)[importedSiteSites count],
|
||||
// (unsigned long)[sitesToDelete count], [MPUserEntity idFor:importUserName] );
|
||||
// NSString *userMasterPassword = askUserPassword( user? user.name: importUserName, [importedSiteSites count],
|
||||
// [sitesToDelete count] );
|
||||
// if (!userMasterPassword) {
|
||||
// inf( "Import cancelled." );
|
||||
// return MPImportResultCancelled;
|
||||
// }
|
||||
// MPKey *userKey = [[MPKey alloc] initForFullName:user? user.name: importUserName withMasterPassword:userMasterPassword];
|
||||
// if (user && ![[userKey keyIDForAlgorithm:user.algorithm] isEqualToData:user.keyID])
|
||||
// return MPImportResultInvalidPassword;
|
||||
// __block MPKey *importKey = userKey;
|
||||
// if (importKeyID && ![[importKey keyIDForAlgorithm:importAlgorithm] isEqualToData:importKeyID])
|
||||
// importKey = [[MPKey alloc] initForFullName:importUserName withMasterPassword:askImportPassword( importUserName )];
|
||||
// if (importKeyID && ![[importKey keyIDForAlgorithm:importAlgorithm] isEqualToData:importKeyID])
|
||||
// return MPImportResultInvalidPassword;
|
||||
//
|
||||
// // Delete existing sites.
|
||||
// if (sitesToDelete.count)
|
||||
// [sitesToDelete enumerateObjectsUsingBlock:^(id obj, bool *stop) {
|
||||
// inf( "Deleting site: %@, it will be replaced by an imported site.", [obj name] );
|
||||
// [context deleteObject:obj];
|
||||
// }];
|
||||
//
|
||||
// // Make sure there is a user.
|
||||
// if (user) {
|
||||
// if (importAvatar != NSNotFound)
|
||||
// user.avatar = importAvatar;
|
||||
// if (importDefaultType)
|
||||
// user.defaultType = importDefaultType;
|
||||
// dbg( "Updating User: %", [user debugDescription] );
|
||||
// }
|
||||
// else {
|
||||
// user = [MPUserEntity insertNewObjectInContext:context];
|
||||
// user.name = importUserName;
|
||||
// user.algorithm = MPAlgorithmDefault;
|
||||
// user.keyID = [userKey keyIDForAlgorithm:user.algorithm];
|
||||
// user.defaultType = importDefaultType?: user.algorithm.defaultType;
|
||||
// if (importAvatar != NSNotFound)
|
||||
// user.avatar = importAvatar;
|
||||
// dbg( "Created User: %", [user debugDescription] );
|
||||
// }
|
||||
//
|
||||
// // Import new sites.
|
||||
// for (NSArray *siteElements in importedSiteSites) {
|
||||
// NSDate *lastUsed = [[NSDateFormatter rfc3339DateFormatter] dateFromString:siteElements[0]];
|
||||
// NSUInteger uses = (unsigned)[siteElements[1] integerValue];
|
||||
// MPSiteType type = (MPSiteType)[siteElements[2] integerValue];
|
||||
// MPAlgorithmVersion version = (MPAlgorithmVersion)[siteElements[3] integerValue];
|
||||
// NSUInteger counter = [siteElements[4] length]? (unsigned)[siteElements[4] integerValue]: NSNotFound;
|
||||
// NSString *loginName = [siteElements[5] length]? siteElements[5]: NULL;
|
||||
// NSString *siteName = siteElements[6];
|
||||
// NSString *exportContent = siteElements[7];
|
||||
//
|
||||
// // Create new site.
|
||||
// id<MPAlgorithm> algorithm = MPAlgorithmForVersion( version );
|
||||
// Class entityType = [algorithm classOfType:type];
|
||||
// if (!entityType) {
|
||||
// err( "Invalid site type in import file: %@ has type %lu", siteName, (long)type );
|
||||
// return MPImportResultInternalError;
|
||||
// }
|
||||
// MPSiteEntity *site = (MPSiteEntity *)[entityType insertNewObjectInContext:context];
|
||||
// site.name = siteName;
|
||||
// site.loginName = loginName;
|
||||
// site.user = user;
|
||||
// site.type = type;
|
||||
// site.uses = uses;
|
||||
// site.lastUsed = lastUsed;
|
||||
// site.algorithm = algorithm;
|
||||
// if ([exportContent length]) {
|
||||
// if (clearText)
|
||||
// [site.algorithm importClearTextPassword:exportContent intoSite:site usingKey:userKey];
|
||||
// else
|
||||
// [site.algorithm importProtectedPassword:exportContent protectedByKey:importKey intoSite:site usingKey:userKey];
|
||||
// }
|
||||
// if ([site isKindOfClass:[MPGeneratedSiteEntity class]] && counter != NSNotFound)
|
||||
// ((MPGeneratedSiteEntity *)site).counter = counter;
|
||||
//
|
||||
// dbg( "Created Site: %", [site debugDescription] );
|
||||
// }
|
||||
//
|
||||
// if (![context saveToStore])
|
||||
// return MPImportResultInternalError;
|
||||
//
|
||||
// inf( "Import completed successfully." );
|
||||
//
|
||||
// [[NSNotificationCenter defaultCenter] postNotificationName:MPSitesImportedNotification object:NULL userInfo:@{
|
||||
// MPSitesImportedNotificationUserKey: user
|
||||
// }];
|
||||
//
|
||||
// return MPImportResultSuccess;
|
||||
return (MPMarshalledUser){};
|
||||
}
|
||||
|
||||
MPMarshalledUser mpw_marshall_read_json(
|
||||
char *in) {
|
||||
|
||||
return (MPMarshalledUser){};
|
||||
}
|
||||
|
||||
MPMarshalledUser mpw_marshall_read(
|
||||
char *in, const MPMarshallFormat outFormat) {
|
||||
|
||||
switch (outFormat) {
|
||||
case MPMarshallFormatFlat:
|
||||
return mpw_marshall_read_flat( in );
|
||||
case MPMarshallFormatJSON:
|
||||
return mpw_marshall_read_json( in );
|
||||
}
|
||||
|
||||
return (MPMarshalledUser){};
|
||||
}
|
94
core/c/mpw-marshall.h
Normal file
94
core/c/mpw-marshall.h
Normal file
@ -0,0 +1,94 @@
|
||||
//==============================================================================
|
||||
// This file is part of Master Password.
|
||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||
//
|
||||
// Master Password is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Master Password is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You can find a copy of the GNU General Public License in the
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
#ifndef _MPW_MARSHALL_H
|
||||
#define _MPW_MARSHALL_H
|
||||
#include "mpw-algorithm.h"
|
||||
|
||||
#ifdef NS_ENUM
|
||||
#define enum(_type, _name) NS_ENUM(_type, _name)
|
||||
#else
|
||||
#define enum(_type, _name) _type _name; enum
|
||||
#endif
|
||||
|
||||
//// Types.
|
||||
|
||||
typedef enum( unsigned int, MPMarshallFormat ) {
|
||||
/** Generate a key for authentication. */
|
||||
MPMarshallFormatFlat,
|
||||
/** Generate a name for identification. */
|
||||
MPMarshallFormatJSON,
|
||||
};
|
||||
|
||||
typedef struct MPMarshalledQuestion {
|
||||
const char *keyword;
|
||||
} MPMarshalledQuestion;
|
||||
|
||||
typedef struct MPMarshalledSite {
|
||||
const char *name;
|
||||
const char *content;
|
||||
MPSiteType type;
|
||||
uint32_t counter;
|
||||
MPAlgorithmVersion version;
|
||||
|
||||
const char *loginName;
|
||||
bool loginGenerated;
|
||||
|
||||
const char *url;
|
||||
unsigned int uses;
|
||||
time_t lastUsed;
|
||||
|
||||
size_t questions_count;
|
||||
MPMarshalledQuestion *questions;
|
||||
} MPMarshalledSite;
|
||||
|
||||
typedef struct MPMarshalledUser {
|
||||
const char *name;
|
||||
MPMasterKey key;
|
||||
MPAlgorithmVersion version;
|
||||
|
||||
unsigned int avatar;
|
||||
MPSiteType defaultType;
|
||||
time_t lastUsed;
|
||||
|
||||
size_t sites_count;
|
||||
MPMarshalledSite *sites;
|
||||
} MPMarshalledUser;
|
||||
|
||||
//// Marshalling.
|
||||
|
||||
bool mpw_marshall_write(
|
||||
char **out, const MPMarshallFormat outFormat, bool redacted,
|
||||
const MPMarshalledUser *marshalledUser);
|
||||
|
||||
//// Unmarshalling.
|
||||
|
||||
MPMarshalledUser mpw_marshall_read(
|
||||
char *in, const MPMarshallFormat outFormat);
|
||||
|
||||
//// Utilities.
|
||||
|
||||
MPMarshalledUser mpw_marshall_user(
|
||||
const char *fullName, MPMasterKey masterKey, const MPAlgorithmVersion algorithmVersion);
|
||||
MPMarshalledSite mpw_marshall_site(
|
||||
MPMarshalledUser *marshalledUser,
|
||||
const char *siteName, const MPSiteType siteType, const uint32_t siteCounter, const MPAlgorithmVersion algorithmVersion);
|
||||
MPMarshalledQuestion mpw_marshal_question(
|
||||
MPMarshalledSite *marshalledSite, const char *keyword);
|
||||
|
||||
#endif // _MPW_MARSHALL_H
|
@ -143,8 +143,7 @@ const MPSiteVariant mpw_variantWithName(const char *variantName) {
|
||||
if (0 == strcmp( stdVariantName, "a" ) || 0 == strcmp( stdVariantName, "answer" ))
|
||||
return MPSiteVariantAnswer;
|
||||
|
||||
fprintf( stderr, "Not a variant name: %s", stdVariantName );
|
||||
abort();
|
||||
ftl( "Not a variant name: %s", stdVariantName );
|
||||
}
|
||||
|
||||
const char *mpw_scopeForVariant(MPSiteVariant variant) {
|
||||
@ -160,8 +159,7 @@ const char *mpw_scopeForVariant(MPSiteVariant variant) {
|
||||
return "com.lyndir.masterpassword.answer";
|
||||
}
|
||||
default: {
|
||||
fprintf( stderr, "Unknown variant: %d", variant );
|
||||
abort();
|
||||
ftl( "Unknown variant: %d", variant );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -190,8 +188,7 @@ const char *mpw_charactersInClass(char characterClass) {
|
||||
case ' ':
|
||||
return " ";
|
||||
default: {
|
||||
fprintf( stderr, "Unknown character class: %c", characterClass );
|
||||
abort();
|
||||
ftl( "Unknown character class: %c", characterClass );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define _MPW_TYPES_H
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef NS_ENUM
|
||||
#define enum(_type, _name) NS_ENUM(_type, _name)
|
||||
@ -27,10 +28,11 @@
|
||||
#define enum(_type, _name) _type _name; enum
|
||||
#endif
|
||||
|
||||
#define MP_dkLen 64
|
||||
|
||||
//// Types.
|
||||
|
||||
#define MPMasterKeySize 64
|
||||
typedef const uint8_t *MPMasterKey;
|
||||
|
||||
typedef enum( unsigned int, MPSiteVariant ) {
|
||||
/** Generate a key for authentication. */
|
||||
MPSiteVariantPassword,
|
||||
@ -54,7 +56,7 @@ typedef enum( unsigned int, MPSiteFeature ) {
|
||||
MPSiteFeatureDevicePrivate = 1 << 11,
|
||||
};
|
||||
|
||||
typedef enum( unsigned int, MPSiteType) {
|
||||
typedef enum( unsigned int, MPSiteType ) {
|
||||
MPSiteTypeGeneratedMaximum = 0x0 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedLong = 0x1 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedMedium = 0x2 | MPSiteTypeClassGenerated | 0x0,
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if COLOR
|
||||
#if MPW_COLOR
|
||||
#include <unistd.h>
|
||||
#include <curses.h>
|
||||
#include <term.h>
|
||||
@ -33,17 +33,14 @@
|
||||
#include "sodium.h"
|
||||
#endif
|
||||
|
||||
#ifndef trc
|
||||
int mpw_verbosity;
|
||||
#endif
|
||||
|
||||
#include "mpw-util.h"
|
||||
int mpw_verbosity = inf_level;
|
||||
|
||||
void mpw_push_buf(uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize) {
|
||||
bool mpw_push_buf(uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize) {
|
||||
|
||||
if (*bufferSize == (size_t)-1)
|
||||
// The buffer was marked as broken, it is missing a previous push. Abort to avoid corrupt content.
|
||||
return;
|
||||
return false;
|
||||
|
||||
*bufferSize += pushSize;
|
||||
uint8_t *resizedBuffer = realloc( *buffer, *bufferSize );
|
||||
@ -52,35 +49,38 @@ void mpw_push_buf(uint8_t **const buffer, size_t *const bufferSize, const void *
|
||||
mpw_free( *buffer, *bufferSize - pushSize );
|
||||
*bufferSize = (size_t)-1;
|
||||
*buffer = NULL;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
*buffer = resizedBuffer;
|
||||
uint8_t *pushDst = *buffer + *bufferSize - pushSize;
|
||||
memcpy( pushDst, pushBuffer, pushSize );
|
||||
return true;
|
||||
}
|
||||
|
||||
void mpw_push_string(uint8_t **buffer, size_t *const bufferSize, const char *pushString) {
|
||||
bool mpw_push_string(uint8_t **buffer, size_t *const bufferSize, const char *pushString) {
|
||||
|
||||
mpw_push_buf( buffer, bufferSize, pushString, strlen( pushString ) );
|
||||
return mpw_push_buf( buffer, bufferSize, pushString, strlen( pushString ) );
|
||||
}
|
||||
|
||||
void mpw_push_int(uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt) {
|
||||
bool mpw_push_int(uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt) {
|
||||
|
||||
mpw_push_buf( buffer, bufferSize, &pushInt, sizeof( pushInt ) );
|
||||
return mpw_push_buf( buffer, bufferSize, &pushInt, sizeof( pushInt ) );
|
||||
}
|
||||
|
||||
void mpw_free(const void *buffer, const size_t bufferSize) {
|
||||
bool mpw_free(const void *buffer, const size_t bufferSize) {
|
||||
|
||||
if (!buffer)
|
||||
return false;
|
||||
|
||||
if (buffer) {
|
||||
memset( (void *)buffer, 0, bufferSize );
|
||||
free( (void *)buffer );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void mpw_free_string(const char *string) {
|
||||
bool mpw_free_string(const char *string) {
|
||||
|
||||
mpw_free( string, strlen( string ) );
|
||||
return mpw_free( string, strlen( string ) );
|
||||
}
|
||||
|
||||
uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize,
|
||||
|
@ -17,7 +17,10 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "mpw-types.h"
|
||||
|
||||
#ifndef _MPW_UTIL_H
|
||||
#define _MPW_UTIL_H
|
||||
|
||||
//// Logging.
|
||||
|
||||
@ -25,41 +28,39 @@
|
||||
extern int mpw_verbosity;
|
||||
#define trc_level 3
|
||||
#define trc(...) \
|
||||
if (mpw_verbosity >= 3) \
|
||||
fprintf( stderr, __VA_ARGS__ )
|
||||
({ if (mpw_verbosity >= 3) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
#ifndef dbg
|
||||
#define dbg_level 2
|
||||
#define dbg(...) \
|
||||
if (mpw_verbosity >= 2) \
|
||||
fprintf( stderr, __VA_ARGS__ )
|
||||
({ if (mpw_verbosity >= 2) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
#ifndef inf
|
||||
#define inf_level 1
|
||||
#define inf(...) \
|
||||
if (mpw_verbosity >= 1) \
|
||||
fprintf( stderr, __VA_ARGS__ )
|
||||
({ if (mpw_verbosity >= 1) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
#ifndef wrn
|
||||
#define wrn_level 0
|
||||
#define wrn(...) \
|
||||
if (mpw_verbosity >= 0) \
|
||||
fprintf( stderr, __VA_ARGS__ )
|
||||
({ if (mpw_verbosity >= 0) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
#ifndef err
|
||||
#define err_level -1
|
||||
#define err(...) \
|
||||
if (mpw_verbosity >= -1) \
|
||||
fprintf( stderr, __VA_ARGS__ )
|
||||
({ if (mpw_verbosity >= -1) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
#ifndef ftl
|
||||
#define ftl_level -2
|
||||
#define ftl(...) \
|
||||
do { \
|
||||
if (mpw_verbosity >= -2) \
|
||||
({ if (mpw_verbosity >= -2) \
|
||||
fprintf( stderr, __VA_ARGS__ ); \
|
||||
exit( 2 ); \
|
||||
} while (0)
|
||||
exit( 2 ); })
|
||||
#endif
|
||||
|
||||
//// Buffers and memory.
|
||||
@ -73,19 +74,19 @@ extern int mpw_verbosity;
|
||||
})
|
||||
|
||||
/** Push a buffer onto a buffer. reallocs the given buffer and appends the given buffer. */
|
||||
void mpw_push_buf(
|
||||
bool mpw_push_buf(
|
||||
uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize);
|
||||
/** Push a string onto a buffer. reallocs the given buffer and appends the given string. */
|
||||
void mpw_push_string(
|
||||
bool mpw_push_string(
|
||||
uint8_t **buffer, size_t *const bufferSize, const char *pushString);
|
||||
/** Push an integer onto a buffer. reallocs the given buffer and appends the given integer. */
|
||||
void mpw_push_int(
|
||||
bool mpw_push_int(
|
||||
uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt);
|
||||
/** Free a buffer after zero'ing its contents. */
|
||||
void mpw_free(
|
||||
bool mpw_free(
|
||||
const void *buffer, const size_t bufferSize);
|
||||
/** Free a string after zero'ing its contents. */
|
||||
void mpw_free_string(
|
||||
bool mpw_free_string(
|
||||
const char *string);
|
||||
|
||||
//// Cryptographic functions.
|
||||
@ -117,3 +118,5 @@ 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);
|
||||
|
||||
#endif // _MPW_UTIL_H
|
||||
|
@ -248,6 +248,7 @@
|
||||
DAA1765219D8B82B0044227B /* copy_pw.png in Resources */ = {isa = PBXBuildFile; fileRef = DAA1763C19D8B82B0044227B /* copy_pw.png */; };
|
||||
DAA1765319D8B82B0044227B /* choose_type@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAA1763D19D8B82B0044227B /* choose_type@2x.png */; };
|
||||
DAA1765419D8B82B0044227B /* choose_type.png in Resources */ = {isa = PBXBuildFile; fileRef = DAA1763E19D8B82B0044227B /* choose_type.png */; };
|
||||
DAA449D21EEC4B5800E7BDD5 /* mpw-marshall.c in Sources */ = {isa = PBXBuildFile; fileRef = DAA449D01EEC4B5800E7BDD5 /* mpw-marshall.c */; };
|
||||
DAADBFE01A68763B00F7A756 /* mpw-algorithm.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D3969393A3A46BD27D7078 /* mpw-algorithm.c */; };
|
||||
DABB981615100B4000B05417 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DABB981515100B4000B05417 /* SystemConfiguration.framework */; };
|
||||
DABD39371711E29700CF925C /* avatar-0.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD366C1711E29400CF925C /* avatar-0.png */; };
|
||||
@ -855,6 +856,8 @@
|
||||
DAA1763C19D8B82B0044227B /* copy_pw.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = copy_pw.png; sourceTree = "<group>"; };
|
||||
DAA1763D19D8B82B0044227B /* choose_type@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "choose_type@2x.png"; sourceTree = "<group>"; };
|
||||
DAA1763E19D8B82B0044227B /* choose_type.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = choose_type.png; sourceTree = "<group>"; };
|
||||
DAA449D01EEC4B5800E7BDD5 /* mpw-marshall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-marshall.c"; sourceTree = "<group>"; };
|
||||
DAA449D11EEC4B5800E7BDD5 /* mpw-marshall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-marshall.h"; sourceTree = "<group>"; };
|
||||
DAAC35DD156BD77D00C5FD93 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
|
||||
DABB981515100B4000B05417 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||
DABD360F1711E29400CF925C /* ui_background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ui_background.png; sourceTree = "<group>"; };
|
||||
@ -1722,6 +1725,8 @@
|
||||
93D39D4E713564B7654341B0 /* mpw-algorithm_v3.c */,
|
||||
93D3969393A3A46BD27D7078 /* mpw-algorithm.c */,
|
||||
93D3990D850D76A94C6B7A4D /* mpw-algorithm.h */,
|
||||
DAA449D01EEC4B5800E7BDD5 /* mpw-marshall.c */,
|
||||
DAA449D11EEC4B5800E7BDD5 /* mpw-marshall.h */,
|
||||
93D392C5A6572DB0EB5B82C8 /* mpw-types.c */,
|
||||
93D39AFD17CBE324D745DAB0 /* mpw-types.h */,
|
||||
93D396C311C3725870343EE0 /* mpw-util.c */,
|
||||
@ -3862,6 +3867,7 @@
|
||||
DABD3C151711E2DC00CF925C /* MPiOSAppDelegate.m in Sources */,
|
||||
DA0CC5941EB6B030009A8ED9 /* MPSiteEntity+CoreDataClass.m in Sources */,
|
||||
DABD3C1C1711E2DC00CF925C /* MPGuideViewController.m in Sources */,
|
||||
DAA449D21EEC4B5800E7BDD5 /* mpw-marshall.c in Sources */,
|
||||
DABD3C1E1711E2DC00CF925C /* MPPreferencesViewController.m in Sources */,
|
||||
DABD3C1F1711E2DC00CF925C /* MPTypeViewController.m in Sources */,
|
||||
DABD3C211711E2DC00CF925C /* MPiOSConfig.m in Sources */,
|
||||
|
@ -23,8 +23,6 @@
|
||||
93D39F833DEC1C89B2F795AC /* MPSitesWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A57A7823DE98A0FF83C /* MPSitesWindowController.m */; };
|
||||
DA0933CC1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0933CB1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png */; };
|
||||
DA0933D01747B91B00DE1CEF /* appstore.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0933CF1747B91B00DE1CEF /* appstore.png */; };
|
||||
DA09745A1E99582900F0BFE8 /* mpw-tests-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DA0974561E99582200F0BFE8 /* mpw-tests-util.c */; };
|
||||
DA09745B1E99582900F0BFE8 /* mpw-tests.c in Sources */ = {isa = PBXBuildFile; fileRef = DA0974571E99582200F0BFE8 /* mpw-tests.c */; };
|
||||
DA09745E1E99586600F0BFE8 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DA09745D1E99586600F0BFE8 /* libxml2.tbd */; };
|
||||
DA0979681E9A834C00F0BFE8 /* libsodium.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA0979571E9A824700F0BFE8 /* libsodium.a */; };
|
||||
DA0CC53E1EB57B69009A8ED9 /* Fabric.plist in Resources */ = {isa = PBXBuildFile; fileRef = DA0CC53D1EB57B69009A8ED9 /* Fabric.plist */; };
|
||||
@ -34,6 +32,22 @@
|
||||
DA16B342170661E0000A0EAB /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC632871486D95D0075AEA5 /* Security.framework */; };
|
||||
DA16B344170661EE000A0EAB /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA16B343170661EE000A0EAB /* Cocoa.framework */; };
|
||||
DA16B345170661F2000A0EAB /* libPearl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC77CAD148291A600BCF976 /* libPearl.a */; };
|
||||
DA1C7AAA1F1A8F24009A3551 /* mpw-marshall.c in Sources */ = {isa = PBXBuildFile; fileRef = DAA449D31EEC4B6B00E7BDD5 /* mpw-marshall.c */; };
|
||||
DA1C7AAB1F1A8F24009A3551 /* mpw-types.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773C21A4746AF004F356A /* mpw-types.c */; };
|
||||
DA1C7AAC1F1A8F24009A3551 /* mpw-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773C51A4746AF004F356A /* mpw-util.c */; };
|
||||
DA1C7AAD1F1A8F24009A3551 /* mpw-algorithm.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773BB1A4746AF004F356A /* mpw-algorithm.c */; };
|
||||
DA1C7AAF1F1A8F24009A3551 /* libsodium.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA0979571E9A824700F0BFE8 /* libsodium.a */; };
|
||||
DA1C7AB01F1A8F24009A3551 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DA09745D1E99586600F0BFE8 /* libxml2.tbd */; };
|
||||
DA1C7AC31F1A8FBA009A3551 /* mpw-cli.c in Sources */ = {isa = PBXBuildFile; fileRef = DA1C7AB91F1A8F6E009A3551 /* mpw-cli.c */; };
|
||||
DA1C7AC81F1A8FD8009A3551 /* mpw-marshall.c in Sources */ = {isa = PBXBuildFile; fileRef = DAA449D31EEC4B6B00E7BDD5 /* mpw-marshall.c */; };
|
||||
DA1C7ACA1F1A8FD8009A3551 /* mpw-types.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773C21A4746AF004F356A /* mpw-types.c */; };
|
||||
DA1C7ACB1F1A8FD8009A3551 /* mpw-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773C51A4746AF004F356A /* mpw-util.c */; };
|
||||
DA1C7ACD1F1A8FD8009A3551 /* mpw-algorithm.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773BB1A4746AF004F356A /* mpw-algorithm.c */; };
|
||||
DA1C7ACF1F1A8FD8009A3551 /* libsodium.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA0979571E9A824700F0BFE8 /* libsodium.a */; };
|
||||
DA1C7AD01F1A8FD8009A3551 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DA09745D1E99586600F0BFE8 /* libxml2.tbd */; };
|
||||
DA1C7AD71F1A8FE6009A3551 /* mpw-bench.c in Sources */ = {isa = PBXBuildFile; fileRef = DA1C7AB81F1A8F6E009A3551 /* mpw-bench.c */; };
|
||||
DA1C7AD81F1A8FF4009A3551 /* mpw-tests-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DA1C7ABA1F1A8F6E009A3551 /* mpw-tests-util.c */; };
|
||||
DA1C7AD91F1A8FF4009A3551 /* mpw-tests.c in Sources */ = {isa = PBXBuildFile; fileRef = DA1C7ABC1F1A8F6E009A3551 /* mpw-tests.c */; };
|
||||
DA2508F119511D3600AC23F1 /* MPPasswordWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */; };
|
||||
DA250925195148E200AC23F1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEBC45214F6364500987BF6 /* QuartzCore.framework */; };
|
||||
DA26861D1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataClass.m in Sources */ = {isa = PBXBuildFile; fileRef = DA26860A1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataClass.m */; };
|
||||
@ -70,6 +84,7 @@
|
||||
DA4DAE951A7D8117003E5423 /* MPTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4DAE931A7D8117003E5423 /* MPTypes.m */; };
|
||||
DA5180CA19FF2F9200A587E9 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */; };
|
||||
DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180CD19FF307E00A587E9 /* MPAppDelegate_Store.m */; };
|
||||
DA531CC31EFF3BF4008C72CB /* mpw-marshall.c in Sources */ = {isa = PBXBuildFile; fileRef = DAA449D31EEC4B6B00E7BDD5 /* mpw-marshall.c */; };
|
||||
DA5E5CF61724A667003798D8 /* MPAlgorithm.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C981724A667003798D8 /* MPAlgorithm.m */; };
|
||||
DA5E5CF71724A667003798D8 /* MPAlgorithmV0.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9A1724A667003798D8 /* MPAlgorithmV0.m */; };
|
||||
DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9C1724A667003798D8 /* MPAlgorithmV1.m */; };
|
||||
@ -103,6 +118,7 @@
|
||||
DA9261521BE1A86700369DE5 /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9261501BE1A86700369DE5 /* Fabric.framework */; };
|
||||
DA9261541BE1A88900369DE5 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9261531BE1A88900369DE5 /* libc++.tbd */; };
|
||||
DA9261561BE1A89600369DE5 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9261551BE1A89600369DE5 /* libz.tbd */; };
|
||||
DAA449D51EEC4B6B00E7BDD5 /* mpw-marshall.c in Sources */ = {isa = PBXBuildFile; fileRef = DAA449D31EEC4B6B00E7BDD5 /* mpw-marshall.c */; };
|
||||
DAAA81B0195A8D1300FA30D9 /* gradient.png in Resources */ = {isa = PBXBuildFile; fileRef = DAAA81AF195A8D1300FA30D9 /* gradient.png */; };
|
||||
DAADCC4719FAFFAD00987B1D /* NSNotificationCenter+PearlEasyCleanup.h in Headers */ = {isa = PBXBuildFile; fileRef = DAADCC3E19FAFFAD00987B1D /* NSNotificationCenter+PearlEasyCleanup.h */; };
|
||||
DAADCC4819FAFFAD00987B1D /* NSPersistentStore+PearlMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = DAADCC3F19FAFFAD00987B1D /* NSPersistentStore+PearlMigration.h */; };
|
||||
@ -234,6 +250,24 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
DA1C7AB11F1A8F24009A3551 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
DA1C7AD11F1A8FD8009A3551 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
DA6774391A474A03004F356A /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -291,9 +325,6 @@
|
||||
DA0933C91747A56A00DE1CEF /* MPInitialWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPInitialWindow.xib; sourceTree = "<group>"; };
|
||||
DA0933CB1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "shot-laptop-leaning-iphone.png"; sourceTree = "<group>"; };
|
||||
DA0933CF1747B91B00DE1CEF /* appstore.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = appstore.png; sourceTree = "<group>"; };
|
||||
DA0974561E99582200F0BFE8 /* mpw-tests-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mpw-tests-util.c"; path = "../../platform-independent/cli-c/cli/mpw-tests-util.c"; sourceTree = "<group>"; };
|
||||
DA0974571E99582200F0BFE8 /* mpw-tests.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mpw-tests.c"; path = "../../platform-independent/cli-c/cli/mpw-tests.c"; sourceTree = "<group>"; };
|
||||
DA09745C1E99583B00F0BFE8 /* mpw-tests-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "mpw-tests-util.h"; path = "../../platform-independent/cli-c/cli/mpw-tests-util.h"; sourceTree = "<group>"; };
|
||||
DA09745D1E99586600F0BFE8 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = usr/lib/libxml2.tbd; sourceTree = SDKROOT; };
|
||||
DA09745F1E995EB500F0BFE8 /* mpw_tests.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = mpw_tests.xml; path = ../../core/java/tests/src/main/resources/mpw_tests.xml; sourceTree = "<group>"; };
|
||||
DA09791B1E9A824700F0BFE8 /* core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core.h; sourceTree = "<group>"; };
|
||||
@ -367,6 +398,13 @@
|
||||
DA0CC5581EB6AE45009A8ED9 /* MasterPassword 9.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MasterPassword 9.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DA16B340170661DB000A0EAB /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
|
||||
DA16B343170661EE000A0EAB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
DA1C7AB61F1A8F24009A3551 /* mpw-cli */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "mpw-cli"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA1C7AB81F1A8F6E009A3551 /* mpw-bench.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-bench.c"; sourceTree = "<group>"; };
|
||||
DA1C7AB91F1A8F6E009A3551 /* mpw-cli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-cli.c"; sourceTree = "<group>"; };
|
||||
DA1C7ABA1F1A8F6E009A3551 /* mpw-tests-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-tests-util.c"; sourceTree = "<group>"; };
|
||||
DA1C7ABB1F1A8F6E009A3551 /* mpw-tests-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-tests-util.h"; sourceTree = "<group>"; };
|
||||
DA1C7ABC1F1A8F6E009A3551 /* mpw-tests.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-tests.c"; sourceTree = "<group>"; };
|
||||
DA1C7AD61F1A8FD8009A3551 /* mpw-bench */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "mpw-bench"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPPasswordWindowController.xib; sourceTree = "<group>"; };
|
||||
DA2508F919513C1400AC23F1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
DA2508FA19513C1400AC23F1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
@ -874,6 +912,8 @@
|
||||
DA9261501BE1A86700369DE5 /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Fabric.framework; sourceTree = "<group>"; };
|
||||
DA9261531BE1A88900369DE5 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
|
||||
DA9261551BE1A89600369DE5 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
DAA449D31EEC4B6B00E7BDD5 /* mpw-marshall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-marshall.c"; sourceTree = "<group>"; };
|
||||
DAA449D41EEC4B6B00E7BDD5 /* mpw-marshall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-marshall.h"; sourceTree = "<group>"; };
|
||||
DAAA81AF195A8D1300FA30D9 /* gradient.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gradient.png; sourceTree = "<group>"; };
|
||||
DAADCC3E19FAFFAD00987B1D /* NSNotificationCenter+PearlEasyCleanup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+PearlEasyCleanup.h"; sourceTree = "<group>"; };
|
||||
DAADCC3F19FAFFAD00987B1D /* NSPersistentStore+PearlMigration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPersistentStore+PearlMigration.h"; sourceTree = "<group>"; };
|
||||
@ -999,6 +1039,24 @@
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
DA1C7AAE1F1A8F24009A3551 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA1C7AAF1F1A8F24009A3551 /* libsodium.a in Frameworks */,
|
||||
DA1C7AB01F1A8F24009A3551 /* libxml2.tbd in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DA1C7ACE1F1A8FD8009A3551 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA1C7ACF1F1A8FD8009A3551 /* libsodium.a in Frameworks */,
|
||||
DA1C7AD01F1A8FD8009A3551 /* libxml2.tbd in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DA5BFA41147E415C00F98B1E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -1156,6 +1214,19 @@
|
||||
path = Fabric;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA1C7AB71F1A8F6E009A3551 /* cli */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA1C7AB81F1A8F6E009A3551 /* mpw-bench.c */,
|
||||
DA1C7AB91F1A8F6E009A3551 /* mpw-cli.c */,
|
||||
DA1C7ABA1F1A8F6E009A3551 /* mpw-tests-util.c */,
|
||||
DA1C7ABB1F1A8F6E009A3551 /* mpw-tests-util.h */,
|
||||
DA1C7ABC1F1A8F6E009A3551 /* mpw-tests.c */,
|
||||
);
|
||||
name = cli;
|
||||
path = "../../platform-independent/cli-c/cli";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA2508F819513C1400AC23F1 /* Other Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1196,6 +1267,8 @@
|
||||
DAC6326C148680650075AEA5 /* libjrswizzle.a */,
|
||||
DAADCC5019FB006500987B1D /* libKCOrderedAccessorFix.a */,
|
||||
DA67743B1A474A03004F356A /* mpw-test */,
|
||||
DA1C7AB61F1A8F24009A3551 /* mpw-cli */,
|
||||
DA1C7AD61F1A8FD8009A3551 /* mpw-bench */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@ -1734,15 +1807,15 @@
|
||||
DA6773291A4746AF004F356A /* C */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA1C7AB71F1A8F6E009A3551 /* cli */,
|
||||
DA831A271A6E1146000AC234 /* mpw-algorithm_v0.c */,
|
||||
DA831A281A6E1146000AC234 /* mpw-algorithm_v1.c */,
|
||||
DA831A291A6E1146000AC234 /* mpw-algorithm_v2.c */,
|
||||
DA831A2A1A6E1146000AC234 /* mpw-algorithm_v3.c */,
|
||||
DA6773BB1A4746AF004F356A /* mpw-algorithm.c */,
|
||||
DA6773BC1A4746AF004F356A /* mpw-algorithm.h */,
|
||||
DA0974561E99582200F0BFE8 /* mpw-tests-util.c */,
|
||||
DA09745C1E99583B00F0BFE8 /* mpw-tests-util.h */,
|
||||
DA0974571E99582200F0BFE8 /* mpw-tests.c */,
|
||||
DAA449D31EEC4B6B00E7BDD5 /* mpw-marshall.c */,
|
||||
DAA449D41EEC4B6B00E7BDD5 /* mpw-marshall.h */,
|
||||
DA6773C21A4746AF004F356A /* mpw-types.c */,
|
||||
DA6773C31A4746AF004F356A /* mpw-types.h */,
|
||||
DA6773C51A4746AF004F356A /* mpw-util.c */,
|
||||
@ -2101,6 +2174,40 @@
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
DA1C7AA61F1A8F24009A3551 /* mpw-cli */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DA1C7AB21F1A8F24009A3551 /* Build configuration list for PBXNativeTarget "mpw-cli" */;
|
||||
buildPhases = (
|
||||
DA1C7AA71F1A8F24009A3551 /* Sources */,
|
||||
DA1C7AAE1F1A8F24009A3551 /* Frameworks */,
|
||||
DA1C7AB11F1A8F24009A3551 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "mpw-cli";
|
||||
productName = "mpw-test";
|
||||
productReference = DA1C7AB61F1A8F24009A3551 /* mpw-cli */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
DA1C7AC61F1A8FD8009A3551 /* mpw-bench */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DA1C7AD21F1A8FD8009A3551 /* Build configuration list for PBXNativeTarget "mpw-bench" */;
|
||||
buildPhases = (
|
||||
DA1C7AC71F1A8FD8009A3551 /* Sources */,
|
||||
DA1C7ACE1F1A8FD8009A3551 /* Frameworks */,
|
||||
DA1C7AD11F1A8FD8009A3551 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "mpw-bench";
|
||||
productName = "mpw-test";
|
||||
productReference = DA1C7AD61F1A8FD8009A3551 /* mpw-bench */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
DA5BFA43147E415C00F98B1E /* MasterPassword */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */;
|
||||
@ -2205,6 +2312,12 @@
|
||||
LastUpgradeCheck = 0830;
|
||||
ORGANIZATIONNAME = Lyndir;
|
||||
TargetAttributes = {
|
||||
DA1C7AA61F1A8F24009A3551 = {
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
};
|
||||
DA1C7AC61F1A8FD8009A3551 = {
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
};
|
||||
DA5BFA43147E415C00F98B1E = {
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
ProvisioningStyle = Automatic;
|
||||
@ -2254,6 +2367,8 @@
|
||||
DAC6326B148680650075AEA5 /* jrswizzle */,
|
||||
DAADCC4F19FB006500987B1D /* KCOrderedAccessorFix */,
|
||||
DA67743A1A474A03004F356A /* mpw-test */,
|
||||
DA1C7AC61F1A8FD8009A3551 /* mpw-bench */,
|
||||
DA1C7AA61F1A8F24009A3551 /* mpw-cli */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@ -2403,6 +2518,30 @@
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
DA1C7AA71F1A8F24009A3551 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA1C7AAA1F1A8F24009A3551 /* mpw-marshall.c in Sources */,
|
||||
DA1C7AAB1F1A8F24009A3551 /* mpw-types.c in Sources */,
|
||||
DA1C7AAC1F1A8F24009A3551 /* mpw-util.c in Sources */,
|
||||
DA1C7AC31F1A8FBA009A3551 /* mpw-cli.c in Sources */,
|
||||
DA1C7AAD1F1A8F24009A3551 /* mpw-algorithm.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DA1C7AC71F1A8FD8009A3551 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA1C7AC81F1A8FD8009A3551 /* mpw-marshall.c in Sources */,
|
||||
DA1C7ACA1F1A8FD8009A3551 /* mpw-types.c in Sources */,
|
||||
DA1C7ACB1F1A8FD8009A3551 /* mpw-util.c in Sources */,
|
||||
DA1C7AD71F1A8FE6009A3551 /* mpw-bench.c in Sources */,
|
||||
DA1C7ACD1F1A8FD8009A3551 /* mpw-algorithm.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DA5BFA40147E415C00F98B1E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -2411,6 +2550,7 @@
|
||||
DA5E5CF61724A667003798D8 /* MPAlgorithm.m in Sources */,
|
||||
DA2686201EBFD7A40001E37E /* MPSiteEntity+CoreDataProperties.m in Sources */,
|
||||
DA5E5CF71724A667003798D8 /* MPAlgorithmV0.m in Sources */,
|
||||
DAA449D51EEC4B6B00E7BDD5 /* mpw-marshall.c in Sources */,
|
||||
DA26861E1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataProperties.m in Sources */,
|
||||
DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */,
|
||||
DA2686231EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataClass.m in Sources */,
|
||||
@ -2453,10 +2593,11 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA09745B1E99582900F0BFE8 /* mpw-tests.c in Sources */,
|
||||
DA09745A1E99582900F0BFE8 /* mpw-tests-util.c in Sources */,
|
||||
DA531CC31EFF3BF4008C72CB /* mpw-marshall.c in Sources */,
|
||||
DA1C7AD81F1A8FF4009A3551 /* mpw-tests-util.c in Sources */,
|
||||
DA6774451A474A3B004F356A /* mpw-types.c in Sources */,
|
||||
DA6774461A474A3B004F356A /* mpw-util.c in Sources */,
|
||||
DA1C7AD91F1A8FF4009A3551 /* mpw-tests.c in Sources */,
|
||||
DA6774431A474A3B004F356A /* mpw-algorithm.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -2724,12 +2865,8 @@
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/Cellar/libsodium/1.0.12/lib,
|
||||
/usr/local/Cellar/libscrypt/1.21/lib,
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
@ -2738,6 +2875,138 @@
|
||||
};
|
||||
name = Test;
|
||||
};
|
||||
DA1C7AB31F1A8F24009A3551 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DA1C7AB41F1A8F24009A3551 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DA1C7AB51F1A8F24009A3551 /* Test */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Test;
|
||||
};
|
||||
DA1C7AD31F1A8FD8009A3551 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DA1C7AD41F1A8FD8009A3551 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DA1C7AD51F1A8FD8009A3551 /* Test */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Test;
|
||||
};
|
||||
DA5BFA6B147E415C00F98B1E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -2987,12 +3256,8 @@
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/Cellar/libsodium/1.0.12/lib,
|
||||
/usr/local/Cellar/libscrypt/1.21/lib,
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
@ -3012,12 +3277,8 @@
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/Cellar/libsodium/1.0.12/lib,
|
||||
/usr/local/Cellar/libscrypt/1.21/lib,
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
@ -3097,6 +3358,26 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
DA1C7AB21F1A8F24009A3551 /* Build configuration list for PBXNativeTarget "mpw-cli" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DA1C7AB31F1A8F24009A3551 /* Debug */,
|
||||
DA1C7AB41F1A8F24009A3551 /* Release */,
|
||||
DA1C7AB51F1A8F24009A3551 /* Test */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Test;
|
||||
};
|
||||
DA1C7AD21F1A8FD8009A3551 /* Build configuration list for PBXNativeTarget "mpw-bench" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DA1C7AD31F1A8FD8009A3551 /* Debug */,
|
||||
DA1C7AD41F1A8FD8009A3551 /* Release */,
|
||||
DA1C7AD51F1A8FD8009A3551 /* Test */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Test;
|
||||
};
|
||||
DA5BFA3E147E415C00F98B1E /* Build configuration list for PBXProject "MasterPassword-macOS" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
@ -49,7 +49,7 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
|
||||
- (BOOL)tryMigrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc;
|
||||
- (BOOL)tryMigrateSite:(MPSiteEntity *)site explicit:(BOOL)explicit;
|
||||
|
||||
- (NSData *)keyIDForKeyData:(NSData *)keyData;
|
||||
- (NSData *)keyIDForKey:(MPMasterKey)masterKey;
|
||||
- (NSData *)keyDataForFullName:(NSString *)fullName withMasterPassword:(NSString *)masterPassword;
|
||||
|
||||
- (NSString *)nameOfType:(MPSiteType)type;
|
||||
|
@ -128,21 +128,21 @@ static NSOperationQueue *_mpwQueue = nil;
|
||||
__block NSData *keyData;
|
||||
[self mpw_perform:^{
|
||||
NSDate *start = [NSDate date];
|
||||
uint8_t const *masterKeyBytes = mpw_masterKeyForUser( fullName.UTF8String, masterPassword.UTF8String, [self version] );
|
||||
if (masterKeyBytes) {
|
||||
keyData = [NSData dataWithBytes:masterKeyBytes length:MP_dkLen];
|
||||
MPMasterKey masterKey = mpw_masterKeyForUser( fullName.UTF8String, masterPassword.UTF8String, [self version] );
|
||||
if (masterKey) {
|
||||
keyData = [NSData dataWithBytes:masterKey length:MPMasterKeySize];
|
||||
trc( @"User: %@, password: %@ derives to key ID: %@ (took %0.2fs)", //
|
||||
fullName, masterPassword, [self keyIDForKeyData:keyData], -[start timeIntervalSinceNow] );
|
||||
mpw_free( masterKeyBytes, MP_dkLen );
|
||||
fullName, masterPassword, [self keyIDForKey:masterKey], -[start timeIntervalSinceNow] );
|
||||
mpw_free( masterKey, MPMasterKeySize );
|
||||
}
|
||||
}];
|
||||
|
||||
return keyData;
|
||||
}
|
||||
|
||||
- (NSData *)keyIDForKeyData:(NSData *)keyData {
|
||||
- (NSData *)keyIDForKey:(MPMasterKey)masterKey {
|
||||
|
||||
return [keyData hashWith:PearlHashSHA256];
|
||||
return [[NSData dataWithBytesNoCopy:(void *)masterKey length:MPMasterKeySize] hashWith:PearlHashSHA256];
|
||||
}
|
||||
|
||||
- (NSString *)nameOfType:(MPSiteType)type {
|
||||
@ -350,9 +350,9 @@ static NSOperationQueue *_mpwQueue = nil;
|
||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
|
||||
variant:(MPSiteVariant)variant context:(NSString *)context usingKey:(MPKey *)key {
|
||||
|
||||
__block NSString *content;
|
||||
__block NSString *content = nil;
|
||||
[self mpw_perform:^{
|
||||
char const *contentBytes = mpw_passwordForSite( [key keyDataForAlgorithm:self].bytes,
|
||||
char const *contentBytes = mpw_passwordForSite( [key keyForAlgorithm:self],
|
||||
name.UTF8String, type, (uint32_t)counter, variant, context.UTF8String, [self version] );
|
||||
if (contentBytes) {
|
||||
content = [NSString stringWithCString:contentBytes encoding:NSUTF8StringEncoding];
|
||||
@ -396,7 +396,7 @@ static NSOperationQueue *_mpwQueue = nil;
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSData *encryptionKey = [siteKey keyDataForAlgorithm:self trimmedLength:PearlCryptKeySize];
|
||||
NSData *encryptionKey = [siteKey keyForAlgorithm:self trimmedLength:PearlCryptKeySize];
|
||||
NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
|
||||
encryptWithSymmetricKey:encryptionKey padding:YES];
|
||||
if ([((MPStoredSiteEntity *)site).contentObject isEqualToData:encryptedContent])
|
||||
@ -412,7 +412,7 @@ static NSOperationQueue *_mpwQueue = nil;
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSData *encryptionKey = [siteKey keyDataForAlgorithm:self trimmedLength:PearlCryptKeySize];
|
||||
NSData *encryptionKey = [siteKey keyForAlgorithm:self trimmedLength:PearlCryptKeySize];
|
||||
NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
|
||||
encryptWithSymmetricKey:encryptionKey padding:YES];
|
||||
NSDictionary *siteQuery = [self queryForDevicePrivateSiteNamed:site.name];
|
||||
@ -713,7 +713,7 @@ static NSOperationQueue *_mpwQueue = nil;
|
||||
return nil;
|
||||
NSData *decryptedContent = nil;
|
||||
if ([encryptedContent length]) {
|
||||
NSData *encryptionKey = [key keyDataForAlgorithm:self trimmedLength:PearlCryptKeySize];
|
||||
NSData *encryptionKey = [key keyForAlgorithm:self trimmedLength:PearlCryptKeySize];
|
||||
decryptedContent = [encryptedContent decryptWithSymmetricKey:encryptionKey padding:YES];
|
||||
}
|
||||
if (!decryptedContent)
|
||||
|
@ -95,13 +95,14 @@
|
||||
- (void)storeSavedKeyFor:(MPUserEntity *)user {
|
||||
|
||||
if (user.saveKey) {
|
||||
NSData *keyData = [self.key keyDataForAlgorithm:user.algorithm];
|
||||
if (keyData) {
|
||||
MPMasterKey masterKey = [self.key keyForAlgorithm:user.algorithm];
|
||||
if (masterKey) {
|
||||
[self forgetSavedKeyFor:user];
|
||||
|
||||
inf( @"Saving key in keychain for user: %@", user.userID );
|
||||
[PearlKeyChain addOrUpdateItemForQuery:[self createKeyQueryforUser:user origin:nil]
|
||||
withAttributes:@{ (__bridge id)kSecValueData: keyData }];
|
||||
[PearlKeyChain addOrUpdateItemForQuery:[self createKeyQueryforUser:user origin:nil] withAttributes:@{
|
||||
(__bridge id)kSecValueData: [NSData dataWithBytesNoCopy:(void *)masterKey length:MPMasterKeySize]
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "mpw-marshall.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#define STORE_OPTIONS NSPersistentStoreFileProtectionKey : NSFileProtectionComplete,
|
||||
@ -840,68 +841,26 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
MPUserEntity *activeUser = [self activeUserForMainThread];
|
||||
inf( @"Exporting sites, %@, for user: %@", revealPasswords? @"revealing passwords": @"omitting passwords", activeUser.userID );
|
||||
|
||||
// Header.
|
||||
NSMutableString *export = [NSMutableString new];
|
||||
[export appendFormat:@"# Master Password site export\n"];
|
||||
if (revealPasswords)
|
||||
[export appendFormat:@"# Export of site names and passwords in clear-text.\n"];
|
||||
else
|
||||
[export appendFormat:@"# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n"];
|
||||
[export appendFormat:@"# \n"];
|
||||
[export appendFormat:@"##\n"];
|
||||
[export appendFormat:@"# Format: 1\n"];
|
||||
[export appendFormat:@"# Date: %@\n", [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]]];
|
||||
[export appendFormat:@"# User Name: %@\n", activeUser.name];
|
||||
[export appendFormat:@"# Full Name: %@\n", activeUser.name];
|
||||
[export appendFormat:@"# Avatar: %lu\n", (unsigned long)activeUser.avatar];
|
||||
[export appendFormat:@"# Key ID: %@\n", [activeUser.keyID encodeHex]];
|
||||
[export appendFormat:@"# Version: %@\n", [PearlInfoPlist get].CFBundleVersion];
|
||||
[export appendFormat:@"# Algorithm: %d\n", activeUser.algorithm.version];
|
||||
[export appendFormat:@"# Default Type: %d\n", activeUser.defaultType];
|
||||
[export appendFormat:@"# Passwords: %@\n", revealPasswords? @"VISIBLE": @"PROTECTED"];
|
||||
[export appendFormat:@"##\n"];
|
||||
[export appendFormat:@"#\n"];
|
||||
[export appendFormat:@"# Last Times Password Login\t Site\tSite\n"];
|
||||
[export appendFormat:@"# used used type name\t name\tpassword\n"];
|
||||
MPMarshalledUser exportUser = mpw_marshall_user( activeUser.name.UTF8String,
|
||||
[self.key keyForAlgorithm:activeUser.algorithm], activeUser.algorithm.version );
|
||||
exportUser.avatar = activeUser.avatar;
|
||||
exportUser.defaultType = activeUser.defaultType;
|
||||
exportUser.lastUsed = (time_t)activeUser.lastUsed.timeIntervalSince1970;
|
||||
|
||||
|
||||
// Sites.
|
||||
for (MPSiteEntity *site in activeUser.sites) {
|
||||
NSDate *lastUsed = site.lastUsed;
|
||||
NSUInteger uses = site.uses;
|
||||
MPSiteType type = site.type;
|
||||
id<MPAlgorithm> algorithm = site.algorithm;
|
||||
NSUInteger counter = 0;
|
||||
NSString *loginName = site.loginName;
|
||||
NSString *siteName = site.name;
|
||||
NSString *content = nil;
|
||||
MPMarshalledSite exportSite = mpw_marshall_site( &exportUser,
|
||||
site.name.UTF8String, site.type, site.counter, site.algorithm.version );
|
||||
exportSite.loginName = site.loginName.UTF8String;
|
||||
exportSite.url = site.url.UTF8String;
|
||||
exportSite.uses = site.uses;
|
||||
exportSite.lastUsed = (time_t)site.lastUsed.timeIntervalSince1970;
|
||||
|
||||
// Generated-specific
|
||||
if ([site isKindOfClass:[MPGeneratedSiteEntity class]])
|
||||
counter = ((MPGeneratedSiteEntity *)site).counter;
|
||||
|
||||
|
||||
// Determine the content to export.
|
||||
if (!(type & MPSiteFeatureDevicePrivate)) {
|
||||
if (revealPasswords)
|
||||
content = [site.algorithm resolvePasswordForSite:site usingKey:self.key];
|
||||
else if (type & MPSiteFeatureExportContent)
|
||||
content = [site.algorithm exportPasswordForSite:site usingKey:self.key];
|
||||
for (MPSiteQuestionEntity *siteQuestion in site.questions)
|
||||
mpw_marshal_question( &exportSite, siteQuestion.keyword.UTF8String );
|
||||
}
|
||||
|
||||
NSString *lastUsedExport = [[NSDateFormatter rfc3339DateFormatter] stringFromDate:lastUsed];
|
||||
long usesExport = (long)uses;
|
||||
NSString *typeExport = strf( @"%lu:%lu:%lu", (long)type, (long)[algorithm version], (long)counter );
|
||||
NSString *loginNameExport = loginName?: @"";
|
||||
NSString *contentExport = content?: @"";
|
||||
[export appendFormat:@"%@ %8ld %8S %25S\t%25S\t%@\n",
|
||||
lastUsedExport, usesExport,
|
||||
(const unsigned short *)[typeExport cStringUsingEncoding:NSUTF16StringEncoding],
|
||||
(const unsigned short *)[loginNameExport cStringUsingEncoding:NSUTF16StringEncoding],
|
||||
(const unsigned short *)[siteName cStringUsingEncoding:NSUTF16StringEncoding],
|
||||
contentExport];
|
||||
}
|
||||
|
||||
return export;
|
||||
mpw_marshall_write( &export, MPMarshallFormatFlat, exportUser );
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPAlgorithm.h"
|
||||
#import "mpw-types.h"
|
||||
|
||||
@protocol MPAlgorithm;
|
||||
|
||||
@ -37,8 +38,7 @@ typedef NS_ENUM( NSUInteger, MPKeyOrigin ) {
|
||||
keyOrigin:(MPKeyOrigin)origin;
|
||||
|
||||
- (NSData *)keyIDForAlgorithm:(id<MPAlgorithm>)algorithm;
|
||||
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm;
|
||||
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm trimmedLength:(NSUInteger)subKeyLength;
|
||||
- (MPMasterKey)keyForAlgorithm:(id<MPAlgorithm>)algorithm;
|
||||
|
||||
- (BOOL)isEqualToKey:(MPKey *)key;
|
||||
|
||||
|
@ -53,28 +53,21 @@
|
||||
|
||||
- (NSData *)keyIDForAlgorithm:(id<MPAlgorithm>)algorithm {
|
||||
|
||||
return [algorithm keyIDForKeyData:[self keyDataForAlgorithm:algorithm]];
|
||||
return [algorithm keyIDForKey:[self keyForAlgorithm:algorithm]];
|
||||
}
|
||||
|
||||
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm {
|
||||
- (MPMasterKey)keyForAlgorithm:(id<MPAlgorithm>)algorithm {
|
||||
|
||||
@synchronized (self) {
|
||||
NSData *keyData = [self.keyCache objectForKey:algorithm];
|
||||
if (keyData)
|
||||
return keyData;
|
||||
|
||||
if (!keyData) {
|
||||
keyData = self.keyResolver( algorithm );
|
||||
if (keyData)
|
||||
[self.keyCache setObject:keyData forKey:algorithm];
|
||||
|
||||
return keyData;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm trimmedLength:(NSUInteger)subKeyLength {
|
||||
|
||||
NSData *keyData = [self keyDataForAlgorithm:algorithm];
|
||||
return [keyData subdataWithRange:NSMakeRange( 0, MIN( subKeyLength, keyData.length ) )];
|
||||
return keyData.length == MPMasterKeySize? keyData.bytes: NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToKey:(MPKey *)key {
|
||||
@ -84,10 +77,7 @@
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
|
||||
if (![object isKindOfClass:[MPKey class]])
|
||||
return NO;
|
||||
|
||||
return [self isEqualToKey:object];
|
||||
return [object isKindOfClass:[MPKey class]] && [self isEqualToKey:object];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="Q1S-vU-GGO">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="Q1S-vU-GGO">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
||||
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
@ -103,7 +103,7 @@
|
||||
</constraints>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Sa-Vg-EEI" userLabel="Name Backdrop">
|
||||
<rect key="frame" x="44" y="263" width="128.5" height="16"/>
|
||||
<rect key="frame" x="43.5" y="263" width="128.5" height="16"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalCompressionResistancePriority="1000" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-s0-4SQ" userLabel="Name Field">
|
||||
<rect key="frame" x="5" y="0.0" width="118.5" height="16"/>
|
||||
@ -1629,7 +1629,7 @@
|
||||
</connections>
|
||||
</searchBar>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LEX-BK-PdS" userLabel="Bad Name Tip">
|
||||
<rect key="frame" x="38" y="86" width="300.5" height="75.5"/>
|
||||
<rect key="frame" x="37.5" y="86" width="300.5" height="75.5"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black_top.png" translatesAutoresizingMaskIntoConstraints="NO" id="Rt5-v4-I0R">
|
||||
<rect key="frame" x="0.0" y="0.0" width="300.5" height="75.5"/>
|
||||
@ -1771,7 +1771,7 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1lc-e7-Qme" userLabel="Emergency Generator">
|
||||
<rect key="frame" x="20" y="135" width="335" height="397.5"/>
|
||||
<rect key="frame" x="20" y="135.5" width="335" height="397.5"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Emergency Generator" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="4Lh-s0-Dbt">
|
||||
<rect key="frame" x="20" y="20" width="295" height="21"/>
|
||||
|
@ -40,6 +40,7 @@ fi
|
||||
|
||||
# Optional features.
|
||||
mpw_color=${mpw_color:-1} # Colorized Identicon, requires libncurses-dev.
|
||||
mpw_json=${mpw_json:-1} # Support for JSON-based user configuration format.
|
||||
mpw_sodium=${mpw_sodium:-1} # Use libsodium if available instead of cperciva's libscrypt.
|
||||
|
||||
# Default build flags.
|
||||
@ -255,12 +256,14 @@ mpw() {
|
||||
-l"crypto"
|
||||
)
|
||||
# optional features
|
||||
(( mpw_color )) && CFLAGS+=( -DCOLOR ) LDFLAGS+=( -l"curses" )
|
||||
(( mpw_color )) && CFLAGS+=( -DMPW_COLOR ) LDFLAGS+=( -l"curses" )
|
||||
(( mpw_json )) && CFLAGS+=( -DMPW_JSON ) LDFLAGS+=( -l"json-c" )
|
||||
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-algorithm.c -o core/mpw-algorithm.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-types.c -o core/mpw-types.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-util.c -o core/mpw-util.o
|
||||
cc "${CFLAGS[@]}" "$@" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" \
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-marshall.c -o core/mpw-marshall.o
|
||||
cc "${CFLAGS[@]}" "$@" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" "core/mpw-marshall.o" \
|
||||
"${LDFLAGS[@]}" "cli/mpw-cli.c" -o "mpw"
|
||||
echo "done! Now run ./install or use ./mpw"
|
||||
}
|
||||
|
@ -65,13 +65,11 @@ int main(int argc, char *const argv[]) {
|
||||
uint8_t *sitePasswordInfo = malloc( 128 );
|
||||
iterations = 3000000;
|
||||
masterKey = mpw_masterKeyForUser( fullName, masterPassword, MPAlgorithmVersionCurrent );
|
||||
if (!masterKey) {
|
||||
if (!masterKey)
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
abort();
|
||||
}
|
||||
mpw_getTime( &startTime );
|
||||
for (int i = 1; i <= iterations; ++i) {
|
||||
free( (void *)mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, 128 ) );
|
||||
free( (void *)mpw_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, 128 ) );
|
||||
|
||||
if (modff(100.f * i / iterations, &percent) == 0)
|
||||
fprintf( stderr, "\rhmac-sha-256: iteration %d / %d (%.0f%%)..", i, iterations, percent );
|
||||
@ -110,10 +108,8 @@ int main(int argc, char *const argv[]) {
|
||||
mpw_getTime( &startTime );
|
||||
for (int i = 1; i <= iterations; ++i) {
|
||||
masterKey = mpw_masterKeyForUser( fullName, masterPassword, MPAlgorithmVersionCurrent );
|
||||
if (!masterKey) {
|
||||
if (!masterKey)
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
abort();
|
||||
}
|
||||
|
||||
free( (void *)mpw_passwordForSite(
|
||||
masterKey, siteName, siteType, siteCounter, siteVariant, siteContext, MPAlgorithmVersionCurrent ) );
|
||||
|
@ -1,5 +1,3 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
@ -15,18 +13,22 @@
|
||||
|
||||
#include "mpw-algorithm.h"
|
||||
#include "mpw-util.h"
|
||||
#include "mpw-marshall.h"
|
||||
|
||||
#define MP_env_fullname "MP_FULLNAME"
|
||||
#define MP_env_sitetype "MP_SITETYPE"
|
||||
#define MP_env_sitecounter "MP_SITECOUNTER"
|
||||
#define MP_env_fullName "MP_FULLNAME"
|
||||
#define MP_env_siteType "MP_SITETYPE"
|
||||
#define MP_env_siteCounter "MP_SITECOUNTER"
|
||||
#define MP_env_algorithm "MP_ALGORITHM"
|
||||
|
||||
static void usage() {
|
||||
|
||||
fprintf( stderr, "Usage: mpw [-u name] [-t type] [-c counter] [-a algorithm] [-V variant] [-C context] [-v|-q] [-h] site\n\n" );
|
||||
fprintf( stderr, " -u name Specify the full name of the user.\n"
|
||||
" Defaults to %s in env or prompts.\n\n", MP_env_fullname );
|
||||
fprintf( stderr, " -t type Specify the password's template.\n"
|
||||
inf( ""
|
||||
"Usage: mpw [-u name] [-t type] [-c counter] [-a algorithm] [-V variant] [-C context] [-v|-q] [-h] site\n\n" );
|
||||
inf( ""
|
||||
" -u name Specify the full name of the user.\n"
|
||||
" Defaults to %s in env or prompts.\n\n", MP_env_fullName );
|
||||
inf( ""
|
||||
" -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"
|
||||
@ -35,34 +37,41 @@ static void usage() {
|
||||
" 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, " -a version The algorithm version to use.\n"
|
||||
" p, phrase | 20 character sentence.\n\n", MP_env_siteType );
|
||||
inf( ""
|
||||
" -c counter The value of the counter.\n"
|
||||
" Defaults to %s in env or 1.\n\n", MP_env_siteCounter );
|
||||
inf( ""
|
||||
" -a version The algorithm version to use.\n"
|
||||
" Defaults to %s in env or %d.\n\n", MP_env_algorithm, MPAlgorithmVersionCurrent );
|
||||
fprintf( stderr, " -V variant The kind of content to generate.\n"
|
||||
inf( ""
|
||||
" -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"
|
||||
inf( ""
|
||||
" -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, " -v Increase output verbosity (can be repeated).\n\n" );
|
||||
fprintf( stderr, " -q Decrease output verbosity (can be repeated).\n\n" );
|
||||
fprintf( stderr, " ENVIRONMENT\n\n"
|
||||
inf( ""
|
||||
" -v Increase output verbosity (can be repeated).\n\n" );
|
||||
inf( ""
|
||||
" -q Decrease output verbosity (can be repeated).\n\n" );
|
||||
inf( ""
|
||||
" ENVIRONMENT\n\n"
|
||||
" %-14s | The full name of the user (see -u).\n"
|
||||
" %-14s | The default password template (see -t).\n"
|
||||
" %-14s | The default counter value (see -c).\n"
|
||||
" %-14s | The default algorithm version (see -a).\n\n",
|
||||
MP_env_fullname, MP_env_sitetype, MP_env_sitecounter, MP_env_algorithm );
|
||||
MP_env_fullName, MP_env_siteType, MP_env_siteCounter, MP_env_algorithm );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
static char *homedir(const char *filename) {
|
||||
static char *mpwPath(const char *prefix, const char *extension) {
|
||||
|
||||
char *homedir = NULL;
|
||||
struct passwd *passwd = getpwuid( getuid() );
|
||||
@ -73,9 +82,15 @@ static char *homedir(const char *filename) {
|
||||
if (!homedir)
|
||||
homedir = getcwd( NULL, 0 );
|
||||
|
||||
char *homefile = NULL;
|
||||
asprintf( &homefile, "%s/%s", homedir, filename );
|
||||
return homefile;
|
||||
char *mpwPath = NULL;
|
||||
asprintf( &mpwPath, "%s.%s", prefix, extension );
|
||||
|
||||
char *slash = strstr( mpwPath, "/" );
|
||||
if (slash)
|
||||
*slash = '\0';
|
||||
|
||||
asprintf( &mpwPath, "%s/.mpw.d/%s", homedir, mpwPath );
|
||||
return mpwPath;
|
||||
}
|
||||
|
||||
static char *getline_prompt(const char *prompt) {
|
||||
@ -95,49 +110,43 @@ static char *getline_prompt(const char *prompt) {
|
||||
|
||||
int main(int argc, char *const argv[]) {
|
||||
|
||||
// Read the environment.
|
||||
const char *fullName = NULL;
|
||||
const char *masterPassword = NULL;
|
||||
const char *siteName = NULL;
|
||||
// Master Password defaults.
|
||||
const char *fullName = NULL, *masterPassword = NULL, *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 );
|
||||
MPAlgorithmVersion algorithmVersion = MPAlgorithmVersionCurrent;
|
||||
const char *algorithmVersionString = getenv( MP_env_algorithm );
|
||||
if (algorithmVersionString && strlen( algorithmVersionString ))
|
||||
if (sscanf( algorithmVersionString, "%u", &algorithmVersion ) != 1)
|
||||
ftl( "Invalid %s: %s\n", MP_env_algorithm, algorithmVersionString );
|
||||
uint32_t siteCounter = 1;
|
||||
|
||||
// Read the options.
|
||||
// Read the environment.
|
||||
const char *fullNameArg = getenv( MP_env_fullName ), *masterPasswordArg = NULL, *siteNameArg = NULL;
|
||||
const char *siteTypeArg = getenv( MP_env_siteType ), *siteVariantArg = NULL, *siteContextArg = NULL;
|
||||
const char *siteCounterArg = getenv( MP_env_siteCounter );
|
||||
const char *algorithmVersionArg = getenv( MP_env_algorithm );
|
||||
|
||||
// Read the command-line options.
|
||||
for (int opt; (opt = getopt( argc, argv, "u:P:t:c:V:a:C:vqh" )) != -1;)
|
||||
switch (opt) {
|
||||
case 'u':
|
||||
fullName = strdup( optarg );
|
||||
fullNameArg = optarg;
|
||||
break;
|
||||
case 'P':
|
||||
// Do not use this. Passing your master password via the command-line
|
||||
// is insecure. This is here for non-interactive testing purposes only.
|
||||
masterPassword = strcpy( malloc( strlen( optarg ) + 1 ), optarg );
|
||||
// Passing your master password via the command-line is insecure. Testing purposes only.
|
||||
masterPasswordArg = optarg;
|
||||
break;
|
||||
case 't':
|
||||
siteTypeString = optarg;
|
||||
siteTypeArg = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
siteCounterString = optarg;
|
||||
siteCounterArg = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
siteVariantString = optarg;
|
||||
siteVariantArg = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
if (sscanf( optarg, "%u", &algorithmVersion ) != 1)
|
||||
ftl( "Not a version: %s\n", optarg );
|
||||
algorithmVersionArg = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
siteContextString = optarg;
|
||||
siteContextArg = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
++mpw_verbosity;
|
||||
@ -161,64 +170,112 @@ int main(int argc, char *const argv[]) {
|
||||
break;
|
||||
default:
|
||||
ftl( "Unknown option: -%c\n", optopt );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ftl("Unexpected option: %c", opt);
|
||||
ftl( "Unexpected option: %c", opt );
|
||||
break;
|
||||
}
|
||||
if (optind < argc)
|
||||
siteName = strdup( argv[optind] );
|
||||
siteNameArg = argv[optind];
|
||||
|
||||
// Convert and validate input.
|
||||
if (!fullName && (fullName = getenv( MP_env_fullname )))
|
||||
fullName = strdup( fullName );
|
||||
if (!fullName && !(fullName = getline_prompt( "Your full name:" )))
|
||||
// Empty strings unset the argument.
|
||||
fullNameArg = fullNameArg && strlen( fullNameArg )? fullNameArg: NULL;
|
||||
masterPasswordArg = masterPasswordArg && strlen( masterPasswordArg )? masterPasswordArg: NULL;
|
||||
siteNameArg = siteNameArg && strlen( siteNameArg )? siteNameArg: NULL;
|
||||
siteTypeArg = siteTypeArg && strlen( siteTypeArg )? siteTypeArg: NULL;
|
||||
siteVariantArg = siteVariantArg && strlen( siteVariantArg )? siteVariantArg: NULL;
|
||||
siteContextArg = siteContextArg && strlen( siteContextArg )? siteContextArg: NULL;
|
||||
siteCounterArg = siteCounterArg && strlen( siteCounterArg )? siteCounterArg: NULL;
|
||||
algorithmVersionArg = algorithmVersionArg && strlen( algorithmVersionArg )? algorithmVersionArg: NULL;
|
||||
|
||||
// Determine fullName and siteName.
|
||||
if (!(fullNameArg && (fullName = strdup( fullNameArg ))) &&
|
||||
!(fullName = getline_prompt( "Your full name:" )))
|
||||
ftl( "Missing full name.\n" );
|
||||
if (!siteName && !(siteName = getline_prompt( "Site name:" )))
|
||||
if (!(siteNameArg && (siteName = strdup( siteNameArg ))) &&
|
||||
!(siteName = getline_prompt( "Site name:" )))
|
||||
ftl( "Missing site name.\n" );
|
||||
if (siteCounterString)
|
||||
siteCounter = (uint32_t)atol( siteCounterString );
|
||||
if (siteCounter < 1)
|
||||
ftl( "Invalid site counter: %d\n", siteCounter );
|
||||
if (siteVariantString)
|
||||
siteVariant = mpw_variantWithName( siteVariantString );
|
||||
|
||||
// Read defaults for fullName user from config.
|
||||
char *mpwSitesPath = mpwPath( fullName, "mpsites" );
|
||||
if (!mpwSitesPath)
|
||||
wrn( "Couldn't resolve path for configuration file: %d\n", errno );
|
||||
|
||||
else {
|
||||
FILE *mpwSites = fopen( mpwSitesPath, "r" );
|
||||
free( mpwSitesPath );
|
||||
if (!mpwSites)
|
||||
dbg( "Couldn't open configuration file: %s: %d\n", mpwSitesPath, errno );
|
||||
|
||||
else {
|
||||
size_t readAmount = 4096, bufSize = 0, bufPointer = 0, readSize = 0;
|
||||
void *buf = NULL;
|
||||
while ((buf = realloc( buf, bufSize += readAmount )) &&
|
||||
(bufPointer += (readSize = fread( buf + bufPointer, 1, readAmount, mpwSites ))) &&
|
||||
(readSize == readAmount));
|
||||
|
||||
// Load personal defaults from user config.
|
||||
MPMarshalledUser user = mpw_marshall_read( buf, MPMarshallFormatFlat );
|
||||
if (!user.name)
|
||||
wrn( "Couldn't parse configuration file: %s\n", mpwSitesPath );
|
||||
|
||||
else {
|
||||
fullName = user.name;
|
||||
algorithmVersion = user.version;
|
||||
siteType = user.defaultType;
|
||||
|
||||
for (int s = 0; s < user.sites_count; ++s) {
|
||||
MPMarshalledSite site = user.sites[s];
|
||||
|
||||
if (strcmp( siteName, site.name ) == 0) {
|
||||
siteType = site.type;
|
||||
siteCounter = site.counter;
|
||||
algorithmVersion = site.version;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse default-overriding command-line parameters.
|
||||
if ((algorithmVersionArg && sscanf( algorithmVersionArg, "%u", &algorithmVersion ) != 1) ||
|
||||
algorithmVersion > MPAlgorithmVersionLatest)
|
||||
ftl( "Invalid algorithm: %s\n", algorithmVersionArg );
|
||||
if (siteCounterArg) {
|
||||
long long int siteCounterInt = atoll( siteCounterArg );
|
||||
if (siteCounterInt < 0 || siteCounterInt > UINT32_MAX)
|
||||
ftl( "Invalid site counter: %s\n", siteCounterArg );
|
||||
siteCounter = (uint32_t)siteCounterInt;
|
||||
}
|
||||
if (siteVariantArg)
|
||||
siteVariant = mpw_variantWithName( siteVariantArg );
|
||||
if (siteVariant == MPSiteVariantLogin)
|
||||
siteType = MPSiteTypeGeneratedName;
|
||||
if (siteVariant == MPSiteVariantAnswer)
|
||||
siteType = MPSiteTypeGeneratedPhrase;
|
||||
if (siteTypeString)
|
||||
siteType = mpw_typeWithName( siteTypeString );
|
||||
trc( "algorithmVersion: %u\n", algorithmVersion );
|
||||
|
||||
// Read the master password.
|
||||
char *mpwConfigPath = homedir( ".mpw" );
|
||||
if (!mpwConfigPath)
|
||||
ftl( "Couldn't resolve path for configuration file: %d\n", errno );
|
||||
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;
|
||||
}
|
||||
}
|
||||
mpw_free( line, linecap );
|
||||
}
|
||||
while (!masterPassword || !strlen(masterPassword))
|
||||
if (siteTypeArg)
|
||||
siteType = mpw_typeWithName( siteTypeArg );
|
||||
if (!(masterPasswordArg && (masterPassword = strdup( masterPasswordArg ))))
|
||||
while (!masterPassword || !strlen( masterPassword ))
|
||||
masterPassword = getpass( "Your master password: " );
|
||||
|
||||
// Summarize operation.
|
||||
const char *identicon = mpw_identicon( fullName, masterPassword );
|
||||
if (!identicon) {
|
||||
err( "Couldn't determine identicon.\n" );
|
||||
} else {
|
||||
fprintf( stderr, "%s's password for %s:\n[ %s ]: ", fullName, siteName, identicon );
|
||||
if (!identicon)
|
||||
wrn( "Couldn't determine identicon.\n" );
|
||||
dbg( "-----------------\n" );
|
||||
dbg( "fullName : %s\n", fullName );
|
||||
trc( "masterPassword : %s\n", masterPassword );
|
||||
dbg( "identicon : %s\n", identicon );
|
||||
dbg( "siteName : %s\n", siteName );
|
||||
dbg( "siteType : %u\n", siteType );
|
||||
dbg( "algorithmVersion : %u\n", algorithmVersion );
|
||||
dbg( "siteCounter : %u\n", siteCounter );
|
||||
dbg( "-----------------\n\n" );
|
||||
inf( "%s's password for %s:\n[ %s ]: ", fullName, siteName, identicon );
|
||||
mpw_free_string( identicon );
|
||||
}
|
||||
|
||||
// Output the password.
|
||||
const uint8_t *masterKey = mpw_masterKeyForUser(
|
||||
@ -229,8 +286,8 @@ int main(int argc, char *const argv[]) {
|
||||
ftl( "Couldn't derive master key." );
|
||||
|
||||
const char *sitePassword = mpw_passwordForSite(
|
||||
masterKey, siteName, siteType, siteCounter, siteVariant, siteContextString, algorithmVersion );
|
||||
mpw_free( masterKey, MP_dkLen );
|
||||
masterKey, siteName, siteType, siteCounter, siteVariant, siteContextArg, algorithmVersion );
|
||||
mpw_free( masterKey, MPMasterKeySize );
|
||||
mpw_free_string( siteName );
|
||||
if (!sitePassword)
|
||||
ftl( "Couldn't derive site password." );
|
||||
|
@ -15,10 +15,8 @@ int main(int argc, char *const argv[]) {
|
||||
int failedTests = 0;
|
||||
|
||||
xmlNodePtr tests = xmlDocGetRootElement( xmlParseFile( "mpw_tests.xml" ) );
|
||||
if (!tests) {
|
||||
if (!tests)
|
||||
ftl( "Couldn't find test case: mpw_tests.xml\n" );
|
||||
abort();
|
||||
}
|
||||
|
||||
for (xmlNodePtr testCase = tests->children; testCase; testCase = testCase->next) {
|
||||
if (testCase->type != XML_ELEMENT_NODE || xmlStrcmp( testCase->name, BAD_CAST "case" ) != 0)
|
||||
@ -48,7 +46,7 @@ int main(int argc, char *const argv[]) {
|
||||
}
|
||||
|
||||
// 1. calculate the master key.
|
||||
const uint8_t *masterKey = mpw_masterKeyForUser(
|
||||
MPMasterKey masterKey = mpw_masterKeyForUser(
|
||||
(char *)fullName, (char *)masterPassword, algorithm );
|
||||
if (!masterKey)
|
||||
ftl( "Couldn't derive master key." );
|
||||
@ -56,7 +54,7 @@ int main(int argc, char *const argv[]) {
|
||||
// 2. calculate the site password.
|
||||
const char *sitePassword = mpw_passwordForSite(
|
||||
masterKey, (char *)siteName, siteType, siteCounter, siteVariant, (char *)siteContext, algorithm );
|
||||
mpw_free( masterKey, MP_dkLen );
|
||||
mpw_free( masterKey, MPMasterKeySize );
|
||||
if (!sitePassword)
|
||||
ftl( "Couldn't derive site password." );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user