Annotation of src/libexec/httpd/auth-bozo.c, Revision 1.4
1.4 ! mrg 1: /* $NetBSD: auth-bozo.c,v 1.3 2007/10/17 18:47:59 tls Exp $ */
1.3 tls 2:
1.4 ! mrg 3: /* $eterna: auth-bozo.c,v 1.8 2008/03/03 03:36:11 mrg Exp $ */
1.1 tls 4:
5: /*
1.4 ! mrg 6: * Copyright (c) 1997-2008 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: * 3. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: */
34:
35: /* this code implements "http basic authorisation" for bozohttpd */
36:
37: #ifdef DO_HTPASSWD
38:
39: #include <sys/param.h>
40:
41: #include <string.h>
42: #include <unistd.h>
43:
44: #include "bozohttpd.h"
45:
46: #ifndef AUTH_FILE
47: #define AUTH_FILE ".htpasswd"
48: #endif
49:
50: static ssize_t base64_decode(const unsigned char *, size_t,
51: unsigned char *, size_t);
52:
53: /*
54: * Check if HTTP authentication is required
55: */
56: void
57: auth_check(http_req *request, const char *file)
58: {
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 */
72: check_special_files(request, basename);
73: }
74: request->hr_authrealm = dir;
75:
76: snprintf(authfile, sizeof(authfile), "%s/%s", dir, AUTH_FILE);
77: if (stat(authfile, &sb) < 0) {
78: debug((DEBUG_NORMAL,
79: "auth_check realm `%s' dir `%s' authfile `%s' missing",
80: dir, file, authfile));
81: return;
82: }
83: if ((fp = fopen(authfile, "r")) == NULL)
84: http_error(403, request, "no permission to open authfile");
85: debug((DEBUG_NORMAL,
86: "auth_check realm `%s' dir `%s' authfile `%s' open",
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';
96: debug((DEBUG_NORMAL,
97: "auth_check authfile `%s':`%s' client `%s':`%s'",
98: user, pass, request->hr_authuser,
99: request->hr_authpass));
100: if (strcmp(request->hr_authuser, user) != 0)
101: continue;
102: if (strcmp(crypt(request->hr_authpass, pass), pass))
103: break;
104: fclose(fp);
105: return;
106: }
107: }
108: fclose(fp);
109: http_error(401, request, "bad auth");
110: }
111:
112: int
113: auth_check_headers(http_req *request, char *val, char *str, ssize_t len)
114: {
115: if (strcasecmp(val, "authorization") == 0 &&
116: strncasecmp(str, "Basic ", 6) == 0) {
117: char authbuf[BUFSIZ];
1.2 reed 118: char *pass = NULL;
1.1 tls 119: ssize_t alen;
120:
1.2 reed 121: alen = base64_decode((unsigned char *)str + 6, len - 6,
122: (unsigned char *)authbuf, sizeof(authbuf) - 1);
1.1 tls 123: if (alen != -1)
124: authbuf[alen] = '\0';
125: if (alen == -1 ||
126: (pass = strchr(authbuf, ':')) == NULL)
127: http_error(400, request,
128: "bad authorization field");
129: *pass++ = '\0';
130: request->hr_authuser = bozostrdup(authbuf);
131: request->hr_authpass = bozostrdup(pass);
132: debug((DEBUG_FAT,
133: "decoded authorization `%s' as `%s':`%s'",
134: str, request->hr_authuser, request->hr_authpass));
135: /* don't store in request->headers */
136: return 1;
137: }
138: return 0;
139: }
140:
141: void
142: auth_check_special_files(http_req *request, const char *name)
143: {
144: if (strcmp(name, AUTH_FILE) == 0)
145: http_error(403, request, "no permission to open authfile");
146: }
147:
148: void
149: auth_check_401(http_req *request, int code)
150: {
151: if (code == 401)
152: bozoprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n",
153: request && request->hr_authrealm ? request->hr_authrealm :
154: "default realm");
155: }
156:
157: #ifndef NO_CGIBIN_SUPPORT
158: void
159: auth_cgi_setenv(http_req *request, char ***curenvpp)
160: {
161: if (request->hr_authuser && *request->hr_authuser) {
162: spsetenv("AUTH_TYPE", "Basic", (*curenvpp)++);
163: spsetenv("REMOTEUSER", request->hr_authuser, (*curenvpp)++);
164: }
165: }
166:
167: int
168: auth_cgi_count(http_req *request)
169: {
170: return (request->hr_authuser && *request->hr_authuser) ? 2 : 0;
171: }
172: #endif /* NO_CGIBIN_SUPPORT */
173:
174: /*
175: * Decode len bytes starting at in using base64 encoding into out.
176: * Result is *not* NUL terminated.
177: * Written by Luke Mewburn <lukem@NetBSD.org>
178: */
179: const unsigned char decodetable[] = {
180: 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
181: 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
182: 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
183: 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 0, 255, 255,
184: 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
185: 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
186: 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
187: 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
188: };
189:
190: static ssize_t
191: base64_decode(const unsigned char *in, size_t ilen, unsigned char *out,
192: size_t olen)
193: {
194: unsigned char *cp;
195: size_t i;
196:
197: cp = out;
198: for (i = 0; i < ilen; i += 4) {
199: if (cp + 3 > out + olen)
200: return (-1);
201: #define IN_CHECK(x) \
202: if ((x) > sizeof(decodetable) || decodetable[(x)] == 255) \
203: return(-1)
204:
205: IN_CHECK(in[i + 0]);
206: *(cp++) = decodetable[in[i + 0]] << 2
207: | decodetable[in[i + 1]] >> 4;
208: IN_CHECK(in[i + 1]);
209: *(cp++) = decodetable[in[i + 1]] << 4
210: | decodetable[in[i + 2]] >> 2;
211: IN_CHECK(in[i + 2]);
212: *(cp++) = decodetable[in[i + 2]] << 6
213: | decodetable[in[i + 3]];
214: #undef IN_CHECK
215: }
216: while (in[i - 1] == '=')
217: cp--,i--;
218: return (cp - out);
219: }
220: #endif /* DO_HTPASSWD */
CVSweb <webmaster@jp.NetBSD.org>