long LWIRecTypeLookup::GetVector(tDataListPtr List, PLWIBITVECTOR* ppVector) { int macError = eDSNoErr; PLWIBITVECTOR pResult = NULL; tDataNodePtr pDataNode = NULL; int nNodes = 0; Index_t value = idx_unknown; macError = LWIMakeBitVector(idx_sentinel, &pResult); GOTO_CLEANUP_ON_MACERROR(macError); if (List != NULL) { nNodes = dsDataListGetNodeCount(List); for (int iNode = 0; iNode < nNodes; iNode++) { macError = dsDataListGetNodeAlloc(0, List, iNode+1, &pDataNode); GOTO_CLEANUP_ON_MACERROR(macError); value = GetIndex(pDataNode->fBufferData); if (value) { LWI_BITVECTOR_SET(pResult, value); } dsDataNodeDeAllocate(NULL, pDataNode); pDataNode = NULL; } } *ppVector = pResult; pResult = NULL; cleanup: if (pResult) { LWIFreeBitVector(pResult); } if (pDataNode) { dsDataNodeDeAllocate(0, pDataNode); } return macError; }
tDirStatus authenticate_user_to_node(KADirectoryNode *node, const char *username, const char *password) { if (!username) return false; size_t ulNameLen = strlen(username); size_t ulPassLen = password ? strlen(password) : 0; dsBool authenticateOnly = true; tDataNodePtr _authType = dsDataNodeAllocateString (node->_directoryRef, kDSStdAuthNodeNativeNoClearText /*kDSStdAuthNodeNativeClearTextOK*/); tDataBufferPtr _authdataBufferPtr = dsDataBufferAllocate(node->_directoryRef, sizeof(ulNameLen) + ulNameLen + sizeof(ulPassLen) + ulPassLen); tDataBufferPtr _stepBufferPtr = dsDataBufferAllocate(node->_directoryRef, 2048); char *cpBuff = _authdataBufferPtr->fBufferData; memcpy(cpBuff, &ulNameLen, sizeof (ulNameLen)); cpBuff += sizeof(ulNameLen); memcpy(cpBuff, username, ulNameLen); cpBuff += ulNameLen; memcpy(cpBuff, &ulPassLen, sizeof(ulPassLen)); cpBuff += sizeof(ulPassLen); memcpy(cpBuff, password, ulPassLen); _authdataBufferPtr->fBufferLength = sizeof(ulNameLen) + ulNameLen + sizeof(ulPassLen) + ulPassLen; tDirStatus status = dsDoDirNodeAuth(node->_nodeRef, _authType, authenticateOnly, _authdataBufferPtr, _stepBufferPtr, 0); dsDataNodeDeAllocate(node->_directoryRef, _authType); dsDataBufferDeAllocate(node->_directoryRef, _authdataBufferPtr); dsDataBufferDeAllocate(node->_directoryRef, _stepBufferPtr); return status; }
CFArrayRef find_records_by_attribute_value(KADirectoryNode *node, const char *recordType, const char *attributeType, tDirPatternMatch matchType, const char *attributeValue, const char *attributesReturned) { tDataNodePtr attributeTypeDataNode = dsDataNodeAllocateString(node->_directoryRef, kDSNAttrAuthenticationAuthority); tDataNodePtr attributeValueDataNode = dsDataNodeAllocateString(node->_directoryRef, attributeValue); tDataListPtr recordTypeDataList = dsBuildListFromStrings(node->_directoryRef, recordType, NULL); tDataListPtr returnAttributesDataList = dsBuildListFromStrings(node->_directoryRef, attributesReturned, NULL); CFArrayRef results = find_records_by_attribute_value_internal(node, recordTypeDataList, attributeTypeDataNode, matchType, attributeValueDataNode, returnAttributesDataList); if (attributeTypeDataNode) dsDataNodeDeAllocate(node->_directoryRef, attributeTypeDataNode); if (attributeValueDataNode) dsDataNodeDeAllocate(node->_directoryRef, attributeValueDataNode); if (recordTypeDataList) dsDataListDeallocate(node->_directoryRef, recordTypeDataList); if (returnAttributesDataList) dsDataListDeallocate(node->_directoryRef, returnAttributesDataList); return results; }
//---------------------------------------------------------------------- // dsauth_set_mppe_keys // get the mppe keys from the password server // if this fails - do nothing. there is no way to // know if the keys are actually going to be needed // at this point. //---------------------------------------------------------------------- static int dsauth_set_mppe_keys(tDirReference dirRef, tDirNodeReference userNode, u_char *remmd, tAttributeValueEntryPtr authAuthorityAttr, const unsigned char *challenge) { tDataNodePtr authKeysDataNodePtr = 0; tDataBufferPtr authDataBufPtr = 0; tDataBufferPtr responseDataBufPtr = 0; tDataBufferPtr chapDataBufPtr = NULL; tDirStatus dsResult = eDSNoErr; char *ptr, *comma, *tagStart; MS_Chap2Response *resp; char *keyaccessPassword = 0; char *keyaccessName = 0; u_int32_t keyaccessNameSize = 0; u_int32_t keyaccessPasswordSize; int len, i; u_int32_t slotIDSize = 0; const char *slotID; tContextData dir_context = 0; int status = 0; mppe_keys_set = 0; // parse authAuthorityAttribute to determine if key agent needs to be used. // auth authority tag will be between 2 semicolons. tagStart = 0; ptr = authAuthorityAttr->fAttributeValueData.fBufferData; // DSAuth_hex_print("authAuth mppe", authAuthorityAttr->fAttributeValueData.fBufferData, authAuthorityAttr->fAttributeValueData.fBufferLength); for (i = 0; i < authAuthorityAttr->fAttributeValueData.fBufferLength; i++) { if (*ptr == ';') { if (tagStart == 0) tagStart = ptr + 1; else break; } ptr++; } if (*ptr != ';') { error("DSAuth plugin: Password Server not available for MPPE key retrieval.\n"); return (status); } if (strncmp(tagStart, kDSTagAuthAuthorityPasswordServer, ptr - tagStart) == 0) { dsauth_get_admin_acct(&keyaccessNameSize, &keyaccessName, &keyaccessPasswordSize, &keyaccessPassword); if (keyaccessName == 0) { error("DSAuth plugin: Could not retrieve key agent account information.\n"); return (status); } // PWS auths expect to receive the PWS ID in the MPPE phase comma = strchr(ptr, ','); if (comma == NULL) { error("DSAuth plugin: Could not retrieve slot ID.\n"); return (status); } slotID = ptr + 1; // skip the ';' as well slotIDSize = comma - slotID; } else { error("DSAuth plugin: unsupported authen authority: recved %s, want %s\n", tagStart, kDSTagAuthAuthorityPasswordServer); return (status); // unsupported authentication authority - don't set the keys } resp = (MS_Chap2Response*)remmd; if ((responseDataBufPtr = dsDataBufferAllocate(dirRef, BUF_LEN)) == 0) { error("DSAuth plugin: Could not allocate data buffer\n"); goto cleanup; } if ((authKeysDataNodePtr = dsDataNodeAllocateString(dirRef, kDSStdAuthMPPEMasterKeys)) == 0) { error("DSAuth plugin: Could not allocate data buffer\n"); goto cleanup; } if ((authDataBufPtr = dsDataBufferAllocate(dirRef, BUF_LEN)) == 0) { error("DSAuth plugin: Could not allocate data buffer\n"); goto cleanup; } /* * phase 1 uses an MSCHAP-style auth for the VPN agent (agent account, server challenge, peer challenge, agent NT response, agent account) * phase 2 retrieves the keys (PWS ID of the user, client NT response, keysize) */ // Phase 1 chapDataBufPtr = dsauth_agent_authbuffer(dirRef, keyaccessName, keyaccessNameSize, keyaccessPassword, keyaccessPasswordSize, challenge); if (chapDataBufPtr == NULL) { error("DSAuth plugin: Could not generate agent auth buffer\n"); goto cleanup; } if ((dsResult = dsDoDirNodeAuth(userNode, authKeysDataNodePtr, TRUE, chapDataBufPtr, responseDataBufPtr, &dir_context)) != eDSNoErr) { error("DSAuth plugin: Could not authenticate key agent for encryption key retrieval, err %d\n", dsResult); goto cleanup; } // Phase 2 ptr = (char*)(authDataBufPtr->fBufferData); // DSAuth_hex_print("PWS ID", slotID, slotIDSize); // DSAuth_hex_print("NTResp", resp->NTResp, NT_RESPONSE_SIZE); // 4 byte length & slotID *((u_int32_t*)ptr) = slotIDSize; ptr += sizeof(u_int32_t); memcpy(ptr, slotID, slotIDSize); ptr += slotIDSize; // 4 byte length & client digest *((u_int32_t*)ptr) = NT_RESPONSE_SIZE; ptr += sizeof(u_int32_t); memcpy(ptr, resp->NTResp, NT_RESPONSE_SIZE); ptr += NT_RESPONSE_SIZE; // 4 byte length and master key len - always 128 *((u_int32_t*)ptr) = 1; ptr += sizeof(u_int32_t); *ptr = MPPE_MAX_KEY_LEN; authDataBufPtr->fBufferLength = slotIDSize + NT_RESPONSE_SIZE + 1 + (3 * sizeof(u_int32_t)); // get the mppe keys if ((dsResult = dsDoDirNodeAuth(userNode, authKeysDataNodePtr, TRUE, authDataBufPtr, responseDataBufPtr, &dir_context)) == eDSNoErr) { if (responseDataBufPtr->fBufferLength == (2 * sizeof(u_int32_t)) + (2 * MPPE_MAX_KEY_LEN)) { ptr = (char*)(responseDataBufPtr->fBufferData); len = *((u_int32_t*)ptr); ptr += sizeof(u_int32_t); if (len == sizeof(mppe_send_key)) memcpy(mppe_send_key, ptr, sizeof(mppe_send_key)); ptr += len; len = *((u_int32_t*)ptr); ptr += sizeof(u_int32_t); if (len == sizeof(mppe_recv_key)) memcpy(mppe_recv_key, ptr, sizeof(mppe_recv_key)); mppe_keys_set = 1; status = 1; } else error("DSAuth plugin: Invalid MPPE data for encryption keys retrieval\n"); } else error("DSAuth plugin: Failed to retrieve MPPE encryption keys from the password server: errno %d, ctxt %x\n", dsResult, dir_context); cleanup: if (dir_context != 0) { dsReleaseContinueData(dirRef, dir_context); } if (keyaccessPassword) { bzero(keyaccessPassword, keyaccessPasswordSize); // clear the admin password from memory #if !TARGET_OS_EMBEDDED // This file is not built for Embedded SecKeychainItemFreeContent(NULL, keyaccessPassword); #endif /* TARGET_OS_EMBEDDED */ } if (keyaccessName) { free(keyaccessName); } if (responseDataBufPtr) dsDataBufferDeAllocate(dirRef, responseDataBufPtr); if (chapDataBufPtr) dsDataNodeDeAllocate(dirRef, chapDataBufPtr); if (authKeysDataNodePtr) dsDataNodeDeAllocate(dirRef, authKeysDataNodePtr); if (authDataBufPtr) dsDataBufferDeAllocate(dirRef, authDataBufPtr); return (status); }
static int dsauth_chap(u_char *name, u_char *ourname, int id, struct chap_digest_type *digest, unsigned char *challenge, unsigned char *response, unsigned char *message, int message_space) { tDirReference dirRef; tDirNodeReference userNode = 0; tDataNodePtr authTypeDataNodePtr = 0; tDataBufferPtr authDataBufPtr = 0; tDataBufferPtr responseDataBufPtr = 0; tAttributeValueEntryPtr recordNameAttr = 0; tAttributeValueEntryPtr authAuthorityAttr = 0; tDirStatus dsResult = eDSNoErr; int authResult = 0; char *ptr; MS_Chap2Response *resp; u_int32_t userShortNameSize; u_int32_t userNameSize = strlen((char*)name); u_int32_t authDataSize; int challenge_len, response_len; CFMutableDictionaryRef serviceInfo = 0; CFMutableDictionaryRef eventDetail; CFDictionaryRef interface; CFStringRef subtypeRef; CFStringRef addrRef; challenge_len = *challenge++; /* skip length, is 16 */ response_len = *response++; // currently only support MS-CHAPv2 if (digest->code != CHAP_MICROSOFT_V2 || response_len != MS_CHAP2_RESPONSE_LEN || challenge_len != CHALLENGE_SIZE) return 0; resp = (MS_Chap2Response*)response; if ((dsResult = dsOpenDirService(&dirRef)) == eDSNoErr) { if ((authTypeDataNodePtr = dsDataNodeAllocateString(dirRef, kDSStdAuthMSCHAP2)) == 0) { error("DSAuth plugin: Could not allocate data buffer\n"); goto cleanup; } // setup service info interface = CFDictionaryGetValue(systemOptions, kRASEntInterface); if (interface && CFGetTypeID(interface) == CFDictionaryGetTypeID()) { subtypeRef = CFDictionaryGetValue(interface, kRASPropInterfaceSubType); if (subtypeRef && CFGetTypeID(subtypeRef) == CFStringGetTypeID()) { serviceInfo = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (serviceInfo) { eventDetail = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (eventDetail) { addrRef = CFStringCreateWithCString(0, remoteaddress, kCFStringEncodingUTF8); if (addrRef) { CFDictionaryAddValue(eventDetail, CFSTR("ClientIP"), addrRef); CFRelease(addrRef); } if (CFStringCompare(subtypeRef, kRASValInterfaceSubTypeL2TP, 0) == kCFCompareEqualTo) { CFDictionaryAddValue(eventDetail, CFSTR("HostPort"), CFSTR("1701")); CFDictionaryAddValue(eventDetail, CFSTR("ProtocolName"), CFSTR("L2TP")); CFDictionaryAddValue(eventDetail, CFSTR("ProtocolVersion"), CFSTR("2")); } else if (CFStringCompare(subtypeRef, kRASValInterfaceSubTypePPTP, 0) == kCFCompareEqualTo) { CFDictionaryAddValue(eventDetail, CFSTR("HostPort"), CFSTR("1723")); CFDictionaryAddValue(eventDetail, CFSTR("ProtocolName"), CFSTR("PPTP")); CFDictionaryAddValue(eventDetail, CFSTR("ProtocolVersion"), CFSTR("1")); } else CFDictionaryAddValue(eventDetail, CFSTR("ProtocolName"), subtypeRef); CFDictionaryAddValue(eventDetail, CFSTR("ServiceName"), CFSTR("VPN")); // add eventDetail to serviceInfo dict CFDictionaryAddValue(serviceInfo, CFSTR("ServiceInformation"), eventDetail); CFRelease(eventDetail); // allocate response buffer with service info if (dsServiceInformationAllocate(serviceInfo, BUF_LEN, &responseDataBufPtr) != eDSNoErr) { error("DSAuth plugin: Unable to allocate service info buffer\n"); goto cleanup; } } else { error("DSAuth plugin: Unable to allocate eventDetail dictionary\n"); goto cleanup; } } else { error("DSAuth plugin: Unable to allocate serviceInfo dictionary\n"); goto cleanup; } } else { error("DSAuth plugin: No Interface subtype found\n"); goto cleanup; } } else { error("DSAuth plugin: No Interface dictionary found\n"); goto cleanup; } if (dsauth_find_user_node(dirRef, (char*)name, &userNode, &recordNameAttr, &authAuthorityAttr) == 0) { userShortNameSize = recordNameAttr->fAttributeValueData.fBufferLength; authDataSize = userNameSize + userShortNameSize + NT_RESPONSE_SIZE + (2 * CHALLENGE_SIZE) + (5 * sizeof(u_int32_t)); if ((authDataBufPtr = dsDataBufferAllocate(dirRef, authDataSize)) != 0) { authDataBufPtr->fBufferLength = authDataSize; // setup the response buffer ptr = (char*)(authDataBufPtr->fBufferData); // 4 byte length & user name *((u_int32_t*)ptr) = userShortNameSize; ptr += sizeof(u_int32_t); memcpy(ptr, recordNameAttr->fAttributeValueData.fBufferData, userShortNameSize); ptr += userShortNameSize; // 4 byte length & server challenge *((u_int32_t*)ptr) = CHALLENGE_SIZE; ptr += sizeof(u_int32_t); memcpy(ptr, challenge, CHALLENGE_SIZE); ptr += CHALLENGE_SIZE; // 4 byte length & peer challenge *((u_int32_t*)ptr) = CHALLENGE_SIZE; ptr += sizeof(u_int32_t); memcpy(ptr, resp->PeerChallenge, CHALLENGE_SIZE); ptr += CHALLENGE_SIZE; // 4 byte length & client digest *((u_int32_t*)ptr) = NT_RESPONSE_SIZE; ptr += sizeof(u_int32_t); memcpy(ptr, resp->NTResp, NT_RESPONSE_SIZE); ptr += NT_RESPONSE_SIZE; // 4 byte length & user name (repeated) *((u_int32_t*)ptr) = userNameSize; ptr += sizeof(u_int32_t); memcpy(ptr, name, userNameSize); if ((dsResult = dsDoDirNodeAuth(userNode, authTypeDataNodePtr, TRUE, authDataBufPtr, responseDataBufPtr, 0)) == eDSNoErr) { // setup return data if ((responseDataBufPtr->fBufferLength == MS_AUTH_RESPONSE_LENGTH + 4) && *((u_int32_t*)(responseDataBufPtr->fBufferData)) == MS_AUTH_RESPONSE_LENGTH) { responseDataBufPtr->fBufferData[4 + MS_AUTH_RESPONSE_LENGTH] = 0; if (resp->Flags[0]) slprintf((char*)message, message_space, "S=%s", responseDataBufPtr->fBufferData + 4); else slprintf((char*)message, message_space, "S=%s M=%s", responseDataBufPtr->fBufferData + 4, "Access granted"); authResult = 1; if ((ccp_wantoptions[0].mppe)) { if (!dsauth_set_mppe_keys(dirRef, userNode, response, authAuthorityAttr, challenge)) { error("DSAuth plugin: MPPE key required, but its retrieval failed.\n"); authResult = 0; } } } } } dsCloseDirNode(userNode); dsDeallocAttributeValueEntry(dirRef, recordNameAttr); dsDeallocAttributeValueEntry(dirRef, authAuthorityAttr); } cleanup: if (serviceInfo) CFRelease(serviceInfo); if (responseDataBufPtr) dsDataBufferDeAllocate(dirRef, responseDataBufPtr); if (authTypeDataNodePtr) dsDataNodeDeAllocate(dirRef, authTypeDataNodePtr); if (authDataBufPtr) dsDataBufferDeAllocate(dirRef, authDataBufPtr); dsCloseDirService(dirRef); } return authResult; }
//---------------------------------------------------------------------- // dsauth_pap //---------------------------------------------------------------------- static int dsauth_pap(char *user, char *passwd, char **msgp, struct wordlist **paddrs, struct wordlist **popts) { tDirReference dirRef; tDirNodeReference userNode = 0; tDataNodePtr authTypeDataNodePtr = 0; tDataBufferPtr authDataBufPtr = 0; tDataBufferPtr responseDataBufPtr = 0; tAttributeValueEntryPtr recordNameAttr = 0; tAttributeValueEntryPtr authAuthorityAttr = 0; tDirStatus dsResult = eDSNoErr; char *ptr; int authResult = 0; u_int32_t userShortNameSize; u_int32_t passwordSize = strlen(passwd); u_int32_t authDataSize; if ((dsResult = dsOpenDirService(&dirRef)) == eDSNoErr) { if ((responseDataBufPtr = dsDataBufferAllocate(dirRef, BUF_LEN)) == 0) { error("DSAuth plugin: Could not allocate data buffer\n"); goto cleanup; } if ((authTypeDataNodePtr = dsDataNodeAllocateString(dirRef, kDSStdAuthNodeNativeNoClearText)) == 0) { error("DSAuth plugin: Could not allocate data buffer\n"); goto cleanup; } if (dsauth_find_user_node(dirRef, user, &userNode, &recordNameAttr, &authAuthorityAttr) == 0) { userShortNameSize = recordNameAttr->fAttributeValueData.fBufferLength; authDataSize = userShortNameSize + passwordSize + (2 * sizeof(u_int32_t)); if ((authDataBufPtr = dsDataBufferAllocate(dirRef, authDataSize)) != 0) { authDataBufPtr->fBufferLength = authDataSize; /* store user name and password into the auth buffer in the correct format */ ptr = (char*)(authDataBufPtr->fBufferData); // 4 byte length & user name *((u_int32_t*)ptr) = userShortNameSize; ptr += sizeof(u_int32_t); memcpy(ptr, recordNameAttr->fAttributeValueData.fBufferData, userShortNameSize); ptr += userShortNameSize; // 4 byte length & password *((u_int32_t*)ptr) = passwordSize; ptr += sizeof(u_int32_t); memcpy(ptr, passwd, passwordSize); if ((dsResult = dsDoDirNodeAuth(userNode, authTypeDataNodePtr, TRUE, authDataBufPtr, responseDataBufPtr, 0)) == eDSNoErr) { authResult = 1; info("DSAuth plugin: user authentication successful\n"); } bzero(authDataBufPtr->fBufferData, authDataSize); // don't leave password in buffer } dsCloseDirNode(userNode); // returned from dsauth_find_user() dsDeallocAttributeValueEntry(dirRef, recordNameAttr); dsDeallocAttributeValueEntry(dirRef, authAuthorityAttr); } cleanup: if (responseDataBufPtr) dsDataBufferDeAllocate(dirRef, responseDataBufPtr); if (authTypeDataNodePtr) dsDataNodeDeAllocate(dirRef, authTypeDataNodePtr); if (authDataBufPtr) dsDataBufferDeAllocate(dirRef, authDataBufPtr); dsCloseDirService(dirRef); } return authResult; }
static long od_check_passwd(char const *uname, char const *password) { long result = eDSAuthFailed; tDirReference dsRef = 0; tDataBuffer *tDataBuff; tDirNodeReference nodeRef = 0; long status = eDSNoErr; tContextData context = 0; uint32_t nodeCount = 0; uint32_t attrIndex = 0; tDataList *nodeName = NULL; tAttributeEntryPtr pAttrEntry = NULL; tDataList *pRecName = NULL; tDataList *pRecType = NULL; tDataList *pAttrType = NULL; uint32_t recCount = 0; tRecordEntry *pRecEntry = NULL; tAttributeListRef attrListRef = 0; char *pUserLocation = NULL; char *pUserName = NULL; tAttributeValueListRef valueRef = 0; tAttributeValueEntry *pValueEntry = NULL; tDataList *pUserNode = NULL; tDirNodeReference userNodeRef = 0; tDataBuffer *pStepBuff = NULL; tDataNode *pAuthType = NULL; tAttributeValueEntry *pRecordType = NULL; uint32_t uiCurr = 0; uint32_t uiLen = 0; uint32_t pwLen = 0; if (!uname || !password) return result; do { status = dsOpenDirService( &dsRef ); if ( status != eDSNoErr ) return result; tDataBuff = dsDataBufferAllocate( dsRef, 4096 ); if (!tDataBuff) break; /* find user on search node */ status = dsFindDirNodes( dsRef, tDataBuff, NULL, eDSSearchNodeName, &nodeCount, &context ); if (status != eDSNoErr || nodeCount < 1) break; status = dsGetDirNodeName( dsRef, tDataBuff, 1, &nodeName ); if (status != eDSNoErr) break; status = dsOpenDirNode( dsRef, nodeName, &nodeRef ); dsDataListDeallocate( dsRef, nodeName ); free( nodeName ); nodeName = NULL; if (status != eDSNoErr) break; pRecName = dsBuildListFromStrings( dsRef, uname, NULL ); pRecType = dsBuildListFromStrings( dsRef, kDSStdRecordTypeUsers, kDSStdRecordTypeComputers, kDSStdRecordTypeMachines, NULL ); pAttrType = dsBuildListFromStrings( dsRef, kDSNAttrMetaNodeLocation, kDSNAttrRecordName, kDSNAttrRecordType, NULL ); recCount = 1; status = dsGetRecordList( nodeRef, tDataBuff, pRecName, eDSExact, pRecType, pAttrType, 0, &recCount, &context ); if ( status != eDSNoErr || recCount == 0 ) break; status = dsGetRecordEntry( nodeRef, tDataBuff, 1, &attrListRef, &pRecEntry ); if ( status != eDSNoErr ) break; for ( attrIndex = 1; (attrIndex <= pRecEntry->fRecordAttributeCount) && (status == eDSNoErr); attrIndex++ ) { status = dsGetAttributeEntry( nodeRef, tDataBuff, attrListRef, attrIndex, &valueRef, &pAttrEntry ); if ( status == eDSNoErr && pAttrEntry != NULL ) { if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation ) == 0 ) { status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry ); if ( status == eDSNoErr && pValueEntry != NULL ) { pUserLocation = (char *) calloc( pValueEntry->fAttributeValueData.fBufferLength + 1, sizeof(char) ); memcpy( pUserLocation, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength ); } } else if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrRecordName ) == 0 ) { status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry ); if ( status == eDSNoErr && pValueEntry != NULL ) { pUserName = (char *) calloc( pValueEntry->fAttributeValueData.fBufferLength + 1, sizeof(char) ); memcpy( pUserName, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength ); } } else if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrRecordType ) == 0 ) { status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry ); if ( status == eDSNoErr && pValueEntry != NULL ) { pRecordType = pValueEntry; pValueEntry = NULL; } } if ( pValueEntry != NULL ) { dsDeallocAttributeValueEntry( dsRef, pValueEntry ); pValueEntry = NULL; } if ( pAttrEntry != NULL ) { dsDeallocAttributeEntry( dsRef, pAttrEntry ); pAttrEntry = NULL; } dsCloseAttributeValueList( valueRef ); valueRef = 0; } } pUserNode = dsBuildFromPath( dsRef, pUserLocation, "/" ); status = dsOpenDirNode( dsRef, pUserNode, &userNodeRef ); dsDataListDeallocate( dsRef, pUserNode ); free( pUserNode ); pUserNode = NULL; if ( status != eDSNoErr ) break; pStepBuff = dsDataBufferAllocate( dsRef, 128 ); pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthNodeNativeClearTextOK ); uiCurr = 0; /* User name */ uiLen = (uint32_t)strlen( pUserName ); memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof(uiLen) ); uiCurr += (uint32_t)sizeof( uiLen ); memcpy( &(tDataBuff->fBufferData[ uiCurr ]), pUserName, uiLen ); uiCurr += uiLen; /* pw */ pwLen = (uint32_t)strlen( password ); memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &pwLen, sizeof(pwLen) ); uiCurr += (uint32_t)sizeof( pwLen ); memcpy( &(tDataBuff->fBufferData[ uiCurr ]), password, pwLen ); uiCurr += pwLen; tDataBuff->fBufferLength = uiCurr; result = dsDoDirNodeAuthOnRecordType( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL, &pRecordType->fAttributeValueData ); } while ( 0 ); /* clean up */ if (pAuthType != NULL) { dsDataNodeDeAllocate( dsRef, pAuthType ); pAuthType = NULL; } if (pRecordType != NULL) { dsDeallocAttributeValueEntry( dsRef, pRecordType ); pRecordType = NULL; } if (tDataBuff != NULL) { bzero( tDataBuff, tDataBuff->fBufferSize ); dsDataBufferDeAllocate( dsRef, tDataBuff ); tDataBuff = NULL; } if (pStepBuff != NULL) { dsDataBufferDeAllocate( dsRef, pStepBuff ); pStepBuff = NULL; } if (pUserLocation != NULL) { free(pUserLocation); pUserLocation = NULL; } if (pRecName != NULL) { dsDataListDeallocate( dsRef, pRecName ); free( pRecName ); pRecName = NULL; } if (pRecType != NULL) { dsDataListDeallocate( dsRef, pRecType ); free( pRecType ); pRecType = NULL; } if (pAttrType != NULL) { dsDataListDeallocate( dsRef, pAttrType ); free( pAttrType ); pAttrType = NULL; } if (nodeRef != 0) { dsCloseDirNode(nodeRef); nodeRef = 0; } if (dsRef != 0) { dsCloseDirService(dsRef); dsRef = 0; } return result; }
tDirStatus authWithNode(tDirReference pDirRef, tDataListPtr pAuthNodeList, const char *pszUsername, const char *pszPassword) { tDirStatus dsErr = eDSNoErr; /* Open the authentication node. */ tDirNodeReference pAuthNodeRef = NULL; dsErr = dsOpenDirNode(pDirRef, pAuthNodeList, &pAuthNodeRef); if (dsErr == eDSNoErr) { /* How like we to authenticate! */ tDataNodePtr pAuthMethod = dsDataNodeAllocateString(pDirRef, kDSStdAuthNodeNativeClearTextOK); if (pAuthMethod) { /* Create the memory holding the authentication data. The data * structure consists of 4 byte length of the username + zero byte, * the username itself, a 4 byte length of the password & the * password itself + zero byte. */ tDataBufferPtr pAuthOutBuf = dsDataBufferAllocate(pDirRef, s_cBufferSize); if (pAuthOutBuf) { size_t cUserName = strlen(pszUsername) + 1; size_t cPassword = strlen(pszPassword) + 1; unsigned long cLen = 0; tDataBufferPtr pAuthInBuf = dsDataBufferAllocate(pDirRef, sizeof(cLen) + cUserName + sizeof(cLen) + cPassword); if (pAuthInBuf) { /* Move the data into the buffer. */ pAuthInBuf->fBufferLength = 0; /* Length of the username */ cLen = cUserName; memcpy(&pAuthInBuf->fBufferData[pAuthInBuf->fBufferLength], &cLen, sizeof(cLen)); pAuthInBuf->fBufferLength += sizeof(cLen); /* The username itself */ memcpy(&pAuthInBuf->fBufferData[pAuthInBuf->fBufferLength], pszUsername, cUserName); pAuthInBuf->fBufferLength += cUserName; /* Length of the password */ cLen = cPassword; memcpy(&pAuthInBuf->fBufferData[pAuthInBuf->fBufferLength], &cLen, sizeof(cLen)); pAuthInBuf->fBufferLength += sizeof(cLen); /* The password itself */ memcpy(&pAuthInBuf->fBufferData[pAuthInBuf->fBufferLength], pszPassword, cPassword); pAuthInBuf->fBufferLength += cPassword; /* Now authenticate */ dsErr = dsDoDirNodeAuth(pAuthNodeRef, pAuthMethod, true, pAuthInBuf, pAuthOutBuf, NULL); /* Clean up. */ dsDataBufferDeAllocate(pDirRef, pAuthInBuf); } else dsErr = eDSAllocationFailed; dsDataBufferDeAllocate(pDirRef, pAuthOutBuf); } else dsErr = eDSAllocationFailed; dsDataNodeDeAllocate(pDirRef, pAuthMethod); } else dsErr = eDSAllocationFailed; dsCloseDirNode(pAuthNodeRef); } return dsErr; }
tDirStatus SaveAuthAuthoritiesWithRecordRef( CDSLocalPlugin* inPlugin, tDirNodeReference inNodeRef, tRecordReference inRecordRef, CAuthAuthority &inAATank ) { tDirStatus siResult = eDSAuthFailed; UInt32 avIndex = 0; UInt32 avCount = 0; char *aaStr = NULL; CFMutableDictionaryRef nodeDict = NULL; CFStringRef preRootAuthString = NULL; tDataListPtr attrValueList = NULL; try { // retrieve the same nodeDict the plugin object is going to use CFDictionaryRef openRecordDict = inPlugin->RecordDictForRecordRef( inRecordRef ); if ( openRecordDict == NULL ) throw( eDSInvalidRecordRef ); nodeDict = (CFMutableDictionaryRef)CFDictionaryGetValue( openRecordDict, CFSTR(kOpenRecordDictNodeDict) ); if ( nodeDict == NULL ) throw( eDSInvalidNodeRef ); preRootAuthString = (CFStringRef) CFDictionaryGetValue( nodeDict, CFSTR(kNodeAuthenticatedUserName) ); if ( preRootAuthString != NULL ) CFRetain( preRootAuthString ); CFDictionarySetValue( nodeDict, CFSTR(kNodeAuthenticatedUserName), CFSTR("root") ); avCount = inAATank.GetValueCount(); if ( avCount == 0 ) { siResult = inPlugin->RemoveAttribute( inRecordRef, CFSTR(kDSNAttrAuthenticationAuthority) ); } else { attrValueList = dsDataListAllocate( 0 ); for ( avIndex = 0; avIndex < avCount; avIndex++ ) { aaStr = inAATank.GetValueAtIndex( avIndex ); if ( aaStr != NULL ) { siResult = dsAppendStringToListAlloc( 0, attrValueList, aaStr ); DSFreeString( aaStr ); if ( siResult != eDSNoErr ) throw( siResult ); } } // need to use SetAttributeValues() instead of RemoveAttribute() to avoid deleting the // shadow hash files. tDataNodePtr attrTypeNode = dsDataNodeAllocateString( 0, kDSNAttrAuthenticationAuthority ); sSetAttributeValues apiData = { kSetAttributeValues, 0, inRecordRef, attrTypeNode, attrValueList }; char *recTypeStr = inPlugin->GetRecordTypeFromRef( inRecordRef ); siResult = inPlugin->SetAttributeValues( &apiData, recTypeStr ); DSFreeString( recTypeStr ); dsDataNodeDeAllocate( 0, attrTypeNode ); } if ( siResult != eDSNoErr ) throw( siResult ); } catch( tDirStatus err ) { DbgLog( kLogPlugin, "SaveAuthAuthorities(): got error %d", err ); siResult = err; } if ( preRootAuthString != NULL ) { CFDictionarySetValue( nodeDict, CFSTR(kNodeAuthenticatedUserName), preRootAuthString ); CFRelease( preRootAuthString ); } else { CFDictionaryRemoveValue( nodeDict, CFSTR(kNodeAuthenticatedUserName) ); } DSFreeString( aaStr ); if ( attrValueList != NULL ) { dsDataListDeallocate( 0, attrValueList ); free( attrValueList ); } return siResult; }
int od_mschap_auth(REQUEST *request, VALUE_PAIR *challenge, VALUE_PAIR * usernamepair) { tDirStatus status = eDSNoErr; tDirReference dsRef = 0; tDirNodeReference userNodeRef = 0; tDataBuffer *tDataBuff = NULL; tDataBuffer *pStepBuff = NULL; tDataNode *pAuthType = NULL; uint32_t uiCurr = 0; uint32_t uiLen = 0; char *username_string = NULL; char *shortUserName = NULL; VALUE_PAIR *response = pairfind(request->packet->vps, PW_MSCHAP2_RESPONSE, VENDORPEC_MICROSOFT); #ifndef NDEBUG unsigned int t; #endif username_string = (char *) malloc(usernamepair->length + 1); if (username_string == NULL) return RLM_MODULE_FAIL; strlcpy(username_string, (char *)usernamepair->vp_strvalue, usernamepair->length + 1); status = dsOpenDirService(&dsRef); if (status != eDSNoErr) { free(username_string); radlog(L_ERR,"rlm_mschap: od_mschap_auth(): dsOpenDirService = %d", status); return RLM_MODULE_FAIL; } status = getUserNodeRef(username_string, &shortUserName, &userNodeRef, dsRef); if(status != RLM_MODULE_OK) { if (status != RLM_MODULE_NOOP) { RDEBUG2("od_mschap_auth: getUserNodeRef() failed"); } if (username_string != NULL) free(username_string); if (dsRef != 0) dsCloseDirService(dsRef); return status; } /* We got a node; fill the stepBuffer kDSStdAuthMSCHAP2 MS-CHAPv2 authentication method. The Open Directory plug-in generates the reply data for the client. The input buffer format consists of a four byte length specifying the length of the user name that follows, the user name, a four byte value specifying the length of the server challenge that follows, the server challenge, a four byte value specifying the length of the peer challenge that follows, the peer challenge, a four byte value specifying the length of the client's digest that follows, and the client's digest. The output buffer consists of a four byte value specifying the length of the return digest for the client's challenge. r = FillAuthBuff(pAuthBuff, 5, strlen(inName), inName, // Directory Services long or short name strlen(schal), schal, // server challenge strlen(peerchal), peerchal, // client challenge strlen(p24), p24, // P24 NT-Response 4, "User"); // must match the username that was used for the hash inName = username_string schal = challenge->vp_strvalue peerchal = response->vp_strvalue + 2 (16 octets) p24 = response->vp_strvalue + 26 (24 octets) */ pStepBuff = dsDataBufferAllocate(dsRef, 4096); tDataBuff = dsDataBufferAllocate(dsRef, 4096); pAuthType = dsDataNodeAllocateString(dsRef, kDSStdAuthMSCHAP2); uiCurr = 0; RDEBUG2("OD username_string = %s, OD shortUserName=%s (length = %lu)\n", username_string, shortUserName, strlen(shortUserName)); /* User name length + username */ uiLen = (uint32_t)strlen(shortUserName); memcpy(&(tDataBuff->fBufferData[uiCurr]), &uiLen, sizeof(uiLen)); uiCurr += sizeof(uiLen); memcpy(&(tDataBuff->fBufferData[uiCurr]), shortUserName, uiLen); uiCurr += uiLen; #ifndef NDEBUG RDEBUG2(" stepbuf server challenge:\t"); for (t = 0; t < challenge->length; t++) { fprintf(stderr, "%02x", challenge->vp_strvalue[t]); } fprintf(stderr, "\n"); #endif /* server challenge (ie. my (freeRADIUS) challenge) */ uiLen = 16; memcpy(&(tDataBuff->fBufferData[uiCurr]), &uiLen, sizeof(uiLen)); uiCurr += sizeof(uiLen); memcpy(&(tDataBuff->fBufferData[uiCurr]), &(challenge->vp_strvalue[0]), uiLen); uiCurr += uiLen; #ifndef NDEBUG RDEBUG2(" stepbuf peer challenge:\t\t"); for (t = 2; t < 18; t++) { fprintf(stderr, "%02x", response->vp_strvalue[t]); } fprintf(stderr, "\n"); #endif /* peer challenge (ie. the client-generated response) */ uiLen = 16; memcpy(&(tDataBuff->fBufferData[uiCurr]), &uiLen, sizeof(uiLen)); uiCurr += sizeof(uiLen); memcpy(&(tDataBuff->fBufferData[uiCurr]), &(response->vp_strvalue[2]), uiLen); uiCurr += uiLen; #ifndef NDEBUG RDEBUG2(" stepbuf p24:\t\t"); for (t = 26; t < 50; t++) { fprintf(stderr, "%02x", response->vp_strvalue[t]); } fprintf(stderr, "\n"); #endif /* p24 (ie. second part of client-generated response) */ uiLen = 24; /* strlen(&(response->vp_strvalue[26])); may contain NULL byte in the middle. */ memcpy(&(tDataBuff->fBufferData[uiCurr]), &uiLen, sizeof(uiLen)); uiCurr += sizeof(uiLen); memcpy(&(tDataBuff->fBufferData[uiCurr]), &(response->vp_strvalue[26]), uiLen); uiCurr += uiLen; /* Client generated use name (short name?) */ uiLen = (uint32_t)strlen(username_string); memcpy(&(tDataBuff->fBufferData[uiCurr]), &uiLen, sizeof(uiLen)); uiCurr += sizeof(uiLen); memcpy(&(tDataBuff->fBufferData[uiCurr]), username_string, uiLen); uiCurr += uiLen; tDataBuff->fBufferLength = uiCurr; status = dsDoDirNodeAuth(userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL); if (status == eDSNoErr) { if (pStepBuff->fBufferLength > 4) { uint32_t len; memcpy(&len, pStepBuff->fBufferData, sizeof(len)); if (len == 40) { char mschap_reply[42] = { '\0' }; pStepBuff->fBufferData[len+4] = '\0'; mschap_reply[0] = 'S'; mschap_reply[1] = '='; memcpy(&(mschap_reply[2]), &(pStepBuff->fBufferData[4]), len); mschap_add_reply(request, &request->reply->vps, *response->vp_strvalue, "MS-CHAP2-Success", mschap_reply, len+2); RDEBUG2("dsDoDirNodeAuth returns stepbuff: %s (len=%ld)\n", mschap_reply, len); } } } /* clean up */ if (username_string != NULL) free(username_string); if (shortUserName != NULL) free(shortUserName); if (tDataBuff != NULL) dsDataBufferDeAllocate(dsRef, tDataBuff); if (pStepBuff != NULL) dsDataBufferDeAllocate(dsRef, pStepBuff); if (pAuthType != NULL) dsDataNodeDeAllocate(dsRef, pAuthType); if (userNodeRef != 0) dsCloseDirNode(userNodeRef); if (dsRef != 0) dsCloseDirService(dsRef); if (status != eDSNoErr) { errno = EACCES; radlog(L_ERR, "rlm_mschap: authentication failed %d", status); /* <-- returns -14091 (eDSAuthMethodNotSupported) -14090 */ return RLM_MODULE_REJECT; } return RLM_MODULE_OK; }
long LWIAttrValDataQuery::Run(sDoMultiAttrValueSearchWithData* pMultiAttrValueSearchWithData, LWE_DS_FLAGS Flags, PNETADAPTERINFO pNetAdapterList) { long macError = eDSNoErr; long macError_userQuery = eDSNoErr; long macError_groupQuery = eDSNoErr; unsigned long bytesWritten = 0; unsigned long nRecordsWritten = 0; unsigned long TotalRecords = 0; LWIQuery* pQuery = NULL; int iter = 0; int resultCount = 0; int patternListCount = 0; int recordTypeCount = 0; int recordAttributeCount = 0; tDataNodePtr pPatternNode = NULL; bool isWithData = (kDoMultipleAttributeValueSearchWithData == pMultiAttrValueSearchWithData->fType); tContextData HandleId = 0; LOG_ENTER("LWIAttrValDataQuery::Run - fType = %d, fResult = %d, fInNodeRef = %d, fInAttrType = %s, fInPattMatchType = 0x%04X, fInAttrInfoOnly = %s, fIOContinueData = %d, fOutDataBuff => { size = %d }", pMultiAttrValueSearchWithData->fType, pMultiAttrValueSearchWithData->fResult, pMultiAttrValueSearchWithData->fInNodeRef, pMultiAttrValueSearchWithData->fInAttrType->fBufferData, pMultiAttrValueSearchWithData->fInPattMatchType, BOOL_STRING(isWithData && pMultiAttrValueSearchWithData->fInAttrInfoOnly), pMultiAttrValueSearchWithData->fIOContinueData, pMultiAttrValueSearchWithData->fOutDataBuff->fBufferSize); patternListCount = dsDataListGetNodeCount(pMultiAttrValueSearchWithData->fInPatterns2MatchList); recordTypeCount = dsDataListGetNodeCount(pMultiAttrValueSearchWithData->fInRecTypeList); recordAttributeCount = isWithData ? dsDataListGetNodeCount(pMultiAttrValueSearchWithData->fInAttrTypeRequestList) : 0; LOG_PARAM("fInPatterns2MatchList.count = %d, fInRecTypeList.count = %d, fInAttrTypeRequestList.count = %d", patternListCount, recordTypeCount, recordAttributeCount); if (pMultiAttrValueSearchWithData->fIOContinueData != 0) { macError = GetQueryFromContextList(pMultiAttrValueSearchWithData->fIOContinueData, &pQuery); if (macError == eDSNoErr) { LOG("Already processed this query, handling IO continuation for result record data"); goto HandleResponse; } } macError = LWIQuery::Create(!isWithData || !pMultiAttrValueSearchWithData->fInAttrInfoOnly, true, // The query results will support fIOContinue (split large results over many calls) pMultiAttrValueSearchWithData->fInNodeRef, Flags, pNetAdapterList, &pQuery); GOTO_CLEANUP_ON_MACERROR(macError); macError = LWIRecTypeLookup::GetVector(pMultiAttrValueSearchWithData->fInRecTypeList, &pQuery->_recTypeSet); GOTO_CLEANUP_ON_MACERROR(macError); if (isWithData) { macError = LWIAttrLookup::GetVector(pMultiAttrValueSearchWithData->fInAttrTypeRequestList, &pQuery->_attributeSet); GOTO_CLEANUP_ON_MACERROR(macError); } else { macError = LWIAttrLookup::GetVector(kDSAttributesAll, &pQuery->_attributeSet); GOTO_CLEANUP_ON_MACERROR(macError); } // We support only exact (including case-insensitive) matches switch (pMultiAttrValueSearchWithData->fInPattMatchType) { case eDSExact: case eDSiExact: // These are fine break; default: LOG("Unsupported pattern match type: 0x%04X", pMultiAttrValueSearchWithData->fInPattMatchType); macError = eDSRecordNotFound; GOTO_CLEANUP_ON_MACERROR(macError); } macError = eDSInvalidRecordType; for (iter = 0; iter < patternListCount; iter++) { macError = dsDataListGetNodeAlloc(pMultiAttrValueSearchWithData->fInNodeRef, pMultiAttrValueSearchWithData->fInPatterns2MatchList, iter+1, &pPatternNode); GOTO_CLEANUP_ON_MACERROR(macError); LOG_PARAM("Searching for pattern (%s)...", pPatternNode->fBufferData); if (pQuery->ShouldQueryUserInformation()) { macError_userQuery = QueryUserInformation(pQuery, pMultiAttrValueSearchWithData->fInAttrType->fBufferData, pPatternNode->fBufferData); if (macError_userQuery != eDSNoErr) { LOG("User query failed [Error: %d]", macError_userQuery); } else { resultCount++; } } if (pQuery->ShouldQueryGroupInformation()) { macError_groupQuery = QueryGroupInformation(pQuery, pMultiAttrValueSearchWithData->fInAttrType->fBufferData, pPatternNode->fBufferData); if (macError_groupQuery != eDSNoErr) { LOG("Group query failed [Error: %d]", macError_groupQuery); } else { resultCount++; } } if (pQuery->ShouldQueryComputerListInformation()) { macError_groupQuery = QueryComputerListInformation(pQuery, pMultiAttrValueSearchWithData->fInAttrType->fBufferData, pPatternNode->fBufferData); if (macError_groupQuery != eDSNoErr) { LOG("Computer List query failed [Error: %d]", macError_groupQuery); } else { resultCount++; } } if (pQuery->ShouldQueryComputerGroupInformation()) { macError_groupQuery = QueryComputerGroupInformation(pQuery, pMultiAttrValueSearchWithData->fInAttrType->fBufferData, pPatternNode->fBufferData); if (macError_groupQuery != eDSNoErr) { LOG("Computer Group query failed [Error: %d]", macError_groupQuery); } else { resultCount++; } } if (pQuery->ShouldQueryComputerInformation()) { macError_groupQuery = QueryComputerInformation(pQuery, pMultiAttrValueSearchWithData->fInAttrType->fBufferData, pPatternNode->fBufferData); if (macError_groupQuery != eDSNoErr) { LOG("Computer query failed [Error: %d]", macError_groupQuery); } else { resultCount++; } } dsDataNodeDeAllocate(NULL, pPatternNode); pPatternNode = NULL; } // If both queries failed, it is a problem if (resultCount == 0 && (macError_userQuery != eDSNoErr) && (macError_groupQuery != eDSNoErr)) { macError = (pQuery->ShouldQueryUserInformation() ? macError_userQuery : macError_groupQuery); GOTO_CLEANUP_ON_MACERROR(macError); } else macError = eDSNoErr; HandleResponse: // Write the results macError = pQuery->WriteResponse(pMultiAttrValueSearchWithData->fOutDataBuff->fBufferData, pMultiAttrValueSearchWithData->fOutDataBuff->fBufferSize, bytesWritten, nRecordsWritten, TotalRecords); GOTO_CLEANUP_ON_MACERROR(macError); if (TotalRecords > nRecordsWritten) { macError = AddQueryToContextList(pQuery, &HandleId); GOTO_CLEANUP_ON_MACERROR(macError); pQuery = NULL; pMultiAttrValueSearchWithData->fIOContinueData = HandleId; } else { pMultiAttrValueSearchWithData->fIOContinueData = 0; } pMultiAttrValueSearchWithData->fOutDataBuff->fBufferLength = bytesWritten; pMultiAttrValueSearchWithData->fInOutMatchRecordCount = nRecordsWritten; if ( bytesWritten > 0 ) { #ifdef SHOW_ALL_DEBUG_SPEW LOG_BUFFER(pMultiAttrValueSearchWithData->fOutDataBuff->fBufferData, bytesWritten); #endif } cleanup: if (pQuery) { delete pQuery; } if (pPatternNode) { dsDataNodeDeAllocate(0, pPatternNode); } LOG_LEAVE("fInOutMatchRecordCount = %d, fIOContinueData = %d --> %d", pMultiAttrValueSearchWithData->fInOutMatchRecordCount, pMultiAttrValueSearchWithData->fIOContinueData, macError); return macError; }
tDirStatus AuthenticateWithNode( tDirReference dirRef, tDataListPtr pathListToAuthNode, const char *username, const char *password ) { tDirStatus err; tDirStatus junk; size_t userNameLen; size_t passwordLen; tDirNodeReference authNodeRef; tDataNodePtr authMethod; tDataBufferPtr authOutBuf; tDataBufferPtr authInBuf; unsigned long length; if (!( (dirRef != NULL) || (pathListToAuthNode != NULL) || (username != NULL) || (password != NULL) ) ) return(eDSBadParam) ; authNodeRef = NULL; authMethod = NULL; authOutBuf = NULL; authInBuf = NULL; userNameLen = STlen(username); passwordLen = STlen(password); /* Open the authentication node. */ err = dsOpenDirNode(dirRef, pathListToAuthNode, &authNodeRef); /* ** Create the input parameters to dsDoDirNodeAuth and then call it. ** The most complex input parameter to dsDoDirNodeAuth is authentication ** data itself, held in authInBuf. This holds the following items: ** ** 4 byte length of user name (includes trailing null) ** user name, including trailing null ** 4 byte length of password (includes trailing null) ** password, including trailing null */ if (err == eDSNoErr) { authMethod = dsDataNodeAllocateString(dirRef, kDSStdAuthNodeNativeClearTextOK); if (authMethod == NULL) err = eDSAllocationFailed; } if (err == eDSNoErr) { /* ** Allocate some arbitrary amount of space for the authOutBuf. This ** buffer comes back containing a credential generated by the ** authentication (apparently a kDS1AttrAuthCredential). However, ** we never need this information, so we basically just create the ** buffer, pass it in to dsDoDirNodeAuth, and then throw it away. ** Unfortunately dsDoDirNodeAuth won't let us pass in NULL. */ authOutBuf = dsDataBufferAllocate(dirRef, kDefaultDSBufferSize); if (authOutBuf == NULL) err = eDSAllocationFailed; } if (err == eDSNoErr) { authInBuf = dsDataBufferAllocate(dirRef, sizeof(length) + userNameLen + 1 + sizeof(length) + passwordLen + 1 ); if (authInBuf == NULL) err = eDSAllocationFailed; } /* Move the data into the buffer. */ if (err == eDSNoErr) { length = userNameLen + 1; /* + 1 to include trailing null */ err = dsDataBufferAppendData(authInBuf, &length, sizeof(length)); } if (err == eDSNoErr) { err = dsDataBufferAppendData(authInBuf, username, userNameLen + 1); } if (err == eDSNoErr) { length = passwordLen + 1; /* + 1 to include trailing null */ err = dsDataBufferAppendData(authInBuf, &length, sizeof(length)); } if (err == eDSNoErr) junk = dsDataBufferAppendData(authInBuf, password, passwordLen + 1); /* Call dsDoDirNodeAuth to do the authentication. */ if (err == eDSNoErr) err = dsDoDirNodeAuthQ(dirRef, authNodeRef, authMethod, true, authInBuf, &authOutBuf, NULL); /* Clean up. */ if (authInBuf != NULL) dsDataBufferDeAllocate(dirRef, authInBuf); if (authOutBuf != NULL) dsDataBufferDeAllocate(dirRef, authOutBuf); if (authMethod != NULL) dsDataNodeDeAllocate(dirRef, authMethod); if (authNodeRef != NULL) dsCloseDirNode(authNodeRef); return err; }
long LWIRecordListQuery::Run(IN OUT sGetRecordList* pGetRecordList, LWE_DS_FLAGS Flags, PNETADAPTERINFO pNetAdapterList) { long macError = eDSNoErr; long macError_userQuery = eDSNoErr; long macError_groupQuery = eDSNoErr; long macError_computerQuery = eDSNoErr; long macError_computergroupQuery = eDSNoErr; long macError_computerlistQuery = eDSNoErr; tDataNodePtr pDataNode = NULL; const char* szNames = NULL; unsigned long bytesWritten = 0; unsigned long nRecordsWritten = 0; unsigned long TotalRecords = 0; LWIQuery* pQuery = NULL; int iter = 0; int resultCount = 0; int recordNameCount; int recordTypeCount; int recordAttributeCount; tContextData HandleId = 0; LOG_ENTER("LWIRecordListQuery::Run - fType = %d, fResult = %d, fInNodeRef = %d, " "fInDataBuf = @%p { len = %d, size = %d }, fInPatternMatch = 0x%04X, " "fIOContinueData = %d", pGetRecordList->fType, pGetRecordList->fResult, pGetRecordList->fInNodeRef, pGetRecordList->fInDataBuff, pGetRecordList->fInDataBuff->fBufferLength, pGetRecordList->fInDataBuff->fBufferSize, pGetRecordList->fInPatternMatch, pGetRecordList->fIOContinueData); recordNameCount = dsDataListGetNodeCount(pGetRecordList->fInRecNameList); recordTypeCount = dsDataListGetNodeCount(pGetRecordList->fInRecTypeList); recordAttributeCount = dsDataListGetNodeCount(pGetRecordList->fInAttribTypeList); LOG_PARAM("fInRecNameList.count = %d, fInRecTypeList.count = %d, " "fInAttribTypeList.count = %d", recordNameCount, recordTypeCount, recordAttributeCount); /* Initialize the out parameters in case we return with error */ pGetRecordList->fInDataBuff->fBufferLength = 0; pGetRecordList->fOutRecEntryCount = 0; if ((UInt32)pGetRecordList->fIOContinueData != 0 && (UInt32)pGetRecordList->fIOContinueData != SPECIAL_DS_CONTINUE_HANDLE) { macError = GetQueryFromContextList(pGetRecordList->fIOContinueData, &pQuery); if (macError == eDSNoErr) { LOG("Already processed this query, handling IO continuation for result record data"); goto HandleResponse; } } macError = LWIQuery::Create(!pGetRecordList->fInAttribInfoOnly, true, // The query results will support fIOContinue (split large results over many calls) pGetRecordList->fInNodeRef, Flags, pNetAdapterList, &pQuery); GOTO_CLEANUP_ON_MACERROR(macError); macError = LWIRecTypeLookup::GetVector(pGetRecordList->fInRecTypeList, &pQuery->_recTypeSet); GOTO_CLEANUP_ON_MACERROR(macError); macError = LWIAttrLookup::GetVector(pGetRecordList->fInAttribTypeList, &pQuery->_attributeSet); GOTO_CLEANUP_ON_MACERROR(macError); for (iter = 0; iter < recordNameCount; iter++) { macError = dsDataListGetNodeAlloc( pGetRecordList->fInNodeRef, pGetRecordList->fInRecNameList, iter+1, &pDataNode ); GOTO_CLEANUP_ON_MACERROR( macError ); szNames = pDataNode->fBufferData; macError = eDSInvalidRecordType; if (pQuery->ShouldQueryUserInformation()) { macError_userQuery = pQuery->QueryUserInformationByName(szNames); if (macError_userQuery != eDSNoErr) { LOG("User query failed [Error: %d]", macError_userQuery); } else { resultCount++; } } if (pQuery->ShouldQueryGroupInformation()) { macError_groupQuery = pQuery->QueryGroupInformationByName(szNames); if (macError_groupQuery != eDSNoErr) { LOG("Group query failed [Error: %d]", macError_groupQuery); } else { resultCount++; } } if (pQuery->ShouldQueryComputerInformation()) { macError_computerQuery = pQuery->QueryComputerInformationByName(szNames); if (macError_computerQuery != eDSNoErr) { LOG("Computer query failed [Error: %d]", macError_computerQuery); } else { resultCount++; } } if (pQuery->ShouldQueryComputerGroupInformation()) { macError_computergroupQuery = pQuery->QueryComputerGroupInformationByName(szNames); if (macError_computergroupQuery != eDSNoErr) { LOG("Computer group query failed [Error: %d]", macError_computergroupQuery); } else { resultCount++; } } if (pQuery->ShouldQueryComputerListInformation()) { macError_computerlistQuery = pQuery->QueryComputerListInformationByName(szNames); if (macError_computerlistQuery != eDSNoErr) { LOG("Computer list query failed [Error: %d]", macError_computerlistQuery); } else { resultCount++; } } dsDataNodeDeAllocate(NULL, pDataNode); pDataNode = NULL; } // If both queries failed, it is a problem if (resultCount == 0 && (macError_userQuery != eDSNoErr) && (macError_groupQuery != eDSNoErr) && (macError_computerQuery != eDSNoErr) && (macError_computergroupQuery != eDSNoErr) && (macError_computerlistQuery != eDSNoErr)) { macError = (pQuery->ShouldQueryUserInformation() ? macError_userQuery : macError_groupQuery); GOTO_CLEANUP_ON_MACERROR(macError); } else macError = eDSNoErr; HandleResponse: // Write the results macError = pQuery->WriteResponse(pGetRecordList->fInDataBuff->fBufferData, pGetRecordList->fInDataBuff->fBufferSize, bytesWritten, nRecordsWritten, TotalRecords); GOTO_CLEANUP_ON_MACERROR(macError); if (TotalRecords > nRecordsWritten) { macError = AddQueryToContextList(pQuery, &HandleId); GOTO_CLEANUP_ON_MACERROR(macError); pQuery = NULL; pGetRecordList->fIOContinueData = HandleId; } else { pGetRecordList->fIOContinueData = 0; } pGetRecordList->fInDataBuff->fBufferLength = bytesWritten; pGetRecordList->fOutRecEntryCount = nRecordsWritten; if ( bytesWritten > 0 ) { #ifdef SHOW_ALL_DEBUG_SPEW LOG_BUFFER(pGetRecordList->fInDataBuff->fBufferData, bytesWritten); #endif } cleanup: if (pDataNode) { dsDataNodeDeAllocate(0, pDataNode); } if (pQuery) { delete pQuery; } if (macError == eDSBufferTooSmall) { pGetRecordList->fIOContinueData = (tContextData)SPECIAL_DS_CONTINUE_HANDLE; } LOG_LEAVE("fOutRecEntryCount = %d, fInDataBuff = { length = %d, size = %d }, fIOContinueData = %d, macError = %d", pGetRecordList->fOutRecEntryCount, pGetRecordList->fInDataBuff->fBufferLength, pGetRecordList->fInDataBuff->fBufferSize, pGetRecordList->fIOContinueData, macError); return macError; }