Annotation of libwww/Library/src/HTAAUtil.c, revision 2.26
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.26 ! frystyk 7: ** @(#) $Id: HTAAUtil.c,v 2.25 1996/08/05 17:22:03 frystyk 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.20 frystyk 31: #include "sysdep.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.23 frystyk 42: HTNetCallback * before;
43: HTNetCallback * after;
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,
82: HTNetCallback * before,
83: HTNetCallback * after,
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: /*
177: ** If the new scheme differs from the existing one then use the
178: ** new context, otherwise only override the old context if new
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: /*
186: ** If the old scheme differs from the new one then delete our
187: ** context by calling the gc provided by the caller
188: */
189: if (strcmp(element->scheme, scheme)) {
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;
198: } else if (context && context != element->context)
199: element->context = context;
2.23 frystyk 200: return YES;
2.19 frystyk 201: }
202: return NO;
203: }
2.1 luotonen 204:
2.23 frystyk 205: PRIVATE int HTAA_deleteElement (void * context)
2.19 frystyk 206: {
2.23 frystyk 207: HTAAElement * me = (HTAAElement *) context;
208: if (me) {
209: HTAAModule * module = HTAA_findModule(me->scheme);
2.1 luotonen 210:
2.23 frystyk 211: /* If module then call the gc of the Authentication Module */
212: if (module && module->gc && me->context)
213: (*module->gc)(me->context);
2.1 luotonen 214:
2.23 frystyk 215: if (AUTH_TRACE) HTTrace("Auth Engine. Deleted element %p\n", me);
216: HT_FREE(me->scheme);
217: HT_FREE(me);
2.19 frystyk 218: return YES;
219: }
220: return NO;
221: }
2.1 luotonen 222:
223: /*
2.23 frystyk 224: ** Find AA Element
225: ** ---------------
226: ** Seaches the set of authentication information bases for a match
227: ** In order to find an anode we do the following:
228: **
229: ** 1) Find the right auth base
230: ** 2) See if there is a realm match
231: ** 3) See if there is a template match for URL
232: **
233: ** Return the node found else NULL which means that we don't have any
234: ** authentication information to hook on to this request or response
2.1 luotonen 235: */
2.26 ! frystyk 236: PRIVATE HTAAElement * HTAA_findElement (BOOL proxy_access,
! 237: const char * realm, const char * url)
2.19 frystyk 238: {
2.23 frystyk 239: HTUTree * tree;
240: if (!url) {
241: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
242: return NULL;
2.19 frystyk 243: }
2.23 frystyk 244: if (AUTH_TRACE) HTTrace("Auth Engine. Looking up `%s'\n", url);
2.19 frystyk 245:
2.23 frystyk 246: /* Find an existing URL Tree for this URL (if any) */
2.19 frystyk 247: {
248: char * host = HTParse(url, "", PARSE_HOST);
249: char * colon = strchr(host, ':');
2.23 frystyk 250: int port = DEFAULT_PORT;
2.19 frystyk 251: if (colon ) {
252: *(colon++) = '\0'; /* Chop off port number */
253: port = atoi(colon);
2.23 frystyk 254: }
2.26 ! frystyk 255: tree = HTUTree_find(proxy_access ? AA_PROXY_TREE : AA_TREE, host,port);
2.23 frystyk 256: HT_FREE(host);
257: if (!tree) {
258: if (AUTH_TRACE) HTTrace("Auth Engine. No information\n");
259: return NULL;
2.19 frystyk 260: }
261: }
2.1 luotonen 262:
2.23 frystyk 263: /* Find a matching AA element (if any) */
2.19 frystyk 264: {
2.23 frystyk 265: char * path = HTParse(url, "", PARSE_PATH);
266: HTAAElement *element = (HTAAElement*)HTUTree_findNode(tree,realm,path);
267: HT_FREE(path);
268: return element;
2.19 frystyk 269: }
2.23 frystyk 270: return NULL;
2.19 frystyk 271: }
272:
2.23 frystyk 273: /* Add a AA context to the URL tree
274: ** --------------------------------
275: ** Each node in the AA URL tree is a list of the modules we must call
276: ** for this particular node.
277: */
2.26 ! frystyk 278: PUBLIC void * HTAA_updateNode (BOOL proxy_access, char const * scheme,
2.24 frystyk 279: const char * realm, const char * url,
280: void * context)
2.23 frystyk 281: {
282: HTUTree * tree = NULL;
283: HTAAModule * module = NULL;
284: if (!scheme || !url) {
285: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
2.24 frystyk 286: return NULL;
2.23 frystyk 287: }
288: if (AUTH_TRACE) HTTrace("Auth Engine. Adding info for `%s'\n", url);
289:
290: /* Find the AA module with this name */
291: if ((module = HTAA_findModule(scheme)) == NULL) {
292: if (AUTH_TRACE) HTTrace("Auth Engine. Module `%s\' not registered\n",
293: scheme ? scheme : "<null>");
2.24 frystyk 294: return NULL;
2.19 frystyk 295: }
296:
2.23 frystyk 297: /* Find an existing URL Tree or create a new one */
2.19 frystyk 298: {
299: char * host = HTParse(url, "", PARSE_HOST);
300: char * colon = strchr(host, ':');
2.23 frystyk 301: int port = DEFAULT_PORT;
2.19 frystyk 302: if (colon ) {
303: *(colon++) = '\0'; /* Chop off port number */
304: port = atoi(colon);
2.23 frystyk 305: }
2.26 ! frystyk 306: tree = HTUTree_new(proxy_access ? AA_PROXY_TREE : AA_TREE,
! 307: host, port, HTAA_deleteElement);
2.19 frystyk 308: HT_FREE(host);
2.23 frystyk 309: if (!tree) {
310: if (AUTH_TRACE) HTTrace("Auth Engine. Can't create tree\n");
2.24 frystyk 311: return NULL;
2.19 frystyk 312: }
313: }
314:
2.23 frystyk 315: /* Find a matching AA element or create a new one */
2.19 frystyk 316: {
2.23 frystyk 317: char * path = HTParse(url, "", PARSE_PATH);
318: HTAAElement * element = NULL;
319: BOOL status;
320: if ((element = (HTAAElement *) HTUTree_findNode(tree, realm, path)))
321: status = HTAA_updateElement(element, scheme, context);
322: else {
323: element = HTAA_newElement(scheme, context);
324: status = HTUTree_addNode(tree, realm, path, element);
325: }
326: HT_FREE(path);
2.24 frystyk 327: return status==YES ? element->context : NULL;
2.19 frystyk 328: }
329: }
330:
331: /* ------------------------------------------------------------------------- */
2.23 frystyk 332: /* AUTHENTICATION ENGINE */
2.19 frystyk 333: /* ------------------------------------------------------------------------- */
334:
2.23 frystyk 335: /* HTAA_beforeFilter
336: ** ------------------
2.24 frystyk 337: ** Make a lookup in the URL tree to find any context for this node,
338: ** If no context is found then we assume that we don't know anything about
339: ** this URL and hence we don't call any BEFORE filters at all.
2.23 frystyk 340: ** Return HT_OK or whatever callback returns
2.19 frystyk 341: */
2.23 frystyk 342: PUBLIC int HTAA_beforeFilter (HTRequest * request, void * param, int status)
2.19 frystyk 343: {
2.25 frystyk 344: char * url = HTAnchor_address((HTAnchor *) HTRequest_anchor(request));
2.23 frystyk 345: const char * realm = HTRequest_realm(request);
2.26 ! frystyk 346: HTAAElement * element = HTAA_findElement(NO, realm, url);
2.25 frystyk 347: HT_FREE(url);
2.23 frystyk 348:
2.26 ! frystyk 349: /* If we have an element then call the before filter with this scheme */
2.23 frystyk 350: if (element) {
351: HTAAModule * module = HTAA_findModule(element->scheme);
352: if (module) {
2.26 ! frystyk 353:
! 354: /* Delete any old challenges if any */
2.24 frystyk 355: HTRequest_deleteChallenge(request);
2.23 frystyk 356: if (AUTH_TRACE) HTTrace("Auth Engine. Found BEFORE filter %p\n",
357: module->before);
358: return (*module->before)(request, element->context,status);
2.19 frystyk 359: }
360: }
2.23 frystyk 361: return HT_OK;
2.19 frystyk 362: }
363:
2.23 frystyk 364: /* HTAA_afterFilter
365: ** -----------------
2.24 frystyk 366: ** Call the AFTER filter that knows how to handle this scheme.
2.19 frystyk 367: ** Return YES or whatever callback returns
368: */
2.23 frystyk 369: PUBLIC BOOL HTAA_afterFilter (HTRequest * request, void * param, int status)
2.19 frystyk 370: {
2.23 frystyk 371: const char * scheme = HTRequest_scheme(request);
2.24 frystyk 372: HTAAModule * module = NULL;
373: /*
374: ** If we don't have a scheme then the server has made an error. We
375: ** try to make up for it by creating our own "noop" realm and use basic.
376: */
377: if (!scheme) {
378: HTRequest_addChallenge(request, "basic", "realm UNKNOWN");
379: scheme = "basic";
380: }
381: if ((module = HTAA_findModule(scheme)) != NULL) {
2.23 frystyk 382: if (AUTH_TRACE)
383: HTTrace("Auth Engine. Found AFTER filter %p\n", module->after);
2.24 frystyk 384: HTRequest_deleteCredentials(request);
2.23 frystyk 385: return (*module->after)(request, NULL, status);
2.19 frystyk 386: }
2.24 frystyk 387: return HT_ERROR;
2.26 ! frystyk 388: }
! 389:
! 390: /* HTAA_proxybeforeFilter
! 391: ** ----------------------
! 392: ** Make a lookup in the proxy URL tree to find any context for this node,
! 393: ** If no context is found then we assume that we don't know anything about
! 394: ** this URL and hence we don't call any BEFORE filters at all.
! 395: ** Return HT_OK or whatever callback returns
! 396: */
! 397: PUBLIC int HTAA_proxyBeforeFilter (HTRequest * request, void * param, int status)
! 398: {
! 399: char * url = HTRequest_proxy(request);
! 400: const char * realm = HTRequest_realm(request);
! 401: HTAAElement * element = HTAA_findElement(YES, realm, url);
! 402:
! 403: /* If we have an element then call the before filter with this scheme */
! 404: if (element) {
! 405: HTAAModule * module = HTAA_findModule(element->scheme);
! 406: if (module) {
! 407:
! 408: /* Delete any old challenges if any */
! 409: HTRequest_deleteChallenge(request);
! 410: if (AUTH_TRACE) HTTrace("Auth Engine. Found BEFORE filter %p\n",
! 411: module->before);
! 412: return (*module->before)(request, element->context,status);
! 413: }
! 414: }
! 415: return HT_OK;
2.19 frystyk 416: }
Webmaster