Пример #1
0
ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request,
				       ldap_handle_t *conn, char const *identity,
				       char const *password, ldap_sasl *sasl,
				       char const **error, char **extra)
{
	ldap_rcode_t		status;
	int			ret = 0;
	int			msgid;
	char const		*mech;
	LDAPMessage		*result = NULL;
	rlm_ldap_sasl_ctx_t	sasl_ctx;		/* SASL defaults */

	memset(&sasl_ctx, 0, sizeof(sasl_ctx));

	sasl_ctx.inst = inst;
	sasl_ctx.request = request;
	sasl_ctx.identity = identity;
	sasl_ctx.password = password;

	ROPTIONAL(RDEBUG2, DEBUG2, "Starting SASL mech(s): %s", sasl->mech);
	do {
		ret = ldap_sasl_interactive_bind(conn->handle, NULL, sasl->mech,
						 NULL, NULL, LDAP_SASL_AUTOMATIC,
						 _sasl_interact, &sasl_ctx, result,
						 &mech, &msgid);
		ldap_msgfree(result);	/* We always need to free the old message */
		if (ret >= 0) ROPTIONAL(RDEBUG3, DEBUG3, "Continuing SASL mech %s...", mech);

		status = rlm_ldap_result(inst, conn, msgid, identity, &result, error, extra);
		/*
		 *	Write the servers response to the debug log
		 */
		if (((request && RDEBUG_ENABLED3) || DEBUG_ENABLED3) && result) {
			struct berval *srv_cred;

			if (ldap_parse_sasl_bind_result(conn->handle, result, &srv_cred, 0) == 0) {
				char *escaped;

				escaped = fr_aprints(request, srv_cred->bv_val, srv_cred->bv_len, '\0');
				ROPTIONAL(RDEBUG3, DEBUG3, "SASL response  : %s", escaped);

				talloc_free(escaped);
				ldap_memfree(srv_cred);
			}
		}
	} while (status == LDAP_PROC_CONTINUE);
	ldap_msgfree(result);

	return status;
}
Пример #2
0
int
_ldap_bind(LDAP *ld, ldap_conndata_t *info, char ppolicy, LDAPMessage *result, int *msgid) {
    int rc;
    LDAPControl **server_ctrls = NULL;
    LDAPControl *ppolicy_ctrl = NULL;
    struct berval passwd;

    DEBUG("_ldap_bind (ld:%p, info:%p, ppolicy:%d, result:%p, msgid:%d)",
            ld, info, ppolicy, result, *msgid);
    if (ppolicy == 1) {
        rc = ldap_create_passwordpolicy_control(ld, &ppolicy_ctrl);
        if (rc != LDAP_SUCCESS) return rc;

        server_ctrls = (LDAPControl **)malloc(sizeof(LDAPControl *) * (1 + 1));
        if (server_ctrls == NULL) return LDAP_NO_MEMORY;

        server_ctrls[0] = ppolicy_ctrl;
        server_ctrls[1] = NULL;
    }

    /* Mechanism is set, use SASL interactive bind. */
    if (strcmp(info->mech, "SIMPLE") != 0) {
        if (info->passwd == NULL) info->passwd = "";
        rc = ldap_sasl_interactive_bind(ld, info->binddn, info->mech, server_ctrls, NULL,
                LDAP_SASL_QUIET, sasl_interact, info, result, &(info->rmech), msgid);
    } else {
        if (info->passwd == NULL) {
            passwd.bv_len = 0;
        } else {
            passwd.bv_len = strlen(info->passwd);
        }
        passwd.bv_val = info->passwd;
        rc = ldap_sasl_bind(ld, info->binddn, LDAP_SASL_SIMPLE, &passwd, server_ctrls,
                NULL, msgid);
    }

    if (ppolicy_ctrl != NULL) ldap_control_free(ppolicy_ctrl);

    free(server_ctrls);
    ldap_msgfree(result);

    return rc;
}
Пример #3
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 )
{
	const char *rmech = NULL;
	LDAPMessage *result = NULL;
	int rc, msgid;

	do {
		rc = ldap_sasl_interactive_bind( ld, dn, mechs,
			serverControls, clientControls,
			flags, interact, defaults, result, &rmech, &msgid );

		ldap_msgfree( result );

		if ( rc != LDAP_SASL_BIND_IN_PROGRESS )
			break;

#ifdef LDAP_CONNECTIONLESS
		if (LDAP_IS_UDP(ld)) {
			break;
		}
#endif

		if ( ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1 || !result ) {
			return( ld->ld_errno );	/* ldap_result sets ld_errno */
		}
	} while ( rc == LDAP_SASL_BIND_IN_PROGRESS );

	return rc;
}
Пример #4
0
/** Initiate an LDAP interactive bind
 *
 * @param[in] inst rlm_ldap configuration.
 * @param[in] request Current request, this may be NULL, in which case all debug logging is done with radlog.
 * @param[in] conn to use. May change as this function calls functions which auto re-connect.
 * @param[in] identity of the user.
 * @param[in] password of the user.
 * @param[in] sasl mechanism to use for bind, and additional parameters.
 * @param[in] serverctrls Search controls to pass to the server.  May be NULL.
 * @param[in] clientctrls Search controls for ldap_sasl_interactive.  May be NULL.
 * @param[out] error message resulting from bind.
 * @param[out] extra information about the error.
 * @return One of the LDAP_PROC_* (#ldap_rcode_t) values.
 */
ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request,
				       ldap_handle_t *conn, char const *identity,
				       char const *password, ldap_sasl *sasl,
				       LDAPControl **serverctrls, LDAPControl **clientctrls,
				       char const **error, char **extra)
{
	ldap_rcode_t		status;
	int			ret = 0;
	int			msgid;
	char const		*mech;
	LDAPMessage		*result = NULL;
	rlm_ldap_sasl_ctx_t	sasl_ctx;		/* SASL defaults */

	LDAPControl		*our_serverctrls[LDAP_MAX_CONTROLS];
	LDAPControl		*our_clientctrls[LDAP_MAX_CONTROLS];

	rlm_ldap_control_merge(our_serverctrls, our_clientctrls,
			       sizeof(our_serverctrls) / sizeof(*our_serverctrls),
			       sizeof(our_clientctrls) / sizeof(*our_clientctrls),
			       conn, serverctrls, clientctrls);

	/* rlm_ldap_result may not be called */
	if (error) *error = NULL;
	if (extra) *extra = NULL;

	sasl_ctx.inst = inst;
	sasl_ctx.request = request;
	sasl_ctx.identity = identity;
	sasl_ctx.password = password;
	sasl_ctx.extra = sasl;

	MOD_ROPTIONAL(RDEBUG2, DEBUG2, "Starting SASL mech(s): %s", sasl->mech);
	for (;;) {
		ret = ldap_sasl_interactive_bind(conn->handle, NULL, sasl->mech,
						 our_serverctrls, our_clientctrls,
						 LDAP_SASL_AUTOMATIC,
						 _sasl_interact, &sasl_ctx, result,
						 &mech, &msgid);

		/*
		 *	If ldap_sasl_interactive_bind indicates it didn't want
		 *	to continue, then we're done.
		 *
		 *	Calling ldap_result here, results in a timeout in some
		 *	cases, so we need to figure out whether the bind was
		 *	successful without the help of ldap_result.
		 */
		if (ret != LDAP_SASL_BIND_IN_PROGRESS) {
			status = rlm_ldap_result(inst, conn, -1, identity, NULL, error, extra);
			break;		/* Old result gets freed on after exit */
		}

		ldap_msgfree(result);	/* We always need to free the old message */

		/*
		 *	If LDAP parse result indicates there was an error
		 *	then we're done.
		 */
		status = rlm_ldap_result(inst, conn, msgid, identity, &result, error, extra);
		switch (status) {
		case LDAP_PROC_SUCCESS:		/* ldap_sasl_interactive_bind should have indicated success */
		case LDAP_PROC_CONTINUE:
			break;

		default:
			goto done;
		}

		/*
		 *	...otherwise, the bind is still in progress.
		 */
		MOD_ROPTIONAL(RDEBUG3, DEBUG3, "Continuing SASL mech %s...", mech);

		/*
		 *	Write the servers response to the debug log
		 */
		if (((request && RDEBUG_ENABLED3) || DEBUG_ENABLED3) && result) {
			struct berval *srv_cred;

			if (ldap_parse_sasl_bind_result(conn->handle, result, &srv_cred, 0) == 0) {
				char *escaped;

				escaped = fr_asprint(request, srv_cred->bv_val, srv_cred->bv_len, '\0');
				MOD_ROPTIONAL(RDEBUG3, DEBUG3, "SASL response  : %s", escaped);

				talloc_free(escaped);
				ldap_memfree(srv_cred);
			}
		}
	}
done:
	ldap_msgfree(result);

	return status;
}