示例#1
0
int
VmDirMLDelete(
    PVDIR_OPERATION    pOperation
    )
{
    DWORD       dwError = 0;
    PSTR        pszLocalErrMsg = NULL;

    pOperation->pBECtx->pBE = VmDirBackendSelect(pOperation->reqDn.lberbv.bv_val);
    assert(pOperation->pBECtx->pBE);

    // AnonymousBind Or in case of a failed bind, do not grant delete access
    if (pOperation->conn->bIsAnonymousBind || VmDirIsFailedAccessInfo(&pOperation->conn->AccessInfo))
    {
        dwError = LDAP_INSUFFICIENT_ACCESS;
        BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrMsg, "Not bind/authenticate yet" );
    }

    dwError = VmDirInternalDeleteEntry( pOperation );
    BAIL_ON_VMDIR_ERROR( dwError );

cleanup:

    VmDirSendLdapResult( pOperation );

    VMDIR_SAFE_FREE_MEMORY( pszLocalErrMsg );

    return pOperation->ldapResult.errCode;

error:

    VMDIR_SET_LDAP_RESULT_ERROR( &(pOperation->ldapResult), dwError, pszLocalErrMsg);

    goto cleanup;
}
示例#2
0
文件: rename.c 项目: vmware/lightwave
int
VmDirPerformRename(
   PVDIR_OPERATION pOperation
   )
{
    ModifyReq *        modReq = &(pOperation->request.modifyReq);
    int                retVal = LDAP_SUCCESS;
    PVDIR_LDAP_RESULT  pResult = &(pOperation->ldapResult);
    ber_len_t          size = 0;
    PSTR               pszLocalErrorMsg = NULL;

    if (!_VmDirIsRenameSupported())
    {
        pResult->errCode = retVal = LDAP_UNWILLING_TO_PERFORM;
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrorMsg, "Operation is not enabled on this server or is not supported at this domain fuctional level.");
    }

    // Get entry DN. 'm' => reqDn.bv_val points to DN within (in-place) ber
    if ( ber_scanf( pOperation->ber, "{mmb", &modReq->dn, &modReq->newrdn, &modReq->bDeleteOldRdn) == LBER_ERROR )
    {
        VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "VmDirPerformRename: ber_scanf failed" );
        pResult->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                      "Decoding error while parsing the target DN");
    }

    if (ber_peek_tag(pOperation->ber, &size) == LDAP_TAG_NEWSUPERIOR)
    {
        if ( ber_scanf(pOperation->ber, "m", &modReq->newSuperior ) == LBER_ERROR ) {
        pResult->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Decoding error while parsing newSuperior");

        }
    }

   if ( ber_scanf( pOperation->ber, "}") == LBER_ERROR )
   {
      VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "PerformRename: ber_scanf failed" );
      pResult->errCode = LDAP_PROTOCOL_ERROR;
      retVal = LDAP_NOTICE_OF_DISCONNECT;
      BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg), "Decoding error while parsing the end of message.");
   }

   retVal = pResult->errCode = VmDirMLModify( pOperation );
   BAIL_ON_VMDIR_ERROR(retVal);

cleanup:
    if (retVal != LDAP_NOTICE_OF_DISCONNECT)
    {
        VmDirSendLdapResult( pOperation );
    }
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    return retVal;

error:
    VMDIR_APPEND_ERROR_MSG(pResult->pszErrMsg, pszLocalErrorMsg);
    goto cleanup;
}
示例#3
0
int
VmDirPerformDelete(
   PVDIR_OPERATION pOperation
   )
{
    int              retVal = LDAP_SUCCESS;
    DeleteReq *      dr = &(pOperation->request.deleteReq);
    BOOLEAN         bResultAlreadySent = FALSE;
    // Get entry DN. 'm' => pOperation->reqDn.lberbv.bv_val points to DN within (in-place) ber
    if ( ber_scanf( pOperation->ber, "m", &(pOperation->reqDn.lberbv) ) == LBER_ERROR )
    {
        VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "PerformDelete: ber_scanf failed" );
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, "Delete Request: dn (%s)", pOperation->reqDn.lberbv.bv_val );

    memset( dr, 0, sizeof( DeleteReq ));

    // NOTE: pOperation->reqDn.lberbv.bv_val is NULL terminated (TODO, verify this)
    dr->dn.lberbv.bv_val = pOperation->reqDn.lberbv.bv_val;
    dr->dn.lberbv.bv_len = pOperation->reqDn.lberbv.bv_len;

    retVal = VmDirMLDelete( pOperation );
    bResultAlreadySent = TRUE;
    BAIL_ON_VMDIR_ERROR(retVal);

cleanup:

    return retVal;

error:
    if (retVal != LDAP_NOTICE_OF_DISCONNECT && bResultAlreadySent == FALSE)
    {
        VmDirSendLdapResult( pOperation );
    }

    goto cleanup;
}
示例#4
0
int
VmDirMLSearch(
    PVDIR_OPERATION pOperation
    )
{
    int     retVal = 0;
    PSTR    pszLocalErrMsg = NULL;

    pOperation->pBEIF = VmDirBackendSelect(pOperation->reqDn.lberbv.bv_val);
    assert(pOperation->pBEIF);

    if (pOperation->conn->bIsAnonymousBind && !VmDirIsSearchForDseRootEntry( pOperation ))
    {
        retVal = LDAP_INSUFFICIENT_ACCESS;
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "Not bind/authenticate yet" );
    }

    // AnonymousBind is handled when retrieving search candidate result
    // DSE_ROOT_DN and PERSISTED_DSE_ROOT_DN, SCHEMA_NAMING_CONTEXT_DN
    // SUB_SCHEMA_SUB_ENTRY_DN should allow anonymous bind READ
    retVal = VmDirInternalSearch( pOperation);
    BAIL_ON_VMDIR_ERROR(retVal);

cleanup:

    VmDirSendLdapResult( pOperation );

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);

    return pOperation->ldapResult.errCode;

error:

    VMDIR_SET_LDAP_RESULT_ERROR( &(pOperation->ldapResult), retVal, pszLocalErrMsg);
    goto cleanup;
}
示例#5
0
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;
}
示例#6
0
static
int
BindListenOnPort(
#ifndef _WIN32
   sa_family_t   addr_type,
   size_t        addr_size,
#else
   short         addr_type,
   int           addr_size,
#endif
    void         *pServ_addr,
    ber_socket_t *pSockfd
)
{
#define LDAP_PORT_LISTEN_BACKLOG 128
   int  optname = 0;
   int  retVal = LDAP_SUCCESS;
   int  retValBind = 0;
   PSTR pszLocalErrMsg = NULL;
   int  on = 1;
#ifdef _WIN32
   DWORD sTimeout = 0;
   int  reTries = 0;
#else
   struct timeval sTimeout = {0};
#endif

   *pSockfd = -1;
   *pSockfd = socket(addr_type, SOCK_STREAM, 0);
   if (*pSockfd < 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: socket() call failed with errno: %d", __func__, errno );
   }

#ifdef _WIN32
    optname = SO_EXCLUSIVEADDRUSE;
#else
    optname = SO_REUSEADDR;
#endif

   if (setsockopt(*pSockfd, SOL_SOCKET, optname, (const char *)(&on), sizeof(on)) < 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() call failed with errno: %d", __func__, errno );
   }

   on = 1;  // turn on TCP_NODELAY below

   if (setsockopt(*pSockfd,  IPPROTO_TCP, TCP_NODELAY, (const char *)(&on), sizeof(on) ) < 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() TCP_NODELAY call failed with errno: %d", __func__, errno );
   }

   if (addr_type == AF_INET6)
   {
#ifdef _WIN32
       if (setsockopt(*pSockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)(&on), sizeof(on) ) < 0)
       {
           errno = WSAGetLastError();
#else
       if (setsockopt(*pSockfd, SOL_IPV6, IPV6_V6ONLY, (const char *)(&on), sizeof(on) ) < 0)
       {
#endif
           retVal = LDAP_OPERATIONS_ERROR;
           BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() IPV6_V6ONLY call failed with errno: %d", __func__, errno );
       }
   }

   if (gVmdirGlobals.dwLdapRecvTimeoutSec > 0)
   {
#ifdef _WIN32
       sTimeout = gVmdirGlobals.dwLdapRecvTimeoutSec*1000;
#else
       sTimeout.tv_sec = gVmdirGlobals.dwLdapRecvTimeoutSec;
       sTimeout.tv_usec = 0;
#endif
       if (setsockopt(*pSockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &sTimeout, sizeof(sTimeout)) < 0)
       {
#ifdef _WIN32
           errno = WSAGetLastError();
#endif
           retVal = LDAP_OPERATIONS_ERROR;
           BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() SO_RCVTIMEO failed, errno: %d", __func__, errno );
       }
   }

   retValBind = bind(*pSockfd, (struct sockaddr *) pServ_addr, addr_size);

#ifdef _WIN32
   // Add retry logic per PR 1347783
   reTries = 0;
   while (retValBind != 0 && reTries < MAX_NUM_OF_BIND_PORT_RETRIES)
   {
      errno = WSAGetLastError();
      if (errno != WSAEADDRINUSE)
      {
         break;
      }
      reTries++;
      VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "%s: bind() call failed with errno: %d, re-trying (%d)",
                                   __func__, errno, reTries);
      VmDirSleep(1000);
      retValBind = bind(*pSockfd, (struct sockaddr *) pServ_addr, addr_size);
   }
#endif

   if (retValBind != 0)
   {
      retVal = LDAP_OPERATIONS_ERROR;
      //need to free socket ...
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: bind() call failed with errno: %d", __func__, errno );
   }

   if (listen(*pSockfd, LDAP_PORT_LISTEN_BACKLOG) != 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: listen() call failed with errno: %d", __func__, errno );
   }

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);
    return retVal;

error:

    if (*pSockfd >= 0)
    {
        tcp_close(*pSockfd);
        *pSockfd = -1;
    }
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, VDIR_SAFE_STRING(pszLocalErrMsg));
    goto cleanup;
}

/*
 *  We own pConnection and delete it when done.
 */
static
DWORD
ProcessAConnection(
   PVOID pArg
   )
{
   VDIR_CONNECTION *pConn = NULL;
   int            retVal = LDAP_SUCCESS;
   ber_tag_t      tag = LBER_ERROR;
   ber_len_t      len = 0;
   BerElement *   ber = NULL;
   ber_int_t      msgid = -1;
   PVDIR_OPERATION pOperation = NULL;
   int            reTries = 0;
   BOOLEAN                      bDownOpThrCount = FALSE;
   PVDIR_CONNECTION_CTX pConnCtx = NULL;

   // increment operation thread counter
   retVal = VmDirSyncCounterIncrement(gVmdirGlobals.pOperationThrSyncCounter);
   BAIL_ON_VMDIR_ERROR(retVal);
   bDownOpThrCount = TRUE;

   pConnCtx = (PVDIR_CONNECTION_CTX)pArg;
   assert(pConnCtx);

   retVal = NewConnection(pConnCtx->sockFd, &pConn, pConnCtx->pSockbuf_IO);
   if (retVal != LDAP_SUCCESS)
   {
       VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: NewConnection [%d] failed with error: %d",
                        __func__, pConnCtx->sockFd, retVal);
       goto error;
   }

   while (TRUE)
   {
       if (VmDirdState() == VMDIRD_STATE_SHUTDOWN)
       {
           goto cleanup;
       }

      ber = ber_alloc();
      assert( ber != NULL);

      /* An LDAP request message looks like:
       * LDAPMessage ::= SEQUENCE {
       *                    messageID       MessageID,
       *                    protocolOp      CHOICE {
       *                       bindRequest     BindRequest,
       *                       unbindRequest   UnbindRequest,
       *                       searchRequest   SearchRequest,
       *                       ... },
       *                       controls       [0] Controls OPTIONAL }
       */


      // reset retry count
      reTries = 0;
      // Read complete LDAP request message (tag, length, and real message).
      while( reTries < MAX_NUM_OF_SOCK_READ_RETRIES )
      {
         if ((tag = ber_get_next( pConn->sb, &len, ber )) == LDAP_TAG_MESSAGE )
         {
            break;
         }

#ifdef _WIN32
         // in ber_get_next (liblber) call, sock_errset() call WSASetLastError()
         errno = WSAGetLastError();
         if ( errno == EWOULDBLOCK || errno == EAGAIN || errno == WSAETIMEDOUT)
#else
         if ( errno == EWOULDBLOCK || errno == EAGAIN)
#endif
         {
            if (gVmdirGlobals.dwLdapRecvTimeoutSec > 0 && ber->ber_len == 0)
            {
                VMDIR_LOG_INFO( LDAP_DEBUG_CONNS,
                    "%s: disconnecting peer (%s), idle > %d seconds",
                    __func__, pConn->szClientIP, gVmdirGlobals.dwLdapRecvTimeoutSec);
                retVal = LDAP_NOTICE_OF_DISCONNECT;
                BAIL_ON_VMDIR_ERROR( retVal );
            }

            //This may occur when not all data have recieved - set to EAGAIN/EWOULDBLOCK by ber_get_next,
            // and in such case ber->ber_len > 0;
            if (reTries > 0 && reTries % 5 == 0)
            {
                VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "%s: ber_get_next() failed with errno = %d, peer (%s), re-trying (%d)",
                                   __func__, errno , pConn->szClientIP, reTries);
            }
            VmDirSleep(200);
            reTries++;
            continue;
         }
         // Unexpected error case.
         if (errno == 0)
         {
             VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "%s: ber_get_next() peer (%s) disconnected",
                 __func__, pConn->szClientIP);
         } else
         {
             VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: ber_get_next() call failed with errno = %d peer (%s)",
                  __func__, errno, pConn->szClientIP);
         }
         retVal = LDAP_NOTICE_OF_DISCONNECT;
         BAIL_ON_VMDIR_ERROR( retVal );
      }

      // Read LDAP request messageID (tag, length (not returned since it is implicit/integer), and messageID value)
      if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID )
      {
         VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessAConnection: ber_get_int() call failed." );
         retVal = LDAP_NOTICE_OF_DISCONNECT;
         BAIL_ON_VMDIR_ERROR( retVal );
      }

      // Read protocolOp (tag) and length of the LDAP operation message, and leave the pointer at the beginning
      // of the LDAP operation message (to be parsed by PerformXYZ methods).
      if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR )
      {
         VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessAConnection: ber_peek_tag() call failed." );
         retVal = LDAP_NOTICE_OF_DISCONNECT;
         BAIL_ON_VMDIR_ERROR( retVal );
      }

      retVal = VmDirNewOperation(ber, msgid, tag, pConn, &pOperation);
      if (retVal)
      {
          VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessAConnection: NewOperation() call failed." );
          retVal = LDAP_OPERATIONS_ERROR;
      }
      BAIL_ON_VMDIR_ERROR( retVal );

      //
      // If this is a multi-stage operation don't overwrite the start time if it's already set.
      //
      pConn->SuperLogRec.iStartTime = pConn->SuperLogRec.iStartTime ? pConn->SuperLogRec.iStartTime : VmDirGetTimeInMilliSec();

      switch (tag)
      {
         case LDAP_REQ_BIND:
            retVal = VmDirPerformBind(pOperation);
            if (retVal != LDAP_SASL_BIND_IN_PROGRESS)
            {
                _VmDirCollectBindSuperLog(pConn, pOperation); // ignore error
            }

            break;

         case LDAP_REQ_ADD:
            retVal = VmDirPerformAdd(pOperation);
            break;

         case LDAP_REQ_SEARCH:
            retVal = VmDirPerformSearch(pOperation);
            break;

         case LDAP_REQ_UNBIND:
            retVal = VmDirPerformUnbind(pOperation);
            break;

         case LDAP_REQ_MODIFY:
             retVal = VmDirPerformModify(pOperation);
             break;

         case LDAP_REQ_DELETE:
             retVal = VmDirPerformDelete(pOperation);
             break;

         case LDAP_REQ_MODDN:
         case LDAP_REQ_COMPARE:
         case LDAP_REQ_ABANDON:
         case LDAP_REQ_EXTENDED:
            VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "ProcessAConnection: Operation is not yet implemented.." );
            pOperation->ldapResult.errCode = retVal = LDAP_UNWILLING_TO_PERFORM;
            // ignore following VmDirAllocateStringA error.
            VmDirAllocateStringA( "Operation is not yet implemented.", &pOperation->ldapResult.pszErrMsg);
            VmDirSendLdapResult( pOperation );
            break;

         default:
            pOperation->ldapResult.errCode = LDAP_PROTOCOL_ERROR;
            retVal = LDAP_NOTICE_OF_DISCONNECT;
            break;
      }

      pConn->SuperLogRec.iEndTime = VmDirGetTimeInMilliSec();
      VmDirOPStatisticUpdate(tag, pConn->SuperLogRec.iEndTime - pConn->SuperLogRec.iStartTime);

      if (tag != LDAP_REQ_BIND)
      {
         VmDirLogOperation(gVmdirGlobals.pLogger, tag, pConn, pOperation->ldapResult.errCode);

         _VmDirScrubSuperLogContent(tag, &pConn->SuperLogRec);
      }

      VmDirFreeOperation(pOperation);
      pOperation = NULL;

      ber_free( ber, 1);
      ber = NULL;

      if (retVal == LDAP_NOTICE_OF_DISCONNECT) // returned as a result of protocol parsing error.
      {
         // RFC 4511, section 4.1.1: If the server receives an LDAPMessage from the client in which the LDAPMessage
         // SEQUENCE tag cannot be recognized, the messageID cannot be parsed, the tag of the protocolOp is not
         // recognized as a request, or the encoding structures or lengths of data fields are found to be incorrect,
         // then the server **SHOULD** return the Notice of Disconnection, with the resultCode
         // set to protocolError, and **MUST** immediately terminate the LDAP session as described in Section 5.3.

         goto cleanup;
      }
   }

cleanup:
   if (retVal == LDAP_NOTICE_OF_DISCONNECT)
   {
      // Optionally send Notice of Disconnection with rs->err.
   }
   if (ber != NULL)
   {
      ber_free( ber, 1 );
   }
    VmDirDeleteConnection(&pConn);
    VMDIR_SAFE_FREE_MEMORY(pConnCtx);
    VmDirFreeOperation(pOperation);

    if (bDownOpThrCount)
    {
        VmDirSyncCounterDecrement(gVmdirGlobals.pOperationThrSyncCounter);
    }

    _VmDirFlowCtrlThrExit();

    // TODO: should we return dwError ?
    return 0;

error:
    goto cleanup;
}
示例#7
0
int
VmDirPerformSearch(
    PVDIR_OPERATION   pOperation
    )
{
   ber_len_t     size = 0;
   SearchReq *   sr = &(pOperation->request.searchReq);
   int           retVal = LDAP_SUCCESS;
   BerValue*           pLberBerv = NULL;
   PSTR                pszLocalErrorMsg = NULL;
   BOOLEAN             bResultAlreadySent = FALSE;
   PVDIR_LDAP_RESULT   pResult = &(pOperation->ldapResult);

   // Parse base object, scope, deref alias, sizeLimit, timeLimit and typesOnly search parameters.
   if ( ber_scanf( pOperation->ber, "{miiiib", &(pOperation->reqDn.lberbv), &sr->scope, &sr->derefAlias, &sr->sizeLimit,
                   &sr->timeLimit, &sr->attrsOnly ) == LBER_ERROR )
   {
      VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "PerformSearch: Decoding baseDN, ... attrsOnly error." );
      pResult->errCode = LDAP_PROTOCOL_ERROR;
      retVal = LDAP_NOTICE_OF_DISCONNECT;
      BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                      "Decoding error while parsing baseDN, ... attrsOnly.");
   }

   VMDIR_LOG_VERBOSE( LDAP_DEBUG_ARGS, "Search Request: base: \"%s\", scope: %d, deref: %d, sizeLimit: %d, timeLimit: %d,"
             "attrsOnly: %d", pOperation->reqDn.lberbv.bv_val, sr->scope, sr->derefAlias, sr->sizeLimit, sr->timeLimit,
             sr->attrsOnly);

   if (sr->scope != LDAP_SCOPE_BASE && sr->scope != LDAP_SCOPE_ONELEVEL &&
       sr->scope != LDAP_SCOPE_SUBTREE)
   {
       pResult->errCode = retVal = LDAP_PROTOCOL_ERROR;
       BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid scope" );
   }

   if (sr->sizeLimit < 0 || sr->sizeLimit > LDAP_MAXINT)
   {
       pResult->errCode = retVal = LDAP_PROTOCOL_ERROR;
       BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid size limit: %d", sr->sizeLimit  );
   }

   if (sr->timeLimit < 0 || sr->timeLimit > LDAP_MAXINT)
   {
       pResult->errCode = retVal = LDAP_PROTOCOL_ERROR;
       BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid time limit: %d", sr->timeLimit );
   }

   if (sr->derefAlias != LDAP_DEREF_NEVER && sr->derefAlias != LDAP_DEREF_SEARCHING &&
       sr->derefAlias != LDAP_DEREF_FINDING && sr->derefAlias != LDAP_DEREF_ALWAYS)
   {
      pResult->errCode = retVal = LDAP_PROTOCOL_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg), "Invalid dereference alias parameter");
   }

   // Parse filter
   retVal = ParseFilter( pOperation, &sr->filter, pResult );
   BAIL_ON_VMDIR_ERROR(retVal);

   // Log String filter, if desired.
   if (VmDirLogGetLevel() >= VMDIR_LOG_VERBOSE && VmDirLogGetMask() & LDAP_DEBUG_ARGS)
   {
      VDIR_BERVALUE strFilter = VDIR_BERVALUE_INIT;
      FilterToStrFilter( sr->filter, &strFilter );
      VMDIR_LOG_VERBOSE( LDAP_DEBUG_ARGS, "    Filter: %s", strFilter.lberbv.bv_val );
      VmDirFreeBervalContent(&strFilter);
   }

   // Parse attributes. 'M' => attribute names point within (in-place) the ber.
   size = sizeof( BerValue ); // Size of the structure is passed-in, and number of attributes are returned back in
                              // the same parameter.
   if ( ber_scanf( pOperation->ber, "{M}}", &pLberBerv, &size, 0 ) == LBER_ERROR )
   {
      pResult->errCode = LDAP_PROTOCOL_ERROR;
      retVal = LDAP_NOTICE_OF_DISCONNECT;
      BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg), "Decoding error while parsing required attributes.");
   }

   // copy pLberBerv content into sr->attrs
   if (pLberBerv && size > 0)
   {
       int iCnt = 0;

       if (VmDirAllocateMemory(sizeof(VDIR_BERVALUE) * (size+1), (PVOID*)&sr->attrs) != 0)
       {
           pResult->errCode = retVal = LDAP_OPERATIONS_ERROR;
           BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg), "no memory");
       }

       for (iCnt = 0; iCnt < size; iCnt++)
       {
           sr->attrs[iCnt].lberbv.bv_val = pLberBerv[iCnt].bv_val;
           sr->attrs[iCnt].lberbv.bv_len = pLberBerv[iCnt].bv_len;
       }
   }

   // Log list of the required attributes, if desired.
   if (( VmDirLogGetMask() & LDAP_DEBUG_ARGS) && size > 0)
   {
       if (VmDirLogSearchRequest(sr, size) != 0)
       {
           pResult->errCode = retVal = LDAP_OPERATIONS_ERROR;
           BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "Error while logging search request");
       }
   }

   // Parse LDAP controls present (if any) in the request.
   retVal = ParseRequestControls(pOperation, pResult);  // ldapResult.errCode set inside
   BAIL_ON_VMDIR_ERROR( retVal );

   retVal = pResult->errCode = VmDirMLSearch( pOperation );
   bResultAlreadySent = TRUE;
   BAIL_ON_VMDIR_ERROR(retVal);

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pLberBerv);
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return retVal;

error:

    VMDIR_APPEND_ERROR_MSG(pResult->pszErrMsg, pszLocalErrorMsg);
    if (retVal != LDAP_NOTICE_OF_DISCONNECT && bResultAlreadySent == FALSE)
    {
        VmDirSendLdapResult( pOperation );
    }

    goto cleanup;
}
示例#8
0
文件: delete.c 项目: vmware/lightwave
int
VmDirPerformDelete(
   PVDIR_OPERATION pOperation
   )
{
    int         retVal = LDAP_SUCCESS;
    DeleteReq * dr = &(pOperation->request.deleteReq);
    BOOLEAN     bRefSent = FALSE;
    PSTR        pszRefStr = NULL;
    PSTR        pszLocalErrMsg = NULL;

    // Get entry DN. 'm' => pOperation->reqDn.lberbv.bv_val points to DN within (in-place) ber
    if ( ber_scanf( pOperation->ber, "m", &(pOperation->reqDn.lberbv) ) == LBER_ERROR )
    {
        VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "PerformDelete: ber_scanf failed" );
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, "Delete Request: dn (%s)", pOperation->reqDn.lberbv.bv_val );

    memset( dr, 0, sizeof( DeleteReq ));

    // NOTE: pOperation->reqDn.lberbv.bv_val is NULL terminated (TODO, verify this)
    dr->dn.lberbv.bv_val = pOperation->reqDn.lberbv.bv_val;
    dr->dn.lberbv.bv_len = pOperation->reqDn.lberbv.bv_len;

    retVal = ParseRequestControls(pOperation, &pOperation->ldapResult);
    BAIL_ON_VMDIR_ERROR(retVal);

    if (pOperation->manageDsaITCtrl == NULL &&
        (gVmdirGlobals.dwEnableRaftReferral & VMDIR_RAFT_ENABLE_UPDATE_REFERRAL) &&
        VmDirRaftNeedReferral(pOperation->reqDn.lberbv.bv_val))
    {
       retVal = VmDirAllocateStringPrintf(&pszRefStr, "%s",
                   pOperation->reqDn.lberbv.bv_len > 0 ? pOperation->reqDn.lberbv.bv_val:"");
       BAIL_ON_VMDIR_ERROR(retVal);

       VmDirSendLdapReferralResult(pOperation, pszRefStr, &bRefSent);
       if (bRefSent)
       {
           goto cleanup;
       }
       // Referral is not sent because the raft state might have changed. Go throughput normal procedure.
    }

    retVal = VmDirMLDelete( pOperation );
    BAIL_ON_VMDIR_ERROR(retVal);

cleanup:
    if (retVal != LDAP_NOTICE_OF_DISCONNECT && bRefSent == FALSE)
    {
        VmDirSendLdapResult( pOperation );
    }
    VMDIR_SAFE_FREE_MEMORY(pszRefStr);
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);
    return retVal;

error:
    VMDIR_SET_LDAP_RESULT_ERROR(&pOperation->ldapResult, retVal, pszLocalErrMsg);
    goto cleanup;
}