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
dump_maps_to_dit(bool_t init_containers)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
dump_domain_to_dit(char * dom_name,bool_t init_containers)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
dump_map_to_dit(char * map_name,char * domain,bool_t init_containers)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
dump_dit_to_maps()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
dump_dit_to_map(char * map_name,char * domain)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
add_separator(char * str)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