/*****************************************************************************/ /* AuthConfig.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 handles authentication/authorization configuration. It reads configuration files, creates the configuration database (linked list), checking paths against that database, and reports surrounding it. See AUTH.C for overall detail on the WASD authorization environment. VERSION HISTORY --------------- 13-SEP-2013 MGD bugfix; AuthConfigLoadCallBack() additional [AuthProxy] with intervening rules should reset proxies 05-MAY-2013 MGD read-only group can be specified as "*" for everyone else 09-SEP-2012 MGD TOKEN authentication 18-JUL-2010 MGD Uni Malaga pushes report items from !3ZL to !4ZL :-) 07-JUN-2009 MGD AuthConfigInit() move WASD_NO_ACME to LNM$FILE_DEV 19-APR-2008 MGD logical name WASD_NO_SYSUAF_ACME disables SYSUAF via ACME logical name WASD_NO_ACME disables ACME altogether 24-NOV-2007 MGD add AGENT+OPAQUE add 'PathLocationPtr' datum force ACME on VMS V7.3 and later AuthConfigLoadCallBack() do not lower-case path 12-JUL-2006 MGD increase AUTH_MAX_PATH_PARAM_LENGTH from 127 to 255 (initially prompted by development of AUTHAGENT_LDAP) add '+=' to realm default syntax to cause realm default to be concatenated to any path access directives bugfix; propagate 'RealmCanString' by making it static 28-MAR-2006 MGD note in boolean 'AuthRealmX509' if X509 realm in use 08-OCT-2005 MGD bugfix; AuthConfigProxyMap() set cache record SYSUAF authentication boolean in tandem with request boolean 18-MAR-2004 MGD ACME authentication 01-SEP-2003 MGD path 'final' keyword to conclude further rule mapping, refine category WATCH rule reporting 26-AUG-2003 MGD service directory located databases 18-JUN-2003 MGD restore pre-v8.3 /SYSUAF behaviour 15-MAY-2003 MGD break-in parameters (default to LGI sysgen parameters) 05-MAY-2003 MGD regular expression support 03-MAY-2003 MGD /SYSUAF=(VMS,ID) allows both VMS and ID authorization (rules with =VMS and =ID can be concurrently deployed) 26-MAR-2003 MGD refine rule failure handling and reporting 15-MAR-2003 MGD script as SYSUAF username can be requested with rule 30-JAN-2003 MGD authentication profile can be requested with rule 07-DEC-2002 MGD skeleton key for admin menu 12-OCT-2002 MGD refine metacon reporting 08-APR-2002 MGD bugfix; AuthConfigProxyMap() wildcard string results 02-MAR-2002 MGD bugfix; identify host group without "=host" 14-OCT-2001 MGD meta-config 04-AUG-2001 MGD support module WATCHing 28-APR-2001 MGD proxy syntax changed from LOCAL=REMOTE to REMOTE=LOCAL 25-APR-2001 MGD bugfix; proxy processing (bit brain-dead in spots!) 13-APR-2001 MGD bugfix; conditions for NetThisVirtualService() call 11-MAR-2001 MGD bugfix; add CONNECT method to access controls 28-FEB-2001 MGD OdsLoadTextFile(), OdsParseTextFile(), [IncludeFile] 13-FEB-2001 MGD authentication via "identification protocol" RFC1413, proxy processing (as if authenticated via the SYSUAF) 10-DEC-2000 MGD X509 (Client Certificate) realm 02-OCT-2000 MGD flush the persona cache when (re)loading 01-SEP-2000 MGD AuthConfigSearch() passed the path as a parameter 13-AUG-2000 MGD bugfix; AuthConfigSearch() quick index 06-MAY-2000 MGD proxy authorization requires changes to path searching 18-MAR-2000 MGD bugfix; lexicographic cut-off point 16-MAR-2000 MGD bugfix; AuthSearchConfig() removed '.' (?!) from match code 04-MAR-2000 MGD use FaolToNet(), et.al. 02-JAN-2000 MGD config file opened via ODS module 20-NOV-1999 MGD add nil-access identifier to bypass hour restrictions 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 #include #include #include #include /* VMS related header files */ #include #include #include #include /* application related header files */ #include "wasd.h" #define WASD_MODULE "AUTHCONFIG" #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 /******************/ /* global storage */ /******************/ BOOL AuthorizationEnabled, AuthConfigACME, AuthConfigSysUafUseACME, AuthFatalProblem, AuthNilAccessExists, AuthPolicyAuthorizedOnly, AuthPolicySysUafRelaxed, AuthPolicySslOnly, AuthPolicySysUafIdentifiers, AuthPolicySysUafProxy, AuthPolicySysUafSslOnly, AuthPolicySysUafVms, AuthPolicySysUafWasdIdentifiers, AuthPromiscuous, AuthProtectRule, AuthRealmToken, AuthRealmX509, AuthSysUafEnabled, AuthSysUafPromiscuous, AuthVmsUserProfileEnabled, AuthVmsUserProfileNoRule; int AuthFailureLimit, AuthFailurePeriodSeconds, AuthFailureTimeoutSeconds; unsigned long AuthHttpsOnlyVmsIdentifier, AuthNilAccessVmsIdentifier, AuthPasswordChangeVmsIdentifier, AuthProxyAccessVmsIdentifier, AuthWasdPwdVmsIdentifier, AuthWasdHttpsVmsIdentifier, AuthWasdReadVmsIdentifier, AuthWasdWriteVmsIdentifier; char *AuthConfigHtaDirectory, *AuthPromiscuousPwdPtr; AUTH_CONFIG_META AuthMeta; AUTH_CONFIG_META *AuthMetaPtr; /********************/ /* external storage */ /********************/ extern BOOL AuthAcmeLinked; extern int EfnWait, ServerPort; extern int ToLowerCase[], ToUpperCase[]; extern char ErrorSanityCheck[], SoftwareID[]; extern ACCOUNTING_STRUCT *AccountingPtr; extern CONFIG_STRUCT Config; extern HTTPD_GBLSEC *HttpdGblSecPtr; extern META_CONFIG *MetaGlobalAuthPtr; extern MSG_STRUCT Msgs; extern SYS_INFO SysInfo; extern WATCH_STRUCT Watch; /*****************************************************************************/ /* Initialize the authentication/authorization environment. Is used at server startup and when the authorization configuration is reloaded. */ AuthConfigInit () { static unsigned long LgiBrkTmo, LgiBrkLim, LgiHidTim; static VMS_ITEM_LIST3 SyiItem [] = { { sizeof(LgiBrkTmo), SYI$_LGI_BRK_TMO, &LgiBrkTmo, 0 }, { sizeof(LgiBrkLim), SYI$_LGI_BRK_LIM, &LgiBrkLim, 0 }, { sizeof(LgiHidTim), SYI$_LGI_HID_TIM, &LgiHidTim, 0 }, { 0,0,0,0 } }; static $DESCRIPTOR (LnmFileDevDsc, "LNM$FILE_DEV"); static $DESCRIPTOR (NoAcmeDsc, "WASD_NO_ACME"); static $DESCRIPTOR (NoSysUafAcmeDsc, "WASD_NO_SYSUAF_ACME"); int status; IO_SB IOsb; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigInit()"); /* if ACME available and linked into this image */ if (SysInfo.VersionInteger >= 730 && AuthAcmeLinked) { /* provide ACME on capable systems unless development logical defined */ status = sys$trnlnm (0, &LnmFileDevDsc, &NoAcmeDsc, 0, 0); if (status == SS$_NOLOGNAM) AuthConfigACME = true; } if (AuthConfigACME) { /* allow mandatory SYSUAF authentication using ACME to be disabled */ status = sys$trnlnm (0, &LnmFileDevDsc, &NoSysUafAcmeDsc, 0, 0); if (status == SS$_NOLOGNAM) AuthConfigSysUafUseACME = true; } MetaConUnload (&MetaGlobalAuthPtr, NULL); AuthConfigLoad (&MetaGlobalAuthPtr); AuthConfigHtaDirectory = v10orPrev10 (HTA_DIRECTORY,-1); status = sys$getsyiw (EfnWait, 0, 0, &SyiItem, &IOsb, 0, 0); if (VMSok (status)) status = IOsb.Status; if (VMSnok (status)) ErrorExitVmsStatus (status, NULL, FI_LI); if (WATCH_MODULE(WATCH_MOD_AUTH)) WatchThis (WATCHALL, WATCH_MOD_AUTH, "LGI !UL !UL !UL", LgiBrkTmo, LgiBrkLim, LgiHidTim); if (Config.cfAuth.FailureLimit) AuthFailureLimit = Config.cfAuth.FailureLimit; else AuthFailureLimit = LgiBrkLim; if (Config.cfAuth.FailurePeriodSeconds) AuthFailurePeriodSeconds = Config.cfAuth.FailurePeriodSeconds; else AuthFailurePeriodSeconds = LgiBrkTmo; if (Config.cfAuth.FailureTimeoutSeconds) AuthFailureTimeoutSeconds = Config.cfAuth.FailureTimeoutSeconds; else AuthFailureTimeoutSeconds = LgiHidTim; } /*****************************************************************************/ /* Load authorization rules into meta-config structure. */ int AuthConfigLoad (META_CONFIG **MetaConPtrPtr) { int status; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigLoad()"); status = MetaConLoad (MetaConPtrPtr, v10orPrev10(CONFIG_AUTH_FILE_NAME, CONFIG_AUTH_FILE_NAME), &AuthConfigLoadCallBack, true, true); if (*MetaConPtrPtr == MetaGlobalAuthPtr) { /* server startup/reload */ MetaConStartupReport (MetaGlobalAuthPtr, "AUTH"); if (VMSnok (status)) exit (status); } return (status); } /*****************************************************************************/ /* Called by MetaConUnload() to free resources allocated during authorization configuration. */ AuthConfigUnload (META_CONFIG *mcptr) { int status; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigUnload()"); if (mcptr->AuthMetaPtr) { if (mcptr->AuthMetaPtr == AuthMetaPtr) { memset (AuthMetaPtr, 0, sizeof(AUTH_CONFIG_META)); AuthMetaPtr = NULL; } else VmFree (mcptr->AuthMetaPtr, FI_LI); mcptr->AuthMetaPtr = NULL; } } /*****************************************************************************/ /* Called by MetaConUnload() callback for each line's associated data, basically to check for a regular expression structure and free it if present, then just dispose of the line data itself. */ AuthConfigUnloadLineData (void *LineDataPtr) { int status; AUTH_PATH *apptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigUnloadLineData()"); apptr = (AUTH_PATH*)LineDataPtr; if (apptr->RegexPregPath.buffer) regfree (&apptr->RegexPregPath); VmFree (apptr, FI_LI); } /*****************************************************************************/ /* For each non-meta-config directive line read by MetaConLoad() this function is called to parse the line text's contents and to configure the private data structure associated with each rule. */ BOOL AuthConfigLoadCallBack (META_CONFIG *mcptr) { static char ProblemOverflow [] = "Storage overflow", ProblemProxyFile [] = "Error opening proxy file"; int status; char *cptr, *sptr, *zptr; char Scratch [256], StringBuffer [1024]; AUTH_CONFIG_META *acptr; METACON_LINE *mclptr; ODS_STRUCT ProxyFileOds; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) { WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigLoadCallBack() !&F !&X", &AuthConfigLoadCallBack, mcptr); if (WATCH_MODULE(WATCH_MOD__DETAIL)) { mclptr = mcptr->ParsePtr; WatchDataFormatted ("!&X !UL !UL !UL !UL !&X !&Z !&Z\n", mclptr, mclptr->Size, mclptr->Token, mclptr->Number, mclptr->Length, mclptr->LineDataPtr, mclptr->TextPtr, mclptr->InlineTextPtr); } } /* get a pointer to the current "line" */ mclptr = mcptr->ParsePtr; /* if this is during server startup/reload set the global service pointer */ if (mcptr == MetaGlobalAuthPtr) acptr = mcptr->AuthMetaPtr = AuthMetaPtr = &AuthMeta; else /* if a report then conjure one up by divine fiat */ if (!mcptr->AuthMetaPtr) acptr = mcptr->AuthMetaPtr = VmGet (sizeof(AUTH_CONFIG_META)); else /* not the first time through */ acptr = mcptr->AuthMetaPtr; if (mclptr->Token == METACON_TOKEN_PRE) { /******************/ /* pre-initialize */ /******************/ AuthConfigProxy (NULL, NULL); AuthConfigLine (NULL, NULL); /* if global service pointer, during server startup or reload */ if (mcptr == MetaGlobalAuthPtr) memset (acptr, 0, sizeof(AUTH_CONFIG_META)); return (true); } if (mclptr->Token == METACON_TOKEN_POST) { /****************/ /* post-process */ /****************/ AuthConfigOther (mcptr); AuthConfigProxy (NULL, NULL); AuthConfigLine (NULL, NULL); return (true); } /***********/ /* process */ /***********/ /* if it's not text/inline then authorization is not interested in it */ if (mclptr->Token != METACON_TOKEN_TEXT && !mclptr->InlineTextPtr) return (true); /* buffer the text associated with the current "line" */ zptr = (sptr = StringBuffer) + sizeof(StringBuffer); if (mclptr->InlineTextPtr) cptr = mclptr->InlineTextPtr; else cptr = mclptr->TextPtr; while (*cptr && sptr < zptr) *sptr++ = *cptr++; if (sptr >= zptr) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemOverflow); return (false); } *sptr = '\0'; cptr = StringBuffer; if (strsame (cptr, "[AuthProxy]", 11)) { /* SYSUAF proxy mapping(s) */ if (acptr->ProxyRuleReset) { AuthConfigProxy (NULL, NULL); acptr->ProxyRuleReset = false; } AuthConfigProxy (mcptr, cptr+11); return (true); } if (strsame (cptr, "[AuthProxyFile]", 15)) { /* file of SYSUAF proxy mappings */ if (acptr->ProxyRuleReset) { AuthConfigProxy (NULL, NULL); acptr->ProxyRuleReset = false; } /* terminate the filename */ cptr += 15; while (*cptr && ISLWS(*cptr)) cptr++; for (sptr = cptr; *sptr && !ISLWS(*sptr); sptr++); *sptr = '\0'; /* a proxy file specification */ status = OdsLoadTextFile (&ProxyFileOds, cptr); if (VMSnok (status)) { MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemProxyFile); FaoToBuffer (Scratch, sizeof(Scratch), NULL, "ERROR=%X!XL@!AZ", status, cptr); AuthConfigProxy (mcptr, Scratch); return (true); } /* pass each line feeding to the proxy configurator */ for (;;) { cptr = OdsParseTextFile (&ProxyFileOds, '\\'); if (!cptr) break; /* if a blank or comment line, then ignore */ while (ISLWS(*cptr)) cptr++; if (!*cptr || *cptr == '!' || *cptr == '#') continue; AuthConfigProxy (mcptr, cptr); } return (true); } acptr->ProxyRuleReset = true; AuthConfigLine (mcptr, cptr); return (true); } /*****************************************************************************/ /* Other things that need initing after the rules have been loaded. */ AuthConfigOther (META_CONFIG *mcptr) { static $DESCRIPTOR (AuthHttpsOnlyVmsIdentifierDsc, AUTH_HTTPS_ONLY_VMS_ID); static $DESCRIPTOR (AuthNilAccessVmsIdentifierDsc, AUTH_NIL_ACCESS_VMS_ID); static $DESCRIPTOR (AuthPasswordChangeVmsIdentifierDsc, AUTH_PASSWORD_CHANGE_VMS_ID); static $DESCRIPTOR (AuthProxyAccessVmsIdentifierDsc, AUTH_PROXY_ACCESS_VMS_ID); static $DESCRIPTOR (AuthWasdHttpsVmsIdentifierDsc, AUTH_WASD_HTTPS_VMS_ID); static $DESCRIPTOR (AuthWasdPwdVmsIdentifierDsc, AUTH_WASD_PWD_VMS_ID); static $DESCRIPTOR (AuthWasdReadVmsIdentifierDsc, AUTH_WASD_READ_VMS_ID); static $DESCRIPTOR (AuthWasdWriteVmsIdentifierDsc, AUTH_WASD_WRITE_VMS_ID); int status; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigOther()"); /* but only if we're dealing with the global configuration */ if (mcptr != MetaGlobalAuthPtr) return; AuthNilAccessExists = false; /* it's implied! */ if (AuthPolicySysUafWasdIdentifiers) AuthPolicySysUafIdentifiers = true; if (AuthPromiscuous) MetaConReport (mcptr, METACON_REPORT_WARNING, "!AZ authenticating any username with !&?specified\rany\r password!!", AUTH_REALM_PROMISCUOUS, AuthPromiscuousPwdPtr); if (AuthPolicyAuthorizedOnly) MetaConReport (mcptr, METACON_REPORT_INFORM, "All request paths must be authorized"); if (AuthPolicySslOnly) MetaConReport (mcptr, METACON_REPORT_INFORM, "Only SSL (https:) will be authorized"); if (AuthSysUafPromiscuous) MetaConReport (mcptr, METACON_REPORT_WARNING, "SYSUAF !AZ (testing only)\n", AUTH_REALM_PROMISCUOUS); if (AuthSysUafEnabled) { if (AuthPolicySysUafIdentifiers) { if (AuthPolicySysUafVms) MetaConReport (mcptr, METACON_REPORT_INFORM, "SYSUAF authentication enabled (rights identifier available)"); else MetaConReport (mcptr, METACON_REPORT_INFORM, "SYSUAF authentication enabled (only via rights identifier)"); } else if (AuthPolicySysUafWasdIdentifiers) MetaConReport (mcptr, METACON_REPORT_INFORM, "SYSUAF authentication enabled (via WASD identifier - deprecated)"); else MetaConReport (mcptr, METACON_REPORT_INFORM, "SYSUAF authentication enabled"); } if (AuthVmsUserProfileEnabled) { if (AuthVmsUserProfileNoRule) MetaConReport (mcptr, METACON_REPORT_INFORM, "VMS security profile enabled (pre-8.2 behaviour)"); else MetaConReport (mcptr, METACON_REPORT_INFORM, "VMS security profile enabled (only by authorization rule)"); } if (AuthPolicySysUafIdentifiers) { status = sys$asctoid (&AuthHttpsOnlyVmsIdentifierDsc, &AuthHttpsOnlyVmsIdentifier, 0); if (VMSnok (status)) MetaConReport (mcptr, METACON_REPORT_INFORM, "Optional identifier !AZ\n%!&M", AUTH_HTTPS_ONLY_VMS_ID, status); status = sys$asctoid (&AuthNilAccessVmsIdentifierDsc, &AuthNilAccessVmsIdentifier, 0); if (VMSnok (status)) MetaConReport (mcptr, METACON_REPORT_INFORM, "Optional identifier !AZ\n%!&M", AUTH_NIL_ACCESS_VMS_ID, status); else AuthNilAccessExists = true; status = sys$asctoid (&AuthPasswordChangeVmsIdentifierDsc, &AuthPasswordChangeVmsIdentifier, 0); if (VMSnok (status)) MetaConReport (mcptr, METACON_REPORT_INFORM, "Optional identifier !AZ\n%!&M", AUTH_PASSWORD_CHANGE_VMS_ID, status); if (AuthPolicySysUafProxy && (AuthPolicySysUafIdentifiers || AuthPolicySysUafWasdIdentifiers)) { status = sys$asctoid (&AuthProxyAccessVmsIdentifierDsc, &AuthProxyAccessVmsIdentifier, 0); if (VMSnok (status)) MetaConReport (mcptr, METACON_REPORT_ERROR, "Required identifier !AZ\n%!&M", AUTH_PROXY_ACCESS_VMS_ID, status); } } if (AuthPolicySysUafWasdIdentifiers) { status = sys$asctoid (&AuthWasdWriteVmsIdentifierDsc, &AuthWasdWriteVmsIdentifier, 0); if (VMSnok (status)) MetaConReport (mcptr, METACON_REPORT_ERROR, "Required identifier !AZ\n%!&M", AUTH_WASD_WRITE_VMS_ID, status); status = sys$asctoid (&AuthWasdReadVmsIdentifierDsc, &AuthWasdReadVmsIdentifier, 0); if (VMSnok (status)) MetaConReport (mcptr, METACON_REPORT_ERROR, "Required identifier !AZ\n%!&M", AUTH_WASD_READ_VMS_ID, status); status = sys$asctoid (&AuthWasdHttpsVmsIdentifierDsc, &AuthWasdHttpsVmsIdentifier, 0); if (VMSnok (status)) MetaConReport (mcptr, METACON_REPORT_ERROR, "Required identifier !AZ\n%!&M", AUTH_WASD_HTTPS_VMS_ID, status); status = sys$asctoid (&AuthWasdPwdVmsIdentifierDsc, &AuthWasdPwdVmsIdentifier, 0); if (VMSnok (status)) MetaConReport (mcptr, METACON_REPORT_ERROR, "Required identifier !AZ\n%!&M", AUTH_WASD_PWD_VMS_ID, status); } if (!(Config.cfAuth.BasicEnabled || Config.cfAuth.DigestEnabled)) MetaConReport (mcptr, METACON_REPORT_WARNING, "Neither BASIC or DIGEST authentication enabled"); if (!AuthorizationEnabled) MetaConReport (mcptr, METACON_REPORT_WARNING, "AUTHORIZATION DISABLED"); /* initialize the authentication cache */ AuthCacheInit (mcptr); AuthTokenInit (); /* also flush the server persona cache */ PersonaCache (NULL, 0); } /*****************************************************************************/ /* Process a line of authorization configuration. */ #define PATH_PARAMETER_SIZE AUTH_MAX_PATH_PARAM_LENGTH #define ACCESS_RESTRICTION_LIST_SIZE PATH_PARAMETER_SIZE+255 AuthConfigLine ( META_CONFIG *mcptr, char *Line ) { static int CurrentSourceRealm; static char RealmCanString [ACCESS_RESTRICTION_LIST_SIZE+1]; BOOL FinalRule, NoCache, PathProblem, PathIsRegex, RealmProblem, VmsUserProfile, VmsUserScriptAs; int status; int SourceGroupRead, SourceGroupWrite, SourceRealm; unsigned long *CanFlagsPtr; unsigned long GroupCanFlags, GroupReadVmsIdentifier, GroupWriteVmsIdentifier, RealmCanFlags, RealmVmsIdentifier, WorldCanFlags; char *cptr, *lptr, *sptr, *zptr, *PathTemplatePtr, *ProxyStringPtr, *RestrictListPtr; char CanScratch [ACCESS_RESTRICTION_LIST_SIZE*2+1], GroupRead [AUTH_MAX_REALM_GROUP_LENGTH+1], GroupRestrictList [ACCESS_RESTRICTION_LIST_SIZE+1], GroupWrite [AUTH_MAX_REALM_GROUP_LENGTH+1], PathParameter [PATH_PARAMETER_SIZE+1], Realm [AUTH_MAX_REALM_GROUP_LENGTH+1], RealmDescription [AUTH_MAX_REALM_DESCR_LENGTH+1], RealmParameter [AUTH_MAX_REALM_PARAM_LENGTH+1], WorldRestrictList [ACCESS_RESTRICTION_LIST_SIZE+1]; METACON_LINE *mclptr; regex_t RegexPreg; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigLine() !&Z", Line); if (!Line) { /* initialize */ CurrentSourceRealm = 0; RealmCanString[0] = '\0'; return; } /* get a pointer to the current "line" */ mclptr = mcptr->ParsePtr; FinalRule = NoCache = PathProblem = RealmProblem = VmsUserProfile = VmsUserScriptAs = false; GroupCanFlags = GroupReadVmsIdentifier = GroupWriteVmsIdentifier = RealmVmsIdentifier = RealmCanFlags = SourceGroupRead = SourceGroupWrite = WorldCanFlags = 0; PathTemplatePtr = NULL; ProxyStringPtr = ""; GroupRead[0] = GroupWrite[0] = GroupRestrictList[0] = Realm[0] = RealmDescription[0] = RealmParameter[0] = PathParameter[0] = WorldRestrictList[0] = '\0'; CanFlagsPtr = &GroupCanFlags; RestrictListPtr = &GroupRestrictList; lptr = Line; if (*lptr == '[' || strsame (lptr, "REALM", 5)) { /*********/ /* realm */ /*********/ if (*lptr == '[') { lptr++; while (*lptr && ISLWS(*lptr)) lptr++; } else { /* skip over keyword and find start of realm name */ while (*lptr && !ISLWS(*lptr)) lptr++; while (*lptr && ISLWS(*lptr)) lptr++; } /* new realm resets proxy mappings */ AuthConfigProxy (NULL, NULL); /* by default (and historically) it's HTA */ SourceRealm = AUTH_SOURCE_HTA; if (*lptr == '\"') { lptr++; zptr = (sptr = RealmDescription) + sizeof(RealmDescription); while (*lptr && *lptr != '\"') { if (sptr < zptr) *sptr++ = *lptr; lptr++; } if (sptr >= zptr) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Problem configuring realm description"); RealmProblem = true; lptr = "]"; } else *sptr = '\0'; if (*lptr == '\"') lptr++; if (*lptr == '=') lptr++; } zptr = (sptr = Realm) + sizeof(Realm); while (*lptr && *lptr != ';' && *lptr != '=' && *lptr != '+' && *lptr != ']' && !ISLWS(*lptr)) { if (sptr < zptr) *sptr++ = TOUP(*lptr); lptr++; } if (sptr >= zptr || !Realm[0]) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Problem configuring realm"); RealmProblem = true; lptr = "]"; } *sptr = '\0'; if (*lptr == '=') { if (strsame (lptr, "=ACME", 5)) { lptr += 5; SourceRealm = AUTH_SOURCE_ACME; } else if (strsame (lptr, "=AGENT+OPAQUE", 13)) { lptr += 13; SourceRealm = AUTH_SOURCE_AGENT_OPAQUE; } else if (strsame (lptr, "=AGENT", 6)) { lptr += 6; SourceRealm = AUTH_SOURCE_AGENT; } else if (strsame (lptr, "=HTA", 4)) { lptr += 4; SourceRealm = AUTH_SOURCE_HTA; } else if (strsame (lptr, "=@HTA", 5)) { lptr += 5; SourceRealm = AUTH_SOURCE_DIR_HTA; } else if (strsame (lptr, "=HOST", 5)) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Host group cannot be an authentication realm"); RealmProblem = true; lptr = "]"; } else if (strsame (lptr, "=ID", 3)) { lptr += 3; SourceRealm = AUTH_SOURCE_ID; if (VMSnok (status = AuthConfigIdentifier (Realm, &RealmVmsIdentifier))) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Realm !AZ identifier %!&M", Realm, status); RealmProblem = true; lptr = "]"; } } else if (strsame (lptr, "=LIST", 5)) { lptr += 5; SourceRealm = AUTH_SOURCE_LIST; } else if (strsame (lptr, "=@LIST", 6)) { lptr += 6; SourceRealm = AUTH_SOURCE_DIR_LIST; } else if (strsame (lptr, "=TOKEN", 6)) { lptr += 6; SourceRealm = AUTH_SOURCE_TOKEN; } else if (strsame (lptr, "=VMS", 4)) { lptr += 4; SourceRealm = AUTH_SOURCE_VMS; } else if (strsame (lptr, "=X509", 5)) { lptr += 5; SourceRealm = AUTH_SOURCE_X509; } else if (strsame (lptr, "=RFC1413", 8)) { lptr += 8; SourceRealm = AUTH_SOURCE_RFC1413; } else { MetaConReport (mcptr, METACON_REPORT_ERROR, "Problem configuring realm source"); RealmProblem = true; lptr = "]"; } } else { /* does it look like a host group? */ for (sptr = Realm; *sptr && isdigit(*sptr); sptr++); if (*sptr == '.') { MetaConReport (mcptr, METACON_REPORT_ERROR, "Host group cannot be an authentication realm"); RealmProblem = true; lptr = "]"; } } /* 'VMS' is a required ACME agent */ if (SourceRealm == AUTH_SOURCE_ACME) SourceRealm = AUTH_SOURCE_ACME; else /* if was "VMS" then it's SYSUAF no matter what was made equal to!! */ if (strsame (Realm, AUTH_REALM_VMS, -1)) SourceRealm = AUTH_SOURCE_VMS; else /* same for "WORLD" */ if (strsame (Realm, AUTH_REALM_WORLD, -1)) SourceRealm = AUTH_SOURCE_WORLD; else /* same for "OPAQUE" */ if (strsame (Realm, AUTH_REALM_OPAQUE, -1)) SourceRealm = AUTH_SOURCE_OPAQUE; else /* and "X509" */ if (strsame (Realm, AUTH_REALM_X509, -1)) SourceRealm = AUTH_SOURCE_X509; else /* and "RFC1413" */ if (strsame (Realm, AUTH_REALM_RFC1413, -1)) SourceRealm = AUTH_SOURCE_RFC1413; else /* and "SKELKEY" */ if (strsame (Realm, AUTH_REALM_SKELKEY, -1)) SourceRealm = AUTH_SOURCE_SKELKEY; else /* and "TOKEN" */ if (strsame (Realm, AUTH_REALM_TOKEN, -1)) SourceRealm = AUTH_SOURCE_TOKEN; else /* and for "EXTERNAL" */ if (strsame (Realm, AUTH_REALM_EXTERNAL, -1)) SourceRealm = AUTH_SOURCE_EXTERNAL; else /* and "NONE" */ if (strsame (Realm, AUTH_REALM_NONE, -1)) SourceRealm = AUTH_SOURCE_NONE; else /* and last but by no means least "PROMISCUOUS" */ if (strsame (Realm, AUTH_REALM_PROMISCUOUS, -1)) SourceRealm = AUTH_SOURCE_PROMISCUOUS; if (AuthPolicySysUafWasdIdentifiers) { /* If this is the VMS realm and identifiers are mandatory for SYSUAF authentication but the realm is not a specific identifier then it must be through the "hard-wired" WASD identifiers. */ if (SourceRealm == AUTH_SOURCE_VMS && AuthPolicySysUafIdentifiers) SourceRealm = AUTH_SOURCE_WASD_ID; } if (SourceRealm == AUTH_SOURCE_ACME && !AuthConfigACME) { MetaConReport (mcptr, METACON_REPORT_ERROR, "ACME authentication is not available"); RealmProblem = true; lptr = "]"; } while (*lptr && ISLWS(*lptr)) lptr++; if (*lptr == '+') { /****************************/ /* optional realm parameter */ /****************************/ lptr++; while (*lptr && ISLWS(*lptr)) lptr++; zptr = (sptr = RealmParameter) + sizeof(RealmParameter)-1; if (*lptr == '\"') { lptr++; while (*lptr && *lptr != '\"' && sptr < zptr) *sptr++ = *lptr++; if (*lptr == '\"') lptr++; } else while (*lptr && *lptr != ';' && *lptr != ']' && !ISLWS(*lptr) && sptr < zptr) *sptr++ = *lptr++; if (sptr >= zptr || !RealmParameter[0]) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Problem configuring realm parameter"); RealmProblem = true; lptr = "]"; } *sptr = '\0'; } while (*lptr && ISLWS(*lptr)) lptr++; /* semicolon separating realm from optional full-access (write) group */ if (*lptr == ';') { /*****************************/ /* optional read+write group */ /*****************************/ SourceGroupWrite = AUTH_SOURCE_HTA; lptr++; while (*lptr && ISLWS(*lptr)) lptr++; zptr = (sptr = GroupWrite) + sizeof(GroupWrite)-1; while (*lptr && *lptr != ';' && *lptr != '=' && *lptr != ']' && !ISLWS(*lptr) && sptr < zptr) *sptr++ = TOUP(*lptr++); if (sptr >= zptr || !GroupWrite[0]) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Problem configuring (first) group"); RealmProblem = true; lptr = "]"; } *sptr = '\0'; if (*lptr == '=') { if (strsame (lptr, "=AGENT+OPAQUE", 13)) { lptr += 13; SourceGroupWrite = AUTH_SOURCE_AGENT_OPAQUE; } else if (strsame (lptr, "=AGENT", 6)) { lptr += 6; SourceGroupWrite = AUTH_SOURCE_AGENT; } else if (strsame (lptr, "=HTA", 4)) { lptr += 4; SourceGroupWrite = AUTH_SOURCE_HTA; } else if (strsame (lptr, "=@HTA", 5)) { lptr += 5; SourceGroupWrite = AUTH_SOURCE_DIR_HTA; } else if (strsame (lptr, "=HOST", 5)) { lptr += 5; SourceGroupWrite = AUTH_SOURCE_HOST; } else if (strsame (lptr, "=ID", 3)) { lptr += 3; SourceGroupWrite = AUTH_SOURCE_ID; if (VMSnok (status = AuthConfigIdentifier (GroupWrite, &GroupWriteVmsIdentifier))) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Group !AZ identifier\n%!&M", GroupWrite, status); RealmProblem = true; lptr = "]"; } } else if (strsame (lptr, "=LIST", 5)) { lptr += 5; SourceGroupWrite = AUTH_SOURCE_LIST; } else if (strsame (lptr, "=@LIST", 6)) { lptr += 6; SourceGroupWrite = AUTH_SOURCE_DIR_LIST; } else if (strsame (lptr, "=X509", 5)) { lptr += 5; SourceGroupWrite = AUTH_SOURCE_X509; } else if (strsame (lptr, "=RFC1413", 8)) { lptr += 8; SourceGroupWrite = AUTH_SOURCE_RFC1413; } else if (strsame (lptr, "=TOKEN", 6)) { lptr += 6; SourceGroupWrite = AUTH_SOURCE_TOKEN; } else { MetaConReport (mcptr, METACON_REPORT_ERROR, "Problem configuring (first) group source"); RealmProblem = true; lptr = "]"; } } else { /* does it look like a host group? */ for (sptr = GroupWrite; *sptr && isdigit(*sptr); sptr++); if (*sptr == '.') SourceGroupWrite = AUTH_SOURCE_HOST; } } /* semicolon separating realm from optional read-only-access group */ if (*lptr == ';') { /****************************/ /* optional read-only group */ /****************************/ SourceGroupRead = AUTH_SOURCE_HTA; lptr++; while (*lptr && ISLWS(*lptr)) lptr++; zptr = (sptr = GroupRead) + sizeof(GroupRead)-1; while (*lptr && *lptr != '=' && *lptr != ']' && !ISLWS(*lptr) && sptr < zptr) *sptr++ = TOUP(*lptr++); if (sptr >= zptr || !GroupRead[0]) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Problem configuring second group"); RealmProblem = true; lptr = "]"; } *sptr = '\0'; if (*lptr == '=') { if (strsame (lptr, "=AGENT+OPAQUE", 13)) { lptr += 6; SourceGroupRead = AUTH_SOURCE_AGENT_OPAQUE; } else if (strsame (lptr, "=AGENT", 6)) { lptr += 6; SourceGroupRead = AUTH_SOURCE_AGENT; } else if (strsame (lptr, "=HTA", 4)) { lptr += 4; SourceGroupRead = AUTH_SOURCE_HTA; } else if (strsame (lptr, "=@HTA", 5)) { lptr += 5; SourceGroupRead = AUTH_SOURCE_DIR_HTA; } else if (strsame (lptr, "=HOST", 5)) { lptr += 5; SourceGroupRead = AUTH_SOURCE_HOST; } else if (strsame (lptr, "=ID", 3)) { lptr += 3; SourceGroupRead = AUTH_SOURCE_ID; if (VMSnok (status = AuthConfigIdentifier (GroupRead, &GroupReadVmsIdentifier))) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Group !AZ identifier\n%!&M", GroupWrite, status); RealmProblem = true; lptr = "]"; } } else if (strsame (lptr, "=LIST", 5)) { lptr += 5; SourceGroupRead = AUTH_SOURCE_LIST; } else if (strsame (lptr, "=@LIST", 6)) { lptr += 6; SourceGroupRead = AUTH_SOURCE_DIR_LIST; } else if (strsame (lptr, "=X509", 5)) { lptr += 5; SourceGroupRead = AUTH_SOURCE_X509; } else if (strsame (lptr, "=RFC1413", 8)) { lptr += 8; SourceGroupRead = AUTH_SOURCE_RFC1413; } else if (strsame (lptr, "=TOKEN", 6)) { lptr += 6; SourceGroupRead = AUTH_SOURCE_TOKEN; } else { MetaConReport (mcptr, METACON_REPORT_ERROR, "Problem configuring second group source"); RealmProblem = true; lptr = "]"; } } else if (GroupRead[0] == '*') SourceGroupRead = AUTH_SOURCE_THEREST; else { /* does it look like a host group? */ for (sptr = GroupRead; *sptr && isdigit(*sptr); sptr++); if (*sptr == '.') SourceGroupWrite = AUTH_SOURCE_HOST; } } while (*lptr && ISLWS(*lptr)) lptr++; if (*lptr == ']') lptr++; else { lptr = ""; MetaConReport (mcptr, METACON_REPORT_ERROR, "Generally confused\n"); RealmProblem = true; } /* find start of any realm-context access directives */ while (*lptr && ISLWS(*lptr)) lptr++; if (*lptr) { zptr = (sptr = RealmCanString) + sizeof(RealmCanString)-1; while (*lptr && sptr < zptr) *sptr++ = *lptr++; *sptr = '\0'; } else RealmCanString[0] = '\0'; /***************************/ /* bit more usage checking */ /***************************/ if ((SourceRealm == AUTH_SOURCE_VMS || SourceRealm == AUTH_SOURCE_ID) && !AuthSysUafEnabled) { MetaConReport (mcptr, METACON_REPORT_ERROR, "/SYSUAF not enabled at command line"); RealmProblem = true; } if (SourceRealm == AUTH_SOURCE_VMS && !AuthPolicySysUafVms && AuthPolicySysUafIdentifiers) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Realm indicates VMS but /SYSUAF=VMS not enabled at command line"); RealmProblem = true; } if (SourceRealm == AUTH_SOURCE_ID && AuthPolicySysUafVms && !AuthPolicySysUafIdentifiers) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Realm indicates ID but /SYSUAF=ID not enabled at command line"); RealmProblem = true; } if ((SourceGroupWrite == AUTH_SOURCE_ID || SourceGroupRead == AUTH_SOURCE_ID) && SourceRealm != AUTH_SOURCE_VMS && SourceRealm != AUTH_SOURCE_ID) { MetaConReport (mcptr, METACON_REPORT_ERROR, "ID used without SYSUAF authentication"); RealmProblem = true; } if (SourceRealm == AUTH_SOURCE_WASD_ID && SourceGroupWrite != AUTH_SOURCE_WASD_ID && AuthPolicySysUafWasdIdentifiers && (GroupWrite[0] || GroupRead[0])) { MetaConReport (mcptr, METACON_REPORT_ERROR, "\"Hard-wired\" WASD identifier usage problem"); RealmProblem = true; } if (SourceRealm == AUTH_SOURCE_TOKEN) { int IPport = atoi(Realm); if (Realm[0] && IPport < 0 || IPport > 65535) { MetaConReport (mcptr, METACON_REPORT_ERROR, "TOKEN port misconfigured"); RealmProblem = true; } } /*************************/ /* close enough for jazz */ /*************************/ AuthConfigAddRealm (mcptr, RealmProblem, Realm, RealmDescription, RealmParameter, SourceRealm, RealmVmsIdentifier, GroupWrite, SourceGroupWrite, GroupWriteVmsIdentifier, GroupRead, SourceGroupRead, GroupReadVmsIdentifier, GroupCanFlags, WorldCanFlags); CurrentSourceRealm = SourceRealm; return; } if (*lptr != '[' && !strsame (lptr, "REALM", 5)) { /********/ /* path */ /********/ if (!CurrentSourceRealm) MetaConReport (mcptr, METACON_REPORT_ERROR, "No realm to apply"); /* if not already retrieved (try to) get (any) proxy mappings */ if (!ProxyStringPtr[0]) ProxyStringPtr = AuthConfigProxy (mcptr, NULL); /* a single dollar effectively indicates 'cancel all proxies' */ if (SAME2(ProxyStringPtr,'$\0')) ProxyStringPtr = ""; /* note start of path template */ PathTemplatePtr = lptr; while (*lptr && !ISLWS(*lptr)) lptr++; /* terminate at the end of the path template */ if (*lptr) *lptr++ = '\0'; PathIsRegex = false; if (Config.cfMisc.RegexSyntax && *PathTemplatePtr == REGEX_CHAR) { cptr = StringRegexCompile (PathTemplatePtr+1, &RegexPreg); if (cptr) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Regex: !AZ", cptr); PathProblem = true; } else { regfree (&RegexPreg); PathIsRegex = true; } } /* find start of access flags */ while (*lptr && ISLWS(*lptr)) lptr++; if (*lptr) { if (CurrentSourceRealm == AUTH_SOURCE_OPAQUE) { /* should be nothing more on the line but there is */ MetaConReport (mcptr, METACON_REPORT_WARNING, "Paths in opaque realms require no parameters - ignored"); lptr = ""; } else if (SAME2(RealmCanString,'+=')) { /* concatenate realm defaults to path access directives */ zptr = (sptr = CanScratch) + sizeof(CanScratch)-1; while (*lptr && sptr < zptr) *sptr++ = *lptr++; for (lptr = RealmCanString+2; *lptr && sptr < zptr; *sptr++ = *lptr++); *sptr = '\0'; lptr = CanScratch; } } else { if (CurrentSourceRealm != AUTH_SOURCE_OPAQUE) { /* nothing more on the line! */ if (RealmCanString[0]) lptr = RealmCanString; else { MetaConReport (mcptr, METACON_REPORT_ERROR, "No access specified and no realm defaults"); lptr = ""; PathProblem = true; } } } while (*lptr) { /********************************/ /* set flags controlling access */ /********************************/ /* find the start of the next element */ while (*lptr && (ISLWS(*lptr) || *lptr == ',' || *lptr == ';')) { if (*lptr++ != ';') continue; /* semicolon separates realm/group and optional world access */ CanFlagsPtr = &WorldCanFlags; RestrictListPtr = &WorldRestrictList; } if (!*lptr) break; if (*lptr == '*' || *lptr == '#' || isdigit(*lptr) || *lptr == '~' || strsame (lptr, "http:", 5) || strsame (lptr, "https:", 6) || strsame (lptr, "localhost", 9)) { /* access restriction list */ for (sptr = RestrictListPtr; *sptr; sptr++); zptr = RestrictListPtr + ACCESS_RESTRICTION_LIST_SIZE; if (sptr > RestrictListPtr && sptr < zptr) *sptr++ = ','; while (*lptr && !ISLWS(*lptr) && *lptr != ',' && *lptr != ';' && sptr < zptr) *sptr++ = *lptr++; if (sptr >= zptr) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Restriction list too long"); PathProblem = true; break; } else *sptr = '\0'; } else if (strsame (lptr, "final", 5) && !isalpha(lptr[5])) FinalRule = true; else if (strsame (lptr, "param=", 6)) { /* agent parameter */ zptr = (sptr = PathParameter) + PATH_PARAMETER_SIZE; lptr += 6; if (*lptr == '\"') { /* delimitted by double quotes */ lptr++; while (*lptr && *lptr != '\"' && sptr < zptr) *sptr++ = *lptr++; if (*lptr) lptr++; } else if (*lptr == '\'') { /* delimitted by single quotes */ lptr++; while (*lptr && *lptr != '\'' && sptr < zptr) *sptr++ = *lptr++; if (*lptr) lptr++; } else { /* delimited by restriction list syntax */ while (*lptr && !ISLWS(*lptr) && *lptr != ',' && *lptr != ';' && sptr < zptr) *sptr++ = *lptr++; } if (sptr >= zptr) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Agent parameter too long"); PathProblem = true; break; } else *sptr = '\0'; } else if (strsame (lptr, "nocache", 7) && !isalpha(lptr[7])) NoCache = true; else if (strsame (lptr, "profile", 7) && !isalpha(lptr[7])) { VmsUserProfile = true; if (!AuthVmsUserProfileEnabled) MetaConReport (mcptr, METACON_REPORT_ERROR, "/PROFILE not enabled at command line"); } else if (strsame (lptr, "scriptas", 8) && !isalpha(lptr[8])) VmsUserScriptAs = true; else if (strsame (lptr, "none", 4) && !isalpha(lptr[4])) *CanFlagsPtr = 0; else /* must come before "read" for obvious reasons! */ if ((strsame (lptr, "READ+WRITE", 10) && !isalpha(lptr[10])) || (strsame (lptr, "R+W", 3) && !isalpha(lptr[3]))) *CanFlagsPtr |= HTTP_READ_METHODS | HTTP_WRITE_METHODS | HTTP_WEBDAV_READ_METHODS | HTTP_WEBDAV_WRITE_METHODS; else if ((strsame (lptr, "READ", 4) && !isalpha(lptr[4])) || (strsame (lptr, "R", 1) && !isalpha(lptr[1]))) *CanFlagsPtr |= HTTP_READ_METHODS | HTTP_WEBDAV_READ_METHODS; else if ((strsame (lptr, "WRITE", 5) && !isalpha(lptr[5])) || (strsame (lptr, "W", 1) && !isalpha(lptr[1]))) *CanFlagsPtr |= HTTP_WRITE_METHODS; else if (strsame (lptr, "CONNECT", 7) && !isalpha(lptr[7])) *CanFlagsPtr |= HTTP_METHOD_CONNECT; else if (strsame (lptr, "DELETE", 6) && !isalpha(lptr[6])) *CanFlagsPtr |= HTTP_METHOD_DELETE; else if (strsame (lptr, "GET", 3) && !isalpha(lptr[3])) *CanFlagsPtr |= HTTP_METHOD_GET | HTTP_METHOD_HEAD; else if (strsame (lptr, "HEAD", 4) && !isalpha(lptr[4])) *CanFlagsPtr |= HTTP_METHOD_HEAD; else if (strsame (lptr, "OPTIONS", 7) && !isalpha(lptr[7])) *CanFlagsPtr |= HTTP_METHOD_OPTIONS; else if (strsame (lptr, "POST", 4) && !isalpha(lptr[4])) *CanFlagsPtr |= HTTP_METHOD_POST; else if (strsame (lptr, "PUT", 3) && !isalpha(lptr[3])) *CanFlagsPtr |= HTTP_METHOD_PUT; else if (strsame (lptr, "TRACE", 5) && !isalpha(lptr[5])) *CanFlagsPtr |= HTTP_METHOD_TRACE; else if (strsame (lptr, "COPY", 4) && !isalpha(lptr[4])) *CanFlagsPtr |= HTTP_METHOD_WEBDAV_COPY; else if (strsame (lptr, "LOCK", 4) && !isalpha(lptr[4])) *CanFlagsPtr |= HTTP_METHOD_WEBDAV_LOCK; else if (strsame (lptr, "MOVE", 4) && !isalpha(lptr[4])) *CanFlagsPtr |= HTTP_METHOD_WEBDAV_MOVE; else if (strsame (lptr, "MKCOL", 5) && !isalpha(lptr[5])) *CanFlagsPtr |= HTTP_METHOD_WEBDAV_MKCOL; else if (strsame (lptr, "PROPFIND", 8) && !isalpha(lptr[8])) *CanFlagsPtr |= HTTP_METHOD_WEBDAV_PROPFIND; else if (strsame (lptr, "PROPPATCH", 9) && !isalpha(lptr[9])) *CanFlagsPtr |= HTTP_METHOD_WEBDAV_PROPPATCH; else if (strsame (lptr, "UNLOCK", 6) && !isalpha(lptr[6])) *CanFlagsPtr |= HTTP_METHOD_WEBDAV_UNLOCK; else { /* otherwise assume it's an alpha-numeric host name */ for (sptr = RestrictListPtr; *sptr; sptr++); zptr = RestrictListPtr + ACCESS_RESTRICTION_LIST_SIZE; if (sptr > RestrictListPtr && sptr < zptr) *sptr++ = ','; while (*lptr && !ISLWS(*lptr) && *lptr != ',' && *lptr != ';' && sptr < zptr) *sptr++ = *lptr++; if (sptr >= zptr) { MetaConReport (mcptr, METACON_REPORT_ERROR, "Restriction list too long"); PathProblem = true; break; } else *sptr = '\0'; } while (*lptr && !ISLWS(*lptr) && *lptr != ',' && *lptr != ';') lptr++; } AuthConfigAddPath (mcptr, PathProblem, PathTemplatePtr, PathIsRegex, FinalRule, GroupRestrictList, WorldRestrictList, ProxyStringPtr, PathParameter, CurrentSourceRealm, GroupCanFlags, WorldCanFlags, NoCache, VmsUserProfile, VmsUserScriptAs); AuthorizationEnabled++; return; } MetaConReport (mcptr, METACON_REPORT_ERROR, "Generally confused\n"); } /*****************************************************************************/ /* */ AuthConfigAddRealm ( META_CONFIG *mcptr, BOOL RealmProblem, char *Realm, char *RealmDescription, char *RealmParameter, unsigned long SourceRealm, unsigned long RealmVmsIdentifier, char *GroupWrite, unsigned long SourceGroupWrite, unsigned long GroupWriteVmsIdentifier, char *GroupRead, unsigned long SourceGroupRead, unsigned long GroupReadVmsIdentifier, unsigned long GroupCanFlags, unsigned long WorldCanFlags ) { int status, RealmDescriptionLength, GroupReadLength, GroupWriteLength, RealmLength, RealmParamLength, StringSpace, WorldRestrictListLength; char *cptr, *pptr, *sptr, *tptr, *OffsetPtr; AUTH_REALM *arptr; METACON_LINE *mclptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) { WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigAddRealm()"); WatchDataFormatted ( "!&B !&Z !&Z !&Z !UL !&X\n\ !&Z !UL !&X\n\ !&Z !UL !&X\n\ !&X !&X\n", RealmProblem, Realm, RealmDescription, RealmParameter, SourceRealm, RealmVmsIdentifier, GroupWrite, SourceGroupWrite, GroupWriteVmsIdentifier, GroupRead, SourceGroupRead, GroupReadVmsIdentifier, GroupCanFlags, WorldCanFlags); } /* get a pointer to the current "line" */ mclptr = mcptr->ParsePtr; GroupReadLength = strlen(GroupRead); GroupWriteLength = strlen(GroupWrite); RealmLength = strlen(Realm); RealmDescriptionLength = strlen(RealmDescription); RealmParamLength = strlen(RealmParameter); StringSpace = 5 + /* number of terminating nulls! */ GroupReadLength + GroupWriteLength + RealmLength + RealmDescriptionLength + RealmParamLength; arptr = VmGet (sizeof(AUTH_REALM) + StringSpace); /* set the meta-config data pointer to this structure, tag it! */ mclptr->LineDataPtr = arptr; arptr->RecordType = AUTH_REALM_RECORD_TYPE; arptr->MetaConNumber = mclptr->Number; arptr->RealmProblem = RealmProblem; /* find the start of the string storage space */ OffsetPtr = (char*)arptr + sizeof(AUTH_REALM); arptr->GroupReadPtr = OffsetPtr; memcpy (arptr->GroupReadPtr, GroupRead, GroupReadLength+1); OffsetPtr += (arptr->GroupReadLength = GroupReadLength) + 1; arptr->SourceGroupRead = SourceGroupRead; arptr->GroupReadVmsIdentifier = GroupReadVmsIdentifier; arptr->GroupWritePtr = OffsetPtr; memcpy (arptr->GroupWritePtr, GroupWrite, GroupWriteLength+1); OffsetPtr += (arptr->GroupWriteLength = GroupWriteLength) + 1; arptr->SourceGroupWrite = SourceGroupWrite; arptr->GroupWriteVmsIdentifier = GroupWriteVmsIdentifier; arptr->RealmPtr = OffsetPtr; memcpy (arptr->RealmPtr, Realm, RealmLength+1); OffsetPtr += (arptr->RealmLength = RealmLength) + 1; arptr->SourceRealm = SourceRealm; arptr->RealmVmsIdentifier = RealmVmsIdentifier; arptr->RealmDescrPtr = OffsetPtr; memcpy (arptr->RealmDescrPtr, RealmDescription, RealmDescriptionLength+1); OffsetPtr += (arptr->RealmDescriptionLength = RealmDescriptionLength) + 1; arptr->RealmParamPtr = OffsetPtr; memcpy (arptr->RealmParamPtr, RealmParameter, RealmParamLength+1); OffsetPtr += (arptr->RealmParamLength = RealmParamLength) + 1; arptr->AuthGroupCan = GroupCanFlags; arptr->AuthWorldCan = WorldCanFlags; if (SourceRealm == AUTH_SOURCE_TOKEN) { /* note that TOKEN authorization is in use */ AuthRealmToken = true; } if (SourceRealm == AUTH_SOURCE_X509) { /* note that X509 client certification is in use */ AuthRealmX509 = true; } } /*****************************************************************************/ /* */ AuthConfigAddPath ( META_CONFIG *mcptr, BOOL PathProblem, char *Path, BOOL PathIsRegex, BOOL FinalRule, char *GroupRestrictList, char *WorldRestrictList, char *ProxyStringPtr, char *PathParameter, unsigned long SourceRealm, unsigned long GroupCanFlags, unsigned long WorldCanFlags, BOOL NoCache, BOOL VmsUserProfile, BOOL VmsUserScriptAs ) { int status, GroupRestrictListLength, PathLength, ProxyStringLength, PathParameterLength, StringSpace, WorldRestrictListLength; char *cptr, *pptr, *sptr, *tptr, *OffsetPtr; AUTH_PATH *apptr; METACON_LINE *mclptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) { WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigAddPath()"); WatchDataFormatted ( "!&B !&Z !&B !&B\n!&Z\n!&Z\n!&Z\n!&Z\n!UL !&X !&X !&B !&B !&B\n", PathProblem, Path, FinalRule, PathIsRegex, GroupRestrictList, WorldRestrictList, ProxyStringPtr, PathParameter, SourceRealm, GroupCanFlags, WorldCanFlags, NoCache, VmsUserProfile, VmsUserScriptAs); } /* get a pointer to the current "line" */ mclptr = mcptr->ParsePtr; GroupRestrictListLength = strlen(GroupRestrictList); PathLength = strlen(Path); ProxyStringLength = strlen(ProxyStringPtr); PathParameterLength = strlen(PathParameter); WorldRestrictListLength = strlen(WorldRestrictList); StringSpace = 5 + /* number of terminating nulls! */ GroupRestrictListLength + PathLength + ProxyStringLength + PathParameterLength + WorldRestrictListLength; apptr = VmGet (sizeof(AUTH_PATH) + StringSpace); /* set the meta-config data pointer to this structure, tag it! */ mclptr->LineDataPtr = apptr; apptr->RecordType = AUTH_PATH_RECORD_TYPE; apptr->MetaConNumber = mclptr->Number; apptr->PathProblem = PathProblem; apptr->SourceRealm = SourceRealm; /* set the meta-config data pointer to this structure */ mclptr->LineDataPtr = apptr; /* find the start of the string storage space */ OffsetPtr = (char*)apptr + sizeof(AUTH_PATH); apptr->GroupRestrictListPtr = sptr = OffsetPtr; cptr = GroupRestrictList; while (*cptr) *sptr++ = *cptr++; *sptr = '\0'; OffsetPtr += (apptr->GroupRestrictListLength = GroupRestrictListLength) + 1; apptr->PathPtr = sptr = OffsetPtr; cptr = Path; while (*cptr) *sptr++ = *cptr++; *sptr = '\0'; OffsetPtr += (apptr->PathLength = PathLength) + 1; if (PathIsRegex) { /* the template was a regular expression, create a compiled version */ StringRegexCompile (apptr->PathPtr, &apptr->RegexPregPath); } apptr->FinalRule = FinalRule; apptr->ProxyStringPtr = sptr = OffsetPtr; cptr = ProxyStringPtr; while (*cptr) *sptr++ = *cptr++; *sptr = '\0'; OffsetPtr += (apptr->ProxyStringLength = ProxyStringLength) + 1; cptr = WorldRestrictList; apptr->WorldRestrictListPtr = sptr = OffsetPtr; while (*cptr) *sptr++ = *cptr++; *sptr = '\0'; OffsetPtr += (apptr->WorldRestrictListLength = WorldRestrictListLength) + 1; apptr->PathParameterPtr = OffsetPtr; memcpy (apptr->PathParameterPtr, PathParameter, PathParameterLength+1); *sptr = '\0'; apptr->PathParameterLength = PathParameterLength; apptr->AuthGroupCan = GroupCanFlags; apptr->AuthWorldCan = WorldCanFlags; apptr->NoCache = NoCache; apptr->VmsUserProfile = VmsUserProfile; apptr->VmsUserScriptAs = VmsUserScriptAs; } /****************************************************************************/ /* When 'StringPtr' is non-NULL the string is parsed looking for something like 'vms-username=remote-username[@host.name]' where the square brackets indicate an optional host host name. Essentially this is any string delimited by white-space. Multiple proxy entries can be placed in a single string (line) separated by white-space. The newly parsed position in the string is returned. This can be done one or many times with the string being dynamically allocated and built up into a series of white-space delimited proxy mappings. If 'StringPtr' is passed as NULL a pointer to the stored string is returned and the internal pointers reset to empty. It is up to the calling routine to then use/dispose of the string as appropriate. */ char* AuthConfigProxy ( META_CONFIG *mcptr, char *StringPtr ) { #define AUTH_CONFIG_META_PROXY_STRING_ALLOC 256 static int ProxyCurrentLength, ProxyLineLength, ProxyStringLength; static char *ProxyStringPtr; char *cptr, *sptr; int Length; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigProxy() !&X !&Z", mcptr, StringPtr); if (!StringPtr) { if (!ProxyCurrentLength) return (""); if (mcptr) return (ProxyStringPtr); VmFree (ProxyStringPtr, FI_LI); ProxyStringPtr = NULL; ProxyCurrentLength = ProxyLineLength = ProxyStringLength = 0; return (""); } if (!AuthPolicySysUafProxy) { /* prevent disabled proxies from inadvertantly allowing access */ if (ProxyCurrentLength) return (ProxyStringPtr); MetaConReport (mcptr, METACON_REPORT_ERROR, "/SYSUAF=PROXY not enabled at command line"); /* override the supplied proxy with this bogus one */ StringPtr = "proxy@command.line=NOT-ENABLED"; } for (;;) { for (sptr = StringPtr; *sptr && ISLWS(*sptr); sptr++); if (!*sptr) break; cptr = sptr; while (*sptr && !ISLWS(*sptr)) sptr++; StringPtr = sptr; if ((Length = (sptr - cptr)) > ProxyStringLength - ProxyCurrentLength) { if (Length < AUTH_CONFIG_META_PROXY_STRING_ALLOC+1) Length = AUTH_CONFIG_META_PROXY_STRING_ALLOC+1; ProxyStringLength += Length; ProxyStringPtr = VmRealloc (ProxyStringPtr, ProxyStringLength+1, FI_LI); } sptr = ProxyStringPtr + ProxyCurrentLength; if (ProxyLineLength > 80) { *sptr++ = '\n'; ProxyLineLength = 0; } else if (ProxyLineLength) *sptr++ = ' '; while (*cptr && !ISLWS(*cptr)) { *sptr++ = *cptr++; ProxyLineLength++; } *sptr = '\0'; ProxyCurrentLength = sptr - ProxyStringPtr; if (WATCH_MODULE(WATCH_MOD_AUTH) && WATCH_MODULE(WATCH_MOD__DETAIL)) WatchDataFormatted ("!UL !UL !&Z\n", ProxyStringLength, ProxyCurrentLength, ProxyStringPtr); } return (NULL); } /****************************************************************************/ /* Searches for a matching proxy entry in the string passed as the 'ProxyStringPtr' field of the authorisation record. Searches against the username in the request's remote user and client host name (which with WASD usually contains the client's IP address). See description in the prologue to AUTH.C for information on what this function provides in proxy mappings. [*|REMOTE][@host-name|@IP-address|VLSM-address]=[*|LOCAL] *@host.name=* (many-to-many, host match) @host-name= (the same, different syntax) remote-name@host.name=* (many-to-the-same, host match) remote-name@host.name=local-name (one-to-one, host match) *@host.name=local-name (many-to-one, host match) *=local-name (many-to-one, all hosts) remote-name=local-name (one-to-one, all hosts) Note that remote an local usernames may be wilcarded only using a single wildcard (i.e. complete match) but host names and addresses may be matched on a partial string using a wildcard. The use of isspace() rather than ISLWS() allows embedded newlines to break very long lines of proxy mappings when outputing them as reports. */ int AuthConfigProxyMap ( REQUEST_STRUCT *rqptr, AUTH_CREC *acrptr ) { BOOL IsDottedDecimal, IsNetMask, SoFarSoGood; int status, ProxyUserNameLength, RemoteUserLength; char *cptr, *dptr, *sptr, *zptr, *ErrorMsgPtr; char RuleHost [128], RemoteUser [AUTH_MAX_USERNAME_LENGTH+1], RuleUserName [AUTH_MAX_USERNAME_LENGTH+1], ProxyUserName [AUTH_MAX_USERNAME_LENGTH+1]; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_MOD_AUTH, "AuthConfigProxyMap()"); /* get name-only portion of any name@host remote username (RFC1413) */ cptr = rqptr->RemoteUser; zptr = (sptr = RemoteUser) + sizeof(RemoteUser); while (*cptr && *cptr != '@' && sptr < zptr) *sptr++ = TOUP(*cptr++); if (sptr >= zptr) { ErrorGeneralOverflow (rqptr, FI_LI); return (AUTH_DENIED_BY_OTHER); } *sptr = '\0'; RemoteUserLength = sptr - RemoteUser; if (WATCHING (rqptr, WATCH_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_AUTH, "PROXY map !AZ@!AZ", RemoteUser, rqptr->ClientPtr->Lookup.HostName); ProxyUserName[0] = '\0'; cptr = rqptr->rqAuth.ProxyStringPtr; while (*cptr) { while (*cptr && isspace (*cptr)) cptr++; if (*cptr == '#') { /* commented-out rule */ if (SAME2(cptr,'#!')) { /* comment spans all characters until next '!' */ while (*cptr && *cptr != '!') cptr++; if (*cptr) cptr++; } else while (*cptr && !isspace (*cptr)) cptr++; continue; } dptr = cptr; IsNetMask = false; SoFarSoGood = true; ErrorMsgPtr = NULL; ProxyUserName[0] = '\0'; if (*cptr == '*' || *cptr == '@') { /********************/ /* wildcard mapping */ /********************/ SET2(RuleUserName,'*\0'); if (*cptr == '*') cptr++; } else { /*************************/ /* get the rule username */ /*************************/ zptr = (sptr = RuleUserName) + sizeof(RuleUserName); while (*cptr && *cptr != '@' && !isspace(*cptr) && sptr < zptr) *sptr++ = *cptr++; if (sptr >= zptr) { ErrorGeneralOverflow (rqptr, FI_LI); return (AUTH_DENIED_BY_OTHER); } *sptr = '\0'; } if (*cptr == '@') { /********************/ /* a host component */ /********************/ IsDottedDecimal = true; cptr++; zptr = (sptr = RuleHost) + sizeof(RuleHost); while (*cptr && *cptr != '=' && !isspace(*cptr) && sptr < zptr) { if (*cptr == '/') IsNetMask = true; if (isalpha(*cptr)) IsDottedDecimal = false; *sptr++ = *cptr++; } if (sptr >= zptr) { ErrorGeneralOverflow (rqptr, FI_LI); return (AUTH_DENIED_BY_OTHER); } *sptr = '\0'; if (IsNetMask) { char *tptr = RuleHost; /* preserve string address using pointer */ status = TcpIpNetMask (rqptr, WATCH_AUTH, &tptr, &rqptr->ClientPtr->IpAddress); if (status == SS$_UNREACHABLE) { /* if the masked IP addresses do not match */ SoFarSoGood = false; } else if (VMSnok(status)) { /* net mask problem */ ErrorMsgPtr = "network mask"; SoFarSoGood = false; } } else if (IsDottedDecimal) { /* if wildcard string compare fails the no match */ if (!StringMatch (rqptr, &rqptr->ClientPtr->IpAddressString, RuleHost)) SoFarSoGood = false; } else { /* if wildcard string compare fails the no match */ if (!StringMatch (rqptr, rqptr->ClientPtr->Lookup.HostName, RuleHost)) SoFarSoGood = false; } } if (*cptr != '=') { ErrorMsgPtr = "rule syntax"; SoFarSoGood = false; } else if (SoFarSoGood) { /***************************/ /* get the SYSUAF username */ /***************************/ cptr++; if (*cptr == '*' || isspace(*cptr)) { /* wildcard mapping */ if (*cptr == '*') cptr++; strcpy (ProxyUserName, RemoteUser); ProxyUserNameLength = RemoteUserLength; } else { zptr = (sptr = ProxyUserName) + sizeof(ProxyUserName); while (*cptr && !isspace(*cptr) && sptr < zptr) *sptr++ = TOUP(*cptr++); if (sptr >= zptr) { ErrorGeneralOverflow (rqptr, FI_LI); return (AUTH_DENIED_BY_OTHER); } *sptr = '\0'; ProxyUserNameLength = sptr - ProxyUserName; } } while (*cptr && !isspace (*cptr)) cptr++; /****************/ /* end of parse */ /****************/ if (WATCHING (rqptr, WATCH_AUTH)) { WatchDataFormatted ("!#AZ", cptr-dptr, dptr); if (!ErrorMsgPtr) WatchDataFormatted ("\n"); else WatchDataFormatted (" rqAuth.RemoteUser, rqptr->RemoteUser); rqptr->rqAuth.RemoteUserLength = rqptr->RemoteUserLength; /* now replace the original remote user with the potential SYSUAF one */ strcpy (rqptr->RemoteUser, ProxyUserName); rqptr->RemoteUserLength = ProxyUserNameLength; if (strsame (acrptr->ProxyUserName, ProxyUserName, -1)) { /************************/ /* use previous details */ /************************/ if (rqptr->rqAuth.UserDetailsLength = acrptr->UserDetailsLength) { rqptr->rqAuth.UserDetailsPtr = VmGetHeap (rqptr, rqptr->rqAuth.UserDetailsLength+1); strcpy (rqptr->rqAuth.UserDetailsPtr, acrptr->UserDetails); } else rqptr->rqAuth.UserDetailsPtr = NULL; if (rqptr->rqAuth.VmsUserProfileLength = acrptr->VmsUserProfileLength) { rqptr->rqAuth.VmsUserProfilePtr = VmGetHeap (rqptr, acrptr->VmsUserProfileLength); memcpy (rqptr->rqAuth.VmsUserProfilePtr, acrptr->VmsUserProfilePtr, acrptr->VmsUserProfileLength); } else rqptr->rqAuth.VmsUserProfilePtr = NULL; rqptr->rqAuth.VmsUserScriptAs = acrptr->VmsUserScriptAs; rqptr->rqAuth.SysUafAuthenticated = acrptr->SysUafAuthenticated = true; return (SS$_NORMAL); } else { /*************************/ /* proxy username verify */ /*************************/ if (VMSok (status = AuthVmsGetUai (rqptr, rqptr->RemoteUser))) status = AuthVmsVerifyUser (rqptr); if (VMSok (status) && (AuthPolicySysUafIdentifiers || AuthPolicySysUafWasdIdentifiers)) { status = AuthVmsHoldsIdentifier (rqptr, AUTH_PROXY_ACCESS_VMS_ID, AuthProxyAccessVmsIdentifier); /* if requires proxy identifier ... and doesn't have it */ if (VMSnok (status)) { if (WATCHING (rqptr, WATCH_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_AUTH, "FAIL SYSUAF proxy identifier"); status = AUTH_DENIED_BY_OTHER; } } if (VMSok (status)) if (AuthVmsUserProfileEnabled) status = AuthVmsCreateUserProfile (rqptr); if (VMSok (status)) { rqptr->rqAuth.SysUafAuthenticated = acrptr->SysUafAuthenticated = true; strcpy (acrptr->ProxyUserName, ProxyUserName); acrptr->ProxyUserNameLength = ProxyUserNameLength; } else { /* the verification has failed for some reason */ rqptr->rqAuth.SysUafAuthenticated = acrptr->SysUafAuthenticated = false; /* restore the original details */ strcpy (rqptr->RemoteUser, rqptr->rqAuth.RemoteUser); rqptr->RemoteUserLength = rqptr->rqAuth.RemoteUserLength; rqptr->rqAuth.RemoteUser[0] = acrptr->ProxyUserName[0] = '\0'; rqptr->rqAuth.RemoteUserLength = acrptr->ProxyUserNameLength = 0; } return (status); } } /****************************************************************************/ /* Get the identifier value from the supplied name. */ AuthConfigIdentifier ( char *NamePtr, unsigned long *ValuePtr ) { static $DESCRIPTOR (NameDsc, ""); int status; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigIdentifier() !&Z", NamePtr); *ValuePtr = 0; NameDsc.dsc$a_pointer = NamePtr; NameDsc.dsc$w_length = strlen(NamePtr); status = sys$asctoid (&NameDsc, ValuePtr, 0); return (status); } /*****************************************************************************/ /* Look for a path template matching the request path in the path authorization meta-config. */ int AuthConfigSearch ( REQUEST_STRUCT *rqptr, char *PathBeingAuthorized ) { BOOL WatchThisMatch; int status, TotalLength; char *cptr, *pptr, *sptr, *tptr, *zptr; AUTH_PATH *apptr; AUTH_REALM *arptr, *RealmDataPtr; METACON_LINE *mclptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_MOD_AUTH, "AuthConfigSearch() !&Z", PathBeingAuthorized); if (WATCHING (rqptr, WATCH_MATCH)) WatchThisMatch = true; else WatchThisMatch = false; RealmDataPtr = NULL; MetaConParseReset (MetaGlobalAuthPtr, true); for (;;) { mclptr = MetaGlobalAuthPtr->ParsePtr = MetaGlobalAuthPtr->ParseNextPtr; if (WATCHPNT(rqptr) && WATCH_MODULE(WATCH_MOD_METACON) && WATCH_MODULE(WATCH_MOD__DETAIL)) WatchDataFormatted ("!&X !UL !UL !UL !UL !&X !&Z\n", mclptr, mclptr->Size, mclptr->Token, mclptr->Number, mclptr->Length, mclptr->LineDataPtr, mclptr->TextPtr); /* if terminating empty "line" */ if (!mclptr->Size) { status = STS$K_ERROR; break; } if (mclptr->Token == METACON_TOKEN_TEXT) { /* get required data, adjust the parse context to the next "line" */ cptr = (char*)mclptr->LineDataPtr; MetaGlobalAuthPtr->ParseNextPtr = (METACON_LINE*)((char*)mclptr + mclptr->Size); } else if (mclptr->Token != METACON_TOKEN_DIRECTORY) { /* not a simple text line, have meta-config parse this one for us */ if (WATCHING (rqptr, WATCH_AUTH)) cptr = MetaConParse (rqptr, MetaGlobalAuthPtr, &mclptr, WATCH_AUTH); else cptr = MetaConParse (rqptr, MetaGlobalAuthPtr, &mclptr, 0); /* if end of rules */ if (!cptr) { status = STS$K_ERROR; break; } /* if error string */ if (!*cptr && *(cptr+1)) { status = SS$_ABORT; break; } /* if inline rule and expression was false */ if (SAME4 (cptr, '\0\0\0\1')) continue; cptr = (char*)mclptr->LineDataPtr; } if (mclptr->Token == METACON_TOKEN_DIRECTORY) { /* get required data, adjust the parse context to the next "line" */ cptr = mclptr->TextPtr + sizeof("[ConfigDirectory]"); while (*cptr && ISLWS(*cptr)) cptr++; zptr = (sptr = rqptr->ConfigDirectory) + sizeof(rqptr->ConfigDirectory)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; rqptr->ConfigDirectoryLength = sptr - rqptr->ConfigDirectory; MetaGlobalAuthPtr->ParseNextPtr = (METACON_LINE*)((char*)mclptr + mclptr->Size); continue; } /* if there is no associated authorization data then ignore line */ if (!cptr) continue; /* check the record type integer of this record */ if (*(int*)cptr == AUTH_REALM_RECORD_TYPE) { /* just note the last realm record encountered */ RealmDataPtr = (AUTH_REALM*)cptr; continue; } if (*(int*)cptr == AUTH_PATH_RECORD_TYPE) { apptr = (AUTH_PATH*)cptr; /* the 'arptr' here points to the last realm record encountered */ if (!(arptr = RealmDataPtr)) { if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) { WatchDataFormatted ( "!&Z final:!&B regex:!&B\n\ !&Z !&Z\n\ !&X !&X !&B !&B !&B\n\ NO REALM TO APPLY!!\n", apptr->PathPtr, apptr->FinalRule, apptr->RegexPregPath.buffer, apptr->GroupRestrictListPtr, apptr->WorldRestrictListPtr, apptr->AuthGroupCan, apptr->AuthWorldCan, apptr->NoCache, apptr->VmsUserProfile, apptr->VmsUserScriptAs); } status = STS$K_ERROR; break; } } else ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) { WatchDataFormatted ( "!&Z\n\ !&B !&Z !&Z !UL !&X\n\ !&Z !UL !&X\n\ !&Z !UL !&X\n\ !&Z !&Z\n\ !&Z\n\ !&X !&X\n\ !&X !&X !&B !&B !&B\n", apptr->PathPtr, apptr->FinalRule, arptr->RealmPtr, arptr->RealmDescrPtr, arptr->SourceRealm, arptr->RealmVmsIdentifier, arptr->GroupWritePtr, arptr->SourceGroupWrite, arptr->GroupWriteVmsIdentifier, arptr->GroupReadPtr, arptr->SourceGroupRead, arptr->GroupReadVmsIdentifier, apptr->GroupRestrictListPtr, apptr->WorldRestrictListPtr, apptr->PathParameterPtr, arptr->AuthGroupCan, arptr->AuthWorldCan, apptr->AuthGroupCan, apptr->AuthWorldCan, apptr->NoCache, apptr->VmsUserProfile, apptr->VmsUserScriptAs); } if (WATCHING (rqptr, WATCH_AUTH)) { int BufferCount; char Buffer [2048]; BufferCount = AuthConfigReportRule (rqptr, mclptr, true, Buffer, sizeof(Buffer)); WatchData (Buffer, BufferCount); } /* quick check obvious non-/match before using expensive functions */ tptr = apptr->PathPtr; pptr = PathBeingAuthorized; if (Config.cfMisc.RegexSyntax && *tptr == REGEX_CHAR) tptr++; /* while matching vanilla characters */ while ((isalnum(*tptr) || *tptr == '/' || *tptr == '-' || *tptr == '_') && TOLO(*pptr) == TOLO(*tptr)) { pptr++; tptr++; } /* if non-matching vanilla character */ if (isalnum(*tptr) || *tptr == '/' || *tptr == '-' || *tptr == '_') { if (!WatchThisMatch) continue; WatchThis (WATCHITM(rqptr), WATCH_MATCH, "NO !&Z", tptr); continue; } /* if a trailing wildcard then it's a match already! */ if (SAME2(tptr,'*\0')) { status = SS$_NORMAL; if (!WatchThisMatch) break; WatchThis (WATCHITM(rqptr), WATCH_MATCH, "YES"); break; } /* expensive comparison of path and template, break if matched */ if (StringMatchAndRegex (rqptr, PathBeingAuthorized, apptr->PathPtr, SMATCH_STRING_REGEX, &apptr->RegexPregPath, NULL)) { status = SS$_NORMAL; break; } } /*************************************/ /* if path not found, or other error */ /*************************************/ if (VMSnok (status)) return (status); /* a final rule is effectively 'path not found' */ if (apptr->FinalRule) return (STS$K_ERROR); /**************/ /* path found */ /**************/ /* As the path authorization information is potentially volatile (i.e. can be reloaded) we need request-local copies of these fields. */ TotalLength = 10 + /* number of terminating nulls */ /* these five are from the realm record */ arptr->GroupWriteLength + arptr->GroupReadLength + arptr->RealmLength + arptr->RealmDescriptionLength + arptr->RealmParamLength + /* these five are from the path record */ apptr->PathLength + apptr->GroupRestrictListLength + apptr->ProxyStringLength + apptr->PathParameterLength + apptr->WorldRestrictListLength; cptr = VmGetHeap (rqptr, TotalLength); /******************************/ /* data from the realm record */ /******************************/ rqptr->rqAuth.RealmProblem = arptr->RealmProblem; memcpy (rqptr->rqAuth.RealmPtr = cptr, arptr->RealmPtr, arptr->RealmLength+1); cptr += arptr->RealmLength+1; rqptr->rqAuth.RealmLength = arptr->RealmLength; rqptr->rqAuth.SourceRealm = arptr->SourceRealm; rqptr->rqAuth.RealmVmsIdentifier = arptr->RealmVmsIdentifier; if (arptr->RealmDescrPtr[0]) { memcpy (rqptr->rqAuth.RealmDescrPtr = cptr, arptr->RealmDescrPtr, arptr->RealmDescriptionLength+1); cptr += arptr->RealmDescriptionLength+1; } else rqptr->rqAuth.RealmDescrPtr = rqptr->rqAuth.RealmPtr; if (arptr->RealmParamPtr[0]) { memcpy (rqptr->rqAuth.RealmParamPtr = cptr, arptr->RealmParamPtr, arptr->RealmParamLength+1); cptr += arptr->RealmParamLength+1; } memcpy (rqptr->rqAuth.ProxyStringPtr = cptr, apptr->ProxyStringPtr, apptr->ProxyStringLength+1); cptr += apptr->ProxyStringLength+1; rqptr->rqAuth.ProxyStringLength = apptr->ProxyStringLength; memcpy (rqptr->rqAuth.GroupWritePtr = cptr, arptr->GroupWritePtr, arptr->GroupWriteLength+1); cptr += arptr->GroupWriteLength+1; rqptr->rqAuth.GroupWriteLength = arptr->GroupWriteLength; rqptr->rqAuth.SourceGroupWrite = arptr->SourceGroupWrite; rqptr->rqAuth.GroupWriteVmsIdentifier = arptr->GroupWriteVmsIdentifier; memcpy (rqptr->rqAuth.GroupReadPtr = cptr, arptr->GroupReadPtr, arptr->GroupReadLength+1); cptr += arptr->GroupReadLength+1; rqptr->rqAuth.GroupReadLength = arptr->GroupReadLength; rqptr->rqAuth.SourceGroupRead = arptr->SourceGroupRead; rqptr->rqAuth.GroupReadVmsIdentifier = arptr->GroupReadVmsIdentifier; /*****************************/ /* data from the path record */ /*****************************/ rqptr->rqAuth.PathProblem = apptr->PathProblem; memcpy (rqptr->rqAuth.PathLocationPtr = cptr, apptr->PathPtr, apptr->PathLength+1); cptr += apptr->PathLength+1; rqptr->rqAuth.PathLocationLength = apptr->PathLength; memcpy (rqptr->rqAuth.GroupRestrictListPtr = cptr, apptr->GroupRestrictListPtr, apptr->GroupRestrictListLength+1); cptr += apptr->GroupRestrictListLength+1; memcpy (rqptr->rqAuth.WorldRestrictListPtr = cptr, apptr->WorldRestrictListPtr, apptr->WorldRestrictListLength+1); rqptr->rqAuth.WorldRestrictListPtr = apptr->WorldRestrictListPtr; memcpy (rqptr->rqAuth.PathParameterPtr = cptr, apptr->PathParameterPtr, apptr->PathParameterLength+1); cptr += apptr->PathParameterLength + 1; rqptr->rqAuth.PathParameterLength = apptr->PathParameterLength; rqptr->rqAuth.GroupCan = apptr->AuthGroupCan; rqptr->rqAuth.WorldCan = apptr->AuthWorldCan; rqptr->rqAuth.NoCache = apptr->NoCache; rqptr->rqAuth.VmsUserProfile = apptr->VmsUserProfile; rqptr->rqAuth.VmsUserScriptAs = apptr->VmsUserScriptAs; return (SS$_NORMAL); } /****************************************************************************/ /* "Realm Description"==:: Returns a NULL is successfully parses, a pointer to an explanatory string if not successful. */ char* AuthConfigParseProtectRule ( REQUEST_STRUCT *rqptr, char *RulePtr, int RuleLength ) { static unsigned long RealmVmsIdentifier; static char PrevRealm [AUTH_MAX_REALM_GROUP_LENGTH+1]; int status, AccessLength, GroupCan, RealmLength, RealmDescrLength, RealmSourceLength, RestrictLength, SourceRealm, StringLength, WorldCan; char *bptr, *cptr, *sptr, *zptr, *AccessPtr, *BufferPtr, *RealmPtr, *RealmDescrPtr, *RealmSourcePtr, *RestrictPtr; char Buffer [1024]; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_AUTH)) WatchThis (WATCHALL, WATCH_MOD_AUTH, "AuthConfigParseProtectRule() !&Z", RulePtr); if (RuleLength <= 0) RuleLength = strlen(RulePtr); if (rqptr) { BufferPtr = VmGetHeap (rqptr, RuleLength+1); memcpy (BufferPtr, RulePtr, RuleLength+1); /* preemptively set this true, then reset once it's parsed ok */ rqptr->rqAuth.RealmProblem = true; } else { if (RuleLength+1 > sizeof(Buffer)) return ("Buffer overflow"); memcpy (BufferPtr = Buffer, RulePtr, RuleLength+1); } zptr = (sptr = bptr = BufferPtr) + RuleLength+1; cptr = RulePtr; RealmDescrPtr = NULL; if (*cptr == '\"') { /* optional realm description */ cptr++; RealmDescrPtr = bptr; while (*cptr && *cptr != '\"') { if (cptr[0] == '\\' && cptr[1]) cptr++; if (sptr < zptr) *sptr++ = *cptr++; } *sptr = '\0'; RealmDescrLength = sptr - RealmDescrPtr; sptr++; if (!RealmDescrLength) return ("Realm description not specified"); if (!*cptr) return ("Mandatory parameter(s) missing"); cptr++; if (*cptr != '=') return ("Mandatory parameter(s) missing"); cptr++; } else { RealmDescrPtr = bptr; *sptr++ = '\0'; RealmDescrLength = 0; } bptr += RealmDescrLength + 1; /* mandatory authentication realm */ RealmPtr = sptr = bptr; while (*cptr && *cptr != '=' && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; RealmLength = sptr - bptr; sptr++; if (!RealmLength) return ("Realm not specified"); if (!*cptr) return ("Mandatory parameter(s) missing"); cptr++; bptr += RealmLength + 1; if (!RealmDescrLength) { /* must have a realm description of some sort - use the realm name */ RealmDescrPtr = RealmPtr; RealmDescrLength = RealmLength; } /* mandatory authentication source */ RealmSourcePtr = sptr = bptr; while (*cptr && *cptr != ':' && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; RealmSourceLength = sptr - bptr; sptr++; if (!RealmSourceLength) return ("Realm type not specified"); if (!*cptr) return ("Mandatory parameter(s) missing"); cptr++; bptr += RealmSourceLength + 1; switch (TOLO(RealmSourcePtr[0])) { case '@' : switch (TOLO(RealmSourcePtr[1])) { case 'l' : SourceRealm = AUTH_SOURCE_DIR_LIST; break; case 'h' : SourceRealm = AUTH_SOURCE_DIR_HTA; break; default : return ("Realm source incorrect"); } break; case 'a' : if (strsame (RealmSourcePtr, "agent+opaque", 12)) SourceRealm = AUTH_SOURCE_AGENT_OPAQUE; else SourceRealm = AUTH_SOURCE_AGENT; break; case 'e' : SourceRealm = AUTH_SOURCE_EXTERNAL; break; case 'h' : switch (TOLO(RealmSourcePtr[1])) { case 't' : SourceRealm = AUTH_SOURCE_HTA; break; case 'o' : SourceRealm = AUTH_SOURCE_HOST; break; default : return ("Realm source incorrect"); } break; case 'i' : SourceRealm = AUTH_SOURCE_ID; break; case 'l' : SourceRealm = AUTH_SOURCE_LIST; break; case 'o' : SourceRealm = AUTH_SOURCE_OPAQUE; break; case 'r' : SourceRealm = AUTH_SOURCE_RFC1413; break; case 'v' : SourceRealm = AUTH_SOURCE_VMS; break; case 'w' : switch (TOLO(RealmSourcePtr[1])) { /** case 'a' : SourceRealm = AUTH_SOURCE_WASD_ID; break; **/ case 'o' : SourceRealm = AUTH_SOURCE_WORLD; break; default : return ("Realm source incorrect"); } break; case 'x' : SourceRealm = AUTH_SOURCE_X509; break; default : return ("Realm source incorrect"); } /* opaque authorization doesn't need an access string */ if (SourceRealm == AUTH_SOURCE_OPAQUE) return (NULL); /* mandatory access string */ AccessPtr = sptr = bptr; while (*cptr && *cptr != ':' && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; AccessLength = sptr - bptr; sptr++; if (!AccessLength) return ("Access not specified"); if (*cptr) cptr++; bptr += AccessLength + 1; /* possibilities: "r", "r+w", "r,r", "r+w,r", "r+w,r+w", */ cptr = AccessPtr; if (cptr[0] == 'r' && cptr[1] == '+' && cptr[2] == 'w') { GroupCan = AUTH_READWRITE_ACCESS; cptr += 3; } else if (cptr[0] == 'r' && (!cptr[1] || cptr[1] == ',')) { GroupCan = AUTH_READONLY_ACCESS; cptr++; } else return ("Group access incorrect"); if (cptr[0] == ',') { cptr++; if (cptr[0] == 'r' && cptr[1] == '+' && cptr[2] == 'w') { WorldCan = AUTH_READWRITE_ACCESS; cptr += 3; } else if (cptr[0] == 'r' && !cptr[1]) { WorldCan = AUTH_READONLY_ACCESS; cptr++; } else return ("World access incorrect"); } else if (cptr[0]) return ("Access incorrect"); else WorldCan = 0; /* access restriction string */ RestrictPtr = sptr = bptr; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; RestrictLength = sptr - bptr; sptr++; bptr += RestrictLength + 1; if (SourceRealm == AUTH_SOURCE_ID) { /* previous identifier value is buffered for a minor efficiency */ if (!strsame (RealmPtr, PrevRealm, -1)) { status = AuthConfigIdentifier (RealmPtr, &RealmVmsIdentifier); if (VMSnok (status)) { if (WATCHING (rqptr, WATCH_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_AUTH, "Realm !AZ identifier %!&M", RealmPtr, status); if (status == SS$_NOSUCHID) return ("Unknown rights identifier"); return ("Rights identifier problem"); } zptr = (sptr = PrevRealm) + sizeof(PrevRealm)-1; for (cptr = RealmPtr; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; } } /* if just validating rather than applying the rule */ if (!rqptr) return (NULL); /********************/ /* apply to request */ /********************/ rqptr->rqAuth.RealmProblem = false; if (RealmDescrPtr) rqptr->rqAuth.RealmDescrPtr = RealmDescrPtr; else rqptr->rqAuth.RealmDescrPtr = RealmPtr; rqptr->rqAuth.RealmPtr = RealmPtr; rqptr->rqAuth.RealmLength = RealmLength; rqptr->rqAuth.SourceRealm = SourceRealm; if (SourceRealm == AUTH_SOURCE_ID) rqptr->rqAuth.RealmVmsIdentifier = RealmVmsIdentifier; else rqptr->rqAuth.RealmVmsIdentifier = 0; rqptr->rqAuth.GroupCan = GroupCan; rqptr->rqAuth.WorldCan = WorldCan; rqptr->rqAuth.GroupWritePtr = ""; rqptr->rqAuth.GroupWriteLength = rqptr->rqAuth.SourceGroupWrite = rqptr->rqAuth.GroupWriteVmsIdentifier = 0; rqptr->rqAuth.GroupReadPtr = ""; rqptr->rqAuth.GroupReadLength = rqptr->rqAuth.SourceGroupRead = rqptr->rqAuth.GroupReadVmsIdentifier = 0; rqptr->rqAuth.GroupRestrictListPtr = RestrictPtr; rqptr->rqAuth.WorldRestrictListPtr = ""; rqptr->rqAuth.ProxyStringPtr = ""; rqptr->rqAuth.ProxyStringLength = 0; rqptr->rqAuth.PathParameterPtr = ""; rqptr->rqAuth.PathParameterLength = 0; rqptr->rqAuth.VmsUserProfile = 0; rqptr->rqAuth.VmsUserScriptAs = NULL; rqptr->rqAuth.NoCache = false; return (NULL); } /*****************************************************************************/ /* This function just wraps the reporting function, loading a temporary database if necessary for reporting from the configuration file. */ AuthConfigReport ( REQUEST_STRUCT *rqptr, BOOL UseServerDatabase, char *VirtualService ) { int status; META_CONFIG *mcptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_MOD_AUTH, "AuthConfigReport() !UL !&Z", UseServerDatabase, VirtualService); if (UseServerDatabase) { /* use mapping rules already loaded into the server */ AuthConfigReportNow (rqptr, MetaGlobalAuthPtr, true, VirtualService); } else { /* load temporary set of rules from mapping file */ status = AuthConfigLoad (&mcptr); if (VMSnok (status)) { /* severe error reported */ rqptr->rqResponse.HttpStatus = 403; ErrorGeneral (rqptr, mcptr->LoadReport.TextPtr, FI_LI); } else AuthConfigReportNow (rqptr, mcptr, false, VirtualService); MetaConUnload (&mcptr, NULL); } AdminEnd (rqptr); } /*****************************************************************************/ /* Display all records in the authorization path meta-config. */ AuthConfigReportNow ( REQUEST_STRUCT *rqptr, META_CONFIG *mcptr, BOOL UseServerDatabase, char *VirtualService ) { static char BeginRules [] = "

Authorization Rules

\n"; static char BeginTable [] = "

\n\ \n\
";

   static char  EndPageFao [] =
"----\
\n\
\n\ \n\ \n\ \n"; BOOL ThisVirtualService; int status, BufferCount; char *cptr; char Buffer [2048]; AUTH_PATH *apptr; METACON_LINE *mclptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_MOD_AUTH, "AuthConfigReportNow() !&B !&Z", UseServerDatabase, VirtualService); AdminPageTitle (rqptr, "Path Authorization"); AdminMetaConReport (rqptr, mcptr, MetaGlobalAuthPtr); AdminMetaConSource (rqptr, mcptr, MetaGlobalAuthPtr); status = FaolToNet (rqptr, BeginRules, NULL); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); AdminVirtualServiceForm (rqptr, ADMIN_REPORT_AUTH_PATHS, VirtualService, UseServerDatabase); status = FaolToNet (rqptr, BeginTable, NULL); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); ThisVirtualService = true; MetaConParseReset (mcptr, true); while (mclptr = MetaConParseRaw (mcptr)) { if (mclptr->Token == METACON_TOKEN_SERVICE) { /* if filtering on a virtual service */ if (VirtualService[0] && !StringMatch (rqptr, VirtualService, mclptr->TextPtr)) ThisVirtualService = false; else ThisVirtualService = true; } else if (!ThisVirtualService) continue; BufferCount = AuthConfigReportRule (rqptr, mclptr, false, Buffer, sizeof(Buffer)); NetWriteBuffered (rqptr, NULL, Buffer, BufferCount); /* break if it's a final record of a specific virtual service */ if (!VirtualService[0]) continue; if (!(cptr = mclptr->LineDataPtr)) continue; if (*(int*)cptr == AUTH_PATH_RECORD_TYPE) { apptr = (AUTH_PATH*)cptr; if (apptr->FinalRule) break; } } status = FaolToNet (rqptr, EndPageFao, NULL); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/html", &rqptr->NetWriteBufferDsc); } /*****************************************************************************/ /* Display all single records from the authorization path meta-config. */ int AuthConfigReportRule ( REQUEST_STRUCT *rqptr, METACON_LINE *mclptr, BOOL WatchRule, char *Buffer, int SizeOfBuffer ) { static char PathFao [] = "!4ZL !#* !&?\r\r!AZ G:!AZ W:!AZ\ !&? FINAL\r\r!&? PROFILE\r\r!&? SCRIPTAS\r\r!&? NOCACHE\r\r\n\ !&@!&@!&@!&@!&?\r\r"; static char WatchPathFao [] = "!4ZL !#* !&?\r\r!AZ G:!AZ W:!AZ\ !&? FINAL\r\r!&? PROFILE\r\r!&? SCRIPTAS\r\r!&? NOCACHE\r\r\n\ !&@!&@!&@!&@!&? <--ERROR\r\r"; static char PathOpaqueFao [] = "!4ZL !#* !AZ\n"; static char WatchPathOpaqueFao [] = "!4ZL !#* !AZ\n"; static char RealmFao [] = "!4ZL !#* !&?\r\r\ [!&@!&;AZ!AZ!&@;!&;AZ!AZ;!&;AZ!AZ]!&?\r\r\n"; static char WatchRealmFao [] = "!4ZL !#* !&?\r\r\ [!&@!&;AZ!AZ!&@;!&;AZ!AZ;!&;AZ!AZ]!&? <--ERROR\r\r\n"; static char CommentFao [] = "!4ZL !#* !AZ\n"; static char NonRuleFao [] = "!4ZL !#* !&?\r\r!#AZ !&;AZ!&?\r\r\n"; static char WatchNonRuleFao [] = "!4ZL !#* !&?\r\r!#AZ !&;AZ!&? <--ERROR\r\r\n"; static char RuleVirtualFao [] = "!4ZL !#* !&?\r\r[[!&;AZ]]!&?\r\r\n"; static char RuleImplicitVirtualFao [] = "0000 [[*:*]]\n"; static char VersionFao [] = "!4ZL [[!AZ]]\n"; static char WatchRuleVirtualFao [] = "!4ZL !#* !&?\r\r[[!&;AZ]]!&? <--ERROR\r\r\n"; int status; unsigned short Length; unsigned long FaoVector [64]; unsigned long *vecptr; char *cptr; char GroupCanString [128], WorldCanString [128]; AUTH_PATH *apptr; AUTH_REALM *arptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_MOD_AUTH, "AuthConfigReportRule()"); if (mclptr->Token == METACON_TOKEN_SERVICE) { vecptr = FaoVector; *vecptr++ = mclptr->Number; *vecptr++ = (mclptr->MetaFileLevel+mclptr->FlowControlLevel) * 3; *vecptr++ = mclptr->ConfigProblem; *vecptr++ = mclptr->TextPtr; *vecptr++ = mclptr->ConfigProblem; status = FaolToBuffer (Buffer, SizeOfBuffer, &Length, WatchRule ? WatchRuleVirtualFao : RuleVirtualFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); return ((int)Length); } else if (mclptr->Number == 1) { status = FaolToNet (rqptr, RuleImplicitVirtualFao, NULL); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } if (mclptr->Token != METACON_TOKEN_TEXT) { vecptr = FaoVector; *vecptr++ = mclptr->Number; if (mclptr->Token == METACON_TOKEN_COMMENT) { *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel+1) * 3; *vecptr++ = mclptr->TextPtr; status = FaolToBuffer (Buffer, SizeOfBuffer, &Length, CommentFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); return ((int)Length); } if (mclptr->Token == METACON_TOKEN_VERSION) { *vecptr++ = mclptr->TextPtr; status = FaolToBuffer (Buffer, SizeOfBuffer, &Length, VersionFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); return ((int)Length); } switch (mclptr->Token) { case METACON_TOKEN_ELIF : case METACON_TOKEN_ELSE : case METACON_TOKEN_UNIF : case METACON_TOKEN_IFIF : if (mclptr->FlowControlLevel) *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel) * 3; else *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel+1) * 3; break; default: *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel+1) * 3; } for (cptr = mclptr->TextPtr; *cptr && !ISLWS(*cptr); cptr++); *vecptr++ = mclptr->ConfigProblem; *vecptr++ = cptr - mclptr->TextPtr; *vecptr++ = mclptr->TextPtr; while (*cptr && ISLWS(*cptr)) cptr++; *vecptr++ = cptr; *vecptr++ = mclptr->ConfigProblem; status = FaolToBuffer (Buffer, SizeOfBuffer, &Length, WatchRule ? WatchNonRuleFao : NonRuleFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); return ((int)Length); } /* for example, proxy configuration */ if (!(cptr = mclptr->LineDataPtr)) return (0); /* check the record type integer of this record */ apptr = arptr = NULL; if (*(int*)cptr == AUTH_REALM_RECORD_TYPE) arptr = (AUTH_REALM*)cptr; else if (*(int*)cptr == AUTH_PATH_RECORD_TYPE) apptr = (AUTH_PATH*)cptr; else ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); if (apptr) { /**********/ /* a path */ /**********/ if (apptr->SourceRealm == AUTH_SOURCE_OPAQUE) { vecptr = FaoVector; *vecptr++ = mclptr->Number; *vecptr++ = (mclptr->MetaFileLevel+mclptr->FlowControlLevel) * 3 + 3; *vecptr++ = apptr->PathPtr; status = FaolToBuffer (Buffer, SizeOfBuffer, &Length, WatchRule ? WatchPathOpaqueFao : PathOpaqueFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); return ((int)Length); } cptr = AuthCanString (apptr->AuthGroupCan, AUTH_CAN_FORMAT_SHORT); if (!cptr) cptr = "*ERROR*"; strcpy (GroupCanString, cptr); cptr = AuthCanString (apptr->AuthWorldCan, AUTH_CAN_FORMAT_SHORT); if (!cptr) cptr = "*ERROR*"; strcpy (WorldCanString, cptr); vecptr = FaoVector; *vecptr++ = mclptr->Number; *vecptr++ = (mclptr->MetaFileLevel + mclptr->FlowControlLevel) * 3 + 3; *vecptr++ = apptr->PathProblem; *vecptr++ = apptr->PathPtr; *vecptr++ = GroupCanString; *vecptr++ = WorldCanString; *vecptr++ = apptr->FinalRule; *vecptr++ = apptr->VmsUserProfile; *vecptr++ = apptr->VmsUserScriptAs; *vecptr++ = apptr->NoCache; if (apptr->GroupRestrictListPtr[0]) { *vecptr++ = "!#* G:!&;AZ\n"; *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel) * 3 + 8; *vecptr++ = apptr->GroupRestrictListPtr; } else *vecptr++ = ""; if (apptr->WorldRestrictListPtr[0]) { *vecptr++ = "!#* W:!&;AZ\n"; *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel) * 3 + 8; *vecptr++ = apptr->WorldRestrictListPtr; } else *vecptr++ = ""; if (apptr->ProxyStringPtr[0]) { *vecptr++ = "!#* !&;AZ\n"; *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel) * 3 + 8; *vecptr++ = apptr->ProxyStringPtr; } else *vecptr++ = ""; if (apptr->PathParameterPtr[0]) { *vecptr++ = WatchRule ? "!#* PARAM=\'!AZ\'\n" : "!#* PARAM=\'!&;AZ\'\n"; *vecptr++ = (mclptr->MetaFileLevel+ mclptr->FlowControlLevel) * 3 + 8; *vecptr++ = apptr->PathParameterPtr; } else *vecptr++ = ""; *vecptr++ = apptr->PathProblem; status = FaolToBuffer (Buffer, SizeOfBuffer, &Length, WatchRule ? WatchPathFao : PathFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); return ((int)Length); } if (arptr) { /***********/ /* a realm */ /***********/ vecptr = FaoVector; *vecptr++ = mclptr->Number; *vecptr++ = (mclptr->MetaFileLevel+mclptr->FlowControlLevel) * 3; *vecptr++ = arptr->RealmProblem; if (arptr->RealmDescrPtr && arptr->RealmDescrPtr[0]) { *vecptr++ = ""!&;AZ"="; *vecptr++ = arptr->RealmDescrPtr; } else *vecptr++ = ""; *vecptr++ = arptr->RealmPtr; *vecptr++ = AuthSourceString (arptr->RealmPtr, arptr->SourceRealm); if (arptr->RealmParamPtr && arptr->RealmParamPtr[0]) { *vecptr++ = "+"!&;AZ""; *vecptr++ = arptr->RealmParamPtr; } else *vecptr++ = ""; *vecptr++ = arptr->GroupWritePtr; *vecptr++ = AuthSourceString (arptr->GroupWritePtr, arptr->SourceGroupWrite); *vecptr++ = arptr->GroupReadPtr; *vecptr++ = AuthSourceString (arptr->GroupReadPtr, arptr->SourceGroupRead); *vecptr++ = arptr->RealmProblem; status = FaolToBuffer (Buffer, SizeOfBuffer, &Length, WatchRule ? WatchRealmFao : RealmFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); return ((int)Length); } return (0); } /*****************************************************************************/