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 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * 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 /* 22004388ebScasper * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * priv_str_xlate.c - Privilege translation routines. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #pragma weak priv_str_to_set = _priv_str_to_set 337c478bd9Sstevel@tonic-gate #pragma weak priv_set_to_str = _priv_set_to_str 347c478bd9Sstevel@tonic-gate #pragma weak priv_gettext = _priv_gettext 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include "synonyms.h" 377c478bd9Sstevel@tonic-gate #include <stdio.h> 387c478bd9Sstevel@tonic-gate #include <stdlib.h> 397c478bd9Sstevel@tonic-gate #include <ctype.h> 407c478bd9Sstevel@tonic-gate #include <strings.h> 417c478bd9Sstevel@tonic-gate #include <errno.h> 427c478bd9Sstevel@tonic-gate #include <string.h> 437c478bd9Sstevel@tonic-gate #include <locale.h> 447c478bd9Sstevel@tonic-gate #include <sys/param.h> 457c478bd9Sstevel@tonic-gate #include <priv.h> 467c478bd9Sstevel@tonic-gate #include <alloca.h> 477c478bd9Sstevel@tonic-gate #include <locale.h> 487c478bd9Sstevel@tonic-gate #include "libc.h" 497c478bd9Sstevel@tonic-gate #include "../i18n/_loc_path.h" 507c478bd9Sstevel@tonic-gate #include "priv_private.h" 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate priv_set_t * 537c478bd9Sstevel@tonic-gate priv_basic(void) 547c478bd9Sstevel@tonic-gate { 557c478bd9Sstevel@tonic-gate priv_data_t *d; 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate LOADPRIVDATA(d); 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate return (d->pd_basicset); 607c478bd9Sstevel@tonic-gate } 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* 637c478bd9Sstevel@tonic-gate * Name: priv_str_to_set() 647c478bd9Sstevel@tonic-gate * 657c478bd9Sstevel@tonic-gate * Description: Given a buffer with privilege strings, the 667c478bd9Sstevel@tonic-gate * equivalent privilege set is returned. 677c478bd9Sstevel@tonic-gate * 687c478bd9Sstevel@tonic-gate * Special tokens recognized: all, none, basic and "". 697c478bd9Sstevel@tonic-gate * 707c478bd9Sstevel@tonic-gate * On failure, this function returns NULL. 717c478bd9Sstevel@tonic-gate * *endptr == NULL and errno set: resource error. 727c478bd9Sstevel@tonic-gate * *endptr != NULL: parse error. 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate priv_set_t * 757c478bd9Sstevel@tonic-gate priv_str_to_set(const char *priv_names, 767c478bd9Sstevel@tonic-gate const char *separators, 777c478bd9Sstevel@tonic-gate const char **endptr) 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate char *base; 817c478bd9Sstevel@tonic-gate char *offset; 827c478bd9Sstevel@tonic-gate char *last; 837c478bd9Sstevel@tonic-gate priv_set_t *pset = NULL; 847c478bd9Sstevel@tonic-gate priv_set_t *zone; 857c478bd9Sstevel@tonic-gate priv_set_t *basic; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate if (endptr != NULL) 887c478bd9Sstevel@tonic-gate *endptr = NULL; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate if ((base = libc_strdup(priv_names)) == NULL || 917c478bd9Sstevel@tonic-gate (pset = priv_allocset()) == NULL) { 927c478bd9Sstevel@tonic-gate /* Whether base is NULL or allocated, this works */ 937c478bd9Sstevel@tonic-gate libc_free(base); 947c478bd9Sstevel@tonic-gate return (NULL); 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate priv_emptyset(pset); 987c478bd9Sstevel@tonic-gate basic = priv_basic(); 997c478bd9Sstevel@tonic-gate zone = privdata->pd_zoneset; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* This is how to use strtok_r nicely in a while loop ... */ 1027c478bd9Sstevel@tonic-gate last = base; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate while ((offset = strtok_r(NULL, separators, &last)) != NULL) { 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * Search for these special case strings. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate if (basic != NULL && strcasecmp(offset, "basic") == 0) { 1097c478bd9Sstevel@tonic-gate priv_union(basic, pset); 1107c478bd9Sstevel@tonic-gate } else if (strcasecmp(offset, "none") == 0) { 1117c478bd9Sstevel@tonic-gate priv_emptyset(pset); 1127c478bd9Sstevel@tonic-gate } else if (strcasecmp(offset, "all") == 0) { 1137c478bd9Sstevel@tonic-gate priv_fillset(pset); 1147c478bd9Sstevel@tonic-gate } else if (strcasecmp(offset, "zone") == 0) { 1157c478bd9Sstevel@tonic-gate priv_union(zone, pset); 1167c478bd9Sstevel@tonic-gate } else { 1177c478bd9Sstevel@tonic-gate boolean_t neg = (*offset == '-' || *offset == '!'); 1187c478bd9Sstevel@tonic-gate int privid; 1197c478bd9Sstevel@tonic-gate int slen; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate privid = priv_getbyname(offset + 1227c478bd9Sstevel@tonic-gate ((neg || *offset == '+') ? 1 : 0)); 1237c478bd9Sstevel@tonic-gate if (privid < 0) { 1247c478bd9Sstevel@tonic-gate slen = offset - base; 1257c478bd9Sstevel@tonic-gate libc_free(base); 1267c478bd9Sstevel@tonic-gate priv_freeset(pset); 1277c478bd9Sstevel@tonic-gate if (endptr != NULL) 1287c478bd9Sstevel@tonic-gate *endptr = priv_names + slen; 1297c478bd9Sstevel@tonic-gate errno = EINVAL; 1307c478bd9Sstevel@tonic-gate return (NULL); 1317c478bd9Sstevel@tonic-gate } else { 1327c478bd9Sstevel@tonic-gate if (neg) 1337c478bd9Sstevel@tonic-gate PRIV_DELSET(pset, privid); 1347c478bd9Sstevel@tonic-gate else 1357c478bd9Sstevel@tonic-gate PRIV_ADDSET(pset, privid); 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate libc_free(base); 1417c478bd9Sstevel@tonic-gate return (pset); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * Name: priv_set_to_str() 1467c478bd9Sstevel@tonic-gate * 1477c478bd9Sstevel@tonic-gate * Description: Given a set of privileges, list of privileges are 1487c478bd9Sstevel@tonic-gate * returned in privilege numeric order (which can be an ASCII sorted 1497c478bd9Sstevel@tonic-gate * list as our implementation allows renumbering. 1507c478bd9Sstevel@tonic-gate * 1517c478bd9Sstevel@tonic-gate * String "none" identifies an empty privilege set, and string "all" 1527c478bd9Sstevel@tonic-gate * identifies a full set. 1537c478bd9Sstevel@tonic-gate * 1547c478bd9Sstevel@tonic-gate * A pointer to a buffer is returned which needs to be freed by 1557c478bd9Sstevel@tonic-gate * the caller. 1567c478bd9Sstevel@tonic-gate * 1577c478bd9Sstevel@tonic-gate * Several types of output are supported: 1587c478bd9Sstevel@tonic-gate * PRIV_STR_PORT - portable output: basic,!basic 1597c478bd9Sstevel@tonic-gate * PRIV_STR_LIT - literal output 1607c478bd9Sstevel@tonic-gate * PRIV_STR_SHORT - shortest output 1617c478bd9Sstevel@tonic-gate * 1627c478bd9Sstevel@tonic-gate * NOTE: this function is called both from inside the library for the 1637c478bd9Sstevel@tonic-gate * current environment and from outside the library using an externally 1647c478bd9Sstevel@tonic-gate * generated priv_data_t * in order to analyze core files. It should 1657c478bd9Sstevel@tonic-gate * return strings which can be free()ed by applications and it should 1667c478bd9Sstevel@tonic-gate * not use any data from the current environment except in the special 1677c478bd9Sstevel@tonic-gate * case that it is called from within libc, with a NULL priv_data_t * 1687c478bd9Sstevel@tonic-gate * argument. 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate char * 1727c478bd9Sstevel@tonic-gate __priv_set_to_str( 1737c478bd9Sstevel@tonic-gate priv_data_t *d, 1747c478bd9Sstevel@tonic-gate const priv_set_t *pset, 1757c478bd9Sstevel@tonic-gate char separator, 1767c478bd9Sstevel@tonic-gate int flag) 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate const char *pstr; 1797c478bd9Sstevel@tonic-gate char *res, *resp; 1807c478bd9Sstevel@tonic-gate int i; 1817c478bd9Sstevel@tonic-gate char neg = separator == '!' ? '-' : '!'; 1827c478bd9Sstevel@tonic-gate priv_set_t *zone; 1837c478bd9Sstevel@tonic-gate boolean_t all; 1847c478bd9Sstevel@tonic-gate boolean_t use_libc_data = (d == NULL); 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate if (use_libc_data) 1877c478bd9Sstevel@tonic-gate LOADPRIVDATA(d); 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate if (flag != PRIV_STR_PORT && __priv_isemptyset(d, pset)) 1907c478bd9Sstevel@tonic-gate return (strdup("none")); 1917c478bd9Sstevel@tonic-gate if (flag != PRIV_STR_LIT && __priv_isfullset(d, pset)) 1927c478bd9Sstevel@tonic-gate return (strdup("all")); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* Safe upper bound: global info contains all NULL separated privs */ 1957c478bd9Sstevel@tonic-gate res = resp = alloca(d->pd_pinfo->priv_globalinfosize); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate /* 1987c478bd9Sstevel@tonic-gate * Compute the shortest form; i.e., the form with the fewest privilege 1997c478bd9Sstevel@tonic-gate * tokens. 2007c478bd9Sstevel@tonic-gate * The following forms are possible: 2017c478bd9Sstevel@tonic-gate * literal: priv1,priv2,priv3 2027c478bd9Sstevel@tonic-gate * tokcount = present 2037c478bd9Sstevel@tonic-gate * port: basic,!missing_basic,other 2047c478bd9Sstevel@tonic-gate * tokcount = 1 + present - presentbasic + missingbasic 2057c478bd9Sstevel@tonic-gate * zone: zone,!missing_zone 2067c478bd9Sstevel@tonic-gate * tokcount = 1 + missingzone 2077c478bd9Sstevel@tonic-gate * all: all,!missing1,!missing2 2087c478bd9Sstevel@tonic-gate * tokcount = 1 + d->pd_nprivs - present; 2097c478bd9Sstevel@tonic-gate * 2107c478bd9Sstevel@tonic-gate * Note that zone and all forms are identical in the global zone; 2117c478bd9Sstevel@tonic-gate * in that case (or any other where the token count is the same), 2127c478bd9Sstevel@tonic-gate * all is preferred. Also, the zone form is only used when the 2137c478bd9Sstevel@tonic-gate * indicated privileges are a subset of the zone set. 2147c478bd9Sstevel@tonic-gate */ 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate if (use_libc_data) 2177c478bd9Sstevel@tonic-gate LOCKPRIVDATA(); 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate if (flag == PRIV_STR_SHORT) { 2207c478bd9Sstevel@tonic-gate int presentbasic, missingbasic, present, missing; 2217c478bd9Sstevel@tonic-gate int presentzone, missingzone; 2227c478bd9Sstevel@tonic-gate int count; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate presentbasic = missingbasic = present = 0; 2257c478bd9Sstevel@tonic-gate presentzone = missingzone = 0; 2267c478bd9Sstevel@tonic-gate zone = d->pd_zoneset; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate for (i = 0; i < d->pd_nprivs; i++) { 2297c478bd9Sstevel@tonic-gate int mem = PRIV_ISMEMBER(pset, i); 2307c478bd9Sstevel@tonic-gate if (d->pd_basicset != NULL && 2317c478bd9Sstevel@tonic-gate PRIV_ISMEMBER(d->pd_basicset, i)) { 2327c478bd9Sstevel@tonic-gate if (mem) 2337c478bd9Sstevel@tonic-gate presentbasic++; 2347c478bd9Sstevel@tonic-gate else 2357c478bd9Sstevel@tonic-gate missingbasic++; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate if (zone != NULL && PRIV_ISMEMBER(zone, i)) { 2387c478bd9Sstevel@tonic-gate if (mem) 2397c478bd9Sstevel@tonic-gate presentzone++; 2407c478bd9Sstevel@tonic-gate else 2417c478bd9Sstevel@tonic-gate missingzone++; 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate if (mem) 2447c478bd9Sstevel@tonic-gate present++; 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate missing = d->pd_nprivs - present; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate if (1 - presentbasic + missingbasic < 0) { 2497c478bd9Sstevel@tonic-gate flag = PRIV_STR_PORT; 2507c478bd9Sstevel@tonic-gate count = present + 1 - presentbasic + missingbasic; 2517c478bd9Sstevel@tonic-gate } else { 2527c478bd9Sstevel@tonic-gate flag = PRIV_STR_LIT; 2537c478bd9Sstevel@tonic-gate count = present; 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate if (count >= 1 + missing) { 2567c478bd9Sstevel@tonic-gate flag = PRIV_STR_SHORT; 2577c478bd9Sstevel@tonic-gate count = 1 + missing; 2587c478bd9Sstevel@tonic-gate all = B_TRUE; 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate if (present == presentzone && 1 + missingzone < count) { 2617c478bd9Sstevel@tonic-gate flag = PRIV_STR_SHORT; 2627c478bd9Sstevel@tonic-gate all = B_FALSE; 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate switch (flag) { 2677c478bd9Sstevel@tonic-gate case PRIV_STR_LIT: 2687c478bd9Sstevel@tonic-gate *res = '\0'; 2697c478bd9Sstevel@tonic-gate break; 2707c478bd9Sstevel@tonic-gate case PRIV_STR_PORT: 2717c478bd9Sstevel@tonic-gate (void) strcpy(res, "basic"); 2727c478bd9Sstevel@tonic-gate if (d->pd_basicset == NULL) 2737c478bd9Sstevel@tonic-gate flag = PRIV_STR_LIT; 2747c478bd9Sstevel@tonic-gate break; 2757c478bd9Sstevel@tonic-gate case PRIV_STR_SHORT: 2767c478bd9Sstevel@tonic-gate if (all) 2777c478bd9Sstevel@tonic-gate (void) strcpy(res, "all"); 2787c478bd9Sstevel@tonic-gate else 2797c478bd9Sstevel@tonic-gate (void) strcpy(res, "zone"); 2807c478bd9Sstevel@tonic-gate break; 2817c478bd9Sstevel@tonic-gate default: 2827c478bd9Sstevel@tonic-gate if (use_libc_data) 2837c478bd9Sstevel@tonic-gate UNLOCKPRIVDATA(); 2847c478bd9Sstevel@tonic-gate return (NULL); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate res += strlen(res); 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate for (i = 0; i < d->pd_nprivs; i++) { 2897c478bd9Sstevel@tonic-gate /* Map the privilege to the next one sorted by name */ 2907c478bd9Sstevel@tonic-gate int priv = d->pd_setsort[i]; 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate if (PRIV_ISMEMBER(pset, priv)) { 2937c478bd9Sstevel@tonic-gate switch (flag) { 2947c478bd9Sstevel@tonic-gate case PRIV_STR_SHORT: 2957c478bd9Sstevel@tonic-gate if (all || PRIV_ISMEMBER(zone, priv)) 2967c478bd9Sstevel@tonic-gate continue; 2977c478bd9Sstevel@tonic-gate break; 2987c478bd9Sstevel@tonic-gate case PRIV_STR_PORT: 2997c478bd9Sstevel@tonic-gate if (PRIV_ISMEMBER(d->pd_basicset, priv)) 3007c478bd9Sstevel@tonic-gate continue; 3017c478bd9Sstevel@tonic-gate break; 3027c478bd9Sstevel@tonic-gate case PRIV_STR_LIT: 3037c478bd9Sstevel@tonic-gate break; 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate if (res != resp) 3067c478bd9Sstevel@tonic-gate *res++ = separator; 3077c478bd9Sstevel@tonic-gate } else { 3087c478bd9Sstevel@tonic-gate switch (flag) { 3097c478bd9Sstevel@tonic-gate case PRIV_STR_LIT: 3107c478bd9Sstevel@tonic-gate continue; 3117c478bd9Sstevel@tonic-gate case PRIV_STR_PORT: 3127c478bd9Sstevel@tonic-gate if (!PRIV_ISMEMBER(d->pd_basicset, priv)) 3137c478bd9Sstevel@tonic-gate continue; 3147c478bd9Sstevel@tonic-gate break; 3157c478bd9Sstevel@tonic-gate case PRIV_STR_SHORT: 3167c478bd9Sstevel@tonic-gate if (!all && !PRIV_ISMEMBER(zone, priv)) 3177c478bd9Sstevel@tonic-gate continue; 3187c478bd9Sstevel@tonic-gate break; 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate if (res != resp) 3217c478bd9Sstevel@tonic-gate *res++ = separator; 3227c478bd9Sstevel@tonic-gate *res++ = neg; 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate pstr = __priv_getbynum(d, priv); 3257c478bd9Sstevel@tonic-gate (void) strcpy(res, pstr); 3267c478bd9Sstevel@tonic-gate res += strlen(pstr); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate if (use_libc_data) 3297c478bd9Sstevel@tonic-gate UNLOCKPRIVDATA(); 3307c478bd9Sstevel@tonic-gate /* Special case the set with some high bits set */ 3317c478bd9Sstevel@tonic-gate return (strdup(*resp == '\0' ? "none" : resp)); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate /* 3357c478bd9Sstevel@tonic-gate * priv_set_to_str() is defined to return a string that 3367c478bd9Sstevel@tonic-gate * the caller must deallocate with free(3C). Grr... 3377c478bd9Sstevel@tonic-gate */ 3387c478bd9Sstevel@tonic-gate char * 3397c478bd9Sstevel@tonic-gate priv_set_to_str(const priv_set_t *pset, char separator, int flag) 3407c478bd9Sstevel@tonic-gate { 3417c478bd9Sstevel@tonic-gate return (__priv_set_to_str(NULL, pset, separator, flag)); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 344*c8d28497Ssayama static char * 345*c8d28497Ssayama do_priv_gettext(const char *priv, const char *file) 3467c478bd9Sstevel@tonic-gate { 3477c478bd9Sstevel@tonic-gate char buf[8*1024]; 3487c478bd9Sstevel@tonic-gate boolean_t inentry = B_FALSE; 349*c8d28497Ssayama FILE *namefp; 3507c478bd9Sstevel@tonic-gate 351*c8d28497Ssayama namefp = fopen(file, "rF"); 3527c478bd9Sstevel@tonic-gate if (namefp == NULL) 3537c478bd9Sstevel@tonic-gate return (NULL); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate /* 3567c478bd9Sstevel@tonic-gate * parse the file; it must have the following format 3577c478bd9Sstevel@tonic-gate * Lines starting with comments "#" 3587c478bd9Sstevel@tonic-gate * Lines starting with non white space with one single token: 3597c478bd9Sstevel@tonic-gate * the privileges; white space indented lines which are the 3607c478bd9Sstevel@tonic-gate * description; no empty lines are allowed in the description. 3617c478bd9Sstevel@tonic-gate */ 3627c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof (buf), namefp) != NULL) { 3637c478bd9Sstevel@tonic-gate char *lp; /* pointer to the current line */ 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate if (buf[0] == '#') 3667c478bd9Sstevel@tonic-gate continue; 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate if (buf[0] == '\n') { 3697c478bd9Sstevel@tonic-gate inentry = B_FALSE; 3707c478bd9Sstevel@tonic-gate continue; 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate if (inentry) 3747c478bd9Sstevel@tonic-gate continue; 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate /* error; not skipping; yet line starts with white space */ 3777c478bd9Sstevel@tonic-gate if (isspace((unsigned char)buf[0])) 3787c478bd9Sstevel@tonic-gate goto out; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate /* Trim trailing newline */ 3817c478bd9Sstevel@tonic-gate buf[strlen(buf) - 1] = '\0'; 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate if (strcasecmp(buf, priv) != 0) { 3847c478bd9Sstevel@tonic-gate inentry = B_TRUE; 3857c478bd9Sstevel@tonic-gate continue; 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate lp = buf; 3897c478bd9Sstevel@tonic-gate while (fgets(lp, sizeof (buf) - (lp - buf), namefp) != NULL) { 3907c478bd9Sstevel@tonic-gate char *tstart; /* start of text */ 3917c478bd9Sstevel@tonic-gate int len; 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate /* Empty line or start of next entry terminates */ 3947c478bd9Sstevel@tonic-gate if (*lp == '\n' || !isspace((unsigned char)*lp)) { 3957c478bd9Sstevel@tonic-gate *lp = '\0'; 3967c478bd9Sstevel@tonic-gate (void) fclose(namefp); 3977c478bd9Sstevel@tonic-gate return (strdup(buf)); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate /* Remove leading white space */ 4017c478bd9Sstevel@tonic-gate tstart = lp; 4027c478bd9Sstevel@tonic-gate while (*tstart != '\0' && 4037c478bd9Sstevel@tonic-gate isspace((unsigned char)*tstart)) { 4047c478bd9Sstevel@tonic-gate tstart++; 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate len = strlen(tstart); 4087c478bd9Sstevel@tonic-gate (void) memmove(lp, tstart, len + 1); 4097c478bd9Sstevel@tonic-gate lp += len; 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate /* Entry to big; prevent fgets() loop */ 4127c478bd9Sstevel@tonic-gate if (lp == &buf[sizeof (buf) - 1]) 4137c478bd9Sstevel@tonic-gate goto out; 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate if (lp != buf) { 4167c478bd9Sstevel@tonic-gate *lp = '\0'; 4177c478bd9Sstevel@tonic-gate (void) fclose(namefp); 4187c478bd9Sstevel@tonic-gate return (strdup(buf)); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate out: 4227c478bd9Sstevel@tonic-gate (void) fclose(namefp); 4237c478bd9Sstevel@tonic-gate return (NULL); 4247c478bd9Sstevel@tonic-gate } 425*c8d28497Ssayama 426*c8d28497Ssayama /* 427*c8d28497Ssayama * priv_gettext() is defined to return a string that 428*c8d28497Ssayama * the caller must deallocate with free(3C). Grr... 429*c8d28497Ssayama */ 430*c8d28497Ssayama char * 431*c8d28497Ssayama priv_gettext(const char *priv) 432*c8d28497Ssayama { 433*c8d28497Ssayama char file[MAXPATHLEN]; 434*c8d28497Ssayama const char *loc; 435*c8d28497Ssayama char *ret; 436*c8d28497Ssayama 437*c8d28497Ssayama /* Not a valid privilege */ 438*c8d28497Ssayama if (priv_getbyname(priv) < 0) 439*c8d28497Ssayama return (NULL); 440*c8d28497Ssayama 441*c8d28497Ssayama if ((loc = setlocale(LC_MESSAGES, NULL)) == NULL) 442*c8d28497Ssayama loc = "C"; 443*c8d28497Ssayama 444*c8d28497Ssayama if (snprintf(file, sizeof (file), 445*c8d28497Ssayama _DFLT_LOC_PATH "%s/LC_MESSAGES/priv_names", loc) < sizeof (file)) { 446*c8d28497Ssayama ret = do_priv_gettext(priv, (const char *)file); 447*c8d28497Ssayama if (ret != NULL) 448*c8d28497Ssayama return (ret); 449*c8d28497Ssayama } 450*c8d28497Ssayama 451*c8d28497Ssayama /* If the path is too long or can't be opened, punt to default */ 452*c8d28497Ssayama ret = do_priv_gettext(priv, "/etc/security/priv_names"); 453*c8d28497Ssayama return (ret); 454*c8d28497Ssayama } 455