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