1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #ifndef _LDAP_PARSE_H 30 #define _LDAP_PARSE_H 31 32 #include <lber.h> 33 #include <ldap.h> 34 #include <rpcsvc/nis.h> 35 36 #include "nis_hashitem.h" 37 38 /* Pick up N2L file names */ 39 #include <ndbm.h> 40 #include "yptol/shim.h" 41 #include "yptol/yptol.h" 42 43 #ifdef __cplusplus 44 extern "C" { 45 #endif 46 47 /* 48 * New <ldap.h> doesn't define LDAP_SCOPE_UNKNOWN, but we still need it. 49 */ 50 #ifndef LDAP_SCOPE_UNKNOWN 51 #define LDAP_SCOPE_UNKNOWN 0xFF 52 #endif 53 54 /* Attribute/value hash list element */ 55 typedef struct { 56 __nis_hash_item_mt item; /* item.name is the attr name */ 57 int numValues; 58 char **value; /* Array of values */ 59 bool_t isDefault; /* True if value is a default */ 60 } __nis_ldap_attribute_t; 61 62 /* YP Domains structure */ 63 typedef struct { 64 int numDomains; /* number of domains listed in mapping file */ 65 char **domainLabels; /* the labels for particular domain names */ 66 char **domains; /* Array of LDAP domains */ 67 int numYppasswdd; /* Number of yppasswddDomainLabels */ 68 char **yppasswddDomainLabels; /* yppasswdd domain labels */ 69 } __yp_domain_context_t; 70 71 /* 72 * Begin object mappings 73 * 74 * Note that the definitions, where necessary, proceed from the bottom 75 * (i.e., the "atomic" components) up. 76 */ 77 78 /* 79 * String match/print descriptor 80 * 81 * Intended for use together with a __nis_mapping_match_type_t, which will 82 * determine which field of the union is valid. 83 * 84 * string Pointer to a NUL-terminated string 85 * single Represents a single-character match such as '[a-bTe-w]', 86 * which would become 87 * { 88 * 3, numRange 89 * {'a', 'T', 'e'}, lo 90 * {'b', 'T', 'w'} hi 91 * } 92 * Each pair lo[i]/hi[i] (0 <= i < numRange) defines the 93 * range of the wild-card match. 94 * limit No use currrently defined; will probably be removed 95 * berString Pointer to a string containing a single formatting 96 * character as defined by ber_printf(3LDAP). Example: "i" 97 * for a binary integer. 98 */ 99 typedef union { 100 char *string; 101 struct { 102 int numRange; 103 unsigned char *lo; /* Array of numRange elements */ 104 unsigned char *hi; /* Array of numRange elements */ 105 } single; 106 enum { 107 bos, 108 eos 109 } limit; 110 char *berString; 111 } __nis_mapping_match_t; 112 113 /* 114 * String match/print types and descriptor 115 * 116 * Used to describe print or match conversions. The 'match' field has 117 * the following interpretation: 118 * 119 * Type __nis_mapping_match_t Comment 120 * 121 * mmt_item <unused> Value as indicated by corresponding 122 * element in __nis_mapping_item_t or 123 * __nis_mapping_sub_element_t array 124 * mmt_string string 125 * mmt_single single 126 * mmt_limit limit Probably not needed 127 * mmt_any <unused> Match any number of any character 128 * mmt_berstring berString 129 * mmt_begin <unused> Indicates beginning of format; optional 130 * mmt_end <unused> Indicates end of format; REQUIRED to 131 * mark the end of an array of 132 * __nis_mapping_format_t's 133 */ 134 typedef enum {mmt_item, mmt_string, mmt_single, mmt_limit, mmt_any, 135 mmt_berstring, mmt_begin, mmt_end} 136 __nis_mapping_match_type_t; 137 138 typedef struct { 139 __nis_mapping_match_type_t type; 140 __nis_mapping_match_t match; 141 } __nis_mapping_format_t; 142 143 /* Forward */ 144 struct __nis_mapping_element_struct; 145 struct __nis_mapping_item_struct; 146 147 /* 148 * LDAP search triple 149 * 150 * Used to represent a search triple like 151 * ou=Group,?one?cn=staff 152 * or 153 * ou=Group,?one?(&(cn=staff)(gidNumber=10)) 154 * or 155 * ou=Hosts,?one?("cn=%s", (cname, "%s.*")) 156 * 157 * base The base DN; defaultSearchBase appended if 'base' ends with 158 * a comma. 159 * scope One of LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, or 160 * LDAP_SCOPE_SUBTREE; LDAP_SCOPE_UNKNOWN means that this 161 * __nis_search_triple_t is inactive 162 * attrs Either a filter, or a list of attribute/value pairs, depending 163 * on context. 164 * element Pointer to a value element. If 'element' is non-NULL, the 165 * 'attrs' value is derived by evaluating 'element'. 166 */ 167 typedef struct { 168 char *base; 169 int scope; 170 char *attrs; 171 struct __nis_mapping_element_struct *element; 172 } __nis_search_triple_t; 173 174 /* 175 * NIS+ index spec 176 * 177 * Represents a NIS+ index list, such as 178 * name=staff,gid=10 179 * 180 * numIndexes The number of entries in the 'name'/'value' arrays 181 * name Array of column names 182 * value Array of column values; uses __nis_mapping_format_t so that 183 * wild-cards can be represented 184 * 185 * Example 186 * name=staff,gid=10 187 * 2, numIndexes 188 * { name 189 * "name", 190 * "gid" 191 * }, 192 * { value 193 * { 194 * {mmt_begin}, 195 * {mmt_string, "staff"}, 196 * {mmt_end} 197 * }, 198 * { 199 * {mmt_begin}, 200 * {mmt_string, "gid"}, 201 * {mmt_end} 202 * } 203 * } 204 */ 205 typedef struct { 206 int numIndexes; 207 char **name; 208 __nis_mapping_format_t **value; 209 } __nis_index_t; 210 211 /* What to do with the LDAP data when a NIS+ entry is deleted */ 212 typedef enum {dd_always, dd_perDbId, dd_never} __nis_delete_disp_t; 213 214 /* Type of an element in a mapping rule */ 215 typedef enum {me_item, me_print, me_split, me_match, me_extract} 216 __nis_mapping_element_type_t; 217 218 /* Type of an item in a mapping rule */ 219 typedef enum {mit_any, mit_nisplus, mit_ldap} __nis_mapping_item_type_t; 220 221 /* 222 * NIS+ object name, with index 223 * 224 * Used to represent a name like 225 * [name = staff, gid = 10]group.org_dir 226 * (Note: spaces around "=" and after "," to make cstyle happy; such spaces 227 * are not usually part of the syntax, but they are allowed.) 228 * 229 * index The index part of the name. numIndexes == 0 means there is 230 * no index. 231 * name The object name proper. If it doesn't end in a dot, the 232 * nisplusLDAPbaseDomain is appended. 233 */ 234 typedef struct { 235 __nis_index_t index; 236 char *name; 237 } __nis_obj_spec_t; 238 239 /* 240 * Complete representation of a subset of either the DIT or a NIS+ object. 241 * Intended for use in a __nis_mapping_item_t, where the 'type' field 242 * determines which field of the __nis_triple_or_obj_t is active. 243 */ 244 typedef union { 245 __nis_search_triple_t triple; 246 __nis_obj_spec_t obj; 247 } __nis_triple_or_obj_t; 248 249 /* 250 * Mapping item 251 * 252 * The mapping item is a single LDAP attribute, or a NIS+ table column, such as 253 * ldap:gidNumber:ou=Group, ?one?cn=staff 254 * or 255 * nisplus:gid[name = staff]group.org_dir 256 * (Note: spaces around "=" and after "," to make cstyle happy; such spaces 257 * are not usually part of the syntax, but they are allowed.) 258 * 259 * type mit_ldap or mit_nisplus 260 * name Attribute/column name 261 * searchSpec LDAP search triple, or NIS+ indexed object name 262 * repeat True if item should be repeated if necessary. This is used 263 * to represent implied lists, such as '(memberUid)', which 264 * denotes all values of the 'memberUid' attribute. 265 * exItem forward mapping item for supporting removespec syntax. 266 * 267 */ 268 typedef struct __nis_mapping_item_struct { 269 __nis_mapping_item_type_t type; 270 char *name; 271 __nis_triple_or_obj_t searchSpec; 272 bool_t repeat; 273 struct __nis_mapping_item_struct *exItem; 274 } __nis_mapping_item_t; 275 276 /* 277 * Sub-element of a mapping rule element 278 * 279 * Each element/sub-element represents the value(s) derived according to 280 * the semantics of the element. Although not explicitly represented here, 281 * values are either strings or BER byte sequences. 282 * 283 * type Type of the 'element' union 284 * element.item A single item 285 * element.print printf(3C)-style value 286 * fmt Array of formatting elements, terminated by 'mmt_end' 287 * numItems Number of items in the 'item' array 288 * item Array of 'numItems' items 289 * doElide Should the last character of the (string) value be 290 * removed ? 291 * elide Character to be removed 292 * element.split Item value string split into multiple values 293 * item A single item 294 * delim The separator character for the split 295 * element.extract Extraction of a sub-string from an item value 296 * fmt Array of formatting elements, terminated by 'mmt_end' 297 * item A single item 298 * 299 * Examples (see __nis_mapping_element_t below for examples using the 'item' 300 * field of __nis_mapping_sub_element_t). For notational convenience, 301 * __nis_mapping_item_t's are shortened to just the item name. 302 * 303 * (1) String value consisting of the string "{crypt}" followed by the 304 * value of the 'passwd' column. The NIS+LDAPmapping(4) representation 305 * is 306 * ("{crypt}%s", passwd) 307 * and the element.print contains 308 * { fmt 309 * {mmt_begin}, 310 * {mmt_string, "{crypt}"}, 311 * {mmt_item}, 312 * {mmt_end} 313 * }, 314 * 1, numItems 315 * { item 316 * {"passwd"} 317 * } 318 * FALSE, doElide 319 * '\0' elide (unused) 320 * 321 * (2) Split a value such as "member1,member2,member3" into multiple 322 * (three, here) values using ',' as the separator. 323 * (members, ",") 324 * element.split 325 * {"members"}, item 326 * ',' delim 327 * 328 * (3) Given a 'cname' column with the value "some.dom.ain.", extract 329 * "some", which becomes the value of the expression. 330 * (cname, "%s.*") 331 * element.extract 332 * { fmt 333 * {mmt_begin}, 334 * {mmt_item}, 335 * {mmt_string, "."}, 336 * {mmt_any}, 337 * {mmt_end} 338 * }, 339 * {"cname"} item 340 */ 341 typedef struct { 342 __nis_mapping_element_type_t type; 343 union { 344 __nis_mapping_item_t item; 345 struct { 346 __nis_mapping_format_t *fmt; 347 int numItems; 348 __nis_mapping_item_t *item; 349 bool_t doElide; 350 unsigned char elide; 351 } print; 352 struct { 353 __nis_mapping_item_t item; 354 unsigned char delim; 355 } split; 356 struct { 357 __nis_mapping_format_t *fmt; 358 __nis_mapping_item_t item; 359 } extract; 360 } element; 361 } __nis_mapping_sub_element_t; 362 363 /* 364 * Mapping rule element 365 * 366 * Each element/sub-element represents the value(s) derived according to 367 * the semantics of the element. Although not explicitly represented here, 368 * values are either strings or BER byte sequences. 369 * 370 * type Type of the 'element' union 371 * element.item A single item 372 * element.print printf(3C)-style value 373 * fmt Array of formatting elements, terminated by 'mmt_end' 374 * numSubElements Number of sub-elements in the 'subElement' array 375 * subElement Array of 'numSubElements' sub-elements 376 * doElide Should the last character of the (string) value(s) be 377 * removed ? 378 * elide Character to be removed 379 * element.split Item value string split into multiple values 380 * item A single item 381 * delim The separator character for the split 382 * element.match Assignment of item values by matching to a format 383 * fmt Array of formatting elements, terminated by 'mmt_end' 384 * numItems Number of items in the 'item' array 385 * item Array of 'numItems' items 386 * element.extract Extraction of a sub-string from an item value 387 * fmt Array of formatting elements, terminated by 'mmt_end' 388 * item A single item 389 * 390 * Examples; items represented by just the item name. 391 * 392 * (1) The value of the 'name' column. 393 * name 394 * element.item 395 * {"name"} item 396 * 397 * (2) Example (1) for a sub-element showed how to construct a value from 398 * a printf(3C)-style format string and one or more item values. 399 * However that example is only valid when used as a sub-expression 400 * (in place of an item in a 'print' list, for example). If 401 * ("{crypt}%s", passwd) 402 * was part of a rule like 403 * userPassword=("{crypt}%s", passwd) 404 * the representation would use a __nis_mapping_element_t as follows. 405 * element.print 406 * { fmt 407 * {mmt_begin}, 408 * {mmt_string, "{crypt}"}, 409 * {mmt_item}, 410 * {mmt_end} 411 * }, 412 * 1, numSubElements 413 * { subElement 414 * me_item, type 415 * {"passwd"} item 416 * }, 417 * FALSE, doElide 418 * '\0' elide (unused) 419 * 420 * (3) Match a value such as "{dh-1024}abcdef000234" to a template format 421 * "{%s}%s", assign "dh-1024" to the 'auth_type' column, and 422 * "abcdef000234" to the 'public_data' column. 423 * ("{%s}%s", auth_type, public_data) 424 * element.match 425 * { fmt 426 * {mmt_begin}, 427 * {mmt_string, "{"}, 428 * {mmt_item}, 429 * {mmt_string, "}"}, 430 * {mmt_item}, 431 * {mmt_end} 432 * } 433 * 2, numItems 434 * { item 435 * {"auth_type"}, 436 * {"public_data"} 437 * } 438 */ 439 typedef struct __nis_mapping_element_struct { 440 __nis_mapping_element_type_t type; 441 union { 442 __nis_mapping_item_t item; 443 struct { 444 __nis_mapping_format_t *fmt; 445 int numSubElements; 446 __nis_mapping_sub_element_t *subElement; 447 bool_t doElide; 448 unsigned char elide; 449 } print; 450 struct { 451 __nis_mapping_item_t item; 452 unsigned char delim; 453 } split; 454 struct { 455 __nis_mapping_format_t *fmt; 456 int numItems; 457 __nis_mapping_item_t *item; 458 } match; 459 struct { 460 __nis_mapping_format_t *fmt; 461 __nis_mapping_item_t item; 462 } extract; 463 } element; 464 } __nis_mapping_element_t; 465 466 /* 467 * One side (left or right) of a mapping rule 468 * 469 * Example 470 * The rule 471 * userPassword=("{crypt}%s", passwd) 472 * would be reprsented by a __nis_mapping_rule_t as follows 473 * { lhs 474 * 1, numElements 475 * { element 476 * me_item, 477 * {"userPassword"} 478 * } 479 * }, 480 * { rhs 481 * 1, numElements 482 * { element 483 * me_print, 484 * { 485 * See example (2) under 486 * __nis_mapping_element_t 487 * above 488 * } 489 * } 490 * } 491 */ 492 typedef struct { 493 int numElements; 494 __nis_mapping_element_t *element; 495 } __nis_mapping_rlhs_t; 496 497 /* A single mapping rule: attribute -> column or column -> attribute */ 498 typedef struct { 499 __nis_mapping_rlhs_t lhs; 500 __nis_mapping_rlhs_t rhs; 501 } __nis_mapping_rule_t; 502 503 /* 504 * Map (sub-set of) NIS+ object to location(s) in the LDAP DB 505 * 506 * read base/scope/filter triple used to read data from LDAP; 507 * LDAP_SCOPE_UNKNOWN indicates that 'read' is unused 508 * write base/scope/attrlist triple used to write data to LDAP; 509 * LDAP_SCOPE_UNKNOWN indicates that 'write' is unused 510 * delDisp What should happen to the LDAP entry when the corresponding 511 * NIS+ data is deleted. 512 * dbIdName The dbId for the delete rule set (if any) 513 * numDbIds The number of rules in the 'dbId' rule set 514 * dbId The delete rule set; this field must point to a valid 515 * rule set if 'delDisp' is 'dd_perDbId'; ignored otherwise 516 * next Pointer to the next __nis_object_dn_t structure for this 517 * NIS+ object. 518 * 519 * Example 520 * The "group.org_dir.x.y.z." NIS+ table should be read from and 521 * written to the "ou=Group" container at "dc=x,dc=y,dc=z". Upon 522 * NIS+ entry deletion, we should always attempt to delete the 523 * corresponding LDAP attributes. 524 * 525 * { read 526 * "ou=Group,dc=x,dc=y,dc=z", 527 * LDAP_SCOPE_ONELEVEL, 528 * "objectClass=posixGroup" 529 * }, 530 * { write 531 * "ou=Group,dc=x,dc=y,dc=z", 532 * LDAP_SCOPE_ONELEVEL, 533 * "objectClass=posixGroup" 534 * }, 535 * dd_always, delDisp 536 * NULL, dbIdName 537 * 0, 538 * NULL, dbId 539 * NULL next 540 */ 541 typedef struct { 542 __nis_search_triple_t read; 543 __nis_search_triple_t write; 544 __nis_delete_disp_t delDisp; 545 char *dbIdName; 546 int numDbIds; 547 __nis_mapping_rule_t **dbId; /* Delete rule set */ 548 void *next; 549 } __nis_object_dn_t; 550 551 /* 552 * Per-dbId or -object mapping 553 * 554 * Initially collected per-dbId (so that item.name=dbId), the 555 * __nis_table_mapping_t's are later stored per-object (whereupon 556 * item.name=objName). 557 * 558 * item Structure used by the hash_item functions 559 * dbId The dbId associated with the __nis_table_mapping_t 560 * structure 561 * index Object sub-set specification; only defined for 562 * tables; index.numIndexes equal to zero means that 563 * the 'index' is unused. 564 * next Pointer to next table sub-set, if any 565 * numColumns Number of columns if the object is a table 566 * column Column names 567 * initTtlLo Lower limit on the initial TTL 568 * initTtlHi Upper limit on the initial TTL 569 * ttl TTL set after refresh 570 * commentChar NIS map comment character 571 * objectDN Location in the LDAP DB 572 * numSplits number of split fields 573 * separatorStr separator string to break up NIS split field attributes 574 * usedns_flag indicates if the -b option to makedbm is used for a map. 575 * securemap_flag indicates if the -s option to makedbm is used for a map. 576 * __nis_mapping_element_t Parsed format strings and name fields storage 577 * numRulesFromLDAP Number of rules (and hence elements in the 578 * 'ruleFromLDAP' array) for mapping LDAP entries 579 * to NIS+ objects 580 * ruleFromLDAP 581 * numRulesToLDAP Number of rules (and hence elements in the 582 * 'ruleToLDAP' array) for mapping NIS+ objects to 583 * LDAP entries 584 * ruleToLDAP 585 * objType The NIS+ object type; NIS_BOGUS_OBJ used to indicate 586 * not set (in which case the other object data fields 587 * should be assumed to be invalid) 588 * objName The fully qualified name of the NIS+ object 589 * objPath The name used internally by libnisdb (which 590 * is path to the data file for the table/directory 591 * containing the object) 592 * obj A copy of the object itself 593 * isMaster Set if this machine is the master for the object 594 * (actually for the directory containing it) 595 * seq_num A sequence number representing the order of the maps 596 * as listed in the NISLDAPmapping.template file. 597 * 598 * Example 599 * Map the subset of the NIS+ 'group.org_dir.x.y.z.' table for which 600 * is true that the 'name' starts with 'a' or 'o' to location per 601 * the __nis_object_dn_t example above. No translation rules. 602 * 603 * { item 604 * "group.org_dir.x.y.z." name 605 * <omitted> 606 * }, 607 * "group_subset", dbId 608 * 1, numIndexes 609 * { index 610 * 1, 611 * {"name"}, 612 * { 613 * {mmt_begin}, 614 * { 615 * mmt_single, 616 * 2, 617 * {'a', 'o'}, 618 * {'a', 'o'}, 619 * } 620 * {mmt_any}, 621 * {mmt_end} 622 * } 623 * } 624 * NULL, next 625 * 4, numColumns 626 * { column 627 * "name", 628 * "passwd", 629 * "gid", 630 * "members" 631 * }, 632 * 1800, initTtlLo 633 * 5400, initTtlHi 634 * 3600, ttl 635 * '#', commentChar 636 * <see __nis_object_dn_t example>, objectDN 637 * 0, numSplits 638 * NULL, separatorStr 639 * 0, usedns_flag 640 * 0, securemap_flag 641 * <see __nis_mapping_element_t example>, e 642 * 0, numRulesFromLDAP 643 * NULL, ruleFromLDAP 644 * 0, numRulesToLDAP 645 * NULL ruleToLDAP 646 * NIS_TABLE_OBJ, objType 647 * "group.org_dir.x.y.z.", objName 648 * "/var/nis/data/group.org_dir" objPath 649 * <pointer to NIS+ object> obj 650 * 1 isMaster 651 */ 652 typedef struct { 653 __nis_hash_item_mt item; /* item.name=dbId||objName */ 654 char *dbId; /* Used during initializaton */ 655 __nis_index_t index; 656 void *next; /* Next sub-set spec */ 657 void *seqNext; /* Next in config sequence */ 658 int numColumns; 659 char **column; 660 time_t initTtlLo; 661 time_t initTtlHi; 662 time_t ttl; 663 char commentChar; 664 __nis_object_dn_t *objectDN; 665 int numSplits; 666 char *separatorStr; 667 int usedns_flag; 668 int securemap_flag; 669 __nis_mapping_element_t *e; 670 int numRulesFromLDAP; 671 __nis_mapping_rule_t **ruleFromLDAP; 672 int numRulesToLDAP; 673 __nis_mapping_rule_t **ruleToLDAP; 674 /* 675 * The following fields contain information about the mapped object. 676 */ 677 zotypes objType; 678 char *objName; /* FQ object name */ 679 char *objPath; /* nisdb's internal name */ 680 nis_object *obj; /* NIS+ object */ 681 int isMaster; /* Master for this object ? */ 682 int seq_num; 683 } __nis_table_mapping_t; 684 685 /* End object mappings */ 686 687 /* Default config file paths */ 688 #define DEFAULTCONFFILE "/var/nis/NIS+LDAPmapping" 689 #define ETCCONFFILE "/etc/default/rpc.nisd" 690 #define YP_DEFAULTCONFFILE NTOL_MAP_FILE 691 #define YP_ETCCONFFILE NTOL_CONFIG_FILE 692 693 /* Path to the root object dir file */ 694 #define ROOTDIRFILE "/var/nis/data/root_dir" 695 /* Path to the root object file */ 696 #define ROOTOBJFILE "/var/nis/data/root.object" 697 698 extern __nis_table_mapping_t *ldapMappingSeq; 699 extern int yp2ldap; 700 701 /* Exported functions */ 702 int parseConfig(char **ldapCLA, char *ldapConfFile); 703 int linked2hash(__nis_table_mapping_t *tlist); 704 int dbids2objs(__nis_hash_table_mt *objs, 705 __nis_hash_table_mt *dbids); 706 void __make_legal(char *s); 707 char *internal_table_name(nis_name name, char *res); 708 nis_name relative_name(char *s); 709 char *internalTableName(char *name); 710 __nis_table_mapping_t *getObjMapping(char *name, char *intNameArg, 711 int asObj, 712 int *doRead, int *doWrite); 713 714 #ifdef __cplusplus 715 } 716 #endif /* __cplusplus */ 717 718 #endif /* _LDAP_PARSE_H */ 719