File: HTAAUtil.c

package info (click to toggle)
cern-httpd 3.0A-1
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 5,392 kB
  • ctags: 6,554
  • sloc: ansic: 37,902; makefile: 1,746; perl: 535; csh: 167; sh: 143
file content (357 lines) | stat: -rw-r--r-- 10,444 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357

/* MODULE							HTAAUtil.c
**		COMMON PARTS OF ACCESS AUTHORIZATION MODULE
**			FOR BOTH SERVER AND BROWSER
**
** IMPORTANT:
**	Routines in this module use dynamic allocation, but free
**	automatically all the memory reserved by them.
**
**	Therefore the caller never has to (and never should)
**	free() any object returned by these functions.
**
**	Therefore also all the strings returned by this package
**	are only valid until the next call to the same function
**	is made. This approach is selected, because of the nature
**	of access authorization: no string returned by the package
**	needs to be valid longer than until the next call.
**
**	This also makes it easy to plug the AA package in:
**	you don't have to ponder whether to free() something
**	here or is it done somewhere else (because it is always
**	done somewhere else).
**
**	The strings that the package needs to store are copied
**	so the original strings given as parameters to AA
**	functions may be freed or modified with no side effects.
**
**	The AA package does not free() anything else than what
**	it has itself allocated.
**
**	AA (Access Authorization) package means modules which
**	names start with HTAA.
**
** AUTHORS:
**	AL	Ari Luotonen	luotonen@dxcern.cern.ch
**	MD 	Mark Donszelmann    duns@vxdeop.cern.ch
**
** HISTORY:
**	 8 Nov 93  MD	(VMS only) Added case insensitive comparison
**			in HTAA_templateCaseMatch
**
**
** BUGS:
**
**
*/

#include "HTUtils.h"
#include "HTAAUtil.h"	/* Implemented here	*/
#include "HTAssoc.h"	/* Assoc list		*/


/* PUBLIC						HTAAScheme_enum()
**		TRANSLATE SCHEME NAME INTO
**		A SCHEME ENUMERATION
**
** ON ENTRY:
**	name		is a string representing the scheme name.
**
** ON EXIT:
**	returns		the enumerated constant for that scheme.
*/
PUBLIC HTAAScheme HTAAScheme_enum ARGS1(CONST char*, name)
{
    static char *upcased = NULL;
    char *cur;

    if (!name) return HTAA_UNKNOWN;

    StrAllocCopy(upcased, name);
    cur = upcased;
    while (*cur) {
	*cur = TOUPPER(*cur);
	cur++;
    }
    
    if      (!strncmp(upcased, "NONE", 4))	   return HTAA_NONE;
    else if (!strncmp(upcased, "BASIC", 5))	   return HTAA_BASIC;
    else if (!strncmp(upcased, "PUBKEY", 6))	   return HTAA_PUBKEY;
    else if (!strncmp(upcased, "KERBEROSV4", 10))  return HTAA_KERBEROS_V4;
    else if (!strncmp(upcased, "KERBEROSV5", 10))  return HTAA_KERBEROS_V5;
    else					   return HTAA_UNKNOWN;
}


/* PUBLIC						HTAAScheme_name()
**			GET THE NAME OF A GIVEN SCHEME
** ON ENTRY:
**	scheme		is one of the scheme enum values:
**			HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
**
** ON EXIT:
**	returns		the name of the scheme, i.e.
**			"None", "Basic", "Pubkey", ...
*/
PUBLIC char *HTAAScheme_name ARGS1(HTAAScheme, scheme)
{
    switch (scheme) {
      case HTAA_NONE:		return "None";          break;
      case HTAA_BASIC:		return "Basic";         break;
      case HTAA_PUBKEY:		return "Pubkey";        break;
      case HTAA_KERBEROS_V4:	return "KerberosV4";	break;
      case HTAA_KERBEROS_V5:	return "KerberosV5";	break;
      case HTAA_UNKNOWN:	return "UNKNOWN";       break;
      default:			return "THIS-IS-A-BUG";
    }
}



/* PUBLIC						HTAA_templateMatch()
**		STRING COMPARISON FUNCTION FOR FILE NAMES
**		   WITH ONE WILDCARD * IN THE TEMPLATE
** NOTE:
**	This is essentially the same code as in HTRules.c, but it
**	cannot be used because it is embedded in between other code.
**	(In fact, HTRules.c should use this routine, but then this
**	 routine would have to be more sophisticated... why is life
**	 sometimes so hard...)
**
** ON ENTRY:
**	template	is a template string to match the file name
**			agaist, may contain a single wildcard
**			character * which matches zero or more
**			arbitrary characters.
**	filename	is the filename (or pathname) to be matched
**			agaist the template.
**
** ON EXIT:
**	returns		YES, if filename matches the template.
**			NO, otherwise.
*/
PUBLIC BOOL HTAA_templateMatch ARGS2(CONST char *, template, 
				     CONST char *, filename)
{
    CONST char *p = template;
    CONST char *q = filename;
    int m;

    if (!template || !filename) {
	if (TRACE) fprintf(stderr,
			   "HTAA_templateMatch: invalid param: %s is NULL!!\n",
			   (template ? "filename" : "template"));
	return NO;
    }

    for( ; *p  &&  *q  &&  *p == *q; p++, q++)	/* Find first mismatch */
	; /* do nothing else */

    if (!*p && !*q)	return YES;	/* Equally long equal strings */
    else if ('*' == *p) {		/* Wildcard */
	p++;				/* Skip wildcard character */
	m = strlen(q) - strlen(p);	/* Amount to match to wildcard */
	if (m < 0) return NO;		/* No match, filename too short */
	else {			/* Skip the matched characters and compare */
	    if (strcmp(p, q+m))	return NO;	/* Tail mismatch */
	    else                return YES;	/* Tail match */
	}
    }	/* if wildcard */
    else		return NO;	/* Length or character mismatch */
}    


/* PUBLIC					HTAA_templateCaseMatch()
**		STRING COMPARISON FUNCTION FOR FILE NAMES
**	   WITH ONE WILDCARD * IN THE TEMPLATE (Case Insensitive)
** NOTE:
**	This is essentially the same code as in HTAA_templateMatch, but
**	it compares case insensitive (for VMS). Reason for this routine
**	is that HTAA_templateMatch gets called from several places, also 
**	there where a case sensitive match is needed, so one cannot just
**	change the HTAA_templateMatch routine for VMS.
**
** ON ENTRY:
**	template	is a template string to match the file name
**			agaist, may contain a single wildcard
**			character * which matches zero or more
**			arbitrary characters.
**	filename	is the filename (or pathname) to be matched
**			agaist the template.
**
** ON EXIT:
**	returns		YES, if filename matches the template.
**			NO, otherwise.
*/
PUBLIC BOOL HTAA_templateCaseMatch ARGS2(CONST char *, template, 
			        	 CONST char *, filename)
{
    CONST char *p = template;
    CONST char *q = filename;
    int m;

    if (!template || !filename) {
	if (TRACE) fprintf(stderr,
			   "HTAA_templateCaseMatch: invalid param: %s is NULL!!\n",
			   (template ? "filename" : "template"));
	return NO;
    }

    for( ; *p  &&  *q  &&  toupper(*p) == toupper(*q); p++, q++) /* Find first mismatch */
	; /* do nothing else */

    if (!*p && !*q)	return YES;	/* Equally long equal strings */
    else if ('*' == *p) {		/* Wildcard */
	p++;				/* Skip wildcard character */
	m = strlen(q) - strlen(p);	/* Amount to match to wildcard */
	if (m < 0) return NO;		/* No match, filename too short */
	else {			/* Skip the matched characters and compare */
	    if (strcasecomp(p, q+m))	return NO;	/* Tail mismatch */
	    else                return YES;	/* Tail match */
	}
    }	/* if wildcard */
    else		return NO;	/* Length or character mismatch */
}    


/* PUBLIC					HTAA_makeProtectionTemplate()
**		CREATE A PROTECTION TEMPLATE FOR THE FILES
**		IN THE SAME DIRECTORY AS THE GIVEN FILE
**		(Used by server if there is no fancier way for
**		it to tell the client, and by browser if server
**		didn't send WWW-ProtectionTemplate: field)
** ON ENTRY:
**	docname	is the document pathname (from URL).
**
** ON EXIT:
**	returns	a template matching docname, and other files
**		files in that directory.
**
**		E.g.  /foo/bar/x.html  =>  /foo/bar/ *
**						    ^
**				Space only to prevent it from
**				being a comment marker here,
**				there really isn't any space.
*/
PUBLIC char *HTAA_makeProtectionTemplate ARGS1(CONST char *, docname)
{
    char *template = NULL;
    char *slash = NULL;

    if (docname) {
	StrAllocCopy(template, docname);
	slash = strrchr(template, '/');
	if (slash) slash++;
	else slash = template;
	*slash = (char)0;
	StrAllocCat(template, "*");
    }
    else StrAllocCopy(template, "*");

    if (TRACE) fprintf(stderr,
		       "make_template: made template `%s' for file `%s'\n",
		       template, docname);

    return template;
}




/*
** Skip leading whitespace from *s forward
*/
#define SKIPWS(s) while (*s==' ' || *s=='\t') s++;

/*
** Kill trailing whitespace starting from *(s-1) backwords
*/
#define KILLWS(s) {char *c=s-1; while (*c==' ' || *c=='\t') *(c--)=(char)0;}


/* PUBLIC						HTAA_parseArgList()
**		PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
** ON ENTRY:
**	str	is a comma-separated list:
**
**			item, item, item
**		where
**			item ::= value
**			       | name=value
**			       | name="value"
**
**		Leading and trailing whitespace is ignored
**		everywhere except inside quotes, so the following
**		examples are equal:
**
**			name=value,foo=bar
**			 name="value",foo="bar"
**			  name = value ,  foo = bar
**			   name = "value" ,  foo = "bar"
**
** ON EXIT:
**	returns	a list of name-value pairs (actually HTAssocList*).
**		For items with no name, just value, the name is
**		the number of order number of that item. E.g.
**		"1" for the first, etc.
*/
PUBLIC HTAssocList *HTAA_parseArgList ARGS1(char *, str)
{
    HTAssocList *assoc_list = HTAssocList_new();
    char *cur = NULL;
    char *name = NULL;
    int index = 0;

    if (!str) return assoc_list;

    while (*str) {
	SKIPWS(str);				/* Skip leading whitespace */
	cur = str;
	index++;

	while (*cur  &&  *cur != '='  &&  *cur != ',')
	    cur++;	/* Find end of name (or lonely value without a name) */
	KILLWS(cur);	/* Kill trailing whitespace */

	if (*cur == '=') {			/* Name followed by a value */
	    *(cur++) = (char)0;			/* Terminate name */
	    StrAllocCopy(name, str);
	    SKIPWS(cur);			/* Skip WS leading the value */
	    str = cur;
	    if (*str == '"') {			/* Quoted value */
		str++;
		cur = str;
		while (*cur  &&  *cur != '"') cur++;
		if (*cur == '"')
		    *(cur++) = (char)0;	/* Terminate value */
		/* else it is lacking terminating quote */
		SKIPWS(cur);			/* Skip WS leading comma */
		if (*cur == ',') cur++;		/* Skip separating colon */
	    }
	    else {				/* Unquoted value */
		while (*cur  &&  *cur != ',') cur++;
		KILLWS(cur);			/* Kill trailing whitespace */
		if (*cur == ',')
		    *(cur++) = (char)0;
		/* else *cur already NULL */
	    }
	}
	else {	/* No name, just a value */
	    if (*cur == ',') 
		*(cur++) = (char)0;		/* Terminate value */
	    /* else last value on line (already terminated by NULL) */
	    StrAllocCopy(name, "nnn");	/* Room for item order number */
	    sprintf(name, "%d", index); /* Item order number for name */
	}
	HTAssocList_add(assoc_list, name, str);
	str = cur;
    } /* while *str */
    FREE(name);						  /* Henrik 14/03-94 */
    return assoc_list;
}