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 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 /* 30 * DESCRIPTION: Contains functions relating to movement of entire maps. 31 */ 32 33 #include <unistd.h> 34 #include <syslog.h> 35 #include <ndbm.h> 36 #include <string.h> 37 #include "ypsym.h" 38 #include "ypdefs.h" 39 #include "shim.h" 40 #include "yptol.h" 41 #include "../ldap_util.h" 42 43 /* 44 * Switch on parts of ypdefs.h 45 */ 46 USE_YPDBPATH 47 USE_DBM 48 49 /* 50 * Decs 51 */ 52 void add_separator(char *); 53 suc_code dump_domain_to_dit(char *, bool_t); 54 suc_code dump_map_to_dit(char *, char *, bool_t); 55 suc_code dump_maps_to_dit(bool_t); 56 suc_code dump_dit_to_map(); 57 suc_code dump_dit_to_maps(); 58 59 /* 60 * FUNCTION : dump_maps_to_dit() 61 * 62 * DESCRIPTION: Dump all the OLD STYLE NIS maps into the DIT. 63 * 64 * Since the DIT is not yet set up details about which maps and 65 * domains exist are gathered from the N2L config file and the 66 * existing map files. 67 * 68 * GIVEN : Flag indicating if containers and domains should be set up. 69 * 70 * RETURNS : Success code 71 */ 72 suc_code 73 dump_maps_to_dit(bool_t init_containers) 74 { 75 char **dom_list; 76 int num_doms, i; 77 78 num_doms = get_mapping_domain_list(&dom_list); 79 80 /* Dump all domains in list */ 81 for (i = 0; i < num_doms; i++) { 82 if (FAILURE == dump_domain_to_dit(dom_list[i], init_containers)) 83 return (FAILURE); 84 } 85 86 return (SUCCESS); 87 } 88 89 /* 90 * FUNCTION : dump_domain_to_dit() 91 * 92 * DESCRIPTION: Dumps all maps in one domain into the DIT 93 * 94 * GIVEN : Name of the domain 95 * Flag indicating if containers and domains should be set up. 96 * 97 * RETURNS : SUCCESS = domain completely dumped 98 * FAILURE = domain not completely dumped 99 * 100 */ 101 suc_code 102 dump_domain_to_dit(char *dom_name, bool_t init_containers) 103 { 104 char **map_list; 105 int i; 106 107 /* Set up nis domain object */ 108 if (SUCCESS != make_nis_domain(dom_name, init_containers)) { 109 if (init_containers) 110 logmsg(MSG_NOTIMECHECK, LOG_ERR, 111 "Could not make nisDomain object for %s", dom_name); 112 else 113 logmsg(MSG_NOTIMECHECK, LOG_ERR, 114 "Problem detected with nisDomain object for %s", 115 dom_name); 116 return (FAILURE); 117 } 118 119 /* Get list of maps from mapping file */ 120 map_list = get_mapping_map_list(dom_name); 121 if (NULL == map_list) { 122 logmsg(MSG_NOTIMECHECK, LOG_ERR, 123 "Could not get map list for %s", dom_name); 124 return (FAILURE); 125 } 126 127 for (i = 0; NULL != map_list[i]; i++) { 128 dump_map_to_dit(map_list[i], dom_name, init_containers); 129 } 130 131 free_map_list(map_list); 132 133 return (SUCCESS); 134 } 135 136 /* 137 * FUNCTION : dump_map_to_dit() 138 * 139 * DESCRIPTION: Dump a OLD STYLE NIS map into the DIT. 140 * 141 * GIVEN : Name of map (not fully qualified) 142 * Name of domain 143 * Flag indicating if containers should be set up. 144 * 145 * RETURNS : SUCCESS = Map copy completed 146 * FAILURE = Map copy not completed 147 */ 148 suc_code 149 dump_map_to_dit(char *map_name, char *domain, bool_t init_containers) 150 { 151 char *myself = "dump_map_to_dit"; 152 DBM *dbm; 153 datum key; 154 datum value; 155 char *map_path; /* Qualified map name */ 156 int entry_count; 157 int next_print; 158 159 printf("Copying map \"%s\", domain \"%s\", to LDAP.\n", 160 map_name, domain); 161 162 /* Create the NIS container */ 163 if (SUCCESS != make_nis_container(map_name, domain, init_containers)) { 164 if (init_containers) 165 logmsg(MSG_NOTIMECHECK, LOG_ERR, 166 "Could not make container for %s %s", 167 map_name, domain); 168 else 169 logmsg(MSG_NOTIMECHECK, LOG_ERR, 170 "Problem detected with container for %s %s", 171 map_name, domain); 172 173 return (FAILURE); 174 } 175 176 /* Make up fully qualified map name */ 177 map_path = (char *)am(myself, strlen(domain) + strlen(map_name) + 178 ypdbpath_sz + 3); 179 if (NULL == map_path) { 180 logmsg(MSG_NOMEM, LOG_ERR, 181 "Could not alloc memory for %s %s", map_name, domain); 182 return (FAILURE); 183 } 184 strcpy(map_path, ypdbpath); 185 add_separator(map_path); 186 strcat(map_path, domain); 187 add_separator(map_path); 188 strcat(map_path, map_name); 189 190 /* Open the DBM file. Use real dbm call */ 191 dbm = dbm_open(map_path, O_RDONLY, 0644); 192 193 /* Finished with full name */ 194 sfree(map_path); 195 196 if (NULL == dbm) { 197 /* 198 * This map probably didn't exist. No problem, user may be 199 * going to populate container using LDAP. 200 */ 201 return (SUCCESS); 202 } 203 204 /* 205 * N2L has no lock for old style maps. No problem ypserv -i is the 206 * only thing that accesses them. 207 */ 208 209 /* For all entries in file */ 210 for (key = dbm_firstkey(dbm), next_print = PRINT_FREQ, entry_count = 1; 211 NULL != key.dptr; key = dbm_nextkey(dbm), entry_count ++) { 212 213 /* Don't write zero length keys */ 214 if (0 == key.dsize) { 215 logmsg(MSG_NOTIMECHECK, LOG_INFO, 216 "Zero length key ignored in %s %s", map_name, domain); 217 continue; 218 } 219 220 /* Don't write 'special' nis entries */ 221 if (is_special_key(&key)) 222 continue; 223 224 /* Get entry */ 225 value = dbm_fetch(dbm, key); 226 227 /* Copy entry to DIT */ 228 if (SUCCESS != write_to_dit(map_name, domain, key, value, 229 TRUE, TRUE)) 230 /* Syslog will have already been done */ 231 break; 232 233 /* If necessary print a progress report */ 234 if (entry_count >= next_print) { 235 printf("%d entries processed.\n", entry_count); 236 next_print *= 2; 237 } 238 } 239 240 dbm_close(dbm); 241 242 return (SUCCESS); 243 } 244 245 /* 246 * FUNCTION : dump_dit_to_maps() 247 * 248 * DESCRIPTION: Dumps the contents of the DIT into the NEW STYLE NIS maps. If 249 * the maps, or their TTL files do not exist creates them. 250 * 251 * Since we are now treating the DIT as authoritative details of 252 * which domains and maps exist are gathered from the DIT. 253 * 254 * GIVEN : Nothing 255 * 256 * RETURNS : Success code 257 */ 258 suc_code 259 dump_dit_to_maps() 260 { 261 char **dom_list; 262 int dom_count; 263 char *dom_path; 264 char **map_list; 265 int i, j; 266 char *myself = "dump_dit_to_maps"; 267 268 /* For all domain objects in DIT */ 269 dom_count = get_mapping_domain_list(&dom_list); 270 271 if (0 == dom_count) { 272 /* No problem, maybe no domains */ 273 return (SUCCESS); 274 } 275 276 /* Dump all domains in list */ 277 for (i = 0; i < dom_count; i++) { 278 279 /* If necessary create domain directory */ 280 dom_path = (char *)am(myself, ypdbpath_sz + 281 strlen(dom_list[i]) + 2); 282 if (NULL == dom_path) { 283 return (FAILURE); 284 } 285 286 strcpy(dom_path, ypdbpath); 287 strcat(dom_path, "/"); 288 strcat(dom_path, dom_list[i]); 289 290 if (0 != mkdir(dom_path, 0644)) { 291 /* If dir exists fine. Just use it */ 292 if (EEXIST != errno) { 293 logmsg(MSG_NOTIMECHECK, LOG_ERR, 294 "Could not make create domain directory %s", 295 dom_path); 296 sfree(dom_path); 297 } 298 } 299 300 sfree(dom_path); 301 302 /* Get list of maps for this domain */ 303 map_list = get_mapping_map_list(dom_list[i]); 304 if (NULL == map_list) { 305 /* No problem. Just no maps in this domain */ 306 continue; 307 } 308 309 /* For all maps in domain */ 310 for (j = 0; map_list[j] != NULL; j++) { 311 /* A normal map update will initialize it. */ 312 if (FAILURE == dump_dit_to_map(map_list[j], 313 dom_list[i])) { 314 free_map_list(map_list); 315 return (FAILURE); 316 } 317 318 /* If we have a netgroup also generate netgroup.byxxx */ 319 if (0 == strcmp(map_list[j], NETGROUP_MAP)) { 320 if (FAILURE == dump_dit_to_map(NETGROUP_BYHOST, 321 dom_list[i])) { 322 free_map_list(map_list); 323 return (FAILURE); 324 } 325 if (FAILURE == dump_dit_to_map(NETGROUP_BYUSER, 326 dom_list[i])) { 327 free_map_list(map_list); 328 return (FAILURE); 329 } 330 } 331 } 332 free_map_list(map_list); 333 } 334 return (SUCCESS); 335 } 336 337 /* 338 * FUNCTION : dump_dit_to_map() 339 * 340 * DESCRIPTION: Dumps the contents of the DIT into one NEW STYLE NIS map. If 341 * the map, or its TTL file does not exist creates them. 342 * 343 * This is the same operation as is carried out when updating a 344 * map that has timed out. As a result we can call the normal 345 * update function. 346 * 347 * 348 * GIVEN : Map name (unqualified) 349 * Domain name. 350 * 351 * RETURNS : SUCCESS = Map copy complete 352 * FAILURE = Problems 353 */ 354 suc_code 355 dump_dit_to_map(char *map_name, char *domain) 356 { 357 char *myself = "dump_dit_to_map"; 358 map_ctrl map; 359 char *map_path; 360 361 printf("Copying LDAP data to map \"%s\", domain \"%s\".\n", 362 map_name, domain); 363 364 /* 365 * To call update_map_from_dit() we need an initialized map_ctrl. 366 * The easiest way to get this is to generate a full path to the new 367 * map and then call map_ctrl_init(). 368 */ 369 map_path = (char *)am(myself, ypdbpath_sz + strlen(map_name) + 370 strlen(domain) + strlen(NTOL_PREFIX) + 3); 371 if (NULL == map_path) 372 return (FAILURE); 373 374 strcpy(map_path, ypdbpath); 375 add_separator(map_path); 376 strcat(map_path, domain); 377 add_separator(map_path); 378 strcat(map_path, NTOL_PREFIX); 379 strcat(map_path, map_name); 380 381 if (FAILURE == map_ctrl_init(&map, map_path)) { 382 sfree(map_path); 383 return (FAILURE); 384 } 385 386 sfree(map_path); 387 388 /* 389 * This is called before anything else is running so don't need to 390 * do normal update lock. 391 */ 392 return (update_map_from_dit(&map, TRUE)); 393 } 394 395 /* 396 * FUNCTION : add_seperator() 397 * 398 * DESCRIPTION: Adds a file separator to a string (which must already be big 399 * enough.) 400 * 401 * GIVEN : Pointer to the string 402 * 403 * RETURNS : Nothing 404 */ 405 void 406 add_separator(char *str) 407 { 408 char *p; 409 410 p = str + strlen(str); 411 *p = SEP_CHAR; 412 *(p+1) = '\0'; 413 }