static DWORD KtLdapBind( LDAP **ppLd, PCSTR pszDc ) { const int version = LDAP_VERSION3; DWORD dwError = ERROR_SUCCESS; int lderr = 0; PSTR pszUrl = NULL; LDAP *pLd = NULL; dwError = LwAllocateStringPrintf(&pszUrl, "ldap://%s", pszDc); BAIL_ON_LSA_ERROR(dwError); lderr = ldap_initialize(&pLd, pszUrl); BAIL_ON_LDAP_ERROR(lderr); lderr = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &version); BAIL_ON_LDAP_ERROR(lderr); lderr = ldap_set_option(pLd, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); BAIL_ON_LDAP_ERROR(lderr); dwError = LwLdapBindDirectorySasl(pLd, pszDc, FALSE); BAIL_ON_LSA_ERROR(dwError); *ppLd = pLd; cleanup: LW_SAFE_FREE_MEMORY(pszUrl); if (dwError == ERROR_SUCCESS && lderr != LDAP_SUCCESS) { dwError = LwMapLdapErrorToLwError(lderr); } return dwError; error: if (pLd) { ldap_memfree(pLd); } *ppLd = NULL; goto cleanup; }
DWORD IDMLdapSaslBind( LDAP* pLd /* IN */ ) { DWORD dwError = 0; DWORD dwCleanupError = 0; BOOLEAN bLocked = FALSE; PSTR pszCachePath = NULL; if (!pLd) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_ERROR(dwError); } switch (IDMKrbGetState(pgIdmKrbContext)) { case IDM_KRB_CONTEXT_STATE_INITIAL: dwError = IDMKrbDetermineJoinState(pgIdmKrbContext); BAIL_ON_ERROR(dwError); case IDM_KRB_CONTEXT_STATE_JOINED: dwError = IDMKrbRenewCredentials(pgIdmKrbContext); if (dwError) { // Refreshing credentials might fail if the system left // the domain or there were issues reaching the domain // controller. IDMKrbSetState(pgIdmKrbContext, IDM_KRB_CONTEXT_STATE_INITIAL); } BAIL_ON_ERROR(dwError); IDM_RWMUTEX_LOCK_SHARED( &pgIdmKrbContext->mutex_rw, bLocked, dwError); BAIL_ON_ERROR(dwError); dwError = LwKrb5SetThreadDefaultCachePath( pgIdmKrbContext->pszCachePath, &pszCachePath); BAIL_ON_ERROR(dwError); dwError = LwMapLdapErrorToLwError( ldap_sasl_interactive_bind_s( pLd, NULL, "GSSAPI", NULL, NULL, LDAP_SASL_QUIET, &IDMSASLInteraction, NULL)); BAIL_ON_ERROR(dwError); break; default: dwError = ERROR_INVALID_STATE; BAIL_ON_ERROR(dwError); break; } cleanup: if (pszCachePath) { LwKrb5SetThreadDefaultCachePath(pszCachePath, NULL); LwFreeMemory(pszCachePath); } IDM_RWMUTEX_UNLOCK(&pgIdmKrbContext->mutex_rw, bLocked, dwCleanupError); if(!dwError) { dwError = dwCleanupError; } return dwError; error: goto cleanup; }
static DWORD LWNetSrvPingCLdapBegin( IN PLWNET_CLDAP_CONNECTION_CONTEXT pContext, IN PDNS_SERVER_INFO pServerInfo, IN PCSTR pszDnsDomainName, IN DWORD dwTimeout ) { DWORD dwError = 0; PSTR pszQuery = NULL; PSTR szAttributeList[] = { NETLOGON_LDAP_ATTRIBUTE_NAME, NULL }; struct timeval timeout = {0}; LDAP *ld = NULL; pContext->hDirectory = NULL; pContext->pServerInfo = pServerInfo; dwError = LwAllocateStringPrintf(&pszQuery, "(&(DnsDomain=%s)(NtVer=\\06\\00\\00\\80))", pszDnsDomainName); BAIL_ON_LWNET_ERROR(dwError); dwError = LwCLdapOpenDirectory(pServerInfo->pszAddress, &pContext->hDirectory); BAIL_ON_LWNET_ERROR(dwError); dwError = LwLdapBindDirectoryAnonymous(pContext->hDirectory); BAIL_ON_LWNET_ERROR(dwError); timeout.tv_sec = 0; timeout.tv_usec = dwTimeout; dwError = LWNetGetSystemTimeInMs(&pContext->StartTime); BAIL_ON_LWNET_ERROR(dwError); ld = LwLdapGetSession(pContext->hDirectory); dwError = ldap_search_ext( ld, "", LDAP_SCOPE_BASE, pszQuery, szAttributeList, 0, NULL, NULL, &timeout, 0, &pContext->msgid); dwError = LwMapLdapErrorToLwError(dwError); BAIL_ON_LWNET_ERROR(dwError); dwError = ldap_get_option( ld, LDAP_OPT_DESC, &pContext->fd); dwError = LwMapLdapErrorToLwError(dwError); BAIL_ON_LWNET_ERROR(dwError); error: if (dwError) { if (pContext->hDirectory) { LWNetSrvPingCLdapEnd(pContext); } } LWNET_SAFE_FREE_STRING(pszQuery); return dwError; }
static DWORD LWNetSrvPingCLdapProcess( IN PLWNET_CLDAP_CONNECTION_CONTEXT pContext, IN DWORD dwDsFlags, IN LWNET_UNIX_MS_TIME_T StopTime, OUT PLWNET_DC_INFO* ppDcInfo, OUT PBOOLEAN pbFailedFindWritable ) { DWORD dwError = 0; DWORD dwResultType = 0; LDAPMessage* pMessage = NULL; PBYTE pNetlogonAttributeValue = NULL; DWORD dwNetlogonAttributeSize = 0; PLWNET_DC_INFO pDcInfo = NULL; BOOLEAN bFailedFindWritable = FALSE; struct timeval timeout = {0}; LDAP *ld = NULL; ld = LwLdapGetSession(pContext->hDirectory); dwResultType = ldap_result( ld, pContext->msgid, 0, &timeout, &pMessage); if (dwResultType == 0) { // timed out goto error; } else if (dwResultType == -1) { // -1 = problem dwError = LDAP_NO_SUCH_OBJECT; LWNET_LOG_VERBOSE("Caught LDAP_NO_SUCH_OBJECT Error on ldap search"); } else { // returns result type if (dwResultType != LDAP_RES_SEARCH_ENTRY) { dwError = LDAP_NO_SUCH_OBJECT; LWNET_LOG_DEBUG("Caught incorrect result type on ldap search: %d", dwError); } } dwError = LwMapLdapErrorToLwError(dwError); BAIL_ON_LWNET_ERROR(dwError); dwError = LwLdapGetBytes( pContext->hDirectory, pMessage, NETLOGON_LDAP_ATTRIBUTE_NAME, &pNetlogonAttributeValue, &dwNetlogonAttributeSize); BAIL_ON_LWNET_ERROR(dwError); dwError = LWNetBuildDCInfo(pNetlogonAttributeValue, dwNetlogonAttributeSize, &pDcInfo); BAIL_ON_LWNET_ERROR(dwError); dwError = LWNetAllocateString(pContext->pServerInfo->pszAddress, &pDcInfo->pszDomainControllerAddress); BAIL_ON_LWNET_ERROR(dwError); pDcInfo->dwPingTime = (DWORD)(StopTime - pContext->StartTime); if (StopTime < pContext->StartTime) { LWNET_LOG_ERROR("Stop time is earlier than start time"); } if (!LWNetSrvIsMatchingDcInfo(pDcInfo, dwDsFlags)) { dwError = LW_ERROR_NO_SUCH_OBJECT; if (LWNetSrvIsMatchingDcInfo(pDcInfo, dwDsFlags & ~DS_WRITABLE_REQUIRED)) { // We found something, but it failed only because it did // not satisfy writability. bFailedFindWritable = TRUE; } } error: if (pMessage) { ldap_msgfree(pMessage); } LWNET_SAFE_FREE_MEMORY(pNetlogonAttributeValue); if (dwError) { LWNET_SAFE_FREE_DC_INFO(pDcInfo); LWNetSrvPingCLdapEnd(pContext); } *ppDcInfo = pDcInfo; *pbFailedFindWritable = bFailedFindWritable; return dwError; }
static DWORD KtLdapQuery( LDAP *pLd, PCSTR pszBaseDn, DWORD dwScope, PCSTR pszFilter, PCSTR pszAttrName, PSTR *ppszAttrVal ) { DWORD dwError = ERROR_SUCCESS; int lderr = LDAP_SUCCESS; char *attrs[2] = { NULL, // This gets filled in later NULL // This null terminates the list of attributes }; LDAPMessage *res = NULL; LDAPMessage *entry = NULL; char *attr = NULL; struct berval **ppBv = NULL; BerElement *ptr = NULL; struct timeval timeout = { .tv_sec = 10, .tv_usec = 0 }; PSTR pszAttrVal = NULL; dwError = LwAllocateString(pszAttrName, &attrs[0]); BAIL_ON_LSA_ERROR(dwError); lderr = ldap_search_ext_s(pLd, pszBaseDn, dwScope, pszFilter, attrs, 0, NULL, NULL, &timeout, 0, &res); BAIL_ON_LDAP_ERROR(lderr); if (ldap_count_entries(pLd, res)) { entry = ldap_first_entry(pLd, res); if (entry == NULL) { dwError = ERROR_DS_GENERIC_ERROR; BAIL_ON_LSA_ERROR(dwError); } attr = ldap_first_attribute(pLd, entry, &ptr); if (attr) { ppBv = ldap_get_values_len(pLd, entry, attr); if (ldap_count_values_len(ppBv)) { dwError = LwAllocateMemory(ppBv[0]->bv_len + 1, OUT_PPVOID(&pszAttrVal)); BAIL_ON_LSA_ERROR(dwError); memcpy(pszAttrVal, ppBv[0]->bv_val, ppBv[0]->bv_len); } ldap_memfree(attr); } ldap_msgfree(res); } *ppszAttrVal = pszAttrVal; cleanup: if (ppBv) { ldap_value_free_len(ppBv); } if (ptr != NULL) { ber_free( ptr, 0 ); } LW_SAFE_FREE_STRING(attrs[0]); if (dwError == ERROR_SUCCESS && lderr != LDAP_SUCCESS) { dwError = LwMapLdapErrorToLwError(lderr); } return dwError; error: *ppszAttrVal = NULL; goto cleanup; } static DWORD KtLdapUnbind( LDAP *pLd ) { DWORD dwError = ERROR_SUCCESS; int lderr = LDAP_SUCCESS; lderr = ldap_unbind_ext_s(pLd, NULL, NULL); BAIL_ON_LDAP_ERROR(lderr); cleanup: if (lderr) { dwError = LwMapLdapErrorToLwError(lderr); } return dwError; error: goto cleanup; }