#include <syslog.h>
#include "CPolicyXML.h"
#pragma mark -
#pragma mark C API
#pragma mark -
int ConvertXMLPolicyToSpaceDelimited( const char *inXMLDataStr, char **outPolicyStr )
{
if ( inXMLDataStr == NULL || outPolicyStr == NULL )
return -1;
CPolicyXML policyObj( inXMLDataStr );
*outPolicyStr = policyObj.GetPolicyAsSpaceDelimitedData();
if ( *outPolicyStr == NULL )
return -1;
return 0;
}
int ConvertSpaceDelimitedPolicyToXML( const char *inPolicyStr, char **outXMLDataStr )
{
PWAccessFeatures policies;
PWMoreAccessFeatures morePolicies = {0};
if ( inPolicyStr == NULL || outXMLDataStr == NULL )
return -1;
GetDefaultUserPolicies( &policies );
if ( ! StringToPWAccessFeaturesExtra( inPolicyStr, &policies, &morePolicies ) )
return -1;
CPolicyXML policyObj;
policyObj.AddMiscPolicies( inPolicyStr );
policyObj.SetPolicyExtra( &policies, &morePolicies );
*outXMLDataStr = policyObj.GetPolicyAsXMLData();
if ( *outXMLDataStr == NULL )
return -1;
return 0;
}
void GetDefaultUserPolicies( PWAccessFeatures *inOutUserPolicies )
{
CPolicyXML::CPolicyXMLCommonInitStatic( inOutUserPolicies );
}
#pragma mark -
#pragma mark Public Methods
#pragma mark -
CPolicyXML::CPolicyXML() : CPolicyBase()
{
CPolicyCommonInit();
}
CPolicyXML::CPolicyXML( CFDictionaryRef inPolicyDict ) : CPolicyBase()
{
CPolicyCommonInit();
this->ConvertPropertyListPolicyToStruct( (CFMutableDictionaryRef)inPolicyDict );
}
CPolicyXML::CPolicyXML( const char *xmlDataStr ) : CPolicyBase()
{
CFDataRef xmlData;
CFStringRef errorString;
CFMutableDictionaryRef policyDict;
CPolicyCommonInit();
if ( xmlDataStr != NULL )
{
xmlData = CFDataCreate( kCFAllocatorDefault, (const unsigned char *)xmlDataStr, strlen(xmlDataStr) );
if ( xmlData != NULL )
{
policyDict = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, xmlData, kCFPropertyListMutableContainersAndLeaves, &errorString );
if ( policyDict != NULL ) {
this->ConvertPropertyListPolicyToStruct( policyDict );
CFRelease( policyDict );
}
CFRelease( xmlData );
}
}
}
CPolicyXML::~CPolicyXML()
{
}
void
CPolicyXML::CPolicyCommonInit( void )
{
CPolicyXML::CPolicyXMLCommonInitStatic( &mPolicy );
bzero( &mExtraPolicy, sizeof(mExtraPolicy) );
mWarnOfExpirationMinutes = 0;
mWarnOfDisableMinutes = 0;
mProjectedPasswordExpireDate = 0;
mProjectedAccountDisableDate = 0;
}
void
CPolicyXML::CPolicyXMLCommonInitStatic( PWAccessFeatures *inOutPolicies )
{
if ( inOutPolicies == NULL )
return;
bzero( inOutPolicies, sizeof(PWAccessFeatures) );
inOutPolicies->usingHistory = false;
inOutPolicies->canModifyPasswordforSelf = true;
inOutPolicies->usingExpirationDate = false;
inOutPolicies->usingHardExpirationDate = false;
inOutPolicies->requiresAlpha = false;
inOutPolicies->requiresNumeric = false;
inOutPolicies->passwordCannotBeName = false;
inOutPolicies->historyCount = 0;
inOutPolicies->isSessionKeyAgent = false;
inOutPolicies->maxMinutesUntilChangePassword = 0;
inOutPolicies->maxMinutesUntilDisabled = 0;
inOutPolicies->maxMinutesOfNonUse = 0;
inOutPolicies->maxFailedLoginAttempts = 0;
inOutPolicies->minChars = 0;
inOutPolicies->maxChars = 0;
}
void
CPolicyXML::GetPolicy( PWAccessFeatures *outPolicy )
{
if ( outPolicy != NULL )
memcpy( outPolicy, &mPolicy, sizeof(PWAccessFeatures) );
}
char *
CPolicyXML::GetPolicyAsSpaceDelimitedData( void )
{
char *returnStr = NULL;
long metaFeatureStrLen = 0;
char featureStr[2048];
char metaFeatureStr[256] = { 0, };
PWAccessFeaturesToStringWithoutStateInfoExtra( &mPolicy, &mExtraPolicy, sizeof(featureStr), featureStr );
if ( mWarnOfExpirationMinutes > 0 )
{
metaFeatureStrLen = sprintf( metaFeatureStr,
" warnOfExpirationMinutes=%lu projectedPasswordExpireDate=%lu",
mWarnOfExpirationMinutes,
(unsigned long)mProjectedPasswordExpireDate );
}
if ( mWarnOfDisableMinutes > 0 )
{
sprintf( metaFeatureStr + metaFeatureStrLen,
" warnOfDisableMinutes=%lu projectedAccountDisableDate=%lu",
mWarnOfDisableMinutes,
(unsigned long)mProjectedAccountDisableDate );
}
returnStr = (char *) malloc( strlen(featureStr) + strlen(metaFeatureStr) + 1 );
if ( returnStr != NULL )
{
strcpy( returnStr, featureStr );
strcat( returnStr, metaFeatureStr );
}
return returnStr;
}
void
CPolicyXML::SetPolicy( PWAccessFeatures *inPolicy )
{
if ( inPolicy != NULL )
{
memcpy( &mPolicy, inPolicy, sizeof(PWAccessFeatures) );
this->ConvertStructToPropertyListPolicy();
}
}
void
CPolicyXML::SetPolicy( CFDictionaryRef inPolicyDict )
{
this->ConvertPropertyListPolicyToStruct( (CFMutableDictionaryRef)inPolicyDict );
}
void
CPolicyXML::SetPolicyExtra( PWAccessFeatures *inPolicy, PWMoreAccessFeatures *inExtraPolicy )
{
if ( inPolicy != NULL && inExtraPolicy != NULL )
{
memcpy( &mPolicy, inPolicy, sizeof(PWAccessFeatures) );
memcpy( &mExtraPolicy, inExtraPolicy, sizeof(PWMoreAccessFeatures) );
this->ConvertStructToPropertyListPolicy();
}
}
void
CPolicyXML::AddMiscPolicies( const char *inPolicyStr )
{
const char *warnOfExpirationMinutes = strstr( inPolicyStr, kPWPolicyStr_warnOfExpirationMinutes );
const char *warnOfDisableMinutes = strstr( inPolicyStr, kPWPolicyStr_warnOfDisableMinutes );
unsigned long value;
if ( StringToPWAccessFeatures_GetValue( warnOfExpirationMinutes, &value ) )
mWarnOfExpirationMinutes = value;
if ( StringToPWAccessFeatures_GetValue( warnOfDisableMinutes, &value ) )
mWarnOfDisableMinutes = value;
}
#pragma mark -
#pragma mark Protected Methods
#pragma mark -
int
CPolicyXML::ConvertPropertyListPolicyToStruct( CFMutableDictionaryRef inPolicyDict )
{
int result = 0;
short aShortValue;
long aLongValue;
bool aBoolValue;
CFTypeRef valueRef;
struct tm bsdTimeStruct;
if ( inPolicyDict == NULL )
return -1;
CFRetain( inPolicyDict );
if ( mPolicyDict != NULL )
CFRelease( mPolicyDict );
mPolicyDict = inPolicyDict;
if ( this->GetBooleanForKey( CFSTR(kPWPolicyStr_canModifyPasswordforSelf), &aBoolValue ) )
mPolicy.canModifyPasswordforSelf = aBoolValue;
if ( this->GetBooleanForKey( CFSTR(kPWPolicyStr_usingExpirationDate), &aBoolValue ) )
mPolicy.usingExpirationDate = aBoolValue;
if ( this->GetBooleanForKey( CFSTR(kPWPolicyStr_usingHardExpirationDate), &aBoolValue ) )
mPolicy.usingHardExpirationDate = aBoolValue;
if ( this->GetBooleanForKey( CFSTR(kPWPolicyStr_requiresAlpha), &aBoolValue ) )
mPolicy.requiresAlpha = aBoolValue;
if ( this->GetBooleanForKey( CFSTR(kPWPolicyStr_requiresNumeric), &aBoolValue ) )
mPolicy.requiresNumeric = aBoolValue;
if ( this->GetBooleanForKey( CFSTR(kPWPolicyStr_requiresMixedCase), &aBoolValue ) )
mExtraPolicy.requiresMixedCase = aBoolValue;
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_notGuessablePattern), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)valueRef, kCFNumberLongType, &aLongValue) )
{
mExtraPolicy.notGuessablePattern = aLongValue;
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_expirationDateGMT), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFDateGetTypeID() )
{
this->ConvertCFDateToBSDTime( (CFDateRef)valueRef, (struct tm *)&mPolicy.expirationDateGMT );
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_hardExpireDateGMT), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFDateGetTypeID() )
{
this->ConvertCFDateToBSDTime( (CFDateRef)valueRef, (struct tm *)&mPolicy.hardExpireDateGMT );
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_maxMinutesUntilChangePW), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)valueRef, kCFNumberLongType, &aLongValue) )
{
mPolicy.maxMinutesUntilChangePassword = aLongValue;
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_maxMinutesUntilDisabled), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)valueRef, kCFNumberLongType, &aLongValue) )
{
mPolicy.maxMinutesUntilDisabled = aLongValue;
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_maxMinutesOfNonUse), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)valueRef, kCFNumberLongType, &aLongValue) )
{
mPolicy.maxMinutesOfNonUse = aLongValue;
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_maxFailedLoginAttempts), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)valueRef, kCFNumberShortType, &aShortValue) )
{
mPolicy.maxFailedLoginAttempts = aShortValue;
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_minChars), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)valueRef, kCFNumberShortType, &aShortValue) )
{
mPolicy.minChars = aShortValue;
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_maxChars), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)valueRef, kCFNumberShortType, &aShortValue) )
{
mPolicy.maxChars = aShortValue;
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_usingHistory), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)valueRef, kCFNumberShortType, &aShortValue) )
{
if ( aShortValue > kPWFileMaxHistoryCount )
aShortValue = kPWFileMaxHistoryCount;
if ( aShortValue > 0 )
{
mPolicy.usingHistory = true;
mPolicy.historyCount = aShortValue - 1;
}
else
{
mPolicy.usingHistory = false;
mPolicy.historyCount = 0;
}
}
if ( this->GetBooleanForKey( CFSTR(kPWPolicyStr_passwordCannotBeName), &aBoolValue ) )
mPolicy.passwordCannotBeName = aBoolValue;
if ( this->GetBooleanForKey( CFSTR(kPWPolicyStr_isSessionKeyAgent), &aBoolValue ) )
mPolicy.isSessionKeyAgent = aBoolValue;
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_warnOfExpirationMinutes), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)valueRef, kCFNumberLongType, &aLongValue) )
{
mWarnOfExpirationMinutes = aLongValue;
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_warnOfDisableMinutes), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)valueRef, kCFNumberLongType, &aLongValue) )
{
mWarnOfDisableMinutes = aLongValue;
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_projectedPasswordExpireDate), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFDateGetTypeID() )
{
this->ConvertCFDateToBSDTime( (CFDateRef)valueRef, &bsdTimeStruct );
mProjectedPasswordExpireDate = timegm( &bsdTimeStruct );
}
if ( CFDictionaryGetValueIfPresent( mPolicyDict, CFSTR(kPWPolicyStr_projectedAccountDisableDate), (const void **)&valueRef ) &&
CFGetTypeID(valueRef) == CFDateGetTypeID() )
{
this->ConvertCFDateToBSDTime( (CFDateRef)valueRef, &bsdTimeStruct );
mProjectedAccountDisableDate = timegm( &bsdTimeStruct );
}
return result;
}
int
CPolicyXML::ConvertStructToPropertyListPolicy( void )
{
CFMutableDictionaryRef policyDict;
int historyNumber;
CFDateRef expirationDateGMTRef;
CFDateRef hardExpireDateGMTRef;
unsigned int aBoolVal;
CFNumberRef warnOfExpirationRef = NULL;
CFNumberRef warnOfDisableRef = NULL;
policyDict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
if ( policyDict == NULL )
return -1;
historyNumber = (mPolicy.usingHistory != 0);
if ( historyNumber > 0 )
historyNumber += mPolicy.historyCount;
CFNumberRef usingHistoryRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &historyNumber );
aBoolVal = (mPolicy.canModifyPasswordforSelf != 0);
CFNumberRef canModifyPasswordforSelfRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &aBoolVal );
aBoolVal = (mPolicy.usingExpirationDate != 0);
CFNumberRef usingExpirationDateRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &aBoolVal );
aBoolVal = (mPolicy.usingHardExpirationDate != 0);
CFNumberRef usingHardExpirationDateRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &aBoolVal );
aBoolVal = (mPolicy.requiresAlpha != 0);
CFNumberRef requiresAlphaRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &aBoolVal );
aBoolVal = (mPolicy.requiresNumeric != 0);
CFNumberRef requiresNumericRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &aBoolVal );
aBoolVal = (mExtraPolicy.requiresMixedCase != 0);
CFNumberRef requiresMixedCaseRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &aBoolVal );
CFNumberRef notGuessablePatternRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &(mExtraPolicy.notGuessablePattern) );
aBoolVal = (mPolicy.passwordCannotBeName != 0);
CFNumberRef passwordCannotBeNameRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &aBoolVal );
aBoolVal = (mPolicy.isSessionKeyAgent != 0);
CFNumberRef isSessionKeyAgentRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &aBoolVal );
CFNumberRef maxMinutesUntilChangePasswordRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &mPolicy.maxMinutesUntilChangePassword );
CFNumberRef maxMinutesUntilDisabledRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &mPolicy.maxMinutesUntilDisabled );
CFNumberRef maxMinutesOfNonUseRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &mPolicy.maxMinutesOfNonUse );
CFNumberRef maxFailedLoginAttemptsRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberShortType, &mPolicy.maxFailedLoginAttempts );
CFNumberRef minCharsRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberShortType, &mPolicy.minChars );
CFNumberRef maxCharsRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberShortType, &mPolicy.maxChars );
this->ConvertBSDTimeToCFDate( (struct tm *)&(mPolicy.expirationDateGMT), &expirationDateGMTRef );
this->ConvertBSDTimeToCFDate( (struct tm *)&(mPolicy.hardExpireDateGMT), &hardExpireDateGMTRef );
if ( mWarnOfExpirationMinutes > 0 )
warnOfExpirationRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &mWarnOfExpirationMinutes );
if ( mWarnOfDisableMinutes > 0 )
warnOfDisableRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &mWarnOfDisableMinutes );
if ( usingHistoryRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_usingHistory), usingHistoryRef );
CFRelease( usingHistoryRef );
}
if ( canModifyPasswordforSelfRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_canModifyPasswordforSelf), canModifyPasswordforSelfRef );
CFRelease( canModifyPasswordforSelfRef );
}
if ( usingExpirationDateRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_usingExpirationDate), usingExpirationDateRef );
CFRelease( usingExpirationDateRef );
}
if ( usingHardExpirationDateRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_usingHardExpirationDate), usingHardExpirationDateRef );
CFRelease( usingHardExpirationDateRef );
}
if ( requiresAlphaRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_requiresAlpha), requiresAlphaRef );
CFRelease( requiresAlphaRef );
}
if ( requiresNumericRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_requiresNumeric), requiresNumericRef );
CFRelease( requiresNumericRef );
}
if ( requiresMixedCaseRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_requiresMixedCase), requiresMixedCaseRef );
CFRelease( requiresMixedCaseRef );
}
if ( notGuessablePatternRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_notGuessablePattern), notGuessablePatternRef );
CFRelease( notGuessablePatternRef );
}
if ( expirationDateGMTRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_expirationDateGMT), expirationDateGMTRef );
CFRelease( expirationDateGMTRef );
}
if ( hardExpireDateGMTRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_hardExpireDateGMT), hardExpireDateGMTRef );
CFRelease( hardExpireDateGMTRef );
}
if ( maxMinutesUntilChangePasswordRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_maxMinutesUntilChangePW), maxMinutesUntilChangePasswordRef );
CFRelease( maxMinutesUntilChangePasswordRef );
}
if ( maxMinutesUntilDisabledRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_maxMinutesUntilDisabled), maxMinutesUntilDisabledRef );
CFRelease( maxMinutesUntilDisabledRef );
}
if ( maxMinutesOfNonUseRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_maxMinutesOfNonUse), maxMinutesOfNonUseRef );
CFRelease( maxMinutesOfNonUseRef );
}
if ( maxFailedLoginAttemptsRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_maxFailedLoginAttempts), maxFailedLoginAttemptsRef );
CFRelease( maxFailedLoginAttemptsRef );
}
if ( minCharsRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_minChars), minCharsRef );
CFRelease( minCharsRef );
}
if ( maxCharsRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_maxChars), maxCharsRef );
CFRelease( maxCharsRef );
}
if ( passwordCannotBeNameRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_passwordCannotBeName), passwordCannotBeNameRef );
CFRelease( passwordCannotBeNameRef );
}
if ( isSessionKeyAgentRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_isSessionKeyAgent), isSessionKeyAgentRef );
CFRelease( isSessionKeyAgentRef );
}
if ( warnOfExpirationRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_warnOfExpirationMinutes), warnOfExpirationRef );
CFRelease( warnOfExpirationRef );
}
if ( warnOfDisableRef != NULL )
{
CFDictionaryAddValue( policyDict, CFSTR(kPWPolicyStr_warnOfDisableMinutes), warnOfDisableRef );
CFRelease( warnOfDisableRef );
}
if ( mPolicyDict != NULL )
CFRelease( mPolicyDict );
mPolicyDict = policyDict;
return 0;
}