/* * Dropbear - a SSH2 server * * Copyright (c) 2002,2003 Matt Johnston * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * strlcat() is copyright as follows: * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * daemon() and getusershell() is copyright as follows: * * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Modifications for Dropbear to getusershell() are by Paul Marinceu */ #include "includes.h" #ifndef HAVE_GETUSERSHELL static char **curshell, **shells, *strings; static char **initshells(); #endif #ifndef HAVE_STRLCPY /* Implemented by matt as specified in freebsd 4.7 manpage. * We don't require great speed, is simply for use with sshpty code */ size_t strlcpy(char *dst, const char *src, size_t size) { size_t i; /* this is undefined, though size==0 -> return 0 */ if (size < 1) { return 0; } for (i = 0; i < size-1; i++) { if (src[i] == '\0') { break; } else { dst[i] = src[i]; } } dst[i] = '\0'; return strlen(src); } #endif /* HAVE_STRLCPY */ #ifndef HAVE_STRLCAT /* taken from openbsd-compat for OpenSSH 7.2p2 */ /* "$OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $" * * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ size_t strlcat(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return(dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return(dlen + (s - src)); /* count does not include NUL */ } #endif /* HAVE_STRLCAT */ #ifndef HAVE_DAEMON /* From NetBSD - daemonise a process */ int daemon(int nochdir, int noclose) { int fd; switch (fork()) { case -1: return (-1); case 0: break; default: _exit(0); } if (setsid() == -1) return -1; if (!nochdir) (void)chdir("/"); if (!noclose && (fd = open(DROPBEAR_PATH_DEVNULL, O_RDWR, 0)) != -1) { (void)dup2(fd, STDIN_FILENO); (void)dup2(fd, STDOUT_FILENO); (void)dup2(fd, STDERR_FILENO); if (fd > STDERR_FILENO) (void)close(fd); } return 0; } #endif /* HAVE_DAEMON */ #ifndef HAVE_BASENAME char *basename(const char *path) { char *foo = strrchr(path, '/'); if (!foo) { return path; } return ++foo; } #endif /* HAVE_BASENAME */ #ifndef HAVE_GETUSERSHELL /* * Get a list of shells from /etc/shells, if it exists. */ char * getusershell() { char *ret; if (curshell == NULL) curshell = initshells(); ret = *curshell; if (ret != NULL) curshell++; return (ret); } void endusershell() { if (shells != NULL) free(shells); shells = NULL; if (strings != NULL) free(strings); strings = NULL; curshell = NULL; } void setusershell() { curshell = initshells(); } static char **initshells() { /* don't touch this list. */ static const char *okshells[] = { "/bin/sh", "/bin/csh", NULL }; register char **sp, *cp; register FILE *fp; struct stat statb; int flen; if (shells != NULL) free(shells); shells = NULL; if (strings != NULL) free(strings); strings = NULL; if ((fp = fopen("/etc/shells", "rc")) == NULL) return (char **) okshells; if (fstat(fileno(fp), &statb) == -1) { (void)fclose(fp); return (char **) okshells; } if ((strings = malloc((u_int)statb.st_size + 1)) == NULL) { (void)fclose(fp); return (char **) okshells; } shells = calloc((unsigned)statb.st_size / 3, sizeof (char *)); if (shells == NULL) { (void)fclose(fp); free(strings); strings = NULL; return (char **) okshells; } sp = shells; cp = strings; flen = statb.st_size; while (fgets(cp, flen - (cp - strings), fp) != NULL) { while (*cp != '#' && *cp != '/' && *cp != '\0') cp++; if (*cp == '#' || *cp == '\0') continue; *sp++ = cp; while (!isspace(*cp) && *cp != '#' && *cp != '\0') cp++; *cp++ = '\0'; } *sp = NULL; (void)fclose(fp); return (shells); } #endif /* HAVE_GETUSERSHELL */