|
1 /* |
|
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
|
3 * |
|
4 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. |
|
5 * |
|
6 * THE BSD LICENSE |
|
7 * |
|
8 * Redistribution and use in source and binary forms, with or without |
|
9 * modification, are permitted provided that the following conditions are met: |
|
10 * |
|
11 * Redistributions of source code must retain the above copyright notice, this |
|
12 * list of conditions and the following disclaimer. |
|
13 * Redistributions in binary form must reproduce the above copyright notice, |
|
14 * this list of conditions and the following disclaimer in the documentation |
|
15 * and/or other materials provided with the distribution. |
|
16 * |
|
17 * Neither the name of the nor the names of its contributors may be |
|
18 * used to endorse or promote products derived from this software without |
|
19 * specific prior written permission. |
|
20 * |
|
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER |
|
25 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
|
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
|
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
|
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
|
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
32 */ |
|
33 |
|
34 #include <strings.h> |
|
35 |
|
36 #include "auth.h" |
|
37 |
|
38 |
|
39 /* ------------------------------ _uudecode ------------------------------- */ |
|
40 |
|
41 const unsigned char pr2six[256]={ |
|
42 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, |
|
43 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63, |
|
44 52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9, |
|
45 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27, |
|
46 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51, |
|
47 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, |
|
48 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, |
|
49 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, |
|
50 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, |
|
51 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, |
|
52 64,64,64,64,64,64,64,64,64,64,64,64,64 |
|
53 }; |
|
54 |
|
55 char *_uudecode(char *bufcoded) |
|
56 { |
|
57 register char *bufin = bufcoded; |
|
58 register unsigned char *bufout; |
|
59 register int nprbytes; |
|
60 unsigned char *bufplain; |
|
61 int nbytesdecoded; |
|
62 |
|
63 /* Find the length */ |
|
64 while(pr2six[(int)*(bufin++)] <= 63); |
|
65 nprbytes = bufin - bufcoded - 1; |
|
66 nbytesdecoded = ((nprbytes+3)/4) * 3; |
|
67 |
|
68 bufout = (unsigned char *) malloc(nbytesdecoded + 1); |
|
69 bufplain = bufout; |
|
70 |
|
71 bufin = bufcoded; |
|
72 |
|
73 while (nprbytes > 0) { |
|
74 *(bufout++) = (unsigned char) |
|
75 (pr2six[(int)(*bufin)] << 2 | pr2six[(int)bufin[1]] >> 4); |
|
76 *(bufout++) = (unsigned char) |
|
77 (pr2six[(int)bufin[1]] << 4 | pr2six[(int)bufin[2]] >> 2); |
|
78 *(bufout++) = (unsigned char) |
|
79 (pr2six[(int)bufin[2]] << 6 | pr2six[(int)bufin[3]]); |
|
80 bufin += 4; |
|
81 nprbytes -= 4; |
|
82 } |
|
83 |
|
84 if(nprbytes & 03) { |
|
85 if(pr2six[(int)bufin[-2]] > 63) |
|
86 nbytesdecoded -= 2; |
|
87 else |
|
88 nbytesdecoded -= 1; |
|
89 } |
|
90 bufplain[nbytesdecoded] = '\0'; |
|
91 |
|
92 return (char *)bufplain; |
|
93 } |
|
94 |
|
95 /* ------------------------------ auth_basic ------------------------------ */ |
|
96 |
|
97 int auth_basic(pblock *param, Session *sn, Request *rq) |
|
98 { |
|
99 char *pwfile, *grpfile, *type, *auth, *user, *pw; |
|
100 char *pwfn, *grpfn; |
|
101 pblock *npb; |
|
102 pb_param *pp; |
|
103 int ret; |
|
104 |
|
105 /* Although this is authorization (which is not cacheable) the |
|
106 * check is not actually done until we call require-auth. So |
|
107 * this part is cacheable; require-auth can be cacheable if the |
|
108 * user has limited the auth to only affect a certain set of |
|
109 * paths. |
|
110 */ |
|
111 rq->directive_is_cacheable = 1; |
|
112 |
|
113 if(request_header("authorization", &auth, sn, rq) == REQ_ABORTED) |
|
114 return REQ_ABORTED; |
|
115 |
|
116 if(!auth) |
|
117 return REQ_NOACTION; |
|
118 |
|
119 type = pblock_findval("auth-type", param); |
|
120 pwfile = pblock_findval("userdb", param); |
|
121 grpfile = pblock_findval("groupdb", param); |
|
122 pwfn = pblock_findval("userfn", param); |
|
123 grpfn = pblock_findval("groupfn", param); |
|
124 |
|
125 if((!type) || (!pwfile) || (!pwfn) || (grpfile && !grpfn)) { |
|
126 // TODO: log error |
|
127 //log_error(LOG_MISCONFIG, "basic-auth", sn, rq, |
|
128 // XP_GetAdminStr(DBT_authError1)); |
|
129 protocol_status(sn, rq, PROTOCOL_SERVER_ERROR, NULL); |
|
130 return REQ_ABORTED; |
|
131 } |
|
132 |
|
133 /* Skip leading whitespace */ |
|
134 while(*auth && (*auth == ' ')) |
|
135 ++auth; |
|
136 if(!(*auth)) { |
|
137 protocol_status(sn, rq, PROTOCOL_FORBIDDEN, NULL); |
|
138 return REQ_ABORTED; |
|
139 } |
|
140 |
|
141 /* Verify correct type */ |
|
142 if((strlen(auth) < 6) || strncasecmp(auth, "basic ", 6)) |
|
143 return REQ_NOACTION; |
|
144 |
|
145 /* Skip whitespace */ |
|
146 auth += 6; |
|
147 while(*auth && (*auth == ' ')) |
|
148 ++auth; |
|
149 |
|
150 if(!*auth) |
|
151 return REQ_NOACTION; |
|
152 |
|
153 /* Uuencoded user:password now */ |
|
154 if(!(user = _uudecode(auth))) |
|
155 return REQ_NOACTION; |
|
156 |
|
157 if(!(pw = strchr(user, ':'))) { |
|
158 free(user); |
|
159 return REQ_NOACTION; |
|
160 } |
|
161 *pw++ = '\0'; |
|
162 |
|
163 npb = pblock_create(4); |
|
164 pblock_nvinsert("user", user, npb); |
|
165 pblock_nvinsert("pw", pw, npb); |
|
166 pblock_nvinsert("userdb", pwfile, npb); |
|
167 if(grpfile) |
|
168 pblock_nvinsert("groupdb", grpfile, npb); |
|
169 pblock_nvinsert("fn", pwfn, npb); |
|
170 |
|
171 if ((ret = func_exec(npb, sn, rq)) != REQ_PROCEED) |
|
172 { |
|
173 goto bye; |
|
174 } |
|
175 |
|
176 pblock_nvinsert("auth-type", "basic", rq->vars); |
|
177 pblock_nvinsert("auth-user", user, rq->vars); |
|
178 pblock_nvinsert("auth-db", pwfile, rq->vars); |
|
179 #if defined(XP_WIN32) || defined(MCC_ADMSERV) |
|
180 /* MLM - the admin server needs this password information, |
|
181 * so I'm putting it back */ |
|
182 pblock_nvinsert("auth-password", pw, rq->vars); |
|
183 #endif /* XP_WIN32 */ |
|
184 |
|
185 if(grpfile) { |
|
186 pblock_nvinsert("groupdb", grpfile, npb); |
|
187 pp = pblock_find("fn", npb); |
|
188 free(pp->value); |
|
189 pp->value = strdup(grpfn); |
|
190 |
|
191 if( (ret = func_exec(npb, sn, rq)) != REQ_PROCEED ) |
|
192 goto bye; |
|
193 } |
|
194 ret = REQ_PROCEED; |
|
195 bye: |
|
196 pblock_free(npb); |
|
197 free(user); |
|
198 return ret; |
|
199 } |