示例#1
0
int
LDAP_CALL
ldap_bind( LDAP *ld, const char *dn, const char *passwd, int authmethod )
{
    /*
     * The bind request looks like this:
     *	BindRequest ::= SEQUENCE {
     *		version		INTEGER,
     *		name		DistinguishedName,	 -- who
     *		authentication	CHOICE {
     *			simple		[0] OCTET STRING -- passwd
     *		}
     *	}
     * all wrapped up in an LDAPMessage sequence.
     */

    LDAPDebug( LDAP_DEBUG_TRACE, "ldap_bind\n", 0, 0, 0 );

    if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
        return( -1 );
    }

    switch ( authmethod ) {
    case LDAP_AUTH_SIMPLE:
        return( ldap_simple_bind( ld, dn, passwd ) );

    default:
        LDAP_SET_LDERRNO( ld, LDAP_AUTH_UNKNOWN, NULL, NULL );
        return( -1 );
    }
}
示例#2
0
/*
 * ldap_simple_bind - bind to the ldap server using simple
 * authentication.  The dn and password of the entry to which to bind are
 * supplied.  LDAP_SUCCESS is returned upon success, the ldap error code
 * otherwise.
 *
 * Example:
 *	ldap_simple_bind_s( ld, "cn=manager, o=university of michigan, c=us",
 *	    "secret" )
 */
int
LDAP_CALL
ldap_simple_bind_s( LDAP *ld, const char *dn, const char *passwd )
{
	int		msgid;
	LDAPMessage	*result;

	LDAPDebug( LDAP_DEBUG_TRACE, "ldap_simple_bind_s\n", 0, 0, 0 );

	if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
		return( LDAP_PARAM_ERROR );
	}

	if ( (msgid = ldap_simple_bind( ld, dn, passwd )) == -1 )
		return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );

	if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 )
		return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );

	return( ldap_result2error( ld, result, 1 ) );
}
示例#3
0
/*
 * ldap_simple_bind - bind to the ldap server using simple
 * authentication.  The dn and password of the entry to which to bind are
 * supplied.  LDAP_SUCCESS is returned upon success, the ldap error code
 * otherwise.
 *
 * Example:
 *	ldap_simple_bind_s( ld, "cn=manager, o=university of michigan, c=us",
 *	    "secret" )
 */
int
LDAP_CALL
ldap_simple_bind_s( LDAP *ld, const char *dn, const char *passwd )
{
	int		msgid;
	LDAPMessage	*result;

	LDAPDebug( LDAP_DEBUG_TRACE, "ldap_simple_bind_s\n", 0, 0, 0 );

	if ( NSLDAPI_VALID_LDAP_POINTER( ld ) &&
	    ( ld->ld_options & LDAP_BITOPT_RECONNECT ) != 0 ) {
		return( simple_bindifnot_s( ld, dn, passwd ));
	}

	if ( (msgid = ldap_simple_bind( ld, dn, passwd )) == -1 )
		return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );

	if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 )
		return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );

	return( ldap_result2error( ld, result, 1 ) );
}
示例#4
0
int
ldap_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *passwd, int authmethod )
{
	Debug( LDAP_DEBUG_TRACE, "ldap_bind\n", 0, 0, 0 );

	switch ( authmethod ) {
	case LDAP_AUTH_SIMPLE:
		return( ldap_simple_bind( ld, dn, passwd ) );

#ifdef HAVE_GSSAPI
	case LDAP_AUTH_NEGOTIATE:
		return( ldap_gssapi_bind_s( ld, dn, passwd) );
#endif

	case LDAP_AUTH_SASL:
		/* user must use ldap_sasl_bind */
		/* FALL-THRU */

	default:
		ld->ld_errno = LDAP_AUTH_UNKNOWN;
		return( -1 );
	}
}
示例#5
0
// wrapper for ldap_simple_bind()
//
NS_IMETHODIMP
nsLDAPOperation::SimpleBind(const nsACString& passwd)
{
    nsRefPtr<nsLDAPConnection> connection = mConnection;
    // There is a possibilty that mConnection can be cleared by another
    // thread. Grabbing a local reference to mConnection may avoid this.
    // See https://bugzilla.mozilla.org/show_bug.cgi?id=557928#c1
    nsresult rv;
    nsCAutoString bindName;
    PRInt32 originalMsgID = mMsgID;
    // Ugly hack alert:
    // the first time we get called with a passwd, remember it.
    // Then, if we get called again w/o a password, use the
    // saved one. Getting called again means we're trying to
    // fall back to VERSION2.
    // Since LDAP operations are thrown away when done, it won't stay
    // around in memory.
    if (!passwd.IsEmpty())
      mSavePassword = passwd;

    NS_PRECONDITION(mMessageListener != 0, "MessageListener not set");

    rv = connection->GetBindName(bindName);
    if (NS_FAILED(rv))
        return rv;

    PR_LOG(gLDAPLogModule, PR_LOG_DEBUG,
           ("nsLDAPOperation::SimpleBind(): called; bindName = '%s'; ",
            bindName.get()));

    // If this is a second try at binding, remove the operation from pending ops
    // because msg id has changed...
    if (originalMsgID)
      connection->RemovePendingOperation(originalMsgID);

    mMsgID = ldap_simple_bind(mConnectionHandle, bindName.get(),
                              PromiseFlatCString(mSavePassword).get());

    if (mMsgID == -1) {
      // XXX Should NS_ERROR_LDAP_SERVER_DOWN cause a rebind here?
      return TranslateLDAPErrorToNSError(ldap_get_lderrno(mConnectionHandle,
                                                          0, 0));
    }

    // make sure the connection knows where to call back once the messages
    // for this operation start coming in
    rv = connection->AddPendingOperation(mMsgID, this);
    switch (rv) {
    case NS_OK:
        break;

        // note that the return value of ldap_abandon_ext() is ignored, as
        // there's nothing useful to do with it

    case NS_ERROR_OUT_OF_MEMORY:
        (void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
        return NS_ERROR_OUT_OF_MEMORY;
        break;

    case NS_ERROR_UNEXPECTED:
    case NS_ERROR_ILLEGAL_VALUE:
    default:
        (void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
        return NS_ERROR_UNEXPECTED;
    }

    return NS_OK;
}
示例#6
0
static int
do_bind (LDAP * ldap_connection, int timelimit)
{
	int rc;
	int rv;
	struct timeval tv;
	LDAPMessage *result;

	/*
	 * set timelimit in ld for select() call in ldap_pvt_connect()
	 * function implemented in libldap2's os-ip.c
	 */
  	tv.tv_sec = timelimit;
  	tv.tv_usec = 0;

DBG2("do_bind(): bind DN=\"%s\" pass=\"%s\"",binddn,passwd);

  	/* LDAPv3 doesn't need bind at all,
  	 * nevertheless, if no binddn is given than bind anonymous */
 	if ( ! strncmp(binddn,"",1) ) {
 		rv = ldap_simple_bind(ldap_connection, NULL, NULL);
 	} else {
		rv = ldap_simple_bind(ldap_connection, binddn, passwd);
 	}

	if (rv < 0)
	{
DBG("do_bind: rv < 0");

#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER)
		if (ldap_get_option (ldap_connection, LDAP_OPT_ERROR_NUMBER, &rc) !=
            LDAP_SUCCESS)
		{
		  rc = LDAP_UNAVAILABLE;
		}
#else
		rc = ldap_connection->ld_errno;
#endif /* LDAP_OPT_ERROR_NUMBER */
		/* Notify if we failed. */
		DBG3("could not connect to LDAP server as %s - %d - %s",
		  binddn, rc, ldap_err2string (rc));

		return rc;
	}

	rc = ldap_result (ldap_connection, rv, 0, &tv, &result);
	if (rc > 0)
	{
DBG1("do_bind rc=%d", rc);
		/* debug ("<== do_bind"); */
		return ldap_result2error (ldap_connection, result, 1);
	}

	/* took too long */
	if (rc == 0)
	{
DBG("do_bind rc=0");

		ldap_abandon (ldap_connection, rv);
	}

DBG("do_bind return -1");
	return -1;
}
示例#7
0
/*
 * ldap_sasl_interactive_bind_s - interactive SASL authentication
 *
 * This routine uses interactive callbacks.
 *
 * LDAP_SUCCESS is returned upon success, the ldap error code
 * otherwise.
 */
int
ldap_sasl_interactive_bind_s(
	LDAP *ld,
	LDAP_CONST char *dn, /* usually NULL */
	LDAP_CONST char *mechs,
	LDAPControl **serverControls,
	LDAPControl **clientControls,
	unsigned flags,
	LDAP_SASL_INTERACT_PROC *interact,
	void *defaults )
{
	int rc;

#if defined( LDAP_R_COMPILE ) && defined( HAVE_CYRUS_SASL )
	ldap_pvt_thread_mutex_lock( &ldap_int_sasl_mutex );
#endif
#ifdef LDAP_CONNECTIONLESS
	if( LDAP_IS_UDP(ld) ) {
		/* Just force it to simple bind, silly to make the user
		 * ask all the time. No, we don't ever actually bind, but I'll
		 * let the final bind handler take care of saving the cdn.
		 */
		rc = ldap_simple_bind(ld, dn, NULL);
		return rc < 0 ? rc : 0;
	} else
#endif
	if( mechs == NULL || *mechs == '\0' ) {
		char *smechs;

		rc = ldap_pvt_sasl_getmechs( ld, &smechs );

		if( rc != LDAP_SUCCESS ) {
			goto done;
		}

#ifdef NEW_LOGGING
		LDAP_LOG ( TRANSPORT, DETAIL1, 
			"ldap_interactive_sasl_bind_s: server supports: %s\n", 
			smechs, 0, 0 );
#else
		Debug( LDAP_DEBUG_TRACE,
			"ldap_interactive_sasl_bind_s: server supports: %s\n",
			smechs, 0, 0 );
#endif

		mechs = smechs;

	} else {
#ifdef NEW_LOGGING
		LDAP_LOG ( TRANSPORT, DETAIL1, 
			"ldap_interactive_sasl_bind_s: user selected: %s\n", mechs, 0, 0 );
#else
		Debug( LDAP_DEBUG_TRACE,
			"ldap_interactive_sasl_bind_s: user selected: %s\n",
			mechs, 0, 0 );
#endif
	}

	rc = ldap_int_sasl_bind( ld, dn, mechs,
		serverControls, clientControls,
		flags, interact, defaults );

done:
#if defined( LDAP_R_COMPILE ) && defined( HAVE_CYRUS_SASL )
	ldap_pvt_thread_mutex_unlock( &ldap_int_sasl_mutex );
#endif

	return rc;
}
示例#8
0
/*
 * ldap_sasl_interactive_bind - interactive SASL authentication
 *
 * This routine uses interactive callbacks.
 *
 * LDAP_SUCCESS is returned upon success, the ldap error code
 * otherwise. LDAP_SASL_BIND_IN_PROGRESS is returned if further
 * calls are needed.
 */
int
ldap_sasl_interactive_bind(
	LDAP *ld,
	LDAP_CONST char *dn, /* usually NULL */
	LDAP_CONST char *mechs,
	LDAPControl **serverControls,
	LDAPControl **clientControls,
	unsigned flags,
	LDAP_SASL_INTERACT_PROC *interact,
	void *defaults,
	LDAPMessage *result,
	const char **rmech,
	int *msgid )
{
	char *smechs = NULL;
	int rc;

#if defined( HAVE_CYRUS_SASL )
	LDAP_MUTEX_LOCK( &ldap_int_sasl_mutex );
#endif
#ifdef LDAP_CONNECTIONLESS
	if( LDAP_IS_UDP(ld) ) {
		/* Just force it to simple bind, silly to make the user
		 * ask all the time. No, we don't ever actually bind, but I'll
		 * let the final bind handler take care of saving the cdn.
		 */
		rc = ldap_simple_bind( ld, dn, NULL );
		rc = rc < 0 ? rc : 0;
		goto done;
	} else
#endif

	/* First time */
	if ( !result ) {

#ifdef HAVE_CYRUS_SASL
	if( mechs == NULL || *mechs == '\0' ) {
		mechs = ld->ld_options.ldo_def_sasl_mech;
	}
#endif
		
	if( mechs == NULL || *mechs == '\0' ) {
		/* FIXME: this needs to be asynchronous too;
		 * perhaps NULL should be disallowed for async usage?
		 */
		rc = ldap_pvt_sasl_getmechs( ld, &smechs );
		if( rc != LDAP_SUCCESS ) {
			goto done;
		}

		Debug( LDAP_DEBUG_TRACE,
			"ldap_sasl_interactive_bind: server supports: %s\n",
			smechs, 0, 0 );

		mechs = smechs;

	} else {
		Debug( LDAP_DEBUG_TRACE,
			"ldap_sasl_interactive_bind: user selected: %s\n",
			mechs, 0, 0 );
	}
	}
	rc = ldap_int_sasl_bind( ld, dn, mechs,
		serverControls, clientControls,
		flags, interact, defaults, result, rmech, msgid );

done:
#if defined( HAVE_CYRUS_SASL )
	LDAP_MUTEX_UNLOCK( &ldap_int_sasl_mutex );
#endif
	if ( smechs ) LDAP_FREE( smechs );

	return rc;
}
示例#9
0
文件: ldaptest.c 项目: tjyang/cpam
void run_ldap_tests(service_t *ldaptest, int sslcertcheck, int querytimeout)
{
#ifdef HAVE_LDAP
	ldap_data_t *req;
	testitem_t *t;
	struct timespec starttime;
	struct timespec endtime;

	/* Pick a sensible default for the timeout setting */
	if (querytimeout == 0) querytimeout = 30;

	for (t = ldaptest->items; (t); t = t->next) {
		LDAPURLDesc	*ludp;
		LDAP		*ld;
		int		rc, finished;
		int		msgID = -1;
		struct timeval	ldaptimeout;
		struct timeval	openldaptimeout;
		LDAPMessage	*result;
		LDAPMessage	*e;
		strbuffer_t	*response;
		char		buf[MAX_LINE_LEN];

		req = (ldap_data_t *) t->privdata;
		if (req->skiptest) continue;

		ludp = (LDAPURLDesc *) req->ldapdesc;

		getntimer(&starttime);

		/* Initiate session with the LDAP server */
		dbgprintf("Initiating LDAP session for host %s port %d\n",
			ludp->lud_host, ludp->lud_port);

		if( (ld = ldap_init(ludp->lud_host, ludp->lud_port)) == NULL ) {
			dbgprintf("ldap_init failed\n");
			req->ldapstatus = XYMON_LDAP_INITFAIL;
			continue;
		}

		/* 
		 * There is apparently no standard way of defining a network
		 * timeout for the initial connection setup. 
		 */
#if (LDAP_VENDOR == OpenLDAP) && defined(LDAP_OPT_NETWORK_TIMEOUT)
		/* 
		 * OpenLDAP has an undocumented ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv)
		 */
		openldaptimeout.tv_sec = querytimeout;
		openldaptimeout.tv_usec = 0;
		ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &openldaptimeout);
#else
		/*
		 * So using an alarm() to interrupt any pending operations
		 * seems to be the least insane way of doing this.
		 *
		 * Note that we must do this right after ldap_init(), as
		 * any operation on the session handle (ld) may trigger the
		 * network connection to be established.
		 */
		connect_timeout = 0;
		signal(SIGALRM, ldap_alarmhandler);
		alarm(querytimeout);
#endif

		/*
		 * This is completely undocumented in the OpenLDAP docs.
		 * But apparently it is documented in 
		 * http://www.ietf.org/proceedings/99jul/I-D/draft-ietf-ldapext-ldap-c-api-03.txt
		 *
		 * Both of these routines appear in the <ldap.h> file 
		 * from OpenLDAP 2.1.22. Their use to enable TLS has
		 * been deciphered from the ldapsearch() utility
		 * sourcecode.
		 *
		 * According to Manon Goo <*****@*****.**>, recent (Jan. 2005)
		 * OpenLDAP implementations refuse to talk LDAPv2.
		 */
#ifdef LDAP_OPT_PROTOCOL_VERSION 
		{
			int protocol = LDAP_VERSION3;

			dbgprintf("Attempting to select LDAPv3\n");
			if ((rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) {
				dbgprintf("Failed to select LDAPv3, trying LDAPv2\n");
				protocol = LDAP_VERSION2;
				if ((rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) {
					req->output = strdup(ldap_err2string(rc));
					req->ldapstatus = XYMON_LDAP_TLSFAIL;
				}
				continue;
			}
		}
#endif

		if (req->usetls) {
			dbgprintf("Trying to enable TLS for session\n");
			if ((rc = ldap_start_tls_s(ld, NULL, NULL)) != LDAP_SUCCESS) {
				dbgprintf("ldap_start_tls failed\n");
				req->output = strdup(ldap_err2string(rc));
				req->ldapstatus = XYMON_LDAP_TLSFAIL;
				continue;
			}
		}

		if (!connect_timeout) {
			msgID = ldap_simple_bind(ld, (t->host->ldapuser ? t->host->ldapuser : ""), 
					 (t->host->ldappasswd ? t->host->ldappasswd : ""));
		}

		/* Cancel any pending alarms */
		alarm(0);
		signal(SIGALRM, SIG_DFL);

		/* Did we connect? */
		if (connect_timeout || (msgID == -1)) {
			req->ldapstatus = XYMON_LDAP_BINDFAIL;
			req->output = "Cannot connect to server";
			continue;
		}

		/* Wait for bind to complete */
		rc = 0; finished = 0; 
		ldaptimeout.tv_sec = querytimeout;
		ldaptimeout.tv_usec = 0L;
		while( ! finished ) {
			int rc2;

			rc = ldap_result(ld, msgID, LDAP_MSG_ONE, &ldaptimeout, &result);
			dbgprintf("ldap_result returned %d for ldap_simple_bind()\n", rc);
			if(rc == -1) {
				finished = 1;
				req->ldapstatus = XYMON_LDAP_BINDFAIL;

				if (result == NULL) {
					errprintf("LDAP library problem - NULL result returned\n");
					req->output = strdup("LDAP BIND failed\n");
				}
				else {
					rc2 = ldap_result2error(ld, result, 1);
					req->output = strdup(ldap_err2string(rc2));
				}
				ldap_unbind(ld);
			}
			else if (rc == 0) {
				finished = 1;
				req->ldapstatus = XYMON_LDAP_BINDFAIL;
				req->output = strdup("Connection timeout");
				ldap_unbind(ld);
			}
			else if( rc > 0 ) {
				finished = 1;
				if (result == NULL) {
					errprintf("LDAP library problem - got a NULL resultcode for status %d\n", rc);
					req->ldapstatus = XYMON_LDAP_BINDFAIL;
					req->output = strdup("LDAP library problem: ldap_result2error returned a NULL result for status %d\n");
					ldap_unbind(ld);
				}
				else {
					rc2 = ldap_result2error(ld, result, 1);
					if(rc2 != LDAP_SUCCESS) {
						req->ldapstatus = XYMON_LDAP_BINDFAIL;
						req->output = strdup(ldap_err2string(rc));
						ldap_unbind(ld);
					}
				}
			}
		} /* ... while() */

		/* We're done connecting. If something went wrong, go to next query. */
		if (req->ldapstatus != 0) continue;

		/* Now do the search. With a timeout */
		ldaptimeout.tv_sec = querytimeout;
		ldaptimeout.tv_usec = 0L;
		rc = ldap_search_st(ld, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0, &ldaptimeout, &result);

		if(rc == LDAP_TIMEOUT) {
			req->ldapstatus = XYMON_LDAP_TIMEOUT;
			req->output = strdup(ldap_err2string(rc));
	  		ldap_unbind(ld);
			continue;
		}
		if( rc != LDAP_SUCCESS ) {
			req->ldapstatus = XYMON_LDAP_SEARCHFAILED;
			req->output = strdup(ldap_err2string(rc));
	  		ldap_unbind(ld);
			continue;
		}

		getntimer(&endtime);

		response = newstrbuffer(0);
		sprintf(buf, "Searching LDAP for %s yields %d results:\n\n", 
			t->testspec, ldap_count_entries(ld, result));
		addtobuffer(response, buf);

		for(e = ldap_first_entry(ld, result); (e != NULL); e = ldap_next_entry(ld, e) ) {
			char 		*dn;
			BerElement	*ber;
			char		*attribute;
			char		**vals;

			dn = ldap_get_dn(ld, e);
			sprintf(buf, "DN: %s\n", dn); 
			addtobuffer(response, buf);

			/* Addtributes and values */
			for (attribute = ldap_first_attribute(ld, e, &ber); (attribute != NULL); attribute = ldap_next_attribute(ld, e, ber) ) {
				if ((vals = ldap_get_values(ld, e, attribute)) != NULL) {
					int i;

					for(i = 0; (vals[i] != NULL); i++) {
						sprintf(buf, "\t%s: %s\n", attribute, vals[i]);
						addtobuffer(response, buf);
					}
				}
				/* Free memory used to store values */
				ldap_value_free(vals);
			}

			/* Free memory used to store attribute */
			ldap_memfree(attribute);
			ldap_memfree(dn);
			if (ber != NULL) ber_free(ber, 0);

			addtobuffer(response, "\n");
		}
		req->ldapstatus = XYMON_LDAP_OK;
		req->output = grabstrbuffer(response);
		tvdiff(&starttime, &endtime, &req->duration);

		ldap_msgfree(result);
		ldap_unbind(ld);
		ldap_free_urldesc(ludp);
	}
#endif
}