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 * 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 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 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 ** 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