summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2016-11-19 19:02:26 +0100
committerAlexander Sulfrian <alexander@sulfrian.net>2016-11-19 21:40:52 +0100
commit09a9fac51c1625af84755900835bf6679881704f (patch)
treecf3ae5aabfe504ffd7a881c5f2b92d2d54e1f297
parentcc6761cf1f424f27a03ee92275f26713b82942cd (diff)
downloadldap-plugin-09a9fac51c1625af84755900835bf6679881704f.tar.gz
ldap-plugin-09a9fac51c1625af84755900835bf6679881704f.tar.bz2
ldap-plugin-09a9fac51c1625af84755900835bf6679881704f.zip
pre_bind: Handle all binds and save extension data
The pre_bind method has to handle the binds for service accounts, too. This way it can save the service name and gold service status after a successful bind.
-rw-r--r--service_passwords.c154
1 files changed, 119 insertions, 35 deletions
diff --git a/service_passwords.c b/service_passwords.c
index 6be182f..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,51 +633,73 @@ 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 (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) {
- /* parent_dn is not an user, so we ignore this bind request. */
- return SLAPI_BIND_SUCCESS;
- }
+ 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);
+ service = get_virtual_service(dn);
- if (rc != 0) {
- /* Invalid service */
- return SLAPI_BIND_FAIL;
- }
+ service_dn = get_service_dn(service);
+ rc |= is_service(service_dn, NULL, &gold_service);
+ slapi_ch_free_string(&service_dn);
- 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");
+ "Invalid service '%s' in bind dn '%s'.\n",
+ service, dn);
+ rc = SLAPI_BIND_FAIL;
+ goto fail1;
+ }
- rc = LDAP_OPERATIONS_ERROR;
- slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
- return rc;
+ 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;
}
- /* auth done */
- slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL);
- return 1;
+ 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;
+ }
+ }
}
+ /* wrong password */
+ rc = SLAPI_BIND_FAIL;
+
+fail1:
+ slapi_ch_free_string(&service);
+
/* auth fail */
- return SLAPI_BIND_FAIL;
+ return rc;
}
/** \c POST_UNBIND plugin to reset the connection data after unbind.
@@ -965,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)