[0001] [0002] [0003] [0004] [0005] [0006] [0007] [0008] [0009] [0010] [0011] [0012] [0013] [0014] [0015] [0016] [0017] [0018] [0019] [0020] [0021] [0022] [0023] [0024] [0025] [0026] [0027] [0028] [0029] [0030] [0031] [0032] [0033] [0034] [0035] [0036] [0037] [0038] [0039] [0040] [0041] [0042] [0043] [0044] [0045] [0046] [0047] [0048] [0049] [0050] [0051] [0052] [0053] [0054] [0055] [0056] [0057] [0058] [0059] [0060] [0061] [0062] [0063] [0064] [0065] [0066] [0067] [0068] [0069] [0070] [0071] [0072] [0073] [0074] [0075] [0076] [0077] [0078] [0079] [0080] [0081] [0082] [0083] [0084] [0085] [0086] [0087] [0088] [0089] [0090] [0091] [0092] [0093] [0094] [0095] [0096] [0097] [0098] [0099] [0100] [0101] [0102] [0103] [0104] [0105] [0106] [0107] [0108] [0109] [0110] [0111] [0112] [0113] [0114] [0115] [0116] [0117] [0118] [0119] [0120] [0121] [0122] [0123] [0124] [0125] [0126] [0127] [0128] [0129] [0130] [0131] [0132] [0133] [0134] [0135] [0136] [0137] [0138] [0139] [0140] [0141] [0142] [0143] [0144] [0145] [0146] [0147] [0148] [0149] [0150] [0151] [0152] [0153] [0154] [0155] [0156] [0157] [0158] [0159] [0160] [0161] [0162] [0163] [0164] [0165] [0166] [0167] [0168] [0169] [0170] [0171] [0172] [0173] [0174] [0175] [0176] [0177] [0178] [0179] [0180] [0181] [0182] [0183] [0184] [0185] [0186] [0187] [0188] [0189] [0190] [0191] [0192] [0193] [0194] [0195] [0196] [0197] [0198] [0199] [0200] [0201] [0202] [0203] [0204] [0205] [0206] [0207] [0208] [0209] [0210] [0211] [0212] [0213] [0214] [0215] [0216] [0217] [0218] [0219] [0220] [0221] [0222] [0223] [0224] [0225] [0226] [0227] [0228] [0229] [0230] [0231] [0232] [0233] [0234] [0235] [0236] [0237] [0238] [0239] [0240] [0241] [0242] [0243] [0244] [0245] [0246] [0247] [0248] [0249] [0250] [0251] [0252] [0253] [0254] [0255] [0256] [0257] [0258] [0259] [0260] [0261] [0262] [0263] [0264] [0265] [0266] [0267] [0268] [0269] [0270] [0271] [0272] [0273] [0274] [0275] [0276] [0277] [0278] [0279] [0280] [0281] [0282] [0283] [0284] [0285] [0286] [0287] [0288] [0289] [0290] [0291] [0292] [0293] [0294] [0295] [0296] [0297] [0298] [0299] [0300] [0301] [0302] [0303] [0304] [0305] [0306] [0307] [0308] [0309] [0310] [0311] [0312] [0313] [0314] [0315] [0316] [0317] [0318] [0319] [0320] [0321] [0322] [0323] [0324] [0325] [0326] [0327] [0328] [0329] [0330] [0331] [0332] [0333] [0334] [0335] [0336] [0337] [0338] [0339] [0340] [0341] [0342] [0343] [0344] [0345] [0346] [0347] [0348] [0349] [0350] [0351] [0352] [0353] [0354]
/*****************************************************************************/ /* Basic.c This module implements the BASIC authentication functionality. VERSION HISTORY --------------- 04-AUG-2001 MGD support module WATCHing 29-APR-2000 MGD proxy authorization 18-SEP-1999 MGD to support authentication agents username/password are no longer forced to upper case (in true VMS fashion :^) 30-OCT-1997 MGD a little maintenance 01-JUL-1996 MGD own module with development of "Digest" authentication */ /*****************************************************************************/ #ifdef WASD_VMS_V7 #undef _VMS__V6__SOURCE #define _VMS__V6__SOURCE #undef __VMS_VER #define __VMS_VER 70000000 #undef __CRTL_VER #define __CRTL_VER 70000000 #endif /* standard C header files */ #include <ctype.h> #include <errno.h> #include <stdio.h> /* VMS related header files */ #include <ssdef.h> #include <stsdef.h> /* application related header files */ #include "wasd.h" #define WASD_MODULE "BASIC" /********************/ /* external storage */ /********************/ extern char SoftwareID[]; extern MSG_STRUCT Msgs; extern WATCH_STRUCT Watch; /*****************************************************************************/ /* */ int BasicAuthorization (REQUEST_STRUCT *rqptr) { int status; char *cptr, *sptr, *zptr; char EncodedString [256], UserNamePassword [256]; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD__OTHER)) WatchThis (WATCHALL, WATCH_MOD__OTHER, "BasicAuthorization() !&Z", rqptr->rqAuth.RequestAuthorizationPtr); rqptr->rqAuth.Scheme = rqptr->rqAuth.ChallengeScheme = AUTH_SCHEME_BASIC; cptr = rqptr->rqAuth.RequestAuthorizationPtr; /* skip across the authorization scheme name ("basic") */ while (*cptr && !ISLWS(*cptr)) cptr++; /* skip over white-space between scheme and encoded string */ while (*cptr && ISLWS(*cptr)) cptr++; /* get the RFC1421-encoded "username:password" string */ zptr = (sptr = EncodedString) + sizeof(EncodedString); while (*cptr && !ISLWS(*cptr) && sptr < zptr) *sptr++ = *cptr++; if (sptr >= zptr) { rqptr->rqResponse.HttpStatus = 401; ErrorGeneralOverflow (rqptr, FI_LI); return (STS$K_ERROR); } *sptr = '\0'; /************************************************/ /* decode and extract the username and password */ /************************************************/ sptr = BasicPrintableDecode (EncodedString, UserNamePassword, sizeof(UserNamePassword)); if (sptr[0]) { /* an error report string has been returned by the decode function */ rqptr->rqResponse.HttpStatus = 401; ErrorGeneral (rqptr, sptr, FI_LI); return (STS$K_ERROR); } cptr = UserNamePassword; /* get the remote username from the decoded "username:password" string */ zptr = (sptr = rqptr->RemoteUser) + sizeof(rqptr->RemoteUser); while (*cptr && *cptr != ':' && sptr < zptr) *sptr++ = *cptr++; if (sptr >= zptr) { rqptr->rqResponse.HttpStatus = 401; ErrorGeneralOverflow (rqptr, FI_LI); return (STS$K_ERROR); } *sptr = '\0'; rqptr->RemoteUserLength = sptr - rqptr->RemoteUser; /* get the password from the decoded "username:password" string */ if (*cptr == ':') cptr++; zptr = (sptr = rqptr->RemoteUserPassword) + sizeof(rqptr->RemoteUserPassword); while (*cptr && sptr < zptr) *sptr++ = *cptr++; if (sptr >= zptr) { rqptr->rqResponse.HttpStatus = 401; ErrorGeneralOverflow (rqptr, FI_LI); return (STS$K_ERROR); } *sptr = '\0'; return (SS$_NORMAL); } /*****************************************************************************/ /* Generate a BASIC challenge string, comprising the authentication realm. Store this null-terminated string in dynamically allocated memory pointed to by 'rqptr->rqAuth.BasicChallengePtr'. */ int BasicChallenge (REQUEST_STRUCT *rqptr) { static $DESCRIPTOR (StringDsc, ""); static $DESCRIPTOR (BasicChallengeFaoDsc, "!AZ: Basic realm=\"!AZ\""); int status; unsigned short Length; char String [256]; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD__OTHER)) WatchThis (WATCHALL, WATCH_MOD__OTHER, "BasicChallenge()"); StringDsc.dsc$a_pointer = String; StringDsc.dsc$w_length = sizeof(String)-1; sys$fao (&BasicChallengeFaoDsc, &Length, &StringDsc, rqptr->ServicePtr->ProxyAuthRequired ? "Proxy-Authenticate" : "WWW-Authenticate", rqptr->rqAuth.RealmDescrPtr); String[Length] = '\0'; /* allocate heap memory */ rqptr->rqAuth.BasicChallengePtr = VmGetHeap (rqptr, Length+1); memcpy (rqptr->rqAuth.BasicChallengePtr, String, Length+1); return (SS$_NORMAL); } /*****************************************************************************/ /* Decodes a string encoded using "Printable Encoding" as described in RFC1421. */ char* BasicPrintableDecode ( char *Encoded, char *Plain, int SizeOfPlain ) { static char ErrorIncorrect [] = "Incorrect character in quantum."; static char ErrorIncomplete [] = "Incomplete quantum."; static char ErrorOverflow [] = "Plain text string too small."; static unsigned char ValueTable [128] = { 255, 255, 255, 255, 255, 255, 255, 255, /* 7 */ 255, 255, 255, 255, 255, 255, 255, 255, /* 15 */ 255, 255, 255, 255, 255, 255, 255, 255, /* 23 */ 255, 255, 255, 255, 255, 255, 255, 255, /* 31 */ 255, 255, 255, 255, 255, 255, 255, 255, /* 39 */ 255, 255, 255, 62, 255, 255, 255, 63, /* 47 */ 52, 53, 54, 55, 56, 57, 58, 59, /* 55 */ 60, 61, 255, 255, 255, 255, 255, 255, /* 63 */ 255, 0, 1, 2, 3, 4, 5, 6, /* 71 */ 7, 8, 9, 10, 11, 12, 13, 14, /* 79 */ 15, 16, 17, 18, 19, 20, 21, 22, /* 87 */ 23, 24, 25, 255, 255, 255, 255, 255, /* 95 */ 255, 26, 27, 28, 29, 30, 31, 32, /* 103 */ 33, 34, 35, 36, 37, 38, 39, 40, /* 111 */ 41, 42, 43, 44, 45, 46, 47, 48, /* 119 */ 49, 50, 51, 255, 255, 255, 255, 255 /* 127 */ }; int ccnt, pcnt; unsigned long reg; char val; char *eptr, *pptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD__OTHER)) WatchThis (WATCHALL, WATCH_MOD__OTHER, "BasicPrintableDecode()"); eptr = Encoded; pptr = Plain; pcnt = SizeOfPlain-1; while (*eptr) { reg = 0; if (*eptr) { if (*eptr == '=') return (ErrorIncorrect); if ((val = ValueTable [*eptr++ & 0x7f]) == 255) return (ErrorIncorrect); reg |= val << 18; } if (*eptr) { if (*eptr == '=') return (ErrorIncorrect); ccnt = 1; if ((val = ValueTable [*eptr++ & 0x7f]) == 255) return (ErrorIncorrect); reg |= val << 12; } if (*eptr) { if (*eptr == '=') eptr++; else { ccnt++; if ((val = ValueTable [*eptr++ & 0x7f]) == 255) return (ErrorIncorrect); reg |= val << 6; } } if (*eptr) { if (*eptr == '=') eptr++; else { ccnt++; if ((val = ValueTable [*eptr++ & 0x7f]) == 255) return (ErrorIncorrect); reg |= val; } } else return (ErrorIncomplete); if (!pcnt--) return (ErrorOverflow); if (ccnt--) *pptr++ = (reg >> 16) & 0xff; if (!pcnt--) return (ErrorOverflow); if (ccnt--) *pptr++ = (reg >> 8) & 0xff; if (!pcnt--) return (ErrorOverflow); if (ccnt--) *pptr++ = reg & 0xff; } *pptr = '\0'; return (""); } /*****************************************************************************/ /* Encodes a plain-text string using "Printable Encoding" as described in RFC1421. This function is not actually used at all in this daemon! It is included here as a tutorial on how the string is encoded at the browser end! */ char* BasicPrintableEncode ( unsigned char *Plain, unsigned char *Encoded, int SizeOfEncoded ) { static char ErrorOverflow [] = "Encoded text string too small."; static unsigned char ValueTable [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int ccnt, ecnt; unsigned long reg; unsigned char *eptr, *pptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD__OTHER)) WatchThis (WATCHALL, WATCH_MOD__OTHER, "BasicPrintableEncode()"); pptr = Plain; eptr = Encoded; ecnt = SizeOfEncoded-1; while (*pptr) { ccnt = reg = 0; if (*pptr) { reg |= *pptr++ << 16; ccnt++; } if (*pptr) { reg |= *pptr++ << 8; ccnt++; } if (*pptr) { reg |= *pptr++; ccnt++; } *eptr++ = ValueTable[(reg>>18)&0x3f]; if (!ecnt--) return (ErrorOverflow); *eptr++ = ValueTable[(reg>>12)&0x3f]; if (!ecnt--) return (ErrorOverflow); if (ccnt == 1) { if (!ecnt--) return (ErrorOverflow); *eptr++ = '='; if (!ecnt--) return (ErrorOverflow); *eptr++ = '='; } else { *eptr++ = ValueTable[(reg>>6)&0x3f]; if (ccnt == 2) { if (!ecnt--) return (ErrorOverflow); *eptr++ = '='; } else { if (!ecnt--) return (ErrorOverflow); *eptr++ = ValueTable[reg&0x3f]; } } } *eptr = '\0'; return (""); } /****************************************************************************/