The following example shows a code excerpt from the source file install-path/examples/testbind.c.
#include "slapi-plugin.h"
int
test_bind(Slapi_PBlock * pb)
{
char * dn; /* Target DN */
int method; /* Authentication method */
struct berval * credentials; /* Client SASL credentials */
Slapi_DN * sdn = NULL; /* DN used in internal srch */
char * attrs[2] = { /* Look at userPassword only */
SLAPI_USERPWD_ATTR,
NULL
};
Slapi_Entry * entry = NULL; /* Entry returned by srch */
Slapi_Attr * attr = NULL; /* Pwd attr in entry found */
int is_repl; /* Is this replication? */
int is_intl; /* Is this an internal op? */
int connId, opId, rc = 0;
long msgId;
/* Obtain the bind information from the parameter block. */
rc |= slapi_pblock_get(pb, SLAPI_BIND_TARGET, &dn);
rc |= slapi_pblock_get(pb, SLAPI_BIND_METHOD, &method);
rc |= slapi_pblock_get(pb, SLAPI_BIND_CREDENTIALS, &credentials);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);
rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId);
rc |= slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl);
rc |= slapi_pblock_get(pb, SLAPI_IS_INTERNAL_OPERATION, &is_intl);
if (rc != 0) {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
SLAPI_LOG_NO_MSGID,
SLAPI_LOG_NO_CONNID,
SLAPI_LOG_NO_OPID,
"test_bind in test-bind plug-in",
"Could not get parameters for bind operation (error %d).\n", rc
);
slapi_send_ldap_result(
pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL);
return (LDAP_OPERATIONS_ERROR);/* Server aborts bind here. */
}
/* The following code handles simple authentication, where a
* user offers a bind DN and a password for authentication.
*
* Handling simple authentication is a matter of finding the
* entry corresponding to the bind DN sent in the request,
* then if the entry is found, checking whether the password
* sent in the request matches a value found on the
* userPassword attribute of the entry. */
/* Avoid interfering with replication or internal operations. */
if (!is_repl && !is_intl) switch (method) {
case LDAP_AUTH_SIMPLE:
/* Find the entry specified by the bind DN... */
sdn = slapi_sdn_new_dn_byref(dn);
rc |= slapi_search_internal_get_entry(
sdn,
attrs,
&entry,
plugin_id
);
slapi_sdn_free(&sdn);
if (rc != 0 || entry == NULL) {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"test_bind in test-bind plug-in",
"Could not find entry: %s\n", dn
);
rc = LDAP_NO_SUCH_OBJECT;
slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
return (rc);
} else {
/* ...check credentials against the userpassword... */
Slapi_Value * credval; /* Value of credentials */
Slapi_ValueSet * pwvalues; /* Password attribute values */
rc |= slapi_entry_attr_find(
entry,
SLAPI_USERPWD_ATTR,
&attr
);
if (attr == NULL) {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"test_bind in test-bind plug-in",
"Entry %s has no userpassword.\n",
dn
);
rc = LDAP_INAPPROPRIATE_AUTH;
slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
return (rc);
}
rc |= slapi_attr_get_valueset(
attr,
&pwvalues
);
if (rc != 0 || slapi_valueset_count(pwvalues) == 0) {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"test_bind in test-bind plug-in",
"Entry %s has no %s attribute values.\n",
dn, SLAPI_USERPWD_ATTR
);
rc = LDAP_INAPPROPRIATE_AUTH;
slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
slapi_valueset_free(pwvalues);
return (rc);
}
credval = slapi_value_new_berval(credentials);
rc = slapi_pw_find_valueset(pwvalues, credval);
slapi_value_free(&credval);
slapi_valueset_free(pwvalues);
if (rc != 0) {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"test_bind in test-bind plug-in",
"Credentials are not correct.\n"
);
rc = LDAP_INVALID_CREDENTIALS;
slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
return (rc);
}
}
/* ...if successful, set authentication for the connection. */
if (rc != 0) return (rc);
rc |=slapi_pblock_set(pb, SLAPI_CONN_DN, slapi_ch_strdup(dn));
rc |=slapi_pblock_set(pb, SLAPI_CONN_AUTHMETHOD, SLAPD_AUTH_SIMPLE);
if (rc != 0) {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"test_bind in test-bind plug-in",
"Failed to set connection info.\n"
);
rc = LDAP_OPERATIONS_ERROR;
slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
return (rc);
} else {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"test_bind in test-bind plug-in",
"Authenticated: %s\n", dn
);
/* Now that authentication succeeded, the plug-in
* returns a value greater than 0, even though the
* authentication has been successful. A return
* code > 0 tells the server not to continue
* processing the bind. A return code of 0, such
* as LDAP_SUCCESS tells the server to continue
* processing the operation. */
slapi_send_ldap_result(
pb, LDAP_SUCCESS, NULL, NULL, 0, NULL);
rc = 1;
}
break;
/* This plug-in supports only simple authentication. */
case LDAP_AUTH_NONE:
/* Anonymous binds are handled by the front-end before
* pre-bind plug-in functions are called, so this
* part of the code should never be reached. */
case LDAP_AUTH_SASL:
default:
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"test_bind in test-bind plug-in",
"Plug-in does not handle auth. method: %d\n", method
);
rc = 0; /* Let server handle bind. */
break;
}
return (rc); /* Server stops processing
* the bind if rc > 0. */
}
The bulk of the code processes the LDAP_AUTH_SIMPLE case. In the simple authentication case, the plug-in uses the DN and the password to authenticate the user binding through plug-in API calls.