17c478bd9Sstevel@tonic-gate /*
2*134a1f4eSCasper H.S. Dik * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
37c478bd9Sstevel@tonic-gate */
47c478bd9Sstevel@tonic-gate
57c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
67c478bd9Sstevel@tonic-gate /* All Rights Reserved */
77c478bd9Sstevel@tonic-gate
87c478bd9Sstevel@tonic-gate /*
97c478bd9Sstevel@tonic-gate * Copyright (c) 1985 Regents of the University of California.
107c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement
117c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
127c478bd9Sstevel@tonic-gate */
137c478bd9Sstevel@tonic-gate
147257d1b4Sraf #include "lint.h"
157c478bd9Sstevel@tonic-gate #include <sys/types.h>
167c478bd9Sstevel@tonic-gate #include <sys/param.h>
177c478bd9Sstevel@tonic-gate #include <sys/stat.h>
187c478bd9Sstevel@tonic-gate #include <ctype.h>
197c478bd9Sstevel@tonic-gate #include <stdio.h>
207c478bd9Sstevel@tonic-gate #include <limits.h>
217c478bd9Sstevel@tonic-gate #include <stdlib.h>
227c478bd9Sstevel@tonic-gate #include <sys/file.h>
237c478bd9Sstevel@tonic-gate #include "libc.h"
247c478bd9Sstevel@tonic-gate #include <unistd.h>
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #define SHELLS "/etc/shells"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate * Do not add local shells here. They should be added in /etc/shells
30da2e3ebdSchin *
31da2e3ebdSchin * Do not add restricted shells:
32da2e3ebdSchin * Shells returned by getusershell traditionally allow:
33da2e3ebdSchin * - users to change away from (i.e., if you have an rksh in
34da2e3ebdSchin * getusershell(), then users can change their shell to ksh)
35da2e3ebdSchin * - by default, ftp in is allowed only for shells returned by
36da2e3ebdSchin * getusershell(); since FTP has no restrictions on directory
37da2e3ebdSchin * movement, adding rksh to getusershell() would defeat that
38da2e3ebdSchin * protection.
397c478bd9Sstevel@tonic-gate */
407c478bd9Sstevel@tonic-gate const char *okshells[] = {
417c478bd9Sstevel@tonic-gate "/usr/bin/sh",
427c478bd9Sstevel@tonic-gate "/usr/bin/csh",
437c478bd9Sstevel@tonic-gate "/usr/bin/ksh",
44da2e3ebdSchin "/usr/bin/ksh93",
457c478bd9Sstevel@tonic-gate "/usr/bin/jsh",
467c478bd9Sstevel@tonic-gate "/bin/sh",
477c478bd9Sstevel@tonic-gate "/bin/csh",
487c478bd9Sstevel@tonic-gate "/bin/ksh",
49da2e3ebdSchin "/bin/ksh93",
507c478bd9Sstevel@tonic-gate "/bin/jsh",
517c478bd9Sstevel@tonic-gate "/sbin/sh",
527c478bd9Sstevel@tonic-gate "/sbin/jsh",
537c478bd9Sstevel@tonic-gate "/usr/bin/pfsh",
547c478bd9Sstevel@tonic-gate "/usr/bin/pfcsh",
557c478bd9Sstevel@tonic-gate "/usr/bin/pfksh",
56*134a1f4eSCasper H.S. Dik "/usr/bin/pfksh93",
577c478bd9Sstevel@tonic-gate "/usr/bin/bash",
587c478bd9Sstevel@tonic-gate "/usr/bin/tcsh",
597c478bd9Sstevel@tonic-gate "/usr/bin/zsh",
60*134a1f4eSCasper H.S. Dik "/usr/bin/pfbash",
61*134a1f4eSCasper H.S. Dik "/usr/bin/pftcsh",
62*134a1f4eSCasper H.S. Dik "/usr/bin/pfzsh",
637c478bd9Sstevel@tonic-gate "/bin/pfsh",
647c478bd9Sstevel@tonic-gate "/bin/pfcsh",
657c478bd9Sstevel@tonic-gate "/bin/pfksh",
66*134a1f4eSCasper H.S. Dik "/bin/pfksh93",
677c478bd9Sstevel@tonic-gate "/bin/bash",
687c478bd9Sstevel@tonic-gate "/bin/tcsh",
697c478bd9Sstevel@tonic-gate "/bin/zsh",
70*134a1f4eSCasper H.S. Dik "/bin/pfbash",
71*134a1f4eSCasper H.S. Dik "/bin/pftcsh",
72*134a1f4eSCasper H.S. Dik "/bin/pfzsh",
737c478bd9Sstevel@tonic-gate "/usr/xpg4/bin/sh",
74*134a1f4eSCasper H.S. Dik "/usr/xpg4/bin/pfsh",
757c478bd9Sstevel@tonic-gate "/sbin/pfsh",
7660c80770Scraigm "/usr/sfw/bin/zsh",
777c478bd9Sstevel@tonic-gate NULL
787c478bd9Sstevel@tonic-gate };
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate static char **shells, *strings;
817c478bd9Sstevel@tonic-gate static char **curshell;
827c478bd9Sstevel@tonic-gate static char **initshells(void);
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate * Get a list of shells from SHELLS, if it exists.
867c478bd9Sstevel@tonic-gate */
877c478bd9Sstevel@tonic-gate char *
getusershell(void)887c478bd9Sstevel@tonic-gate getusershell(void)
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate char *ret;
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate if (curshell == NULL)
937c478bd9Sstevel@tonic-gate curshell = initshells();
947c478bd9Sstevel@tonic-gate ret = *curshell;
957c478bd9Sstevel@tonic-gate if (ret != NULL)
967c478bd9Sstevel@tonic-gate curshell++;
977c478bd9Sstevel@tonic-gate return (ret);
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate void
endusershell(void)1017c478bd9Sstevel@tonic-gate endusershell(void)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate if (shells != NULL)
1057c478bd9Sstevel@tonic-gate (void) free((char *)shells);
1067c478bd9Sstevel@tonic-gate shells = NULL;
1077c478bd9Sstevel@tonic-gate if (strings != NULL)
1087c478bd9Sstevel@tonic-gate (void) free(strings);
1097c478bd9Sstevel@tonic-gate strings = NULL;
1107c478bd9Sstevel@tonic-gate curshell = NULL;
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate void
setusershell(void)1147c478bd9Sstevel@tonic-gate setusershell(void)
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate curshell = initshells();
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate static char **
initshells(void)1217c478bd9Sstevel@tonic-gate initshells(void)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate char **sp, *cp;
1247c478bd9Sstevel@tonic-gate FILE *fp;
1257c478bd9Sstevel@tonic-gate struct stat statb;
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate if (shells != NULL)
1287c478bd9Sstevel@tonic-gate (void) free((char *)shells);
1297c478bd9Sstevel@tonic-gate shells = NULL;
1307c478bd9Sstevel@tonic-gate if (strings != NULL)
1317c478bd9Sstevel@tonic-gate (void) free(strings);
1327c478bd9Sstevel@tonic-gate strings = NULL;
133004388ebScasper if ((fp = fopen(SHELLS, "rF")) == (FILE *)0)
1347c478bd9Sstevel@tonic-gate return ((char **)okshells);
1357c478bd9Sstevel@tonic-gate /*
1367c478bd9Sstevel@tonic-gate * The +1 in the malloc() below is needed to handle the final
1377c478bd9Sstevel@tonic-gate * fgets() NULL terminator. From fgets(3S):
1387c478bd9Sstevel@tonic-gate *
1397c478bd9Sstevel@tonic-gate * char *fgets(char *s, int n, FILE *stream);
1407c478bd9Sstevel@tonic-gate *
1417c478bd9Sstevel@tonic-gate * The fgets() function reads characters from the stream into
1427c478bd9Sstevel@tonic-gate * the array pointed to by s, until n-1 characters are read, or
1437c478bd9Sstevel@tonic-gate * a newline character is read and transferred to s, or an end-
1447c478bd9Sstevel@tonic-gate * of-file condition is encountered. The string is then termi-
1457c478bd9Sstevel@tonic-gate * nated with a null character.
1467c478bd9Sstevel@tonic-gate */
1477c478bd9Sstevel@tonic-gate if ((fstat(fileno(fp), &statb) == -1) || (statb.st_size > LONG_MAX) ||
1487c478bd9Sstevel@tonic-gate ((strings = malloc((size_t)statb.st_size + 1)) == NULL)) {
1497c478bd9Sstevel@tonic-gate (void) fclose(fp);
1507c478bd9Sstevel@tonic-gate return ((char **)okshells);
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate shells = calloc((size_t)statb.st_size / 3, sizeof (char *));
1537c478bd9Sstevel@tonic-gate if (shells == NULL) {
1547c478bd9Sstevel@tonic-gate (void) fclose(fp);
1557c478bd9Sstevel@tonic-gate (void) free(strings);
1567c478bd9Sstevel@tonic-gate strings = NULL;
1577c478bd9Sstevel@tonic-gate return ((char **)okshells);
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate sp = shells;
1607c478bd9Sstevel@tonic-gate cp = strings;
1617c478bd9Sstevel@tonic-gate while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
1627c478bd9Sstevel@tonic-gate while (*cp != '#' && *cp != '/' && *cp != '\0')
1637c478bd9Sstevel@tonic-gate cp++;
1647c478bd9Sstevel@tonic-gate if (*cp == '#' || *cp == '\0')
1657c478bd9Sstevel@tonic-gate continue;
1667c478bd9Sstevel@tonic-gate *sp++ = cp;
1677c478bd9Sstevel@tonic-gate while (!isspace(*cp) && *cp != '#' && *cp != '\0')
1687c478bd9Sstevel@tonic-gate cp++;
1697c478bd9Sstevel@tonic-gate *cp++ = '\0';
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate *sp = (char *)0;
1727c478bd9Sstevel@tonic-gate (void) fclose(fp);
1737c478bd9Sstevel@tonic-gate return (shells);
1747c478bd9Sstevel@tonic-gate }
175