#if 0
#define DEBUGTIME 1
#else
#define DEBUGTIME 0
#endif
#if DEBUGTIME
#include <syslog.h>
#define SRVLOG1(A,B, args...) syslog(LOG_ALERT, (B), ##args)
#endif
#include <sys/stat.h>
#include "AuthFile.h"
#include "CAuthFileBase.h"
#include "CReplicaFile.h"
#define kDSValueAuthAuthorityShadowHash ";ShadowHash;"
#define kDSTagAuthAuthorityShadowHash "ShadowHash"
#define kDSTagAuthAuthorityBetterHashOnly "BetterHashOnly"
#define kHashNameListPrefix "HASHLIST:"
#if DEBUGTIME
void GetTimeAsString( BSDTimeStructCopy *inTime, char *outString )
{
sprintf( outString, "%d/%d/%d %d:%d",
inTime->tm_mon + 1,
inTime->tm_mday,
inTime->tm_year + 1900,
inTime->tm_hour,
inTime->tm_min );
}
void LogTimeAsString( BSDTimeStructCopy *inTime, char *preStr )
{
char timeStr[256];
GetTimeAsString( inTime, timeStr );
SRVLOG2( kLogMeta, "%s: %s", preStr, timeStr );
}
#else
#define LogTimeAsString(A,B)
#endif
int TimeIsStale( BSDTimeStructCopy *inTime )
{
time_t theTime, theGMTime;
time(&theGMTime);
theTime = timegm( (struct tm *)inTime );
if ( theTime <= 0 )
theTime = 0x7FFFFFFF;
#if DEBUGTIME
LogTimeAsString( (BSDTimeStructCopy *)inTime, "pwrec" );
SRVLOG1( kLogMeta, "theTime: %ld, %ld", theGMTime, theTime );
SRVLOG1( kLogMeta, "diff: %ld", theGMTime - theTime );
#endif
return ( (unsigned long)theGMTime > (unsigned long)theTime );
}
int LoginTimeIsStale( BSDTimeStructCopy *inLastLogin, unsigned long inMaxMinutesOfNonUse )
{
time_t theTime, theGMTime;
long maxMinutesOfNonUse = (long)(inMaxMinutesOfNonUse & 0x7FFFFFFF);
time(&theGMTime);
theTime = timegm( (struct tm *)inLastLogin );
#if DEBUGTIME
LogTimeAsString( (BSDTimeStructCopy *)inLastLogin, "pwrec" );
SRVLOG1( kLogMeta, "theGMTime, theTime: %ld, %ld", theGMTime, theTime );
SRVLOG1( kLogMeta, "diff: %ld", ((theGMTime - theTime)/60) );
SRVLOG1( kLogMeta, "min-nonuse: %ld", maxMinutesOfNonUse );
SRVLOG1( kLogMeta, "returning: %d", ( ((theGMTime - theTime)/60) > maxMinutesOfNonUse ) );
#endif
return ( ((theGMTime - theTime)/60) > maxMinutesOfNonUse );
}
void PWGlobalAccessFeaturesToString( PWGlobalAccessFeatures *inAccessFeatures, char *outString )
{
char temp1Str[256];
char temp2Str[256];
char temp3Str[512];
int historyValue = 0;
if ( outString == NULL || inAccessFeatures == NULL )
throw(-1);
if ( inAccessFeatures->usingHistory )
historyValue = 1 + inAccessFeatures->historyCount;
sprintf( temp1Str, "%s=%d %s=%d %s=%d %s=%d %s=%d %s=%d ",
kPWPolicyStr_usingHistory, historyValue,
kPWPolicyStr_canModifyPasswordforSelf, (inAccessFeatures->noModifyPasswordforSelf == 0),
kPWPolicyStr_usingExpirationDate, (inAccessFeatures->usingExpirationDate != 0),
kPWPolicyStr_usingHardExpirationDate, (inAccessFeatures->usingHardExpirationDate != 0),
kPWPolicyStr_requiresAlpha, (inAccessFeatures->requiresAlpha != 0),
kPWPolicyStr_requiresNumeric, (inAccessFeatures->requiresNumeric != 0) );
sprintf( temp2Str, "%s=%lu %s=%lu %s=%lu ",
kPWPolicyStr_expirationDateGMT, timegm( (struct tm *)&inAccessFeatures->expirationDateGMT ),
kPWPolicyStr_hardExpireDateGMT, timegm( (struct tm *)&inAccessFeatures->hardExpireDateGMT ),
kPWPolicyStr_maxMinutesUntilChangePW, inAccessFeatures->maxMinutesUntilChangePassword );
sprintf( temp3Str, "%s=%lu %s=%lu %s=%u %s=%u %s=%u %s=%d %s=%d %s=%d ",
kPWPolicyStr_maxMinutesUntilDisabled, inAccessFeatures->maxMinutesUntilDisabled,
kPWPolicyStr_maxMinutesOfNonUse, inAccessFeatures->maxMinutesOfNonUse,
kPWPolicyStr_maxFailedLoginAttempts, inAccessFeatures->maxFailedLoginAttempts,
kPWPolicyStr_minChars, inAccessFeatures->minChars,
kPWPolicyStr_maxChars, inAccessFeatures->maxChars,
kPWPolicyStr_passwordCannotBeName, (inAccessFeatures->passwordCannotBeName != 0),
kPWPolicyStr_requiresMixedCase, (inAccessFeatures->requiresMixedCase != 0),
kPWPolicyStr_newPasswordRequired, (inAccessFeatures->newPasswordRequired != 0) );
strcpy( outString, temp1Str );
strcat( outString, temp2Str );
strcat( outString, temp3Str );
}
void PWGlobalAccessFeaturesToStringExtra( PWGlobalAccessFeatures *inAccessFeatures, PWGlobalMoreAccessFeatures *inExtraFeatures, int inMaxLen, char *outString )
{
char tempStr[2048];
long len;
if ( outString == NULL || inAccessFeatures == NULL )
return;
PWGlobalAccessFeaturesToString( inAccessFeatures, tempStr );
len = snprintf( outString, inMaxLen, "%s", tempStr );
if ( len >= inMaxLen )
return;
snprintf( outString + len, inMaxLen - len, "%s=%lu %s=%lu",
kPWPolicyStr_minutesUntilFailedLoginReset, inExtraFeatures->minutesUntilFailedLoginReset,
kPWPolicyStr_notGuessablePattern, inExtraFeatures->notGuessablePattern );
}
void PWAccessFeaturesToString( PWAccessFeatures *inAccessFeatures, char *outString )
{
char temp1Str[256];
char temp2Str[2048];
char temp3Str[64];
if ( outString == NULL || inAccessFeatures == NULL )
throw(-1);
snprintf( temp1Str, sizeof(temp1Str), "%s=%d %s=%d %s=%d ",
kPWPolicyStr_isDisabled, (inAccessFeatures->isDisabled != 0),
kPWPolicyStr_isAdminUser, (inAccessFeatures->isAdminUser != 0),
kPWPolicyStr_newPasswordRequired, (inAccessFeatures->newPasswordRequired != 0) );
PWAccessFeaturesToStringWithoutStateInfo( inAccessFeatures, temp2Str );
snprintf( temp3Str, sizeof(temp3Str), " %s=%d",
kPWPolicyStr_isSessionKeyAgent, (inAccessFeatures->isSessionKeyAgent != 0) );
strcpy( outString, temp1Str );
strcat( outString, temp2Str );
strcat( outString, temp3Str );
}
void PWAccessFeaturesToStringExtra( PWAccessFeatures *inAccessFeatures, PWMoreAccessFeatures *inExtraFeatures, int inMaxLen, char *outString )
{
char temp2Str[2048];
if ( outString == NULL || inAccessFeatures == NULL )
return;
int segment1Length = snprintf( outString, inMaxLen, "%s=%d %s=%d %s=%d ",
kPWPolicyStr_isDisabled, (inAccessFeatures->isDisabled != 0),
kPWPolicyStr_isAdminUser, (inAccessFeatures->isAdminUser != 0),
kPWPolicyStr_newPasswordRequired, (inAccessFeatures->newPasswordRequired != 0) );
inMaxLen -= segment1Length;
PWAccessFeaturesToStringWithoutStateInfoExtra( inAccessFeatures, inExtraFeatures, sizeof(temp2Str), temp2Str );
int segment2Length = snprintf( outString + segment1Length, inMaxLen, "%s", temp2Str );
inMaxLen -= segment2Length;
snprintf( outString + segment1Length + segment2Length, inMaxLen, " %s=%d",
kPWPolicyStr_isSessionKeyAgent, (inAccessFeatures->isSessionKeyAgent != 0) );
}
void PWActualAccessFeaturesToString( PWGlobalAccessFeatures *inGAccessFeatures, PWAccessFeatures *inAccessFeatures, char *outString )
{
int historyValue = 0;
int usingExpirationDate;
int usingHardExpirationDate;
int requiresAlpha;
int requiresNumeric;
int passwordCannotBeName;
UInt32 maxMinutesUntilChangePassword;
UInt32 maxMinutesUntilDisabled;
UInt32 maxMinutesOfNonUse;
UInt16 maxFailedLoginAttempts;
UInt16 minChars;
UInt16 maxChars;
char temp1Str[256];
char temp2Str[256];
char temp3Str[256];
char temp4Str[512];
if ( outString == NULL || inAccessFeatures == NULL )
throw(-1);
usingExpirationDate = (inAccessFeatures->usingExpirationDate != 0);
if ( usingExpirationDate == 0 )
usingExpirationDate = (inGAccessFeatures->usingExpirationDate != 0);
usingHardExpirationDate = (inAccessFeatures->usingHardExpirationDate != 0);
if ( usingHardExpirationDate == 0 )
usingHardExpirationDate = (inGAccessFeatures->usingHardExpirationDate != 0);
requiresAlpha = (inAccessFeatures->requiresAlpha != 0);
if ( requiresAlpha == 0 )
requiresAlpha = (inGAccessFeatures->requiresAlpha != 0);
requiresNumeric = (inAccessFeatures->requiresNumeric != 0);
if ( requiresNumeric == 0 )
requiresNumeric = (inGAccessFeatures->requiresNumeric != 0);
passwordCannotBeName = (inAccessFeatures->passwordCannotBeName != 0);
if ( passwordCannotBeName == 0 )
passwordCannotBeName = (inGAccessFeatures->passwordCannotBeName != 0);
maxMinutesUntilChangePassword = inAccessFeatures->maxMinutesUntilChangePassword;
if ( maxMinutesUntilChangePassword == 0 )
maxMinutesUntilChangePassword = inGAccessFeatures->maxMinutesUntilChangePassword;
maxMinutesUntilDisabled = inAccessFeatures->maxMinutesUntilDisabled;
if ( maxMinutesUntilDisabled == 0 )
maxMinutesUntilDisabled = inGAccessFeatures->maxMinutesUntilDisabled;
maxMinutesOfNonUse = inAccessFeatures->maxMinutesOfNonUse;
if ( maxMinutesOfNonUse == 0 )
maxMinutesOfNonUse = inGAccessFeatures->maxMinutesOfNonUse;
maxFailedLoginAttempts = inAccessFeatures->maxFailedLoginAttempts;
if ( maxFailedLoginAttempts == 0 )
maxFailedLoginAttempts = inGAccessFeatures->maxFailedLoginAttempts;
minChars = inAccessFeatures->minChars;
if ( minChars == 0 )
minChars = inGAccessFeatures->minChars;
maxChars = inAccessFeatures->maxChars;
if ( maxChars == 0 )
maxChars = inGAccessFeatures->maxChars;
if ( inAccessFeatures->usingHistory )
historyValue = 1 + inAccessFeatures->historyCount;
else
if ( inGAccessFeatures->usingHistory )
historyValue = 1 + inGAccessFeatures->historyCount;
sprintf( temp1Str, "%s=%d %s=%d %s=%d %s=%d ",
kPWPolicyStr_isDisabled, (inAccessFeatures->isDisabled != 0),
kPWPolicyStr_isAdminUser, (inAccessFeatures->isAdminUser != 0),
kPWPolicyStr_newPasswordRequired, (inAccessFeatures->newPasswordRequired != 0),
kPWPolicyStr_usingHistory, historyValue );
sprintf( temp2Str, "%s=%d %s=%d %s=%d %s=%d ",
kPWPolicyStr_canModifyPasswordforSelf, (inAccessFeatures->canModifyPasswordforSelf != 0),
kPWPolicyStr_usingExpirationDate, usingExpirationDate,
kPWPolicyStr_usingHardExpirationDate, usingHardExpirationDate,
kPWPolicyStr_requiresAlpha, requiresAlpha );
sprintf( temp3Str, "%s=%d %s=%lu %s=%lu ",
kPWPolicyStr_requiresNumeric, requiresNumeric,
kPWPolicyStr_expirationDateGMT, timegm( (struct tm *)&inAccessFeatures->expirationDateGMT ),
kPWPolicyStr_hardExpireDateGMT, timegm( (struct tm *)&inAccessFeatures->hardExpireDateGMT ) );
snprintf( temp4Str, sizeof(temp4Str), "%s=%lu %s=%lu %s=%lu %s=%u %s=%u %s=%u %s=%d %s=%d",
kPWPolicyStr_maxMinutesUntilChangePW, maxMinutesUntilChangePassword,
kPWPolicyStr_maxMinutesUntilDisabled, maxMinutesUntilDisabled,
kPWPolicyStr_maxMinutesOfNonUse, maxMinutesOfNonUse,
kPWPolicyStr_maxFailedLoginAttempts, maxFailedLoginAttempts,
kPWPolicyStr_minChars, minChars,
kPWPolicyStr_maxChars, maxChars,
kPWPolicyStr_passwordCannotBeName, passwordCannotBeName,
kPWPolicyStr_isSessionKeyAgent, (inAccessFeatures->isSessionKeyAgent != 0) );
strcpy( outString, temp1Str );
strcat( outString, temp2Str );
strcat( outString, temp3Str );
strcat( outString, temp4Str );
}
void PWActualAccessFeaturesToStringExtra( PWGlobalAccessFeatures *inGAccessFeatures, PWAccessFeatures *inAccessFeatures, PWMoreAccessFeatures *inExtraFeatures, int inMaxLen, char *outString )
{
int segment1Length = 0;
unsigned int requiresMixedCase = (inExtraFeatures->requiresMixedCase || inGAccessFeatures->requiresMixedCase);
unsigned long notGuessablePattern = inExtraFeatures->notGuessablePattern;
if ( inMaxLen > 1280 )
{
PWActualAccessFeaturesToString( inGAccessFeatures, inAccessFeatures, outString );
segment1Length = strlen( outString );
}
else
{
char tempStr[1280];
PWActualAccessFeaturesToString( inGAccessFeatures, inAccessFeatures, tempStr );
segment1Length = snprintf( outString, inMaxLen, "%s", tempStr );
}
inMaxLen -= segment1Length;
if ( notGuessablePattern == 0 )
notGuessablePattern = 0;
snprintf( outString + segment1Length, inMaxLen, " %s=%d, %s=%lu",
kPWPolicyStr_requiresMixedCase, (requiresMixedCase != 0),
kPWPolicyStr_notGuessablePattern, notGuessablePattern );
}
void PWAccessFeaturesToStringWithoutStateInfo( PWAccessFeatures *inAccessFeatures, char *outString )
{
int historyValue = 0;
if ( outString == NULL || inAccessFeatures == NULL )
throw(-1);
if ( inAccessFeatures->usingHistory )
historyValue = 1 + inAccessFeatures->historyCount;
snprintf( outString, 2048,
"%s=%d %s=%d %s=%d %s=%d %s=%d %s=%d %s=%lu %s=%lu %s=%lu %s=%lu %s=%lu %s=%u %s=%u %s=%u %s=%d",
kPWPolicyStr_usingHistory, historyValue,
kPWPolicyStr_canModifyPasswordforSelf, (inAccessFeatures->canModifyPasswordforSelf != 0),
kPWPolicyStr_usingExpirationDate, (inAccessFeatures->usingExpirationDate != 0),
kPWPolicyStr_usingHardExpirationDate, (inAccessFeatures->usingHardExpirationDate != 0),
kPWPolicyStr_requiresAlpha, (inAccessFeatures->requiresAlpha != 0),
kPWPolicyStr_requiresNumeric, (inAccessFeatures->requiresNumeric != 0),
kPWPolicyStr_expirationDateGMT, timegm( (struct tm *)&inAccessFeatures->expirationDateGMT ),
kPWPolicyStr_hardExpireDateGMT, timegm( (struct tm *)&inAccessFeatures->hardExpireDateGMT ),
kPWPolicyStr_maxMinutesUntilChangePW, inAccessFeatures->maxMinutesUntilChangePassword,
kPWPolicyStr_maxMinutesUntilDisabled, inAccessFeatures->maxMinutesUntilDisabled,
kPWPolicyStr_maxMinutesOfNonUse, inAccessFeatures->maxMinutesOfNonUse,
kPWPolicyStr_maxFailedLoginAttempts, inAccessFeatures->maxFailedLoginAttempts,
kPWPolicyStr_minChars, inAccessFeatures->minChars,
kPWPolicyStr_maxChars, inAccessFeatures->maxChars,
kPWPolicyStr_passwordCannotBeName, (inAccessFeatures->passwordCannotBeName != 0) );
}
void PWAccessFeaturesToStringWithoutStateInfoExtra( PWAccessFeatures *inAccessFeatures, PWMoreAccessFeatures *inExtraFeatures, int inMaxLen, char *outString )
{
if ( inMaxLen >= 2048 )
{
PWAccessFeaturesToStringWithoutStateInfo( inAccessFeatures, outString );
}
else
{
char tempStr[2048];
PWAccessFeaturesToStringWithoutStateInfo( inAccessFeatures, tempStr );
snprintf( outString, inMaxLen, "%s", tempStr );
}
long firstSegmentLen = strlen( outString );
inMaxLen -= firstSegmentLen;
if ( inMaxLen > 0 )
{
snprintf( outString + firstSegmentLen, inMaxLen,
" %s=%d %s=%lu",
kPWPolicyStr_requiresMixedCase, (inExtraFeatures->requiresMixedCase != 0),
kPWPolicyStr_notGuessablePattern, inExtraFeatures->notGuessablePattern );
}
}
Boolean StringToPWGlobalAccessFeatures( const char *inString, PWGlobalAccessFeatures *inOutAccessFeatures )
{
const char *usingHistory = strstr( inString, kPWPolicyStr_usingHistory );
const char *canModifyPasswordforSelf = strstr( inString, kPWPolicyStr_canModifyPasswordforSelf );
const char *usingExpirationDate = strstr( inString, kPWPolicyStr_usingExpirationDate );
const char *usingHardExpirationDate = strstr( inString, kPWPolicyStr_usingHardExpirationDate );
const char *requiresAlpha = strstr( inString, kPWPolicyStr_requiresAlpha );
const char *requiresNumeric = strstr( inString, kPWPolicyStr_requiresNumeric );
const char *expirationDateGMT = strstr( inString, kPWPolicyStr_expirationDateGMT );
const char *hardExpireDateGMT = strstr( inString, kPWPolicyStr_hardExpireDateGMT );
const char *maxMinutesUntilChangePassword = strstr( inString, kPWPolicyStr_maxMinutesUntilChangePW );
const char *maxMinutesUntilDisabled = strstr( inString, kPWPolicyStr_maxMinutesUntilDisabled );
const char *maxMinutesOfNonUse = strstr( inString, kPWPolicyStr_maxMinutesOfNonUse );
const char *maxFailedLoginAttempts = strstr( inString, kPWPolicyStr_maxFailedLoginAttempts );
const char *minChars = strstr( inString, kPWPolicyStr_minChars );
const char *maxChars = strstr( inString, kPWPolicyStr_maxChars );
const char *passwordCannotBeName = strstr( inString, kPWPolicyStr_passwordCannotBeName );
const char *requiresMixedCase = strstr( inString, kPWPolicyStr_requiresMixedCase );
const char *newPasswordRequired = strstr( inString, kPWPolicyStr_newPasswordRequired );
unsigned long value;
if ( StringToPWAccessFeatures_GetValue( usingHistory, &value ) )
{
if ( value > 0 )
{
if ( value > kPWFileMaxHistoryCount )
value = kPWFileMaxHistoryCount;
inOutAccessFeatures->usingHistory = 1;
inOutAccessFeatures->historyCount = value - 1;
}
else
{
inOutAccessFeatures->usingHistory = 0;
inOutAccessFeatures->historyCount = 0;
}
}
if ( StringToPWAccessFeatures_GetValue( canModifyPasswordforSelf, &value ) )
inOutAccessFeatures->noModifyPasswordforSelf = (value==0);
if ( StringToPWAccessFeatures_GetValue( usingExpirationDate, &value ) )
inOutAccessFeatures->usingExpirationDate = value;
if ( StringToPWAccessFeatures_GetValue( usingHardExpirationDate, &value ) )
inOutAccessFeatures->usingHardExpirationDate = value;
if ( StringToPWAccessFeatures_GetValue( requiresAlpha, &value ) )
inOutAccessFeatures->requiresAlpha = value;
if ( StringToPWAccessFeatures_GetValue( requiresNumeric, &value ) )
inOutAccessFeatures->requiresNumeric = value;
if ( StringToPWAccessFeatures_GetValue( expirationDateGMT, &value ) )
gmtime_r( (time_t *)&value, (struct tm *)&inOutAccessFeatures->expirationDateGMT );
if ( StringToPWAccessFeatures_GetValue( hardExpireDateGMT, &value ) )
gmtime_r( (time_t *)&value, (struct tm *)&inOutAccessFeatures->hardExpireDateGMT );
if ( StringToPWAccessFeatures_GetValue( maxMinutesUntilChangePassword, &value ) )
inOutAccessFeatures->maxMinutesUntilChangePassword = value;
if ( StringToPWAccessFeatures_GetValue( maxMinutesUntilDisabled, &value ) )
inOutAccessFeatures->maxMinutesUntilDisabled = value;
if ( StringToPWAccessFeatures_GetValue( maxMinutesOfNonUse, &value ) )
inOutAccessFeatures->maxMinutesOfNonUse = value;
if ( StringToPWAccessFeatures_GetValue( maxFailedLoginAttempts, &value ) )
inOutAccessFeatures->maxFailedLoginAttempts = (UInt16)value;
if ( StringToPWAccessFeatures_GetValue( minChars, &value ) )
inOutAccessFeatures->minChars = value;
if ( StringToPWAccessFeatures_GetValue( maxChars, &value ) )
inOutAccessFeatures->maxChars = value;
if ( StringToPWAccessFeatures_GetValue( passwordCannotBeName, &value ) )
inOutAccessFeatures->passwordCannotBeName = value;
if ( StringToPWAccessFeatures_GetValue( requiresMixedCase, &value ) )
inOutAccessFeatures->requiresMixedCase = value;
if ( StringToPWAccessFeatures_GetValue( newPasswordRequired, &value ) )
inOutAccessFeatures->newPasswordRequired = value;
return true;
}
Boolean StringToPWGlobalAccessFeaturesExtra( const char *inString, PWGlobalAccessFeatures *inOutAccessFeatures, PWGlobalMoreAccessFeatures *inOutExtraFeatures )
{
Boolean result = StringToPWGlobalAccessFeatures( inString, inOutAccessFeatures );
const char *notGuessablePattern = strstr( inString, kPWPolicyStr_notGuessablePattern );
const char *minutesUntilFailedLoginReset = strstr( inString, kPWPolicyStr_minutesUntilFailedLoginReset );
unsigned long value;
if ( StringToPWAccessFeatures_GetValue( notGuessablePattern, &value ) )
inOutExtraFeatures->notGuessablePattern = value;
if ( StringToPWAccessFeatures_GetValue( minutesUntilFailedLoginReset, &value ) )
inOutExtraFeatures->minutesUntilFailedLoginReset = value;
return result;
}
Boolean StringToPWAccessFeatures( const char *inString, PWAccessFeatures *inOutAccessFeatures )
{
const char *isDisabled = strstr( inString, kPWPolicyStr_isDisabled );
const char *isAdminUser = strstr( inString, kPWPolicyStr_isAdminUser );
const char *newPasswordRequired = strstr( inString, kPWPolicyStr_newPasswordRequired );
const char *usingHistory = strstr( inString, kPWPolicyStr_usingHistory );
const char *canModifyPasswordforSelf = strstr( inString, kPWPolicyStr_canModifyPasswordforSelf );
const char *usingExpirationDate = strstr( inString, kPWPolicyStr_usingExpirationDate );
const char *usingHardExpirationDate = strstr( inString, kPWPolicyStr_usingHardExpirationDate );
const char *requiresAlpha = strstr( inString, kPWPolicyStr_requiresAlpha );
const char *requiresNumeric = strstr( inString, kPWPolicyStr_requiresNumeric );
const char *expirationDateGMT = strstr( inString, kPWPolicyStr_expirationDateGMT );
const char *hardExpireDateGMT = strstr( inString, kPWPolicyStr_hardExpireDateGMT );
const char *maxMinutesUntilChangePassword = strstr( inString, kPWPolicyStr_maxMinutesUntilChangePW );
const char *maxMinutesUntilDisabled = strstr( inString, kPWPolicyStr_maxMinutesUntilDisabled );
const char *maxMinutesOfNonUse = strstr( inString, kPWPolicyStr_maxMinutesOfNonUse );
const char *maxFailedLoginAttempts = strstr( inString, kPWPolicyStr_maxFailedLoginAttempts );
const char *minChars = strstr( inString, kPWPolicyStr_minChars );
const char *maxChars = strstr( inString, kPWPolicyStr_maxChars );
const char *passwordCannotBeName = strstr( inString, kPWPolicyStr_passwordCannotBeName );
const char *isSessionKeyAgent = strstr( inString, kPWPolicyStr_isSessionKeyAgent );
const char *resetToGlobalDefaults = strstr( inString, kPWPolicyStr_resetToGlobalDefaults );
unsigned long value;
if ( StringToPWAccessFeatures_GetValue( isDisabled, &value ) )
inOutAccessFeatures->isDisabled = value;
if ( StringToPWAccessFeatures_GetValue( isAdminUser, &value ) )
inOutAccessFeatures->isAdminUser = value;
if ( StringToPWAccessFeatures_GetValue( newPasswordRequired, &value ) )
inOutAccessFeatures->newPasswordRequired = value;
if ( StringToPWAccessFeatures_GetValue( usingHistory, &value ) )
{
if ( value > 0 )
{
if ( value > kPWFileMaxHistoryCount )
value = kPWFileMaxHistoryCount;
inOutAccessFeatures->usingHistory = 1;
inOutAccessFeatures->historyCount = value - 1;
}
else
{
inOutAccessFeatures->usingHistory = 0;
inOutAccessFeatures->historyCount = 0;
}
}
if ( StringToPWAccessFeatures_GetValue( canModifyPasswordforSelf, &value ) )
inOutAccessFeatures->canModifyPasswordforSelf = value;
if ( StringToPWAccessFeatures_GetValue( usingExpirationDate, &value ) )
inOutAccessFeatures->usingExpirationDate = value;
if ( StringToPWAccessFeatures_GetValue( usingHardExpirationDate, &value ) )
inOutAccessFeatures->usingHardExpirationDate = value;
if ( StringToPWAccessFeatures_GetValue( requiresAlpha, &value ) )
inOutAccessFeatures->requiresAlpha = value;
if ( StringToPWAccessFeatures_GetValue( requiresNumeric, &value ) )
inOutAccessFeatures->requiresNumeric = value;
if ( StringToPWAccessFeatures_GetValue( expirationDateGMT, &value ) )
gmtime_r( (time_t *)&value, (struct tm *)&inOutAccessFeatures->expirationDateGMT );
if ( StringToPWAccessFeatures_GetValue( hardExpireDateGMT, &value ) )
gmtime_r( (time_t *)&value, (struct tm *)&inOutAccessFeatures->hardExpireDateGMT );
if ( StringToPWAccessFeatures_GetValue( maxMinutesUntilChangePassword, &value ) )
inOutAccessFeatures->maxMinutesUntilChangePassword = value;
if ( StringToPWAccessFeatures_GetValue( maxMinutesUntilDisabled, &value ) )
inOutAccessFeatures->maxMinutesUntilDisabled = value;
if ( StringToPWAccessFeatures_GetValue( maxMinutesOfNonUse, &value ) )
inOutAccessFeatures->maxMinutesOfNonUse = value;
if ( StringToPWAccessFeatures_GetValue( maxFailedLoginAttempts, &value ) )
inOutAccessFeatures->maxFailedLoginAttempts = (UInt16)value;
if ( StringToPWAccessFeatures_GetValue( minChars, &value ) )
inOutAccessFeatures->minChars = value;
if ( StringToPWAccessFeatures_GetValue( maxChars, &value ) )
inOutAccessFeatures->maxChars = value;
if ( StringToPWAccessFeatures_GetValue( passwordCannotBeName, &value ) )
inOutAccessFeatures->passwordCannotBeName = value;
if ( StringToPWAccessFeatures_GetValue( isSessionKeyAgent, &value ) )
inOutAccessFeatures->isSessionKeyAgent = value;
if ( StringToPWAccessFeatures_GetValue( resetToGlobalDefaults, &value ) && value > 0 )
{
inOutAccessFeatures->usingHistory = 0;
inOutAccessFeatures->canModifyPasswordforSelf = 1;
inOutAccessFeatures->usingExpirationDate = 0;
inOutAccessFeatures->usingHardExpirationDate = 0;
inOutAccessFeatures->requiresAlpha = 0;
inOutAccessFeatures->requiresNumeric = 0;
inOutAccessFeatures->passwordCannotBeName = 0;
inOutAccessFeatures->historyCount = 0;
inOutAccessFeatures->maxMinutesUntilChangePassword = 0;
inOutAccessFeatures->maxMinutesUntilDisabled = 0;
inOutAccessFeatures->maxMinutesOfNonUse = 0;
inOutAccessFeatures->maxFailedLoginAttempts = 0;
inOutAccessFeatures->minChars = 0;
inOutAccessFeatures->maxChars = 0;
}
return true;
}
Boolean StringToPWAccessFeaturesExtra( const char *inString, PWAccessFeatures *inOutAccessFeatures, PWMoreAccessFeatures *inOutExtraFeatures )
{
const char *requiresMixedCase = strstr( inString, kPWPolicyStr_requiresMixedCase );
const char *notGuessablePattern = strstr( inString, kPWPolicyStr_notGuessablePattern );
const char *resetToGlobalDefaults = strstr( inString, kPWPolicyStr_resetToGlobalDefaults );
unsigned long value;
if ( inOutExtraFeatures == NULL )
return false;
Boolean result = StringToPWAccessFeatures( inString, inOutAccessFeatures );
if ( result )
{
if ( StringToPWAccessFeatures_GetValue( requiresMixedCase, &value ) )
inOutExtraFeatures->requiresMixedCase = value;
if ( StringToPWAccessFeatures_GetValue( notGuessablePattern, &value ) )
inOutExtraFeatures->notGuessablePattern = value;
if ( StringToPWAccessFeatures_GetValue( resetToGlobalDefaults, &value ) && value > 0 )
{
inOutExtraFeatures->requiresMixedCase = 0;
inOutExtraFeatures->notGuessablePattern = 0;
}
result = true;
}
return result;
}
Boolean StringToPWAccessFeatures_GetValue( const char *inString, unsigned long *outValue )
{
const char *valueStr;
char valBuffer[64];
unsigned int idx = 0;
if ( inString == NULL )
return false;
valueStr = strchr( inString, '=' );
if ( valueStr == NULL )
return false;
valueStr++;
while ( *valueStr && *valueStr > ' ' && idx < sizeof(valBuffer) - 1 )
valBuffer[idx++] = *valueStr++;
valBuffer[idx] = '\0';
if ( idx <= 0 )
return false;
sscanf( valBuffer, "%lu", outValue );
return true;
}
void CrashIfBuiltWrong(void)
{
if ( sizeof(PWFileEntry) != 4360 ||
sizeof(PWAccessFeatures) != 112 ||
sizeof(PWFileHeader) != 4768 ||
sizeof(BSDTimeStructCopy) != 44 )
{
fprintf( stderr, "PasswordServer has been built wrong!!!\n" );
fprintf( stderr, "DO NOT SHIP THIS PRODUCT\n" );
fprintf( stderr, "PWFileEntry=%ld\n", sizeof(PWFileEntry) );
fprintf( stderr, "PWAccessFeatures=%ld\n", sizeof(PWAccessFeatures) );
fprintf( stderr, "PWFileHeader=%ld\n", sizeof(PWFileHeader) );
fprintf( stderr, "BSDTimeStructCopy=%ld\n", sizeof(BSDTimeStructCopy) );
char *someBadAddress = (char *)0xFFFFFFFF;
someBadAddress[0] = 0;
}
}
int pwsf_GetPublicKey(char *outPublicKey)
{
int err = -1;
CAuthFileBase authFile;
err = authFile.validateFiles();
if ( err == 0 )
err = authFile.getRSAPublicKey( outPublicKey );
return err;
}
int pwsf_GetPublicKeyFromFile(const char *inFile, char *outPublicKey)
{
int err = -1;
CAuthFileBase authFile(inFile);
err = authFile.validateFiles();
if ( err == 0 )
err = authFile.getRSAPublicKey( outPublicKey );
return err;
}
void pwsf_CreateReplicaFile( const char *inIPStr, const char *inDNSStr, const char *inPublicKey )
{
struct stat sb;
if ( stat(kPWReplicaFile, &sb) == 0 )
{
remove( kPWReplicaFile );
}
{
CReplicaFile replicaFile;
replicaFile.SetParent( inIPStr, (inDNSStr != NULL && inDNSStr[0] != '\0') ? inDNSStr : NULL );
if ( inPublicKey != NULL )
{
replicaFile.AddServerUniqueID( inPublicKey );
}
else
{
CAuthFileBase authFile;
char rsaKey[kPWFileMaxPublicKeyBytes];
if ( authFile.getRSAPublicKey( rsaKey ) == 0 )
replicaFile.AddServerUniqueID( rsaKey );
}
replicaFile.SetReplicaPolicy( kReplicaAllowAll );
replicaFile.SaveXMLData();
}
}
void pwsf_ResetReplicaFile( const char *inPublicKey )
{
CFStringRef firstIPAddressString;
CFStringRef dnsString;
CFMutableArrayRef ipAddressArray = NULL;
CFIndex ipAddressCount = 0;
CReplicaFile replicaFile;
CFMutableDictionaryRef serverDict = (CFMutableDictionaryRef) replicaFile.GetParent();
char ipStr[256] = {0,};
char dnsStr[256] = {0,};
strcpy( ipStr, "0.0.0.0" );
if ( serverDict != NULL )
{
ipAddressArray = replicaFile.GetIPAddresses( serverDict );
if ( ipAddressArray != NULL )
{
ipAddressCount = CFArrayGetCount( ipAddressArray );
firstIPAddressString = (CFStringRef) CFArrayGetValueAtIndex( ipAddressArray, 0 );
if ( firstIPAddressString != NULL )
CFStringGetCString( firstIPAddressString, ipStr, sizeof(ipStr), kCFStringEncodingUTF8 );
}
if ( CFDictionaryGetValueIfPresent(serverDict, CFSTR(kPWReplicaDNSKey), (const void **)&dnsString) )
CFStringGetCString( dnsString, dnsStr, sizeof(dnsStr), kCFStringEncodingUTF8 );
}
pwsf_CreateReplicaFile( ipStr, dnsStr, inPublicKey );
if ( ipAddressCount > 1 )
{
CReplicaFile newReplicaFile;
serverDict = (CFMutableDictionaryRef) newReplicaFile.GetParent();
if ( serverDict != NULL )
{
newReplicaFile.AddOrReplaceValue( serverDict, CFSTR(kPWReplicaIPKey), ipAddressArray );
newReplicaFile.SetParent( serverDict );
newReplicaFile.SaveXMLData();
}
}
}
char* pwsf_GetPrincName( PWFileEntry *userRec )
{
if ( strcmp( userRec->digest[kPWHashSlotKERBEROS_NAME].method, "KerberosPrincName" ) == 0 )
return userRec->digest[kPWHashSlotKERBEROS_NAME].digest;
return userRec->usernameStr;
}
int pwsf_ShadowHashDataToArray( const char *inAAData, CFMutableArrayRef *outHashTypeArray )
{
CFMutableArrayRef hashTypeArray = NULL;
char hashType[256];
if ( inAAData == NULL || outHashTypeArray == NULL || *inAAData == '\0' )
return 0;
*outHashTypeArray = NULL;
if ( strncmp( inAAData, kDSTagAuthAuthorityBetterHashOnly, sizeof(kDSTagAuthAuthorityBetterHashOnly)-1 ) == 0 )
{
hashTypeArray = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
if ( hashTypeArray == NULL )
return 0;
pwsf_AppendUTF8StringToArray( "SMB-NT", hashTypeArray );
pwsf_AppendUTF8StringToArray( "SALTED-SHA1", hashTypeArray );
}
else
if ( strncmp( inAAData, kHashNameListPrefix, sizeof(kHashNameListPrefix)-1 ) == 0 )
{
const char *endPtr;
const char *tptr = inAAData + sizeof(kHashNameListPrefix) - 1;
hashTypeArray = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
if ( hashTypeArray == NULL )
return 0;
if ( *tptr++ == '<' && strchr(tptr, '>') != NULL )
{
while ( (endPtr = strchr( tptr, ',' )) != NULL )
{
strlcpy( hashType, tptr, (endPtr - tptr) + 1 );
pwsf_AppendUTF8StringToArray( hashType, hashTypeArray );
tptr += (endPtr - tptr) + 1;
}
endPtr = strchr( tptr, '>' );
if ( endPtr != NULL )
{
strlcpy( hashType, tptr, (endPtr - tptr) + 1 );
pwsf_AppendUTF8StringToArray( hashType, hashTypeArray );
}
}
}
*outHashTypeArray = hashTypeArray;
return 1;
}
char * pwsf_ShadowHashArrayToData( CFArrayRef inHashTypeArray, long *outResultLen )
{
char *aaNewData = NULL;
char *newDataCStr = NULL;
long len = 0;
CFMutableStringRef newDataString = NULL;
CFStringRef stringRef;
CFIndex stringLen;
CFIndex typeCount = CFArrayGetCount( inHashTypeArray );
if ( typeCount > 0 )
{
newDataString = CFStringCreateMutable( kCFAllocatorDefault, 0 );
if ( newDataString == NULL )
return NULL;
for ( CFIndex index = 0; index < typeCount; index++ )
{
stringRef = (CFStringRef) CFArrayGetValueAtIndex( inHashTypeArray, index );
if ( stringRef != NULL )
{
if ( CFStringGetLength(newDataString) > 0 )
CFStringAppend( newDataString, CFSTR(",") );
CFStringAppend( newDataString, stringRef );
}
}
}
stringLen = CFStringGetLength( newDataString );
newDataCStr = (char *) calloc( 1, stringLen + 1 );
CFStringGetCString( newDataString, newDataCStr, stringLen + 1, kCFStringEncodingUTF8 );
aaNewData = (char *) calloc( 1, sizeof(kDSValueAuthAuthorityShadowHash) + sizeof(kHashNameListPrefix) + stringLen + 2 );
if ( newDataCStr != NULL && aaNewData != NULL )
len = sprintf( aaNewData, "%s<%s>", kHashNameListPrefix, newDataCStr );
if ( newDataCStr != NULL )
free( newDataCStr );
if ( outResultLen != NULL )
*outResultLen = len;
return aaNewData;
}
void pwsf_AppendUTF8StringToArray( const char *inUTF8Str, CFMutableArrayRef inArray )
{
CFStringRef stringRef = CFStringCreateWithCString( kCFAllocatorDefault, inUTF8Str, kCFStringEncodingUTF8 );
CFArrayAppendValue( inArray, stringRef );
CFRelease( stringRef );
}