19768ca48f57aaf035f508a473421d210b5145e99Greg Hartman/* $OpenBSD: misc.c,v 1.109 2017/03/14 00:55:37 dtucker 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> 329768ca48f57aaf035f508a473421d210b5145e99Greg Hartman#include <sys/time.h> 33d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <sys/un.h> 34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 35d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <limits.h> 36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h> 37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdio.h> 38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdlib.h> 39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h> 40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <time.h> 41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <unistd.h> 42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 43bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netinet/in.h> 44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netinet/in_systm.h> 45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netinet/ip.h> 46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netinet/tcp.h> 47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 48d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <ctype.h> 49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <errno.h> 50bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <fcntl.h> 51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netdb.h> 52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_PATHS_H 53bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# include <paths.h> 54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <pwd.h> 55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef SSH_TUN_OPENBSD 57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <net/if.h> 58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 60bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "xmalloc.h" 61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "misc.h" 62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "log.h" 63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "ssh.h" 64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 65bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* remove newline at end of string */ 66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchop(char *s) 68bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *t = s; 70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (*t) { 71bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*t == '\n' || *t == '\r') { 72bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *t = '\0'; 73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return s; 74bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman t++; 76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 77bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return s; 78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 81bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* set/unset filedescriptor to non-blocking */ 82bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanset_nonblock(int fd) 84bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 85bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int val; 86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 879768ca48f57aaf035f508a473421d210b5145e99Greg Hartman val = fcntl(fd, F_GETFL); 88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (val < 0) { 899768ca48f57aaf035f508a473421d210b5145e99Greg Hartman error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); 90bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 92bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (val & O_NONBLOCK) { 93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug3("fd %d is O_NONBLOCK", fd); 94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 96bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug2("fd %d setting O_NONBLOCK", fd); 97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman val |= O_NONBLOCK; 98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fcntl(fd, F_SETFL, val) == -1) { 99bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd, 100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strerror(errno)); 101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanunset_nonblock(int fd) 108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int val; 110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1119768ca48f57aaf035f508a473421d210b5145e99Greg Hartman val = fcntl(fd, F_GETFL); 112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (val < 0) { 1139768ca48f57aaf035f508a473421d210b5145e99Greg Hartman error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); 114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!(val & O_NONBLOCK)) { 117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug3("fd %d is not O_NONBLOCK", fd); 118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("fd %d clearing O_NONBLOCK", fd); 121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman val &= ~O_NONBLOCK; 122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fcntl(fd, F_SETFL, val) == -1) { 123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s", 124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fd, strerror(errno)); 125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanconst char * 131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanssh_gai_strerror(int gaierr) 132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 133d059297112922cabb0c674840589be8db821fd9aAdam Langley if (gaierr == EAI_SYSTEM && errno != 0) 134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return strerror(errno); 135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return gai_strerror(gaierr); 136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* disable nagle on socket */ 139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanset_nodelay(int fd) 141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int opt; 143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman socklen_t optlen; 144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman optlen = sizeof opt; 146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { 147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("getsockopt TCP_NODELAY: %.100s", strerror(errno)); 148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (opt == 1) { 151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug2("fd %d is TCP_NODELAY", fd); 152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman opt = 1; 155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug2("fd %d setting TCP_NODELAY", fd); 156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) 157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); 158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Characters considered whitespace in strsep calls. */ 161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define WHITESPACE " \t\r\n" 162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define QUOTE "\"" 163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* return next token in configuration line */ 165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstrdelim(char **s) 167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *old; 169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int wspace = 0; 170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s == NULL) 172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman old = *s; 175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s = strpbrk(*s, WHITESPACE QUOTE "="); 177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s == NULL) 178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (old); 179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s[0] == '\"') { 181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memmove(*s, *s + 1, strlen(*s)); /* move nul too */ 182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Find matching quote */ 183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((*s = strpbrk(*s, QUOTE)) == NULL) { 184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (NULL); /* no matching quote */ 185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s[0] = '\0'; 187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s += strspn(*s + 1, WHITESPACE) + 1; 188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (old); 189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Allow only one '=' to be skipped */ 193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s[0] == '=') 194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wspace = 1; 195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s[0] = '\0'; 196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Skip any extra whitespace after first token */ 198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s += strspn(*s + 1, WHITESPACE) + 1; 199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s[0] == '=' && !wspace) 200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s += strspn(*s + 1, WHITESPACE) + 1; 201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (old); 203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstruct passwd * 206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanpwcopy(struct passwd *pw) 207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct passwd *copy = xcalloc(1, sizeof(*copy)); 209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_name = xstrdup(pw->pw_name); 2119768ca48f57aaf035f508a473421d210b5145e99Greg Hartman copy->pw_passwd = xstrdup(pw->pw_passwd); 212d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef HAVE_STRUCT_PASSWD_PW_GECOS 213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_gecos = xstrdup(pw->pw_gecos); 214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_uid = pw->pw_uid; 216bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_gid = pw->pw_gid; 217d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE 218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_expire = pw->pw_expire; 219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 220d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE 221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_change = pw->pw_change; 222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 223d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef HAVE_STRUCT_PASSWD_PW_CLASS 224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_class = xstrdup(pw->pw_class); 225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_dir = xstrdup(pw->pw_dir); 227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman copy->pw_shell = xstrdup(pw->pw_shell); 228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return copy; 229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Convert ASCII string to TCP/IP port number. 233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Port must be >=0 and <=65535. 234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Return -1 if invalid. 235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmana2port(const char *s) 238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman long long port; 240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *errstr; 241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 242bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman port = strtonum(s, 0, 65535, &errstr); 243bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errstr != NULL) 244bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 245bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (int)port; 246bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 247bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 248bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 249bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmana2tun(const char *s, int *remote) 250bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *errstr = NULL; 252bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *sp, *ep; 253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int tun; 254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (remote != NULL) { 256bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *remote = SSH_TUNID_ANY; 257bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sp = xstrdup(s); 258bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((ep = strchr(sp, ':')) == NULL) { 259d059297112922cabb0c674840589be8db821fd9aAdam Langley free(sp); 260bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (a2tun(s, NULL)); 261bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 262bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ep[0] = '\0'; ep++; 263bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *remote = a2tun(ep, NULL); 264bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tun = a2tun(sp, NULL); 265d059297112922cabb0c674840589be8db821fd9aAdam Langley free(sp); 266bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (*remote == SSH_TUNID_ERR ? *remote : tun); 267bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 268bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 269bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strcasecmp(s, "any") == 0) 270bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (SSH_TUNID_ANY); 271bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 272bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); 273bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errstr != NULL) 274bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (SSH_TUNID_ERR); 275bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 276bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (tun); 277bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define SECONDS 1 280bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define MINUTES (SECONDS * 60) 281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define HOURS (MINUTES * 60) 282bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define DAYS (HOURS * 24) 283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define WEEKS (DAYS * 7) 284bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 285bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 286bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Convert a time string into seconds; format is 287bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * a sequence of: 288bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * time[qualifier] 289bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 290bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Valid time qualifiers are: 291bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * <none> seconds 292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * s|S seconds 293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * m|M minutes 294bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * h|H hours 295bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * d|D days 296bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * w|W weeks 297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Examples: 299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 90m 90 minutes 300bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1h30m 90 minutes 301bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2d 2 days 302bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1w 1 week 303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 304bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Return -1 if time string is invalid. 305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 306bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanlong 307bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanconvtime(const char *s) 308bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 3099768ca48f57aaf035f508a473421d210b5145e99Greg Hartman long total, secs, multiplier = 1; 310bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *p; 311bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *endp; 312bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 313bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno = 0; 314bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman total = 0; 315bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p = s; 316bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 317bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (p == NULL || *p == '\0') 318bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 319bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 320bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (*p) { 321bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman secs = strtol(p, &endp, 10); 322bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (p == endp || 323bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || 324bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman secs < 0) 325bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 326bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 327bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (*endp++) { 328bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '\0': 329bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman endp--; 330bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 's': 332bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'S': 333bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'm': 335bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'M': 3369768ca48f57aaf035f508a473421d210b5145e99Greg Hartman multiplier = MINUTES; 337bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 338bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'h': 339bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'H': 3409768ca48f57aaf035f508a473421d210b5145e99Greg Hartman multiplier = HOURS; 341bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 342bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'd': 343bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'D': 3449768ca48f57aaf035f508a473421d210b5145e99Greg Hartman multiplier = DAYS; 345bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 346bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'w': 347bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'W': 3489768ca48f57aaf035f508a473421d210b5145e99Greg Hartman multiplier = WEEKS; 349bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 350bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 351bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 352bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 3539768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (secs >= LONG_MAX / multiplier) 3549768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return -1; 3559768ca48f57aaf035f508a473421d210b5145e99Greg Hartman secs *= multiplier; 3569768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (total >= LONG_MAX - secs) 3579768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return -1; 358bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman total += secs; 359bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (total < 0) 360bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 361bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p = endp; 362bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 363bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 364bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return total; 365bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 366bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 367bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 368bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Returns a standardized host+port identifier string. 369bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Caller must free returned string. 370bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 371bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 372bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanput_host_port(const char *host, u_short port) 373bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 374bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *hoststr; 375bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 376bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (port == 0 || port == SSH_DEFAULT_PORT) 377bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return(xstrdup(host)); 378bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0) 379bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("put_host_port: asprintf: %s", strerror(errno)); 380bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug3("put_host_port: %s", hoststr); 381bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return hoststr; 382bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 383bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 384bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 385bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Search for next delimiter between hostnames/addresses and ports. 386bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Argument may be modified (for termination). 387bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Returns *cp if parsing succeeds. 388bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * *cp is set to the start of the next delimiter, if one was found. 389bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * If this is the last field, *cp is set to NULL. 390bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 391bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 392bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanhpdelim(char **cp) 393bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 394bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *s, *old; 395bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 396bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cp == NULL || *cp == NULL) 397bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 398bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 399bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman old = s = *cp; 400bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*s == '[') { 401bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((s = strchr(s, ']')) == NULL) 402bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 403bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 404bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman s++; 405bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if ((s = strpbrk(s, ":/")) == NULL) 406bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman s = *cp + strlen(*cp); /* skip to end (see first case below) */ 407bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 408bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (*s) { 409bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '\0': 410bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *cp = NULL; /* no more fields*/ 411bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 412bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 413bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case ':': 414bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '/': 415bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *s = '\0'; /* terminate */ 416bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *cp = s + 1; 417bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 418bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 419bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 420bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 421bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 422bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 423bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return old; 424bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 425bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 426bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 427bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancleanhostname(char *host) 428bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 429bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*host == '[' && host[strlen(host) - 1] == ']') { 430bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host[strlen(host) - 1] = '\0'; 431bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (host + 1); 432bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else 433bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return host; 434bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 435bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 436bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 437bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancolon(char *cp) 438bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 439bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int flag = 0; 440bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 441bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == ':') /* Leading colon is part of file name. */ 442bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 443bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == '[') 444bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman flag = 1; 445bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 446bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (; *cp; ++cp) { 447bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == '@' && *(cp+1) == '[') 448bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman flag = 1; 449bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == ']' && *(cp+1) == ':' && flag) 450bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (cp+1); 451bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == ':' && !flag) 452bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (cp); 453bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == '/') 454bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 455bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 456bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 457bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 458bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 4599768ca48f57aaf035f508a473421d210b5145e99Greg Hartman/* 4609768ca48f57aaf035f508a473421d210b5145e99Greg Hartman * Parse a [user@]host[:port] string. 4619768ca48f57aaf035f508a473421d210b5145e99Greg Hartman * Caller must free returned user and host. 4629768ca48f57aaf035f508a473421d210b5145e99Greg Hartman * Any of the pointer return arguments may be NULL (useful for syntax checking). 4639768ca48f57aaf035f508a473421d210b5145e99Greg Hartman * If user was not specified then *userp will be set to NULL. 4649768ca48f57aaf035f508a473421d210b5145e99Greg Hartman * If port was not specified then *portp will be -1. 4659768ca48f57aaf035f508a473421d210b5145e99Greg Hartman * Returns 0 on success, -1 on failure. 4669768ca48f57aaf035f508a473421d210b5145e99Greg Hartman */ 4679768ca48f57aaf035f508a473421d210b5145e99Greg Hartmanint 4689768ca48f57aaf035f508a473421d210b5145e99Greg Hartmanparse_user_host_port(const char *s, char **userp, char **hostp, int *portp) 4699768ca48f57aaf035f508a473421d210b5145e99Greg Hartman{ 4709768ca48f57aaf035f508a473421d210b5145e99Greg Hartman char *sdup, *cp, *tmp; 4719768ca48f57aaf035f508a473421d210b5145e99Greg Hartman char *user = NULL, *host = NULL; 4729768ca48f57aaf035f508a473421d210b5145e99Greg Hartman int port = -1, ret = -1; 4739768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 4749768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (userp != NULL) 4759768ca48f57aaf035f508a473421d210b5145e99Greg Hartman *userp = NULL; 4769768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (hostp != NULL) 4779768ca48f57aaf035f508a473421d210b5145e99Greg Hartman *hostp = NULL; 4789768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (portp != NULL) 4799768ca48f57aaf035f508a473421d210b5145e99Greg Hartman *portp = -1; 4809768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 4819768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if ((sdup = tmp = strdup(s)) == NULL) 4829768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return -1; 4839768ca48f57aaf035f508a473421d210b5145e99Greg Hartman /* Extract optional username */ 4849768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if ((cp = strchr(tmp, '@')) != NULL) { 4859768ca48f57aaf035f508a473421d210b5145e99Greg Hartman *cp = '\0'; 4869768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (*tmp == '\0') 4879768ca48f57aaf035f508a473421d210b5145e99Greg Hartman goto out; 4889768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if ((user = strdup(tmp)) == NULL) 4899768ca48f57aaf035f508a473421d210b5145e99Greg Hartman goto out; 4909768ca48f57aaf035f508a473421d210b5145e99Greg Hartman tmp = cp + 1; 4919768ca48f57aaf035f508a473421d210b5145e99Greg Hartman } 4929768ca48f57aaf035f508a473421d210b5145e99Greg Hartman /* Extract mandatory hostname */ 4939768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if ((cp = hpdelim(&tmp)) == NULL || *cp == '\0') 4949768ca48f57aaf035f508a473421d210b5145e99Greg Hartman goto out; 4959768ca48f57aaf035f508a473421d210b5145e99Greg Hartman host = xstrdup(cleanhostname(cp)); 4969768ca48f57aaf035f508a473421d210b5145e99Greg Hartman /* Convert and verify optional port */ 4979768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (tmp != NULL && *tmp != '\0') { 4989768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if ((port = a2port(tmp)) <= 0) 4999768ca48f57aaf035f508a473421d210b5145e99Greg Hartman goto out; 5009768ca48f57aaf035f508a473421d210b5145e99Greg Hartman } 5019768ca48f57aaf035f508a473421d210b5145e99Greg Hartman /* Success */ 5029768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (userp != NULL) { 5039768ca48f57aaf035f508a473421d210b5145e99Greg Hartman *userp = user; 5049768ca48f57aaf035f508a473421d210b5145e99Greg Hartman user = NULL; 5059768ca48f57aaf035f508a473421d210b5145e99Greg Hartman } 5069768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (hostp != NULL) { 5079768ca48f57aaf035f508a473421d210b5145e99Greg Hartman *hostp = host; 5089768ca48f57aaf035f508a473421d210b5145e99Greg Hartman host = NULL; 5099768ca48f57aaf035f508a473421d210b5145e99Greg Hartman } 5109768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (portp != NULL) 5119768ca48f57aaf035f508a473421d210b5145e99Greg Hartman *portp = port; 5129768ca48f57aaf035f508a473421d210b5145e99Greg Hartman ret = 0; 5139768ca48f57aaf035f508a473421d210b5145e99Greg Hartman out: 5149768ca48f57aaf035f508a473421d210b5145e99Greg Hartman free(sdup); 5159768ca48f57aaf035f508a473421d210b5145e99Greg Hartman free(user); 5169768ca48f57aaf035f508a473421d210b5145e99Greg Hartman free(host); 5179768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return ret; 5189768ca48f57aaf035f508a473421d210b5145e99Greg Hartman} 5199768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 520bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* function to assist building execv() arguments */ 521bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 522bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanaddargs(arglist *args, char *fmt, ...) 523bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 524bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_list ap; 525bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *cp; 526bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int nalloc; 527bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int r; 528bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 529bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_start(ap, fmt); 530bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman r = vasprintf(&cp, fmt, ap); 531bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_end(ap); 532bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (r == -1) 533bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("addargs: argument too long"); 534bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 535bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nalloc = args->nalloc; 536bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (args->list == NULL) { 537bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nalloc = 32; 538bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->num = 0; 539bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (args->num+2 >= nalloc) 540bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nalloc *= 2; 541bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 542ccacbc9b0331c30b8be12e8e0349e983abf28fc0Greg Hartman args->list = xreallocarray(args->list, nalloc, sizeof(char *)); 543bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->nalloc = nalloc; 544bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->list[args->num++] = cp; 545bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->list[args->num] = NULL; 546bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 547bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 548bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 549bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanreplacearg(arglist *args, u_int which, char *fmt, ...) 550bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 551bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_list ap; 552bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *cp; 553bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int r; 554bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 555bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_start(ap, fmt); 556bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman r = vasprintf(&cp, fmt, ap); 557bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_end(ap); 558bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (r == -1) 559bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("replacearg: argument too long"); 560bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 561bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (which >= args->num) 562bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("replacearg: tried to replace invalid arg %d >= %d", 563bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman which, args->num); 564d059297112922cabb0c674840589be8db821fd9aAdam Langley free(args->list[which]); 565bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->list[which] = cp; 566bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 567bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 568bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 569bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanfreeargs(arglist *args) 570bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 571bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int i; 572bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 573bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (args->list != NULL) { 574bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < args->num; i++) 575d059297112922cabb0c674840589be8db821fd9aAdam Langley free(args->list[i]); 576d059297112922cabb0c674840589be8db821fd9aAdam Langley free(args->list); 577bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->nalloc = args->num = 0; 578bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args->list = NULL; 579bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 580bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 581bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 582bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 583bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Expands tildes in the file name. Returns data allocated by xmalloc. 584bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Warning: this calls getpw*. 585bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 586bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 587bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantilde_expand_filename(const char *filename, uid_t uid) 588bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 589d059297112922cabb0c674840589be8db821fd9aAdam Langley const char *path, *sep; 590d059297112922cabb0c674840589be8db821fd9aAdam Langley char user[128], *ret; 591bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct passwd *pw; 592bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int len, slash; 593bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 594bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*filename != '~') 595bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (xstrdup(filename)); 596bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman filename++; 597bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 598bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman path = strchr(filename, '/'); 599bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (path != NULL && path > filename) { /* ~user/path */ 600bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman slash = path - filename; 601bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (slash > sizeof(user) - 1) 602bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("tilde_expand_filename: ~username too long"); 603bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memcpy(user, filename, slash); 604bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman user[slash] = '\0'; 605bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((pw = getpwnam(user)) == NULL) 606bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("tilde_expand_filename: No such user %s", user); 607bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if ((pw = getpwuid(uid)) == NULL) /* ~/path */ 608bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("tilde_expand_filename: No such uid %ld", (long)uid); 609bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 610bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Make sure directory has a trailing '/' */ 611bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman len = strlen(pw->pw_dir); 612d059297112922cabb0c674840589be8db821fd9aAdam Langley if (len == 0 || pw->pw_dir[len - 1] != '/') 613d059297112922cabb0c674840589be8db821fd9aAdam Langley sep = "/"; 614d059297112922cabb0c674840589be8db821fd9aAdam Langley else 615d059297112922cabb0c674840589be8db821fd9aAdam Langley sep = ""; 616bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 617bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Skip leading '/' from specified path */ 618bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (path != NULL) 619bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman filename = path + 1; 620d059297112922cabb0c674840589be8db821fd9aAdam Langley 621d059297112922cabb0c674840589be8db821fd9aAdam Langley if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX) 622bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("tilde_expand_filename: Path too long"); 623bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 624d059297112922cabb0c674840589be8db821fd9aAdam Langley return (ret); 625bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 626bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 627bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 628bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Expand a string with a set of %[char] escapes. A number of escapes may be 629bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * specified as (char *escape_chars, char *replacement) pairs. The list must 630bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * be terminated by a NULL escape_char. Returns replaced string in memory 631bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * allocated by xmalloc. 632bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 633bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 634bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanpercent_expand(const char *string, ...) 635bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 636bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define EXPAND_MAX_KEYS 16 637bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int num_keys, i, j; 638bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct { 639bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *key; 640bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *repl; 641bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } keys[EXPAND_MAX_KEYS]; 642bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char buf[4096]; 643bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_list ap; 644bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 645bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Gather keys */ 646bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_start(ap, string); 647bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) { 648bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman keys[num_keys].key = va_arg(ap, char *); 649bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (keys[num_keys].key == NULL) 650bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 651bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman keys[num_keys].repl = va_arg(ap, char *); 652bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (keys[num_keys].repl == NULL) 653bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: NULL replacement", __func__); 654bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 655bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) 656bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: too many keys", __func__); 657bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_end(ap); 658bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 659bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Expand string */ 660bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *buf = '\0'; 661bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; *string != '\0'; string++) { 662bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*string != '%') { 663bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman append: 664bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buf[i++] = *string; 665bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (i >= sizeof(buf)) 666bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: string too long", __func__); 667bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buf[i] = '\0'; 668bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 669bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 670bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman string++; 671bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* %% case */ 672bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*string == '%') 673bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto append; 6749768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (*string == '\0') 6759768ca48f57aaf035f508a473421d210b5145e99Greg Hartman fatal("%s: invalid format", __func__); 676bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (j = 0; j < num_keys; j++) { 677bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strchr(keys[j].key, *string) != NULL) { 678bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman i = strlcat(buf, keys[j].repl, sizeof(buf)); 679bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (i >= sizeof(buf)) 680bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: string too long", __func__); 681bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 682bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 683bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 684bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (j >= num_keys) 685bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: unknown key %%%c", __func__, *string); 686bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 687bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (xstrdup(buf)); 688bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#undef EXPAND_MAX_KEYS 689bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 690bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 691bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 692bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Read an entire line from a public key file into a static buffer, discarding 693bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * lines that exceed the buffer size. Returns 0 on success, -1 on failure. 694bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 695bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 696bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanread_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, 697bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_long *lineno) 698bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 699bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (fgets(buf, bufsz, f) != NULL) { 700bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf[0] == '\0') 701bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 702bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (*lineno)++; 703bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf[strlen(buf) - 1] == '\n' || feof(f)) { 704bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 705bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 706bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("%s: %s line %lu exceeds size limit", __func__, 707bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman filename, *lineno); 708bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* discard remainder of line */ 709bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (fgetc(f) != '\n' && !feof(f)) 710bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ; /* nothing */ 711bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 712bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 713bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 714bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 715bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 716bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 717bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantun_open(int tun, int mode) 718bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 719bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#if defined(CUSTOM_SYS_TUN_OPEN) 720bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (sys_tun_open(tun, mode)); 721bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#elif defined(SSH_TUN_OPENBSD) 722bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct ifreq ifr; 723bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char name[100]; 724bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int fd = -1, sock; 7259768ca48f57aaf035f508a473421d210b5145e99Greg Hartman const char *tunbase = "tun"; 7269768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 7279768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (mode == SSH_TUNMODE_ETHERNET) 7289768ca48f57aaf035f508a473421d210b5145e99Greg Hartman tunbase = "tap"; 729bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 730bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Open the tunnel device */ 731bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (tun <= SSH_TUNID_MAX) { 7329768ca48f57aaf035f508a473421d210b5145e99Greg Hartman snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); 733bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fd = open(name, O_RDWR); 734bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (tun == SSH_TUNID_ANY) { 735bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (tun = 100; tun >= 0; tun--) { 7369768ca48f57aaf035f508a473421d210b5145e99Greg Hartman snprintf(name, sizeof(name), "/dev/%s%d", 7379768ca48f57aaf035f508a473421d210b5145e99Greg Hartman tunbase, tun); 738bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((fd = open(name, O_RDWR)) >= 0) 739bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 740bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 741bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 742bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("%s: invalid tunnel %u", __func__, tun); 7439768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return -1; 744bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 745bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 746bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fd < 0) { 7479768ca48f57aaf035f508a473421d210b5145e99Greg Hartman debug("%s: %s open: %s", __func__, name, strerror(errno)); 7489768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return -1; 749bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 750bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 751bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("%s: %s mode %d fd %d", __func__, name, mode, fd); 752bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 7539768ca48f57aaf035f508a473421d210b5145e99Greg Hartman /* Bring interface up if it is not already */ 7549768ca48f57aaf035f508a473421d210b5145e99Greg Hartman snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); 755bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) 756bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto failed; 757bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 7589768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { 7599768ca48f57aaf035f508a473421d210b5145e99Greg Hartman debug("%s: get interface %s flags: %s", __func__, 7609768ca48f57aaf035f508a473421d210b5145e99Greg Hartman ifr.ifr_name, strerror(errno)); 761bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto failed; 7629768ca48f57aaf035f508a473421d210b5145e99Greg Hartman } 763bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 7649768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (!(ifr.ifr_flags & IFF_UP)) { 7659768ca48f57aaf035f508a473421d210b5145e99Greg Hartman ifr.ifr_flags |= IFF_UP; 7669768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { 7679768ca48f57aaf035f508a473421d210b5145e99Greg Hartman debug("%s: activate interface %s: %s", __func__, 7689768ca48f57aaf035f508a473421d210b5145e99Greg Hartman ifr.ifr_name, strerror(errno)); 7699768ca48f57aaf035f508a473421d210b5145e99Greg Hartman goto failed; 7709768ca48f57aaf035f508a473421d210b5145e99Greg Hartman } 7719768ca48f57aaf035f508a473421d210b5145e99Greg Hartman } 772bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 773bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(sock); 7749768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return fd; 775bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 776bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman failed: 777bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fd >= 0) 778bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(fd); 779bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (sock >= 0) 780bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(sock); 7819768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return -1; 782bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#else 783bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("Tunnel interfaces are not supported on this platform"); 784bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 785bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 786bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 787bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 788bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 789bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansanitise_stdfd(void) 790bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 791bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int nullfd, dupfd; 792bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 793bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 794bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "Couldn't open /dev/null: %s\n", 795bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strerror(errno)); 796bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 797bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 7989768ca48f57aaf035f508a473421d210b5145e99Greg Hartman while (++dupfd <= STDERR_FILENO) { 7999768ca48f57aaf035f508a473421d210b5145e99Greg Hartman /* Only populate closed fds. */ 8009768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (fcntl(dupfd, F_GETFL) == -1 && errno == EBADF) { 8019768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (dup2(nullfd, dupfd) == -1) { 8029768ca48f57aaf035f508a473421d210b5145e99Greg Hartman fprintf(stderr, "dup2: %s\n", strerror(errno)); 8039768ca48f57aaf035f508a473421d210b5145e99Greg Hartman exit(1); 8049768ca48f57aaf035f508a473421d210b5145e99Greg Hartman } 805bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 806bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 8079768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (nullfd > STDERR_FILENO) 808bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(nullfd); 809bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 810bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 811bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 812bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantohex(const void *vp, size_t l) 813bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 814bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const u_char *p = (const u_char *)vp; 815bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char b[3], *r; 816bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size_t i, hl; 817bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 818bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (l > 65536) 819bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return xstrdup("tohex: length > 65536"); 820bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 821bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman hl = l * 2 + 1; 822bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman r = xcalloc(1, hl); 823bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < l; i++) { 824bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(b, sizeof(b), "%02x", p[i]); 825bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strlcat(r, b, hl); 826bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 827bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (r); 828bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 829bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 830bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int64_t 831bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanget_u64(const void *vp) 832bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 833bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const u_char *p = (const u_char *)vp; 834bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int64_t v; 835bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 836bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v = (u_int64_t)p[0] << 56; 837bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[1] << 48; 838bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[2] << 40; 839bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[3] << 32; 840bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[4] << 24; 841bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[5] << 16; 842bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[6] << 8; 843bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int64_t)p[7]; 844bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 845bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (v); 846bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 847bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 848bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int32_t 849bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanget_u32(const void *vp) 850bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 851bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const u_char *p = (const u_char *)vp; 852bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int32_t v; 853bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 854bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v = (u_int32_t)p[0] << 24; 855bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int32_t)p[1] << 16; 856bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int32_t)p[2] << 8; 857bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int32_t)p[3]; 858bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 859bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (v); 860bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 861bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 862d059297112922cabb0c674840589be8db821fd9aAdam Langleyu_int32_t 863d059297112922cabb0c674840589be8db821fd9aAdam Langleyget_u32_le(const void *vp) 864d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 865d059297112922cabb0c674840589be8db821fd9aAdam Langley const u_char *p = (const u_char *)vp; 866d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int32_t v; 867d059297112922cabb0c674840589be8db821fd9aAdam Langley 868d059297112922cabb0c674840589be8db821fd9aAdam Langley v = (u_int32_t)p[0]; 869d059297112922cabb0c674840589be8db821fd9aAdam Langley v |= (u_int32_t)p[1] << 8; 870d059297112922cabb0c674840589be8db821fd9aAdam Langley v |= (u_int32_t)p[2] << 16; 871d059297112922cabb0c674840589be8db821fd9aAdam Langley v |= (u_int32_t)p[3] << 24; 872d059297112922cabb0c674840589be8db821fd9aAdam Langley 873d059297112922cabb0c674840589be8db821fd9aAdam Langley return (v); 874d059297112922cabb0c674840589be8db821fd9aAdam Langley} 875d059297112922cabb0c674840589be8db821fd9aAdam Langley 876bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int16_t 877bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanget_u16(const void *vp) 878bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 879bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const u_char *p = (const u_char *)vp; 880bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int16_t v; 881bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 882bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v = (u_int16_t)p[0] << 8; 883bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman v |= (u_int16_t)p[1]; 884bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 885bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (v); 886bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 887bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 888bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 889bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanput_u64(void *vp, u_int64_t v) 890bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 891bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *p = (u_char *)vp; 892bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 893bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[0] = (u_char)(v >> 56) & 0xff; 894bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[1] = (u_char)(v >> 48) & 0xff; 895bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[2] = (u_char)(v >> 40) & 0xff; 896bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[3] = (u_char)(v >> 32) & 0xff; 897bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[4] = (u_char)(v >> 24) & 0xff; 898bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[5] = (u_char)(v >> 16) & 0xff; 899bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[6] = (u_char)(v >> 8) & 0xff; 900bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[7] = (u_char)v & 0xff; 901bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 902bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 903bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 904bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanput_u32(void *vp, u_int32_t v) 905bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 906bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *p = (u_char *)vp; 907bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 908bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[0] = (u_char)(v >> 24) & 0xff; 909bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[1] = (u_char)(v >> 16) & 0xff; 910bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[2] = (u_char)(v >> 8) & 0xff; 911bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[3] = (u_char)v & 0xff; 912bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 913bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 914d059297112922cabb0c674840589be8db821fd9aAdam Langleyvoid 915d059297112922cabb0c674840589be8db821fd9aAdam Langleyput_u32_le(void *vp, u_int32_t v) 916d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 917d059297112922cabb0c674840589be8db821fd9aAdam Langley u_char *p = (u_char *)vp; 918d059297112922cabb0c674840589be8db821fd9aAdam Langley 919d059297112922cabb0c674840589be8db821fd9aAdam Langley p[0] = (u_char)v & 0xff; 920d059297112922cabb0c674840589be8db821fd9aAdam Langley p[1] = (u_char)(v >> 8) & 0xff; 921d059297112922cabb0c674840589be8db821fd9aAdam Langley p[2] = (u_char)(v >> 16) & 0xff; 922d059297112922cabb0c674840589be8db821fd9aAdam Langley p[3] = (u_char)(v >> 24) & 0xff; 923d059297112922cabb0c674840589be8db821fd9aAdam Langley} 924bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 925bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 926bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanput_u16(void *vp, u_int16_t v) 927bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 928bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *p = (u_char *)vp; 929bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 930bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[0] = (u_char)(v >> 8) & 0xff; 931bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p[1] = (u_char)v & 0xff; 932bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 933bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 934bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 935bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanms_subtract_diff(struct timeval *start, int *ms) 936bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 937bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct timeval diff, finish; 938bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 939bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman gettimeofday(&finish, NULL); 940bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman timersub(&finish, start, &diff); 941bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000); 942bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 943bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 944bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 945bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanms_to_timeval(struct timeval *tv, int ms) 946bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 947bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ms < 0) 948bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ms = 0; 949bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tv->tv_sec = ms / 1000; 950bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tv->tv_usec = (ms % 1000) * 1000; 951bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 952bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 953d059297112922cabb0c674840589be8db821fd9aAdam Langleytime_t 954d059297112922cabb0c674840589be8db821fd9aAdam Langleymonotime(void) 955d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 956d059297112922cabb0c674840589be8db821fd9aAdam Langley#if defined(HAVE_CLOCK_GETTIME) && \ 957d059297112922cabb0c674840589be8db821fd9aAdam Langley (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME)) 958d059297112922cabb0c674840589be8db821fd9aAdam Langley struct timespec ts; 959d059297112922cabb0c674840589be8db821fd9aAdam Langley static int gettime_failed = 0; 960d059297112922cabb0c674840589be8db821fd9aAdam Langley 961d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!gettime_failed) { 962d059297112922cabb0c674840589be8db821fd9aAdam Langley#if defined(CLOCK_BOOTTIME) 963d059297112922cabb0c674840589be8db821fd9aAdam Langley if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) 964d059297112922cabb0c674840589be8db821fd9aAdam Langley return (ts.tv_sec); 965d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 966d059297112922cabb0c674840589be8db821fd9aAdam Langley#if defined(CLOCK_MONOTONIC) 967d059297112922cabb0c674840589be8db821fd9aAdam Langley if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) 968d059297112922cabb0c674840589be8db821fd9aAdam Langley return (ts.tv_sec); 969d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 970d059297112922cabb0c674840589be8db821fd9aAdam Langley debug3("clock_gettime: %s", strerror(errno)); 971d059297112922cabb0c674840589be8db821fd9aAdam Langley gettime_failed = 1; 972d059297112922cabb0c674840589be8db821fd9aAdam Langley } 973d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */ 974d059297112922cabb0c674840589be8db821fd9aAdam Langley 975d059297112922cabb0c674840589be8db821fd9aAdam Langley return time(NULL); 976d059297112922cabb0c674840589be8db821fd9aAdam Langley} 977d059297112922cabb0c674840589be8db821fd9aAdam Langley 9789768ca48f57aaf035f508a473421d210b5145e99Greg Hartmandouble 9799768ca48f57aaf035f508a473421d210b5145e99Greg Hartmanmonotime_double(void) 9809768ca48f57aaf035f508a473421d210b5145e99Greg Hartman{ 9819768ca48f57aaf035f508a473421d210b5145e99Greg Hartman#if defined(HAVE_CLOCK_GETTIME) && \ 9829768ca48f57aaf035f508a473421d210b5145e99Greg Hartman (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME)) 9839768ca48f57aaf035f508a473421d210b5145e99Greg Hartman struct timespec ts; 9849768ca48f57aaf035f508a473421d210b5145e99Greg Hartman static int gettime_failed = 0; 9859768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 9869768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (!gettime_failed) { 9879768ca48f57aaf035f508a473421d210b5145e99Greg Hartman#if defined(CLOCK_BOOTTIME) 9889768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) 9899768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return (ts.tv_sec + (double)ts.tv_nsec / 1000000000); 9909768ca48f57aaf035f508a473421d210b5145e99Greg Hartman#endif 9919768ca48f57aaf035f508a473421d210b5145e99Greg Hartman#if defined(CLOCK_MONOTONIC) 9929768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) 9939768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return (ts.tv_sec + (double)ts.tv_nsec / 1000000000); 9949768ca48f57aaf035f508a473421d210b5145e99Greg Hartman#endif 9959768ca48f57aaf035f508a473421d210b5145e99Greg Hartman debug3("clock_gettime: %s", strerror(errno)); 9969768ca48f57aaf035f508a473421d210b5145e99Greg Hartman gettime_failed = 1; 9979768ca48f57aaf035f508a473421d210b5145e99Greg Hartman } 9989768ca48f57aaf035f508a473421d210b5145e99Greg Hartman#endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */ 9999768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 10009768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return (double)time(NULL); 10019768ca48f57aaf035f508a473421d210b5145e99Greg Hartman} 10029768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 1003bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 1004bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanbandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) 1005bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1006bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->buflen = buflen; 1007bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->rate = kbps; 1008bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->thresh = bw->rate; 1009bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->lamt = 0; 1010bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman timerclear(&bw->bwstart); 1011bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman timerclear(&bw->bwend); 1012bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1013bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1014bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Callback from read/write loop to insert bandwidth-limiting delays */ 1015bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 1016bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanbandwidth_limit(struct bwlimit *bw, size_t read_len) 1017bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1018bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int64_t waitlen; 1019bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct timespec ts, rm; 1020bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1021bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!timerisset(&bw->bwstart)) { 1022bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman gettimeofday(&bw->bwstart, NULL); 1023bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 1024bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1025bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1026bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->lamt += read_len; 1027bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bw->lamt < bw->thresh) 1028bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 1029bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1030bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman gettimeofday(&bw->bwend, NULL); 1031bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman timersub(&bw->bwend, &bw->bwstart, &bw->bwend); 1032bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!timerisset(&bw->bwend)) 1033bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 1034bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1035bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->lamt *= 8; 1036bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman waitlen = (double)1000000L * bw->lamt / bw->rate; 1037bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1038bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->bwstart.tv_sec = waitlen / 1000000L; 1039bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->bwstart.tv_usec = waitlen % 1000000L; 1040bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1041bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (timercmp(&bw->bwstart, &bw->bwend, >)) { 1042bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman timersub(&bw->bwstart, &bw->bwend, &bw->bwend); 1043bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1044bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Adjust the wait time */ 1045bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bw->bwend.tv_sec) { 1046bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->thresh /= 2; 1047bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bw->thresh < bw->buflen / 4) 1048bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->thresh = bw->buflen / 4; 1049bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (bw->bwend.tv_usec < 10000) { 1050bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->thresh *= 2; 1051bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bw->thresh > bw->buflen * 8) 1052bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->thresh = bw->buflen * 8; 1053bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1054bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1055bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts); 1056bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (nanosleep(&ts, &rm) == -1) { 1057bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errno != EINTR) 1058bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1059bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ts = rm; 1060bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1061bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1062bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1063bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bw->lamt = 0; 1064bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman gettimeofday(&bw->bwstart, NULL); 1065bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1066bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1067bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Make a template filename for mk[sd]temp() */ 1068bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 1069bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanmktemp_proto(char *s, size_t len) 1070bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1071bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *tmpdir; 1072bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int r; 1073bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1074bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((tmpdir = getenv("TMPDIR")) != NULL) { 1075bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); 1076bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (r > 0 && (size_t)r < len) 1077bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 1078bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1079bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); 1080bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (r < 0 || (size_t)r >= len) 1081bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("%s: template string too short", __func__); 1082bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1083bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1084bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic const struct { 1085bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *name; 1086bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int value; 1087bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} ipqos[] = { 1088bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af11", IPTOS_DSCP_AF11 }, 1089bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af12", IPTOS_DSCP_AF12 }, 1090bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af13", IPTOS_DSCP_AF13 }, 1091d059297112922cabb0c674840589be8db821fd9aAdam Langley { "af21", IPTOS_DSCP_AF21 }, 1092bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af22", IPTOS_DSCP_AF22 }, 1093bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af23", IPTOS_DSCP_AF23 }, 1094bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af31", IPTOS_DSCP_AF31 }, 1095bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af32", IPTOS_DSCP_AF32 }, 1096bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af33", IPTOS_DSCP_AF33 }, 1097bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af41", IPTOS_DSCP_AF41 }, 1098bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af42", IPTOS_DSCP_AF42 }, 1099bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "af43", IPTOS_DSCP_AF43 }, 1100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs0", IPTOS_DSCP_CS0 }, 1101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs1", IPTOS_DSCP_CS1 }, 1102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs2", IPTOS_DSCP_CS2 }, 1103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs3", IPTOS_DSCP_CS3 }, 1104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs4", IPTOS_DSCP_CS4 }, 1105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs5", IPTOS_DSCP_CS5 }, 1106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs6", IPTOS_DSCP_CS6 }, 1107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "cs7", IPTOS_DSCP_CS7 }, 1108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "ef", IPTOS_DSCP_EF }, 1109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "lowdelay", IPTOS_LOWDELAY }, 1110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "throughput", IPTOS_THROUGHPUT }, 1111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "reliability", IPTOS_RELIABILITY }, 1112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { NULL, -1 } 1113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}; 1114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 1116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanparse_ipqos(const char *cp) 1117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int i; 1119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *ep; 1120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman long val; 1121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cp == NULL) 1123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 1124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; ipqos[i].name != NULL; i++) { 1125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strcasecmp(cp, ipqos[i].name) == 0) 1126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return ipqos[i].value; 1127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Try parsing as an integer */ 1129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman val = strtol(cp, &ep, 0); 1130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255) 1131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 1132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return val; 1133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanconst char * 1136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmaniptos2str(int iptos) 1137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int i; 1139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static char iptos_str[sizeof "0xff"]; 1140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; ipqos[i].name != NULL; i++) { 1142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ipqos[i].value == iptos) 1143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return ipqos[i].name; 1144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); 1146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return iptos_str; 1147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1148d059297112922cabb0c674840589be8db821fd9aAdam Langley 1149d059297112922cabb0c674840589be8db821fd9aAdam Langleyvoid 1150d059297112922cabb0c674840589be8db821fd9aAdam Langleylowercase(char *s) 1151d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 1152d059297112922cabb0c674840589be8db821fd9aAdam Langley for (; *s; s++) 1153d059297112922cabb0c674840589be8db821fd9aAdam Langley *s = tolower((u_char)*s); 1154d059297112922cabb0c674840589be8db821fd9aAdam Langley} 1155d059297112922cabb0c674840589be8db821fd9aAdam Langley 1156d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 1157d059297112922cabb0c674840589be8db821fd9aAdam Langleyunix_listener(const char *path, int backlog, int unlink_first) 1158d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 1159d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sockaddr_un sunaddr; 1160d059297112922cabb0c674840589be8db821fd9aAdam Langley int saved_errno, sock; 1161d059297112922cabb0c674840589be8db821fd9aAdam Langley 1162d059297112922cabb0c674840589be8db821fd9aAdam Langley memset(&sunaddr, 0, sizeof(sunaddr)); 1163d059297112922cabb0c674840589be8db821fd9aAdam Langley sunaddr.sun_family = AF_UNIX; 1164d059297112922cabb0c674840589be8db821fd9aAdam Langley if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { 1165d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: \"%s\" too long for Unix domain socket", __func__, 1166d059297112922cabb0c674840589be8db821fd9aAdam Langley path); 1167d059297112922cabb0c674840589be8db821fd9aAdam Langley errno = ENAMETOOLONG; 1168d059297112922cabb0c674840589be8db821fd9aAdam Langley return -1; 1169d059297112922cabb0c674840589be8db821fd9aAdam Langley } 1170d059297112922cabb0c674840589be8db821fd9aAdam Langley 1171d059297112922cabb0c674840589be8db821fd9aAdam Langley sock = socket(PF_UNIX, SOCK_STREAM, 0); 1172d059297112922cabb0c674840589be8db821fd9aAdam Langley if (sock < 0) { 1173d059297112922cabb0c674840589be8db821fd9aAdam Langley saved_errno = errno; 1174d059297112922cabb0c674840589be8db821fd9aAdam Langley error("socket: %.100s", strerror(errno)); 1175d059297112922cabb0c674840589be8db821fd9aAdam Langley errno = saved_errno; 1176d059297112922cabb0c674840589be8db821fd9aAdam Langley return -1; 1177d059297112922cabb0c674840589be8db821fd9aAdam Langley } 1178d059297112922cabb0c674840589be8db821fd9aAdam Langley if (unlink_first == 1) { 1179d059297112922cabb0c674840589be8db821fd9aAdam Langley if (unlink(path) != 0 && errno != ENOENT) 1180d059297112922cabb0c674840589be8db821fd9aAdam Langley error("unlink(%s): %.100s", path, strerror(errno)); 1181d059297112922cabb0c674840589be8db821fd9aAdam Langley } 1182d059297112922cabb0c674840589be8db821fd9aAdam Langley if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { 1183d059297112922cabb0c674840589be8db821fd9aAdam Langley saved_errno = errno; 1184d059297112922cabb0c674840589be8db821fd9aAdam Langley error("bind: %.100s", strerror(errno)); 1185d059297112922cabb0c674840589be8db821fd9aAdam Langley close(sock); 1186d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: cannot bind to path: %s", __func__, path); 1187d059297112922cabb0c674840589be8db821fd9aAdam Langley errno = saved_errno; 1188d059297112922cabb0c674840589be8db821fd9aAdam Langley return -1; 1189d059297112922cabb0c674840589be8db821fd9aAdam Langley } 1190d059297112922cabb0c674840589be8db821fd9aAdam Langley if (listen(sock, backlog) < 0) { 1191d059297112922cabb0c674840589be8db821fd9aAdam Langley saved_errno = errno; 1192d059297112922cabb0c674840589be8db821fd9aAdam Langley error("listen: %.100s", strerror(errno)); 1193d059297112922cabb0c674840589be8db821fd9aAdam Langley close(sock); 1194d059297112922cabb0c674840589be8db821fd9aAdam Langley unlink(path); 1195d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: cannot listen on path: %s", __func__, path); 1196d059297112922cabb0c674840589be8db821fd9aAdam Langley errno = saved_errno; 1197d059297112922cabb0c674840589be8db821fd9aAdam Langley return -1; 1198d059297112922cabb0c674840589be8db821fd9aAdam Langley } 1199d059297112922cabb0c674840589be8db821fd9aAdam Langley return sock; 1200d059297112922cabb0c674840589be8db821fd9aAdam Langley} 1201d059297112922cabb0c674840589be8db821fd9aAdam Langley 1202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 1203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansock_set_v6only(int s) 1204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 12059768ca48f57aaf035f508a473421d210b5145e99Greg Hartman#if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) 1206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int on = 1; 1207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); 1209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) 1210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); 1211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 1212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 12139768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 12149768ca48f57aaf035f508a473421d210b5145e99Greg Hartman/* 12159768ca48f57aaf035f508a473421d210b5145e99Greg Hartman * Compares two strings that maybe be NULL. Returns non-zero if strings 12169768ca48f57aaf035f508a473421d210b5145e99Greg Hartman * are both NULL or are identical, returns zero otherwise. 12179768ca48f57aaf035f508a473421d210b5145e99Greg Hartman */ 12189768ca48f57aaf035f508a473421d210b5145e99Greg Hartmanstatic int 12199768ca48f57aaf035f508a473421d210b5145e99Greg Hartmanstrcmp_maybe_null(const char *a, const char *b) 12209768ca48f57aaf035f508a473421d210b5145e99Greg Hartman{ 12219768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if ((a == NULL && b != NULL) || (a != NULL && b == NULL)) 12229768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; 12239768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (a != NULL && strcmp(a, b) != 0) 12249768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; 12259768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 1; 12269768ca48f57aaf035f508a473421d210b5145e99Greg Hartman} 12279768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 12289768ca48f57aaf035f508a473421d210b5145e99Greg Hartman/* 12299768ca48f57aaf035f508a473421d210b5145e99Greg Hartman * Compare two forwards, returning non-zero if they are identical or 12309768ca48f57aaf035f508a473421d210b5145e99Greg Hartman * zero otherwise. 12319768ca48f57aaf035f508a473421d210b5145e99Greg Hartman */ 12329768ca48f57aaf035f508a473421d210b5145e99Greg Hartmanint 12339768ca48f57aaf035f508a473421d210b5145e99Greg Hartmanforward_equals(const struct Forward *a, const struct Forward *b) 12349768ca48f57aaf035f508a473421d210b5145e99Greg Hartman{ 12359768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (strcmp_maybe_null(a->listen_host, b->listen_host) == 0) 12369768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; 12379768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (a->listen_port != b->listen_port) 12389768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; 12399768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (strcmp_maybe_null(a->listen_path, b->listen_path) == 0) 12409768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; 12419768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (strcmp_maybe_null(a->connect_host, b->connect_host) == 0) 12429768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; 12439768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (a->connect_port != b->connect_port) 12449768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; 12459768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (strcmp_maybe_null(a->connect_path, b->connect_path) == 0) 12469768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; 12479768ca48f57aaf035f508a473421d210b5145e99Greg Hartman /* allocated_port and handle are not checked */ 12489768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 1; 12499768ca48f57aaf035f508a473421d210b5145e99Greg Hartman} 12509768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 12519768ca48f57aaf035f508a473421d210b5145e99Greg Hartman/* returns 1 if bind to specified port by specified user is permitted */ 12529768ca48f57aaf035f508a473421d210b5145e99Greg Hartmanint 12539768ca48f57aaf035f508a473421d210b5145e99Greg Hartmanbind_permitted(int port, uid_t uid) 12549768ca48f57aaf035f508a473421d210b5145e99Greg Hartman{ 12559768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (port < IPPORT_RESERVED && uid != 0) 12569768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; 12579768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 1; 12589768ca48f57aaf035f508a473421d210b5145e99Greg Hartman} 12599768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 12609768ca48f57aaf035f508a473421d210b5145e99Greg Hartman/* returns 1 if process is already daemonized, 0 otherwise */ 12619768ca48f57aaf035f508a473421d210b5145e99Greg Hartmanint 12629768ca48f57aaf035f508a473421d210b5145e99Greg Hartmandaemonized(void) 12639768ca48f57aaf035f508a473421d210b5145e99Greg Hartman{ 12649768ca48f57aaf035f508a473421d210b5145e99Greg Hartman int fd; 12659768ca48f57aaf035f508a473421d210b5145e99Greg Hartman 12669768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) >= 0) { 12679768ca48f57aaf035f508a473421d210b5145e99Greg Hartman close(fd); 12689768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; /* have controlling terminal */ 12699768ca48f57aaf035f508a473421d210b5145e99Greg Hartman } 12709768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (getppid() != 1) 12719768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; /* parent is not init */ 12729768ca48f57aaf035f508a473421d210b5145e99Greg Hartman if (getsid(0) != getpid()) 12739768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 0; /* not session leader */ 12749768ca48f57aaf035f508a473421d210b5145e99Greg Hartman debug3("already daemonized"); 12759768ca48f57aaf035f508a473421d210b5145e99Greg Hartman return 1; 12769768ca48f57aaf035f508a473421d210b5145e99Greg Hartman} 1277