[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 ("");
}

/****************************************************************************/