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