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