diff options
-rw-r--r-- | docs/conf/modules.conf.example | 8 | ||||
-rw-r--r-- | src/modules/extra/m_ldapauth.cpp | 53 |
2 files changed, 55 insertions, 6 deletions
diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 32217138a..e20769373 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -991,6 +991,8 @@ # # # <ldapwhitelist cidr="10.42.0.0/16"> # # # +# <ldaprequire attribute="attr" value="val"> # +# # # The baserdn indicates the base DN to search in for users. Usually # # this is 'ou=People,dc=yourdomain,dc=yourtld'. # # # @@ -1022,6 +1024,12 @@ # ldapwhitelist indicates that clients connecting from an IP in the # # provided CIDR do not need to authenticate against LDAP. It can be # # repeated to whitelist multiple CIDRs. # +# # +# ldaprequire allows further filtering on the LDAP user, by requiring # +# certain LDAP attibutes to have a given value. It can be repeated, # +# in which case the list will act as an OR list, that is, the # +# authentication will succeed if any of the requirements in the list # +# is satisfied. # #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # LDAP oper configuration module: Adds the ability to authenticate # diff --git a/src/modules/extra/m_ldapauth.cpp b/src/modules/extra/m_ldapauth.cpp index c4e937b9f..f404471ea 100644 --- a/src/modules/extra/m_ldapauth.cpp +++ b/src/modules/extra/m_ldapauth.cpp @@ -49,6 +49,7 @@ class ModuleLDAPAuth : public Module std::string username; std::string password; std::vector<std::string> whitelistedcidrs; + std::vector<std::pair<std::string, std::string> > requiredattributes; int searchscope; bool verbose; bool useusername; @@ -77,6 +78,7 @@ public: { ConfigReader Conf; whitelistedcidrs.clear(); + requiredattributes.clear(); base = Conf.ReadValue("ldapauth", "baserdn", 0); attribute = Conf.ReadValue("ldapauth", "attribute", 0); @@ -99,6 +101,17 @@ public: } } + ConfigTagList attributetags = ServerInstance->Config->ConfTags("ldaprequire"); + + for (ConfigIter i = attributetags.first; i != attributetags.second; ++i) + { + const std::string attr = i->second->getString("attribute"); + const std::string val = i->second->getString("value"); + + if (!attr.empty() && !val.empty()) + requiredattributes.push_back(make_pair(attr, val)); + } + if (scope == "base") searchscope = LDAP_SCOPE_BASE; else if (scope == "onelevel") @@ -242,19 +255,47 @@ public: } cred.bv_val = (char*)user->password.data(); cred.bv_len = user->password.length(); - if ((res = ldap_sasl_bind_s(conn, ldap_get_dn(conn, entry), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL)) == LDAP_SUCCESS) + if ((res = ldap_sasl_bind_s(conn, ldap_get_dn(conn, entry), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL)) != LDAP_SUCCESS) + { + if (verbose) + ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s!%s@%s (%s)", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), ldap_err2string(res)); + ldap_msgfree(msg); + return false; + } + + if (requiredattributes.empty()) { ldap_msgfree(msg); ldapAuthed.set(user,1); return true; } - else + + bool authed = false; + + for (std::vector<std::pair<std::string, std::string> >::const_iterator it = requiredattributes.begin(); it != requiredattributes.end(); ++it) { - if (verbose) - ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s!%s@%s (%s)", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), ldap_err2string(res)); - ldap_msgfree(msg); - return false; + const std::string &attr = it->first; + const std::string &val = it->second; + + struct berval attr_value; + attr_value.bv_val = const_cast<char*>(val.c_str()); + attr_value.bv_len = val.length(); + + ServerInstance->Logs->Log("m_ldapauth", DEBUG, "LDAP compare: %s=%s", attr.c_str(), val.c_str()); + + authed = (ldap_compare_ext_s(conn, ldap_get_dn(conn, entry), attr.c_str(), &attr_value, NULL, NULL) == LDAP_COMPARE_TRUE); + + if (authed) + break; } + + ldap_msgfree(msg); + + if (!authed) + return false; + + ldapAuthed.set(user,1); + return true; } ModResult OnCheckReady(LocalUser* user) |