No empty .Rs/.Re
[netbsd-mini2440.git] / libexec / httpd / auth-bozo.c
blob7badf01ba4919a7fd09969bcef8b93194006a997
1 /* $NetBSD: auth-bozo.c,v 1.6 2009/04/18 07:38:40 mrg Exp $ */
3 /* $eterna: auth-bozo.c,v 1.13 2009/04/18 07:38:56 mrg Exp $ */
5 /*
6 * Copyright (c) 1997-2009 Matthew R. Green
7 * All rights reserved.
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.
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.
33 /* this code implements "http basic authorisation" for bozohttpd */
35 #ifdef DO_HTPASSWD
37 #include <sys/param.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <unistd.h>
43 #include "bozohttpd.h"
45 #ifndef AUTH_FILE
46 #define AUTH_FILE ".htpasswd"
47 #endif
49 static ssize_t base64_decode(const unsigned char *, size_t,
50 unsigned char *, size_t);
53 * Check if HTTP authentication is required
55 int
56 auth_check(http_req *request, const char *file)
58 struct stat sb;
59 char dir[MAXPATHLEN], authfile[MAXPATHLEN], *basename;
60 char user[BUFSIZ], *pass;
61 FILE *fp;
62 int len;
64 /* get dir=dirname(file) */
65 snprintf(dir, sizeof(dir), "%s", file);
66 if ((basename = strrchr(dir, '/')) == NULL)
67 strcpy(dir, ".");
68 else {
69 *basename++ = '\0';
70 /* ensure basename(file) != AUTH_FILE */
71 if (check_special_files(request, basename))
72 return 1;
74 request->hr_authrealm = bozostrdup(dir);
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 0;
83 if ((fp = fopen(authfile, "r")) == NULL)
84 return http_error(403, request, "no permission to open "
85 "authfile");
86 debug((DEBUG_NORMAL,
87 "auth_check realm `%s' dir `%s' authfile `%s' open",
88 dir, file, authfile));
89 if (request->hr_authuser && request->hr_authpass) {
90 while (fgets(user, sizeof(user), fp) != NULL) {
91 len = strlen(user);
92 if (len > 0 && user[len-1] == '\n')
93 user[--len] = '\0';
94 if ((pass = strchr(user, ':')) == NULL)
95 continue;
96 *pass++ = '\0';
97 debug((DEBUG_NORMAL,
98 "auth_check authfile `%s':`%s' client `%s':`%s'",
99 user, pass, request->hr_authuser,
100 request->hr_authpass));
101 if (strcmp(request->hr_authuser, user) != 0)
102 continue;
103 if (strcmp(crypt(request->hr_authpass, pass), pass))
104 break;
105 fclose(fp);
106 return 0;
109 fclose(fp);
110 return http_error(401, request, "bad auth");
113 void
114 auth_cleanup(http_req *request)
117 if (request == NULL)
118 return;
119 if (request->hr_authuser)
120 free(request->hr_authuser);
121 if (request->hr_authpass)
122 free(request->hr_authpass);
123 if (request->hr_authrealm)
124 free(request->hr_authrealm);
128 auth_check_headers(http_req *request, char *val, char *str, ssize_t len)
130 if (strcasecmp(val, "authorization") == 0 &&
131 strncasecmp(str, "Basic ", 6) == 0) {
132 char authbuf[BUFSIZ];
133 char *pass = NULL;
134 ssize_t alen;
136 alen = base64_decode((unsigned char *)str + 6, len - 6,
137 (unsigned char *)authbuf, sizeof(authbuf) - 1);
138 if (alen != -1)
139 authbuf[alen] = '\0';
140 if (alen == -1 ||
141 (pass = strchr(authbuf, ':')) == NULL)
142 return http_error(400, request,
143 "bad authorization field");
144 *pass++ = '\0';
145 request->hr_authuser = bozostrdup(authbuf);
146 request->hr_authpass = bozostrdup(pass);
147 debug((DEBUG_FAT,
148 "decoded authorization `%s' as `%s':`%s'",
149 str, request->hr_authuser, request->hr_authpass));
150 /* don't store in request->headers */
151 return 1;
153 return 0;
157 auth_check_special_files(http_req *request, const char *name)
159 if (strcmp(name, AUTH_FILE) == 0)
160 return http_error(403, request, "no permission to open authfile");
161 return 0;
164 void
165 auth_check_401(http_req *request, int code)
167 if (code == 401)
168 bozoprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n",
169 request && request->hr_authrealm ? request->hr_authrealm :
170 "default realm");
173 #ifndef NO_CGIBIN_SUPPORT
174 void
175 auth_cgi_setenv(http_req *request, char ***curenvpp)
177 if (request->hr_authuser && *request->hr_authuser) {
178 spsetenv("AUTH_TYPE", "Basic", (*curenvpp)++);
179 spsetenv("REMOTE_USER", request->hr_authuser, (*curenvpp)++);
184 auth_cgi_count(http_req *request)
186 return (request->hr_authuser && *request->hr_authuser) ? 2 : 0;
188 #endif /* NO_CGIBIN_SUPPORT */
191 * Decode len bytes starting at in using base64 encoding into out.
192 * Result is *not* NUL terminated.
193 * Written by Luke Mewburn <lukem@NetBSD.org>
195 const unsigned char decodetable[] = {
196 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
197 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
198 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
199 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 0, 255, 255,
200 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
201 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
202 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
203 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
206 static ssize_t
207 base64_decode(const unsigned char *in, size_t ilen, unsigned char *out,
208 size_t olen)
210 unsigned char *cp;
211 size_t i;
213 cp = out;
214 for (i = 0; i < ilen; i += 4) {
215 if (cp + 3 > out + olen)
216 return (-1);
217 #define IN_CHECK(x) \
218 if ((x) > sizeof(decodetable) || decodetable[(x)] == 255) \
219 return(-1)
221 IN_CHECK(in[i + 0]);
222 *(cp++) = decodetable[in[i + 0]] << 2
223 | decodetable[in[i + 1]] >> 4;
224 IN_CHECK(in[i + 1]);
225 *(cp++) = decodetable[in[i + 1]] << 4
226 | decodetable[in[i + 2]] >> 2;
227 IN_CHECK(in[i + 2]);
228 *(cp++) = decodetable[in[i + 2]] << 6
229 | decodetable[in[i + 3]];
230 #undef IN_CHECK
232 while (in[i - 1] == '=')
233 cp--,i--;
234 return (cp - out);
236 #endif /* DO_HTPASSWD */