1 /* 2 * Dropbear - a SSH2 server 3 * 4 * Copyright (c) 2002,2003 Matt Johnston 5 * All rights reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * strlcat() is copyright as follows: 26 * Copyright (c) 1998 Todd C. Miller <Todd.Miller (at) courtesan.com> 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 2. Redistributions in binary form must reproduce the above copyright 35 * notice, this list of conditions and the following disclaimer in the 36 * documentation and/or other materials provided with the distribution. 37 * 3. The name of the author may not be used to endorse or promote products 38 * derived from this software without specific prior written permission. 39 * 40 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 41 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 42 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 43 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 44 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 45 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 46 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 47 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 48 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 49 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 * 51 * daemon() and getusershell() is copyright as follows: 52 * 53 * Copyright (c) 1990, 1993 54 * The Regents of the University of California. All rights reserved. 55 * 56 * Redistribution and use in source and binary forms, with or without 57 * modification, are permitted provided that the following conditions 58 * are met: 59 * 1. Redistributions of source code must retain the above copyright 60 * notice, this list of conditions and the following disclaimer. 61 * 2. Redistributions in binary form must reproduce the above copyright 62 * notice, this list of conditions and the following disclaimer in the 63 * documentation and/or other materials provided with the distribution. 64 * 3. Neither the name of the University nor the names of its contributors 65 * may be used to endorse or promote products derived from this software 66 * without specific prior written permission. 67 * 68 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 69 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 70 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 71 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 72 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 73 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 74 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 75 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 76 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 77 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 78 * SUCH DAMAGE. 79 * 80 * Modifications for Dropbear to getusershell() are by Paul Marinceu 81 */ 82 83 #include "includes.h" 84 85 #ifndef HAVE_GETUSERSHELL 86 static char **curshell, **shells, *strings; 87 static char **initshells(); 88 #endif 89 90 #ifndef HAVE_STRLCPY 91 /* Implemented by matt as specified in freebsd 4.7 manpage. 92 * We don't require great speed, is simply for use with sshpty code */ 93 size_t strlcpy(char *dst, const char *src, size_t size) { 94 95 size_t i; 96 97 /* this is undefined, though size==0 -> return 0 */ 98 if (size < 1) { 99 return 0; 100 } 101 102 for (i = 0; i < size-1; i++) { 103 if (src[i] == '\0') { 104 break; 105 } else { 106 dst[i] = src[i]; 107 } 108 } 109 110 dst[i] = '\0'; 111 return strlen(src); 112 113 } 114 #endif /* HAVE_STRLCPY */ 115 116 #ifndef HAVE_STRLCAT 117 /* taken from openbsd-compat for OpenSSH 3.6.1p1 */ 118 /* "$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $" 119 * 120 * Appends src to string dst of size siz (unlike strncat, siz is the 121 * full size of dst, not space left). At most siz-1 characters 122 * will be copied. Always NUL terminates (unless siz <= strlen(dst)). 123 * Returns strlen(src) + MIN(siz, strlen(initial dst)). 124 * If retval >= siz, truncation occurred. 125 */ 126 size_t 127 strlcat(dst, src, siz) 128 char *dst; 129 const char *src; 130 size_t siz; 131 { 132 register char *d = dst; 133 register const char *s = src; 134 register size_t n = siz; 135 size_t dlen; 136 137 /* Find the end of dst and adjust bytes left but don't go past end */ 138 while (n-- != 0 && *d != '\0') 139 d++; 140 dlen = d - dst; 141 n = siz - dlen; 142 143 if (n == 0) 144 return(dlen + strlen(s)); 145 while (*s != '\0') { 146 if (n != 1) { 147 *d++ = *s; 148 n--; 149 } 150 s++; 151 } 152 *d = '\0'; 153 154 return(dlen + (s - src)); /* count does not include NUL */ 155 } 156 #endif /* HAVE_STRLCAT */ 157 158 #ifndef HAVE_DAEMON 159 /* From NetBSD - daemonise a process */ 160 161 int daemon(int nochdir, int noclose) { 162 163 int fd; 164 165 switch (fork()) { 166 case -1: 167 return (-1); 168 case 0: 169 break; 170 default: 171 _exit(0); 172 } 173 174 if (setsid() == -1) 175 return -1; 176 177 if (!nochdir) 178 (void)chdir("/"); 179 180 if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 181 (void)dup2(fd, STDIN_FILENO); 182 (void)dup2(fd, STDOUT_FILENO); 183 (void)dup2(fd, STDERR_FILENO); 184 if (fd > STDERR_FILENO) 185 (void)close(fd); 186 } 187 return 0; 188 } 189 #endif /* HAVE_DAEMON */ 190 191 #ifndef HAVE_BASENAME 192 193 char *basename(const char *path) { 194 195 char *foo = strrchr(path, '/'); 196 return ++foo; 197 } 198 199 #endif /* HAVE_BASENAME */ 200 201 #ifndef HAVE_GETUSERSHELL 202 203 /* 204 * Get a list of shells from /etc/shells, if it exists. 205 */ 206 char * getusershell() { 207 char *ret; 208 209 if (curshell == NULL) 210 curshell = initshells(); 211 ret = *curshell; 212 if (ret != NULL) 213 curshell++; 214 return (ret); 215 } 216 217 void endusershell() { 218 219 if (shells != NULL) 220 free(shells); 221 shells = NULL; 222 if (strings != NULL) 223 free(strings); 224 strings = NULL; 225 curshell = NULL; 226 } 227 228 void setusershell() { 229 curshell = initshells(); 230 } 231 232 static char **initshells() { 233 /* don't touch this list. */ 234 const char *okshells[] = { "/bin/sh", "/bin/csh", NULL }; 235 register char **sp, *cp; 236 register FILE *fp; 237 struct stat statb; 238 int flen; 239 240 if (shells != NULL) 241 free(shells); 242 shells = NULL; 243 if (strings != NULL) 244 free(strings); 245 strings = NULL; 246 if ((fp = fopen("/etc/shells", "rc")) == NULL) 247 return (char **) okshells; 248 if (fstat(fileno(fp), &statb) == -1) { 249 (void)fclose(fp); 250 return (char **) okshells; 251 } 252 if ((strings = malloc((u_int)statb.st_size + 1)) == NULL) { 253 (void)fclose(fp); 254 return (char **) okshells; 255 } 256 shells = calloc((unsigned)statb.st_size / 3, sizeof (char *)); 257 if (shells == NULL) { 258 (void)fclose(fp); 259 free(strings); 260 strings = NULL; 261 return (char **) okshells; 262 } 263 sp = shells; 264 cp = strings; 265 flen = statb.st_size; 266 while (fgets(cp, flen - (cp - strings), fp) != NULL) { 267 while (*cp != '#' && *cp != '/' && *cp != '\0') 268 cp++; 269 if (*cp == '#' || *cp == '\0') 270 continue; 271 *sp++ = cp; 272 while (!isspace(*cp) && *cp != '#' && *cp != '\0') 273 cp++; 274 *cp++ = '\0'; 275 } 276 *sp = NULL; 277 (void)fclose(fp); 278 return (shells); 279 } 280 281 #endif /* HAVE_GETUSERSHELL */ 282