Changeset 745 for trunk/server/source3/lib/tldap.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
source3/lib/tldap.c (modified) (17 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/lib/tldap.c
r414 r745 19 19 20 20 #include "includes.h" 21 22 23 24 25 26 21 27 22 28 bool tevent_req_is_ldap_error(struct tevent_req *req, int *perr) … … 419 425 } 420 426 421 state->iov.iov_base = blob.data;427 state->iov.iov_base = blob.data; 422 428 state->iov.iov_len = blob.length; 423 429 … … 506 512 507 513 /* 508 * We're the first one s, add the read_ldap request that waits for the514 * We're the first one, add the read_ldap request that waits for the 509 515 * answer from the server 510 516 */ … … 555 561 struct tevent_req *req; 556 562 struct tldap_msg_state *state; 557 struct tevent_context *ev;558 563 struct asn1_data *data; 559 564 uint8_t *inbuf; … … 614 619 state->data = talloc_move(state, &data); 615 620 616 ev = state->ev;617 618 621 talloc_set_destructor(req, NULL); 619 622 tldap_msg_unset_pending(req); … … 734 737 { 735 738 char *result = talloc_array(mem_ctx, char, blob.length+1); 739 740 741 742 743 736 744 memcpy(result, blob.data, blob.length); 737 745 result[blob.length] = '\0'; … … 741 749 static bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx, 742 750 struct asn1_data *data, 743 char ** result)751 char **result) 744 752 { 745 753 DATA_BLOB string; 754 746 755 if (!asn1_read_OctetString(data, mem_ctx, &string)) 747 756 return false; 748 *result = blob2string_talloc(mem_ctx, string); 757 758 result = blob2string_talloc(mem_ctx, string); 759 749 760 data_blob_free(&string); 761 762 763 764 765 750 766 return true; 751 767 } … … 869 885 int tldap_sasl_bind_recv(struct tevent_req *req) 870 886 { 871 int err; 872 873 if (tevent_req_is_ldap_error(req, &err)) { 874 return err; 875 } 876 return TLDAP_SUCCESS; 887 return tldap_simple_recv(req); 877 888 } 878 889 … … 957 968 /*****************************************************************************/ 958 969 959 /* 960 * This piece has a dependency on ldb, the ldb_parse_tree() function is used. 961 * In case we want to separate out tldap, we need to copy or rewrite it. 970 /* can't use isalpha() as only a strict set is valid for LDAP */ 971 972 static bool tldap_is_alpha(char c) 973 { 974 return (((c >= 'a') && (c <= 'z')) || \ 975 ((c >= 'A') && (c <= 'Z'))); 976 } 977 978 static bool tldap_is_adh(char c) 979 { 980 return tldap_is_alpha(c) || isdigit(c) || (c == '-'); 981 } 982 983 #define TLDAP_FILTER_AND ASN1_CONTEXT(0) 984 #define TLDAP_FILTER_OR ASN1_CONTEXT(1) 985 #define TLDAP_FILTER_NOT ASN1_CONTEXT(2) 986 #define TLDAP_FILTER_EQ ASN1_CONTEXT(3) 987 #define TLDAP_FILTER_SUB ASN1_CONTEXT(4) 988 #define TLDAP_FILTER_LE ASN1_CONTEXT(5) 989 #define TLDAP_FILTER_GE ASN1_CONTEXT(6) 990 #define TLDAP_FILTER_PRES ASN1_CONTEXT_SIMPLE(7) 991 #define TLDAP_FILTER_APX ASN1_CONTEXT(8) 992 #define TLDAP_FILTER_EXT ASN1_CONTEXT(9) 993 994 #define TLDAP_SUB_INI ASN1_CONTEXT_SIMPLE(0) 995 #define TLDAP_SUB_ANY ASN1_CONTEXT_SIMPLE(1) 996 #define TLDAP_SUB_FIN ASN1_CONTEXT_SIMPLE(2) 997 998 999 /* oid's should be numerical only in theory, 1000 * but apparently some broken servers may have alphanum aliases instead. 1001 * Do like openldap libraries and allow alphanum aliases for oids, but 1002 * do not allow Tagging options in that case. 962 1003 */ 963 964 #include "lib/ldb/include/ldb.h" 965 #include "lib/ldb/include/ldb_errors.h" 966 967 static bool ldap_push_filter(struct asn1_data *data, 968 struct ldb_parse_tree *tree) 969 { 1004 static bool tldap_is_attrdesc(const char *s, int len, bool no_tagopts) 1005 { 1006 bool is_oid = false; 1007 bool dot = false; 970 1008 int i; 971 1009 972 switch (tree->operation) { 973 case LDB_OP_AND: 974 case LDB_OP_OR: 975 asn1_push_tag(data, 976 ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1)); 977 for (i=0; i<tree->u.list.num_elements; i++) { 978 if (!ldap_push_filter(data, 979 tree->u.list.elements[i])) { 1010 /* first char has stricter rules */ 1011 if (isdigit(*s)) { 1012 is_oid = true; 1013 } else if (!tldap_is_alpha(*s)) { 1014 /* bad first char */ 1015 return false; 1016 } 1017 1018 for (i = 1; i < len; i++) { 1019 1020 if (is_oid) { 1021 if (isdigit(s[i])) { 1022 dot = false; 1023 continue; 1024 } 1025 if (s[i] == '.') { 1026 if (dot) { 1027 /* malformed */ 1028 return false; 1029 } 1030 dot = true; 1031 continue; 1032 } 1033 } else { 1034 if (tldap_is_adh(s[i])) { 1035 continue; 1036 } 1037 } 1038 1039 if (s[i] == ';') { 1040 if (no_tagopts) { 1041 /* no tagging options */ 980 1042 return false; 981 1043 } 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 982 1243 } 983 1244 asn1_pop_tag(data); 984 break; 985 986 case LDB_OP_NOT: 987 asn1_push_tag(data, ASN1_CONTEXT(2)); 988 if (!ldap_push_filter(data, tree->u.isnot.child)) { 1245 goto done; 1246 1247 case '(': 1248 case ')': 1249 tldap_debug(ld, TLDAP_DEBUG_ERROR, 1250 "Invalid parenthesis '%c'\n", *s); 1251 return false; 1252 1253 case '\0': 1254 tldap_debug(ld, TLDAP_DEBUG_ERROR, 1255 "Invalid filter termination\n"); 1256 return false; 1257 1258 default: 1259 ret = tldap_push_filter_basic(ld, data, &s); 1260 if (!ret) { 989 1261 return false; 990 1262 } 1263 1264 1265 1266 1267 1268 1269 1270 991 1271 asn1_pop_tag(data); 992 break; 993 994 case LDB_OP_EQUALITY: 995 /* equality test */ 996 asn1_push_tag(data, ASN1_CONTEXT(3)); 997 asn1_write_OctetString(data, tree->u.equality.attr, 998 strlen(tree->u.equality.attr)); 999 asn1_write_OctetString(data, tree->u.equality.value.data, 1000 tree->u.equality.value.length); 1001 asn1_pop_tag(data); 1002 break; 1003 1004 case LDB_OP_SUBSTRING: 1005 /* 1006 SubstringFilter ::= SEQUENCE { 1007 type AttributeDescription, 1008 -- at least one must be present 1009 substrings SEQUENCE OF CHOICE { 1010 initial [0] LDAPString, 1011 any [1] LDAPString, 1012 final [2] LDAPString } } 1013 */ 1014 asn1_push_tag(data, ASN1_CONTEXT(4)); 1015 asn1_write_OctetString(data, tree->u.substring.attr, 1016 strlen(tree->u.substring.attr)); 1017 asn1_push_tag(data, ASN1_SEQUENCE(0)); 1018 i = 0; 1019 if (!tree->u.substring.start_with_wildcard) { 1020 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0)); 1021 asn1_write_DATA_BLOB_LDAPString( 1022 data, tree->u.substring.chunks[i]); 1272 goto done; 1273 } 1274 1275 while (*s) { 1276 ret = tldap_push_filter_int(ld, data, &s); 1277 if (!ret) { 1278 return false; 1279 } 1280 1281 if (*s == ')') { 1282 /* end of list, return */ 1023 1283 asn1_pop_tag(data); 1024 i++; 1025 } 1026 while (tree->u.substring.chunks[i]) { 1027 int ctx; 1028 1029 if ((!tree->u.substring.chunks[i + 1]) && 1030 (tree->u.substring.end_with_wildcard == 0)) { 1031 ctx = 2; 1284 break; 1285 } 1286 } 1287 1288 done: 1289 if (*s != ')') { 1290 tldap_debug(ld, TLDAP_DEBUG_ERROR, 1291 "Incomplete or malformed filter\n"); 1292 return false; 1293 } 1294 s++; 1295 1296 if (data->has_error) { 1297 return false; 1298 } 1299 1300 *_s = s; 1301 return true; 1302 } 1303 1304 1305 static bool tldap_push_filter_basic(struct tldap_context *ld, 1306 struct asn1_data *data, 1307 const char **_s) 1308 { 1309 TALLOC_CTX *tmpctx = talloc_tos(); 1310 const char *s = *_s; 1311 const char *e; 1312 const char *eq; 1313 const char *val; 1314 const char *type; 1315 const char *dn; 1316 const char *rule; 1317 const char *star; 1318 size_t type_len = 0; 1319 char *uval; 1320 size_t uval_len; 1321 bool write_octect = true; 1322 bool ret; 1323 1324 eq = strchr(s, '='); 1325 if (!eq) { 1326 tldap_debug(ld, TLDAP_DEBUG_ERROR, 1327 "Invalid filter, missing equal sign\n"); 1328 return false; 1329 } 1330 1331 val = eq + 1; 1332 e = eq - 1; 1333 1334 switch (*e) { 1335 case '<': 1336 asn1_push_tag(data, TLDAP_FILTER_LE); 1337 break; 1338 1339 case '>': 1340 asn1_push_tag(data, TLDAP_FILTER_GE); 1341 break; 1342 1343 case '~': 1344 asn1_push_tag(data, TLDAP_FILTER_APX); 1345 break; 1346 1347 case ':': 1348 asn1_push_tag(data, TLDAP_FILTER_EXT); 1349 write_octect = false; 1350 1351 type = NULL; 1352 dn = NULL; 1353 rule = NULL; 1354 1355 if (*s == ':') { /* [:dn]:rule:= value */ 1356 if (s == e) { 1357 /* malformed filter */ 1358 return false; 1359 } 1360 dn = s; 1361 } else { /* type[:dn][:rule]:= value */ 1362 type = s; 1363 dn = strchr(s, ':'); 1364 type_len = dn - type; 1365 if (dn == e) { /* type:= value */ 1366 dn = NULL; 1367 } 1368 } 1369 if (dn) { 1370 dn++; 1371 1372 rule = strchr(dn, ':'); 1373 if ((rule == dn + 1) || rule + 1 == e) { 1374 /* malformed filter, contains "::" */ 1375 return false; 1376 } 1377 1378 if (StrnCaseCmp(dn, "dn:", 3) != 0) { 1379 if (rule == e) { 1380 rule = dn; 1381 dn = NULL; 1382 } else { 1383 /* malformed filter. With two 1384 * optionals, the first must be "dn" 1385 */ 1386 return false; 1387 } 1032 1388 } else { 1033 ctx = 1; 1389 if (rule == e) { 1390 rule = NULL; 1391 } else { 1392 rule++; 1393 } 1034 1394 } 1035 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx)); 1036 asn1_write_DATA_BLOB_LDAPString( 1037 data, tree->u.substring.chunks[i]); 1038 asn1_pop_tag(data); 1039 i++; 1040 } 1041 asn1_pop_tag(data); 1042 asn1_pop_tag(data); 1043 break; 1044 1045 case LDB_OP_GREATER: 1046 /* greaterOrEqual test */ 1047 asn1_push_tag(data, ASN1_CONTEXT(5)); 1048 asn1_write_OctetString(data, tree->u.comparison.attr, 1049 strlen(tree->u.comparison.attr)); 1050 asn1_write_OctetString(data, tree->u.comparison.value.data, 1051 tree->u.comparison.value.length); 1052 asn1_pop_tag(data); 1053 break; 1054 1055 case LDB_OP_LESS: 1056 /* lessOrEqual test */ 1057 asn1_push_tag(data, ASN1_CONTEXT(6)); 1058 asn1_write_OctetString(data, tree->u.comparison.attr, 1059 strlen(tree->u.comparison.attr)); 1060 asn1_write_OctetString(data, tree->u.comparison.value.data, 1061 tree->u.comparison.value.length); 1062 asn1_pop_tag(data); 1063 break; 1064 1065 case LDB_OP_PRESENT: 1066 /* present test */ 1067 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7)); 1068 asn1_write_LDAPString(data, tree->u.present.attr); 1069 asn1_pop_tag(data); 1070 return !data->has_error; 1071 1072 case LDB_OP_APPROX: 1073 /* approx test */ 1074 asn1_push_tag(data, ASN1_CONTEXT(8)); 1075 asn1_write_OctetString(data, tree->u.comparison.attr, 1076 strlen(tree->u.comparison.attr)); 1077 asn1_write_OctetString(data, tree->u.comparison.value.data, 1078 tree->u.comparison.value.length); 1079 asn1_pop_tag(data); 1080 break; 1081 1082 case LDB_OP_EXTENDED: 1395 } 1396 1397 if (!type && !dn && !rule) { 1398 /* malformed filter, there must be at least one */ 1399 return false; 1400 } 1401 1083 1402 /* 1084 1403 MatchingRuleAssertion ::= SEQUENCE { 1085 1404 matchingRule [1] MatchingRuleID OPTIONAL, 1086 type [2] AttributeDescription OPTIONAL,1405 type [2] AttributeDescription OPTIONAL, 1087 1406 matchValue [3] AssertionValue, 1088 1407 dnAttributes [4] BOOLEAN DEFAULT FALSE 1089 1408 } 1090 1409 */ 1091 asn1_push_tag(data, ASN1_CONTEXT(9)); 1092 if (tree->u.extended.rule_id) { 1410 1411 /* check and add rule */ 1412 if (rule) { 1413 ret = tldap_is_attrdesc(rule, e - rule, true); 1414 if (!ret) { 1415 return false; 1416 } 1093 1417 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1)); 1094 asn1_write _LDAPString(data, tree->u.extended.rule_id);1418 asn1_write); 1095 1419 asn1_pop_tag(data); 1096 1420 } 1097 if (tree->u.extended.attr) { 1421 1422 /* check and add type */ 1423 if (type) { 1424 ret = tldap_is_attrdesc(type, type_len, false); 1425 if (!ret) { 1426 return false; 1427 } 1098 1428 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2)); 1099 asn1_write _LDAPString(data, tree->u.extended.attr);1429 asn1_write); 1100 1430 asn1_pop_tag(data); 1101 1431 } 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1102 1443 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3)); 1103 asn1_write _DATA_BLOB_LDAPString(data, &tree->u.extended.value);1444 asn1_write); 1104 1445 asn1_pop_tag(data); 1446 1105 1447 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4)); 1106 asn1_write_uint8(data, tree->u.extended.dnAttributes);1448 asn1_write_uint8(data, ); 1107 1449 asn1_pop_tag(data); 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1108 1594 asn1_pop_tag(data); 1109 break; 1110 1111 default: 1595 1596 val = star + 1; 1597 1598 } while (*star == '*'); 1599 1600 *_s = star; 1601 1602 /* end of sequence */ 1603 asn1_pop_tag(data); 1604 return true; 1605 } 1606 1607 /* NOTE: although openldap libraries allow for spaces in some places, mosly 1608 * around parenthesis, we do not allow any spaces (except in values of 1609 * course) as I couldn't fine any place in RFC 4512 or RFC 4515 where 1610 * leading or trailing spaces where allowed. 1611 */ 1612 static bool tldap_push_filter(struct tldap_context *ld, 1613 struct asn1_data *data, 1614 const char *filter) 1615 { 1616 const char *s = filter; 1617 bool ret; 1618 1619 ret = tldap_push_filter_int(ld, data, &s); 1620 if (ret && *s) { 1621 tldap_debug(ld, TLDAP_DEBUG_ERROR, 1622 "Incomplete or malformed filter\n"); 1112 1623 return false; 1113 1624 } 1114 return !data->has_error;1115 }1116 1117 static bool tldap_push_filter(struct asn1_data *data, const char *filter)1118 {1119 struct ldb_parse_tree *tree;1120 bool ret;1121 1122 tree = ldb_parse_tree(talloc_tos(), filter);1123 if (tree == NULL) {1124 return false;1125 }1126 ret = ldap_push_filter(data, tree);1127 TALLOC_FREE(tree);1128 1625 return ret; 1129 1626 } … … 1166 1663 asn1_write_BOOLEAN(state->out, attrsonly); 1167 1664 1168 if (!tldap_push_filter( state->out, filter)) {1665 if (!tldap_push_filter(state->out, filter)) { 1169 1666 goto encoding_error; 1170 1667 } … … 1345 1842 tevent_req_set_callback(req, tldap_search_cb, &state); 1346 1843 1844 1845 1846 1847 1848 1849 1850 1347 1851 while (tevent_req_is_in_progress(req) 1348 1852 && (state.rc == TLDAP_SUCCESS)) { … … 1455 1959 } 1456 1960 1457 bool tldap_entry_attributes(struct tldap_message *msg, int *num_attributes, 1458 struct tldap_attribute **attributes) 1961 bool tldap_entry_attributes(struct tldap_message *msg, 1962 struct tldap_attribute **attributes, 1963 int *num_attributes) 1459 1964 { 1460 1965 if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) { … … 1628 2133 1629 2134 int tldap_add(struct tldap_context *ld, const char *dn, 1630 int num_attributes, struct tldap_mod *attributes,2135 attributes, 1631 2136 struct tldap_control *sctrls, int num_sctrls, 1632 2137 struct tldap_control *cctrls, int num_cctrls) … … 1668 2173 struct tldap_context *ld, 1669 2174 const char *dn, 1670 int num_mods, struct tldap_mod *mods,2175 mods, 1671 2176 struct tldap_control *sctrls, 1672 2177 int num_sctrls, … … 1728 2233 1729 2234 int tldap_modify(struct tldap_context *ld, const char *dn, 1730 int num_mods, struct tldap_mod *mods,2235 mods, 1731 2236 struct tldap_control *sctrls, int num_sctrls, 1732 2237 struct tldap_control *cctrls, int num_cctrls) … … 1743 2248 } 1744 2249 1745 req = tldap_modify_send(frame, ev, ld, dn, num_mods,mods,2250 req = tldap_modify_send(frame, ev, ld, dn, mods, 1746 2251 sctrls, num_sctrls, cctrls, num_cctrls); 1747 2252 if (req == NULL) { … … 1878 2383 *sctrls = NULL; 1879 2384 *num_sctrls = 0; 2385 1880 2386 } 1881 2387 *sctrls = msg->res_sctrls;
Note:
See TracChangeset
for help on using the changeset viewer.
