[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]
/*****************************************************************************/
/*
                               AuthHTL.c


    THE GNU GENERAL PUBLIC LICENSE APPLIES DOUBLY TO ANYTHING TO DO WITH
                    AUTHENTICATION AND AUTHORIZATION!

    This package is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; version 2 of the License, or any later
    version.

>   This package is distributed in the hope that it will be useful,
>   but WITHOUT ANY WARRANTY; without even the implied warranty of
>   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>   GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

This module provides functions related to the authentication of
case-insensitive usernames via simple lists of names (and optional
case-insensitive passwords and user detail).

See AUTH.C for overall detail on the WASD authorization environment.


VERSION HISTORY
---------------
26-JUN-2012  MGD  bugfix; AuthReadSimpleList() parameter /DIRECTORY= processing
26-AUG-2003  MGD  service directory located authorization databases
12-AUG-2003  MGD  allow the database directory location to be specified using
                  an authorization rule 'param="/directory=device:[directory]"'
27-APR-2002  MGD  use sys$setprv()
04-AUG-2001  MGD  support module WATCHing
05-FEB-2000  MGD  change HTL database type from ".HTL" to ".$HTL"
                  (keep the nomenclature in line with ".$HTA", see AUTHHTA.C)
01-JAN-2000  MGD  no significant modifications for ODS-5 (no NAM block)
28-AUG-1999  MGD  unbundled from AUTH.C for v6.1
*/
/*****************************************************************************/

#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>
#include <string.h>

/* VMS related header files */
#include <descrip.h>
#include <rms.h>
#include <rmsdef.h>
#include <ssdef.h>
#include <stsdef.h>

/* application related header files */
#include "wasd.h"

#define WASD_MODULE "AUTHHTL"

#if WATCH_MOD
#define FI_NOLI WASD_MODULE, __LINE__
#else
/* in production let's keep the exact line to ourselves! */
#define FI_NOLI WASD_MODULE, 0
#endif

/********************/
/* external storage */
/********************/

extern int  ToLowerCase[],
            ToUpperCase[];

extern unsigned long  SysPrvMask[];

extern char  *AuthConfigHtaDirectory;

extern char  ErrorSanityCheck[];

extern ACCOUNTING_STRUCT  *AccountingPtr;
extern MSG_STRUCT  Msgs;
extern WATCH_STRUCT  Watch;

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

int AuthReadSimpleList
(
REQUEST_STRUCT* rqptr,
char *DatabaseName,
BOOL AuthenticatePassword
)
{
   int  status,
        AuthFileNameLength;
   char  *cptr, *sptr, *zptr,
         *cptrBuffer;
   char  AuthFileName [256],
         Line [1024];
   struct FAB  AuthFileFab;
   struct RAB  AuthFileRab;

   /*********/
   /* begin */
   /*********/

   if (WATCHMOD (rqptr, WATCH_MOD_AUTH))
      WatchThis (WATCHITM(rqptr), WATCH_MOD_AUTH,
                 "AuthReadSimpleList() !&Z !&Z !&B",
                 DatabaseName, rqptr->RemoteUser, AuthenticatePassword);

   /* flag that case-less username and password checks were performed */
   rqptr->rqAuth.CaseLess = true;

   /* must supply a user name and database name */
   if (!rqptr->RemoteUser[0] || !DatabaseName[0])
      return (AUTH_DENIED_BY_LOGIN);

   if (rqptr->rqAuth.PathParameterPtr &&
       rqptr->rqAuth.PathParameterPtr[0])
   {
      if ((cptr = strstr (rqptr->rqAuth.PathParameterPtr, "/directory=")) ||
          (cptr = strstr (rqptr->rqAuth.PathParameterPtr, "/DIRECTORY=")))
         cptr += 11;
      else
         cptr = NULL;
   }
   else
      cptr = NULL;

   if (!cptr)
   {
      if (rqptr->rqAuth.DirectoryPtr)
        cptr = rqptr->rqAuth.DirectoryPtr;
      else
      if (rqptr->ConfigDirectory[0])
         cptr = rqptr->ConfigDirectory;
      else
         cptr = AuthConfigHtaDirectory;
   }

   /* just a safeguard against the service directory not being configured */
   if (!*cptr) cptr = AUTH_DIR_NOT_CONFIGURED;

   zptr = (sptr = AuthFileName) + sizeof(AuthFileName)-1;
   while (*cptr && sptr < zptr) *sptr++ = *cptr++;
   for (cptr = DatabaseName; *cptr && sptr < zptr; *sptr++ = *cptr++);
   for (cptr = HTL_FILE_TYPE; *cptr && sptr < zptr; *sptr++ = *cptr++);
   *sptr = '\0';
   AuthFileNameLength = sptr - AuthFileName;

   if (WATCHING (rqptr, WATCH_AUTH))
      WatchThis (WATCHITM(rqptr), WATCH_AUTH, "FILE !AZ", AuthFileName);

   AuthFileFab = cc$rms_fab;
   AuthFileFab.fab$b_fac = FAB$M_GET;
   AuthFileFab.fab$l_fna = AuthFileName;  
   AuthFileFab.fab$b_fns = AuthFileNameLength;
   AuthFileFab.fab$b_shr = FAB$M_SHRGET;

   /* turn on SYSPRV to allow access to authentication database file */
   sys$setprv (1, &SysPrvMask, 0, 0);

   status = sys$open (&AuthFileFab, 0, 0);

   sys$setprv (0, &SysPrvMask, 0, 0);

   /* status from sys$open() */
   if (VMSnok (status))
   {
      rqptr->rqResponse.HttpStatus = 500;
      rqptr->rqResponse.ErrorTextPtr = MsgFor(rqptr,MSG_AUTH_DATABASE);
      rqptr->rqResponse.ErrorOtherTextPtr = DatabaseName;
      ErrorVmsStatus (rqptr, status, FI_LI);
      return (status);
   }

   AuthFileRab = cc$rms_rab;
   AuthFileRab.rab$l_fab = &AuthFileFab;
   AuthFileRab.rab$b_mbf = 2;
   AuthFileRab.rab$l_rop = RAB$M_RAH;

   if (VMSnok (status = sys$connect (&AuthFileRab, 0, 0)))
   {
      sys$close (&AuthFileFab, 0, 0);
      rqptr->rqResponse.HttpStatus = 500;
      rqptr->rqResponse.ErrorTextPtr = MsgFor(rqptr,MSG_AUTH_DATABASE);
      rqptr->rqResponse.ErrorOtherTextPtr = DatabaseName;
      ErrorVmsStatus (rqptr, status, FI_LI);
      return (status);
   }

   /*****************/
   /* locate record */
   /*****************/

   AuthFileRab.rab$l_ubf = Line;
   AuthFileRab.rab$w_usz = sizeof(Line)-1;

   while (VMSok (status = sys$get (&AuthFileRab, 0, 0)))
   {
      AuthFileRab.rab$l_rbf[AuthFileRab.rab$w_rsz] = '\0';
      if (AuthFileRab.rab$w_rsz)
      {
         if (AuthFileRab.rab$l_ubf[AuthFileRab.rab$w_rsz-1] == '\\')
         {
            /* directive is continued on next line */
            AuthFileRab.rab$l_ubf[AuthFileRab.rab$w_rsz-1] = ' ';
            AuthFileRab.rab$l_ubf += AuthFileRab.rab$w_rsz;
            AuthFileRab.rab$w_usz -= AuthFileRab.rab$w_rsz;
            continue;
         }
      }
      for (cptr = Line; *cptr && ISLWS(*cptr); cptr++)
      if (*cptr == '#' || *cptr == '!') continue;

      sptr = rqptr->RemoteUser;
      while (*cptr && !ISLWS(*cptr) && *cptr != '=' && *sptr &&
             TOLO(*cptr) == TOLO(*sptr))
         { cptr++; sptr++; }
      if ((*cptr && !ISLWS(*cptr) && *cptr != '=') || *sptr) continue;
      break;
   }

   sys$close (&AuthFileFab);

   if (status == RMS$_EOF)
   {
      /* user record not found */
      if (WATCHING (rqptr, WATCH_AUTH))
         WatchThis (WATCHITM(rqptr), WATCH_AUTH,
                    "FAIL !AZ!AZ username", DatabaseName,
                    AuthSourceString (DatabaseName, AUTH_SOURCE_LIST));

      if (AuthenticatePassword)
         return (AUTH_DENIED_BY_LOGIN);
      else
         return (AUTH_DENIED_BY_GROUP);
   }

   /* if just checking if the user name is an entry in the list file */
   if (!AuthenticatePassword) return (SS$_NORMAL);

   sptr = cptr;
   if (*sptr == '=') while (*sptr && !ISLWS(*sptr)) sptr++;
   while (*sptr && ISLWS(*sptr)) sptr++;
   if (*sptr)
   {
      cptrBuffer = cptr;
      for (cptr = sptr; *cptr; cptr++);
      if (cptr > sptr) cptr--;
      while (cptr > sptr && ISLWS(*cptr)) cptr--;
      if (!ISLWS(*cptr)) cptr++;
      *cptr = '\0';
      rqptr->rqAuth.UserDetailsLength = cptr - sptr;
      rqptr->rqAuth.UserDetailsPtr = cptr =
         VmGetHeap (rqptr, rqptr->rqAuth.UserDetailsLength+1);
      strcpy (cptr, sptr);
      cptr = cptrBuffer;
   }

   /* if just checking if the user name is an entry in the list file */
   if (!AuthenticatePassword) return (status);

   /* simple, clear-text password comparison */
   if (*cptr != '=')
   {
      if (WATCHING (rqptr, WATCH_AUTH))
         WatchThis (WATCHITM(rqptr), WATCH_AUTH,
                    "FAIL !AZ!AZ no password", DatabaseName,
                    AuthSourceString (DatabaseName, AUTH_SOURCE_LIST));
      return (AUTH_DENIED_BY_LOGIN);
   }
   while (*cptr && *cptr == '=') cptr++;
   sptr = rqptr->RemoteUserPassword;
   while (*cptr && !ISLWS(*cptr) && *sptr && TOLO(*cptr) == TOLO(*sptr))
      { cptr++; sptr++; }
   if ((*cptr && !ISLWS(*cptr)) || *sptr)
   {
      /* passwords do not match */
      if (WATCHING (rqptr, WATCH_AUTH))
         WatchThis (WATCHITM(rqptr), WATCH_AUTH,
                    "FAIL !AZ!AZ password", DatabaseName,
                    AuthSourceString (DatabaseName, AUTH_SOURCE_LIST));
      return (AUTH_DENIED_BY_LOGIN);
   }

   /* passwords match */
   return (SS$_NORMAL);
}

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