stringtok(parts, toLower(qname.toString()), ".");
for (auto i = parts.crbegin(); i != parts.crend(); i++) {
- dn = "dc=" + *i + "," + dn;
+ dn = "dc=" + d_pldap->escape(*i) + "," + dn;
}
SLOG(g_log << Logger::Debug << d_myname << " Search = basedn: " << dn + getArg("basedn") << ", filter: " << filter << ", qtype: " << qtype.toString() << endl,
return ldapGetError(d_ld, rc);
}
-const string PowerLDAP::escape(const string& str)
+// Escape sensitive characters according to the rules in RFC4514, section 2.4
+// and RFC4515, section 3.
+const std::string PowerLDAP::escape(const string& input)
{
- string a;
- string::const_iterator i;
- char tmp[4];
-
- for (i = str.begin(); i != str.end(); i++) {
- // RFC4515 3
- if ((unsigned char)*i == '*' || (unsigned char)*i == '(' || (unsigned char)*i == ')' || (unsigned char)*i == '\\' || (unsigned char)*i == '\0' || (unsigned char)*i > 127) {
- snprintf(tmp, sizeof(tmp), "\\%02x", (unsigned char)*i);
-
- a += tmp;
+ std::string out;
+ std::array<char, 1 + 3> hexbuf{};
+ auto length = input.length();
+
+ out.reserve(length);
+ for (decltype(length) pos = 0; pos < length; ++pos) {
+ uint8_t chr = static_cast<uint8_t>(input[pos]);
+ // Perform UTF-8 encoding of 8-bit values if needed
+ if (chr >= 0x80) {
+ ::snprintf(hexbuf.data(), hexbuf.size(), "\\%02X",
+ static_cast<uint8_t>(0xc0 | ((chr >> 6) & 0x3f)));
+ out.append(hexbuf.data());
+ ::snprintf(hexbuf.data(), hexbuf.size(), "\\%02X",
+ static_cast<uint8_t>(0x80 | (chr & 0x3f)));
+ out.append(hexbuf.data());
+ }
+ else {
+ bool escape4514{false};
+ bool escape4515{false};
+ // Characters which need escaping regardless of their position
+ switch (chr) {
+ case '"':
+ case '+':
+ case ',':
+ case ';':
+ case '<':
+ case '>':
+ escape4514 = true;
+ break;
+ case '*':
+ case '(':
+ case ')':
+ case '\\':
+ case '\0':
+ escape4515 = true;
+ break;
+ default:
+ break;
+ }
+ // Characters which need escaping if in first position
+ if (pos == 0) {
+ escape4514 |= chr == ' ' || chr == '#';
+ }
+ // Characters which need escaping if in last position
+ if (pos == length - 1) {
+ escape4514 |= chr == ' ';
+ }
+ if (escape4515) {
+ ::snprintf(hexbuf.data(), hexbuf.size(), "\\%02X", chr);
+ out.append(hexbuf.data());
+ }
+ else {
+ if (escape4514) {
+ out.append(1, '\\');
+ }
+ out.append(1, chr);
+ }
}
- else
- a += *i;
}
-
- return a;
+ return out;
}