1 /*
2  * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2008, 2009, 2010, 2011, 2012
3  *      Inferno Nettverk A/S, Norway.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. The above copyright notice, this list of conditions and the following
9  *    disclaimer must appear in all copies of the software, derivative works
10  *    or modified versions, and any portions thereof, aswell as in all
11  *    supporting documentation.
12  * 2. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:
14  *      This product includes software developed by
15  *      Inferno Nettverk A/S, Norway.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * Inferno Nettverk A/S requests users of this software to return to
31  *
32  *  Software Distribution Coordinator  or  sdc@inet.no
33  *  Inferno Nettverk A/S
34  *  Oslo Research Park
35  *  Gaustadall�en 21
36  *  NO-0349 Oslo
37  *  Norway
38  *
39  * any improvements or extensions that they make and grant Inferno Nettverk A/S
40  * the rights to redistribute these changes.
41  *
42  */
43 
44 #include "common.h"
45 
46 static const char rcsid[] =
47 "$Id: userio.c,v 1.60 2012/11/01 23:57:57 michaels Exp $";
48 
49 /* ARGSUSED */
50 char *
socks_getusername(host,buf,buflen)51 socks_getusername(host, buf, buflen)
52    const sockshost_t *host;
53    char *buf;
54    size_t buflen;
55 {
56    const char *function = "socks_getusername()";
57    char *name;
58 
59    if ((name = socks_getenv(ENV_SOCKS_USERNAME, dontcare)) != NULL
60    ||  (name = socks_getenv(ENV_SOCKS_USER,     dontcare)) != NULL
61    ||  (name = socks_getenv(ENV_SOCKS5_USER,    dontcare)) != NULL)
62       slog(LOG_NEGOTIATE,
63            "%s: using socks username from environment: \"%s\"", function, name);
64 #if SOCKS_CLIENT
65    else {
66       struct passwd *pw;
67 
68       if ((pw = getpwuid(getuid())) != NULL)
69          name = pw->pw_name;
70       else
71          name = getlogin();
72    }
73 #endif /* SOCKS_CLIENT */
74 
75    if (name == NULL)
76       return NULL;
77 
78    if (strlen(name) >= buflen) {
79       swarnx("%s: socks username %lu characters too long, truncated",
80       function, (unsigned long)((strlen(name) + 1) - buflen));
81       name[buflen - 1] = NUL;
82    }
83 
84    strcpy(buf, name);
85    return buf;
86 }
87 
88 char *
socks_getpassword(host,user,buf,buflen)89 socks_getpassword(host, user, buf, buflen)
90    const sockshost_t *host;
91    const char *user;
92    char *buf;
93    size_t buflen;
94 {
95    const char *function = "socks_getpassword()";
96    char *password;
97    int password_is_from_env;
98 
99    if ((password = socks_getenv(ENV_SOCKS_PASSWORD, dontcare)) != NULL
100    ||  (password = socks_getenv(ENV_SOCKS_PASSWD,   dontcare)) != NULL
101    ||  (password = socks_getenv(ENV_SOCKS5_PASSWD,  dontcare)) != NULL)
102       password_is_from_env = 1;
103    else {
104 #if SOCKS_CLIENT && HAVE_GETPASS
105       char prompt[256 + MAXSOCKSHOSTSTRING];
106       char hstring[MAXSOCKSHOSTSTRING];
107 
108       snprintf(prompt, sizeof(prompt), "%s@%s socks password: ",
109                user, sockshost2string(host, hstring, sizeof(hstring)));
110 
111       password = getpass(prompt);
112 
113 #else /* !SOCKS_CLIENT && HAVE_GETPASS */
114 
115       password = NULL;
116 #endif /* !SOCKS_CLIENT && HAVE_GETPASS */
117 
118       password_is_from_env = 0;
119    }
120 
121    if (password == NULL)
122       return NULL;
123 
124    if (strlen(password) >= buflen) {
125       swarnx("%s: socks password is %lu characters too long; truncated",
126              function, (unsigned long)((strlen(password) + 1) - buflen));
127 
128       password[buflen - 1] = NUL;
129    }
130 
131    strcpy(buf, password);
132 
133    if (!password_is_from_env) /* don't zero environment. */
134       bzero(password, strlen(password));
135 
136    return buf;
137 }
138 
139 char *
socks_getenv(name,value)140 socks_getenv(name, value)
141    const char *name;
142    value_t value;
143 {
144    char *p = NULL;
145 
146 #if SOCKS_CLIENT
147 #if HAVE_CONFENV_DISABLE
148    const char *safenames[] = { ENV_SOCKS_BINDLOCALONLY,
149                                ENV_SOCKS_DEBUG,
150                                ENV_SOCKS_DISABLE_THREADLOCK,
151                                ENV_SOCKS_DIRECTROUTE_FALLBACK,
152                                ENV_SOCKS_PASSWORD,
153                                ENV_SOCKS_PASSWD,
154                                ENV_SOCKS5_PASSWD,
155                                ENV_SOCKS_USERNAME,
156                                ENV_SOCKS_USER,
157                                ENV_SOCKS5_USER,
158    };
159    size_t i;
160 #endif /* HAVE_CONFENV_DISABLE */
161 
162    if (strcmp(name, ENV_SOCKS_CONF)         == 0
163    ||  strcmp(name, ENV_SOCKS_LOGOUTPUT)    == 0
164    ||  strcmp(name, ENV_SOCKS_ERRLOGOUTPUT) == 0
165    ||  strcmp(name, ENV_TMPDIR)             == 0) {
166       /*
167        * Even if getenv() is not disabled, we don't want to return
168        * anything for this if the program may be running setuid,
169        * as it could allow reading/writing of arbitrary files.
170        */
171       if (issetugid())
172          return NULL;
173       else
174          return getenv(name);
175    }
176 
177 #if HAVE_CONFENV_DISABLE
178    /*
179     * If the name is safe, get it regardless of confenv being disabled.
180     */
181    for (i = 0; i < ELEMENTS(safenames); ++i)
182       if (strcmp(name, safenames[i]) == 0) {
183          p = getenv(name);
184          break;
185       }
186 
187 #else /* !HAVE_CONFENV_DISABLE */
188    p = getenv(name);
189 #endif /* !HAVE_CONFENV_DISABLE */
190 
191 #else /* !SOCKS_CLIENT */
192    p = getenv(name);
193 #endif /* !SOCKS_CLIENT */
194 
195    if (p == NULL || value == dontcare) {
196       /*
197        * Some variables have a default based on configure/define.
198        */
199       if (strcmp(name, ENV_SOCKS_DIRECTROUTE_FALLBACK) == 0)
200          p = (SOCKS_DIRECTROUTE_FALLBACK ? "yes" : "no");
201       else
202          return p;
203    }
204 
205    switch (value) {
206       case istrue:
207          if (strcasecmp(p, "yes")  == 0
208          ||  strcasecmp(p, "true") == 0
209          ||  strcasecmp(p, "1")    == 0)
210             return p;
211          return NULL;
212 
213       case isfalse:
214          if (strcasecmp(p, "no")    == 0
215          ||  strcasecmp(p, "false") == 0
216          ||  strcasecmp(p, "0")     == 0)
217             return p;
218          return NULL;
219 
220       default:
221          SERRX(value);
222    }
223 
224    /* NOTREACHED */
225 }
226