summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2016-11-19 21:47:59 +0100
committerAlexander Sulfrian <alexander@sulfrian.net>2016-11-19 21:47:59 +0100
commit5e69ecdbbaf06b0bb217b1e487291164dc7d2f3d (patch)
tree6b14804bb090770488f556a13d976697e8a87ed5
parent304a6c51a98dc029f5067460f965b344984c76ee (diff)
parent09a9fac51c1625af84755900835bf6679881704f (diff)
downloadldap-plugin-5e69ecdbbaf06b0bb217b1e487291164dc7d2f3d.tar.gz
ldap-plugin-5e69ecdbbaf06b0bb217b1e487291164dc7d2f3d.tar.bz2
ldap-plugin-5e69ecdbbaf06b0bb217b1e487291164dc7d2f3d.zip
Merge branch 'master' into debian
* master: pre_bind: Handle all binds and save extension data POST_BIND: Remove hook.
-rw-r--r--service_passwords.c218
1 files changed, 107 insertions, 111 deletions
diff --git a/service_passwords.c b/service_passwords.c
index 1f27600..5aaed65 100644
--- a/service_passwords.c
+++ b/service_passwords.c
@@ -503,6 +503,68 @@ static char *get_service_dn(const char *service)
return new_dn;
}
+
+/** Save the information from a successful bind in the connection data.
+ *
+ * This method saves the verified data after a bind into the connection
+ * structure. The bind dn is set as the connection dn and the service name
+ * and the gold status is saved into the extension object of the connection
+ * data.
+ *
+ * The method directly stores the pointer to the service name in the
+ * extension data, so that the caller should not be free it anymore after a
+ * successful call to this method. Instead the destructor of the extension
+ * data (or the \c POST_UNBIND hook) will take care of the memory.
+ *
+ * @param[in,out] pb Parameter block of the operation.
+ * @param[in] dn The bind dn.
+ * @param[in] service_name The service name found in the bind dn. (The pointer
+ * is saved inside the extensions data, so that the caller
+ * should not free the memory.)
+ * @param[in] gold_service Whether the service (found in the bind dn) is a
+ * gold service.
+ * @return
+ * * <tt>0</tt> on success
+ * * <tt>!= 0</tt> in case of any error
+ */
+static int save_connection_info(Slapi_PBlock *pb, char *dn, char *service_name, int gold_service)
+{
+ Slapi_Connection *conn;
+
+ private_connection_data *conn_ext;
+
+ int rc = 0;
+ char fn[] = "save_connection_info in service_passwords plug-in";
+
+ rc |= slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
+ rc |= slapi_pblock_set(pb, SLAPI_CONN_DN, dn);
+ if (rc != 0) {
+ slapi_log_error(
+ SLAPI_LOG_PLUGIN, fn,
+ "Failed to get/set connection info.\n");
+ return -1;
+ }
+
+ /* set the connection private data */
+ conn_ext = (private_connection_data*)slapi_get_object_extension(
+ private.conn_ext.obj_type, conn, private.conn_ext.handle);
+ if (conn_ext == NULL) {
+ slapi_log_error(
+ SLAPI_LOG_PLUGIN, fn,
+ "Failed to get connection private data.\n");
+ return -1;
+ }
+
+ conn_ext->gold_service = gold_service;
+ conn_ext->service_name = service_name;
+ slapi_log_error(
+ SLAPI_LOG_PLUGIN, fn,
+ "Setting connection data: %d %s.\n",
+ gold_service, service_name);
+
+ return 0;
+}
+
/** \c PRE_BIND plugin to allow password fallback.
*
* This function is called before a bind operation. If the BIND_DN is a user
@@ -571,104 +633,17 @@ static int pre_bind(Slapi_PBlock *pb)
return SLAPI_BIND_SUCCESS;
}
- parent_dn = slapi_dn_parent(dn);
- rc |= is_user(parent_dn, &gold_account);
- slapi_ch_free_string(&parent_dn);
-
- if (rc != 0) {
- /* parent_dn is not an user, so we ignore this bind request. */
- return SLAPI_BIND_SUCCESS;
- }
-
- service = get_virtual_service(dn);
- service_dn = get_service_dn(service);
- rc |= is_service(service_dn, NULL, &gold_service);
- slapi_ch_free_string(&service_dn);
- slapi_ch_free_string(&service);
-
- if (rc != 0) {
- /* Invalid service */
- return SLAPI_BIND_FAIL;
- }
-
- if (gold_service != 0 && gold_account == 0) {
- /* This is a bind for a gold_service, but it's not a gold account. */
- return SLAPI_BIND_FAIL;
- }
-
- if (auth_with_password_fallback(dn, credentials) == 0) {
- /* auth success: set connection info */
- rc |= slapi_pblock_set(pb, SLAPI_CONN_DN, dn);
- if (rc != 0) {
- slapi_log_error(
- SLAPI_LOG_PLUGIN, fn,
- "Failed to set connection info.\n");
-
- rc = LDAP_OPERATIONS_ERROR;
- slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
- return rc;
- }
-
- /* auth done */
- slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL);
- return 1;
- }
-
- /* auth fail */
- return SLAPI_BIND_FAIL;
-}
-
-/** \c POST_BIND plugin to save the extra connection data after bind.
- *
- * This method is called after a bind operation and try to detect if the
- * \c BIND_DN contains a service name. The \c BIND_DN either be a service dn or
- * a virtual service entry of a user. If it is a virtual entry of the user, than
- * the service prefix is used to build the service dn.
- *
- * If the service dn is found, the method checks whether that entry is a gold
- * service or not. The service name and the gold service status is saved in the
- * private connection extension data, so that it can be used by the other
- * methods of this plugin.
- *
- * @param[in,out] pb Parameter block of the operation.
- * @return
- * * <tt>0</tt> on success
- * * <tt>!= 0</tt> in case of error
- */
-static int post_bind(Slapi_PBlock *pb)
-{
- Slapi_Connection *conn;
- char *bind_dn;
-
- private_connection_data *conn_ext = NULL;
- int gold_service = 0;
- char *service = NULL;
- char *service_dn = NULL;
- char *parent_dn = NULL;
-
- int rc = 0;
- char fn[] = "post_bind in service_passwords plug-in";
-
- rc |= slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
- rc |= slapi_pblock_get(pb, SLAPI_CONN_DN, &bind_dn);
-
- if (rc != 0) {
- slapi_log_error(
- SLAPI_LOG_PLUGIN, fn,
- "Could not get parameters (error %d).\n", rc);
- return rc;
- }
-
- if (is_service(bind_dn, &service, &gold_service) != 0) {
- parent_dn = slapi_dn_parent(bind_dn);
+ if (is_service(dn, &service, &gold_service) != 0) {
+ parent_dn = slapi_dn_parent(dn);
rc |= is_user(parent_dn, NULL);
slapi_ch_free_string(&parent_dn);
if (rc != 0) {
- return 0;
+ /* parent_dn is not an user, so we ignore this bind request. */
+ return SLAPI_BIND_SUCCESS;
}
- service = get_virtual_service(bind_dn);
+ service = get_virtual_service(dn);
service_dn = get_service_dn(service);
rc |= is_service(service_dn, NULL, &gold_service);
@@ -678,33 +653,55 @@ static int post_bind(Slapi_PBlock *pb)
slapi_log_error(
SLAPI_LOG_PLUGIN, fn,
"Invalid service '%s' in bind dn '%s'.\n",
- service, bind_dn);
+ service, dn);
+ rc = SLAPI_BIND_FAIL;
goto fail1;
}
- }
- /* set the connection private data */
- conn_ext = (private_connection_data*)slapi_get_object_extension(
- private.conn_ext.obj_type, conn, private.conn_ext.handle);
- if (conn_ext == NULL) {
- slapi_log_error(
- SLAPI_LOG_PLUGIN, fn,
- "Failed to get connection private data.\n");
+ if (gold_service != 0 && gold_account == 0) {
+ /* This is a bind for a gold_service, but it's not a gold account. */
+ rc = SLAPI_BIND_FAIL;
+ goto fail1;
+ }
- rc = LDAP_OPERATIONS_ERROR;
- goto fail1;
+ if (auth_with_password_fallback(dn, credentials) == 0) {
+ /* auth success: set connection info */
+ if (save_connection_info(pb, dn, service, gold_service) == 0) {
+ slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL);
+ return 1;
+ }
+ else {
+ rc = LDAP_OPERATIONS_ERROR;
+ slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
+ goto fail1;
+ }
+ }
+ }
+ else {
+ /* service: simple auth, no fallback */
+ if (auth(dn, credentials) == 0) {
+ if (save_connection_info(pb, dn, service, gold_service) == 0) {
+ slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL);
+ return 1;
+ }
+ else {
+ rc = LDAP_OPERATIONS_ERROR;
+ slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
+ goto fail1;
+ }
+ }
}
- conn_ext->gold_service = gold_service;
- conn_ext->service_name = service;
- return 0;
+ /* wrong password */
+ rc = SLAPI_BIND_FAIL;
fail1:
slapi_ch_free_string(&service);
+
+ /* auth fail */
return rc;
}
-
/** \c POST_UNBIND plugin to reset the connection data after unbind.
*
* @param[in,out] pb Parameter block of the operation.
@@ -1052,9 +1049,9 @@ void free_connection_data(void *extension,
Slapi_PluginDesc bindpdesc = {
.spd_id = "service_passwords",
.spd_vendor = "spline",
- .spd_version = "0.3",
- .spd_description = "preoperation plugin "
- "to authenticate a bind against different passwords"
+ .spd_version = "0.4",
+ .spd_description = "plugin to authenticate a bind "
+ "against different passwords"
};
int service_passwords_init(Slapi_PBlock *pb)
@@ -1076,7 +1073,6 @@ int service_passwords_init(Slapi_PBlock *pb)
rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_BIND_FN, (void *) pre_bind);
rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ENTRY_FN, (void *) pre_entry);
rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_SEARCH_FN, (void *) pre_search);
- rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_BIND_FN, (void *) post_bind);
rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_UNBIND_FN, (void *) post_unbind);
rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &private.plugin_id);
if (rc != 0) {