From 09a9fac51c1625af84755900835bf6679881704f Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Sat, 19 Nov 2016 19:02:26 +0100 Subject: 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. --- service_passwords.c | 154 ++++++++++++++++++++++++++++++++++++++++------------ 1 file 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 + * * 0 on success + * * != 0 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) -- cgit v1.2.3-1-g7c22