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 5*f48205beScasper * Common Development and Distribution License (the "License"). 6*f48205beScasper * 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*f48205beScasper * Copyright 2007 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 #include <errno.h> 297c478bd9Sstevel@tonic-gate #include <deflt.h> 307c478bd9Sstevel@tonic-gate #include <locale.h> 317c478bd9Sstevel@tonic-gate #include <sys/types.h> 327c478bd9Sstevel@tonic-gate #include <sys/param.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <ctype.h> 367c478bd9Sstevel@tonic-gate #include <pwd.h> 377c478bd9Sstevel@tonic-gate #include <grp.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <exec_attr.h> 407c478bd9Sstevel@tonic-gate #include <user_attr.h> 417c478bd9Sstevel@tonic-gate #include <auth_attr.h> 427c478bd9Sstevel@tonic-gate #include <prof_attr.h> 437c478bd9Sstevel@tonic-gate #include <errno.h> 447c478bd9Sstevel@tonic-gate #include <priv.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #include <bsm/adt.h> 477c478bd9Sstevel@tonic-gate #include <bsm/adt_event.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN /* Should be defined by cc -D */ 507c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 517c478bd9Sstevel@tonic-gate #endif 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate extern int cannot_audit(int); 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate static char *pathsearch(char *); 567c478bd9Sstevel@tonic-gate static int getrealpath(const char *, char *); 577c478bd9Sstevel@tonic-gate static int checkattrs(char *, int, char *[]); 587c478bd9Sstevel@tonic-gate static void sanitize_environ(); 597c478bd9Sstevel@tonic-gate static uid_t get_uid(char *); 607c478bd9Sstevel@tonic-gate static gid_t get_gid(char *); 617c478bd9Sstevel@tonic-gate static priv_set_t *get_privset(const char *); 627c478bd9Sstevel@tonic-gate static priv_set_t *get_granted_privs(uid_t); 637c478bd9Sstevel@tonic-gate static void get_default_privs(priv_set_t *); 647c478bd9Sstevel@tonic-gate static void get_profile_privs(char *, char **, int *, priv_set_t *); 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate static int isnumber(char *); 677c478bd9Sstevel@tonic-gate static void usage(void); 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate extern char **environ; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate #define PROFLIST_SEP "," 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate int 747c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 757c478bd9Sstevel@tonic-gate { 767c478bd9Sstevel@tonic-gate char *cmd; 777c478bd9Sstevel@tonic-gate char **cmdargs; 787c478bd9Sstevel@tonic-gate char cmd_realpath[MAXPATHLEN]; 797c478bd9Sstevel@tonic-gate int c; 807c478bd9Sstevel@tonic-gate char *pset = NULL; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 837c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "P:")) != EOF) { 867c478bd9Sstevel@tonic-gate switch (c) { 877c478bd9Sstevel@tonic-gate case 'P': 887c478bd9Sstevel@tonic-gate if (pset == NULL) { 897c478bd9Sstevel@tonic-gate pset = optarg; 907c478bd9Sstevel@tonic-gate break; 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 937c478bd9Sstevel@tonic-gate default: 947c478bd9Sstevel@tonic-gate usage(); 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate argc -= optind; 987c478bd9Sstevel@tonic-gate argv += optind; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate if (argc < 1) 1017c478bd9Sstevel@tonic-gate usage(); 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate cmd = argv[0]; 1047c478bd9Sstevel@tonic-gate cmdargs = &argv[0]; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate if (pset != NULL) { 1077c478bd9Sstevel@tonic-gate uid_t uid = getuid(); 1087c478bd9Sstevel@tonic-gate priv_set_t *wanted = get_privset(pset); 1097c478bd9Sstevel@tonic-gate priv_set_t *granted; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate adt_session_data_t *ah; /* audit session handle */ 1127c478bd9Sstevel@tonic-gate adt_event_data_t *event; /* event to be generated */ 1137c478bd9Sstevel@tonic-gate char cwd[MAXPATHLEN]; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate granted = get_granted_privs(uid); 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate /* Audit use */ 1187c478bd9Sstevel@tonic-gate if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) { 1197c478bd9Sstevel@tonic-gate perror("pfexec: adt_start_session"); 1207c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate if ((event = adt_alloc_event(ah, ADT_prof_cmd)) == NULL) { 1237c478bd9Sstevel@tonic-gate perror("pfexec: adt_alloc_event"); 1247c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate if ((event->adt_prof_cmd.cwdpath = 1277c478bd9Sstevel@tonic-gate getcwd(cwd, sizeof (cwd))) == NULL) { 1287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1297c478bd9Sstevel@tonic-gate gettext("pfexec: can't add cwd path\n")); 1307c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate event->adt_prof_cmd.cmdpath = cmd; 1347c478bd9Sstevel@tonic-gate event->adt_prof_cmd.argc = argc - 1; 1357c478bd9Sstevel@tonic-gate event->adt_prof_cmd.argv = &argv[1]; 1367c478bd9Sstevel@tonic-gate event->adt_prof_cmd.envp = environ; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate if (granted != NULL) { 1397c478bd9Sstevel@tonic-gate priv_intersect(granted, wanted); 1407c478bd9Sstevel@tonic-gate event->adt_prof_cmd.inherit_set = wanted; 1417c478bd9Sstevel@tonic-gate if (adt_put_event(event, ADT_SUCCESS, 1427c478bd9Sstevel@tonic-gate ADT_SUCCESS) != 0) { 1437c478bd9Sstevel@tonic-gate perror("pfexec: adt_put_event"); 1447c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate if (setppriv(PRIV_ON, PRIV_INHERITABLE, wanted) != 0) { 1477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1487c478bd9Sstevel@tonic-gate gettext("setppriv(): %s\n"), 1497c478bd9Sstevel@tonic-gate strerror(errno)); 1507c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate /* Trick exec into thinking we're not suid */ 1537c478bd9Sstevel@tonic-gate (void) setppriv(PRIV_ON, PRIV_PERMITTED, wanted); 1547c478bd9Sstevel@tonic-gate priv_freeset(event->adt_prof_cmd.inherit_set); 1557c478bd9Sstevel@tonic-gate } else { 1567c478bd9Sstevel@tonic-gate if (adt_put_event(event, ADT_SUCCESS, 1577c478bd9Sstevel@tonic-gate ADT_SUCCESS) != 0) { 1587c478bd9Sstevel@tonic-gate perror("pfexec: adt_put_event"); 1597c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate adt_free_event(event); 1637c478bd9Sstevel@tonic-gate (void) adt_end_session(ah); 1647c478bd9Sstevel@tonic-gate (void) setreuid(uid, uid); 1657c478bd9Sstevel@tonic-gate (void) execvp(cmd, cmdargs); 1667c478bd9Sstevel@tonic-gate perror(cmd); 1677c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate if ((cmd = pathsearch(cmd)) == NULL) 1717c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate if (getrealpath(cmd, cmd_realpath) == 0) 1747c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate if (checkattrs(cmd_realpath, argc, argv) == 0) 1777c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate (void) execv(cmd, cmdargs); 1807c478bd9Sstevel@tonic-gate /* 1817c478bd9Sstevel@tonic-gate * We'd be here only if execv fails. 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate perror("pfexec"); 1847c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1857c478bd9Sstevel@tonic-gate /* LINTED */ 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * gets realpath for cmd. 1917c478bd9Sstevel@tonic-gate * return 1 on success, 0 on failure. 1927c478bd9Sstevel@tonic-gate */ 1937c478bd9Sstevel@tonic-gate static int 1947c478bd9Sstevel@tonic-gate getrealpath(const char *cmd, char *cmd_realpath) 1957c478bd9Sstevel@tonic-gate { 1967c478bd9Sstevel@tonic-gate if (realpath(cmd, cmd_realpath) == NULL) { 1977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1987c478bd9Sstevel@tonic-gate gettext("pfexec: can't get real path of ``%s''\n"), cmd); 1997c478bd9Sstevel@tonic-gate return (0); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate return (1); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * gets execution attributed for cmd, sets uids/gids, checks environ. 2067c478bd9Sstevel@tonic-gate * returns 1 on success, 0 on failure. 2077c478bd9Sstevel@tonic-gate */ 2087c478bd9Sstevel@tonic-gate static int 2097c478bd9Sstevel@tonic-gate checkattrs(char *cmd_realpath, int argc, char *argv[]) 2107c478bd9Sstevel@tonic-gate { 2117c478bd9Sstevel@tonic-gate char *value; 2127c478bd9Sstevel@tonic-gate uid_t uid, euid; 213*f48205beScasper gid_t gid = (gid_t)-1; 214*f48205beScasper gid_t egid = (gid_t)-1; 2157c478bd9Sstevel@tonic-gate struct passwd *pwent; 2167c478bd9Sstevel@tonic-gate execattr_t *exec; 2177c478bd9Sstevel@tonic-gate priv_set_t *lset = NULL; 2187c478bd9Sstevel@tonic-gate priv_set_t *iset = NULL; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate adt_session_data_t *ah; /* audit session handle */ 2217c478bd9Sstevel@tonic-gate adt_event_data_t *event; /* event to be generated */ 2227c478bd9Sstevel@tonic-gate char cwd[MAXPATHLEN]; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate uid = euid = getuid(); 2257c478bd9Sstevel@tonic-gate if ((pwent = getpwuid(uid)) == NULL) { 2267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%d: ", (int)uid); 2277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't get passwd entry\n")); 2287c478bd9Sstevel@tonic-gate return (0); 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate /* Set up to audit use */ 2317c478bd9Sstevel@tonic-gate if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) { 2327c478bd9Sstevel@tonic-gate perror("pfexec: adt_start_session"); 2337c478bd9Sstevel@tonic-gate return (0); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate if ((event = adt_alloc_event(ah, ADT_prof_cmd)) == NULL) { 2367c478bd9Sstevel@tonic-gate perror("pfexec: adt_alloc_event"); 2377c478bd9Sstevel@tonic-gate return (0); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate if ((event->adt_prof_cmd.cwdpath = getcwd(cwd, sizeof (cwd))) == NULL) { 2407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("pfexec: can't add cwd path\n")); 2417c478bd9Sstevel@tonic-gate return (0); 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate /* 2447c478bd9Sstevel@tonic-gate * Get the exec attrs: uid, gid, euid and egid 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate if ((exec = getexecuser(pwent->pw_name, 2477c478bd9Sstevel@tonic-gate KV_COMMAND, (char *)cmd_realpath, GET_ONE)) == NULL) { 2487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", cmd_realpath); 2497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2507c478bd9Sstevel@tonic-gate gettext("can't get execution attributes\n")); 2517c478bd9Sstevel@tonic-gate return (0); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate if ((value = kva_match(exec->attr, EXECATTR_UID_KW)) != NULL) { 2547c478bd9Sstevel@tonic-gate euid = uid = get_uid(value); 2557c478bd9Sstevel@tonic-gate event->adt_prof_cmd.proc_euid = uid; 2567c478bd9Sstevel@tonic-gate event->adt_prof_cmd.proc_ruid = uid; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate if ((value = kva_match(exec->attr, EXECATTR_GID_KW)) != NULL) { 2597c478bd9Sstevel@tonic-gate egid = gid = get_gid(value); 2607c478bd9Sstevel@tonic-gate event->adt_prof_cmd.proc_egid = gid; 2617c478bd9Sstevel@tonic-gate event->adt_prof_cmd.proc_rgid = gid; 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate if ((value = kva_match(exec->attr, EXECATTR_EUID_KW)) != NULL) { 2647c478bd9Sstevel@tonic-gate event->adt_prof_cmd.proc_euid = euid = get_uid(value); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate if ((value = kva_match(exec->attr, EXECATTR_EGID_KW)) != NULL) { 2677c478bd9Sstevel@tonic-gate event->adt_prof_cmd.proc_egid = egid = get_gid(value); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate if ((value = kva_match(exec->attr, EXECATTR_LPRIV_KW)) != NULL) { 2707c478bd9Sstevel@tonic-gate lset = get_privset(value); 2717c478bd9Sstevel@tonic-gate event->adt_prof_cmd.limit_set = lset; 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate if ((value = kva_match(exec->attr, EXECATTR_IPRIV_KW)) != NULL) { 2747c478bd9Sstevel@tonic-gate iset = get_privset(value); 2757c478bd9Sstevel@tonic-gate event->adt_prof_cmd.inherit_set = iset; 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate if (euid == uid || iset != NULL) { 2787c478bd9Sstevel@tonic-gate sanitize_environ(); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* Finish audit info */ 2827c478bd9Sstevel@tonic-gate event->adt_prof_cmd.cmdpath = cmd_realpath; 2837c478bd9Sstevel@tonic-gate event->adt_prof_cmd.argc = argc - 1; 2847c478bd9Sstevel@tonic-gate event->adt_prof_cmd.argv = &argv[1]; 2857c478bd9Sstevel@tonic-gate event->adt_prof_cmd.envp = environ; 2867c478bd9Sstevel@tonic-gate if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 2877c478bd9Sstevel@tonic-gate perror("pfexec: adt_put_event"); 2887c478bd9Sstevel@tonic-gate return (0); 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate adt_free_event(event); 2917c478bd9Sstevel@tonic-gate (void) adt_end_session(ah); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate set_attrs: 2947c478bd9Sstevel@tonic-gate /* 2957c478bd9Sstevel@tonic-gate * Set gids/uids and privileges. 2967c478bd9Sstevel@tonic-gate * 2977c478bd9Sstevel@tonic-gate */ 298*f48205beScasper if ((gid != (gid_t)-1) || (egid != (gid_t)-1)) { 2997c478bd9Sstevel@tonic-gate if ((setregid(gid, egid) == -1)) { 3007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", cmd_realpath); 3017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't set gid\n")); 3027c478bd9Sstevel@tonic-gate return (0); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate if (lset != NULL && setppriv(PRIV_SET, PRIV_LIMIT, lset) != 0 || 3067c478bd9Sstevel@tonic-gate iset != NULL && setppriv(PRIV_ON, PRIV_INHERITABLE, iset) != 0) { 3077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: can't set privileges\n"), 3087c478bd9Sstevel@tonic-gate cmd_realpath); 3097c478bd9Sstevel@tonic-gate return (0); 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate if (setreuid(uid, euid) == -1) { 3127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", cmd_realpath); 3137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't set uid\n")); 3147c478bd9Sstevel@tonic-gate return (0); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate if (iset != NULL && getppriv(PRIV_INHERITABLE, iset) == 0) 3177c478bd9Sstevel@tonic-gate (void) setppriv(PRIV_SET, PRIV_PERMITTED, iset); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate free_execattr(exec); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate return (1); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate /* 3267c478bd9Sstevel@tonic-gate * cleans up environ. code from su.c 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate static void 3297c478bd9Sstevel@tonic-gate sanitize_environ() 3307c478bd9Sstevel@tonic-gate { 3317c478bd9Sstevel@tonic-gate char **pp = environ; 3327c478bd9Sstevel@tonic-gate char **qq, *p; 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate while ((p = *pp) != NULL) { 3357c478bd9Sstevel@tonic-gate if (*p == 'L' && p[1] == 'D' && p[2] == '_') { 3367c478bd9Sstevel@tonic-gate for (qq = pp; (*qq = qq[1]) != NULL; qq++) { 3377c478bd9Sstevel@tonic-gate ; 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate } else { 3407c478bd9Sstevel@tonic-gate pp++; 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate static uid_t 3477c478bd9Sstevel@tonic-gate get_uid(char *value) 3487c478bd9Sstevel@tonic-gate { 3497c478bd9Sstevel@tonic-gate struct passwd *passwd_ent; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate if ((passwd_ent = getpwnam(value)) != NULL) 3527c478bd9Sstevel@tonic-gate return (passwd_ent->pw_uid); 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate if (isnumber(value)) 3557c478bd9Sstevel@tonic-gate return (atoi(value)); 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "pfexec: %s: ", value); 3587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't get user entry\n")); 3597c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 3607c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate static uid_t 3657c478bd9Sstevel@tonic-gate get_gid(char *value) 3667c478bd9Sstevel@tonic-gate { 3677c478bd9Sstevel@tonic-gate struct group *group_ent; 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate if ((group_ent = getgrnam(value)) != NULL) 3707c478bd9Sstevel@tonic-gate return (group_ent->gr_gid); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate if (isnumber(value)) 3737c478bd9Sstevel@tonic-gate return (atoi(value)); 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "pfexec: %s: ", value); 3767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't get group entry\n")); 3777c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 3787c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate static int 3837c478bd9Sstevel@tonic-gate isnumber(char *s) 3847c478bd9Sstevel@tonic-gate { 3857c478bd9Sstevel@tonic-gate int c; 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate if (*s == '\0') 3887c478bd9Sstevel@tonic-gate return (0); 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate while ((c = *s++) != '\0') { 3917c478bd9Sstevel@tonic-gate if (!isdigit(c)) { 3927c478bd9Sstevel@tonic-gate return (0); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate return (1); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate static priv_set_t * 4007c478bd9Sstevel@tonic-gate get_privset(const char *s) 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate priv_set_t *res; 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate if ((res = priv_str_to_set(s, ",", NULL)) == NULL) { 4057c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: bad privilege set\n", s); 4067c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate return (res); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate static void 4127c478bd9Sstevel@tonic-gate usage(void) 4137c478bd9Sstevel@tonic-gate { 4147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("pfexec [-P privset] cmd [arg ..]\n")); 4157c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* 4207c478bd9Sstevel@tonic-gate * This routine exists on failure and returns NULL if no granted privileges 4217c478bd9Sstevel@tonic-gate * are set. 4227c478bd9Sstevel@tonic-gate */ 4237c478bd9Sstevel@tonic-gate static priv_set_t * 4247c478bd9Sstevel@tonic-gate get_granted_privs(uid_t uid) 4257c478bd9Sstevel@tonic-gate { 4267c478bd9Sstevel@tonic-gate struct passwd *pwent; 4277c478bd9Sstevel@tonic-gate userattr_t *ua; 4287c478bd9Sstevel@tonic-gate char *profs; 4297c478bd9Sstevel@tonic-gate priv_set_t *res; 4307c478bd9Sstevel@tonic-gate char *profArray[MAXPROFS]; 4317c478bd9Sstevel@tonic-gate int profcnt = 0; 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate res = priv_allocset(); 4347c478bd9Sstevel@tonic-gate if (res == NULL) { 4357c478bd9Sstevel@tonic-gate perror("priv_allocset"); 4367c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate priv_emptyset(res); 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate if ((pwent = getpwuid(uid)) == NULL) { 4427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%d: ", (int)uid); 4437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't get passwd entry\n")); 4447c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate ua = getusernam(pwent->pw_name); 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate if (ua != NULL && ua->attr != NULL && 4507c478bd9Sstevel@tonic-gate (profs = kva_match(ua->attr, USERATTR_PROFILES_KW)) != NULL) { 4517c478bd9Sstevel@tonic-gate get_profile_privs(profs, profArray, &profcnt, res); 4527c478bd9Sstevel@tonic-gate free_proflist(profArray, profcnt); 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate get_default_privs(res); 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate if (ua != NULL) 4587c478bd9Sstevel@tonic-gate free_userattr(ua); 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate return (res); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate static void 4647c478bd9Sstevel@tonic-gate get_default_privs(priv_set_t *pset) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate char *profs = NULL; 4677c478bd9Sstevel@tonic-gate char *profArray[MAXPROFS]; 4687c478bd9Sstevel@tonic-gate int profcnt = 0; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate if (defopen(AUTH_POLICY) == 0) { 4717c478bd9Sstevel@tonic-gate /* get privileges from default profiles */ 4727c478bd9Sstevel@tonic-gate profs = defread(DEF_PROF); 4737c478bd9Sstevel@tonic-gate if (profs != NULL) { 4747c478bd9Sstevel@tonic-gate get_profile_privs(profs, profArray, &profcnt, pset); 4757c478bd9Sstevel@tonic-gate free_proflist(profArray, profcnt); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate (void) defopen(NULL); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate static void 4827c478bd9Sstevel@tonic-gate get_profile_privs(char *profiles, char **profArray, int *profcnt, 4837c478bd9Sstevel@tonic-gate priv_set_t *pset) 4847c478bd9Sstevel@tonic-gate { 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate char *prof; 4877c478bd9Sstevel@tonic-gate char *lasts; 4887c478bd9Sstevel@tonic-gate profattr_t *pa; 4897c478bd9Sstevel@tonic-gate char *privs; 4907c478bd9Sstevel@tonic-gate int i; 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate for (prof = strtok_r(profiles, PROFLIST_SEP, &lasts); 4937c478bd9Sstevel@tonic-gate prof != NULL; 4947c478bd9Sstevel@tonic-gate prof = strtok_r(NULL, PROFLIST_SEP, &lasts)) 4957c478bd9Sstevel@tonic-gate getproflist(prof, profArray, profcnt); 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate /* get the privileges from list of profiles */ 4987c478bd9Sstevel@tonic-gate for (i = 0; i < *profcnt; i++) { 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate if ((pa = getprofnam(profArray[i])) == NULL) { 5017c478bd9Sstevel@tonic-gate /* 5027c478bd9Sstevel@tonic-gate * this should never happen. 5037c478bd9Sstevel@tonic-gate * unless the database has an undefined profile 5047c478bd9Sstevel@tonic-gate */ 5057c478bd9Sstevel@tonic-gate continue; 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate /* get privs from this profile */ 5097c478bd9Sstevel@tonic-gate privs = kva_match(pa->attr, PROFATTR_PRIVS_KW); 5107c478bd9Sstevel@tonic-gate if (privs != NULL) { 5117c478bd9Sstevel@tonic-gate priv_set_t *tmp = priv_str_to_set(privs, ",", NULL); 5127c478bd9Sstevel@tonic-gate if (tmp != NULL) { 5137c478bd9Sstevel@tonic-gate priv_union(tmp, pset); 5147c478bd9Sstevel@tonic-gate priv_freeset(tmp); 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate free_profattr(pa); 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate /* 5237c478bd9Sstevel@tonic-gate * This function can return either the first argument or dynamically 5247c478bd9Sstevel@tonic-gate * allocated memory. Reuse with care. 5257c478bd9Sstevel@tonic-gate */ 5267c478bd9Sstevel@tonic-gate static char * 5277c478bd9Sstevel@tonic-gate pathsearch(char *cmd) 5287c478bd9Sstevel@tonic-gate { 5297c478bd9Sstevel@tonic-gate char *path, *dir; 5307c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* 5337c478bd9Sstevel@tonic-gate * Implement shell like PATH searching; if the pathname contains 5347c478bd9Sstevel@tonic-gate * one or more slashes, don't search the path, even if the '/' 5357c478bd9Sstevel@tonic-gate * isn't the first character. (E.g., ./command or dir/command) 5367c478bd9Sstevel@tonic-gate * No path equals to a search in ".", just like the shell. 5377c478bd9Sstevel@tonic-gate */ 5387c478bd9Sstevel@tonic-gate if (strchr(cmd, '/') != NULL) 5397c478bd9Sstevel@tonic-gate return (cmd); 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate path = getenv("PATH"); 5427c478bd9Sstevel@tonic-gate if (path == NULL) 5437c478bd9Sstevel@tonic-gate return (cmd); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate /* 5467c478bd9Sstevel@tonic-gate * We need to copy $PATH because our sub processes may need it. 5477c478bd9Sstevel@tonic-gate */ 5487c478bd9Sstevel@tonic-gate path = strdup(path); 5497c478bd9Sstevel@tonic-gate if (path == NULL) { 5507c478bd9Sstevel@tonic-gate perror("pfexec: strdup $PATH"); 5517c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":")) { 5557c478bd9Sstevel@tonic-gate if (snprintf(buf, sizeof (buf), "%s/%s", dir, cmd) >= 5567c478bd9Sstevel@tonic-gate sizeof (buf)) { 5577c478bd9Sstevel@tonic-gate continue; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate if (access(buf, X_OK) == 0) { 5607c478bd9Sstevel@tonic-gate free(path); 5617c478bd9Sstevel@tonic-gate return (strdup(buf)); 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate free(path); 5657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: Command not found\n"), cmd); 5667c478bd9Sstevel@tonic-gate return (NULL); 5677c478bd9Sstevel@tonic-gate } 568