/* 4.2.2. Bind Response The Bind response is defined as follows. BindResponse ::= [APPLICATION 1] SEQUENCE { COMPONENTS OF LDAPResult, serverSaslCreds [7] OCTET STRING OPTIONAL } */ VOID VmDirSendSASLBindResponse( PVDIR_OPERATION pOperation ) { DWORD dwError = 0; BerElementBuffer berbuf; BerElement * ber = (BerElement *) &berbuf; PVDIR_LDAP_RESULT pResult = &(pOperation->ldapResult); ber_tag_t respType = GetResultTag(pOperation->reqCode); (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer )); ber_init2( ber, NULL, LBER_USE_DER ); VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, "VmDirSendLdapResponse: code (%d), Error (%d)(%s)", respType, pResult->errCode, VDIR_SAFE_STRING(pResult->pszErrMsg)); dwError = ber_printf( ber, "{it{ess" /*"}}"*/, pOperation->msgId, // message sequence id GetResultTag(pOperation->reqCode), // ldap response type pResult->errCode, // ldap return code e.g. LDAP_SASL_CONNTINUE pResult->matchedDn.lberbv.bv_len > 0 ? pResult->matchedDn.lberbv.bv_val : "", VDIR_SAFE_STRING(pResult->pszErrMsg)); // error text detail BAIL_ON_LBER_ERROR(dwError); // Send back TAG and SASL reply blob // NOTE, not exactly sure if we ever need to send Tag but WITHOUT blob reply if blob is empty. // but this should NOT happen in GSSAPI scenario. if ( pResult->replyInfo.type == REP_SASL && pResult->replyInfo.replyData.bvSaslReply.lberbv.bv_len > 0 ) { dwError = ber_printf( ber, "tO", LDAP_TAG_SASL_RES_CREDS, &pResult->replyInfo.replyData.bvSaslReply.lberbv ); BAIL_ON_LBER_ERROR(dwError); } dwError = ber_printf( ber, "N}N}" ); BAIL_ON_LBER_ERROR(dwError); dwError = WriteBerOnSocket( pOperation->conn, ber ); BAIL_ON_VMDIR_ERROR(dwError); cleanup: ber_free_buf( ber ); return; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "lber error (%d)", dwError); goto cleanup; }
void VmDirSendLdapReferralResult( VDIR_OPERATION * op, PCSTR pszRefSuffix, PBOOLEAN pbRefSent ) { DWORD dwError = 0; BerElementBuffer berbuf; BerElement * ber = (BerElement *) &berbuf; ber_int_t msgId = 0; PCSTR pszSocketInfo = NULL; PSTR pszLeader = NULL; PSTR pszRef = NULL; PVDIR_BERVALUE pBerv = NULL; BOOLEAN bIsLdaps = FALSE; *pbRefSent = FALSE; (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer )); msgId = op->msgId; ber_init2( ber, NULL, LBER_USE_DER ); if (op->conn) { pszSocketInfo = op->conn->szClientIP; } dwError = VmDirRaftGetLeader(&pszLeader); BAIL_ON_VMDIR_ERROR(dwError); if (pszLeader == NULL) { //server self is a raft leader or leader cannot determined (e.g. in voting stage). goto done; } if (op->conn->dwServerPort == VmDirGetLdapsPort()) { bIsLdaps = TRUE; } dwError = VmDirAllocateStringPrintf(&pszRef, "%s://%s/%s", bIsLdaps ? "ldaps":"ldap", pszLeader, pszRefSuffix ); BAIL_ON_VMDIR_ERROR(dwError); op->ldapResult.errCode = 0; if ((op->reqCode == LDAP_REQ_SEARCH && gVmdirGlobals.dwEnableRaftReferral & VMDIR_RAFT_SEARCH_REFERRAL_ERROR_CODE) || ((op->reqCode == LDAP_REQ_ADD || op->reqCode == LDAP_REQ_DELETE || op->reqCode == LDAP_REQ_MODIFY || op->reqCode == LDAP_REQ_MODDN) && gVmdirGlobals.dwEnableRaftReferral & VMDIR_RAFT_ENABLE_UPDATE_ERROR_CODE)) { op->ldapResult.errCode = LDAP_REFERRAL; } dwError = VmDirAllocateMemory( sizeof(VDIR_BERVALUE) * 2, (PVOID*)&pBerv); BAIL_ON_VMDIR_ERROR(dwError); pBerv[0].lberbv_len = VmDirStringLenA(pszRef); pBerv[0].lberbv_val = pszRef; pBerv[0].bOwnBvVal = TRUE; pBerv[1].lberbv_val = NULL; pBerv[1].lberbv_len = 0; dwError = ber_printf(ber, "{it{W}N}{it{ess}N}", msgId, LDAP_RES_SEARCH_REFERENCE, pBerv, msgId, GetResultTag(op->reqCode), op->ldapResult.errCode, "", ""); BAIL_ON_LBER_ERROR(dwError); dwError = WriteBerOnSocket( op->conn, ber ); BAIL_ON_VMDIR_ERROR(dwError); *pbRefSent = TRUE; VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "VmDirSendLdapReferralResult: sent with referral %s", pszRef); done: ber_free_buf( ber ); VmDirFreeBervalArrayContent(pBerv, 1); VMDIR_SAFE_FREE_MEMORY(pBerv); VMDIR_SAFE_FREE_MEMORY(pszLeader); return; error: goto done; }