| 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 | */ |