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