+
+ if (!requiredattributes.empty())
+ {
+ bool authed = false;
+
+ for (std::vector<std::pair<std::string, std::string> >::const_iterator it = requiredattributes.begin(); it != requiredattributes.end(); ++it)
+ {
+ 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(MODNAME, LOG_DEBUG, "LDAP compare: %s=%s", attr.c_str(), val.c_str());
+
+ authed = (ldap_compare_ext_s(conn, DN, attr.c_str(), &attr_value, NULL, NULL) == LDAP_COMPARE_TRUE);
+
+ if (authed)
+ break;
+ }
+
+ if (!authed)
+ {
+ if (verbose)
+ ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (Lacks required LDAP attributes)", user->GetFullRealHost().c_str());
+ return false;
+ }
+ }
+
+ if (!vhost.empty())
+ {
+ irc::commasepstream stream(DN);
+
+ // mashed map of key:value parts of the DN
+ std::map<std::string, std::string> dnParts;
+
+ std::string dnPart;
+ while (stream.GetToken(dnPart))
+ {
+ std::string::size_type pos = dnPart.find('=');
+ if (pos == std::string::npos) // malformed
+ continue;
+
+ std::string key = dnPart.substr(0, pos);
+ std::string value = dnPart.substr(pos + 1, dnPart.length() - pos + 1); // +1s to skip the = itself
+ dnParts[key] = value;
+ }
+
+ // change host according to config key
+ ldapVhost.set(user, SafeReplace(vhost, dnParts));
+ }
+
+ ldapAuthed.set(user,1);
+ return true;