2
** COMMON PARTS OF ACCESS AUTHORIZATION MODULE
3
** FOR BOTH SERVER AND BROWSER
6
** Routines in this module use dynamic allocation, but free
7
** automatically all the memory reserved by them.
9
** Therefore the caller never has to (and never should)
10
** free() any object returned by these functions.
12
** Therefore also all the strings returned by this package
13
** are only valid until the next call to the same function
14
** is made. This approach is selected, because of the nature
15
** of access authorization: no string returned by the package
16
** needs to be valid longer than until the next call.
18
** This also makes it easy to plug the AA package in:
19
** you don't have to ponder whether to free() something
20
** here or is it done somewhere else (because it is always
21
** done somewhere else).
23
** The strings that the package needs to store are copied
24
** so the original strings given as parameters to AA
25
** functions may be freed or modified with no side effects.
27
** The AA package does not free() anything else than what
28
** it has itself allocated.
30
** AA (Access Authorization) package means modules which
31
** names start with HTAA.
34
** AL Ari Luotonen luotonen@dxcern.cern.ch
35
** MD Mark Donszelmann duns@vxdeop.cern.ch
38
** 8 Nov 93 MD (VMS only) Added case insensitive comparison in HTAA_templateCaseMatch
48
#include <HTAAUtil.h> /* Implemented here */
49
#include <HTAssoc.h> /* Assoc list */
53
#include <LYStrings.h>
56
/* PUBLIC HTAAScheme_enum()
57
** TRANSLATE SCHEME NAME INTO
58
** A SCHEME ENUMERATION
61
** name is a string representing the scheme name.
64
** returns the enumerated constant for that scheme.
66
PUBLIC HTAAScheme HTAAScheme_enum ARGS1(CONST char*, name)
73
StrAllocCopy(upcased, name);
76
if (!strncmp(upcased, "NONE", 4)) {
79
} else if (!strncmp(upcased, "BASIC", 5)) {
82
} else if (!strncmp(upcased, "PUBKEY", 6)) {
85
} else if (!strncmp(upcased, "KERBEROSV4", 10)) {
87
return HTAA_KERBEROS_V4;
88
} else if (!strncmp(upcased, "KERBEROSV5", 10)) {
90
return HTAA_KERBEROS_V5;
98
/* PUBLIC HTAAScheme_name()
99
** GET THE NAME OF A GIVEN SCHEME
101
** scheme is one of the scheme enum values:
102
** HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
105
** returns the name of the scheme, i.e.
106
** "None", "Basic", "Pubkey", ...
108
PUBLIC char *HTAAScheme_name ARGS1(HTAAScheme, scheme)
117
case HTAA_KERBEROS_V4:
119
case HTAA_KERBEROS_V5:
124
return "THIS-IS-A-BUG";
129
/* PUBLIC HTAAMethod_enum()
130
** TRANSLATE METHOD NAME INTO AN ENUMERATED VALUE
132
** name is the method name to translate.
135
** returns HTAAMethod enumerated value corresponding
136
** to the given name.
138
PUBLIC HTAAMethod HTAAMethod_enum ARGS1(CONST char *, name)
141
return METHOD_UNKNOWN;
143
if (0==strcasecomp(name, "GET"))
145
else if (0==strcasecomp(name, "PUT"))
148
return METHOD_UNKNOWN;
152
/* PUBLIC HTAAMethod_name()
153
** GET THE NAME OF A GIVEN METHOD
155
** method is one of the method enum values:
156
** METHOD_GET, METHOD_PUT, ...
159
** returns the name of the scheme, i.e.
162
PUBLIC char *HTAAMethod_name ARGS1(HTAAMethod, method)
172
return "THIS-IS-A-BUG";
177
/* PUBLIC HTAAMethod_inList()
178
** IS A METHOD IN A LIST OF METHOD NAMES
180
** method is the method to look for.
181
** list is a list of method names.
184
** returns YES, if method was found.
187
PUBLIC BOOL HTAAMethod_inList ARGS2(HTAAMethod, method,
193
while (NULL != (item = (char*)HTList_nextObject(cur))) {
194
CTRACE((tfp, " %s", item));
195
if (method == HTAAMethod_enum(item))
199
return NO; /* Not found */
203
/* PUBLIC HTAA_templateMatch()
204
** STRING COMPARISON FUNCTION FOR FILE NAMES
205
** WITH ONE WILDCARD * IN THE TEMPLATE
207
** This is essentially the same code as in HTRules.c, but it
208
** cannot be used because it is embedded in between other code.
209
** (In fact, HTRules.c should use this routine, but then this
210
** routine would have to be more sophisticated... why is life
211
** sometimes so hard...)
214
** template is a template string to match the file name
215
** against, may contain a single wildcard
216
** character * which matches zero or more
217
** arbitrary characters.
218
** filename is the filename (or pathname) to be matched
219
** against the template.
222
** returns YES, if filename matches the template.
225
PUBLIC BOOL HTAA_templateMatch ARGS2(CONST char *, template,
226
CONST char *, filename)
228
CONST char *p = template;
229
CONST char *q = filename;
232
for (; *p && *q && *p == *q; p++, q++) /* Find first mismatch */
233
; /* do nothing else */
236
return YES; /* Equally long equal strings */
237
else if ('*' == *p) { /* Wildcard */
238
p++; /* Skip wildcard character */
239
m = strlen(q) - strlen(p); /* Amount to match to wildcard */
241
return NO; /* No match, filename too short */
242
else { /* Skip the matched characters and compare */
244
return NO; /* Tail mismatch */
246
return YES; /* Tail match */
250
return NO; /* Length or character mismatch */
254
/* PUBLIC HTAA_templateCaseMatch()
255
** STRING COMPARISON FUNCTION FOR FILE NAMES
256
** WITH ONE WILDCARD * IN THE TEMPLATE (Case Insensitive)
258
** This is essentially the same code as in HTAA_templateMatch, but
259
** it compares case insensitive (for VMS). Reason for this routine
260
** is that HTAA_templateMatch gets called from several places, also
261
** there where a case sensitive match is needed, so one cannot just
262
** change the HTAA_templateMatch routine for VMS.
265
** template is a template string to match the file name
266
** against, may contain a single wildcard
267
** character * which matches zero or more
268
** arbitrary characters.
269
** filename is the filename (or pathname) to be matched
270
** against the template.
273
** returns YES, if filename matches the template.
276
PUBLIC BOOL HTAA_templateCaseMatch ARGS2(CONST char *, template,
277
CONST char *, filename)
279
CONST char *p = template;
280
CONST char *q = filename;
283
/* Find first mismatch */
284
for (; *p && *q && TOUPPER(*p) == TOUPPER(*q); p++, q++)
285
; /* do nothing else */
288
return YES; /* Equally long equal strings */
289
else if ('*' == *p) { /* Wildcard */
290
p++; /* Skip wildcard character */
291
m = strlen(q) - strlen(p); /* Amount to match to wildcard */
293
return NO; /* No match, filename too short */
294
else { /* Skip the matched characters and compare */
295
if (strcasecomp(p, q+m))
296
return NO; /* Tail mismatch */
298
return YES; /* Tail match */
302
return NO; /* Length or character mismatch */
306
/* PUBLIC HTAA_makeProtectionTemplate()
307
** CREATE A PROTECTION TEMPLATE FOR THE FILES
308
** IN THE SAME DIRECTORY AS THE GIVEN FILE
309
** (Used by server if there is no fancier way for
310
** it to tell the client, and by browser if server
311
** didn't send WWW-ProtectionTemplate: field)
313
** docname is the document pathname (from URL).
316
** returns a template matching docname, and other files
317
** files in that directory.
319
** E.g. /foo/bar/x.html => /foo/bar/ *
321
** Space only to prevent it from
322
** being a comment marker here,
323
** there really isn't any space.
325
PUBLIC char *HTAA_makeProtectionTemplate ARGS1(CONST char *, docname)
327
char *template = NULL;
331
StrAllocCopy(template, docname);
332
slash = strrchr(template, '/');
338
StrAllocCat(template, "*");
341
StrAllocCopy(template, "*");
343
CTRACE((tfp, "make_template: made template `%s' for file `%s'\n",
351
** Skip leading whitespace from *s forward
353
#define SKIPWS(s) while (*s==' ' || *s=='\t') s++;
356
** Kill trailing whitespace starting from *(s-1) backwards
358
#define KILLWS(s) {char *c=s-1; while (*c==' ' || *c=='\t') *(c--)='\0';}
361
/* PUBLIC HTAA_parseArgList()
362
** PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
364
** str is a comma-separated list:
372
** Leading and trailing whitespace is ignored
373
** everywhere except inside quotes, so the following
374
** examples are equal:
376
** name=value,foo=bar
377
** name="value",foo="bar"
378
** name = value , foo = bar
379
** name = "value" , foo = "bar"
382
** returns a list of name-value pairs (actually HTAssocList*).
383
** For items with no name, just value, the name is
384
** the number of order number of that item. E.g.
385
** "1" for the first, etc.
387
PUBLIC HTAssocList *HTAA_parseArgList ARGS1(char *, str)
389
HTAssocList *assoc_list = HTAssocList_new();
398
SKIPWS(str); /* Skip leading whitespace */
402
while (*cur && *cur != '=' && *cur != ',')
403
cur++; /* Find end of name (or lonely value without a name) */
404
KILLWS(cur); /* Kill trailing whitespace */
406
if (*cur == '=') { /* Name followed by a value */
407
*(cur++) = '\0'; /* Terminate name */
408
StrAllocCopy(name, str);
409
SKIPWS(cur); /* Skip WS leading the value */
411
if (*str == '"') { /* Quoted value */
414
while (*cur && *cur != '"')
417
*(cur++) = '\0'; /* Terminate value */
418
/* else it is lacking terminating quote */
419
SKIPWS(cur); /* Skip WS leading comma */
421
cur++; /* Skip separating colon */
423
else { /* Unquoted value */
424
while (*cur && *cur != ',')
426
KILLWS(cur); /* Kill trailing whitespace */
429
/* else *cur already NULL */
432
else { /* No name, just a value */
434
*(cur++) = '\0'; /* Terminate value */
435
/* else last value on line (already terminated by NULL) */
436
HTSprintf0(&name, "%d", n); /* Item order number for name */
438
HTAssocList_add(assoc_list, name, str);
447
/************** HEADER LINE READER -- DOES UNFOLDING *************************/
449
#define BUFFER_SIZE 1024
451
PRIVATE size_t buffer_length;
452
PRIVATE char *buffer = 0;
453
PRIVATE char *start_pointer;
454
PRIVATE char *end_pointer;
455
PRIVATE int in_soc = -1;
458
PRIVATE void FreeHTAAUtil NOARGS
462
#endif /* LY_FIND_LEAKS */
464
/* PUBLIC HTAA_setupReader()
465
** SET UP HEADER LINE READER, i.e., give
466
** the already-read-but-not-yet-processed
467
** buffer of text to be read before more
468
** is read from the socket.
470
** start_of_headers is a pointer to a buffer containing
471
** the beginning of the header lines
472
** (rest will be read from a socket).
473
** length is the number of valid characters in
474
** 'start_of_headers' buffer.
475
** soc is the socket to use when start_of_headers
476
** buffer is used up.
479
** Subsequent calls to HTAA_getUnfoldedLine()
480
** will use this buffer first and then
481
** proceed to read from socket.
483
PUBLIC void HTAA_setupReader ARGS3(char *, start_of_headers,
487
if (!start_of_headers)
488
length = 0; /* initialize length (is this reached at all?) */
489
if (buffer == NULL) { /* first call? */
490
buffer_length = length;
491
if (buffer_length < BUFFER_SIZE) /* would fall below BUFFER_SIZE? */
492
buffer_length = BUFFER_SIZE;
493
buffer = (char*)malloc((size_t)(sizeof(char)*(buffer_length + 1)));
495
else if (length > (int)buffer_length) { /* need more space? */
496
buffer_length = length;
497
buffer = (char*)realloc((char*)buffer,
498
(size_t)(sizeof(char)*(buffer_length + 1)));
500
if (buffer == NULL) outofmem(__FILE__, "HTAA_setupReader");
502
atexit(FreeHTAAUtil);
504
start_pointer = buffer;
505
if (start_of_headers) {
506
strncpy(buffer, start_of_headers, length);
507
buffer[length] = '\0';
508
end_pointer = buffer + length;
511
*start_pointer = '\0';
512
end_pointer = start_pointer;
518
/* PUBLIC HTAA_getUnfoldedLine()
519
** READ AN UNFOLDED HEADER LINE FROM SOCKET
521
** HTAA_setupReader must absolutely be called before
522
** this function to set up internal buffer.
525
** returns a newly-allocated character string representing
526
** the read line. The line is unfolded, i.e.
527
** lines that begin with whitespace are appended
528
** to current line. E.g.
530
** Field-Name: Blaa-Blaa
531
** This-Is-A-Continuation-Line
534
** is seen by the caller as:
536
** Field-Name: Blaa-Blaa This-Is-A-Continuation-Line Here-Is_Another
539
PUBLIC char *HTAA_getUnfoldedLine NOARGS
544
BOOL peek_for_folding = NO;
547
CTRACE((tfp, "%s %s\n",
548
"HTAA_getUnfoldedLine: buffer not initialized",
549
"with function HTAA_setupReader()"));
555
/* Reading from socket */
557
if (start_pointer >= end_pointer) {/*Read the next block and continue*/
560
count = SSL_read(SSL_handle, buffer, BUFFER_SIZE);
562
count = NETREAD(in_soc, buffer, BUFFER_SIZE);
564
count = NETREAD(in_soc, buffer, BUFFER_SIZE);
570
start_pointer = buffer;
571
end_pointer = buffer + count;
575
while (cur < end_pointer) {
576
*cur = TOASCII(*cur);
586
if (peek_for_folding) {
587
if (*cur != ' ' && *cur != '\t')
588
return line; /* Ok, no continuation line */
589
else /* So this is a continuation line, continue */
590
peek_for_folding = NO;
594
/* Finding end-of-line */
596
while (cur < end_pointer && *cur != '\n') /* Find the end-of-line */
597
cur++; /* (or end-of-buffer). */
600
/* Terminating line */
602
if (cur < end_pointer) { /* So *cur==LF, terminate line */
603
*cur = '\0'; /* Overwrite LF */
604
if (*(cur-1) == '\r')
605
*(cur-1) = '\0'; /* Overwrite CR */
606
peek_for_folding = YES; /* Check for a continuation line */
610
/* Copying the result */
613
StrAllocCat(line, start_pointer); /* Append */
615
StrAllocCopy(line, start_pointer); /* A new line */
617
start_pointer = cur+1; /* Skip the read line */