Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame^] | 1 | From 01a44c96dbd04936e9cb2501745a834a0b09d504 Mon Sep 17 00:00:00 2001 |
| 2 | From: Amos Jeffries <yadij@users.noreply.github.com> |
| 3 | Date: Sun, 13 May 2018 06:57:41 +0000 |
| 4 | Subject: [PATCH] Bug 4843 pt1: ext_edirectory_userip_acl refactoring for GCC-8 |
| 5 | (#204) |
| 6 | |
| 7 | Proposed changes to this helper to fix strcat / strncat buffer |
| 8 | overread / overflow issues. |
| 9 | |
| 10 | The approach takes three parts: |
| 11 | |
| 12 | * adds a makeHexString function to replace many for-loops |
| 13 | catenating bits of strings together with hex conversion into a |
| 14 | second buffer. Replacing with a snprintf() and buffer overflow |
| 15 | handling. |
| 16 | |
| 17 | * a copy of Ip::Address::lookupHostIp to convert the input |
| 18 | string into IP address binary format, then generate the hex |
| 19 | string using the above new hex function instead of looped |
| 20 | sub-string concatenations across several buffers. |
| 21 | This removes all the "00" and "0000" strncat() calls and |
| 22 | allows far simpler code even with added buffer overflow |
| 23 | handling. |
| 24 | |
| 25 | * replace multiple string part concatenations with a few simpler |
| 26 | calls to snprintf() for all the search_ip buffer constructions. |
| 27 | Adding buffer overflow handling as needed for the new calls. |
| 28 | --- |
| 29 | Signed-off-by: Khem Raj <raj.khem@gmail.com> |
| 30 | Upstream-Status: Backport |
| 31 | |
| 32 | .../ext_edirectory_userip_acl.cc | 376 ++++++------------ |
| 33 | 1 file changed, 120 insertions(+), 256 deletions(-) |
| 34 | |
| 35 | diff --git a/helpers/external_acl/eDirectory_userip/ext_edirectory_userip_acl.cc b/helpers/external_acl/eDirectory_userip/ext_edirectory_userip_acl.cc |
| 36 | index 63609e4..ad16bfd 100644 |
| 37 | --- a/helpers/external_acl/eDirectory_userip/ext_edirectory_userip_acl.cc |
| 38 | +++ b/helpers/external_acl/eDirectory_userip/ext_edirectory_userip_acl.cc |
| 39 | @@ -67,6 +67,9 @@ |
| 40 | #ifdef HAVE_LDAP_H |
| 41 | #include <ldap.h> |
| 42 | #endif |
| 43 | +#ifdef HAVE_NETDB_H |
| 44 | +#include <netdb.h> |
| 45 | +#endif |
| 46 | |
| 47 | #ifdef HELPER_INPUT_BUFFER |
| 48 | #define EDUI_MAXLEN HELPER_INPUT_BUFFER |
| 49 | @@ -714,11 +717,14 @@ BindLDAP(edui_ldap_t *l, char *dn, char *pw, unsigned int t) |
| 50 | |
| 51 | /* Copy details - dn and pw CAN be NULL for anonymous and/or TLS */ |
| 52 | if (dn != NULL) { |
| 53 | + if (strlen(dn) >= sizeof(l->dn)) |
| 54 | + return LDAP_ERR_OOB; /* DN too large */ |
| 55 | + |
| 56 | if ((l->basedn[0] != '\0') && (strstr(dn, l->basedn) == NULL)) { |
| 57 | /* We got a basedn, but it's not part of dn */ |
| 58 | - xstrncpy(l->dn, dn, sizeof(l->dn)); |
| 59 | - strncat(l->dn, ",", 1); |
| 60 | - strncat(l->dn, l->basedn, strlen(l->basedn)); |
| 61 | + const int x = snprintf(l->dn, sizeof(l->dn)-1, "%s,%s", dn, l->basedn); |
| 62 | + if (x < 0 || static_cast<size_t>(x) >= sizeof(l->dn)) |
| 63 | + return LDAP_ERR_OOB; /* DN too large */ |
| 64 | } else |
| 65 | xstrncpy(l->dn, dn, sizeof(l->dn)); |
| 66 | } |
| 67 | @@ -778,24 +784,73 @@ BindLDAP(edui_ldap_t *l, char *dn, char *pw, unsigned int t) |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | +// XXX: duplicate (partial) of Ip::Address::lookupHostIp |
| 72 | +/** |
| 73 | + * Convert the IP address string representation in src to |
| 74 | + * its binary representation. |
| 75 | + * |
| 76 | + * \return binary representation of the src IP address. |
| 77 | + * Must be free'd using freeaddrinfo(). |
| 78 | + */ |
| 79 | +static struct addrinfo * |
| 80 | +makeIpBinary(const char *src) |
| 81 | +{ |
| 82 | + struct addrinfo want; |
| 83 | + memset(&want, 0, sizeof(want)); |
| 84 | + want.ai_flags = AI_NUMERICHOST; // prevent actual DNS lookups! |
| 85 | + |
| 86 | + struct addrinfo *dst = nullptr; |
| 87 | + if (getaddrinfo(src, nullptr, &want, &dst) != 0) { |
| 88 | + // not an IP address |
| 89 | + /* free any memory getaddrinfo() dynamically allocated. */ |
| 90 | + if (dst) |
| 91 | + freeaddrinfo(dst); |
| 92 | + return nullptr; |
| 93 | + } |
| 94 | + |
| 95 | + return dst; |
| 96 | +} |
| 97 | + |
| 98 | +/** |
| 99 | + * Convert srcLen bytes from src into HEX and store into dst, which |
| 100 | + * has a maximum content size of dstSize including c-string terminator. |
| 101 | + * The dst value produced will be a 0-terminated c-string. |
| 102 | + * |
| 103 | + * \retval N length of dst written (excluding c-string terminator) |
| 104 | + * \retval -11 (LDAP_ERR_OOB) buffer overflow detected |
| 105 | + */ |
| 106 | +static int |
| 107 | +makeHexString(char *dst, const int dstSize, const char *src, const int srcLen) |
| 108 | +{ |
| 109 | + // HEX encoding doubles the amount of bytes/octets copied |
| 110 | + if ((srcLen*2) >= dstSize) |
| 111 | + return LDAP_ERR_OOB; // cannot copy that many |
| 112 | + |
| 113 | + *dst = 0; |
| 114 | + |
| 115 | + for (int k = 0; k < srcLen; ++k) { |
| 116 | + int c = static_cast<int>(src[k]); |
| 117 | + if (c < 0) |
| 118 | + c = c + 256; |
| 119 | + char hexc[4]; |
| 120 | + const int hlen = snprintf(hexc, sizeof(hexc), "%02X", c); |
| 121 | + if (hlen < 0 || static_cast<size_t>(hlen) > sizeof(hexc)) // should be impossible |
| 122 | + return LDAP_ERR_OOB; |
| 123 | + strcat(dst, hexc); |
| 124 | + } |
| 125 | + return strlen(dst); |
| 126 | +} |
| 127 | + |
| 128 | /* |
| 129 | * ConvertIP() - <edui_ldap_t> <ip> |
| 130 | * |
| 131 | * Take an IPv4 address in dot-decimal or IPv6 notation, and convert to 2-digit HEX stored in l->search_ip |
| 132 | * This is the networkAddress that we search LDAP for. |
| 133 | - * |
| 134 | - * PENDING -- CHANGE OVER TO inet*_pton, but inet6_pton does not provide the correct syntax |
| 135 | - * |
| 136 | */ |
| 137 | static int |
| 138 | ConvertIP(edui_ldap_t *l, char *ip) |
| 139 | { |
| 140 | - char bufa[EDUI_MAXLEN], bufb[EDUI_MAXLEN], obj[EDUI_MAXLEN]; |
| 141 | - char hexc[4], *p; |
| 142 | void *y, *z; |
| 143 | - size_t s; |
| 144 | - long x; |
| 145 | - int i, j, t, swi; /* IPv6 "::" cut over toggle */ |
| 146 | if (l == NULL) return LDAP_ERR_NULL; |
| 147 | if (ip == NULL) return LDAP_ERR_PARAM; |
| 148 | if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */ |
| 149 | @@ -831,183 +886,22 @@ ConvertIP(edui_ldap_t *l, char *ip) |
| 150 | l->status |= (LDAP_IPV4_S); |
| 151 | z = NULL; |
| 152 | } |
| 153 | - s = strlen(ip); |
| 154 | - *(bufa) = '\0'; |
| 155 | - *(bufb) = '\0'; |
| 156 | - *(obj) = '\0'; |
| 157 | - /* StringSplit() will zero out bufa & obj at each call */ |
| 158 | - memset(l->search_ip, '\0', sizeof(l->search_ip)); |
| 159 | - xstrncpy(bufa, ip, sizeof(bufa)); /* To avoid segfaults, use bufa instead of ip */ |
| 160 | - swi = 0; |
| 161 | - if (l->status & LDAP_IPV6_S) { |
| 162 | - /* Search for :: in string */ |
| 163 | - if ((bufa[0] == ':') && (bufa[1] == ':')) { |
| 164 | - /* bufa starts with a ::, so just copy and clear */ |
| 165 | - xstrncpy(bufb, bufa, sizeof(bufb)); |
| 166 | - *(bufa) = '\0'; |
| 167 | - ++swi; /* Indicates that there is a bufb */ |
| 168 | - } else if ((bufa[0] == ':') && (bufa[1] != ':')) { |
| 169 | - /* bufa starts with a :, a typo so just fill in a ':', cat and clear */ |
| 170 | - bufb[0] = ':'; |
| 171 | - strncat(bufb, bufa, strlen(bufa)); |
| 172 | - *(bufa) = '\0'; |
| 173 | - ++swi; /* Indicates that there is a bufb */ |
| 174 | - } else { |
| 175 | - p = strstr(bufa, "::"); |
| 176 | - if (p != NULL) { |
| 177 | - /* Found it, break bufa down and split into bufb here */ |
| 178 | - *(bufb) = '\0'; |
| 179 | - i = strlen(p); |
| 180 | - memcpy(bufb, p, i); |
| 181 | - *p = '\0'; |
| 182 | - bufb[i] = '\0'; |
| 183 | - ++swi; /* Indicates that there is a bufb */ |
| 184 | - } |
| 185 | - } |
| 186 | - } |
| 187 | - s = strlen(bufa); |
| 188 | - if (s < 1) |
| 189 | - s = strlen(bufb); |
| 190 | - while (s > 0) { |
| 191 | - if ((l->status & LDAP_IPV4_S) && (swi == 0)) { |
| 192 | - /* Break down IPv4 address */ |
| 193 | - t = StringSplit(bufa, '.', obj, sizeof(obj)); |
| 194 | - if (t > 0) { |
| 195 | - errno = 0; |
| 196 | - x = strtol(obj, (char **)NULL, 10); |
| 197 | - if (((x < 0) || (x > 255)) || ((errno != 0) && (x == 0)) || ((obj[0] != '0') && (x == 0))) |
| 198 | - return LDAP_ERR_OOB; /* Out of bounds -- Invalid address */ |
| 199 | - memset(hexc, '\0', sizeof(hexc)); |
| 200 | - int hlen = snprintf(hexc, sizeof(hexc), "%02X", (int)x); |
| 201 | - strncat(l->search_ip, hexc, hlen); |
| 202 | - } else |
| 203 | - break; /* reached end of octet */ |
| 204 | - } else if (l->status & LDAP_IPV6_S) { |
| 205 | - /* Break down IPv6 address */ |
| 206 | - if (swi > 1) |
| 207 | - t = StringSplit(bufb, ':', obj, sizeof(obj)); /* After "::" */ |
| 208 | - else |
| 209 | - t = StringSplit(bufa, ':', obj, sizeof(obj)); /* Before "::" */ |
| 210 | - /* Convert octet by size (t) - and fill 0's */ |
| 211 | - switch (t) { /* IPv6 is already in HEX, copy contents */ |
| 212 | - case 4: |
| 213 | - hexc[0] = (char) toupper((int)obj[0]); |
| 214 | - i = (int)hexc[0]; |
| 215 | - if (!isxdigit(i)) |
| 216 | - return LDAP_ERR_OOB; /* Out of bounds */ |
| 217 | - hexc[1] = (char) toupper((int)obj[1]); |
| 218 | - i = (int)hexc[1]; |
| 219 | - if (!isxdigit(i)) |
| 220 | - return LDAP_ERR_OOB; /* Out of bounds */ |
| 221 | - hexc[2] = '\0'; |
| 222 | - strncat(l->search_ip, hexc, 2); |
| 223 | - hexc[0] = (char) toupper((int)obj[2]); |
| 224 | - i = (int)hexc[0]; |
| 225 | - if (!isxdigit(i)) |
| 226 | - return LDAP_ERR_OOB; /* Out of bounds */ |
| 227 | - hexc[1] = (char) toupper((int)obj[3]); |
| 228 | - i = (int)hexc[1]; |
| 229 | - if (!isxdigit(i)) |
| 230 | - return LDAP_ERR_OOB; /* Out of bounds */ |
| 231 | - hexc[2] = '\0'; |
| 232 | - strncat(l->search_ip, hexc, 2); |
| 233 | - break; |
| 234 | - case 3: |
| 235 | - hexc[0] = '0'; |
| 236 | - hexc[1] = (char) toupper((int)obj[0]); |
| 237 | - i = (int)hexc[1]; |
| 238 | - if (!isxdigit(i)) |
| 239 | - return LDAP_ERR_OOB; /* Out of bounds */ |
| 240 | - hexc[2] = '\0'; |
| 241 | - strncat(l->search_ip, hexc, 2); |
| 242 | - hexc[0] = (char) toupper((int)obj[1]); |
| 243 | - i = (int)hexc[0]; |
| 244 | - if (!isxdigit(i)) |
| 245 | - return LDAP_ERR_OOB; /* Out of bounds */ |
| 246 | - hexc[1] = (char) toupper((int)obj[2]); |
| 247 | - i = (int)hexc[1]; |
| 248 | - if (!isxdigit(i)) |
| 249 | - return LDAP_ERR_OOB; /* Out of bounds */ |
| 250 | - hexc[2] = '\0'; |
| 251 | - strncat(l->search_ip, hexc, 2); |
| 252 | - break; |
| 253 | - case 2: |
| 254 | - strncat(l->search_ip, "00", 2); |
| 255 | - hexc[0] = (char) toupper((int)obj[0]); |
| 256 | - i = (int)hexc[0]; |
| 257 | - if (!isxdigit(i)) |
| 258 | - return LDAP_ERR_OOB; /* Out of bounds */ |
| 259 | - hexc[1] = (char) toupper((int)obj[1]); |
| 260 | - i = (int)hexc[1]; |
| 261 | - if (!isxdigit(i)) |
| 262 | - return LDAP_ERR_OOB; /* Out of bounds */ |
| 263 | - hexc[2] = '\0'; |
| 264 | - strncat(l->search_ip, hexc, 2); |
| 265 | - break; |
| 266 | - case 1: |
| 267 | - strncat(l->search_ip, "00", 2); |
| 268 | - hexc[0] = '0'; |
| 269 | - hexc[1] = (char) toupper((int)obj[0]); |
| 270 | - i = (int)hexc[1]; |
| 271 | - if (!isxdigit(i)) |
| 272 | - return LDAP_ERR_OOB; /* Out of bounds */ |
| 273 | - hexc[2] = '\0'; |
| 274 | - strncat(l->search_ip, hexc, 2); |
| 275 | - break; |
| 276 | - default: |
| 277 | - if (t > 4) |
| 278 | - return LDAP_ERR_OOB; |
| 279 | - break; |
| 280 | - } |
| 281 | - /* Code to pad the address with 0's between a '::' */ |
| 282 | - if ((strlen(bufa) == 0) && (swi == 1)) { |
| 283 | - /* We are *AT* the split, pad in some 0000 */ |
| 284 | - t = strlen(bufb); |
| 285 | - /* How many ':' exist in bufb ? */ |
| 286 | - j = 0; |
| 287 | - for (i = 0; i < t; ++i) { |
| 288 | - if (bufb[i] == ':') |
| 289 | - ++j; |
| 290 | - } |
| 291 | - --j; /* Preceding "::" doesn't count */ |
| 292 | - t = 8 - (strlen(l->search_ip) / 4) - j; /* Remainder */ |
| 293 | - if (t > 0) { |
| 294 | - for (i = 0; i < t; ++i) |
| 295 | - strncat(l->search_ip, "0000", 4); |
| 296 | - } |
| 297 | - } |
| 298 | - } |
| 299 | - if ((bufa[0] == '\0') && (swi > 0)) { |
| 300 | - s = strlen(bufb); |
| 301 | - ++swi; |
| 302 | - } else |
| 303 | - s = strlen(bufa); |
| 304 | - } |
| 305 | - s = strlen(l->search_ip); |
| 306 | |
| 307 | - /* CHECK sizes of address, truncate or pad */ |
| 308 | - /* if "::" is at end of ip, then pad another block or two */ |
| 309 | - while ((l->status & LDAP_IPV6_S) && (s < 32)) { |
| 310 | - strncat(l->search_ip, "0000", 4); |
| 311 | - s = strlen(l->search_ip); |
| 312 | - } |
| 313 | - if ((l->status & LDAP_IPV6_S) && (s > 32)) { |
| 314 | - /* Too long, truncate */ |
| 315 | - l->search_ip[32] = '\0'; |
| 316 | - s = strlen(l->search_ip); |
| 317 | - } |
| 318 | - /* If at end of ip, and its not long enough, then pad another block or two */ |
| 319 | - while ((l->status & LDAP_IPV4_S) && (s < 8)) { |
| 320 | - strncat(l->search_ip, "00", 2); |
| 321 | - s = strlen(l->search_ip); |
| 322 | - } |
| 323 | - if ((l->status & LDAP_IPV4_S) && (s > 8)) { |
| 324 | - /* Too long, truncate */ |
| 325 | - l->search_ip[8] = '\0'; |
| 326 | - s = strlen(l->search_ip); |
| 327 | + size_t s = LDAP_ERR_INVALID; |
| 328 | + if (struct addrinfo *dst = makeIpBinary(ip)) { |
| 329 | + if (dst->ai_family == AF_INET6) { |
| 330 | + struct sockaddr_in6 *sia = reinterpret_cast<struct sockaddr_in6 *>(dst->ai_addr); |
| 331 | + const char *ia = reinterpret_cast<const char *>(sia->sin6_addr.s6_addr); |
| 332 | + s = makeHexString(l->search_ip, sizeof(l->search_ip), ia, 16); // IPv6 = 16-byte address |
| 333 | + |
| 334 | + } else if (dst->ai_family == AF_INET) { |
| 335 | + struct sockaddr_in *sia = reinterpret_cast<struct sockaddr_in *>(dst->ai_addr); |
| 336 | + const char *ia = reinterpret_cast<const char *>(&(sia->sin_addr)); |
| 337 | + s = makeHexString(l->search_ip, sizeof(l->search_ip), ia, 4); // IPv4 = 4-byte address |
| 338 | + } // else leave s with LDAP_ERR_INVALID value |
| 339 | + freeaddrinfo(dst); |
| 340 | } |
| 341 | |
| 342 | - /* Completed, s is length of address in HEX */ |
| 343 | return s; |
| 344 | } |
| 345 | |
| 346 | @@ -1099,48 +993,42 @@ SearchFilterLDAP(edui_ldap_t *l, char *group) |
| 347 | } |
| 348 | if (group == NULL) { |
| 349 | /* No groupMembership= to add, yay! */ |
| 350 | - xstrncpy(bufa, "(&", sizeof(bufa)); |
| 351 | - strncat(bufa, edui_conf.search_filter, strlen(edui_conf.search_filter)); |
| 352 | /* networkAddress */ |
| 353 | - snprintf(bufb, sizeof(bufb), "(|(networkAddress=1\\23%s)", bufc); |
| 354 | if (l->status & LDAP_IPV4_S) { |
| 355 | - int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s))", \ |
| 356 | - bufc, bufc); |
| 357 | - strncat(bufb, bufd, ln); |
| 358 | + const int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s)", bufc, bufc); |
| 359 | + if (ln < 0 || static_cast<size_t>(ln) >= sizeof(bufd)) |
| 360 | + return LDAP_ERR_OOB; |
| 361 | + |
| 362 | } else if (l->status & LDAP_IPV6_S) { |
| 363 | - int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s))", \ |
| 364 | - bufc, bufc); |
| 365 | - strncat(bufb, bufd, ln); |
| 366 | - } else |
| 367 | - strncat(bufb, ")", 1); |
| 368 | - strncat(bufa, bufb, strlen(bufb)); |
| 369 | - strncat(bufa, ")", 1); |
| 370 | + const int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s)", bufc, bufc); |
| 371 | + if (ln < 0 || static_cast<size_t>(ln) >= sizeof(bufd)) |
| 372 | + return LDAP_ERR_OOB; |
| 373 | + } |
| 374 | + const int x = snprintf(bufa, sizeof(bufa), "(&%s(|(networkAddress=1\\23%s)%s))", edui_conf.search_filter, bufc, bufd); |
| 375 | + if (x < 0 || static_cast<size_t>(x) >= sizeof(bufa)) |
| 376 | + return LDAP_ERR_OOB; |
| 377 | + |
| 378 | } else { |
| 379 | /* Needs groupMembership= to add... */ |
| 380 | - xstrncpy(bufa, "(&(&", sizeof(bufa)); |
| 381 | - strncat(bufa, edui_conf.search_filter, strlen(edui_conf.search_filter)); |
| 382 | /* groupMembership -- NOTE: Squid *MUST* provide "cn=" from squid.conf */ |
| 383 | - snprintf(bufg, sizeof(bufg), "(groupMembership=%s", group); |
| 384 | if ((l->basedn[0] != '\0') && (strstr(group, l->basedn) == NULL)) { |
| 385 | - strncat(bufg, ",", 1); |
| 386 | - strncat(bufg, l->basedn, strlen(l->basedn)); |
| 387 | + const int ln = snprintf(bufg, sizeof(bufg), ",%s", l->basedn); |
| 388 | + if (ln < 0 || static_cast<size_t>(ln) >= sizeof(bufd)) |
| 389 | + return LDAP_ERR_OOB; |
| 390 | } |
| 391 | - strncat(bufg, ")", 1); |
| 392 | - strncat(bufa, bufg, strlen(bufg)); |
| 393 | /* networkAddress */ |
| 394 | - snprintf(bufb, sizeof(bufb), "(|(networkAddress=1\\23%s)", bufc); |
| 395 | if (l->status & LDAP_IPV4_S) { |
| 396 | - int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s))", \ |
| 397 | - bufc, bufc); |
| 398 | - strncat(bufb, bufd, ln); |
| 399 | + const int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s)", bufc, bufc); |
| 400 | + if (ln < 0 || static_cast<size_t>(ln) >= sizeof(bufd)) |
| 401 | + return LDAP_ERR_OOB; |
| 402 | } else if (l->status & LDAP_IPV6_S) { |
| 403 | - int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s))", \ |
| 404 | - bufc, bufc); |
| 405 | - strncat(bufb, bufd, ln); |
| 406 | - } else |
| 407 | - strncat(bufb, ")", 1); |
| 408 | - strncat(bufa, bufb, strlen(bufb)); |
| 409 | - strncat(bufa, "))", 2); |
| 410 | + const int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s)", bufc, bufc); |
| 411 | + if (ln < 0 || static_cast<size_t>(ln) >= sizeof(bufd)) |
| 412 | + return LDAP_ERR_OOB; |
| 413 | + } |
| 414 | + const int x = snprintf(bufa, sizeof(bufa), "(&(&%s(groupMembership=%s%s)(|(networkAddress=1\\23%s)%s)))", edui_conf.search_filter, group, bufg, bufc, bufd); |
| 415 | + if (x < 0 || static_cast<size_t>(x) >= sizeof(bufa)) |
| 416 | + return LDAP_ERR_OOB; |
| 417 | } |
| 418 | s = strlen(bufa); |
| 419 | xstrncpy(l->search_filter, bufa, sizeof(l->search_filter)); |
| 420 | @@ -1212,10 +1100,10 @@ static int |
| 421 | SearchIPLDAP(edui_ldap_t *l) |
| 422 | { |
| 423 | ber_len_t i, x; |
| 424 | - ber_len_t j, k; |
| 425 | - ber_len_t y, z; |
| 426 | - int c; |
| 427 | - char bufa[EDUI_MAXLEN], bufb[EDUI_MAXLEN], hexc[4]; |
| 428 | + ber_len_t j; |
| 429 | + ber_len_t z; |
| 430 | + char bufa[EDUI_MAXLEN]; |
| 431 | + char bufb[EDUI_MAXLEN]; |
| 432 | LDAPMessage *ent; |
| 433 | if (l == NULL) return LDAP_ERR_NULL; |
| 434 | if (l->lp == NULL) return LDAP_ERR_POINTER; |
| 435 | @@ -1273,19 +1161,11 @@ SearchIPLDAP(edui_ldap_t *l) |
| 436 | /* bufa is the address, just compare it */ |
| 437 | if (!(l->status & LDAP_IPV4_S) || (l->status & LDAP_IPV6_S)) |
| 438 | break; /* Not looking for IPv4 */ |
| 439 | - for (k = 0; k < z; ++k) { |
| 440 | - c = (int) bufa[k]; |
| 441 | - if (c < 0) |
| 442 | - c = c + 256; |
| 443 | - int hlen = snprintf(hexc, sizeof(hexc), "%02X", c); |
| 444 | - if (k == 0) |
| 445 | - xstrncpy(bufb, hexc, sizeof(bufb)); |
| 446 | - else |
| 447 | - strncat(bufb, hexc, hlen); |
| 448 | - } |
| 449 | - y = strlen(bufb); |
| 450 | + const int blen = makeHexString(bufb, sizeof(bufb), bufa, z); |
| 451 | + if (blen < 0) |
| 452 | + return blen; |
| 453 | /* Compare value with IP */ |
| 454 | - if (memcmp(l->search_ip, bufb, y) == 0) { |
| 455 | + if (memcmp(l->search_ip, bufb, blen) == 0) { |
| 456 | /* We got a match! - Scan 'ber' for 'cn' values */ |
| 457 | z = ldap_count_values_len(ber); |
| 458 | for (j = 0; j < z; ++j) { |
| 459 | @@ -1308,19 +1188,11 @@ SearchIPLDAP(edui_ldap_t *l) |
| 460 | /* bufa + 2 is the address (skip 2 digit port) */ |
| 461 | if (!(l->status & LDAP_IPV4_S) || (l->status & LDAP_IPV6_S)) |
| 462 | break; /* Not looking for IPv4 */ |
| 463 | - for (k = 2; k < z; ++k) { |
| 464 | - c = (int) bufa[k]; |
| 465 | - if (c < 0) |
| 466 | - c = c + 256; |
| 467 | - int hlen = snprintf(hexc, sizeof(hexc), "%02X", c); |
| 468 | - if (k == 2) |
| 469 | - xstrncpy(bufb, hexc, sizeof(bufb)); |
| 470 | - else |
| 471 | - strncat(bufb, hexc, hlen); |
| 472 | - } |
| 473 | - y = strlen(bufb); |
| 474 | + const int blen = makeHexString(bufb, sizeof(bufb), &bufa[2], z); |
| 475 | + if (blen < 0) |
| 476 | + return blen; |
| 477 | /* Compare value with IP */ |
| 478 | - if (memcmp(l->search_ip, bufb, y) == 0) { |
| 479 | + if (memcmp(l->search_ip, bufb, blen) == 0) { |
| 480 | /* We got a match! - Scan 'ber' for 'cn' values */ |
| 481 | z = ldap_count_values_len(ber); |
| 482 | for (j = 0; j < z; ++j) { |
| 483 | @@ -1343,19 +1215,11 @@ SearchIPLDAP(edui_ldap_t *l) |
| 484 | /* bufa + 2 is the address (skip 2 digit port) */ |
| 485 | if (!(l->status & LDAP_IPV6_S)) |
| 486 | break; /* Not looking for IPv6 */ |
| 487 | - for (k = 2; k < z; ++k) { |
| 488 | - c = (int) bufa[k]; |
| 489 | - if (c < 0) |
| 490 | - c = c + 256; |
| 491 | - int hlen = snprintf(hexc, sizeof(hexc), "%02X", c); |
| 492 | - if (k == 2) |
| 493 | - xstrncpy(bufb, hexc, sizeof(bufb)); |
| 494 | - else |
| 495 | - strncat(bufb, hexc, hlen); |
| 496 | - } |
| 497 | - y = strlen(bufb); |
| 498 | + const int blen = makeHexString(bufb, sizeof(bufb), &bufa[2], z); |
| 499 | + if (blen < 0) |
| 500 | + return blen; |
| 501 | /* Compare value with IP */ |
| 502 | - if (memcmp(l->search_ip, bufb, y) == 0) { |
| 503 | + if (memcmp(l->search_ip, bufb, blen) == 0) { |
| 504 | /* We got a match! - Scan 'ber' for 'cn' values */ |
| 505 | z = ldap_count_values_len(ber); |
| 506 | for (j = 0; j < z; ++j) { |