Annotation of libwww/Library/src/HTAAUtil.c, revision 2.32
2.23 frystyk 1: /*
2.9 frystyk 2: ** COMMON PARTS OF ACCESS AUTHORIZATION MODULE
3: ** FOR BOTH SERVER AND BROWSER
4: **
2.13 frystyk 5: ** (c) COPYRIGHT MIT 1995.
2.9 frystyk 6: ** Please first read the full copyright statement in the file COPYRIGH.
2.32 ! kahan 7: ** @(#) $Id: HTAAUtil.c,v 1.3 1998/10/08 18:13:49 cvs Exp $
2.1 luotonen 8: **
2.19 frystyk 9: ** The authentication information is stored in a list of authentication
10: ** data bases, each uniquely identified by a hostname and a port number.
11: ** Each data base contains a set of templates which can be used to predict
12: ** what information to use in a hierarchical tree. All authentication
13: ** dependent information is stored as opaque data in a anode. Normally
14: ** a server application would only keep one auth base but if it wants
15: ** different protection setup as a function of different interfaces then
16: ** it can have one auth base representing each interface. For example a
17: ** server with interfaces "www.foo.com" and "internal.foo.com" can have
18: ** different protection setups for each interface.
2.1 luotonen 19: **
20: ** AUTHORS:
21: ** AL Ari Luotonen luotonen@dxcern.cern.ch
2.3 duns 22: ** MD Mark Donszelmann duns@vxdeop.cern.ch
2.19 frystyk 23: ** HFN Henrik Frystyk
2.1 luotonen 24: **
25: ** HISTORY:
2.4 luotonen 26: ** 8 Nov 93 MD (VMS only) Added case insensitive comparison
27: ** in HTAA_templateCaseMatch
2.1 luotonen 28: */
29:
2.11 frystyk 30: /* Library include files */
2.30 frystyk 31: #include "wwwsys.h"
2.23 frystyk 32: #include "WWWUtil.h"
33: #include "WWWCore.h"
2.19 frystyk 34: #include "HTAAUtil.h" /* Implemented here */
35:
2.26 frystyk 36: #define AA_TREE "w3c-AA" /* Name of the AA tree */
37: #define AA_PROXY_TREE "w3c-proxy-AA" /* Name of the proxy AA tree */
2.23 frystyk 38: #define DEFAULT_PORT 80 /* Concentrate on HTTP */
39:
40: struct _HTAAModule {
2.19 frystyk 41: char * scheme;
2.29 frystyk 42: HTNetBefore * before;
43: HTNetAfter * after;
2.23 frystyk 44: HTUTree_gc * gc;
45: };
46:
47: typedef struct _HTAAElement {
48: char * scheme;
49: void * context;
50: } HTAAElement;
2.19 frystyk 51:
52: PRIVATE HTList * HTSchemes; /* List of registered authentication schemes */
53:
54: /* ------------------------------------------------------------------------- */
2.23 frystyk 55: /* AUTHENTICATION MODULE MANAGEMENT */
2.19 frystyk 56: /* ------------------------------------------------------------------------- */
57:
2.23 frystyk 58: PRIVATE BOOL delete_module (HTAAModule * module)
2.19 frystyk 59: {
2.23 frystyk 60: if (module) {
61: HT_FREE(module->scheme);
62: HT_FREE(module);
63: return YES;
2.19 frystyk 64: }
65: return NO;
66: }
2.1 luotonen 67:
2.23 frystyk 68: PRIVATE HTAAModule * find_module (const char * scheme)
2.19 frystyk 69: {
2.23 frystyk 70: if (!HTSchemes) HTSchemes = HTList_new();
71: if (scheme) {
72: HTList * cur = HTSchemes;
73: HTAAModule * pres = NULL;
74: while ((pres = (HTAAModule *) HTList_nextObject(cur)))
75: if (!strcasecomp(pres->scheme, scheme)) return pres;
76: } else
77: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
78: return NULL;
2.19 frystyk 79: }
2.1 luotonen 80:
2.23 frystyk 81: PUBLIC HTAAModule * HTAA_newModule (const char * scheme,
2.29 frystyk 82: HTNetBefore * before,
83: HTNetAfter * after,
2.23 frystyk 84: HTUTree_gc * gc)
85: {
86: if (scheme) {
87: HTAAModule * pres = find_module(scheme);
88:
89: /* If found then update entry - else create a new one */
90: if (!pres) {
91: if (!(pres = (HTAAModule *) HT_CALLOC(1, sizeof(HTAAModule))))
92: HT_OUTOFMEM("HTAA_newModule");
93: StrAllocCopy(pres->scheme, scheme);
94: pres->before = before;
95: pres->after = after;
96: pres->gc = gc;
97:
98: /* Add the new AA Module to the list */
99: HTList_addObject(HTSchemes, (void *) pres);
100: if (AUTH_TRACE) HTTrace("Auth Engine. Created module %p\n", pres);
101: } else {
102: if (AUTH_TRACE) HTTrace("Auth Engine. Found module %p\n", pres);
2.19 frystyk 103: }
2.23 frystyk 104: return pres;
105: } else {
106: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
107: return NULL;
2.19 frystyk 108: }
109: }
2.1 luotonen 110:
2.23 frystyk 111: PUBLIC HTAAModule * HTAA_findModule (const char * scheme)
2.19 frystyk 112: {
2.23 frystyk 113: if (scheme) {
114: HTAAModule * pres = find_module(scheme);
115: if (AUTH_TRACE)
116: HTTrace("Auth Engine. did %sfind %s\n", pres ? "" : "NOT ",scheme);
117: return pres;
118: } else {
119: if (AUTH_TRACE) HTTrace("Auth Engine. Bad augument\n");
2.19 frystyk 120: }
121: return NULL;
122: }
2.1 luotonen 123:
2.23 frystyk 124: PUBLIC BOOL HTAA_deleteModule (const char * scheme)
2.19 frystyk 125: {
2.23 frystyk 126: if (scheme) {
127: HTAAModule * pres = find_module(scheme);
128: if (pres) {
129: HTList_removeObject(HTSchemes, pres);
130: if (AUTH_TRACE) HTTrace("Auth Engine. deleted %p\n", pres);
131: delete_module(pres);
132: return YES;
133: }
2.1 luotonen 134: }
2.19 frystyk 135: return NO;
2.1 luotonen 136: }
137:
2.23 frystyk 138: PUBLIC BOOL HTAA_deleteAllModules (void)
2.19 frystyk 139: {
2.23 frystyk 140: if (HTSchemes) {
141: HTList * cur = HTSchemes;
142: HTAAModule * pres;
143: while ((pres = (HTAAModule *) HTList_nextObject(cur)))
144: delete_module(pres);
145: HTList_delete(HTSchemes);
146: HTSchemes = NULL;
2.19 frystyk 147: return YES;
148: }
149: return NO;
150: }
2.1 luotonen 151:
2.23 frystyk 152: /* ------------------------------------------------------------------------- */
153: /* HANDLE THE AA URL TREE */
154: /* ------------------------------------------------------------------------- */
155:
2.19 frystyk 156: /*
2.23 frystyk 157: ** A AA element is a particular AA procotol associated with a
158: ** particular point in the URL tree. The scheme is the name of the
159: ** AA protocol known to be able to handle this context. This protocol
160: ** must have been registered as a AA module.
161: */
162: PRIVATE HTAAElement * HTAA_newElement (const char * scheme, void * context)
163: {
164: if (scheme) {
165: HTAAElement * me;
166: if ((me = (HTAAElement *) HT_CALLOC(1, sizeof(HTAAElement))) == NULL)
167: HT_OUTOFMEM("HTAAElement_new");
168: StrAllocCopy(me->scheme, scheme);
169: me->context = context;
170: if (AUTH_TRACE) HTTrace("Auth Engine. Created element %p\n", me);
171: return me;
2.19 frystyk 172: }
173: return NULL;
174: }
2.1 luotonen 175:
2.24 frystyk 176: /*
2.27 frystyk 177: ** If the new context differs from the existing one then use the
178: ** new one, otherwise only override the old context if new
2.24 frystyk 179: ** one differs from NULL
180: */
2.23 frystyk 181: PRIVATE BOOL HTAA_updateElement (HTAAElement * element,
182: const char * scheme, void * context)
2.19 frystyk 183: {
2.23 frystyk 184: if (element && scheme) {
2.24 frystyk 185: /*
2.27 frystyk 186: ** If the old context differs from the new one then
187: ** call the gc provided by the caller
2.24 frystyk 188: */
2.27 frystyk 189: if (context && context != element->context) {
2.24 frystyk 190: HTAAModule * module = HTAA_findModule(element->scheme);
191: if (module && module->gc && element->context)
192: (*module->gc)(element->context);
193: /*
194: ** Insert the new scheme
195: */
196: StrAllocCopy(element->scheme, scheme);
197: element->context = context;
2.27 frystyk 198: }
2.23 frystyk 199: return YES;
2.19 frystyk 200: }
201: return NO;
202: }
2.1 luotonen 203:
2.23 frystyk 204: PRIVATE int HTAA_deleteElement (void * context)
2.19 frystyk 205: {
2.23 frystyk 206: HTAAElement * me = (HTAAElement *) context;
207: if (me) {
208: HTAAModule * module = HTAA_findModule(me->scheme);
2.1 luotonen 209:
2.23 frystyk 210: /* If module then call the gc of the Authentication Module */
211: if (module && module->gc && me->context)
212: (*module->gc)(me->context);
2.1 luotonen 213:
2.23 frystyk 214: if (AUTH_TRACE) HTTrace("Auth Engine. Deleted element %p\n", me);
215: HT_FREE(me->scheme);
216: HT_FREE(me);
2.19 frystyk 217: return YES;
218: }
219: return NO;
220: }
2.1 luotonen 221:
222: /*
2.23 frystyk 223: ** Find AA Element
224: ** ---------------
225: ** Seaches the set of authentication information bases for a match
226: ** In order to find an anode we do the following:
227: **
228: ** 1) Find the right auth base
229: ** 2) See if there is a realm match
230: ** 3) See if there is a template match for URL
231: **
232: ** Return the node found else NULL which means that we don't have any
233: ** authentication information to hook on to this request or response
2.1 luotonen 234: */
2.26 frystyk 235: PRIVATE HTAAElement * HTAA_findElement (BOOL proxy_access,
236: const char * realm, const char * url)
2.19 frystyk 237: {
2.23 frystyk 238: HTUTree * tree;
239: if (!url) {
240: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
241: return NULL;
2.19 frystyk 242: }
2.23 frystyk 243: if (AUTH_TRACE) HTTrace("Auth Engine. Looking up `%s'\n", url);
2.19 frystyk 244:
2.23 frystyk 245: /* Find an existing URL Tree for this URL (if any) */
2.19 frystyk 246: {
247: char * host = HTParse(url, "", PARSE_HOST);
248: char * colon = strchr(host, ':');
2.23 frystyk 249: int port = DEFAULT_PORT;
2.19 frystyk 250: if (colon ) {
251: *(colon++) = '\0'; /* Chop off port number */
252: port = atoi(colon);
2.23 frystyk 253: }
2.26 frystyk 254: tree = HTUTree_find(proxy_access ? AA_PROXY_TREE : AA_TREE, host,port);
2.23 frystyk 255: HT_FREE(host);
256: if (!tree) {
257: if (AUTH_TRACE) HTTrace("Auth Engine. No information\n");
258: return NULL;
2.19 frystyk 259: }
260: }
2.1 luotonen 261:
2.23 frystyk 262: /* Find a matching AA element (if any) */
2.19 frystyk 263: {
2.28 frystyk 264: char * path = HTParse(url, "", PARSE_PATH | PARSE_PUNCTUATION);
2.23 frystyk 265: HTAAElement *element = (HTAAElement*)HTUTree_findNode(tree,realm,path);
266: HT_FREE(path);
267: return element;
2.19 frystyk 268: }
2.23 frystyk 269: return NULL;
2.19 frystyk 270: }
271:
2.23 frystyk 272: /* Add a AA context to the URL tree
273: ** --------------------------------
274: ** Each node in the AA URL tree is a list of the modules we must call
275: ** for this particular node.
276: */
2.26 frystyk 277: PUBLIC void * HTAA_updateNode (BOOL proxy_access, char const * scheme,
2.24 frystyk 278: const char * realm, const char * url,
279: void * context)
2.23 frystyk 280: {
281: HTUTree * tree = NULL;
282: HTAAModule * module = NULL;
283: if (!scheme || !url) {
284: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
2.24 frystyk 285: return NULL;
2.23 frystyk 286: }
287: if (AUTH_TRACE) HTTrace("Auth Engine. Adding info for `%s'\n", url);
288:
289: /* Find the AA module with this name */
290: if ((module = HTAA_findModule(scheme)) == NULL) {
291: if (AUTH_TRACE) HTTrace("Auth Engine. Module `%s\' not registered\n",
292: scheme ? scheme : "<null>");
2.24 frystyk 293: return NULL;
2.19 frystyk 294: }
295:
2.23 frystyk 296: /* Find an existing URL Tree or create a new one */
2.19 frystyk 297: {
298: char * host = HTParse(url, "", PARSE_HOST);
299: char * colon = strchr(host, ':');
2.23 frystyk 300: int port = DEFAULT_PORT;
2.19 frystyk 301: if (colon ) {
302: *(colon++) = '\0'; /* Chop off port number */
303: port = atoi(colon);
2.23 frystyk 304: }
2.26 frystyk 305: tree = HTUTree_new(proxy_access ? AA_PROXY_TREE : AA_TREE,
306: host, port, HTAA_deleteElement);
2.19 frystyk 307: HT_FREE(host);
2.23 frystyk 308: if (!tree) {
309: if (AUTH_TRACE) HTTrace("Auth Engine. Can't create tree\n");
2.24 frystyk 310: return NULL;
2.19 frystyk 311: }
312: }
313:
2.23 frystyk 314: /* Find a matching AA element or create a new one */
2.19 frystyk 315: {
2.28 frystyk 316: char * path = HTParse(url, "", PARSE_PATH | PARSE_PUNCTUATION);
2.23 frystyk 317: HTAAElement * element = NULL;
318: BOOL status;
319: if ((element = (HTAAElement *) HTUTree_findNode(tree, realm, path)))
320: status = HTAA_updateElement(element, scheme, context);
321: else {
2.32 ! kahan 322: /* create the new element */
! 323: element = HTAA_newElement(scheme, context);
! 324: status = HTUTree_addNode(tree, realm, path, element);
2.23 frystyk 325: }
326: HT_FREE(path);
2.24 frystyk 327: return status==YES ? element->context : NULL;
2.31 frystyk 328: }
329: }
330:
331: /* Delete a AA context from the URL tree
332: ** -------------------------------------
333: ** Each node in the AA URL tree is a list of the modules we must call
334: ** for this particular node.
335: */
336: PUBLIC BOOL HTAA_deleteNode (BOOL proxy_access, char const * scheme,
337: const char * realm, const char * url)
338: {
339: HTUTree * tree = NULL;
340: HTAAModule * module = NULL;
341: if (!scheme || !url) {
342: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
343: return NO;
344: }
345: if (AUTH_TRACE) HTTrace("Auth Engine. Deleting info for `%s'\n", url);
346:
347: /* Find the AA module with this name */
348: if ((module = HTAA_findModule(scheme)) == NULL) {
349: if (AUTH_TRACE) HTTrace("Auth Engine. Module `%s\' not registered\n",
350: scheme ? scheme : "<null>");
351: return NO;
352: }
353:
354: /* Find an existing URL Tree or create a new one */
355: {
356: char * host = HTParse(url, "", PARSE_HOST);
357: char * colon = strchr(host, ':');
358: int port = DEFAULT_PORT;
359: if (colon ) {
360: *(colon++) = '\0'; /* Chop off port number */
361: port = atoi(colon);
362: }
363: tree = HTUTree_new(proxy_access ? AA_PROXY_TREE : AA_TREE,
364: host, port, HTAA_deleteElement);
365: HT_FREE(host);
366: if (!tree) {
367: if (AUTH_TRACE) HTTrace("Auth Engine. Can't create tree\n");
368: return NO;
369: }
370: }
371:
372: /* Delete any existing node */
373: {
374: char * path = HTParse(url, "", PARSE_PATH | PARSE_PUNCTUATION);
375: BOOL status = HTUTree_deleteNode(tree, realm, path);
376: HT_FREE(path);
377: return status;
2.19 frystyk 378: }
379: }
380:
381: /* ------------------------------------------------------------------------- */
2.23 frystyk 382: /* AUTHENTICATION ENGINE */
2.19 frystyk 383: /* ------------------------------------------------------------------------- */
384:
2.23 frystyk 385: /* HTAA_beforeFilter
386: ** ------------------
2.24 frystyk 387: ** Make a lookup in the URL tree to find any context for this node,
388: ** If no context is found then we assume that we don't know anything about
389: ** this URL and hence we don't call any BEFORE filters at all.
2.23 frystyk 390: ** Return HT_OK or whatever callback returns
2.19 frystyk 391: */
2.29 frystyk 392: PUBLIC int HTAA_beforeFilter (HTRequest * request, void * param, int mode)
2.19 frystyk 393: {
2.25 frystyk 394: char * url = HTAnchor_address((HTAnchor *) HTRequest_anchor(request));
2.23 frystyk 395: const char * realm = HTRequest_realm(request);
2.26 frystyk 396: HTAAElement * element = HTAA_findElement(NO, realm, url);
2.25 frystyk 397: HT_FREE(url);
2.23 frystyk 398:
2.26 frystyk 399: /* If we have an element then call the before filter with this scheme */
2.23 frystyk 400: if (element) {
401: HTAAModule * module = HTAA_findModule(element->scheme);
402: if (module) {
403: if (AUTH_TRACE) HTTrace("Auth Engine. Found BEFORE filter %p\n",
2.29 frystyk 404: module->before);
405: return (*module->before)(request, element->context, mode);
2.19 frystyk 406: }
407: }
2.23 frystyk 408: return HT_OK;
2.19 frystyk 409: }
410:
2.23 frystyk 411: /* HTAA_afterFilter
412: ** -----------------
2.24 frystyk 413: ** Call the AFTER filter that knows how to handle this scheme.
2.19 frystyk 414: ** Return YES or whatever callback returns
415: */
2.29 frystyk 416: PUBLIC int HTAA_afterFilter (HTRequest * request, HTResponse * response,
417: void * param, int status)
2.19 frystyk 418: {
2.29 frystyk 419: const char * scheme = HTResponse_scheme(response);
2.24 frystyk 420: HTAAModule * module = NULL;
2.27 frystyk 421: if (AUTH_TRACE) HTTrace("Auth Engine. After filter status %d\n", status);
2.24 frystyk 422: /*
423: ** If we don't have a scheme then the server has made an error. We
424: ** try to make up for it by creating our own "noop" realm and use basic.
425: */
426: if (!scheme) {
2.29 frystyk 427: HTResponse_addChallenge(response, "basic", "realm LIBWWW-UNKNOWN");
2.24 frystyk 428: scheme = "basic";
429: }
430: if ((module = HTAA_findModule(scheme)) != NULL) {
2.23 frystyk 431: if (AUTH_TRACE)
432: HTTrace("Auth Engine. Found AFTER filter %p\n", module->after);
2.29 frystyk 433: HTRequest_deleteCredentialsAll(request);
2.32 ! kahan 434: HTRequest_addAARetry (request);
2.29 frystyk 435: return (*module->after)(request, response, NULL, status);
2.19 frystyk 436: }
2.24 frystyk 437: return HT_ERROR;
2.26 frystyk 438: }
439:
440: /* HTAA_proxybeforeFilter
441: ** ----------------------
442: ** Make a lookup in the proxy URL tree to find any context for this node,
443: ** If no context is found then we assume that we don't know anything about
444: ** this URL and hence we don't call any BEFORE filters at all.
445: ** Return HT_OK or whatever callback returns
446: */
2.29 frystyk 447: PUBLIC int HTAA_proxyBeforeFilter (HTRequest * request, void * param, int mode)
2.26 frystyk 448: {
449: char * url = HTRequest_proxy(request);
450:
2.27 frystyk 451: /*
452: ** We may not have a proxy - for example if it has been disabled for this
453: ** request or it isn't a proxied access method.
454: */
455: if (url) {
456: const char * realm = HTRequest_realm(request);
457: HTAAElement * element = HTAA_findElement(YES, realm, url);
458:
459: /* If we have an element then call the before filter with the scheme */
460: if (element) {
461: HTAAModule * module = HTAA_findModule(element->scheme);
462: if (module) {
463: if (AUTH_TRACE)
464: HTTrace("Auth Engine. Found Proxy BEFORE filter %p with context %p\n",
465: module->before, element->context);
466: return (*module->before)(request, element->context, HT_NO_PROXY_ACCESS);
467: }
2.26 frystyk 468: }
469: }
470: return HT_OK;
2.19 frystyk 471: }
Webmaster