From eadecd41caf9a15b973f704ad77801507d68f961 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Thu, 14 Jan 2016 04:48:06 +0100 Subject: Add more documentation Add doxygen compatible comments to most functions. --- service_passwords.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 114 insertions(+), 10 deletions(-) diff --git a/service_passwords.c b/service_passwords.c index fdd4bbd..bf70770 100644 --- a/service_passwords.c +++ b/service_passwords.c @@ -9,7 +9,21 @@ extern int slapi_pw_find(struct berval **vals, struct berval *v); static Slapi_ComponentId *plugin_id = NULL; -/* Get an entry specified by a DN and with the specified attributes. */ +/** Get an entry specified by a DN and with the specified attributes. + * + * This functions get a entry specified by a \c DN. It's doing this with an + * internal search and limit the requested attributes to the requested + * values. The entry is written to an \c Slapi_Entry pointer. + * + * @param[in] dn \c DN of the requested entry. + * @param[in] attrs \c NULL terminated list of requested attributes. + * @param[out] entry Pointer to a pointer to \c Slapi_Entry to be filled with + * the entry. The caller is responsible to free the filled + * pointer with \c slapi_entry_free. + * @return + * * 0 on success + * * not 0 on error (maybe an ldap errno like \c LDAP_NO_SUCH_OBJECT) + */ static int get_entry(const char *dn, char **attrs, Slapi_Entry **entry) { Slapi_Entry **entries = NULL; @@ -59,7 +73,14 @@ static int get_entry(const char *dn, char **attrs, Slapi_Entry **entry) return rc; } -/* Check if the parent entry contains a uid attribute. */ +/** Check if the given DN contains a \c uid attribute. + * + * This function checks, if the entry specified by the DN contains a \c uid + * attribute and that this attribute is not empty. + * + * @param[in] dn DN of the entry. + * @return 0 if the \c uid attribute was found, 1 otherwise + */ static int dn_contains_uid(const char *dn) { char *attrs[] = { "uid", NULL }; @@ -96,7 +117,21 @@ fail1: return rc; } -static char* is_service_dn(const char *dn) +/** Check if the given DN is a service account. + * + * This function checks, if the given DN is a DN of a service account. All + * services have to do a bind on such a DN before a search so that this plugin + * can identify the service and rewrite the search results to the service + * specific password entries. + * + * @param[in] dn The DN to check (most times this should be the bound DN of the + * connection). + * @return If the DN is a service account, this function returns a zero + * terminated string with the name of the service, otherwise it simply + * returns a \c NULL pointer. The caller is responsible to free the + * returned string with \c slapi_ch_free_string. + */ +static char* is_service(const char *dn) { char *service = NULL; @@ -143,6 +178,22 @@ fail1: return service; } +/** Try to authenticate agains a specific DN with given credentials. + * + * This functions simply checks if the given credentials match the saved + * password in the \c userPassword attribute of the entry specified by the + * given DN. This function does nothing magic and use a slapi method to + * check the password and should support therefore all the password hashing + * schemes supported by the slapd. + * + * @param[in] dn The DN of the entry. + * @param[in] credentials A \c berval with the supplied password. + * + * @return + * * 0 is auth was successfull + * * -1 if the specified DN was not found + * * 1 in all other cases + */ static int auth(char *dn, struct berval *credentials) { char *attrs[] = { "userPassword", NULL }; @@ -181,6 +232,23 @@ fail1: return rc; } +/** Check if the supplied credentials match the stored password of a given entry + * or the parent entry (if the given entry does not exists). + * + * This function tries to check the supplied credentials against the + * \c userPassword attribute of the entry specified by the supplied DN. + * If the supplied DN does not exists, it will try to authenticate agains + * the direct parent of the specified DN. If the entry exists, but does not + * have a \c userPassword attribute or the attribute is empty, the + * authentication will fail. + * + * @param[in] dn The DN of the entry. + * @param[in] credentials A \c berval with the supplied password. + * + * @return + * * 0 if the authentication was successfull + * * 1 otherwise + */ static int auth_with_password_fallback(char *dn, struct berval *credentials) { char *parent_dn; @@ -215,6 +283,25 @@ static int auth_with_password_fallback(char *dn, struct berval *credentials) return 1; } +/** \c PRE_BIND plugin to allow password fallback. + * + * This function is called before a bind operation. If the BIND_DN is a user + * entry with a \c cn= prefix we try to authenticate against the + * service password entry or fallback to the user entry if the serice password + * does not exist. + * + * @param[in,out] pb Parameter block of the operation. + * @return + * * SLAPI_BIND_SUCCESS: \b CONFUSING! This does not force the bind to + * succeed. This simply means to continue the processing and handle the bind + * in the backend. + * * SLAPI_BIND_FAIL: This force the bind to fail and send + * LDAP_INVALID_CREDENTIALS back to the client. + * * All other values causes special handling. If no error is set and + * LDAP_CONN_DN in the pb is set to a value the bind succeed. Otherwise the + * bind will fail. But in both cases this method is responsible for sending + * the response to the client. + */ static int pre_bind(Slapi_PBlock *pb) { char *dn; @@ -248,7 +335,7 @@ static int pre_bind(Slapi_PBlock *pb) } if (is_replication || is_internal) { - return 0; + return SLAPI_BIND_SUCCESS; } if (method != LDAP_AUTH_SIMPLE) { @@ -258,7 +345,7 @@ static int pre_bind(Slapi_PBlock *pb) "(method %d).\n", method); - return 0; + return SLAPI_BIND_SUCCESS; } parent_dn = slapi_dn_parent(dn); @@ -267,7 +354,7 @@ static int pre_bind(Slapi_PBlock *pb) if (rc != 0) { /* parent_dn is not an user, so we ignore this bind request. */ - return 0; + return SLAPI_BIND_SUCCESS; } if (auth_with_password_fallback(dn, credentials) == 0) { @@ -290,11 +377,28 @@ static int pre_bind(Slapi_PBlock *pb) } /* auth fail */ - rc = LDAP_INVALID_CREDENTIALS; - slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL); - return rc; + return SLAPI_BIND_FAIL; } +/** \c PRE_ENTRY plugin to rewrite returned search results to keep the service + * name until bind. + * + * We want to have optional service specific password. Therefore we need to know + * the service during bind of the user. To keep this information, we add a + * simple (virtual) service prefix to the user DN. If a service search for + * users, it has to do a bind with a service account before. The service name is + * extracted from this bind and the dn of the found entries is extended to + * \c cn=,. During a bind the plugin can extract the service + * name and do magic stuff. + * + * This function is called for each search result entry before sending it back + * to the client and the result can be change by updating the parameter block. + * + * @param[in,out] pb Parameter block of the operation. + * @return + * * >= 0 send the result to the client and continue + * * < 0 do not send this result, but continue with the other results + */ static int pre_entry(Slapi_PBlock *pb) { char *bind_dn; @@ -345,7 +449,7 @@ static int pre_entry(Slapi_PBlock *pb) return 0; } - service = is_service_dn(bind_dn); + service = is_service(bind_dn); if (service == NULL) { goto fail1; } -- cgit v1.2.3-1-g7c22