File: | d/auth.c |
Warning: | line 337, column 33 Access out-of-bound array element (buffer overflow) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * The contents of this file are subject to the Mozilla Public License | |||
3 | * Version 1.1 (the "License"); you may not use this file except in | |||
4 | * compliance with the License. You may obtain a copy of the License at | |||
5 | * http://mozilla.org/. | |||
6 | * | |||
7 | * Software distributed under the License is distributed on an "AS IS" | |||
8 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See | |||
9 | * the License for the specific language governing rights and limitations | |||
10 | * under the License. | |||
11 | * | |||
12 | * The Original Code is AOLserver Code and related documentation | |||
13 | * distributed by AOL. | |||
14 | * | |||
15 | * The Initial Developer of the Original Code is America Online, | |||
16 | * Inc. Portions created by AOL are Copyright (C) 1999 America Online, | |||
17 | * Inc. All Rights Reserved. | |||
18 | * | |||
19 | * Alternatively, the contents of this file may be used under the terms | |||
20 | * of the GNU General Public License (the "GPL"), in which case the | |||
21 | * provisions of GPL are applicable instead of those above. If you wish | |||
22 | * to allow use of your version of this file only under the terms of the | |||
23 | * GPL and not to allow others to use your version of this file under the | |||
24 | * License, indicate your decision by deleting the provisions above and | |||
25 | * replace them with the notice and other provisions required by the GPL. | |||
26 | * If you do not delete the provisions above, a recipient may use your | |||
27 | * version of this file under either the License or the GPL. | |||
28 | */ | |||
29 | ||||
30 | /* | |||
31 | * auth.c -- | |||
32 | * | |||
33 | * URL level HTTP authorization support. | |||
34 | */ | |||
35 | ||||
36 | #include "nsd.h" | |||
37 | ||||
38 | /* | |||
39 | * The following proc is used for simple user authorization. It | |||
40 | * could be useful for global modules (e.g., nscp). | |||
41 | */ | |||
42 | ||||
43 | static Ns_UserAuthorizeProc *userProcPtr = NULL((void*)0); | |||
44 | ||||
45 | ||||
46 | /* | |||
47 | *---------------------------------------------------------------------- | |||
48 | * | |||
49 | * Ns_AuthorizeRequest -- | |||
50 | * | |||
51 | * Check for proper HTTP authorization of a request. | |||
52 | * | |||
53 | * Results: | |||
54 | * User supplied routine is expected to return NS_OK if authorization | |||
55 | * is allowed, NS_UNAUTHORIZED if a correct username/passwd could | |||
56 | * allow authorization, NS_FORBIDDEN if no username/passwd would ever | |||
57 | * allow access, or NS_ERROR on error. | |||
58 | * | |||
59 | * Side effects: | |||
60 | * Depends on user supplied routine. "method" and "url" could be NULL in | |||
61 | * case of non-HTTP requests. | |||
62 | * | |||
63 | *---------------------------------------------------------------------- | |||
64 | */ | |||
65 | ||||
66 | Ns_ReturnCode | |||
67 | Ns_AuthorizeRequest(const char *server, const char *method, const char *url, | |||
68 | const char *user, const char *passwd, const char *peer) | |||
69 | { | |||
70 | Ns_ReturnCode status; | |||
71 | const NsServer *servPtr; | |||
72 | ||||
73 | NS_NONNULL_ASSERT(server != NULL)((void) (0)); | |||
74 | NS_NONNULL_ASSERT(method != NULL)((void) (0)); | |||
75 | NS_NONNULL_ASSERT(url != NULL)((void) (0)); | |||
76 | ||||
77 | servPtr = NsGetServer(server); | |||
78 | if (unlikely(servPtr == NULL)(__builtin_expect((servPtr == ((void*)0)), 0)) || servPtr->request.authProc == NULL((void*)0)) { | |||
79 | status = NS_OK; | |||
80 | } else { | |||
81 | status = (*servPtr->request.authProc)(server, method, url, user, passwd, peer); | |||
82 | } | |||
83 | return status; | |||
84 | } | |||
85 | ||||
86 | ||||
87 | /* | |||
88 | *---------------------------------------------------------------------- | |||
89 | * | |||
90 | * Ns_SetRequestAuthorizeProc -- | |||
91 | * | |||
92 | * Set the proc to call when authorizing requests. | |||
93 | * | |||
94 | * Results: | |||
95 | * None. | |||
96 | * | |||
97 | * Side effects: | |||
98 | * None. | |||
99 | * | |||
100 | *---------------------------------------------------------------------- | |||
101 | */ | |||
102 | ||||
103 | void | |||
104 | Ns_SetRequestAuthorizeProc(const char *server, Ns_RequestAuthorizeProc *procPtr) | |||
105 | { | |||
106 | NsServer *servPtr; | |||
107 | ||||
108 | NS_NONNULL_ASSERT(server != NULL)((void) (0)); | |||
109 | NS_NONNULL_ASSERT(procPtr != NULL)((void) (0)); | |||
110 | ||||
111 | servPtr = NsGetServer(server); | |||
112 | if (servPtr != NULL((void*)0)) { | |||
113 | servPtr->request.authProc = procPtr; | |||
114 | } | |||
115 | } | |||
116 | ||||
117 | ||||
118 | /* | |||
119 | *---------------------------------------------------------------------- | |||
120 | * | |||
121 | * NsTclRequestAuthorizeObjCmd -- | |||
122 | * | |||
123 | * Implements "ns_requestauthorize". | |||
124 | * | |||
125 | * Results: | |||
126 | * Tcl result. | |||
127 | * | |||
128 | * Side effects: | |||
129 | * See docs. | |||
130 | * | |||
131 | *---------------------------------------------------------------------- | |||
132 | */ | |||
133 | ||||
134 | int | |||
135 | NsTclRequestAuthorizeObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const* objv) | |||
136 | { | |||
137 | const NsInterp *itPtr = clientData; | |||
138 | int result = TCL_OK0; | |||
139 | char *method, *url, *authuser, *authpasswd, *ipaddr = NULL((void*)0); | |||
140 | Ns_ObjvSpec args[] = { | |||
141 | {"method", Ns_ObjvString, &method, NULL((void*)0)}, | |||
142 | {"url", Ns_ObjvString, &url, NULL((void*)0)}, | |||
143 | {"authuser", Ns_ObjvString, &authuser, NULL((void*)0)}, | |||
144 | {"authpasswd", Ns_ObjvString, &authpasswd, NULL((void*)0)}, | |||
145 | {"?ipaddr", Ns_ObjvString, &ipaddr, NULL((void*)0)}, | |||
146 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)} | |||
147 | }; | |||
148 | ||||
149 | if (Ns_ParseObjv(NULL((void*)0), args, interp, 1, objc, objv) != NS_OK) { | |||
150 | result = TCL_ERROR1; | |||
151 | ||||
152 | } else { | |||
153 | Ns_ReturnCode status; | |||
154 | ||||
155 | status = Ns_AuthorizeRequest(itPtr->servPtr->server, method, url, | |||
156 | authuser, authpasswd, ipaddr); | |||
157 | switch (status) { | |||
158 | case NS_OK: | |||
159 | Tcl_SetObjResult(interp, Tcl_NewStringObj("OK", 2)); | |||
160 | break; | |||
161 | ||||
162 | case NS_ERROR: | |||
163 | Tcl_SetObjResult(interp, Tcl_NewStringObj("ERROR", 5)); | |||
164 | break; | |||
165 | ||||
166 | case NS_FORBIDDEN: | |||
167 | Tcl_SetObjResult(interp, Tcl_NewStringObj("FORBIDDEN", -1)); | |||
168 | break; | |||
169 | ||||
170 | case NS_UNAUTHORIZED: | |||
171 | Tcl_SetObjResult(interp, Tcl_NewStringObj("UNAUTHORIZED", -1)); | |||
172 | break; | |||
173 | ||||
174 | case NS_FILTER_BREAK: NS_FALL_THROUGH((void)0); /* fall through */ | |||
175 | case NS_FILTER_RETURN: NS_FALL_THROUGH((void)0); /* fall through */ | |||
176 | case NS_TIMEOUT: | |||
177 | Ns_TclPrintfResult(interp, "could not authorize \"%s %s\"", | |||
178 | Tcl_GetString(objv[1]), Tcl_GetString(objv[2])); | |||
179 | result = TCL_ERROR1; | |||
180 | } | |||
181 | } | |||
182 | return result; | |||
183 | } | |||
184 | ||||
185 | ||||
186 | /* | |||
187 | *---------------------------------------------------------------------- | |||
188 | * | |||
189 | * Ns_AuthorizeUser -- | |||
190 | * | |||
191 | * Verify that a user's password matches his name. | |||
192 | * passwd is the unencrypted password. | |||
193 | * | |||
194 | * Results: | |||
195 | * NS_OK or NS_ERROR; if none registered, NS_ERROR. | |||
196 | * | |||
197 | * Side effects: | |||
198 | * Depends on the supplied routine. | |||
199 | * | |||
200 | *---------------------------------------------------------------------- | |||
201 | */ | |||
202 | ||||
203 | Ns_ReturnCode | |||
204 | Ns_AuthorizeUser(const char *user, const char *passwd) | |||
205 | { | |||
206 | Ns_ReturnCode status; | |||
207 | ||||
208 | NS_NONNULL_ASSERT(user != NULL)((void) (0)); | |||
209 | NS_NONNULL_ASSERT(passwd != NULL)((void) (0)); | |||
210 | ||||
211 | if (userProcPtr == NULL((void*)0)) { | |||
212 | status = NS_ERROR; | |||
213 | } else { | |||
214 | status = (*userProcPtr)(user, passwd); | |||
215 | } | |||
216 | return status; | |||
217 | } | |||
218 | ||||
219 | ||||
220 | /* | |||
221 | *---------------------------------------------------------------------- | |||
222 | * | |||
223 | * Ns_SetUserAuthorizeProc -- | |||
224 | * | |||
225 | * Set the proc to call when authorizing users. | |||
226 | * | |||
227 | * Results: | |||
228 | * None. | |||
229 | * | |||
230 | * Side effects: | |||
231 | * None. | |||
232 | * | |||
233 | *---------------------------------------------------------------------- | |||
234 | */ | |||
235 | ||||
236 | void | |||
237 | Ns_SetUserAuthorizeProc(Ns_UserAuthorizeProc *procPtr) | |||
238 | { | |||
239 | NS_NONNULL_ASSERT(procPtr != NULL)((void) (0)); | |||
240 | ||||
241 | userProcPtr = procPtr; | |||
242 | } | |||
243 | ||||
244 | /* | |||
245 | *---------------------------------------------------------------------- | |||
246 | * | |||
247 | * NsParseAuth -- | |||
248 | * | |||
249 | * Parse an HTTP authorization string. | |||
250 | * | |||
251 | * Results: | |||
252 | * None. | |||
253 | * | |||
254 | * Side effects: | |||
255 | * May set the auth Passwd and User connection pointers. | |||
256 | * | |||
257 | *---------------------------------------------------------------------- | |||
258 | */ | |||
259 | ||||
260 | void | |||
261 | NsParseAuth(Conn *connPtr, const char *auth) | |||
262 | { | |||
263 | register char *p; | |||
264 | Tcl_DString authDs; | |||
265 | ||||
266 | NS_NONNULL_ASSERT(connPtr != NULL)((void) (0)); | |||
267 | NS_NONNULL_ASSERT(auth != NULL)((void) (0)); | |||
268 | ||||
269 | if (connPtr->auth == NULL((void*)0)) { | |||
| ||||
270 | connPtr->auth = Ns_SetCreate(NS_SET_NAME_AUTH"auth"); | |||
271 | } | |||
272 | ||||
273 | Tcl_DStringInit(&authDs); | |||
274 | Tcl_DStringAppend(&authDs, auth, -1); | |||
275 | ||||
276 | p = authDs.string; | |||
277 | while (*p != '\0' && CHARTYPE(space, *p)(((*__ctype_b_loc ())[(int) (((int)((unsigned char)(*p))))] & (unsigned short int) _ISspace)) == 0) { | |||
278 | ++p; | |||
279 | } | |||
280 | if (*p != '\0') { | |||
281 | register char *q, *v; | |||
282 | char save; | |||
283 | ||||
284 | save = *p; | |||
285 | *p = '\0'; | |||
286 | ||||
287 | if (STRIEQ(authDs.string, "Basic")(strcasecmp((authDs.string),("Basic")) == 0)) { | |||
288 | size_t size; | |||
289 | ssize_t userLength; | |||
290 | ||||
291 | (void)Ns_SetPutSz(connPtr->auth, "AuthMethod", 10, "Basic", 5); | |||
292 | ||||
293 | /* Skip spaces */ | |||
294 | q = p + 1; | |||
295 | while (*q != '\0' && CHARTYPE(space, *q)(((*__ctype_b_loc ())[(int) (((int)((unsigned char)(*q))))] & (unsigned short int) _ISspace)) != 0) { | |||
296 | q++; | |||
297 | } | |||
298 | ||||
299 | size = strlen(q) + 3u; | |||
300 | v = ns_malloc(size); | |||
301 | size = Ns_HtuuDecode(q, (unsigned char *) v, size); | |||
302 | v[size] = '\0'; | |||
303 | ||||
304 | q = strchr(v, INTCHAR(':')((int)((unsigned char)((':'))))); | |||
305 | if (q != NULL((void*)0)) { | |||
306 | ssize_t pwLength; | |||
307 | ||||
308 | *q++ = '\0'; | |||
309 | pwLength = ((v+size) - q); | |||
310 | (void)Ns_SetPutSz(connPtr->auth, "Password", 8, q, pwLength); | |||
311 | userLength = (ssize_t)size - (pwLength + 1); | |||
312 | } else { | |||
313 | userLength = (ssize_t)size; | |||
314 | } | |||
315 | (void)Ns_SetPutSz(connPtr->auth, "Username", 8, v, userLength); | |||
316 | ns_free(v); | |||
317 | ||||
318 | } else if (STRIEQ(authDs.string, "Digest")(strcasecmp((authDs.string),("Digest")) == 0)) { | |||
319 | (void)Ns_SetPutSz(connPtr->auth, "AuthMethod", 10, "Digest", 6); | |||
320 | ||||
321 | /* Skip spaces */ | |||
322 | q = p + 1; | |||
323 | while (*q != '\0' && CHARTYPE(space, *q)(((*__ctype_b_loc ())[(int) (((int)((unsigned char)(*q))))] & (unsigned short int) _ISspace)) != 0) { | |||
324 | q++; | |||
325 | } | |||
326 | ||||
327 | while (*q != '\0') { | |||
328 | size_t idx; | |||
329 | char save2; | |||
330 | ||||
331 | p = strchr(q, INTCHAR('=')((int)((unsigned char)(('='))))); | |||
332 | if (p == NULL((void*)0)) { | |||
333 | break; | |||
334 | } | |||
335 | v = p - 1; | |||
336 | /* Trim trailing spaces */ | |||
337 | while (v > q && CHARTYPE(space, *v)(((*__ctype_b_loc ())[(int) (((int)((unsigned char)(*v))))] & (unsigned short int) _ISspace)) != 0) { | |||
| ||||
338 | v--; | |||
339 | } | |||
340 | /* Remember position */ | |||
341 | save2 = *(++v); | |||
342 | *v = '\0'; | |||
343 | idx = Ns_SetPutSz(connPtr->auth, q, (ssize_t)(v-q), NULL((void*)0), 0); | |||
344 | /* Restore character */ | |||
345 | *v = save2; | |||
346 | /* Skip = and optional spaces */ | |||
347 | p++; | |||
348 | while (*p != '\0' && CHARTYPE(space, *p)(((*__ctype_b_loc ())[(int) (((int)((unsigned char)(*p))))] & (unsigned short int) _ISspace)) != 0) { | |||
349 | p++; | |||
350 | } | |||
351 | if (*p == '\0') { | |||
352 | break; | |||
353 | } | |||
354 | /* Find end of the value, deal with quotes strings */ | |||
355 | if (*p == '"') { | |||
356 | for (q = ++p; *q != '\0' && *q != '"'; q++) { | |||
357 | ; | |||
358 | } | |||
359 | } else { | |||
360 | for (q = p; *q != '\0' && *q != ',' && CHARTYPE(space, *q)(((*__ctype_b_loc ())[(int) (((int)((unsigned char)(*q))))] & (unsigned short int) _ISspace)) == 0; q++) { | |||
361 | ; | |||
362 | } | |||
363 | } | |||
364 | save2 = *q; | |||
365 | *q = '\0'; | |||
366 | /* Update with current value */ | |||
367 | Ns_SetPutValueSz(connPtr->auth, idx, p, -1); | |||
368 | *q = save2; | |||
369 | /* Advance to the end of the param value, can be end or next name*/ | |||
370 | while (*q != '\0' && (*q == ',' || *q == '"' || CHARTYPE(space, *q)(((*__ctype_b_loc ())[(int) (((int)((unsigned char)(*q))))] & (unsigned short int) _ISspace)) != 0)) { | |||
371 | q++; | |||
372 | } | |||
373 | } | |||
374 | } else if (STRIEQ(authDs.string, "Bearer")(strcasecmp((authDs.string),("Bearer")) == 0)) { | |||
375 | ||||
376 | (void)Ns_SetPutSz(connPtr->auth, "AuthMethod", 10, "Bearer", 6); | |||
377 | ||||
378 | /* Skip spaces */ | |||
379 | q = p + 1; | |||
380 | while (*q != '\0' && CHARTYPE(space, *q)(((*__ctype_b_loc ())[(int) (((int)((unsigned char)(*q))))] & (unsigned short int) _ISspace)) != 0) { | |||
381 | q++; | |||
382 | } | |||
383 | (void)Ns_SetPutSz(connPtr->auth, "Token", 5, q, authDs.length - (q - authDs.string)); | |||
384 | } | |||
385 | if (p != NULL((void*)0)) { | |||
386 | *p = save; | |||
387 | } | |||
388 | } | |||
389 | Tcl_DStringFree(&authDs); | |||
390 | } | |||
391 | ||||
392 | /* | |||
393 | * Local Variables: | |||
394 | * mode: c | |||
395 | * c-basic-offset: 4 | |||
396 | * fill-column: 78 | |||
397 | * indent-tabs-mode: nil | |||
398 | * End: | |||
399 | */ |