DWORD VmDirSASLGSSAPIBind( LDAP** ppLd, PCSTR pszURI ) { DWORD dwError = 0; int retVal = 0; LDAP* pLd = NULL; const int ldapVer = LDAP_VERSION3; if ( ppLd == NULL || pszURI == NULL ) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } retVal = ldap_initialize( &pLd, pszURI); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); retVal = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); retVal = ldap_sasl_interactive_bind_s( pLd, NULL, "GSSAPI", NULL, NULL, LDAP_SASL_QUIET, _VmDirSASLGSSAPIInteraction, NULL); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); *ppLd = pLd; cleanup: return dwError; ldaperror: VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLGSSBind failed. (%d)(%s)", retVal, ldap_err2string(retVal) ); dwError = VmDirMapLdapError(retVal); error: if (retVal == 0) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLGSSBind failed. (%u)", dwError); } if ( pLd ) { ldap_unbind_ext_s( pLd, NULL, NULL); } goto cleanup; }
int ParseAndFreeSyncStateControl( LDAPControl ***pCtrls, int *piEntryState ) { int retVal = LDAP_SUCCESS; int entryState = -1; if (pCtrls == NULL) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ParseAndFreeSyncStateControl: pCtrls is NULL" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_SIMPLE_LDAP_ERROR(retVal); } if ((*pCtrls)[0] == NULL) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ParseAndFreeSyncStateControl: (*pCtrls)[0] is NULL" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_SIMPLE_LDAP_ERROR(retVal); } if (VmDirStringCompareA((*pCtrls)[0]->ldctl_oid, LDAP_CONTROL_SYNC_STATE, TRUE) != 0) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ParseAndFreeSyncStateControl: (*pCtrls)[0]->ldctrl_oid is not expected: %s", VDIR_SAFE_STRING((*pCtrls)[0]->ldctl_oid)); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_SIMPLE_LDAP_ERROR(retVal); } retVal = ParseSyncStateControlVal(&(*pCtrls)[0]->ldctl_value, &entryState); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); ldap_controls_free(*pCtrls); *pCtrls = NULL; *piEntryState = entryState; cleanup: return retVal; ldaperror: goto cleanup; }
int VmDirPerformBind( PVDIR_OPERATION pOperation ) { BindReq * pBindReq = &(pOperation->request.bindReq); int retVal = LDAP_SUCCESS; ber_len_t berLen = 0; ber_tag_t berTag = 0; BOOLEAN bResultAlreadySent = FALSE; memset( pBindReq, 0, sizeof( BindReq )); if (ber_scanf( pOperation->ber, "{imt", &pOperation->protocol, &(pOperation->reqDn.lberbv), &pBindReq->method ) == LBER_ERROR ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "PerformBind: ber_scanf failed" ); BAIL_ON_STATIC_LDAP_ERROR( retVal, LDAP_PROTOCOL_ERROR, (pOperation->ldapResult.pszErrMsg), "Decoding error while parsing protocol version, bind DN, bind method."); } VMDIR_LOG_VERBOSE( LDAP_DEBUG_ARGS, "Bind Request (%s): Protocol version: %d, Bind DN: \"%s\", Method: %ld", pOperation->conn->szClientIP, pOperation->protocol, pOperation->reqDn.lberbv.bv_val, pBindReq->method ); if (pOperation->protocol != LDAP_VERSION3) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "PerformBind: Non-ldap-v3 version." ); BAIL_ON_STATIC_LDAP_ERROR( retVal, LDAP_PROTOCOL_ERROR, (pOperation->ldapResult.pszErrMsg), "Currently, only LDAP V3 is supported."); } switch (pBindReq->method) { case LDAP_AUTH_SIMPLE: if ( ber_scanf( pOperation->ber, "m}", &(pBindReq->cred.lberbv) ) == LBER_ERROR ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "PerformBind: ber_scanf failed" ); BAIL_ON_STATIC_LDAP_ERROR( retVal, LDAP_PROTOCOL_ERROR, (pOperation->ldapResult.pszErrMsg), "Decoding error while parsing simple credentials."); } break; case LDAP_AUTH_SASL: if ( ber_scanf( pOperation->ber, "{m" /*}*/, &(pBindReq->bvMechanism.lberbv) ) == LBER_ERROR) { BAIL_ON_STATIC_LDAP_ERROR( retVal, LDAP_PROTOCOL_ERROR, (pOperation->ldapResult.pszErrMsg), "Decoding error while parsing sasl mechanism."); } berTag = ber_peek_tag( pOperation->ber, &berLen ); if ( berTag == LDAP_TAG_LDAPCRED ) { if ( ber_scanf( pOperation->ber, "m", &(pBindReq->cred.lberbv)) == LBER_ERROR ) { BAIL_ON_STATIC_LDAP_ERROR( retVal, LDAP_PROTOCOL_ERROR, (pOperation->ldapResult.pszErrMsg), "Decoding error while parsing sasl creds."); } } if ( ber_scanf( pOperation->ber, /*{{*/ "}}" ) == LBER_ERROR ) { BAIL_ON_STATIC_LDAP_ERROR( retVal, LDAP_PROTOCOL_ERROR, (pOperation->ldapResult.pszErrMsg), "Decoding error."); } break; default: BAIL_ON_STATIC_LDAP_ERROR( retVal, LDAP_UNWILLING_TO_PERFORM, (pOperation->ldapResult.pszErrMsg), "bind method not supported."); } retVal = VmDirMLBind( pOperation ); bResultAlreadySent = TRUE; if (retVal && retVal != LDAP_SASL_BIND_IN_PROGRESS) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "Bind Request Failed (%s) error %u: Protocol version: %d, Bind DN: \"%s\", Method: %ld", pOperation->conn->szClientIP, retVal, pOperation->protocol, VDIR_SAFE_STRING(pOperation->reqDn.lberbv.bv_val), pBindReq->method ); } BAIL_ON_SIMPLE_LDAP_ERROR(retVal); cleanup: return retVal; ldaperror: pOperation->ldapResult.errCode = retVal; if (retVal != LDAP_NOTICE_OF_DISCONNECT && bResultAlreadySent == FALSE) { VmDirSendLdapResult( pOperation ); } goto cleanup; }
int VmDirCreateSyncRequestControl( PCSTR pszInvocationId, USN lastLocalUsnProcessed, PCSTR pszUtdVector, LDAPControl * syncReqCtrl ) { int retVal = LDAP_SUCCESS; BerElement * ber = NULL; PSTR pszLastLocalUsnProcessed = NULL; if (syncReqCtrl == NULL) { retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_SIMPLE_LDAP_ERROR(retVal); } if ((ber = ber_alloc()) == NULL) { retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_SIMPLE_LDAP_ERROR(retVal); } if (VmDirAllocateStringPrintf(&pszLastLocalUsnProcessed, "%lld", lastLocalUsnProcessed)) { retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_SIMPLE_LDAP_ERROR(retVal); } if ( ber_printf( ber, "{i{sss}}", LDAP_SYNC_REFRESH_ONLY, pszInvocationId, pszLastLocalUsnProcessed, pszUtdVector ) == -1) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "VmDirCreateSyncRequestControl: ber_printf failed." ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_SIMPLE_LDAP_ERROR( retVal ); } memset( syncReqCtrl, 0, sizeof( LDAPControl )); syncReqCtrl->ldctl_oid = LDAP_CONTROL_SYNC; syncReqCtrl->ldctl_iscritical = '1'; if (ber_flatten2(ber, &syncReqCtrl->ldctl_value, 1)) { retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_SIMPLE_LDAP_ERROR(retVal); } cleanup: VMDIR_SAFE_FREE_STRINGA(pszLastLocalUsnProcessed); if (ber) { ber_free(ber, 1); } return retVal; ldaperror: ber_bvfree(&syncReqCtrl->ldctl_value); goto cleanup; }
DWORD VmDirAnonymousLDAPBindWithTimeout( LDAP** ppLd, PCSTR pszLdapURI, int timeout ) { DWORD dwError = 0; int retVal = 0; const int ldapVer = LDAP_VERSION3; BerValue ldapBindPwd = {0}; LDAP* pLocalLd = NULL; struct timeval nettimeout = {0}; if (ppLd == NULL || pszLdapURI == NULL) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } retVal = ldap_initialize( &pLocalLd, pszLdapURI); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); retVal = ldap_set_option( pLocalLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); if (timeout > 0) { nettimeout.tv_sec = timeout; // timeout connect retVal = ldap_set_option(pLocalLd, LDAP_OPT_NETWORK_TIMEOUT, (void *)&nettimeout); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); } ldapBindPwd.bv_val = NULL; ldapBindPwd.bv_len = 0; retVal = ldap_sasl_bind_s( pLocalLd, "", LDAP_SASL_SIMPLE, &ldapBindPwd, // no credentials NULL, NULL, NULL); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); *ppLd = pLocalLd; cleanup: return dwError; ldaperror: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "VmDirAnonymousLDAPBind to (%s) failed. (%d)(%s)", VDIR_SAFE_STRING(pszLdapURI), retVal, ldap_err2string(retVal) ); dwError = VmDirMapLdapError(retVal); error: if (retVal == 0) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "VmDirAnonymousLDAPBind to (%s) failed. (%u)", VDIR_SAFE_STRING(pszLdapURI), dwError); } if (pLocalLd) { ldap_unbind_ext_s( pLocalLd, NULL, NULL); } goto cleanup; }
/* * Bind to a LDAP server via SSL port. * Require server certificate verification. * * In 5.5. mix mode, replication goes through ldaps port. */ DWORD VmDirSSLBind( LDAP** ppLd, PCSTR pszURI, PCSTR pszDN, PCSTR pszPassword ) { DWORD dwError = 0; int retVal = 0; LDAP* pLd = NULL; BerValue ldapBindPwd = {0}; const int ldapVer = LDAP_VERSION3; int iTLSDEMAND = LDAP_OPT_X_TLS_DEMAND; int iTLSMin = LDAP_OPT_X_TLS_PROTOCOL_TLS1_0; PSTR pszTrustCertFile = NULL; SSL_CTX* pSslCtx = NULL; if ( ppLd == NULL || pszURI == NULL ) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } // only allow ldaps traffic over SSL port if ( VmDirStringNCompareA( pszURI, VMDIR_LDAPS_PROTOCOL, 5, FALSE) != 0 ) { dwError = VMDIR_ERROR_ACCESS_DENIED; BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirPrepareOpensslClientCtx( &pSslCtx, &pszTrustCertFile, pszURI ); BAIL_ON_VMDIR_ERROR(dwError); retVal = ldap_set_option( NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &iTLSDEMAND); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); retVal = ldap_set_option(NULL, LDAP_OPT_X_TLS_PROTOCOL_MIN, &iTLSMin); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); retVal = ldap_initialize(&pLd, pszURI); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); retVal = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); retVal = ldap_set_option( pLd, LDAP_OPT_X_TLS_CTX, pSslCtx); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); ldapBindPwd.bv_val = 0; ldapBindPwd.bv_len = 0; if (pszPassword) { ldapBindPwd.bv_val = (PSTR) pszPassword; ldapBindPwd.bv_len = (ULONG) VmDirStringLenA(pszPassword); } retVal = ldap_sasl_bind_s( pLd, pszDN, LDAP_SASL_SIMPLE, &ldapBindPwd, // ldaps with credentials NULL, NULL, NULL); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); *ppLd = pLd; cleanup: if (pSslCtx) { SSL_CTX_free(pSslCtx); } VMDIR_SAFE_FREE_MEMORY(pszTrustCertFile); return dwError; ldaperror: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "VmDirSSLBind failed for %s %s. (%d)(%s)", pszURI, pszDN, retVal, ldap_err2string(retVal)); dwError = VmDirMapLdapError(retVal); error: if (retVal == 0) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSSLBind failed. (%u)", dwError); } if ( pLd ) { ldap_unbind_ext_s( pLd, NULL, NULL); } goto cleanup; }
DWORD VmDirSASLSRPBindExt1( LDAP** ppLd, PCSTR pszURI, PCSTR pszUPN, PCSTR pszPass, int iTimeout ) { DWORD dwError = 0; int retVal = 0; PSTR pszLowerCaseUPN = NULL; LDAP* pLd = NULL; const int ldapVer = LDAP_VERSION3; const int iSaslNoCanon = 1; VMDIR_SASL_INTERACTIVE_DEFAULT srpDefault = {0}; int iCnt = 0; struct timeval optTimeout={0}; optTimeout.tv_usec = 0; optTimeout.tv_sec = iTimeout; if ( ppLd == NULL || pszURI == NULL || pszUPN == NULL || pszPass == NULL ) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirAllocASCIIUpperToLower( pszUPN, &pszLowerCaseUPN ); BAIL_ON_VMDIR_ERROR(dwError); srpDefault.pszAuthName = pszLowerCaseUPN; srpDefault.pszPass = pszPass; for (iCnt=0; iCnt<2; iCnt++) { retVal = ldap_initialize( &pLd, pszURI); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); retVal = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); // turn off SASL hostname canonicalization for SRP mech retVal = ldap_set_option(pLd, LDAP_OPT_X_SASL_NOCANON, &iSaslNoCanon); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); if (iTimeout > 0) { // timeout connect retVal = ldap_set_option(pLd, LDAP_OPT_NETWORK_TIMEOUT, (void *)&optTimeout); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); } retVal = ldap_sasl_interactive_bind_s( pLd, NULL, "SRP", NULL, NULL, LDAP_SASL_QUIET, _VmDirSASLSRPInteraction, &srpDefault); if (retVal == LDAP_SERVER_DOWN || retVal == LDAP_TIMEOUT) { VmDirSleep(50); // pause 50 ms if ( pLd ) { ldap_unbind_ext_s(pLd, NULL, NULL); pLd = NULL; } continue; // if transient network error, retry once. } else { break; } } BAIL_ON_SIMPLE_LDAP_ERROR(retVal); // bail ldap_sasl_interactive_bind_s failure. *ppLd = pLd; cleanup: VMDIR_SAFE_FREE_MEMORY(pszLowerCaseUPN); return dwError; ldaperror: VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLSRPBind failed. (%d)(%s)", retVal, ldap_err2string(retVal) ); dwError = VmDirMapLdapError(retVal); error: if (retVal == 0) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLSRPBind failed. (%u)", dwError); } if ( pLd ) { ldap_unbind_ext_s( pLd, NULL, NULL); } goto cleanup; }
DWORD VmDirSASLSRPBind( LDAP** ppLd, PCSTR pszURI, PCSTR pszUPN, PCSTR pszPass ) { DWORD dwError = 0; int retVal = 0; PSTR pszLowerCaseUPN = NULL; LDAP* pLd = NULL; const int ldapVer = LDAP_VERSION3; VMDIR_SASL_INTERACTIVE_DEFAULT srpDefault = {0}; int iCnt = 0; if ( ppLd == NULL || pszURI == NULL || pszUPN == NULL || pszPass == NULL ) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirAllocASCIIUpperToLower( pszUPN, &pszLowerCaseUPN ); BAIL_ON_VMDIR_ERROR(dwError); srpDefault.pszAuthName = pszLowerCaseUPN; srpDefault.pszPass = pszPass; for (iCnt=0; iCnt<2; iCnt++) { retVal = ldap_initialize( &pLd, pszURI); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); retVal = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer); BAIL_ON_SIMPLE_LDAP_ERROR(retVal); retVal = ldap_sasl_interactive_bind_s( pLd, NULL, "SRP", NULL, NULL, LDAP_SASL_QUIET, _VmDirSASLSRPInteraction, &srpDefault); if (retVal == LDAP_SERVER_DOWN) { VmDirSleep(50); // pause 50 ms if ( pLd ) { ldap_unbind_ext_s(pLd, NULL, NULL); pLd = NULL; } continue; // if transient network error, retry once. } else { break; } } BAIL_ON_SIMPLE_LDAP_ERROR(retVal); // bail ldap_sasl_interactive_bind_s failure. *ppLd = pLd; cleanup: VMDIR_SAFE_FREE_MEMORY(pszLowerCaseUPN); return dwError; ldaperror: VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLSRPBind failed. (%d)(%s)", retVal, ldap_err2string(retVal) ); dwError = VmDirMapLdapError(retVal); error: if (retVal == 0) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLSRPBind failed. (%u)", dwError); } if ( pLd ) { ldap_unbind_ext_s( pLd, NULL, NULL); } goto cleanup; }