xref: /onnv-gate/usr/src/lib/libnisdb/yptol/shim_ancil.c (revision 7035:f93a1cefda5f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52189Ssdussud  * Common Development and Distribution License (the "License").
62189Ssdussud  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*7035Svt115884  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved  	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
310Sstevel@tonic-gate  * under license from the Regents of the University of California.
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #ifndef	lint
370Sstevel@tonic-gate static	char sccsid[] = "%Z%%M% %I%     %E% SMI";
380Sstevel@tonic-gate #endif
390Sstevel@tonic-gate 
402189Ssdussud #include <stdlib.h>
410Sstevel@tonic-gate #include <dirent.h>
420Sstevel@tonic-gate #include <strings.h>
430Sstevel@tonic-gate #include "ypsym.h"
440Sstevel@tonic-gate #include "ypdefs.h"
450Sstevel@tonic-gate USE_YPDBPATH
460Sstevel@tonic-gate USE_DBM
470Sstevel@tonic-gate #include "shim.h"
482189Ssdussud #include "../ldap_util.h"
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /*
510Sstevel@tonic-gate  * This constructs a file name from a passed domain name, a passed map name,
520Sstevel@tonic-gate  * and a globally known YP data base path prefix.
530Sstevel@tonic-gate  *
540Sstevel@tonic-gate  * Has to be in shim because it needs the N2L prefix
550Sstevel@tonic-gate  *
560Sstevel@tonic-gate  * RETURNS :	TRUE = A name was successfully created
570Sstevel@tonic-gate  *		FALSE = A name could not be created
580Sstevel@tonic-gate  */
590Sstevel@tonic-gate 
600Sstevel@tonic-gate bool_t
ypmkfilename(domain,map,path)610Sstevel@tonic-gate ypmkfilename(domain, map, path)
620Sstevel@tonic-gate 	char *domain;
630Sstevel@tonic-gate 	char *map;
640Sstevel@tonic-gate 	char *path;
650Sstevel@tonic-gate {
660Sstevel@tonic-gate 	int length;
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 	/* Do not allow any path as a domain name. */
690Sstevel@tonic-gate 	if (strchr(domain, '/') != NULL)
700Sstevel@tonic-gate 		return (FALSE);
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	length = strlen(domain) + strlen(map) + ypdbpath_sz + 3;
730Sstevel@tonic-gate 	if (yptol_mode)
740Sstevel@tonic-gate 		length += strlen(NTOL_PREFIX) + 1;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	if ((MAXNAMLEN + 1) < length) {
772189Ssdussud 		(void) fprintf(stderr, "ypserv:  Map name string too long.\n");
780Sstevel@tonic-gate 		return (FALSE);
790Sstevel@tonic-gate 	}
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	strcpy(path, ypdbpath);
820Sstevel@tonic-gate 	strcat(path, "/");
830Sstevel@tonic-gate 	strcat(path, domain);
840Sstevel@tonic-gate 	strcat(path, "/");
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	/* If in N2L mode add N2L prefix */
870Sstevel@tonic-gate 	if (yptol_mode)
880Sstevel@tonic-gate 		strcat(path, NTOL_PREFIX);
890Sstevel@tonic-gate 	strcat(path, map);
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	return (TRUE);
920Sstevel@tonic-gate }
932189Ssdussud 
942189Ssdussud /*
952189Ssdussud  * check whether a map is already in an array/list
962189Ssdussud  *
972189Ssdussud  * RETURNS: TRUE if yes
982189Ssdussud  *          FALSE if not
992189Ssdussud  */
1002189Ssdussud bool_t
on_maplist(char * mapname,char ** list)1012189Ssdussud on_maplist(char *mapname, char **list) {
1022189Ssdussud 	int i = 0;
1032189Ssdussud 
1042189Ssdussud 	if (list == NULL) {
1052189Ssdussud 		return (FALSE);
1062189Ssdussud 	}
1072189Ssdussud 
1082189Ssdussud 	while (list[i] != NULL) {
1092189Ssdussud 		if (strcmp(mapname, list[i++]) == 0) {
1102189Ssdussud 			return (TRUE);
1112189Ssdussud 		}
1122189Ssdussud 	}
1132189Ssdussud 
1142189Ssdussud 	return (FALSE);
1152189Ssdussud }
1162189Ssdussud 
1172189Ssdussud /*
1182189Ssdussud  * add a map at the end of an array/list
1192189Ssdussud  *
1202189Ssdussud  * list_len: if -1, we do not know list length
1212189Ssdussud  *
1222189Ssdussud  * RETURNS: TRUE if map was added
1232189Ssdussud  *          FALSE if not
1242189Ssdussud  */
1252189Ssdussud bool_t
add_in_maplist(char * mapname,char *** list,int * list_len)1262189Ssdussud add_in_maplist(char *mapname, char ***list, int *list_len) {
1272189Ssdussud 	int i = 0;
1282189Ssdussud 	char **list_tmp;
1292189Ssdussud 
1302189Ssdussud 	if (list == NULL) {
1312189Ssdussud 		return (FALSE);
1322189Ssdussud 	}
1332189Ssdussud 
1342189Ssdussud 	list_tmp = *list;
1352189Ssdussud 
1362189Ssdussud 	if (list_tmp == NULL) {
1372189Ssdussud 		*list_len = 0;
1382189Ssdussud 	} else {
1392189Ssdussud 		/* find 1st free element */
1402189Ssdussud 		while (list_tmp[i] != NULL) {
1412189Ssdussud 			/*
1422189Ssdussud 			 * increment in loop so that
1432189Ssdussud 			 * list_tmp[i] == NULL
1442189Ssdussud 			 * when exiting
1452189Ssdussud 			 */
1462189Ssdussud 			i++;
1472189Ssdussud 		}
1482189Ssdussud 	}
1492189Ssdussud 
1502189Ssdussud 	/* if we don't know list length, assume we reach its end */
1512189Ssdussud 	if (*list_len == -1) {
1522189Ssdussud 		*list_len = i;
1532189Ssdussud 	}
1542189Ssdussud 
1552189Ssdussud 	/* do we need to reallocate ? */
1562189Ssdussud 	if (i+1 >= *list_len) {
1572189Ssdussud 		list_tmp = (char **)realloc(list_tmp,
1582189Ssdussud 				    (*list_len + ARRAY_CHUNK) *
1592189Ssdussud 					sizeof (char *));
1602189Ssdussud 		if (list_tmp == NULL) {
1612189Ssdussud 			return (FALSE);
1622189Ssdussud 		}
1632189Ssdussud 		*list = list_tmp;
1642189Ssdussud 		*list_len += ARRAY_CHUNK;
1652189Ssdussud 	}
1662189Ssdussud 
1672189Ssdussud 	/* add in list */
1682189Ssdussud 	(*list)[i] = strdup(mapname);
1692189Ssdussud 	if ((*list)[i] == NULL) {
1702189Ssdussud 		/* strdup() failed */
1712189Ssdussud 		return (FALSE);
1722189Ssdussud 	}
1732189Ssdussud 	(*list)[++i] = NULL;
1742189Ssdussud 
1752189Ssdussud 	return (TRUE);
1762189Ssdussud }
1772189Ssdussud 
1782189Ssdussud /*
1792189Ssdussud  * This checks to see whether a domain name is present at the local node as a
1802189Ssdussud  * subdirectory of ypdbpath
1812189Ssdussud  *
1822189Ssdussud  * Was originally in cmd/ypcmd/shared/ancil.c as ypcheck_domain(domain).
1832189Ssdussud  * Now ypcheck_domain(domain) calls this function.
1842189Ssdussud  */
1852189Ssdussud bool
ypcheck_domain_yptol(char * domain)1862189Ssdussud ypcheck_domain_yptol(char *domain)
1872189Ssdussud {
1882189Ssdussud 	char path[MAXNAMLEN + 1];
1892189Ssdussud 	struct stat filestat;
1902189Ssdussud 	bool present = FALSE;
1912189Ssdussud 
1922189Ssdussud 	strcpy(path, ypdbpath);
1932189Ssdussud 	strcat(path, "/");
1942189Ssdussud 	if (strlcat(path, domain, MAXNAMLEN + 1) >=  MAXNAMLEN + 1)
1952189Ssdussud 		return (present);
1962189Ssdussud 
1972189Ssdussud 	if (stat(path, &filestat) != -1) {
1982189Ssdussud 		if (S_ISDIR(filestat.st_mode))
1992189Ssdussud 			present = TRUE;
2002189Ssdussud 	}
2012189Ssdussud 	return (present);
2022189Ssdussud }
2032189Ssdussud 
2042189Ssdussud /*
2052189Ssdussud  * This performs an existence check on the dbm data base files <name>.pag and
2062189Ssdussud  * <name>.dir.  pname is a ptr to the filename.  This should be an absolute
2072189Ssdussud  * path.
2082189Ssdussud  * Returns TRUE if the map exists and is accessible; else FALSE.
2092189Ssdussud  *
2102189Ssdussud  * Note:  The file name should be a "base" form, without a file "extension" of
2112189Ssdussud  * .dir or .pag appended.  See ypmkfilename for a function which will generate
2122189Ssdussud  * the name correctly.  Errors in the stat call will be reported at this level,
2132189Ssdussud  * however, the non-existence of a file is not considered an error, and so will
2142189Ssdussud  * not be reported.
2152189Ssdussud  *
2162189Ssdussud  * Was originally in cmd/ypcmd/shared/utils.c as ypcheck_map_existence().
2172189Ssdussud  * Now ypcheck_map_existence() calls this function.
2182189Ssdussud  */
2192189Ssdussud bool
ypcheck_map_existence_yptol(char * pname)2202189Ssdussud ypcheck_map_existence_yptol(char *pname)
2212189Ssdussud {
2222189Ssdussud 	char dbfile[MAXNAMLEN + sizeof (TTL_POSTFIX) + 1];
223*7035Svt115884 	struct stat64 filestat;
2242189Ssdussud 	int len;
2252189Ssdussud 
2262189Ssdussud 	if (!pname || ((len = (int)strlen(pname)) == 0) ||
2272189Ssdussud 	    (len + sizeof (dbm_pag) + sizeof (TTL_POSTFIX)) >
2282189Ssdussud 	    sizeof (dbfile)) {
2292189Ssdussud 		return (FALSE);
2302189Ssdussud 	}
2312189Ssdussud 
2322189Ssdussud 	errno = 0;
2332189Ssdussud 
2342189Ssdussud 	/* Check for existance of .dir file */
2352189Ssdussud 	(void) strcpy(dbfile, pname);
2362189Ssdussud 	(void) strcat(dbfile, dbm_dir);
2372189Ssdussud 
238*7035Svt115884 	if (stat64(dbfile, &filestat) == -1) {
2392189Ssdussud 		if (errno != ENOENT) {
2402189Ssdussud 			(void) fprintf(stderr,
241*7035Svt115884 			    "ypserv:  Stat error on map file %s.\n",
242*7035Svt115884 			    dbfile);
2432189Ssdussud 		}
2442189Ssdussud 		return (FALSE);
2452189Ssdussud 	}
2462189Ssdussud 
2472189Ssdussud 	/* Check for existance of .pag file */
2482189Ssdussud 	(void) strcpy(dbfile, pname);
2492189Ssdussud 	(void) strcat(dbfile, dbm_pag);
2502189Ssdussud 
251*7035Svt115884 	if (stat64(dbfile, &filestat) == -1) {
2522189Ssdussud 		if (errno != ENOENT) {
2532189Ssdussud 			(void) fprintf(stderr,
254*7035Svt115884 			    "ypserv:  Stat error on map file %s.\n",
255*7035Svt115884 			    dbfile);
2562189Ssdussud 		}
2572189Ssdussud 		return (FALSE);
2582189Ssdussud 	}
2592189Ssdussud 
2602189Ssdussud 	if (yptol_mode) {
2612189Ssdussud 		/* Check for existance of TTL .dir file */
2622189Ssdussud 		(void) strcpy(dbfile, pname);
2632189Ssdussud 		(void) strcat(dbfile, TTL_POSTFIX);
2642189Ssdussud 		(void) strcat(dbfile, dbm_dir);
2652189Ssdussud 
266*7035Svt115884 		if (stat64(dbfile, &filestat) == -1) {
2672189Ssdussud 			if (errno != ENOENT) {
2682189Ssdussud 				(void) fprintf(stderr,
269*7035Svt115884 				    "ypserv:  Stat error on map file %s.\n",
270*7035Svt115884 				    dbfile);
2712189Ssdussud 			}
2722189Ssdussud 			return (FALSE);
2732189Ssdussud 		}
2742189Ssdussud 
2752189Ssdussud 		/* Check for existance of TTL .pag file */
2762189Ssdussud 		(void) strcpy(dbfile, pname);
2772189Ssdussud 		(void) strcat(dbfile, TTL_POSTFIX);
2782189Ssdussud 		(void) strcat(dbfile, dbm_pag);
2792189Ssdussud 
280*7035Svt115884 		if (stat64(dbfile, &filestat) == -1) {
2812189Ssdussud 			if (errno != ENOENT) {
2822189Ssdussud 				(void) fprintf(stderr,
283*7035Svt115884 				    "ypserv:  Stat error on map file %s.\n",
284*7035Svt115884 				    dbfile);
2852189Ssdussud 			}
2862189Ssdussud 			return (FALSE);
2872189Ssdussud 		}
2882189Ssdussud 	}
2892189Ssdussud 
2902189Ssdussud 	return (TRUE);
2912189Ssdussud }
2922189Ssdussud 
2932189Ssdussud /*
2942189Ssdussud  * This adds maps in a domain to a given list,
2952189Ssdussud  * from maps in /var/yp/<domain>
2962189Ssdussud  * Inspired from yplist_maps() in cmd/ypcmd/ypserv_ancil.c
2972189Ssdussud  *
2982189Ssdussud  * domain is the relevant domain name
2992189Ssdussud  * map_list is the list of maps in an array of map names,
3002189Ssdussud  *    which may or may not be empty
3012189Ssdussud  *
3022189Ssdussud  * RETURNS :    TRUE = everything went fine
3032189Ssdussud  *              FALSE = an error occured
3042189Ssdussud  */
3052189Ssdussud bool_t
add_map_domain_to_list(char * domain,char *** map_list)3062189Ssdussud add_map_domain_to_list(char *domain, char ***map_list)
3072189Ssdussud {
3082189Ssdussud 	char domdir[MAXNAMLEN + 1];
3092189Ssdussud 	char path[MAXNAMLEN + 1];
3102189Ssdussud 	int domdir_len = sizeof (domdir);
3112189Ssdussud 	DIR *dirp;
3122189Ssdussud 	struct dirent *dp;
3132189Ssdussud 	int name_len;
3142189Ssdussud 	int dbm_pag_len = sizeof (dbm_pag);
3152189Ssdussud 	char *ext;
3162189Ssdussud 	char *mapname;
3172189Ssdussud 	int map_list_len = -1;
3182189Ssdussud 
3192189Ssdussud 	if (map_list == NULL) {
3202189Ssdussud 		return (FALSE);
3212189Ssdussud 	}
3222189Ssdussud 
3232189Ssdussud 	/* no domain, not a problem */
3242189Ssdussud 	if (domain == NULL) {
3252189Ssdussud 		return (TRUE);
3262189Ssdussud 	}
3272189Ssdussud 
3282189Ssdussud 	/* not a valid domain, not a problem */
3292189Ssdussud 	if (!ypcheck_domain_yptol(domain)) {
3302189Ssdussud 		return (TRUE);
3312189Ssdussud 	}
3322189Ssdussud 
3332189Ssdussud 	if (snprintf(domdir, domdir_len, "%s/%s", ypdbpath, domain)
3342189Ssdussud 	    > domdir_len) {
3352189Ssdussud 		return (FALSE);
3362189Ssdussud 	}
3372189Ssdussud 
3382189Ssdussud 	if ((dirp = opendir(domdir)) == NULL) {
3392189Ssdussud 		return (FALSE);
3402189Ssdussud 	}
3412189Ssdussud 
3422189Ssdussud 	for (dp = readdir(dirp); dp != NULL;
3432189Ssdussud 	    dp = readdir(dirp)) {
3442189Ssdussud 		/*
3452189Ssdussud 		 * If it's possible that the file name is one of the two files
3462189Ssdussud 		 * implementing a map, remove the extension (dbm_pag or dbm_dir)
3472189Ssdussud 		 */
3482189Ssdussud 		name_len = (int)strlen(dp->d_name);
3492189Ssdussud 
3502189Ssdussud 		if (name_len < dbm_pag_len - 1) {
3512189Ssdussud 			continue;		/* Too Short */
3522189Ssdussud 		}
3532189Ssdussud 
3542189Ssdussud 		ext = &(dp->d_name[name_len - (dbm_pag_len - 1)]);
3552189Ssdussud 
3562189Ssdussud 		if (strcmp(ext, dbm_pag) != 0) {
3572189Ssdussud 			continue;		/* No dbm file extension */
3582189Ssdussud 		}
3592189Ssdussud 
3602189Ssdussud 		*ext = '\0';
3612189Ssdussud 
3622189Ssdussud 		/*
3632189Ssdussud 		 * In yptol mode look at LDAP_ prefixed maps. In non yptol mode
3642189Ssdussud 		 * ignore them.
3652189Ssdussud 		 */
3662189Ssdussud 		if (yptol_mode) {
3672189Ssdussud 			if (0 != strncmp(dp->d_name, NTOL_PREFIX,
3682189Ssdussud 			    strlen(NTOL_PREFIX))) {
3692189Ssdussud 				continue;
3702189Ssdussud 			}
3712189Ssdussud 
3722189Ssdussud 			/*
3732189Ssdussud 			 * Already have an LDAP_ prefix. Don't want to add it
3742189Ssdussud 			 * twice.
3752189Ssdussud 			 */
3762189Ssdussud 			mapname = dp->d_name + strlen(NTOL_PREFIX);
3772189Ssdussud 		} else {
3782189Ssdussud 			if (0 == strncmp(dp->d_name, NTOL_PREFIX,
3792189Ssdussud 			    strlen(NTOL_PREFIX))) {
3802189Ssdussud 				continue;
3812189Ssdussud 			}
3822189Ssdussud 			mapname = dp->d_name;
3832189Ssdussud 		}
3842189Ssdussud 
3852189Ssdussud 		if (ypmkfilename(domain, mapname, path) == FALSE) {
3862189Ssdussud 			(void) closedir(dirp);
3872189Ssdussud 			return (FALSE);
3882189Ssdussud 		}
3892189Ssdussud 
3902189Ssdussud 		/*
3912189Ssdussud 		 * At this point, path holds the map file base name (no dbm
3922189Ssdussud 		 * file extension), and mapname holds the map name.
3932189Ssdussud 		 */
3942189Ssdussud 		if (ypcheck_map_existence_yptol(path) &&
3952189Ssdussud 		    !on_maplist(mapname, *map_list)) {
3962189Ssdussud 			if (add_in_maplist(mapname, map_list, &map_list_len) ==
3972189Ssdussud 			    FALSE) {
3982189Ssdussud 				(void) closedir(dirp);
3992189Ssdussud 				return (FALSE);
4002189Ssdussud 			}
4012189Ssdussud 		}
4022189Ssdussud 	}
4032189Ssdussud 
4042189Ssdussud 	(void) closedir(dirp);
4052189Ssdussud 	return (TRUE);
4062189Ssdussud }
407