misc.c revision d059297112922cabb0c674840589be8db821fd9a
1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: misc.c,v 1.96 2015/01/16 06:40:12 deraadt Exp $ */ 2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 2000 Markus Friedl. All rights reserved. 4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 2005,2006 Damien Miller. All rights reserved. 5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Redistribution and use in source and binary forms, with or without 7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * modification, are permitted provided that the following conditions 8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * are met: 9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1. Redistributions of source code must retain the above copyright 10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer. 11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2. Redistributions in binary form must reproduce the above copyright 12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer in the 13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * documentation and/or other materials provided with the distribution. 14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h" 28bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/types.h> 30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/ioctl.h> 31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/socket.h> 32d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <sys/un.h> 33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 34d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <limits.h> 35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h> 36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdio.h> 37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdlib.h> 38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h> 39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <time.h> 40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <unistd.h> 41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netinet/in.h> 43bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netinet/in_systm.h> 44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netinet/ip.h> 45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netinet/tcp.h> 46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 47d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <ctype.h> 48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <errno.h> 49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <fcntl.h> 50bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netdb.h> 51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_PATHS_H 52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# include <paths.h> 53bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <pwd.h> 54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef SSH_TUN_OPENBSD 56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <net/if.h> 57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "xmalloc.h" 60bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "misc.h" 61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "log.h" 62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "ssh.h" 63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* remove newline at end of string */ 65bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchop(char *s) 67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 68bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *t = s; 69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (*t) { 70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*t == '\n' || *t == '\r') { 71bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *t = '\0'; 72bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return s; 73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 74bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman t++; 75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return s; 77bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* set/unset filedescriptor to non-blocking */ 81bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 82bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanset_nonblock(int fd) 83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 84bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int val; 85bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman val = fcntl(fd, F_GETFL, 0); 87bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (val < 0) { 88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); 89bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 90bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (val & O_NONBLOCK) { 92bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug3("fd %d is O_NONBLOCK", fd); 93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug2("fd %d setting O_NONBLOCK", fd); 96bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman val |= O_NONBLOCK; 97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fcntl(fd, F_SETFL, val) == -1) { 98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd, 99bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strerror(errno)); 100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanunset_nonblock(int fd) 107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int val; 109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman val = fcntl(fd, F_GETFL, 0); 111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (val < 0) { 112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); 113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!(val & O_NONBLOCK)) { 116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug3("fd %d is not O_NONBLOCK", fd); 117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("fd %d clearing O_NONBLOCK", fd); 120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman val &= ~O_NONBLOCK; 121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fcntl(fd, F_SETFL, val) == -1) { 122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s", 123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fd, strerror(errno)); 124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanconst char * 130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanssh_gai_strerror(int gaierr) 131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 132d059297112922cabb0c674840589be8db821fd9aAdam Langley if (gaierr == EAI_SYSTEM && errno != 0) 133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return strerror(errno); 134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return gai_strerror(gaierr); 135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* disable nagle on socket */ 138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanset_nodelay(int fd) 140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int opt; 142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman socklen_t optlen; 143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman optlen = sizeof opt; 145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { 146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("getsockopt TCP_NODELAY: %.100s", strerror(errno)); 147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (opt == 1) { 150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug2("fd %d is TCP_NODELAY", fd); 151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman opt = 1; 154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug2("fd %d setting TCP_NODELAY", fd); 155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) 156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); 157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Characters considered whitespace in strsep calls. */ 160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define WHITESPACE " \t\r\n" 161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define QUOTE "\"" 162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* return next token in configuration line */ 164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstrdelim(char **s) 166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *old; 168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int wspace = 0; 169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s == NULL) 171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman old = *s; 174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s = strpbrk(*s, WHITESPACE QUOTE "="); 176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s == NULL) 177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (old); 178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s[0] == '\"') { 180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memmove(*s, *s + 1, strlen(*s)); /* move nul too */ 181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Find matching quote */ 182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((*s = strpbrk(*s, QUOTE)) == NULL) { 183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (NULL); /* no matching quote */ 184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s[0] = '\0'; 186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s += strspn(*s + 1, WHITESPACE) + 1; 187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (old); 188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Allow only one '=' to be skipped */ 192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s[0] == '=') 193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wspace = 1; 194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s[0] = '\0'; 195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Skip any extra whitespace after first token */ 197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s += strspn(*s + 1, WHITESPACE) + 1; 198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s[0] == '=' && !wspace) 199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s += strspn(*s + 1, WHITESPACE) + 1; 200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (old); 202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstruct passwd * 205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanpwcopy(struct passwd *pw) 206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct passwd *copy = xcalloc(1, sizeof(*copy)); 208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_name = xstrdup(pw->pw_name); 210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_passwd = pw->pw_passwd ? xstrdup(pw->pw_passwd) : NULL; 211d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef HAVE_STRUCT_PASSWD_PW_GECOS 212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_gecos = xstrdup(pw->pw_gecos); 213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_uid = pw->pw_uid; 215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_gid = pw->pw_gid; 216d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE 217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_expire = pw->pw_expire; 218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 219d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE 220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_change = pw->pw_change; 221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 222d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef HAVE_STRUCT_PASSWD_PW_CLASS 223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_class = xstrdup(pw->pw_class); 224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_dir = xstrdup(pw->pw_dir); 226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_shell = xstrdup(pw->pw_shell); 227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return copy; 228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Convert ASCII string to TCP/IP port number. 232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Port must be >=0 and <=65535. 233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Return -1 if invalid. 234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmana2port(const char *s) 237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman long long port; 239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *errstr; 240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman port = strtonum(s, 0, 65535, &errstr); 242bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errstr != NULL) 243bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 244bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (int)port; 245bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 246bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 247bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 248bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmana2tun(const char *s, int *remote) 249bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 250bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *errstr = NULL; 251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *sp, *ep; 252bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int tun; 253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (remote != NULL) { 255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *remote = SSH_TUNID_ANY; 256bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sp = xstrdup(s); 257bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((ep = strchr(sp, ':')) == NULL) { 258d059297112922cabb0c674840589be8db821fd9aAdam Langley free(sp); 259bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (a2tun(s, NULL)); 260bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 261bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ep[0] = '\0'; ep++; 262bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *remote = a2tun(ep, NULL); 263bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tun = a2tun(sp, NULL); 264d059297112922cabb0c674840589be8db821fd9aAdam Langley free(sp); 265bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (*remote == SSH_TUNID_ERR ? *remote : tun); 266bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 267bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 268bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strcasecmp(s, "any") == 0) 269bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (SSH_TUNID_ANY); 270bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 271bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); 272bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errstr != NULL) 273bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (SSH_TUNID_ERR); 274bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 275bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (tun); 276bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 277bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define SECONDS 1 279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define MINUTES (SECONDS * 60) 280bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define HOURS (MINUTES * 60) 281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define DAYS (HOURS * 24) 282bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define WEEKS (DAYS * 7) 283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 284bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 285bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Convert a time string into seconds; format is 286bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * a sequence of: 287bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * time[qualifier] 288bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 289bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Valid time qualifiers are: 290bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * <none> seconds 291bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * s|S seconds 292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * m|M minutes 293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * h|H hours 294bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * d|D days 295bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * w|W weeks 296bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Examples: 298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 90m 90 minutes 299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1h30m 90 minutes 300bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2d 2 days 301bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1w 1 week 302bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Return -1 if time string is invalid. 304bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanlong 306bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanconvtime(const char *s) 307bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 308bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman long total, secs; 309bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *p; 310bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *endp; 311bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 312bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno = 0; 313bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman total = 0; 314bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p = s; 315bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 316bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (p == NULL || *p == '\0') 317bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 318bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 319bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (*p) { 320bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman secs = strtol(p, &endp, 10); 321bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (p == endp || 322bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || 323bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman secs < 0) 324bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 325bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 326bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (*endp++) { 327bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '\0': 328bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman endp--; 329bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 330bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 's': 331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'S': 332bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 333bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'm': 334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'M': 335bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman secs *= MINUTES; 336bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 337bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'h': 338bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'H': 339bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman secs *= HOURS; 340bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 341bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'd': 342bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'D': 343bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman secs *= DAYS; 344bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 345bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'w': 346bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'W': 347bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman secs *= WEEKS; 348bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 349bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 350bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 351bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 352bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman total += secs; 353bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (total < 0) 354bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 355bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p = endp; 356bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 357bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 358bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return total; 359bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 360bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 361bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 362bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Returns a standardized host+port identifier string. 363bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Caller must free returned string. 364bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 365bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 366bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanput_host_port(const char *host, u_short port) 367bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 368bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *hoststr; 369bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 370bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (port == 0 || port == SSH_DEFAULT_PORT) 371bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return(xstrdup(host)); 372bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0) 373bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("put_host_port: asprintf: %s", strerror(errno)); 374bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug3("put_host_port: %s", hoststr); 375bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return hoststr; 376bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 377bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 378bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 379bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Search for next delimiter between hostnames/addresses and ports. 380bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Argument may be modified (for termination). 381bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Returns *cp if parsing succeeds. 382bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * *cp is set to the start of the next delimiter, if one was found. 383bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * If this is the last field, *cp is set to NULL. 384bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 385bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 386bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanhpdelim(char **cp) 387bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 388bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *s, *old; 389bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 390bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cp == NULL || *cp == NULL) 391bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 392bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 393bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman old = s = *cp; 394bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s == '[') { 395bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((s = strchr(s, ']')) == NULL) 396bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 397bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 398bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman s++; 399bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if ((s = strpbrk(s, ":/")) == NULL) 400bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman s = *cp + strlen(*cp); /* skip to end (see first case below) */ 401bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 402bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (*s) { 403bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '\0': 404bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *cp = NULL; /* no more fields*/ 405bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 406bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 407bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case ':': 408bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '/': 409bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s = '\0'; /* terminate */ 410bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *cp = s + 1; 411bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 412bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 413bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 414bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 415bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 416bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 417bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return old; 418bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 419bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 420bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 421bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancleanhostname(char *host) 422bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 423bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*host == '[' && host[strlen(host) - 1] == ']') { 424bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host[strlen(host) - 1] = '\0'; 425bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (host + 1); 426bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else 427bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return host; 428bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 429bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 430bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 431bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancolon(char *cp) 432bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 433bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int flag = 0; 434bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 435bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == ':') /* Leading colon is part of file name. */ 436bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 437bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == '[') 438bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman flag = 1; 439bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 440bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (; *cp; ++cp) { 441bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == '@' && *(cp+1) == '[') 442bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman flag = 1; 443bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == ']' && *(cp+1) == ':' && flag) 444bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (cp+1); 445bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == ':' && !flag) 446bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (cp); 447bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == '/') 448bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 449bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 450bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 451bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 452bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 453bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* function to assist building execv() arguments */ 454bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 455bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanaddargs(arglist *args, char *fmt, ...) 456bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 457bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_list ap; 458bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *cp; 459bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int nalloc; 460bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int r; 461bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 462bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_start(ap, fmt); 463bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman r = vasprintf(&cp, fmt, ap); 464bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_end(ap); 465bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (r == -1) 466bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("addargs: argument too long"); 467bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 468bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nalloc = args->nalloc; 469bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (args->list == NULL) { 470bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nalloc = 32; 471bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->num = 0; 472bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (args->num+2 >= nalloc) 473bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nalloc *= 2; 474bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 475bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->list = xrealloc(args->list, nalloc, sizeof(char *)); 476bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->nalloc = nalloc; 477bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->list[args->num++] = cp; 478bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->list[args->num] = NULL; 479bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 480bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 481bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 482bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanreplacearg(arglist *args, u_int which, char *fmt, ...) 483bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 484bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_list ap; 485bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *cp; 486bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int r; 487bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 488bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_start(ap, fmt); 489bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman r = vasprintf(&cp, fmt, ap); 490bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_end(ap); 491bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (r == -1) 492bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("replacearg: argument too long"); 493bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 494bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (which >= args->num) 495bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("replacearg: tried to replace invalid arg %d >= %d", 496bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman which, args->num); 497d059297112922cabb0c674840589be8db821fd9aAdam Langley free(args->list[which]); 498bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->list[which] = cp; 499bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 500bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 501bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 502bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanfreeargs(arglist *args) 503bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 504bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int i; 505bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 506bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (args->list != NULL) { 507bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < args->num; i++) 508d059297112922cabb0c674840589be8db821fd9aAdam Langley free(args->list[i]); 509d059297112922cabb0c674840589be8db821fd9aAdam Langley free(args->list); 510bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->nalloc = args->num = 0; 511bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->list = NULL; 512bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 513bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 514bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 515bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 516bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Expands tildes in the file name. Returns data allocated by xmalloc. 517bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Warning: this calls getpw*. 518bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 519bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 520bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantilde_expand_filename(const char *filename, uid_t uid) 521bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 522d059297112922cabb0c674840589be8db821fd9aAdam Langley const char *path, *sep; 523d059297112922cabb0c674840589be8db821fd9aAdam Langley char user[128], *ret; 524bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct passwd *pw; 525bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int len, slash; 526bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 527bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*filename != '~') 528bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (xstrdup(filename)); 529bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman filename++; 530bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 531bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman path = strchr(filename, '/'); 532bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (path != NULL && path > filename) { /* ~user/path */ 533bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman slash = path - filename; 534bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (slash > sizeof(user) - 1) 535bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("tilde_expand_filename: ~username too long"); 536bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memcpy(user, filename, slash); 537bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman user[slash] = '\0'; 538bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((pw = getpwnam(user)) == NULL) 539bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("tilde_expand_filename: No such user %s", user); 540bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if ((pw = getpwuid(uid)) == NULL) /* ~/path */ 541bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("tilde_expand_filename: No such uid %ld", (long)uid); 542bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 543bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Make sure directory has a trailing '/' */ 544bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman len = strlen(pw->pw_dir); 545d059297112922cabb0c674840589be8db821fd9aAdam Langley if (len == 0 || pw->pw_dir[len - 1] != '/') 546d059297112922cabb0c674840589be8db821fd9aAdam Langley sep = "/"; 547d059297112922cabb0c674840589be8db821fd9aAdam Langley else 548d059297112922cabb0c674840589be8db821fd9aAdam Langley sep = ""; 549bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 550bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Skip leading '/' from specified path */ 551bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (path != NULL) 552bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman filename = path + 1; 553d059297112922cabb0c674840589be8db821fd9aAdam Langley 554d059297112922cabb0c674840589be8db821fd9aAdam Langley if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX) 555bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("tilde_expand_filename: Path too long"); 556bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 557d059297112922cabb0c674840589be8db821fd9aAdam Langley return (ret); 558bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 559bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 560bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 561bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Expand a string with a set of %[char] escapes. A number of escapes may be 562bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * specified as (char *escape_chars, char *replacement) pairs. The list must 563bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * be terminated by a NULL escape_char. Returns replaced string in memory 564bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * allocated by xmalloc. 565bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 566bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 567bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanpercent_expand(const char *string, ...) 568bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 569bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define EXPAND_MAX_KEYS 16 570bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int num_keys, i, j; 571bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct { 572bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *key; 573bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *repl; 574bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } keys[EXPAND_MAX_KEYS]; 575bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char buf[4096]; 576bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_list ap; 577bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 578bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Gather keys */ 579bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_start(ap, string); 580bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) { 581bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman keys[num_keys].key = va_arg(ap, char *); 582bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (keys[num_keys].key == NULL) 583bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 584bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman keys[num_keys].repl = va_arg(ap, char *); 585bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (keys[num_keys].repl == NULL) 586bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: NULL replacement", __func__); 587bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 588bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) 589bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: too many keys", __func__); 590bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_end(ap); 591bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 592bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Expand string */ 593bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *buf = '\0'; 594bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; *string != '\0'; string++) { 595bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*string != '%') { 596bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman append: 597bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buf[i++] = *string; 598bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (i >= sizeof(buf)) 599bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: string too long", __func__); 600bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buf[i] = '\0'; 601bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 602bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 603bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman string++; 604bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* %% case */ 605bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*string == '%') 606bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto append; 607bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (j = 0; j < num_keys; j++) { 608bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strchr(keys[j].key, *string) != NULL) { 609bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman i = strlcat(buf, keys[j].repl, sizeof(buf)); 610bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (i >= sizeof(buf)) 611bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: string too long", __func__); 612bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 613bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 614bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 615bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (j >= num_keys) 616bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: unknown key %%%c", __func__, *string); 617bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 618bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (xstrdup(buf)); 619bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#undef EXPAND_MAX_KEYS 620bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 621bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 622bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 623bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Read an entire line from a public key file into a static buffer, discarding 624bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * lines that exceed the buffer size. Returns 0 on success, -1 on failure. 625bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 626bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 627bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanread_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, 628bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_long *lineno) 629bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 630bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (fgets(buf, bufsz, f) != NULL) { 631bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf[0] == '\0') 632bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 633bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (*lineno)++; 634bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf[strlen(buf) - 1] == '\n' || feof(f)) { 635bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 636bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 637bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("%s: %s line %lu exceeds size limit", __func__, 638bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman filename, *lineno); 639bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* discard remainder of line */ 640bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (fgetc(f) != '\n' && !feof(f)) 641bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ; /* nothing */ 642bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 643bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 644bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 645bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 646bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 647bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 648bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantun_open(int tun, int mode) 649bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 650bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#if defined(CUSTOM_SYS_TUN_OPEN) 651bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (sys_tun_open(tun, mode)); 652bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#elif defined(SSH_TUN_OPENBSD) 653bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct ifreq ifr; 654bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char name[100]; 655bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int fd = -1, sock; 656bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 657bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Open the tunnel device */ 658bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (tun <= SSH_TUNID_MAX) { 659bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(name, sizeof(name), "/dev/tun%d", tun); 660bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fd = open(name, O_RDWR); 661bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (tun == SSH_TUNID_ANY) { 662bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (tun = 100; tun >= 0; tun--) { 663bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(name, sizeof(name), "/dev/tun%d", tun); 664bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((fd = open(name, O_RDWR)) >= 0) 665bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 666bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 667bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 668bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("%s: invalid tunnel %u", __func__, tun); 669bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 670bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 671bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 672bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fd < 0) { 673bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("%s: %s open failed: %s", __func__, name, strerror(errno)); 674bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 675bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 676bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 677bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("%s: %s mode %d fd %d", __func__, name, mode, fd); 678bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 679bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Set the tunnel device operation mode */ 680bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun); 681bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) 682bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto failed; 683bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 684bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) 685bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto failed; 686bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 687bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Set interface mode */ 688bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ifr.ifr_flags &= ~IFF_UP; 689bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (mode == SSH_TUNMODE_ETHERNET) 690bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ifr.ifr_flags |= IFF_LINK0; 691bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 692bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ifr.ifr_flags &= ~IFF_LINK0; 693bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) 694bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto failed; 695bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 696bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Bring interface up */ 697bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ifr.ifr_flags |= IFF_UP; 698bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) 699bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto failed; 700bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 701bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(sock); 702bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (fd); 703bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 704bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman failed: 705bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fd >= 0) 706bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(fd); 707bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (sock >= 0) 708bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(sock); 709bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("%s: failed to set %s mode %d: %s", __func__, name, 710bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mode, strerror(errno)); 711bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 712bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#else 713bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("Tunnel interfaces are not supported on this platform"); 714bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 715bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 716bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 717bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 718bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 719bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansanitise_stdfd(void) 720bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 721bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int nullfd, dupfd; 722bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 723bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 724bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "Couldn't open /dev/null: %s\n", 725bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strerror(errno)); 726bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 727bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 728bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (++dupfd <= 2) { 729bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Only clobber closed fds */ 730bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fcntl(dupfd, F_GETFL, 0) >= 0) 731bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 732bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (dup2(nullfd, dupfd) == -1) { 733bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "dup2: %s\n", strerror(errno)); 734bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 735bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 736bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 737bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (nullfd > 2) 738bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(nullfd); 739bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 740bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 741bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 742bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantohex(const void *vp, size_t l) 743bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 744bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const u_char *p = (const u_char *)vp; 745bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char b[3], *r; 746bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size_t i, hl; 747bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 748bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (l > 65536) 749bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return xstrdup("tohex: length > 65536"); 750bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 751bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman hl = l * 2 + 1; 752bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman r = xcalloc(1, hl); 753bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < l; i++) { 754bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(b, sizeof(b), "%02x", p[i]); 755bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strlcat(r, b, hl); 756bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 757bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (r); 758bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 759bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 760bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int64_t 761bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanget_u64(const void *vp) 762bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 763bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const u_char *p = (const u_char *)vp; 764bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int64_t v; 765bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 766bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v = (u_int64_t)p[0] << 56; 767bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[1] << 48; 768bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[2] << 40; 769bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[3] << 32; 770bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[4] << 24; 771bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[5] << 16; 772bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[6] << 8; 773bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[7]; 774bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 775bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (v); 776bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 777bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 778bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int32_t 779bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanget_u32(const void *vp) 780bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 781bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const u_char *p = (const u_char *)vp; 782bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int32_t v; 783bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 784bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v = (u_int32_t)p[0] << 24; 785bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int32_t)p[1] << 16; 786bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int32_t)p[2] << 8; 787bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int32_t)p[3]; 788bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 789bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (v); 790bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 791bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 792d059297112922cabb0c674840589be8db821fd9aAdam Langleyu_int32_t 793d059297112922cabb0c674840589be8db821fd9aAdam Langleyget_u32_le(const void *vp) 794d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 795d059297112922cabb0c674840589be8db821fd9aAdam Langley const u_char *p = (const u_char *)vp; 796d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int32_t v; 797d059297112922cabb0c674840589be8db821fd9aAdam Langley 798d059297112922cabb0c674840589be8db821fd9aAdam Langley v = (u_int32_t)p[0]; 799d059297112922cabb0c674840589be8db821fd9aAdam Langley v |= (u_int32_t)p[1] << 8; 800d059297112922cabb0c674840589be8db821fd9aAdam Langley v |= (u_int32_t)p[2] << 16; 801d059297112922cabb0c674840589be8db821fd9aAdam Langley v |= (u_int32_t)p[3] << 24; 802d059297112922cabb0c674840589be8db821fd9aAdam Langley 803d059297112922cabb0c674840589be8db821fd9aAdam Langley return (v); 804d059297112922cabb0c674840589be8db821fd9aAdam Langley} 805d059297112922cabb0c674840589be8db821fd9aAdam Langley 806bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int16_t 807bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanget_u16(const void *vp) 808bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 809bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const u_char *p = (const u_char *)vp; 810bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int16_t v; 811bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 812bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v = (u_int16_t)p[0] << 8; 813bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int16_t)p[1]; 814bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 815bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (v); 816bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 817bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 818bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 819bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanput_u64(void *vp, u_int64_t v) 820bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 821bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *p = (u_char *)vp; 822bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 823bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[0] = (u_char)(v >> 56) & 0xff; 824bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[1] = (u_char)(v >> 48) & 0xff; 825bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[2] = (u_char)(v >> 40) & 0xff; 826bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[3] = (u_char)(v >> 32) & 0xff; 827bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[4] = (u_char)(v >> 24) & 0xff; 828bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[5] = (u_char)(v >> 16) & 0xff; 829bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[6] = (u_char)(v >> 8) & 0xff; 830bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[7] = (u_char)v & 0xff; 831bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 832bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 833bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 834bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanput_u32(void *vp, u_int32_t v) 835bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 836bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *p = (u_char *)vp; 837bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 838bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[0] = (u_char)(v >> 24) & 0xff; 839bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[1] = (u_char)(v >> 16) & 0xff; 840bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[2] = (u_char)(v >> 8) & 0xff; 841bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[3] = (u_char)v & 0xff; 842bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 843bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 844d059297112922cabb0c674840589be8db821fd9aAdam Langleyvoid 845d059297112922cabb0c674840589be8db821fd9aAdam Langleyput_u32_le(void *vp, u_int32_t v) 846d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 847d059297112922cabb0c674840589be8db821fd9aAdam Langley u_char *p = (u_char *)vp; 848d059297112922cabb0c674840589be8db821fd9aAdam Langley 849d059297112922cabb0c674840589be8db821fd9aAdam Langley p[0] = (u_char)v & 0xff; 850d059297112922cabb0c674840589be8db821fd9aAdam Langley p[1] = (u_char)(v >> 8) & 0xff; 851d059297112922cabb0c674840589be8db821fd9aAdam Langley p[2] = (u_char)(v >> 16) & 0xff; 852d059297112922cabb0c674840589be8db821fd9aAdam Langley p[3] = (u_char)(v >> 24) & 0xff; 853d059297112922cabb0c674840589be8db821fd9aAdam Langley} 854bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 855bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 856bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanput_u16(void *vp, u_int16_t v) 857bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 858bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *p = (u_char *)vp; 859bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 860bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[0] = (u_char)(v >> 8) & 0xff; 861bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[1] = (u_char)v & 0xff; 862bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 863bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 864bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 865bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanms_subtract_diff(struct timeval *start, int *ms) 866bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 867bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct timeval diff, finish; 868bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 869bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman gettimeofday(&finish, NULL); 870bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman timersub(&finish, start, &diff); 871bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000); 872bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 873bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 874bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 875bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanms_to_timeval(struct timeval *tv, int ms) 876bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 877bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ms < 0) 878bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ms = 0; 879bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tv->tv_sec = ms / 1000; 880bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tv->tv_usec = (ms % 1000) * 1000; 881bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 882bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 883d059297112922cabb0c674840589be8db821fd9aAdam Langleytime_t 884d059297112922cabb0c674840589be8db821fd9aAdam Langleymonotime(void) 885d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 886d059297112922cabb0c674840589be8db821fd9aAdam Langley#if defined(HAVE_CLOCK_GETTIME) && \ 887d059297112922cabb0c674840589be8db821fd9aAdam Langley (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME)) 888d059297112922cabb0c674840589be8db821fd9aAdam Langley struct timespec ts; 889d059297112922cabb0c674840589be8db821fd9aAdam Langley static int gettime_failed = 0; 890d059297112922cabb0c674840589be8db821fd9aAdam Langley 891d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!gettime_failed) { 892d059297112922cabb0c674840589be8db821fd9aAdam Langley#if defined(CLOCK_BOOTTIME) 893d059297112922cabb0c674840589be8db821fd9aAdam Langley if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) 894d059297112922cabb0c674840589be8db821fd9aAdam Langley return (ts.tv_sec); 895d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 896d059297112922cabb0c674840589be8db821fd9aAdam Langley#if defined(CLOCK_MONOTONIC) 897d059297112922cabb0c674840589be8db821fd9aAdam Langley if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) 898d059297112922cabb0c674840589be8db821fd9aAdam Langley return (ts.tv_sec); 899d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 900d059297112922cabb0c674840589be8db821fd9aAdam Langley debug3("clock_gettime: %s", strerror(errno)); 901d059297112922cabb0c674840589be8db821fd9aAdam Langley gettime_failed = 1; 902d059297112922cabb0c674840589be8db821fd9aAdam Langley } 903d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */ 904d059297112922cabb0c674840589be8db821fd9aAdam Langley 905d059297112922cabb0c674840589be8db821fd9aAdam Langley return time(NULL); 906d059297112922cabb0c674840589be8db821fd9aAdam Langley} 907d059297112922cabb0c674840589be8db821fd9aAdam Langley 908bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 909bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanbandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) 910bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 911bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->buflen = buflen; 912bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->rate = kbps; 913bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->thresh = bw->rate; 914bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->lamt = 0; 915bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman timerclear(&bw->bwstart); 916bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman timerclear(&bw->bwend); 917bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 918bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 919bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Callback from read/write loop to insert bandwidth-limiting delays */ 920bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 921bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanbandwidth_limit(struct bwlimit *bw, size_t read_len) 922bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 923bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int64_t waitlen; 924bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct timespec ts, rm; 925bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 926bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!timerisset(&bw->bwstart)) { 927bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman gettimeofday(&bw->bwstart, NULL); 928bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 929bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 930bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 931bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->lamt += read_len; 932bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bw->lamt < bw->thresh) 933bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 934bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 935bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman gettimeofday(&bw->bwend, NULL); 936bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman timersub(&bw->bwend, &bw->bwstart, &bw->bwend); 937bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!timerisset(&bw->bwend)) 938bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 939bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 940bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->lamt *= 8; 941bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman waitlen = (double)1000000L * bw->lamt / bw->rate; 942bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 943bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->bwstart.tv_sec = waitlen / 1000000L; 944bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->bwstart.tv_usec = waitlen % 1000000L; 945bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 946bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (timercmp(&bw->bwstart, &bw->bwend, >)) { 947bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman timersub(&bw->bwstart, &bw->bwend, &bw->bwend); 948bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 949bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Adjust the wait time */ 950bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bw->bwend.tv_sec) { 951bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->thresh /= 2; 952bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bw->thresh < bw->buflen / 4) 953bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->thresh = bw->buflen / 4; 954bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (bw->bwend.tv_usec < 10000) { 955bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->thresh *= 2; 956bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bw->thresh > bw->buflen * 8) 957bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->thresh = bw->buflen * 8; 958bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 959bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 960bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts); 961bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (nanosleep(&ts, &rm) == -1) { 962bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errno != EINTR) 963bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 964bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ts = rm; 965bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 966bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 967bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 968bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->lamt = 0; 969bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman gettimeofday(&bw->bwstart, NULL); 970bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 971bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 972bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Make a template filename for mk[sd]temp() */ 973bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 974bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanmktemp_proto(char *s, size_t len) 975bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 976bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *tmpdir; 977bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int r; 978bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 979bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((tmpdir = getenv("TMPDIR")) != NULL) { 980bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); 981bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (r > 0 && (size_t)r < len) 982bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 983bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 984bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); 985bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (r < 0 || (size_t)r >= len) 986bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: template string too short", __func__); 987bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 988bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 989bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic const struct { 990bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *name; 991bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int value; 992bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} ipqos[] = { 993bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af11", IPTOS_DSCP_AF11 }, 994bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af12", IPTOS_DSCP_AF12 }, 995bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af13", IPTOS_DSCP_AF13 }, 996d059297112922cabb0c674840589be8db821fd9aAdam Langley { "af21", IPTOS_DSCP_AF21 }, 997bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af22", IPTOS_DSCP_AF22 }, 998bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af23", IPTOS_DSCP_AF23 }, 999bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af31", IPTOS_DSCP_AF31 }, 1000bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af32", IPTOS_DSCP_AF32 }, 1001bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af33", IPTOS_DSCP_AF33 }, 1002bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af41", IPTOS_DSCP_AF41 }, 1003bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af42", IPTOS_DSCP_AF42 }, 1004bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af43", IPTOS_DSCP_AF43 }, 1005bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs0", IPTOS_DSCP_CS0 }, 1006bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs1", IPTOS_DSCP_CS1 }, 1007bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs2", IPTOS_DSCP_CS2 }, 1008bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs3", IPTOS_DSCP_CS3 }, 1009bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs4", IPTOS_DSCP_CS4 }, 1010bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs5", IPTOS_DSCP_CS5 }, 1011bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs6", IPTOS_DSCP_CS6 }, 1012bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs7", IPTOS_DSCP_CS7 }, 1013bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "ef", IPTOS_DSCP_EF }, 1014bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "lowdelay", IPTOS_LOWDELAY }, 1015bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "throughput", IPTOS_THROUGHPUT }, 1016bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "reliability", IPTOS_RELIABILITY }, 1017bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { NULL, -1 } 1018bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}; 1019bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1020bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 1021bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanparse_ipqos(const char *cp) 1022bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1023bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int i; 1024bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *ep; 1025bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman long val; 1026bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1027bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cp == NULL) 1028bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 1029bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; ipqos[i].name != NULL; i++) { 1030bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strcasecmp(cp, ipqos[i].name) == 0) 1031bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return ipqos[i].value; 1032bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1033bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Try parsing as an integer */ 1034bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman val = strtol(cp, &ep, 0); 1035bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255) 1036bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 1037bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return val; 1038bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1039bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1040bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanconst char * 1041bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmaniptos2str(int iptos) 1042bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1043bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int i; 1044bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static char iptos_str[sizeof "0xff"]; 1045bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1046bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; ipqos[i].name != NULL; i++) { 1047bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ipqos[i].value == iptos) 1048bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return ipqos[i].name; 1049bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1050bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); 1051bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return iptos_str; 1052bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1053d059297112922cabb0c674840589be8db821fd9aAdam Langley 1054d059297112922cabb0c674840589be8db821fd9aAdam Langleyvoid 1055d059297112922cabb0c674840589be8db821fd9aAdam Langleylowercase(char *s) 1056d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 1057d059297112922cabb0c674840589be8db821fd9aAdam Langley for (; *s; s++) 1058d059297112922cabb0c674840589be8db821fd9aAdam Langley *s = tolower((u_char)*s); 1059d059297112922cabb0c674840589be8db821fd9aAdam Langley} 1060d059297112922cabb0c674840589be8db821fd9aAdam Langley 1061d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 1062d059297112922cabb0c674840589be8db821fd9aAdam Langleyunix_listener(const char *path, int backlog, int unlink_first) 1063d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 1064d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sockaddr_un sunaddr; 1065d059297112922cabb0c674840589be8db821fd9aAdam Langley int saved_errno, sock; 1066d059297112922cabb0c674840589be8db821fd9aAdam Langley 1067d059297112922cabb0c674840589be8db821fd9aAdam Langley memset(&sunaddr, 0, sizeof(sunaddr)); 1068d059297112922cabb0c674840589be8db821fd9aAdam Langley sunaddr.sun_family = AF_UNIX; 1069d059297112922cabb0c674840589be8db821fd9aAdam Langley if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { 1070d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: \"%s\" too long for Unix domain socket", __func__, 1071d059297112922cabb0c674840589be8db821fd9aAdam Langley path); 1072d059297112922cabb0c674840589be8db821fd9aAdam Langley errno = ENAMETOOLONG; 1073d059297112922cabb0c674840589be8db821fd9aAdam Langley return -1; 1074d059297112922cabb0c674840589be8db821fd9aAdam Langley } 1075d059297112922cabb0c674840589be8db821fd9aAdam Langley 1076d059297112922cabb0c674840589be8db821fd9aAdam Langley sock = socket(PF_UNIX, SOCK_STREAM, 0); 1077d059297112922cabb0c674840589be8db821fd9aAdam Langley if (sock < 0) { 1078d059297112922cabb0c674840589be8db821fd9aAdam Langley saved_errno = errno; 1079d059297112922cabb0c674840589be8db821fd9aAdam Langley error("socket: %.100s", strerror(errno)); 1080d059297112922cabb0c674840589be8db821fd9aAdam Langley errno = saved_errno; 1081d059297112922cabb0c674840589be8db821fd9aAdam Langley return -1; 1082d059297112922cabb0c674840589be8db821fd9aAdam Langley } 1083d059297112922cabb0c674840589be8db821fd9aAdam Langley if (unlink_first == 1) { 1084d059297112922cabb0c674840589be8db821fd9aAdam Langley if (unlink(path) != 0 && errno != ENOENT) 1085d059297112922cabb0c674840589be8db821fd9aAdam Langley error("unlink(%s): %.100s", path, strerror(errno)); 1086d059297112922cabb0c674840589be8db821fd9aAdam Langley } 1087d059297112922cabb0c674840589be8db821fd9aAdam Langley if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { 1088d059297112922cabb0c674840589be8db821fd9aAdam Langley saved_errno = errno; 1089d059297112922cabb0c674840589be8db821fd9aAdam Langley error("bind: %.100s", strerror(errno)); 1090d059297112922cabb0c674840589be8db821fd9aAdam Langley close(sock); 1091d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: cannot bind to path: %s", __func__, path); 1092d059297112922cabb0c674840589be8db821fd9aAdam Langley errno = saved_errno; 1093d059297112922cabb0c674840589be8db821fd9aAdam Langley return -1; 1094d059297112922cabb0c674840589be8db821fd9aAdam Langley } 1095d059297112922cabb0c674840589be8db821fd9aAdam Langley if (listen(sock, backlog) < 0) { 1096d059297112922cabb0c674840589be8db821fd9aAdam Langley saved_errno = errno; 1097d059297112922cabb0c674840589be8db821fd9aAdam Langley error("listen: %.100s", strerror(errno)); 1098d059297112922cabb0c674840589be8db821fd9aAdam Langley close(sock); 1099d059297112922cabb0c674840589be8db821fd9aAdam Langley unlink(path); 1100d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: cannot listen on path: %s", __func__, path); 1101d059297112922cabb0c674840589be8db821fd9aAdam Langley errno = saved_errno; 1102d059297112922cabb0c674840589be8db821fd9aAdam Langley return -1; 1103d059297112922cabb0c674840589be8db821fd9aAdam Langley } 1104d059297112922cabb0c674840589be8db821fd9aAdam Langley return sock; 1105d059297112922cabb0c674840589be8db821fd9aAdam Langley} 1106d059297112922cabb0c674840589be8db821fd9aAdam Langley 1107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 1108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansock_set_v6only(int s) 1109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef IPV6_V6ONLY 1111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int on = 1; 1112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); 1114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) 1115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); 1116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 1117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1118