Register the SASL mechanism by using the same function that registers the plug-in, slapi_register_supported_saslmechanism(). The following example shows the function that registers both the plug-in and the SASL mechanism.
#include "slapi-plugin.h" Slapi_PluginDesc saslpdesc = { "test-saslbind", /* plug-in identifier */ "Sun Microsystems, Inc.", /* vendor name */ "6.0", /* plug-in revision number */ "Sample SASL pre-bind plug-in" /* plug-in description */ }; #define TEST_MECHANISM "my_sasl_mechanism" #define TEST_AUTHMETHOD SLAPD_AUTH_SASL TEST_MECHANISM /* Register the plug-in with the server. */ #ifdef _WIN32 __declspec(dllexport) #endif int testsasl_init(Slapi_PBlock * pb) { int rc = 0; /* 0 means success */ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_CURRENT_VERSION ); rc |= slapi_pblock_set( /* Plug-in description */ pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &saslpdesc ); rc |= slapi_pblock_set( /* Pre-op bind SASL function */ pb, SLAPI_PLUGIN_PRE_BIND_FN, (void *) testsasl_bind ); /* Register the SASL mechanism. */ slapi_register_supported_saslmechanism(TEST_MECHANISM); return (rc); }
Refer to Part II, Directory Server Plug-In API Reference for details on using slapi_register_supported_saslmechanism().
The plug-in function testsasl_bind() first obtains the client DN, method, SASL mechanism, and credentials. If the client does not ask to use the TEST_MECHANISM, the function returns 0 so the server can process the bind. The following example shows how the processing is done.
#include "slapi-plugin.h" #define TEST_MECHANISM "my_sasl_mechanism" #define TEST_AUTHMETHOD SLAPD_AUTH_SASL TEST_MECHANISM int testsasl_bind(Slapi_PBlock * pb) { char * dn; /* Target DN */ int method; /* Authentication method */ char * mechanism; /* SASL mechanism */ struct berval * credentials; /* SASL client credentials */ struct berval svrcreds; /* SASL server credentials */ int connId, opId, rc = 0; long msgId; 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_BIND_SASLMECHANISM, &mechanism); 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); if (rc == 0) { if (mechanism == NULL || strcmp(mechanism, TEST_MECHANISM) != 0) return(rc); /* Client binding another way. */ } else { /* slapi_pblock_get() failed! */ return(rc); } /* Using the SASL mechanism that always succeeds, set conn. info. */ rc |= slapi_pblock_set(pb, SLAPI_CONN_DN, slapi_ch_strdup(dn)); rc |= slapi_pblock_set(pb, SLAPI_CONN_AUTHMETHOD, TEST_AUTHMETHOD); if (rc != 0) { /* Failed to set conn. info! */ slapi_log_info_ex( SLAPI_LOG_INFO_AREA_PLUGIN, SLAPI_LOG_INFO_LEVEL_DEFAULT, msgId, connId, opId, "testsasl_bind in test-saslbind plug-in", "slapi_pblock_set() for connection information failed.\n" ); slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL); return(LDAP_OPERATIONS_ERROR); /* Server tries other mechs. */ } /* Set server credentials. */ svrcreds.bv_val = "my credentials"; svrcreds.bv_len = sizeof("my credentials") - 1; rc |= slapi_pblock_set(pb, SLAPI_BIND_RET_SASLCREDS, &svrcreds); if (rc != 0) { /* Failed to set credentials! */ slapi_log_info_ex( SLAPI_LOG_INFO_AREA_PLUGIN, SLAPI_LOG_INFO_LEVEL_DEFAULT, msgId, connId, opId, "testsasl_bind in test-saslbind plug-in", "slapi_pblock_set() for server credentials failed.\n" ); rc |= slapi_pblock_set(pb, SLAPI_CONN_DN, NULL); rc |= slapi_pblock_set(pb, SLAPI_CONN_AUTHMETHOD, SLAPD_AUTH_NONE); return(LDAP_OPERATIONS_ERROR); /* Server tries other mechs. */ } /* Send credentials to client. */ slapi_log_info_ex( SLAPI_LOG_INFO_AREA_PLUGIN, SLAPI_LOG_INFO_LEVEL_DEFAULT, msgId, connId, opId, "testsasl_bind in test-saslbind plug-in", "Authenticated: %s\n", dn ); slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); return 1; /* Server stops processing the * bind if the plug-in returns * a value greater than 0. */ }
The preceding example sets the DN for the client connection and the authentication method, as Directory Server does for a bind. To set SLAPI_CONN_DN and SLAPI_CONN_AUTHMETHOD is the key step of the bind. Without these values in the parameter block, Directory Server handles the client request as if the bind were anonymous. Thus, the client is left with access rights that correspond to an anonymous bind. Next, according to the SASL model, Directory Server sends credentials to the client as shown.