/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2015 Gary Mills * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Portions of this source code were derived from Berkeley 4.3 BSD * under license from the Regents of the University of California. */ #include <stdlib.h> #include <dirent.h> #include <strings.h> #include "ypsym.h" #include "ypdefs.h" USE_YPDBPATH USE_DBM #include "shim.h" #include "../ldap_util.h" /* * This constructs a file name from a passed domain name, a passed map name, * and a globally known YP data base path prefix. * * Has to be in shim because it needs the N2L prefix * * RETURNS : TRUE = A name was successfully created * FALSE = A name could not be created */ bool_t ypmkfilename(domain, map, path) char *domain; char *map; char *path; { int length; /* Do not allow any path as a domain name. */ if (strchr(domain, '/') != NULL) return (FALSE); length = strlen(domain) + strlen(map) + ypdbpath_sz + 3; if (yptol_mode) length += strlen(NTOL_PREFIX) + 1; if ((MAXNAMLEN + 1) < length) { (void) fprintf(stderr, "ypserv: Map name string too long.\n"); return (FALSE); } strcpy(path, ypdbpath); strcat(path, "/"); strcat(path, domain); strcat(path, "/"); /* If in N2L mode add N2L prefix */ if (yptol_mode) strcat(path, NTOL_PREFIX); strcat(path, map); return (TRUE); } /* * check whether a map is already in an array/list * * RETURNS: TRUE if yes * FALSE if not */ bool_t on_maplist(char *mapname, char **list) { int i = 0; if (list == NULL) { return (FALSE); } while (list[i] != NULL) { if (strcmp(mapname, list[i++]) == 0) { return (TRUE); } } return (FALSE); } /* * add a map at the end of an array/list * * list_len: if -1, we do not know list length * * RETURNS: TRUE if map was added * FALSE if not */ bool_t add_in_maplist(char *mapname, char ***list, int *list_len) { int i = 0; char **list_tmp; if (list == NULL) { return (FALSE); } list_tmp = *list; if (list_tmp == NULL) { *list_len = 0; } else { /* find 1st free element */ while (list_tmp[i] != NULL) { /* * increment in loop so that * list_tmp[i] == NULL * when exiting */ i++; } } /* if we don't know list length, assume we reach its end */ if (*list_len == -1) { *list_len = i; } /* do we need to reallocate ? */ if (i+1 >= *list_len) { list_tmp = (char **)realloc(list_tmp, (*list_len + ARRAY_CHUNK) * sizeof (char *)); if (list_tmp == NULL) { return (FALSE); } *list = list_tmp; *list_len += ARRAY_CHUNK; } /* add in list */ (*list)[i] = strdup(mapname); if ((*list)[i] == NULL) { /* strdup() failed */ return (FALSE); } (*list)[++i] = NULL; return (TRUE); } /* * This checks to see whether a domain name is present at the local node as a * subdirectory of ypdbpath * * Was originally in cmd/ypcmd/shared/ancil.c as ypcheck_domain(domain). * Now ypcheck_domain(domain) calls this function. */ bool ypcheck_domain_yptol(char *domain) { char path[MAXNAMLEN + 1]; struct stat filestat; bool present = FALSE; strcpy(path, ypdbpath); strcat(path, "/"); if (strlcat(path, domain, MAXNAMLEN + 1) >= MAXNAMLEN + 1) return (present); if (stat(path, &filestat) != -1) { if (S_ISDIR(filestat.st_mode)) present = TRUE; } return (present); } /* * This performs an existence check on the dbm data base files <name>.pag and * <name>.dir. pname is a ptr to the filename. This should be an absolute * path. * Returns TRUE if the map exists and is accessible; else FALSE. * * Note: The file name should be a "base" form, without a file "extension" of * .dir or .pag appended. See ypmkfilename for a function which will generate * the name correctly. Errors in the stat call will be reported at this level, * however, the non-existence of a file is not considered an error, and so will * not be reported. * * Was originally in cmd/ypcmd/shared/utils.c as ypcheck_map_existence(). * Now ypcheck_map_existence() calls this function. */ bool ypcheck_map_existence_yptol(char *pname) { char dbfile[MAXNAMLEN + sizeof (TTL_POSTFIX) + 1]; struct stat64 filestat; int len; if (!pname || ((len = (int)strlen(pname)) == 0) || (len + sizeof (dbm_pag) + sizeof (TTL_POSTFIX)) > sizeof (dbfile)) { return (FALSE); } errno = 0; /* Check for existance of .dir file */ (void) strcpy(dbfile, pname); (void) strcat(dbfile, dbm_dir); if (stat64(dbfile, &filestat) == -1) { if (errno != ENOENT) { (void) fprintf(stderr, "ypserv: Stat error on map file %s.\n", dbfile); } return (FALSE); } /* Check for existance of .pag file */ (void) strcpy(dbfile, pname); (void) strcat(dbfile, dbm_pag); if (stat64(dbfile, &filestat) == -1) { if (errno != ENOENT) { (void) fprintf(stderr, "ypserv: Stat error on map file %s.\n", dbfile); } return (FALSE); } if (yptol_mode) { /* Check for existance of TTL .dir file */ (void) strcpy(dbfile, pname); (void) strcat(dbfile, TTL_POSTFIX); (void) strcat(dbfile, dbm_dir); if (stat64(dbfile, &filestat) == -1) { if (errno != ENOENT) { (void) fprintf(stderr, "ypserv: Stat error on map file %s.\n", dbfile); } return (FALSE); } /* Check for existance of TTL .pag file */ (void) strcpy(dbfile, pname); (void) strcat(dbfile, TTL_POSTFIX); (void) strcat(dbfile, dbm_pag); if (stat64(dbfile, &filestat) == -1) { if (errno != ENOENT) { (void) fprintf(stderr, "ypserv: Stat error on map file %s.\n", dbfile); } return (FALSE); } } return (TRUE); } /* * This adds maps in a domain to a given list, * from maps in /var/yp/<domain> * Inspired from yplist_maps() in cmd/ypcmd/ypserv_ancil.c * * domain is the relevant domain name * map_list is the list of maps in an array of map names, * which may or may not be empty * * RETURNS : TRUE = everything went fine * FALSE = an error occured */ bool_t add_map_domain_to_list(char *domain, char ***map_list) { char domdir[MAXNAMLEN + 1]; char path[MAXNAMLEN + 1]; int domdir_len = sizeof (domdir); DIR *dirp; struct dirent *dp; int name_len; int dbm_pag_len = sizeof (dbm_pag); char *ext; char *mapname; int map_list_len = -1; if (map_list == NULL) { return (FALSE); } /* no domain, not a problem */ if (domain == NULL) { return (TRUE); } /* not a valid domain, not a problem */ if (!ypcheck_domain_yptol(domain)) { return (TRUE); } if (snprintf(domdir, domdir_len, "%s/%s", ypdbpath, domain) > domdir_len) { return (FALSE); } if ((dirp = opendir(domdir)) == NULL) { return (FALSE); } for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { /* * If it's possible that the file name is one of the two files * implementing a map, remove the extension (dbm_pag or dbm_dir) */ name_len = (int)strlen(dp->d_name); if (name_len < dbm_pag_len - 1) { continue; /* Too Short */ } ext = &(dp->d_name[name_len - (dbm_pag_len - 1)]); if (strcmp(ext, dbm_pag) != 0) { continue; /* No dbm file extension */ } *ext = '\0'; /* * In yptol mode look at LDAP_ prefixed maps. In non yptol mode * ignore them. */ if (yptol_mode) { if (0 != strncmp(dp->d_name, NTOL_PREFIX, strlen(NTOL_PREFIX))) { continue; } /* * Already have an LDAP_ prefix. Don't want to add it * twice. */ mapname = dp->d_name + strlen(NTOL_PREFIX); } else { if (0 == strncmp(dp->d_name, NTOL_PREFIX, strlen(NTOL_PREFIX))) { continue; } mapname = dp->d_name; } if (ypmkfilename(domain, mapname, path) == FALSE) { (void) closedir(dirp); return (FALSE); } /* * At this point, path holds the map file base name (no dbm * file extension), and mapname holds the map name. */ if (ypcheck_map_existence_yptol(path) && !on_maplist(mapname, *map_list)) { if (add_in_maplist(mapname, map_list, &map_list_len) == FALSE) { (void) closedir(dirp); return (FALSE); } } } (void) closedir(dirp); return (TRUE); }