Annotation of libwww/Library/src/HTAAUtil.c, revision 2.24
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.24 ! frystyk 7: ** @(#) $Id: HTAAUtil.c,v 2.23 1996/07/08 19:10:37 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.23 frystyk 36: #define AA_NAME "w3c-AA" /* Name of the AA tree */
37: #define DEFAULT_PORT 80 /* Concentrate on HTTP */
38:
39: struct _HTAAModule {
2.19 frystyk 40: char * scheme;
2.23 frystyk 41: HTNetCallback * before;
42: HTNetCallback * after;
43: HTUTree_gc * gc;
44: };
45:
46: typedef struct _HTAAElement {
47: char * scheme;
48: void * context;
49: } HTAAElement;
2.19 frystyk 50:
51: PRIVATE HTList * HTSchemes; /* List of registered authentication schemes */
52:
53: /* ------------------------------------------------------------------------- */
2.23 frystyk 54: /* AUTHENTICATION MODULE MANAGEMENT */
2.19 frystyk 55: /* ------------------------------------------------------------------------- */
56:
2.23 frystyk 57: PRIVATE BOOL delete_module (HTAAModule * module)
2.19 frystyk 58: {
2.23 frystyk 59: if (module) {
60: HT_FREE(module->scheme);
61: HT_FREE(module);
62: return YES;
2.19 frystyk 63: }
64: return NO;
65: }
2.1 luotonen 66:
2.23 frystyk 67: PRIVATE HTAAModule * find_module (const char * scheme)
2.19 frystyk 68: {
2.23 frystyk 69: if (!HTSchemes) HTSchemes = HTList_new();
70: if (scheme) {
71: HTList * cur = HTSchemes;
72: HTAAModule * pres = NULL;
73: while ((pres = (HTAAModule *) HTList_nextObject(cur)))
74: if (!strcasecomp(pres->scheme, scheme)) return pres;
75: } else
76: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
77: return NULL;
2.19 frystyk 78: }
2.1 luotonen 79:
2.23 frystyk 80: PUBLIC HTAAModule * HTAA_newModule (const char * scheme,
81: HTNetCallback * before,
82: HTNetCallback * after,
83: HTUTree_gc * gc)
84: {
85: if (scheme) {
86: HTAAModule * pres = find_module(scheme);
87:
88: /* If found then update entry - else create a new one */
89: if (!pres) {
90: if (!(pres = (HTAAModule *) HT_CALLOC(1, sizeof(HTAAModule))))
91: HT_OUTOFMEM("HTAA_newModule");
92: StrAllocCopy(pres->scheme, scheme);
93: pres->before = before;
94: pres->after = after;
95: pres->gc = gc;
96:
97: /* Add the new AA Module to the list */
98: HTList_addObject(HTSchemes, (void *) pres);
99: if (AUTH_TRACE) HTTrace("Auth Engine. Created module %p\n", pres);
100: } else {
101: if (AUTH_TRACE) HTTrace("Auth Engine. Found module %p\n", pres);
2.19 frystyk 102: }
2.23 frystyk 103: return pres;
104: } else {
105: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
106: return NULL;
2.19 frystyk 107: }
108: }
2.1 luotonen 109:
2.23 frystyk 110: PUBLIC HTAAModule * HTAA_findModule (const char * scheme)
2.19 frystyk 111: {
2.23 frystyk 112: if (scheme) {
113: HTAAModule * pres = find_module(scheme);
114: if (AUTH_TRACE)
115: HTTrace("Auth Engine. did %sfind %s\n", pres ? "" : "NOT ",scheme);
116: return pres;
117: } else {
118: if (AUTH_TRACE) HTTrace("Auth Engine. Bad augument\n");
2.19 frystyk 119: }
120: return NULL;
121: }
2.1 luotonen 122:
2.23 frystyk 123: PUBLIC BOOL HTAA_deleteModule (const char * scheme)
2.19 frystyk 124: {
2.23 frystyk 125: if (scheme) {
126: HTAAModule * pres = find_module(scheme);
127: if (pres) {
128: HTList_removeObject(HTSchemes, pres);
129: if (AUTH_TRACE) HTTrace("Auth Engine. deleted %p\n", pres);
130: delete_module(pres);
131: return YES;
132: }
2.1 luotonen 133: }
2.19 frystyk 134: return NO;
2.1 luotonen 135: }
136:
2.23 frystyk 137: PUBLIC BOOL HTAA_deleteAllModules (void)
2.19 frystyk 138: {
2.23 frystyk 139: if (HTSchemes) {
140: HTList * cur = HTSchemes;
141: HTAAModule * pres;
142: while ((pres = (HTAAModule *) HTList_nextObject(cur)))
143: delete_module(pres);
144: HTList_delete(HTSchemes);
145: HTSchemes = NULL;
2.19 frystyk 146: return YES;
147: }
148: return NO;
149: }
2.1 luotonen 150:
2.23 frystyk 151: /* ------------------------------------------------------------------------- */
152: /* HANDLE THE AA URL TREE */
153: /* ------------------------------------------------------------------------- */
154:
2.19 frystyk 155: /*
2.23 frystyk 156: ** A AA element is a particular AA procotol associated with a
157: ** particular point in the URL tree. The scheme is the name of the
158: ** AA protocol known to be able to handle this context. This protocol
159: ** must have been registered as a AA module.
160: */
161: PRIVATE HTAAElement * HTAA_newElement (const char * scheme, void * context)
162: {
163: if (scheme) {
164: HTAAElement * me;
165: if ((me = (HTAAElement *) HT_CALLOC(1, sizeof(HTAAElement))) == NULL)
166: HT_OUTOFMEM("HTAAElement_new");
167: StrAllocCopy(me->scheme, scheme);
168: me->context = context;
169: if (AUTH_TRACE) HTTrace("Auth Engine. Created element %p\n", me);
170: return me;
2.19 frystyk 171: }
172: return NULL;
173: }
2.1 luotonen 174:
2.24 ! frystyk 175: /*
! 176: ** If the new scheme differs from the existing one then use the
! 177: ** new context, otherwise only override the old context if new
! 178: ** one differs from NULL
! 179: */
2.23 frystyk 180: PRIVATE BOOL HTAA_updateElement (HTAAElement * element,
181: const char * scheme, void * context)
2.19 frystyk 182: {
2.23 frystyk 183: if (element && scheme) {
2.24 ! frystyk 184: /*
! 185: ** If the old scheme differs from the new one then delete our
! 186: ** context by calling the gc provided by the caller
! 187: */
! 188: if (strcmp(element->scheme, scheme)) {
! 189: HTAAModule * module = HTAA_findModule(element->scheme);
! 190: if (module && module->gc && element->context)
! 191: (*module->gc)(element->context);
! 192: /*
! 193: ** Insert the new scheme
! 194: */
! 195: StrAllocCopy(element->scheme, scheme);
! 196: element->context = context;
! 197: } else if (context && context != element->context)
! 198: element->context = context;
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.23 frystyk 235: PRIVATE HTAAElement * HTAA_findElement (const char * realm, const char * url)
2.19 frystyk 236: {
2.23 frystyk 237: HTUTree * tree;
238: if (!url) {
239: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
240: return NULL;
2.19 frystyk 241: }
2.23 frystyk 242: if (AUTH_TRACE) HTTrace("Auth Engine. Looking up `%s'\n", url);
2.19 frystyk 243:
2.23 frystyk 244: /* Find an existing URL Tree for this URL (if any) */
2.19 frystyk 245: {
246: char * host = HTParse(url, "", PARSE_HOST);
247: char * colon = strchr(host, ':');
2.23 frystyk 248: int port = DEFAULT_PORT;
2.19 frystyk 249: if (colon ) {
250: *(colon++) = '\0'; /* Chop off port number */
251: port = atoi(colon);
2.23 frystyk 252: }
253: tree = HTUTree_find(AA_NAME, host, port);
254: HT_FREE(host);
255: if (!tree) {
256: if (AUTH_TRACE) HTTrace("Auth Engine. No information\n");
257: return NULL;
2.19 frystyk 258: }
259: }
2.1 luotonen 260:
2.23 frystyk 261: /* Find a matching AA element (if any) */
2.19 frystyk 262: {
2.23 frystyk 263: char * path = HTParse(url, "", PARSE_PATH);
264: HTAAElement *element = (HTAAElement*)HTUTree_findNode(tree,realm,path);
265: HT_FREE(path);
266: return element;
2.19 frystyk 267: }
2.23 frystyk 268: return NULL;
2.19 frystyk 269: }
270:
2.23 frystyk 271: /* Add a AA context to the URL tree
272: ** --------------------------------
273: ** Each node in the AA URL tree is a list of the modules we must call
274: ** for this particular node.
275: */
2.24 ! frystyk 276: PUBLIC void * HTAA_updateNode (char const * scheme,
! 277: const char * realm, const char * url,
! 278: void * context)
2.23 frystyk 279: {
280: HTUTree * tree = NULL;
281: HTAAModule * module = NULL;
282: if (!scheme || !url) {
283: if (AUTH_TRACE) HTTrace("Auth Engine. Bad argument\n");
2.24 ! frystyk 284: return NULL;
2.23 frystyk 285: }
286: if (AUTH_TRACE) HTTrace("Auth Engine. Adding info for `%s'\n", url);
287:
288: /* Find the AA module with this name */
289: if ((module = HTAA_findModule(scheme)) == NULL) {
290: if (AUTH_TRACE) HTTrace("Auth Engine. Module `%s\' not registered\n",
291: scheme ? scheme : "<null>");
2.24 ! frystyk 292: return NULL;
2.19 frystyk 293: }
294:
2.23 frystyk 295: /* Find an existing URL Tree or create a new one */
2.19 frystyk 296: {
297: char * host = HTParse(url, "", PARSE_HOST);
298: char * colon = strchr(host, ':');
2.23 frystyk 299: int port = DEFAULT_PORT;
2.19 frystyk 300: if (colon ) {
301: *(colon++) = '\0'; /* Chop off port number */
302: port = atoi(colon);
2.23 frystyk 303: }
304: tree = HTUTree_new(AA_NAME, host, port, HTAA_deleteElement);
2.19 frystyk 305: HT_FREE(host);
2.23 frystyk 306: if (!tree) {
307: if (AUTH_TRACE) HTTrace("Auth Engine. Can't create tree\n");
2.24 ! frystyk 308: return NULL;
2.19 frystyk 309: }
310: }
311:
2.23 frystyk 312: /* Find a matching AA element or create a new one */
2.19 frystyk 313: {
2.23 frystyk 314: char * path = HTParse(url, "", PARSE_PATH);
315: HTAAElement * element = NULL;
316: BOOL status;
317: if ((element = (HTAAElement *) HTUTree_findNode(tree, realm, path)))
318: status = HTAA_updateElement(element, scheme, context);
319: else {
320: element = HTAA_newElement(scheme, context);
321: status = HTUTree_addNode(tree, realm, path, element);
322: }
323: HT_FREE(path);
2.24 ! frystyk 324: return status==YES ? element->context : NULL;
2.19 frystyk 325: }
326: }
327:
328: /* ------------------------------------------------------------------------- */
2.23 frystyk 329: /* AUTHENTICATION ENGINE */
2.19 frystyk 330: /* ------------------------------------------------------------------------- */
331:
2.23 frystyk 332: /* HTAA_beforeFilter
333: ** ------------------
2.24 ! frystyk 334: ** Make a lookup in the URL tree to find any context for this node,
! 335: ** If no context is found then we assume that we don't know anything about
! 336: ** this URL and hence we don't call any BEFORE filters at all.
2.23 frystyk 337: ** Return HT_OK or whatever callback returns
2.19 frystyk 338: */
2.23 frystyk 339: PUBLIC int HTAA_beforeFilter (HTRequest * request, void * param, int status)
2.19 frystyk 340: {
2.23 frystyk 341: char * url = HTAnchor_physical(HTRequest_anchor(request));
342: const char * realm = HTRequest_realm(request);
343: HTAAElement * element = HTAA_findElement(realm, url);
344:
2.24 ! frystyk 345: /* Delete any old challenges if any */
2.23 frystyk 346: if (element) {
347: HTAAModule * module = HTAA_findModule(element->scheme);
348: if (module) {
2.24 ! frystyk 349: HTRequest_deleteChallenge(request);
2.23 frystyk 350: if (AUTH_TRACE) HTTrace("Auth Engine. Found BEFORE filter %p\n",
351: module->before);
352: return (*module->before)(request, element->context,status);
2.19 frystyk 353: }
354: }
2.23 frystyk 355: return HT_OK;
2.19 frystyk 356: }
357:
2.23 frystyk 358: /* HTAA_afterFilter
359: ** -----------------
2.24 ! frystyk 360: ** Call the AFTER filter that knows how to handle this scheme.
2.19 frystyk 361: ** Return YES or whatever callback returns
362: */
2.23 frystyk 363: PUBLIC BOOL HTAA_afterFilter (HTRequest * request, void * param, int status)
2.19 frystyk 364: {
2.23 frystyk 365: const char * scheme = HTRequest_scheme(request);
2.24 ! frystyk 366: HTAAModule * module = NULL;
! 367: /*
! 368: ** If we don't have a scheme then the server has made an error. We
! 369: ** try to make up for it by creating our own "noop" realm and use basic.
! 370: */
! 371: if (!scheme) {
! 372: HTRequest_addChallenge(request, "basic", "realm UNKNOWN");
! 373: scheme = "basic";
! 374: }
! 375: if ((module = HTAA_findModule(scheme)) != NULL) {
2.23 frystyk 376: if (AUTH_TRACE)
377: HTTrace("Auth Engine. Found AFTER filter %p\n", module->after);
2.24 ! frystyk 378: HTRequest_deleteCredentials(request);
2.23 frystyk 379: return (*module->after)(request, NULL, status);
2.19 frystyk 380: }
2.24 ! frystyk 381: return HT_ERROR;
2.19 frystyk 382: }
Webmaster