Ejemplo n.º 1
0
/* 
	This function returns the current Dirsync_Private that's inside 
	Repl_Agmt ra as a ldap control.

  */
LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra)
{

	LDAPControl *control = NULL;
	BerElement *ber;
	Dirsync_Private *dp;
	char iscritical = PR_TRUE;

	LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_dirsync_control\n" );
	
	PR_ASSERT(ra);
	
	dp = (Dirsync_Private *) agmt_get_priv(ra);
	PR_ASSERT (dp);
	ber = 	ber_alloc();

	ber_printf( ber, "{iio}", dp->dirsync_flags, dp->dirsync_maxattributecount, dp->dirsync_cookie ? dp->dirsync_cookie : "", dp->dirsync_cookie_len );

	/* Use a regular directory server instead of a real AD - for testing */
	if (getenv("WINSYNC_USE_DS")) {
		iscritical = PR_FALSE;
	}
	slapi_build_control( REPL_DIRSYNC_CONTROL_OID, ber, iscritical, &control);

	ber_free(ber,1);

	LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_dirsync_control\n" );


	return control;

}
Ejemplo n.º 2
0
int
VmDirCreateRequestVoteCtrl(
    PVDIR_REQUEST_VOTE_CONTROL_VALUE pRequestVoteCtrlValue,
    LDAPControl*    pRequestVoteCtrl
    )
{
    int             retVal = LDAP_SUCCESS;
    BerElement*     pBer = NULL;
    BerValue        candidateIdBV = {0};
    BerValue        lastLogIndexBV = {0};

    if (!pRequestVoteCtrlValue || !pRequestVoteCtrl)
    {
        BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_INVALID_PARAMETER);
    }

    if ((pBer = ber_alloc()) == NULL)
    {
        BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_NO_MEMORY);
    }

    candidateIdBV.bv_val = pRequestVoteCtrlValue->candidateId;
    candidateIdBV.bv_len = VmDirStringLenA(pRequestVoteCtrlValue->candidateId);

    retVal = VmDirAllocateStringPrintf(&lastLogIndexBV.bv_val, "%"PRIu64, pRequestVoteCtrlValue->lastLogIndex);
    BAIL_ON_VMDIR_ERROR( retVal );
    lastLogIndexBV.bv_len = VmDirStringLenA(lastLogIndexBV.bv_val);

    if ( ber_printf( pBer, "{iOOi}", pRequestVoteCtrlValue->term, &candidateIdBV,
                    &lastLogIndexBV, pRequestVoteCtrlValue->lastLogTerm) == -1)
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "%s: ber_printf failed.", __FUNCTION__ );
        BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_NO_MEMORY);
    }

    memset( pRequestVoteCtrl, 0, sizeof( LDAPControl ));
    pRequestVoteCtrl->ldctl_oid = LDAP_REQUEST_VOTE_CONTROL;
    pRequestVoteCtrl->ldctl_iscritical = '1';
    if (ber_flatten2(pBer, &pRequestVoteCtrl->ldctl_value, 1))
    {
        BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_NO_MEMORY);
    }

cleanup:
    VMDIR_SAFE_FREE_MEMORY(lastLogIndexBV.bv_val);
    if (pBer)
    {
        ber_free(pBer, 1);
    }
    return retVal;

error:
    VmDirFreeCtrlContent(pRequestVoteCtrl);
    goto cleanup;
}
Ejemplo n.º 3
0
/** Takes the object DN and BER encodes the data into the BER value which is used as part of the request
 *
 @verbatim
	RequestBer contents:
		clientVersion		INTEGER
		targetObjectDN		OCTET STRING
 @endverbatim
 *
 * @param[out] request_bv where to write the request BER value (must be freed with ber_bvfree).
 * @param[in] dn to query for.
 * @return 0 on success, and < 0 on error.
 */
static int ber_encode_request_data(char const *dn, struct berval **request_bv)
{
	int err = 0;
	int rc = 0;
	BerElement *request_ber = NULL;

	if (!dn || !*dn) {
		err = NMAS_E_INVALID_PARAMETER;
		goto finish;
	}

	/* Allocate a BerElement for the request parameters.*/
	if ((request_ber = ber_alloc()) == NULL) {
		err = NMAS_E_FRAG_FAILURE;
		goto finish;
	}

	rc = ber_printf(request_ber, "{io}", NMAS_LDAP_EXT_VERSION, dn, strlen(dn) + 1);
	if (rc < 0) {
		err = NMAS_E_FRAG_FAILURE;
		goto finish;
	}

	/*
	 *	Convert the BER we just built to a berval that we'll
	 *	send with the extended request.
	 */
	if (ber_flatten(request_ber, request_bv) < 0) {
		err = NMAS_E_FRAG_FAILURE;
		goto finish;
	}

finish:
	if (request_ber) ber_free(request_ber, 1);

	return err;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
static int berEncodePasswordData(
    struct berval **requestBV,
    const char    *objectDN,
    const char    *password,
    const char    *password2)
{
    int err = 0, rc=0;
    BerElement *requestBer = NULL;

    const char    * utf8ObjPtr = NULL;
    int     utf8ObjSize = 0;
    const char    * utf8PwdPtr = NULL;
    int     utf8PwdSize = 0;
    const char    * utf8Pwd2Ptr = NULL;
    int     utf8Pwd2Size = 0;


    /* Convert objectDN and tag strings from Unicode to UTF-8 */
    utf8ObjSize = strlen(objectDN)+1;
    utf8ObjPtr = objectDN;

    if (password != NULL) {
        utf8PwdSize = strlen(password)+1;
        utf8PwdPtr = password;
    }

    if (password2 != NULL) {
        utf8Pwd2Size = strlen(password2)+1;
        utf8Pwd2Ptr = password2;
    }

    /* Allocate a BerElement for the request parameters. */
    if ((requestBer = ber_alloc()) == NULL) {
        err = LDAP_ENCODING_ERROR;
        goto Cleanup;
    }

    if (password != NULL && password2 != NULL) {
        /* BER encode the NMAS Version, the objectDN, and the password */
        rc = ber_printf(requestBer, "{iooo}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize, utf8PwdPtr, utf8PwdSize, utf8Pwd2Ptr, utf8Pwd2Size);
    } else if (password != NULL) {
        /* BER encode the NMAS Version, the objectDN, and the password */
        rc = ber_printf(requestBer, "{ioo}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize, utf8PwdPtr, utf8PwdSize);
    } else {
        /* BER encode the NMAS Version and the objectDN */
        rc = ber_printf(requestBer, "{io}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize);
    }

    if (rc < 0) {
        err = LDAP_ENCODING_ERROR;
        goto Cleanup;
    } else {
        err = 0;
    }

    /* Convert the BER we just built to a berval that we'll send with the extended request. */
    if (ber_flatten(requestBer, requestBV) == LBER_ERROR) {
        err = LDAP_ENCODING_ERROR;
        goto Cleanup;
    }

Cleanup:

    if (requestBer) {
        ber_free(requestBer, 1);
    }

    return err;
}
Ejemplo n.º 7
0
static int berEncodeLoginData(
    struct berval **requestBV,
    char     *objectDN,
    unsigned int  methodIDLen,
    unsigned int *methodID,
    char     *tag,
    size_t   putDataLen,
    void     *putData)
{
    int err = 0;
    BerElement *requestBer = NULL;

    unsigned int i;
    unsigned int elemCnt = methodIDLen / sizeof(unsigned int);

    char	*utf8ObjPtr=NULL;
    int     utf8ObjSize = 0;

    char    *utf8TagPtr = NULL;
    int     utf8TagSize = 0;

    utf8ObjPtr = objectDN;
    utf8ObjSize = strlen(utf8ObjPtr)+1;

    utf8TagPtr = tag;
    utf8TagSize = strlen(utf8TagPtr)+1;

    /* Allocate a BerElement for the request parameters. */
    if ((requestBer = ber_alloc()) == NULL) {
        err = LDAP_ENCODING_ERROR;
        goto Cleanup;
    }

    /* BER encode the NMAS Version and the objectDN */
    err = (ber_printf(requestBer, "{io", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize) < 0) ? LDAP_ENCODING_ERROR : 0;

    /* BER encode the MethodID Length and value */
    if (!err) {
        err = (ber_printf(requestBer, "{i{", methodIDLen) < 0) ? LDAP_ENCODING_ERROR : 0;
    }

    for (i = 0; !err && i < elemCnt; i++) {
        err = (ber_printf(requestBer, "i", methodID[i]) < 0) ? LDAP_ENCODING_ERROR : 0;
    }

    if (!err) {
        err = (ber_printf(requestBer, "}}", 0) < 0) ? LDAP_ENCODING_ERROR : 0;
    }

    if (putData) {
        /* BER Encode the the tag and data */
        err = (ber_printf(requestBer, "oio}", utf8TagPtr, utf8TagSize, putDataLen, putData, putDataLen) < 0) ? LDAP_ENCODING_ERROR : 0;
    } else {
        /* BER Encode the the tag */
        err = (ber_printf(requestBer, "o}", utf8TagPtr, utf8TagSize) < 0) ? LDAP_ENCODING_ERROR : 0;
    }

    if (err) {
        goto Cleanup;
    }

    /* Convert the BER we just built to a berval that we'll send with the extended request. */
    if (ber_flatten(requestBer, requestBV) == LBER_ERROR) {
        err = LDAP_ENCODING_ERROR;
        goto Cleanup;
    }

Cleanup:

    if (requestBer) {
        ber_free(requestBer, 1);
    }

    return err;
}
Ejemplo n.º 8
0
DOMAIN_CONTROLLER_INFO *
dc_locate(const char *prefix, const char *dname)
{
	lsa_srv_ctx_t *ctx;
	srv_rr_t *sr;
	BerElement *pdu = NULL, *ret;
	struct _berelement *be, *rbe;
 	DOMAIN_CONTROLLER_INFO *dci = NULL;
	int r, fd = -1;
	struct sockaddr_storage addr;
	struct sockaddr_in6 *paddr;
	socklen_t addrlen;
	char *dcaddr = NULL, *dcname = NULL;

	ctx = lsa_srv_init();
	if (ctx == NULL)
		goto fail;

	r = lsa_srv_lookup(ctx, prefix, dname);
	if (r <= 0) 
		goto fail;

	if (lsa_srv_output)
		lsa_srv_output(ctx);

	if ((fd = lsa_bind()) < 0)
		goto fail;

	if ((pdu = ber_alloc()) == NULL)
		goto fail;
	
	/* 
	 * Is ntver right? It certainly works on w2k8... If others are needed,
	 * that might require changes to lsa_cldap_parse
	 */
	r = lsa_cldap_setup_pdu(pdu, dname, NULL, NETLOGON_NT_VERSION_5EX); 

	struct pollfd pingchk = {fd, POLLIN, 0};

	if ((dcaddr = malloc(INET6_ADDRSTRLEN + 2)) == NULL)
		goto fail;
	if (strncpy(dcaddr, "\\\\", 3) == NULL)
		goto fail;
	if ((dcname = malloc(MAXHOSTNAMELEN + 3)) == NULL)
		goto fail;

	be = (struct _berelement *)pdu;
	sr = NULL;
	while ((sr = lsa_srv_next(ctx, sr)) != NULL) {
		r = sendto(fd, be->ber_buf, (size_t)(be->ber_end - be->ber_buf),
		    0, (struct sockaddr *)&sr->addr, sizeof(sr->addr));
		if (poll(&pingchk, 1, 100) == 0)
			continue;

		if ((ret = ber_alloc()) == NULL)
			goto fail;		
		rbe = (struct _berelement *)ret;
		recvfrom(fd, rbe->ber_buf, (size_t)(rbe->ber_end - rbe->ber_buf), 
		    0, (struct sockaddr *)&addr, &addrlen);

		if ((dci = malloc(sizeof (DOMAIN_CONTROLLER_INFO))) == NULL) {
			ber_free(ret, 1);
			goto fail;
		}
		dci->DomainControllerName = dcname;

		r = lsa_cldap_parse(ret, dci);
		ber_free(ret, 1);
		if (r == 0)
			break;
		if (r > 1)
			goto fail;
	}

	if (sr == NULL)
		goto fail;

	paddr = (struct sockaddr_in6 *)&addr;
	inet_ntop(paddr->sin6_family, &paddr->sin6_addr, dcaddr+2, 
	    INET6_ADDRSTRLEN);
	dci->DomainControllerAddress = dcaddr;
	dci->DomainControllerAddressType = DS_INET_ADDRESS;

	ber_free(pdu, 1);
	lsa_srv_fini(ctx);
	(void) close(fd);
	return (dci);

 fail:
	lsa_srv_fini(ctx);
	if (dci)
		freedci(dci);
	else
		free(dcname);
	free(dcaddr);
	ber_free(pdu, 1);
	if (fd >= 0)
		(void) close(fd);
	return (NULL);
}
Ejemplo n.º 9
0
int
VmDirCreateAppendEntriesCtrl(
    PVDIR_APPEND_ENTRIES_CONTROL_VALUE pAppendEntriesCtrlValue,
    LDAPControl*    pAppendEntriesCtrl
    )
{
    int             retVal = LDAP_SUCCESS;
    BerElement*     pBer = NULL;
    BerValue        leaderBV = {0};
    BerValue        preLogIndexBV = {0};
    BerValue        leaderCommitBV = {0};
    BerValue        entriesBV = {0};

    if (!pAppendEntriesCtrlValue || !pAppendEntriesCtrl)
    {
        BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_INVALID_PARAMETER);
    }

    if ((pBer = ber_alloc()) == NULL)
    {
        BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_NO_MEMORY);
    }

    leaderBV.bv_val = (char*)pAppendEntriesCtrlValue->leader;
    leaderBV.bv_len = VmDirStringLenA(pAppendEntriesCtrlValue->leader);

    retVal = VmDirAllocateStringPrintf(&preLogIndexBV.bv_val, "%"PRIu64, pAppendEntriesCtrlValue->preLogIndex);
    BAIL_ON_VMDIR_ERROR( retVal );
    preLogIndexBV.bv_len = VmDirStringLenA(preLogIndexBV.bv_val);

    retVal = VmDirAllocateStringPrintf(&leaderCommitBV.bv_val, "%"PRIu64, pAppendEntriesCtrlValue->leaderCommit);
    BAIL_ON_VMDIR_ERROR( retVal );
    leaderCommitBV.bv_len = VmDirStringLenA( leaderCommitBV.bv_val);

    entriesBV.bv_val = pAppendEntriesCtrlValue->entries.lberbv.bv_val;
    entriesBV.bv_len = pAppendEntriesCtrlValue->entries.lberbv.bv_len;

    if ( ber_printf( pBer, "{iOOiOO}", pAppendEntriesCtrlValue->term, &leaderBV,
                     &preLogIndexBV, pAppendEntriesCtrlValue->preLogTerm, &leaderCommitBV, &entriesBV) == -1)
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "%s: ber_printf failed.", __FUNCTION__ );
        BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_NO_MEMORY);
    }

    memset( pAppendEntriesCtrl, 0, sizeof( LDAPControl ));
    pAppendEntriesCtrl->ldctl_oid = LDAP_APPEND_ENTRIES_CONTROL;
    pAppendEntriesCtrl->ldctl_iscritical = '1';
    if (ber_flatten2(pBer, &pAppendEntriesCtrl->ldctl_value, 1))
    {
        BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_NO_MEMORY);
    }

cleanup:
    VMDIR_SAFE_FREE_MEMORY(preLogIndexBV.bv_val);
    VMDIR_SAFE_FREE_MEMORY(leaderCommitBV.bv_val);
    if (pBer)
    {
        ber_free(pBer, 1);
    }
    return retVal;

error:
    VmDirFreeCtrlContent(pAppendEntriesCtrl);
    goto cleanup;
}
Ejemplo n.º 10
0
/*
 * Filter out unresponsive servers, and save the domain info
 * returned by the "LDAP ping" in the returned object.
 * If ctx != NULL, this is a query for a DC, in which case we
 * also save the Domain GUID, Site name, and Forest name as
 * "auto" (discovered) values in the ctx.
 *
 * Only return the "winner".  (We only want one DC/GC)
 */
ad_disc_ds_t *
ldap_ping(ad_disc_t ctx, ad_disc_cds_t *dclist, char *dname, int reqflags)
{
	struct sockaddr_in6 addr6;
	socklen_t addrlen;
	struct pollfd pingchk;
	ad_disc_cds_t *send_ds;
	ad_disc_cds_t *recv_ds = NULL;
	ad_disc_ds_t *ret_ds = NULL;
	BerElement *req = NULL;
	BerElement *res = NULL;
	struct _berelement *be, *rbe;
	size_t be_len, rbe_len;
	int fd = -1;
	int tries = 3;
	int waitsec;
	int r;
	uint16_t msgid;

	/* One plus a null entry. */
	ret_ds = calloc(2, sizeof (ad_disc_ds_t));
	if (ret_ds == NULL)
		goto fail;

	if ((fd = socket(PF_INET6, SOCK_DGRAM, 0)) < 0)
		goto fail;

	(void) memset(&addr6, 0, sizeof (addr6));
	addr6.sin6_family = AF_INET6;
	addr6.sin6_addr = in6addr_any;
	if (bind(fd, (struct sockaddr *)&addr6, sizeof (addr6)) < 0)
		goto fail;

	/*
	 * semi-unique msgid...
	 */
	msgid = gethrtime() & 0xffff;

	/*
	 * Is ntver right? It certainly works on w2k8... If others are needed,
	 * that might require changes to cldap_parse
	 */
	req = cldap_build_request(dname, NULL,
	    NETLOGON_NT_VERSION_5EX, msgid);
	if (req == NULL)
		goto fail;
	be = (struct _berelement *)req;
	be_len = be->ber_end - be->ber_buf;

	if ((res = ber_alloc()) == NULL)
		goto fail;
	rbe = (struct _berelement *)res;
	rbe_len = rbe->ber_end - rbe->ber_buf;

	pingchk.fd = fd;
	pingchk.events = POLLIN;
	pingchk.revents = 0;

try_again:
	send_ds = dclist;
	waitsec = 5;
	while (recv_ds == NULL && waitsec > 0) {

		/*
		 * If there is another candidate, send to it.
		 */
		if (send_ds->cds_ds.host[0] != '\0') {
			send_to_cds(send_ds, be->ber_buf, be_len, fd);
			send_ds++;

			/*
			 * Wait 1/10 sec. before the next send.
			 */
			r = poll(&pingchk, 1, 100);
#if 0 /* DEBUG */
			/* Drop all responses 1st pass. */
			if (waitsec == 5)
				r = 0;
#endif
		} else {
			/*
			 * No more candidates to "ping", so
			 * just wait a sec for responses.
			 */
			r = poll(&pingchk, 1, 1000);
			if (r == 0)
				--waitsec;
		}

		if (r > 0) {
			/*
			 * Got a response.
			 */
			(void) memset(&addr6, 0, addrlen = sizeof (addr6));
			r = recvfrom(fd, rbe->ber_buf, rbe_len, 0,
			    (struct sockaddr *)&addr6, &addrlen);

			recv_ds = find_cds_by_addr(dclist, &addr6);
			if (recv_ds == NULL)
				continue;

			(void) cldap_parse(ctx, recv_ds, res);
			if ((recv_ds->cds_ds.flags & reqflags) != reqflags) {
				logger(LOG_ERR, "Skip %s"
				    "due to flags 0x%X",
				    recv_ds->cds_ds.host,
				    recv_ds->cds_ds.flags);
				recv_ds = NULL;
			}
		}
	}

	if (recv_ds == NULL) {
		if (--tries <= 0)
			goto fail;
		goto try_again;
	}

	(void) memcpy(ret_ds, recv_ds, sizeof (*ret_ds));

	ber_free(res, 1);
	ber_free(req, 1);
	(void) close(fd);
	return (ret_ds);

fail:
	ber_free(res, 1);
	ber_free(req, 1);
	(void) close(fd);
	free(ret_ds);
	return (NULL);
}
Ejemplo n.º 11
0
/*
 * Construct CLDAPMessage PDU for NetLogon search request.
 *
 *  CLDAPMessage ::= SEQUENCE {
 *      messageID       MessageID,
 *      protocolOp      searchRequest   SearchRequest;
 *  }
 *
 *  SearchRequest ::=
 *      [APPLICATION 3] SEQUENCE {
 *          baseObject    LDAPDN,
 *          scope         ENUMERATED {
 *                             baseObject            (0),
 *                             singleLevel           (1),
 *                             wholeSubtree          (2)
 *                        },
 *          derefAliases  ENUMERATED {
 *                                     neverDerefAliases     (0),
 *                                     derefInSearching      (1),
 *                                     derefFindingBaseObj   (2),
 *                                     derefAlways           (3)
 *                                },
 *          sizeLimit     INTEGER (0 .. MaxInt),
 *          timeLimit     INTEGER (0 .. MaxInt),
 *          attrsOnly     BOOLEAN,
 *          filter        Filter,
 *          attributes    SEQUENCE OF AttributeType
 *  }
 */
BerElement *
cldap_build_request(const char *dname,
	const char *host, uint32_t ntver, uint16_t msgid)
{
	BerElement 	*ber;
	int		len = 0;
	char		*basedn = "";
	int scope = LDAP_SCOPE_BASE, deref = LDAP_DEREF_NEVER,
	    sizelimit = 0, timelimit = 0, attrsonly = 0;
	char		filter[512];
	char		ntver_esc[13];
	char		*p, *pend;

	/*
	 * Construct search filter in LDAP format.
	 */
	p = filter;
	pend = p + sizeof (filter);

	len = snprintf(p, pend - p, "(&(DnsDomain=%s)", dname);
	if (len >= (pend - p))
		goto fail;
	p += len;

	if (host != NULL) {
		len = snprintf(p, (pend - p), "(Host=%s)", host);
		if (len >= (pend - p))
			goto fail;
		p += len;
	}

	if (ntver != 0) {
		/*
		 * Format NtVer as little-endian with LDAPv3 escapes.
		 */
		cldap_escape_le64(ntver_esc, ntver, sizeof (ntver));
		len = snprintf(p, (pend - p), "(NtVer=%s)", ntver_esc);
		if (len >= (pend - p))
			goto fail;
		p += len;
	}

	len = snprintf(p, pend - p, ")");
	if (len >= (pend - p))
		goto fail;
	p += len;

	/*
	 * Encode CLDAPMessage and beginning of SearchRequest sequence.
	 */

	if ((ber = ber_alloc()) == NULL)
		goto fail;

	if (ber_printf(ber, "{it{seeiib", msgid,
	    LDAP_REQ_SEARCH, basedn, scope, deref,
	    sizelimit, timelimit, attrsonly) < 0)
		goto fail;

	/*
	 * Encode Filter sequence.
	 */
	if (ldap_put_filter(ber, filter) < 0)
		goto fail;
	/*
	 * Encode attribute and close Filter and SearchRequest sequences.
	 */
	if (ber_printf(ber, "{s}}}", NETLOGON_ATTR_NAME) < 0)
		goto fail;

	/*
	 * Success
	 */
	return (ber);

fail:
	if (ber != NULL)
		ber_free(ber, 1);
	return (NULL);
}
Ejemplo n.º 12
0
/*
 * Get a Slapi_Entry ready to send over the wire as part of
 * a total update protocol stream. Convert the entry and all
 * of its state information to a BerElement which will be the
 * payload of an extended LDAP operation.
 *
 * Entries consist of:
 * - An entry DN
 * - A uniqueID
 * - A set of present attributes, each of which consists of:
 *   - A set of present values, each of which consists of:
 *     - A value
 *     - A set of CSNs
 *   - A set of deleted values, each of which consists of:
 *     - A value
 *     - A set of CSNs
 * - A set of deleted attibutes, each of which consists of:
 *   - An attribute type
 *   - A set of CSNs. Note that this list of CSNs will always contain exactly one CSN.
 * 
 * This all gets mashed into one BerElement, ready to be blasted over the wire to
 * a replica.
 *
 */
BerElement *
entry2bere(const Slapi_Entry *e, char **excluded_attrs)
{
	BerElement *ber = NULL;
	const char *str = NULL;
	const char *dnstr = NULL;
    char *type;
	Slapi_DN *sdn = NULL;
	Slapi_Attr *attr = NULL, *prev_attr;
    int rc;

	PR_ASSERT(NULL != e);

	if ((ber = ber_alloc()) == NULL)
	{
		goto loser;
	}
	BER_DEBUG("{");
	if (ber_printf(ber, "{") == -1) /* Begin outer sequence */
	{
		goto loser;
	}

	/* Get the entry's uniqueid */
	if ((str = slapi_entry_get_uniqueid(e)) == NULL)
	{
		goto loser;
	}
	BER_DEBUG("s(uniqueid)");
	if (ber_printf(ber, "s", str) == -1)
	{
		goto loser;
	}

	/* Get the entry's DN */
	if ((sdn = slapi_entry_get_sdn((Slapi_Entry *)e)) == NULL) /* XXXggood had to cast away const */
	{
		goto loser;
	}
	if ((dnstr = slapi_sdn_get_dn(sdn)) == NULL)
	{
		goto loser;
	}
	BER_DEBUG("s(dn)");
	if (ber_printf(ber, "s", dnstr) == -1)
	{
		goto loser;
	}

	/* Next comes the annoted list of the entry's attributes */
	BER_DEBUG("[");
	if (ber_printf(ber, "[") == -1) /* Begin set of attributes */
	{
		goto loser;
	}
	/*
	 * We iterate over all of the non-deleted attributes first.
	 */ 
	slapi_entry_first_attr(e, &attr);
	while (NULL != attr)
	{
        /* ONREPL - skip uniqueid attribute since we already sent uniqueid 
           This is a hack; need to figure a better way of storing uniqueid
           in an entry */
        slapi_attr_get_type (attr, &type);
        if (strcasecmp (type, SLAPI_ATTR_UNIQUEID) != 0)
        {
			/* Check to see if this attribute is excluded by the fractional list */
			if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type)) 
			{
				/* Process this attribute */
				rc = my_ber_printf_attr (ber, attr, PR_FALSE);
				if (rc != 0)
				{
					goto loser;
				}
			}
        }
		
		prev_attr = attr;
		slapi_entry_next_attr(e, prev_attr, &attr);
	}

	/*
	 * Now iterate over the deleted attributes.
	 */ 
	entry_first_deleted_attribute(e, &attr);
	while (attr != NULL)
	{
		slapi_attr_get_type (attr, &type);
		/* Check to see if this attribute is excluded by the fractional list */
		if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type)) 
		{
			/* Process this attribute */
			rc = my_ber_printf_attr (ber, attr, PR_TRUE);
			if (rc != 0)
			{
				goto loser;
			}
		}
		entry_next_deleted_attribute(e, &attr);
	}
	BER_DEBUG("]");
	if (ber_printf(ber, "]") == -1) /* End set for attributes */
	{
		goto loser;
	}
	BER_DEBUG("}");
	if (ber_printf(ber, "}") == -1) /* End sequence for this entry */
	{
		goto loser;
	}
	
	/* If we get here, everything went ok */
	BER_DEBUG("\n");
	goto free_and_return;
loser:
	if (NULL != ber)
	{
		ber_free(ber, 1);
		ber = NULL;
	}

free_and_return:
	return ber;
}