/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * AuthFile.cpp * PasswordServer */ #if 0 #define DEBUGTIME 1 #else #define DEBUGTIME 0 #endif #if DEBUGTIME //#include "CLog.h" #include #define SRVLOG1(A,B, args...) syslog(LOG_ALERT, (B), ##args) #endif #include #include #include #include #include "AuthFile.h" #include "CAuthFileBase.h" #include "CReplicaFile.h" // from DirServicesConst.h (our layer is below DS) #define kDSValueAuthAuthorityShadowHash ";ShadowHash;" #define kDSTagAuthAuthorityShadowHash "ShadowHash" #define kDSTagAuthAuthorityBetterHashOnly "BetterHashOnly" #define kHashNameListPrefix "HASHLIST:" #if DEBUGTIME //------------------------------------------------------------------------------------------------ // GetTimeAsString //------------------------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------------------------ // TimeIsStale // // Returns: Boolean value //------------------------------------------------------------------------------------------------ int TimeIsStale( BSDTimeStructCopy *inTime ) { time_t theTime, theGMTime; // get GMT in seconds time(&theGMTime); // get user time in seconds 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 // broken for dates that push the signing bit? //return ( difftime( theGMTime, theTime ) > 0 ); return ( (unsigned long)theGMTime > (unsigned long)theTime ); } //------------------------------------------------------------------------------------------------ // LoginTimeIsStale // // Returns: Boolean value //------------------------------------------------------------------------------------------------ int LoginTimeIsStale( BSDTimeStructCopy *inLastLogin, unsigned long inMaxMinutesOfNonUse ) { time_t theTime, theGMTime; long maxMinutesOfNonUse = (long)(inMaxMinutesOfNonUse & 0x7FFFFFFF); // get GMT in seconds time(&theGMTime); // get user time in seconds theTime = timegm( (struct tm *)inLastLogin ); // if ( theTime <= 0 ) // theTime = theGMTime; #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 ); } //------------------------------------------------------------------------------------------------ // PWGlobalAccessFeaturesToString // // Prepares the PWGlobalAccessFeatures struct for transmission over our text-based protocol //------------------------------------------------------------------------------------------------ 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); // Boolean values are stored in the struct as single bits. They must be unsigned for // display. if ( inAccessFeatures->usingHistory ) historyValue = 1 + GlobalHistoryCount(*inAccessFeatures); 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 ); } //------------------------------------------------------------------------------------------------ // PWGlobalAccessFeaturesToStringExtra //------------------------------------------------------------------------------------------------ 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 ); } //------------------------------------------------------------------------------------------------ // PWAccessFeaturesToString // // Prepares the PWAccessFeatures struct for transmission over our text-based protocol //------------------------------------------------------------------------------------------------ void PWAccessFeaturesToString( PWAccessFeatures *inAccessFeatures, char *outString ) { char temp1Str[256]; char temp2Str[2048]; char temp3Str[64]; if ( outString == NULL || inAccessFeatures == NULL ) throw(-1); // Boolean values are stored in the struct as single bits. They must be unsigned for // display. 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 ); } //------------------------------------------------------------------------------------------------ // PWAccessFeaturesToStringExtra // // Prepares the PWAccessFeatures struct for transmission over our text-based protocol //------------------------------------------------------------------------------------------------ void PWAccessFeaturesToStringExtra( PWAccessFeatures *inAccessFeatures, PWMoreAccessFeatures *inExtraFeatures, int inMaxLen, char *outString ) { char temp2Str[2048]; if ( outString == NULL || inAccessFeatures == NULL ) return; // Boolean values are stored in the struct as single bits. They must be unsigned for // display. 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) ); } //------------------------------------------------------------------------------------------------ // PWActualAccessFeaturesToString // // Prepares the PWAccessFeatures struct and PWGlobalAccessFeatures defaults for transmission // over our text-based protocol //------------------------------------------------------------------------------------------------ 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; // TODO: get the actual time values for expiration dates char temp1Str[256]; char temp2Str[256]; char temp3Str[256]; char temp4Str[512]; if ( outString == NULL || inAccessFeatures == NULL ) throw(-1); // get values for policies that can be in either the user record // or the global record 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; // Boolean values are stored in the struct as single bits. They must be unsigned for // display. if ( inAccessFeatures->usingHistory ) historyValue = 1 + inAccessFeatures->historyCount; else if ( inGAccessFeatures->usingHistory ) historyValue = 1 + GlobalHistoryCount(*inGAccessFeatures); 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 ); } //------------------------------------------------------------------------------------------------ // PWActualAccessFeaturesToStringExtra // // Prepares the PWAccessFeatures struct and PWGlobalAccessFeatures defaults for transmission // over our text-based protocol //------------------------------------------------------------------------------------------------ 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/*inGAccessFeatures->notGuessablePattern*/; snprintf( outString + segment1Length, inMaxLen, " %s=%d, %s=%lu", kPWPolicyStr_requiresMixedCase, (requiresMixedCase != 0), kPWPolicyStr_notGuessablePattern, notGuessablePattern ); } //------------------------------------------------------------------------------------------------ // PWAccessFeaturesToStringWithoutStateInfo // // Prepares the PWAccessFeatures struct for transmission over our text-based protocol // Returns in the subset of policies that are true policies and not state // information, such as: isDisabled, isAdminUser, and newPasswordRequired. //------------------------------------------------------------------------------------------------ void PWAccessFeaturesToStringWithoutStateInfo( PWAccessFeatures *inAccessFeatures, char *outString ) { int historyValue = 0; if ( outString == NULL || inAccessFeatures == NULL ) throw(-1); // Boolean values are stored in the struct as single bits. They must be unsigned for // display. 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) ); } //------------------------------------------------------------------------------------------------ // PWAccessFeaturesToStringWithoutStateInfoExtra // // Prepares the policy data for transmission over our text-based protocol. // Returns in the subset of policies that are true policies and not state // information, such as: isDisabled, isAdminUser, and newPasswordRequired. //------------------------------------------------------------------------------------------------ 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 ); } } //------------------------------------------------------------------------------------------------ // StringToPWGlobalAccessFeatures // // Returns: TRUE if the string is successfully parsed // // Features specified in the string overwrite features in . Features // not specified in the string remain as-is. If they were undefined before, they are undefined // on exit. //------------------------------------------------------------------------------------------------ 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 ) { // clamp to the password server's maximum value if ( value > kPWFileMaxHistoryCount ) value = kPWFileMaxHistoryCount; inOutAccessFeatures->usingHistory = 1; SetGlobalHistoryCount(*inOutAccessFeatures, value - 1); } else { inOutAccessFeatures->usingHistory = 0; SetGlobalHistoryCount(*inOutAccessFeatures, 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; // no checking for now return true; } //------------------------------------------------------------------------------------------------ // StringToPWGlobalAccessFeaturesExtra // // Returns: TRUE if the string is successfully parsed //------------------------------------------------------------------------------------------------ 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; } //------------------------------------------------------------------------------------------------ // StringToPWAccessFeatures // // Returns: TRUE if the string is successfully parsed // // Features specified in the string overwrite features in . Features // not specified in the string remain as-is. If they were undefined before, they are undefined // on exit. //------------------------------------------------------------------------------------------------ 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 ) { // clamp to the password server's maximum value 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; // this policy must be processed last 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; } // no checking for now return true; } //------------------------------------------------------------------------------------------------ // StringToPWAccessFeaturesExtra // // Returns: TRUE if the string is successfully parsed // // Features specified in the string overwrite features in . Features // not specified in the string remain as-is. If they were undefined before, they are undefined // on exit. //------------------------------------------------------------------------------------------------ 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; } // no checking for now result = true; } return result; } //------------------------------------------------------------------------------------------------ // StringToPWAccessFeatures_GetValue // // Returns: TRUE if a value is discovered // // Takes a value like, "isDisabled=0" and returns the "0" in . // If is NULL, the function just returns false. //------------------------------------------------------------------------------------------------ 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; } //------------------------------------------------------------------------------------------------ // CrashIfBuiltWrong // // Compares the current database struct sizes to our hand-checked constant. // If the size changes, don't run. //------------------------------------------------------------------------------------------------ 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; } } //------------------------------------------------------------------------------------------------ // pwsf_PreserveUnrepresentedPolicies // // concatenates policies that are not in one of the policy structs //------------------------------------------------------------------------------------------------ void pwsf_PreserveUnrepresentedPolicies( const char *inOriginalStr, int inMaxLen, char *inOutString ) { if ( inOriginalStr == NULL || inOutString == NULL ) return; const char *warnOfExpirationMinutes = strstr( inOriginalStr, kPWPolicyStr_warnOfExpirationMinutes ); const char *warnOfDisableMinutes = strstr( inOriginalStr, kPWPolicyStr_warnOfDisableMinutes ); const char *endPtr = NULL; long curLen = strlen( inOutString ); if ( warnOfExpirationMinutes != NULL ) { endPtr = strchr( warnOfExpirationMinutes, ' ' ); if ( endPtr != NULL ) strlcat( inOutString, warnOfExpirationMinutes, MIN(curLen + (endPtr - warnOfExpirationMinutes) + 1, inMaxLen) ); else strlcat( inOutString, warnOfExpirationMinutes, inMaxLen ); curLen = strlen( inOutString ); } if ( warnOfDisableMinutes != NULL ) { endPtr = strchr( warnOfDisableMinutes, ' ' ); if ( endPtr != NULL ) strlcat( inOutString, warnOfDisableMinutes, MIN(curLen + (endPtr - warnOfDisableMinutes) + 1, inMaxLen) ); else strlcat( inOutString, warnOfDisableMinutes, inMaxLen ); } } //------------------------------------------------------------------------------------------------ // pwsf_GetPublicKey // // RETURNS: 0=ok, -1 fail // // Retrieves the RSA public key from the password server database. // must be a pointer to a buffer at least kPWFileMaxPublicKeyBytes long. //------------------------------------------------------------------------------------------------ int pwsf_GetPublicKey(char *outPublicKey) { int err = -1; CAuthFileBase authFile; err = authFile.validateFiles(); if ( err == 0 ) err = authFile.getRSAPublicKey( outPublicKey ); return err; } //------------------------------------------------------------------------------------------------ // pwsf_GetPublicKeyFromFile // // RETURNS: 0=ok, -1 fail // // Retrieves the RSA public key from the password server database. // must be a pointer to a buffer at least kPWFileMaxPublicKeyBytes long. //------------------------------------------------------------------------------------------------ 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; } //------------------------------------------------------------------------------------------------ // pwsf_CreateReplicaFile // // Creates the '/var/db/authserver/authserverreplicas' file. // Client must be running as root. //------------------------------------------------------------------------------------------------ void pwsf_CreateReplicaFile( const char *inIPStr, const char *inDNSStr, const char *inPublicKey ) { struct stat sb; if ( stat(kPWReplicaFile, &sb) == 0 ) { // replace the existing file 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(); } } //------------------------------------------------------------------------------------------------ // pwsf_ResetReplicaFile // // Resets the '/var/db/authserver/authserverreplicas' file to have no replicas. // Client must be running as root. //------------------------------------------------------------------------------------------------ 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 ) { // fetch data to preserve 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 ); } // replace the replica file pwsf_CreateReplicaFile( ipStr, dnsStr, inPublicKey ); // restore IP list (if > 1 address) if ( ipAddressCount > 1 ) { CReplicaFile newReplicaFile; serverDict = (CFMutableDictionaryRef) newReplicaFile.GetParent(); if ( serverDict != NULL ) { newReplicaFile.AddOrReplaceValue( serverDict, CFSTR(kPWReplicaIPKey), ipAddressArray ); newReplicaFile.SetParent( serverDict ); newReplicaFile.SaveXMLData(); } } } // ---------------------------------------------------------------------------------------- // pwsf_GetPrincName // // Returns: the kerberos principal name for the record; must never return NULL. // ---------------------------------------------------------------------------------------- char* pwsf_GetPrincName( PWFileEntry *userRec ) { if ( strcmp( userRec->digest[kPWHashSlotKERBEROS_NAME].method, "KerberosPrincName" ) == 0 ) return userRec->digest[kPWHashSlotKERBEROS_NAME].digest; return userRec->usernameStr; } // ---------------------------------------------------------------------------------------- // pwsf_ShadowHashDataToArray // // Returns: TRUE if an array is returned in . // ---------------------------------------------------------------------------------------- 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; // get the existing list (if any) 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 ) { // comma delimited list 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; } // ---------------------------------------------------------------------------------------- // pwsf_ShadowHashArrayToData // ---------------------------------------------------------------------------------------- char * pwsf_ShadowHashArrayToData( CFArrayRef inHashTypeArray, long *outResultLen ) { char *aaNewData = NULL; char *newDataCStr = NULL; long len = 0; CFMutableStringRef newDataString = NULL; CFStringRef stringRef; CFIndex stringLen; // build the new string 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 ); } } } // build the auth-authority 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 ); // build string if ( newDataCStr != NULL && aaNewData != NULL ) len = sprintf( aaNewData, "%s<%s>", kHashNameListPrefix, newDataCStr ); // clean up if ( newDataCStr != NULL ) free( newDataCStr ); // return string length (if requested) if ( outResultLen != NULL ) *outResultLen = len; return aaNewData; } // ---------------------------------------------------------------------------------------- // pwsf_AppendUTF8StringToArray // ---------------------------------------------------------------------------------------- void pwsf_AppendUTF8StringToArray( const char *inUTF8Str, CFMutableArrayRef inArray ) { CFStringRef stringRef = CFStringCreateWithCString( kCFAllocatorDefault, inUTF8Str, kCFStringEncodingUTF8 ); CFArrayAppendValue( inArray, stringRef ); CFRelease( stringRef ); } // ---------------------------------------------------------------------------------------- // pwsf_EndianAdjustTimeStruct // ---------------------------------------------------------------------------------------- void pwsf_EndianAdjustTimeStruct( BSDTimeStructCopy *inOutTimeStruct, int native ) { #if TARGET_RT_LITTLE_ENDIAN if ( native == 1 ) { // adjust to native byte order inOutTimeStruct->tm_sec = EndianS32_BtoN(inOutTimeStruct->tm_sec); inOutTimeStruct->tm_min = EndianS32_BtoN(inOutTimeStruct->tm_min); inOutTimeStruct->tm_hour = EndianS32_BtoN(inOutTimeStruct->tm_hour); inOutTimeStruct->tm_mday = EndianS32_BtoN(inOutTimeStruct->tm_mday); inOutTimeStruct->tm_mon = EndianS32_BtoN(inOutTimeStruct->tm_mon); inOutTimeStruct->tm_year = EndianS32_BtoN(inOutTimeStruct->tm_year); inOutTimeStruct->tm_wday = EndianS32_BtoN(inOutTimeStruct->tm_wday); inOutTimeStruct->tm_yday = EndianS32_BtoN(inOutTimeStruct->tm_yday); inOutTimeStruct->tm_isdst = EndianS32_BtoN(inOutTimeStruct->tm_isdst); inOutTimeStruct->tm_gmtoff = EndianS32_BtoN(inOutTimeStruct->tm_gmtoff); } else { // adjust to big-endian byte order inOutTimeStruct->tm_sec = EndianS32_NtoB(inOutTimeStruct->tm_sec); inOutTimeStruct->tm_min = EndianS32_NtoB(inOutTimeStruct->tm_min); inOutTimeStruct->tm_hour = EndianS32_NtoB(inOutTimeStruct->tm_hour); inOutTimeStruct->tm_mday = EndianS32_NtoB(inOutTimeStruct->tm_mday); inOutTimeStruct->tm_mon = EndianS32_NtoB(inOutTimeStruct->tm_mon); inOutTimeStruct->tm_year = EndianS32_NtoB(inOutTimeStruct->tm_year); inOutTimeStruct->tm_wday = EndianS32_NtoB(inOutTimeStruct->tm_wday); inOutTimeStruct->tm_yday = EndianS32_NtoB(inOutTimeStruct->tm_yday); inOutTimeStruct->tm_isdst = EndianS32_NtoB(inOutTimeStruct->tm_isdst); inOutTimeStruct->tm_gmtoff = EndianS32_NtoB(inOutTimeStruct->tm_gmtoff); } #endif } // ---------------------------------------------------------------------------------------- // pwsf_EndianAdjustPWFileHeader // ---------------------------------------------------------------------------------------- void pwsf_EndianAdjustPWFileHeader( PWFileHeader *inOutHeader, int native ) { #if TARGET_RT_LITTLE_ENDIAN if ( native == 1 ) { // adjust to native byte order inOutHeader->signature = EndianU32_BtoN(inOutHeader->signature); inOutHeader->version = EndianU32_BtoN(inOutHeader->version); inOutHeader->entrySize = EndianU32_BtoN(inOutHeader->entrySize); inOutHeader->sequenceNumber = EndianU32_BtoN(inOutHeader->sequenceNumber); inOutHeader->numberOfSlotsCurrentlyInFile = EndianU32_BtoN(inOutHeader->numberOfSlotsCurrentlyInFile); inOutHeader->deepestSlotUsed = EndianU32_BtoN(inOutHeader->deepestSlotUsed); inOutHeader->access.maxMinutesUntilChangePassword = EndianU32_BtoN(inOutHeader->access.maxMinutesUntilChangePassword); inOutHeader->access.maxMinutesUntilDisabled = EndianU32_BtoN(inOutHeader->access.maxMinutesUntilDisabled); inOutHeader->access.maxMinutesOfNonUse = EndianU32_BtoN(inOutHeader->access.maxMinutesOfNonUse); inOutHeader->access.maxFailedLoginAttempts = EndianU16_BtoN(inOutHeader->access.maxFailedLoginAttempts); inOutHeader->access.minChars = EndianU16_BtoN(inOutHeader->access.minChars); inOutHeader->access.maxChars = EndianU16_BtoN(inOutHeader->access.maxChars); pwsf_EndianAdjustTimeStruct(&(inOutHeader->access.expirationDateGMT), 1); pwsf_EndianAdjustTimeStruct(&(inOutHeader->access.hardExpireDateGMT), 1); inOutHeader->publicKeyLen = EndianU32_BtoN(inOutHeader->publicKeyLen); // 1024-bit RSA public key - expected size is 233 inOutHeader->privateKeyLen = EndianU32_BtoN(inOutHeader->privateKeyLen); inOutHeader->deepestSlotUsedByThisServer = EndianU32_BtoN(inOutHeader->deepestSlotUsedByThisServer); inOutHeader->accessModDate = EndianU32_BtoN(inOutHeader->accessModDate); inOutHeader->extraAccess.minutesUntilFailedLoginReset = EndianU32_BtoN(inOutHeader->extraAccess.minutesUntilFailedLoginReset); inOutHeader->extraAccess.notGuessablePattern = EndianU32_BtoN(inOutHeader->extraAccess.notGuessablePattern); } else { // adjust to big-endian byte order inOutHeader->signature = EndianU32_NtoB(inOutHeader->signature); inOutHeader->version = EndianU32_NtoB(inOutHeader->version); inOutHeader->entrySize = EndianU32_NtoB(inOutHeader->entrySize); inOutHeader->sequenceNumber = EndianU32_NtoB(inOutHeader->sequenceNumber); inOutHeader->numberOfSlotsCurrentlyInFile = EndianU32_NtoB(inOutHeader->numberOfSlotsCurrentlyInFile); inOutHeader->deepestSlotUsed = EndianU32_NtoB(inOutHeader->deepestSlotUsed); inOutHeader->access.maxMinutesUntilChangePassword = EndianU32_NtoB(inOutHeader->access.maxMinutesUntilChangePassword); inOutHeader->access.maxMinutesUntilDisabled = EndianU32_NtoB(inOutHeader->access.maxMinutesUntilDisabled); inOutHeader->access.maxMinutesOfNonUse = EndianU32_NtoB(inOutHeader->access.maxMinutesOfNonUse); inOutHeader->access.maxFailedLoginAttempts = EndianU32_NtoB(inOutHeader->access.maxFailedLoginAttempts); pwsf_EndianAdjustTimeStruct(&(inOutHeader->access.expirationDateGMT), 0); pwsf_EndianAdjustTimeStruct(&(inOutHeader->access.hardExpireDateGMT), 0); inOutHeader->access.minChars = EndianU16_NtoB(inOutHeader->access.minChars); inOutHeader->access.maxChars = EndianU16_NtoB(inOutHeader->access.maxChars); inOutHeader->publicKeyLen = EndianU32_NtoB(inOutHeader->publicKeyLen); inOutHeader->privateKeyLen = EndianU32_NtoB(inOutHeader->privateKeyLen); inOutHeader->deepestSlotUsedByThisServer = EndianU32_NtoB(inOutHeader->deepestSlotUsedByThisServer); inOutHeader->accessModDate = EndianU32_NtoB(inOutHeader->accessModDate); inOutHeader->extraAccess.minutesUntilFailedLoginReset = EndianU32_NtoB(inOutHeader->extraAccess.minutesUntilFailedLoginReset); inOutHeader->extraAccess.notGuessablePattern = EndianU32_NtoB(inOutHeader->extraAccess.notGuessablePattern); } #endif }