diff options
author | Alexander Sulfrian <alexander@sulfrian.net> | 2016-11-19 21:47:59 +0100 |
---|---|---|
committer | Alexander Sulfrian <alexander@sulfrian.net> | 2016-11-19 21:47:59 +0100 |
commit | 5e69ecdbbaf06b0bb217b1e487291164dc7d2f3d (patch) | |
tree | 6b14804bb090770488f556a13d976697e8a87ed5 | |
parent | 304a6c51a98dc029f5067460f965b344984c76ee (diff) | |
parent | 09a9fac51c1625af84755900835bf6679881704f (diff) | |
download | ldap-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.c | 218 |
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) { |