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
dump_maps_to_dit(bool_t init_containers)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
dump_domain_to_dit(char * dom_name,bool_t init_containers)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
dump_map_to_dit(char * map_name,char * domain,bool_t init_containers)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
dump_dit_to_maps()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
dump_dit_to_map(char * map_name,char * domain)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
add_separator(char * str)406 add_separator(char *str)
407 {
408 char *p;
409
410 p = str + strlen(str);
411 *p = SEP_CHAR;
412 *(p+1) = '\0';
413 }
414