1 /*
2  * Copyright (c) 2010, 2011, 2012, 2013, 2019, 2020
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: method.c,v 1.25.10.6 2020/11/11 17:02:26 karls Exp $";
48 
49 int
methodisvalid(method,ruletype)50 methodisvalid(method, ruletype)
51    const int method;
52    const objecttype_t ruletype;
53 {
54 
55    switch (ruletype) {
56       case object_crule:
57 #if HAVE_SOCKS_HOSTID
58       case object_hrule:
59 #endif /* HAVE_SOCKS_HOSTID */
60 
61          switch (method) {
62             case AUTHMETHOD_NONE:
63             case AUTHMETHOD_RFC931:
64             case AUTHMETHOD_PAM_ANY:
65             case AUTHMETHOD_PAM_ADDRESS:
66                return 1;
67 
68             default:
69                return 0;
70          }
71 
72          /* NOTREACHED */
73 
74       case object_srule:
75          /* all methods are valid for socks-rules. */
76          return 1;
77 
78       default:
79          SERRX(ruletype);
80    }
81 
82    /* NOTREACHED */
83 }
84 
85 #if !SOCKS_CLIENT
86 int
methodcanprovide(method,what)87 methodcanprovide(method, what)
88    const int method;
89    const methodinfo_t what;
90 {
91    const char *function = "methodcanprovide()";
92 
93    switch (method) {
94       case AUTHMETHOD_NOTSET:
95          return 0; /* does not provide anything. */
96 
97       case AUTHMETHOD_NONE:
98          return 0; /* does not provide anything. */
99 
100       case AUTHMETHOD_PAM_ANY:
101          return 0; /* may provide something, but can not depend on it. */
102 
103       case AUTHMETHOD_BSDAUTH:
104 #if HAVE_LDAP
105       case AUTHMETHOD_LDAPAUTH:
106 #endif /* HAVE_LDAP */
107       case AUTHMETHOD_GSSAPI:
108       case AUTHMETHOD_PAM_ADDRESS:
109       case AUTHMETHOD_PAM_USERNAME:
110       case AUTHMETHOD_RFC931:
111       case AUTHMETHOD_UNAME:
112          switch (what) {
113             case username:
114                return 1;
115 
116             default:
117                return 0;
118          }
119 
120          /* NOTREACHED */
121 
122       default:
123          SERRX(method);
124    }
125 
126    return 0; /* NOTREACHED */
127 }
128 
129 int
methodworkswith(method,what)130 methodworkswith(method, what)
131    const int method;
132    const methodinfo_t what;
133 {
134    const char *function = "methodworkswith()";
135 
136    switch (method) {
137       case AUTHMETHOD_NOTSET:
138          return 0; /* does not work with anything. */
139 
140       case AUTHMETHOD_NONE:
141          switch (what) {
142             case tcpreplies:
143             case udpreplies:
144             case replies:
145                return 1;
146 
147             default:
148                SERRX(what);
149          }
150          break;
151 
152       case AUTHMETHOD_PAM_ANY:
153       case AUTHMETHOD_PAM_ADDRESS:
154       case AUTHMETHOD_RFC931:
155          switch (what) {
156             case replies:
157             case udpreplies:
158                return 0;
159 
160             case tcpreplies:
161                return 1;
162 
163             default:
164                SERRX(what);
165          }
166          break;
167 
168       default:
169          switch (what) {
170             case udpreplies:
171             case tcpreplies:
172             case replies:
173                return 0;
174 
175             default:
176                SERRX(what);
177          }
178          break;
179    }
180 
181    return 0; /* NOTREACHED */
182 }
183 
184 
185 const char *
authname(auth)186 authname(auth)
187    const authmethod_t *auth;
188 {
189 
190    if (auth == NULL)
191       return NULL;
192 
193    switch (auth->method) {
194       case AUTHMETHOD_NOTSET:
195       case AUTHMETHOD_NONE:
196       case AUTHMETHOD_NOACCEPT: /* closing connection next presumably. */
197          return NULL;
198 
199       case AUTHMETHOD_UNAME:
200          return (const char *)auth->mdata.uname.name;
201 
202 #if HAVE_LIBWRAP
203       case AUTHMETHOD_RFC931:
204          return (const char *)auth->mdata.rfc931.name;
205 #endif /* HAVE_LIBWRAP */
206 
207 #if HAVE_PAM
208       case AUTHMETHOD_PAM_ANY:      /* maybe there is a name, maybe not. */
209       case AUTHMETHOD_PAM_ADDRESS:
210       case AUTHMETHOD_PAM_USERNAME:
211          return (const char *)auth->mdata.pam.name;
212 #endif /* HAVE_PAM */
213 
214 #if HAVE_BSDAUTH
215       case AUTHMETHOD_BSDAUTH:
216          return (const char *)auth->mdata.bsd.name;
217 #endif /* HAVE_BSDAUTH */
218 
219 #if HAVE_LDAP
220       case AUTHMETHOD_LDAPAUTH:
221          return (const char *)auth->mdata.ldap.name;
222 #endif /* HAVE_LDAP */
223 
224 #if HAVE_GSSAPI
225       case AUTHMETHOD_GSSAPI:
226          return (const char *)auth->mdata.gssapi.name;
227 #endif /* HAVE_GSSAPI */
228 
229       default:
230          SERRX(auth->method);
231    }
232 
233    /* NOTREACHED */
234 }
235 
236 #if HAVE_PAC
237 
238 const char *
authsids(auth)239 authsids(auth)
240    const authmethod_t *auth;
241 {
242 
243    if (auth == NULL)
244       return NULL;
245 
246    switch (auth->method) {
247       case AUTHMETHOD_NOTSET:
248       case AUTHMETHOD_NONE:
249       case AUTHMETHOD_UNAME:
250 #if HAVE_LIBWRAP
251       case AUTHMETHOD_RFC931:
252 #endif /* HAVE_LIBWRAP */
253 #if HAVE_PAM
254       case AUTHMETHOD_PAM_ANY:      /* maybe there is a name, maybe not. */
255       case AUTHMETHOD_PAM_ADDRESS:
256       case AUTHMETHOD_PAM_USERNAME:
257 #endif /* HAVE_PAM */
258 #if HAVE_BSDAUTH
259       case AUTHMETHOD_BSDAUTH:
260 #endif /* HAVE_BSDAUTH */
261 #if HAVE_LDAP
262       case AUTHMETHOD_LDAPAUTH:
263 #endif /* HAVE_LDAP */
264       case AUTHMETHOD_NOACCEPT: /* closing connection next presumably. */
265          return NULL;
266 
267 #if HAVE_GSSAPI
268       case AUTHMETHOD_GSSAPI:
269          return (const char *)auth->mdata.gssapi.sids;
270 #endif /* HAVE_GSSAPI */
271 
272       default:
273          SERRX(auth->method);
274    }
275 
276    /* NOTREACHED */
277 }
278 
279 #endif /* HAVE_PAC */
280 
281 char *
build_addrstr_src(hostidv,hostidc,peer,proxy_ext,proxy,local,peerauth,proxyauth,str,strsize)282 build_addrstr_src(hostidv, hostidc, peer, proxy_ext, proxy, local,
283                   peerauth, proxyauth, str, strsize)
284    const struct in_addr *hostidv;
285    const unsigned int hostidc;
286    const sockshost_t *peer;
287    const sockshost_t *proxy_ext;
288    const sockshost_t *proxy;
289    const sockshost_t *local;
290    const authmethod_t *peerauth;
291    const authmethod_t *proxyauth;
292    char *str;
293    size_t strsize;
294 {
295    const char *function = "build_addrstr_src()";
296    size_t strused;
297    char peerstr[MAXSOCKSHOSTSTRING], peerauthstr[MAXAUTHINFOLEN],
298         proxyauthstr[MAXAUTHINFOLEN], pstr[MAXSOCKSHOSTSTRING],
299         pe_str[MAXSOCKSHOSTSTRING + sizeof("[]")], lstr[MAXSOCKSHOSTSTRING];
300 
301    strused = 0;
302    if (hostidv != NULL && hostidc > 0) {
303       size_t i;
304 
305       for (i = 0; i < hostidc; ++i) {
306          char ntop[MAXSOCKADDRSTRING];
307 
308          if (inet_ntop(AF_INET, &hostidv[i], ntop, sizeof(ntop)) == NULL) {
309             slog(LOG_DEBUG, "%s: inet_ntop(3) failed on %s %x: %s",
310                  function,
311                  atype2string(SOCKS_ADDR_IPV4),
312                  hostidv[i].s_addr,
313                  strerror(errno));
314 
315              snprintf(ntop, sizeof(ntop), "<unknown>");
316          }
317 
318          strused += snprintf(&str[strused], strsize - strused,
319                              "%s[%s]",
320                              i > 0 ? " " : "",
321                              ntop);
322 
323       }
324       if ((strused + 1) < strsize) {
325          str[strused]      = ' ';
326          str[strused + 1]  = NUL;
327          strused           += 1;
328       }
329    }
330 
331    if ((proxy_ext) == NULL)
332       *pe_str = NUL;
333    else
334       snprintf(pe_str, sizeof(pe_str),
335                "[%s] ", sockshost2string(proxy_ext, NULL, 0));
336 
337    snprintf(&str[strused], strsize - strused,
338             "%s%s "
339             "%s"
340             "%s%s%s"
341             "%s",
342 
343             authinfo((peerauth), peerauthstr, sizeof(peerauthstr)),
344             (peer) == NULL ?
345                "0.0.0.0.0" : sockshost2string((peer), peerstr, sizeof(peerstr)),
346 
347             pe_str,
348 
349             authinfo((proxyauth), proxyauthstr, sizeof(proxyauthstr)),
350             (proxy) == NULL ?
351                "" : sockshost2string((proxy), pstr, sizeof(pstr)),
352             (proxy) == NULL ? "" : " ",
353 
354             (local) == NULL ?
355                "0.0.0.0.0" : sockshost2string((local), lstr, sizeof(lstr)));
356 
357    return str;
358 }
359 
360 char *
build_addrstr_dst(local,proxy,proxy_ext,peer,peerauth,proxyauth,hostidv,hostidc,str,strsize)361 build_addrstr_dst(local, proxy, proxy_ext, peer,
362                   peerauth, proxyauth, hostidv, hostidc, str, strsize)
363    const sockshost_t *local;
364    const sockshost_t *proxy;
365    const sockshost_t *proxy_ext;
366    const sockshost_t *peer;
367    const authmethod_t *peerauth;
368    const authmethod_t *proxyauth;
369    const struct in_addr *hostidv;
370    const unsigned int hostidc;
371    char *str;
372    size_t strsize;
373 {
374    const char *function = "build_addrstr_dst()";
375    size_t strused;
376    char peerstr[MAXSOCKSHOSTSTRING], peerauthstr[MAXAUTHINFOLEN],
377         proxyauthstr[MAXAUTHINFOLEN], pstr[MAXSOCKSHOSTSTRING],
378         pe_str[MAXSOCKSHOSTSTRING + sizeof("[]")], lstr[MAXSOCKSHOSTSTRING];
379 
380    if ((proxy_ext) == NULL)
381       *pe_str = NUL;
382    else
383       snprintf(pe_str, sizeof(pe_str),
384                "[%s] ", sockshost2string(proxy_ext, NULL, 0));
385 
386    strused =
387    snprintf((str), (strsize),
388             "%s "
389             "%s%s%s"
390             "%s"
391             "%s%s",
392 
393             local == NULL ?
394                "0.0.0.0.0" : sockshost2string(local, lstr, sizeof(lstr)),
395 
396             authinfo(proxyauth, proxyauthstr, sizeof(proxyauthstr)),
397             proxy == NULL ?
398                "" : sockshost2string(proxy, pstr, sizeof(pstr)),
399             proxy == NULL ? "" : " ",
400 
401             pe_str,
402 
403             authinfo(peerauth, peerauthstr, sizeof(peerauthstr)),
404             peer == NULL ?
405              "0.0.0.0.0" : sockshost2string(peer, peerstr, sizeof(peerstr)));
406 
407    if (hostidv != NULL && hostidc > 0) {
408       ssize_t i;
409 
410       if ((strused + 1) < strsize) {
411          str[strused]      = ' ';
412          str[strused + 1]  = NUL;
413          strused          += 1;
414       }
415 
416       for (i = hostidc - 1; i >= 0; --i) {
417          char ntop[MAXSOCKADDRSTRING];
418 
419          if (inet_ntop(AF_INET, &hostidv[i], ntop, sizeof(ntop)) == NULL) {
420             slog(LOG_DEBUG, "%s: inet_ntop(3) failed on %s %x: %s",
421                  function,
422                  atype2string(SOCKS_ADDR_IPV4),
423                  hostidv[i].s_addr,
424                  strerror(errno));
425 
426              snprintf(ntop, sizeof(ntop), "<unknown>");
427          }
428 
429          strused += snprintf(&str[strused], strsize - strused,
430                              "%s[%s]",
431                              (i == ((ssize_t)hostidc) - 1) ? "" : " ",
432                              ntop);
433       }
434    }
435 
436    return str;
437 }
438 
439 const char *
authinfo(auth,info,infolen)440 authinfo(auth, info, infolen)
441    const authmethod_t *auth;
442    char *info;
443    size_t infolen;
444 {
445    const char *name, *method, *methodinfo = NULL;
446 
447    if (info == NULL || infolen == 0) {
448       static char buf[MAXAUTHINFOLEN];
449 
450       info    = buf;
451       infolen = sizeof(buf);
452    }
453 
454    if (auth != NULL) {
455       name   = authname(auth);
456       method = method2string(auth->method);
457 
458 #if HAVE_GSSAPI
459       if (auth->method == AUTHMETHOD_GSSAPI)
460          methodinfo
461          = gssapiprotection2string(auth->mdata.gssapi.state.protection);
462 #endif /* HAVE_GSSAPI */
463    }
464    else
465       name = method = NULL;
466 
467    if (name == NULL || *name == NUL)
468       *info = NUL;
469    else
470       snprintf(info, infolen, "%s%s%s%%%s@",
471                method,
472                methodinfo == NULL ? "" : "/",
473                methodinfo == NULL ? "" : methodinfo,
474                name);
475 
476    return info;
477 }
478 
479 #endif /* !SOCKS_CLIENT  */
480