xref: /titanic_44/usr/src/lib/libnisdb/yptol/shim_ancil.c (revision b892d001be3e81239c3493ef95a5605d427dd3ce)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54a190493Ssdussud  * Common Development and Distribution License (the "License").
64a190493Ssdussud  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*b892d001Svt115884  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
317c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #ifndef	lint
377c478bd9Sstevel@tonic-gate static	char sccsid[] = "%Z%%M% %I%     %E% SMI";
387c478bd9Sstevel@tonic-gate #endif
397c478bd9Sstevel@tonic-gate 
404a190493Ssdussud #include <stdlib.h>
417c478bd9Sstevel@tonic-gate #include <dirent.h>
427c478bd9Sstevel@tonic-gate #include <strings.h>
437c478bd9Sstevel@tonic-gate #include "ypsym.h"
447c478bd9Sstevel@tonic-gate #include "ypdefs.h"
457c478bd9Sstevel@tonic-gate USE_YPDBPATH
467c478bd9Sstevel@tonic-gate USE_DBM
477c478bd9Sstevel@tonic-gate #include "shim.h"
484a190493Ssdussud #include "../ldap_util.h"
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate  * This constructs a file name from a passed domain name, a passed map name,
527c478bd9Sstevel@tonic-gate  * and a globally known YP data base path prefix.
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  * Has to be in shim because it needs the N2L prefix
557c478bd9Sstevel@tonic-gate  *
567c478bd9Sstevel@tonic-gate  * RETURNS :	TRUE = A name was successfully created
577c478bd9Sstevel@tonic-gate  *		FALSE = A name could not be created
587c478bd9Sstevel@tonic-gate  */
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate bool_t
ypmkfilename(domain,map,path)617c478bd9Sstevel@tonic-gate ypmkfilename(domain, map, path)
627c478bd9Sstevel@tonic-gate 	char *domain;
637c478bd9Sstevel@tonic-gate 	char *map;
647c478bd9Sstevel@tonic-gate 	char *path;
657c478bd9Sstevel@tonic-gate {
667c478bd9Sstevel@tonic-gate 	int length;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	/* Do not allow any path as a domain name. */
697c478bd9Sstevel@tonic-gate 	if (strchr(domain, '/') != NULL)
707c478bd9Sstevel@tonic-gate 		return (FALSE);
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	length = strlen(domain) + strlen(map) + ypdbpath_sz + 3;
737c478bd9Sstevel@tonic-gate 	if (yptol_mode)
747c478bd9Sstevel@tonic-gate 		length += strlen(NTOL_PREFIX) + 1;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	if ((MAXNAMLEN + 1) < length) {
774a190493Ssdussud 		(void) fprintf(stderr, "ypserv:  Map name string too long.\n");
787c478bd9Sstevel@tonic-gate 		return (FALSE);
797c478bd9Sstevel@tonic-gate 	}
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	strcpy(path, ypdbpath);
827c478bd9Sstevel@tonic-gate 	strcat(path, "/");
837c478bd9Sstevel@tonic-gate 	strcat(path, domain);
847c478bd9Sstevel@tonic-gate 	strcat(path, "/");
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	/* If in N2L mode add N2L prefix */
877c478bd9Sstevel@tonic-gate 	if (yptol_mode)
887c478bd9Sstevel@tonic-gate 		strcat(path, NTOL_PREFIX);
897c478bd9Sstevel@tonic-gate 	strcat(path, map);
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	return (TRUE);
927c478bd9Sstevel@tonic-gate }
934a190493Ssdussud 
944a190493Ssdussud /*
954a190493Ssdussud  * check whether a map is already in an array/list
964a190493Ssdussud  *
974a190493Ssdussud  * RETURNS: TRUE if yes
984a190493Ssdussud  *          FALSE if not
994a190493Ssdussud  */
1004a190493Ssdussud bool_t
on_maplist(char * mapname,char ** list)1014a190493Ssdussud on_maplist(char *mapname, char **list) {
1024a190493Ssdussud 	int i = 0;
1034a190493Ssdussud 
1044a190493Ssdussud 	if (list == NULL) {
1054a190493Ssdussud 		return (FALSE);
1064a190493Ssdussud 	}
1074a190493Ssdussud 
1084a190493Ssdussud 	while (list[i] != NULL) {
1094a190493Ssdussud 		if (strcmp(mapname, list[i++]) == 0) {
1104a190493Ssdussud 			return (TRUE);
1114a190493Ssdussud 		}
1124a190493Ssdussud 	}
1134a190493Ssdussud 
1144a190493Ssdussud 	return (FALSE);
1154a190493Ssdussud }
1164a190493Ssdussud 
1174a190493Ssdussud /*
1184a190493Ssdussud  * add a map at the end of an array/list
1194a190493Ssdussud  *
1204a190493Ssdussud  * list_len: if -1, we do not know list length
1214a190493Ssdussud  *
1224a190493Ssdussud  * RETURNS: TRUE if map was added
1234a190493Ssdussud  *          FALSE if not
1244a190493Ssdussud  */
1254a190493Ssdussud bool_t
add_in_maplist(char * mapname,char *** list,int * list_len)1264a190493Ssdussud add_in_maplist(char *mapname, char ***list, int *list_len) {
1274a190493Ssdussud 	int i = 0;
1284a190493Ssdussud 	char **list_tmp;
1294a190493Ssdussud 
1304a190493Ssdussud 	if (list == NULL) {
1314a190493Ssdussud 		return (FALSE);
1324a190493Ssdussud 	}
1334a190493Ssdussud 
1344a190493Ssdussud 	list_tmp = *list;
1354a190493Ssdussud 
1364a190493Ssdussud 	if (list_tmp == NULL) {
1374a190493Ssdussud 		*list_len = 0;
1384a190493Ssdussud 	} else {
1394a190493Ssdussud 		/* find 1st free element */
1404a190493Ssdussud 		while (list_tmp[i] != NULL) {
1414a190493Ssdussud 			/*
1424a190493Ssdussud 			 * increment in loop so that
1434a190493Ssdussud 			 * list_tmp[i] == NULL
1444a190493Ssdussud 			 * when exiting
1454a190493Ssdussud 			 */
1464a190493Ssdussud 			i++;
1474a190493Ssdussud 		}
1484a190493Ssdussud 	}
1494a190493Ssdussud 
1504a190493Ssdussud 	/* if we don't know list length, assume we reach its end */
1514a190493Ssdussud 	if (*list_len == -1) {
1524a190493Ssdussud 		*list_len = i;
1534a190493Ssdussud 	}
1544a190493Ssdussud 
1554a190493Ssdussud 	/* do we need to reallocate ? */
1564a190493Ssdussud 	if (i+1 >= *list_len) {
1574a190493Ssdussud 		list_tmp = (char **)realloc(list_tmp,
1584a190493Ssdussud 				    (*list_len + ARRAY_CHUNK) *
1594a190493Ssdussud 					sizeof (char *));
1604a190493Ssdussud 		if (list_tmp == NULL) {
1614a190493Ssdussud 			return (FALSE);
1624a190493Ssdussud 		}
1634a190493Ssdussud 		*list = list_tmp;
1644a190493Ssdussud 		*list_len += ARRAY_CHUNK;
1654a190493Ssdussud 	}
1664a190493Ssdussud 
1674a190493Ssdussud 	/* add in list */
1684a190493Ssdussud 	(*list)[i] = strdup(mapname);
1694a190493Ssdussud 	if ((*list)[i] == NULL) {
1704a190493Ssdussud 		/* strdup() failed */
1714a190493Ssdussud 		return (FALSE);
1724a190493Ssdussud 	}
1734a190493Ssdussud 	(*list)[++i] = NULL;
1744a190493Ssdussud 
1754a190493Ssdussud 	return (TRUE);
1764a190493Ssdussud }
1774a190493Ssdussud 
1784a190493Ssdussud /*
1794a190493Ssdussud  * This checks to see whether a domain name is present at the local node as a
1804a190493Ssdussud  * subdirectory of ypdbpath
1814a190493Ssdussud  *
1824a190493Ssdussud  * Was originally in cmd/ypcmd/shared/ancil.c as ypcheck_domain(domain).
1834a190493Ssdussud  * Now ypcheck_domain(domain) calls this function.
1844a190493Ssdussud  */
1854a190493Ssdussud bool
ypcheck_domain_yptol(char * domain)1864a190493Ssdussud ypcheck_domain_yptol(char *domain)
1874a190493Ssdussud {
1884a190493Ssdussud 	char path[MAXNAMLEN + 1];
1894a190493Ssdussud 	struct stat filestat;
1904a190493Ssdussud 	bool present = FALSE;
1914a190493Ssdussud 
1924a190493Ssdussud 	strcpy(path, ypdbpath);
1934a190493Ssdussud 	strcat(path, "/");
1944a190493Ssdussud 	if (strlcat(path, domain, MAXNAMLEN + 1) >=  MAXNAMLEN + 1)
1954a190493Ssdussud 		return (present);
1964a190493Ssdussud 
1974a190493Ssdussud 	if (stat(path, &filestat) != -1) {
1984a190493Ssdussud 		if (S_ISDIR(filestat.st_mode))
1994a190493Ssdussud 			present = TRUE;
2004a190493Ssdussud 	}
2014a190493Ssdussud 	return (present);
2024a190493Ssdussud }
2034a190493Ssdussud 
2044a190493Ssdussud /*
2054a190493Ssdussud  * This performs an existence check on the dbm data base files <name>.pag and
2064a190493Ssdussud  * <name>.dir.  pname is a ptr to the filename.  This should be an absolute
2074a190493Ssdussud  * path.
2084a190493Ssdussud  * Returns TRUE if the map exists and is accessible; else FALSE.
2094a190493Ssdussud  *
2104a190493Ssdussud  * Note:  The file name should be a "base" form, without a file "extension" of
2114a190493Ssdussud  * .dir or .pag appended.  See ypmkfilename for a function which will generate
2124a190493Ssdussud  * the name correctly.  Errors in the stat call will be reported at this level,
2134a190493Ssdussud  * however, the non-existence of a file is not considered an error, and so will
2144a190493Ssdussud  * not be reported.
2154a190493Ssdussud  *
2164a190493Ssdussud  * Was originally in cmd/ypcmd/shared/utils.c as ypcheck_map_existence().
2174a190493Ssdussud  * Now ypcheck_map_existence() calls this function.
2184a190493Ssdussud  */
2194a190493Ssdussud bool
ypcheck_map_existence_yptol(char * pname)2204a190493Ssdussud ypcheck_map_existence_yptol(char *pname)
2214a190493Ssdussud {
2224a190493Ssdussud 	char dbfile[MAXNAMLEN + sizeof (TTL_POSTFIX) + 1];
223*b892d001Svt115884 	struct stat64 filestat;
2244a190493Ssdussud 	int len;
2254a190493Ssdussud 
2264a190493Ssdussud 	if (!pname || ((len = (int)strlen(pname)) == 0) ||
2274a190493Ssdussud 	    (len + sizeof (dbm_pag) + sizeof (TTL_POSTFIX)) >
2284a190493Ssdussud 	    sizeof (dbfile)) {
2294a190493Ssdussud 		return (FALSE);
2304a190493Ssdussud 	}
2314a190493Ssdussud 
2324a190493Ssdussud 	errno = 0;
2334a190493Ssdussud 
2344a190493Ssdussud 	/* Check for existance of .dir file */
2354a190493Ssdussud 	(void) strcpy(dbfile, pname);
2364a190493Ssdussud 	(void) strcat(dbfile, dbm_dir);
2374a190493Ssdussud 
238*b892d001Svt115884 	if (stat64(dbfile, &filestat) == -1) {
2394a190493Ssdussud 		if (errno != ENOENT) {
2404a190493Ssdussud 			(void) fprintf(stderr,
2414a190493Ssdussud 			    "ypserv:  Stat error on map file %s.\n",
2424a190493Ssdussud 			    dbfile);
2434a190493Ssdussud 		}
2444a190493Ssdussud 		return (FALSE);
2454a190493Ssdussud 	}
2464a190493Ssdussud 
2474a190493Ssdussud 	/* Check for existance of .pag file */
2484a190493Ssdussud 	(void) strcpy(dbfile, pname);
2494a190493Ssdussud 	(void) strcat(dbfile, dbm_pag);
2504a190493Ssdussud 
251*b892d001Svt115884 	if (stat64(dbfile, &filestat) == -1) {
2524a190493Ssdussud 		if (errno != ENOENT) {
2534a190493Ssdussud 			(void) fprintf(stderr,
2544a190493Ssdussud 			    "ypserv:  Stat error on map file %s.\n",
2554a190493Ssdussud 			    dbfile);
2564a190493Ssdussud 		}
2574a190493Ssdussud 		return (FALSE);
2584a190493Ssdussud 	}
2594a190493Ssdussud 
2604a190493Ssdussud 	if (yptol_mode) {
2614a190493Ssdussud 		/* Check for existance of TTL .dir file */
2624a190493Ssdussud 		(void) strcpy(dbfile, pname);
2634a190493Ssdussud 		(void) strcat(dbfile, TTL_POSTFIX);
2644a190493Ssdussud 		(void) strcat(dbfile, dbm_dir);
2654a190493Ssdussud 
266*b892d001Svt115884 		if (stat64(dbfile, &filestat) == -1) {
2674a190493Ssdussud 			if (errno != ENOENT) {
2684a190493Ssdussud 				(void) fprintf(stderr,
2694a190493Ssdussud 				    "ypserv:  Stat error on map file %s.\n",
2704a190493Ssdussud 				    dbfile);
2714a190493Ssdussud 			}
2724a190493Ssdussud 			return (FALSE);
2734a190493Ssdussud 		}
2744a190493Ssdussud 
2754a190493Ssdussud 		/* Check for existance of TTL .pag file */
2764a190493Ssdussud 		(void) strcpy(dbfile, pname);
2774a190493Ssdussud 		(void) strcat(dbfile, TTL_POSTFIX);
2784a190493Ssdussud 		(void) strcat(dbfile, dbm_pag);
2794a190493Ssdussud 
280*b892d001Svt115884 		if (stat64(dbfile, &filestat) == -1) {
2814a190493Ssdussud 			if (errno != ENOENT) {
2824a190493Ssdussud 				(void) fprintf(stderr,
2834a190493Ssdussud 				    "ypserv:  Stat error on map file %s.\n",
2844a190493Ssdussud 				    dbfile);
2854a190493Ssdussud 			}
2864a190493Ssdussud 			return (FALSE);
2874a190493Ssdussud 		}
2884a190493Ssdussud 	}
2894a190493Ssdussud 
2904a190493Ssdussud 	return (TRUE);
2914a190493Ssdussud }
2924a190493Ssdussud 
2934a190493Ssdussud /*
2944a190493Ssdussud  * This adds maps in a domain to a given list,
2954a190493Ssdussud  * from maps in /var/yp/<domain>
2964a190493Ssdussud  * Inspired from yplist_maps() in cmd/ypcmd/ypserv_ancil.c
2974a190493Ssdussud  *
2984a190493Ssdussud  * domain is the relevant domain name
2994a190493Ssdussud  * map_list is the list of maps in an array of map names,
3004a190493Ssdussud  *    which may or may not be empty
3014a190493Ssdussud  *
3024a190493Ssdussud  * RETURNS :    TRUE = everything went fine
3034a190493Ssdussud  *              FALSE = an error occured
3044a190493Ssdussud  */
3054a190493Ssdussud bool_t
add_map_domain_to_list(char * domain,char *** map_list)3064a190493Ssdussud add_map_domain_to_list(char *domain, char ***map_list)
3074a190493Ssdussud {
3084a190493Ssdussud 	char domdir[MAXNAMLEN + 1];
3094a190493Ssdussud 	char path[MAXNAMLEN + 1];
3104a190493Ssdussud 	int domdir_len = sizeof (domdir);
3114a190493Ssdussud 	DIR *dirp;
3124a190493Ssdussud 	struct dirent *dp;
3134a190493Ssdussud 	int name_len;
3144a190493Ssdussud 	int dbm_pag_len = sizeof (dbm_pag);
3154a190493Ssdussud 	char *ext;
3164a190493Ssdussud 	char *mapname;
3174a190493Ssdussud 	int map_list_len = -1;
3184a190493Ssdussud 
3194a190493Ssdussud 	if (map_list == NULL) {
3204a190493Ssdussud 		return (FALSE);
3214a190493Ssdussud 	}
3224a190493Ssdussud 
3234a190493Ssdussud 	/* no domain, not a problem */
3244a190493Ssdussud 	if (domain == NULL) {
3254a190493Ssdussud 		return (TRUE);
3264a190493Ssdussud 	}
3274a190493Ssdussud 
3284a190493Ssdussud 	/* not a valid domain, not a problem */
3294a190493Ssdussud 	if (!ypcheck_domain_yptol(domain)) {
3304a190493Ssdussud 		return (TRUE);
3314a190493Ssdussud 	}
3324a190493Ssdussud 
3334a190493Ssdussud 	if (snprintf(domdir, domdir_len, "%s/%s", ypdbpath, domain)
3344a190493Ssdussud 	    > domdir_len) {
3354a190493Ssdussud 		return (FALSE);
3364a190493Ssdussud 	}
3374a190493Ssdussud 
3384a190493Ssdussud 	if ((dirp = opendir(domdir)) == NULL) {
3394a190493Ssdussud 		return (FALSE);
3404a190493Ssdussud 	}
3414a190493Ssdussud 
3424a190493Ssdussud 	for (dp = readdir(dirp); dp != NULL;
3434a190493Ssdussud 	    dp = readdir(dirp)) {
3444a190493Ssdussud 		/*
3454a190493Ssdussud 		 * If it's possible that the file name is one of the two files
3464a190493Ssdussud 		 * implementing a map, remove the extension (dbm_pag or dbm_dir)
3474a190493Ssdussud 		 */
3484a190493Ssdussud 		name_len = (int)strlen(dp->d_name);
3494a190493Ssdussud 
3504a190493Ssdussud 		if (name_len < dbm_pag_len - 1) {
3514a190493Ssdussud 			continue;		/* Too Short */
3524a190493Ssdussud 		}
3534a190493Ssdussud 
3544a190493Ssdussud 		ext = &(dp->d_name[name_len - (dbm_pag_len - 1)]);
3554a190493Ssdussud 
3564a190493Ssdussud 		if (strcmp(ext, dbm_pag) != 0) {
3574a190493Ssdussud 			continue;		/* No dbm file extension */
3584a190493Ssdussud 		}
3594a190493Ssdussud 
3604a190493Ssdussud 		*ext = '\0';
3614a190493Ssdussud 
3624a190493Ssdussud 		/*
3634a190493Ssdussud 		 * In yptol mode look at LDAP_ prefixed maps. In non yptol mode
3644a190493Ssdussud 		 * ignore them.
3654a190493Ssdussud 		 */
3664a190493Ssdussud 		if (yptol_mode) {
3674a190493Ssdussud 			if (0 != strncmp(dp->d_name, NTOL_PREFIX,
3684a190493Ssdussud 			    strlen(NTOL_PREFIX))) {
3694a190493Ssdussud 				continue;
3704a190493Ssdussud 			}
3714a190493Ssdussud 
3724a190493Ssdussud 			/*
3734a190493Ssdussud 			 * Already have an LDAP_ prefix. Don't want to add it
3744a190493Ssdussud 			 * twice.
3754a190493Ssdussud 			 */
3764a190493Ssdussud 			mapname = dp->d_name + strlen(NTOL_PREFIX);
3774a190493Ssdussud 		} else {
3784a190493Ssdussud 			if (0 == strncmp(dp->d_name, NTOL_PREFIX,
3794a190493Ssdussud 			    strlen(NTOL_PREFIX))) {
3804a190493Ssdussud 				continue;
3814a190493Ssdussud 			}
3824a190493Ssdussud 			mapname = dp->d_name;
3834a190493Ssdussud 		}
3844a190493Ssdussud 
3854a190493Ssdussud 		if (ypmkfilename(domain, mapname, path) == FALSE) {
3864a190493Ssdussud 			(void) closedir(dirp);
3874a190493Ssdussud 			return (FALSE);
3884a190493Ssdussud 		}
3894a190493Ssdussud 
3904a190493Ssdussud 		/*
3914a190493Ssdussud 		 * At this point, path holds the map file base name (no dbm
3924a190493Ssdussud 		 * file extension), and mapname holds the map name.
3934a190493Ssdussud 		 */
3944a190493Ssdussud 		if (ypcheck_map_existence_yptol(path) &&
3954a190493Ssdussud 		    !on_maplist(mapname, *map_list)) {
3964a190493Ssdussud 			if (add_in_maplist(mapname, map_list, &map_list_len) ==
3974a190493Ssdussud 			    FALSE) {
3984a190493Ssdussud 				(void) closedir(dirp);
3994a190493Ssdussud 				return (FALSE);
4004a190493Ssdussud 			}
4014a190493Ssdussud 		}
4024a190493Ssdussud 	}
4034a190493Ssdussud 
4044a190493Ssdussud 	(void) closedir(dirp);
4054a190493Ssdussud 	return (TRUE);
4064a190493Ssdussud }
407