Annotation of src/libexec/httpd/auth-bozo.c, Revision 1.4.16.1
1.4.16.1! msaitoh 1: /* $NetBSD: auth-bozo.c,v 1.13 2014/07/08 14:01:21 mrg Exp $ */
1.3 tls 2:
1.4.16.1! msaitoh 3: /* $eterna: auth-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $ */
1.1 tls 4:
5: /*
1.4.16.1! msaitoh 6: * Copyright (c) 1997-2014 Matthew R. Green
1.1 tls 7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer and
16: * dedication in the documentation and/or other materials provided
17: * with the distribution.
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,
24: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: *
31: */
32:
33: /* this code implements "http basic authorisation" for bozohttpd */
34:
35: #ifdef DO_HTPASSWD
36:
37: #include <sys/param.h>
38:
39: #include <string.h>
1.4.16.1! msaitoh 40: #include <stdlib.h>
1.1 tls 41: #include <unistd.h>
42:
43: #include "bozohttpd.h"
44:
45: #ifndef AUTH_FILE
46: #define AUTH_FILE ".htpasswd"
47: #endif
48:
49: static ssize_t base64_decode(const unsigned char *, size_t,
50: unsigned char *, size_t);
51:
52: /*
53: * Check if HTTP authentication is required
54: */
1.4.16.1! msaitoh 55: int
! 56: bozo_auth_check(bozo_httpreq_t *request, const char *file)
1.1 tls 57: {
1.4.16.1! msaitoh 58: bozohttpd_t *httpd = request->hr_httpd;
1.1 tls 59: struct stat sb;
60: char dir[MAXPATHLEN], authfile[MAXPATHLEN], *basename;
61: char user[BUFSIZ], *pass;
62: FILE *fp;
63: int len;
64:
65: /* get dir=dirname(file) */
66: snprintf(dir, sizeof(dir), "%s", file);
67: if ((basename = strrchr(dir, '/')) == NULL)
68: strcpy(dir, ".");
69: else {
70: *basename++ = '\0';
71: /* ensure basename(file) != AUTH_FILE */
1.4.16.1! msaitoh 72: if (bozo_check_special_files(request, basename))
! 73: return 1;
1.1 tls 74: }
1.4.16.1! msaitoh 75: request->hr_authrealm = bozostrdup(httpd, dir);
1.1 tls 76:
1.4.16.1! msaitoh 77: if ((size_t)snprintf(authfile, sizeof(authfile), "%s/%s", dir, AUTH_FILE) >=
! 78: sizeof(authfile)) {
! 79: return bozo_http_error(httpd, 404, request,
! 80: "authfile path too long");
! 81: }
1.1 tls 82: if (stat(authfile, &sb) < 0) {
1.4.16.1! msaitoh 83: debug((httpd, DEBUG_NORMAL,
! 84: "bozo_auth_check realm `%s' dir `%s' authfile `%s' missing",
1.1 tls 85: dir, file, authfile));
1.4.16.1! msaitoh 86: return 0;
1.1 tls 87: }
88: if ((fp = fopen(authfile, "r")) == NULL)
1.4.16.1! msaitoh 89: return bozo_http_error(httpd, 403, request,
! 90: "no permission to open authfile");
! 91: debug((httpd, DEBUG_NORMAL,
! 92: "bozo_auth_check realm `%s' dir `%s' authfile `%s' open",
1.1 tls 93: dir, file, authfile));
94: if (request->hr_authuser && request->hr_authpass) {
95: while (fgets(user, sizeof(user), fp) != NULL) {
96: len = strlen(user);
97: if (len > 0 && user[len-1] == '\n')
98: user[--len] = '\0';
99: if ((pass = strchr(user, ':')) == NULL)
100: continue;
101: *pass++ = '\0';
1.4.16.1! msaitoh 102: debug((httpd, DEBUG_NORMAL,
! 103: "bozo_auth_check authfile `%s':`%s' "
! 104: "client `%s':`%s'",
1.1 tls 105: user, pass, request->hr_authuser,
106: request->hr_authpass));
107: if (strcmp(request->hr_authuser, user) != 0)
108: continue;
1.4.16.1! msaitoh 109: if (strcmp(crypt(request->hr_authpass, pass),
! 110: pass) != 0)
1.1 tls 111: break;
112: fclose(fp);
1.4.16.1! msaitoh 113: return 0;
1.1 tls 114: }
115: }
116: fclose(fp);
1.4.16.1! msaitoh 117: return bozo_http_error(httpd, 401, request, "bad auth");
! 118: }
! 119:
! 120: void
! 121: bozo_auth_cleanup(bozo_httpreq_t *request)
! 122: {
! 123:
! 124: if (request == NULL)
! 125: return;
! 126: free(request->hr_authuser);
! 127: free(request->hr_authpass);
! 128: free(request->hr_authrealm);
1.1 tls 129: }
130:
131: int
1.4.16.1! msaitoh 132: bozo_auth_check_headers(bozo_httpreq_t *request, char *val, char *str, ssize_t len)
1.1 tls 133: {
1.4.16.1! msaitoh 134: bozohttpd_t *httpd = request->hr_httpd;
! 135:
1.1 tls 136: if (strcasecmp(val, "authorization") == 0 &&
137: strncasecmp(str, "Basic ", 6) == 0) {
138: char authbuf[BUFSIZ];
1.2 reed 139: char *pass = NULL;
1.1 tls 140: ssize_t alen;
141:
1.4.16.1! msaitoh 142: alen = base64_decode((unsigned char *)str + 6,
! 143: (size_t)(len - 6),
! 144: (unsigned char *)authbuf,
! 145: sizeof(authbuf) - 1);
1.1 tls 146: if (alen != -1)
147: authbuf[alen] = '\0';
148: if (alen == -1 ||
149: (pass = strchr(authbuf, ':')) == NULL)
1.4.16.1! msaitoh 150: return bozo_http_error(httpd, 400, request,
1.1 tls 151: "bad authorization field");
152: *pass++ = '\0';
1.4.16.1! msaitoh 153: request->hr_authuser = bozostrdup(httpd, authbuf);
! 154: request->hr_authpass = bozostrdup(httpd, pass);
! 155: debug((httpd, DEBUG_FAT,
1.1 tls 156: "decoded authorization `%s' as `%s':`%s'",
157: str, request->hr_authuser, request->hr_authpass));
158: /* don't store in request->headers */
159: return 1;
160: }
161: return 0;
162: }
163:
1.4.16.1! msaitoh 164: int
! 165: bozo_auth_check_special_files(bozo_httpreq_t *request,
! 166: const char *name)
1.1 tls 167: {
1.4.16.1! msaitoh 168: bozohttpd_t *httpd = request->hr_httpd;
! 169:
1.1 tls 170: if (strcmp(name, AUTH_FILE) == 0)
1.4.16.1! msaitoh 171: return bozo_http_error(httpd, 403, request,
! 172: "no permission to open authfile");
! 173: return 0;
1.1 tls 174: }
175:
176: void
1.4.16.1! msaitoh 177: bozo_auth_check_401(bozo_httpreq_t *request, int code)
1.1 tls 178: {
1.4.16.1! msaitoh 179: bozohttpd_t *httpd = request->hr_httpd;
! 180:
1.1 tls 181: if (code == 401)
1.4.16.1! msaitoh 182: bozo_printf(httpd,
! 183: "WWW-Authenticate: Basic realm=\"%s\"\r\n",
! 184: (request && request->hr_authrealm) ?
! 185: request->hr_authrealm : "default realm");
1.1 tls 186: }
187:
188: #ifndef NO_CGIBIN_SUPPORT
189: void
1.4.16.1! msaitoh 190: bozo_auth_cgi_setenv(bozo_httpreq_t *request,
! 191: char ***curenvpp)
1.1 tls 192: {
1.4.16.1! msaitoh 193: bozohttpd_t *httpd = request->hr_httpd;
! 194:
1.1 tls 195: if (request->hr_authuser && *request->hr_authuser) {
1.4.16.1! msaitoh 196: bozo_setenv(httpd, "AUTH_TYPE", "Basic", (*curenvpp)++);
! 197: bozo_setenv(httpd, "REMOTE_USER", request->hr_authuser,
! 198: (*curenvpp)++);
1.1 tls 199: }
200: }
201:
202: int
1.4.16.1! msaitoh 203: bozo_auth_cgi_count(bozo_httpreq_t *request)
1.1 tls 204: {
205: return (request->hr_authuser && *request->hr_authuser) ? 2 : 0;
206: }
207: #endif /* NO_CGIBIN_SUPPORT */
208:
209: /*
210: * Decode len bytes starting at in using base64 encoding into out.
211: * Result is *not* NUL terminated.
212: * Written by Luke Mewburn <lukem@NetBSD.org>
213: */
214: const unsigned char decodetable[] = {
215: 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
216: 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
217: 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
218: 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 0, 255, 255,
219: 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
220: 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
221: 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
222: 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
223: };
224:
225: static ssize_t
226: base64_decode(const unsigned char *in, size_t ilen, unsigned char *out,
227: size_t olen)
228: {
229: unsigned char *cp;
230: size_t i;
231:
232: cp = out;
233: for (i = 0; i < ilen; i += 4) {
234: if (cp + 3 > out + olen)
235: return (-1);
236: #define IN_CHECK(x) \
237: if ((x) > sizeof(decodetable) || decodetable[(x)] == 255) \
238: return(-1)
239:
240: IN_CHECK(in[i + 0]);
1.4.16.1! msaitoh 241: /*LINTED*/
1.1 tls 242: *(cp++) = decodetable[in[i + 0]] << 2
243: | decodetable[in[i + 1]] >> 4;
244: IN_CHECK(in[i + 1]);
1.4.16.1! msaitoh 245: /*LINTED*/
1.1 tls 246: *(cp++) = decodetable[in[i + 1]] << 4
247: | decodetable[in[i + 2]] >> 2;
248: IN_CHECK(in[i + 2]);
249: *(cp++) = decodetable[in[i + 2]] << 6
250: | decodetable[in[i + 3]];
251: #undef IN_CHECK
252: }
253: while (in[i - 1] == '=')
254: cp--,i--;
255: return (cp - out);
256: }
257: #endif /* DO_HTPASSWD */
CVSweb <webmaster@jp.NetBSD.org>