/*****************************************************************************/ /* AuthACME.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. The Authentication and Credentials Management Extensions (ACME) subsystem provides authentication and persona-based credential services. Applications use these services to enforce authentication policies defined by ACME agents running in the context of the ACME_SERVER process. This module will form the basis of an authentication capability using the $ACM() system service and the "Authentication and Credential Management Extensions" server. It is not available on VAX and is only for VMS later than V7.3. See AUTH.C for overall detail on the WASD authorization environment. WHY ACME? --------- It offers a vendor maintained authentication service that, in part, parallels that provided by the WASD SYSUAF authentication facility. Of course, the "vendor maintained" is the important bit! It should be more robust and less-likely to get (or be) broken than the WASD equivalent. So, for applicable platforms no more $GETAUI() and then checking password expiry and creating password hashes and comparing them, etc., etc. It's all handled by the one SYS$ACM() call. Does this mean the historical AUTHVMS.C contortions can be dispensed with? Well, no, of course not. For non-supported platforms it still must be maintained, as well as WASD's use of some portions of the SYSUAF account information for further controlling access (e.g. privileged accounts, rights identifiers). Any down sides? Well it appears as if the authentication failure information returned by SYS$ACM() is quite chunky, basically one %ACME-E-AUTHFAIL, so you lose the explanatory information available with AuthVmsVerifyUser(). The WASD SYSUAF password change functions available via HTADMIN.C and AUTHVMS.C also get a gee-up by using the ACME service. The password change SYS$ACM() will invoke the site's full password policy (much better than the half-assed WASD implementation) and so potentially provide dictionary and password history functionality, etc., for web-based password change. Other reasons for using ACME ... well it can authenticate from sources other than the SYSUAF and supply a mapped VMS username as a result. At the time of writing the only other HP-supported "domain of interpretation" is the "MSV1_0" Microsoft Lan Manager domain-based authentication. There may be more in the future, including third-party and locally developed ACME plug-ins. So WASD having this now provides for future authentication developments as well. VERSION HISTORY --------------- 10-OCT-2009 MGD AuthAcmeVerifyUser() requires SECURITY privilege to allow ACME$M_NOAUTHORIZATION for authentication-only when using WASD_NIL_ACCESS identifier, AuthAcmeVerifyUser() can now use [AuthSYSUAFlogonType] and/or an optional authorization rule parameter 'param="logon=.."' to specify the login mode (default is still NETWORK) 29-APR-2009 MGD DOI name of '*' indicates use the default of ACME$LATEST_ENABLED_AGENT_LIST rather than the specified DOI (authentication realm is set to the DOI authentication realm) 24-NOV-2007 MGD force ACME on VMS V7.3 and later 31-JUL-2005 MGD add remote IP address to refine intrusion data and reduce possibility of DOS attack on particular usernames, bugfix; AuthAcmeVerifyUser() ACME$_LOGON_TYPE requires IMPERSONATE (DETACH) privilege for VMS V7.3-1 and earlier 16-MAR-2004 MGD initial (new with WASD v8.5) */ /*****************************************************************************/ #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 #ifndef WASD_ACME # define WASD_ACME 0 #endif /**************************************/ #if WASD_ACME /* ACME authentication */ /**************************************/ /* standard C header files */ #include #include #include #include /* VMS related header files */ #include #include #include #include #include #define ILE3 ile3 /* because of the __VMS_VER */ #include #include #include /* application related header files */ #include "wasd.h" #define WASD_MODULE "AUTHACME" #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 */ /******************/ /* this image is linked with ACME capabilities */ BOOL AuthAcmeLinked = true; /********************/ /* external storage */ /********************/ #ifdef DBUG extern BOOL Debug; #else #define Debug 0 #endif extern BOOL AuthConfigACME, AuthNilAccessExists, AuthSysUafEnabled; extern int EfnWait, EfnNoWait; extern int ToLowerCase[], ToUpperCase[]; extern unsigned long DetachMask[], SecurityMask[]; extern char ErrorSanityCheck[]; extern ACCOUNTING_STRUCT *AccountingPtr; extern CONFIG_STRUCT Config; extern MSG_STRUCT Msgs; extern SYS_INFO SysInfo; extern WATCH_STRUCT Watch; /*****************************************************************************/ /* Verify the request username/password using $ACM() services. Return the results via AST AuthAcmeVerifyUserAst(). */ int AuthAcmeVerifyUser (REQUEST_STRUCT* rqptr) { int status, SetPrvStatus, UserNameLength; unsigned long AcmeLogonType, FuncCode; unsigned long PrivMask [2]; char *cptr, *sptr, *zptr; char UserNameBuffer [256]; AUTH_ACME *acmeptr; ILE3 *itmptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_MOD_AUTH, "AuthAcmeVerifyUser() !&Z !&Z", rqptr->rqAuth.RealmPtr, rqptr->RemoteUser); if (!AuthConfigACME) ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); rqptr->rqAuth.SysUafAuthenticated = true; if (!(cptr = rqptr->rqAuth.PathParameterPtr)) cptr = ""; while (*cptr && (TOLO(*cptr) != 'l' || !strsame(cptr,"logon=",6))) cptr++; if (*cptr) { /* same set of parameters as used by AuthVmsGetUai() */ if (strsame (cptr, "logon=NETWORK", 13)) AcmeLogonType = ACME$K_NETWORK; else if (strsame (cptr, "logon=BATCH", 11)) AcmeLogonType = ACME$K_BATCH; else if (strsame (cptr, "logon=LOCAL", 11)) AcmeLogonType = ACME$K_LOCAL; else if (strsame (cptr, "logon=DIALUP", 12)) AcmeLogonType = ACME$K_DIALUP; else if (strsame (cptr, "logon=REMOTE", 12)) AcmeLogonType = ACME$K_REMOTE; else { AcmeLogonType = 0; if (WATCHING (rqptr, WATCH_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_AUTH, "unknown ACME$_LOGON_TYPE \"!AZ\"", cptr); } } else if (Config.cfAuth.SysUafLogonType) AcmeLogonType = Config.cfAuth.SysUafLogonType; else AcmeLogonType = ACME$K_NETWORK; rqptr->rqAuth.SysUafLogonType = AcmeLogonType; FuncCode = ACME$_FC_AUTHENTICATE_PRINCIPAL; PrivMask[0] = DetachMask[0]; PrivMask[1] = DetachMask[1]; acmeptr = rqptr->rqAuth.AcmeDataPtr = (AUTH_ACME*)VmGetHeap (rqptr, sizeof(AUTH_ACME)); itmptr = &acmeptr->AcmItemList; if (rqptr->rqAuth.SourceRealm == AUTH_SOURCE_VMS || rqptr->rqAuth.SourceRealm == AUTH_SOURCE_ID || rqptr->rqAuth.SourceRealm == AUTH_SOURCE_WASD_ID || MATCH4 (rqptr->rqAuth.RealmPtr, "VMS\0") || MATCH4 (rqptr->rqAuth.RealmPtr, "VMS-") || MATCH4 (rqptr->rqAuth.RealmPtr, "VMS_")) { cptr = "VMS"; /* flag that case-less username and password checks were performed */ rqptr->rqAuth.CaseLess = true; FuncCode = ACME$_FC_AUTHENTICATE_PRINCIPAL; if (AuthNilAccessExists) { /* don't authorize access, just authenticate credentials */ FuncCode |= ACME$M_NOAUTHORIZATION; PrivMask[0] |= SecurityMask[0]; PrivMask[1] |= SecurityMask[1]; } } else cptr = rqptr->rqAuth.RealmPtr; if (*cptr == '*') { /* use the default DOI(s) ACME$LATEST_ENABLED_AGENT_LIST? */ itmptr->ile3$w_code = ACME$_AUTHENTICATING_DOI_NAME; itmptr->ile3$w_length = sizeof(acmeptr->AuthDoiName)-1; itmptr->ile3$ps_bufaddr = acmeptr->AuthDoiName; itmptr->ile3$ps_retlen_addr = &acmeptr->AuthDoiNameLength; itmptr++; /* just for WATCH purposes */ acmeptr->TargetDoiName[0] = '*'; } else { /* specify the DOI */ zptr = (sptr = acmeptr->TargetDoiName) + sizeof(acmeptr->TargetDoiName)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; acmeptr->TargetDoiNameLength = sptr - acmeptr->TargetDoiName; itmptr->ile3$w_code = ACME$_TARGET_DOI_NAME; itmptr->ile3$w_length = acmeptr->TargetDoiNameLength; itmptr->ile3$ps_bufaddr = acmeptr->TargetDoiName; itmptr->ile3$ps_retlen_addr = 0; itmptr++; } /* requires IMPERSONATE (DETACH) privilege on VMS V7.3-1 or earlier */ itmptr->ile3$w_code = ACME$_LOGON_TYPE; itmptr->ile3$w_length = sizeof(AcmeLogonType); itmptr->ile3$ps_bufaddr = &AcmeLogonType; itmptr->ile3$ps_retlen_addr = 0; itmptr++; itmptr->ile3$w_code = ACME$_PRINCIPAL_NAME_IN; itmptr->ile3$w_length = rqptr->RemoteUserLength; itmptr->ile3$ps_bufaddr = rqptr->RemoteUser; itmptr->ile3$ps_retlen_addr = 0; itmptr++; /* requires IMPERSONATE (DETACH) privilege */ itmptr->ile3$w_code = ACME$_REMOTE_HOST_NAME; itmptr->ile3$w_length = strlen(&rqptr->ClientPtr->IpAddressString); itmptr->ile3$ps_bufaddr = &rqptr->ClientPtr->IpAddressString; itmptr->ile3$ps_retlen_addr = 0; itmptr++; /* create a composite string containing the user name */ zptr = (sptr = UserNameBuffer) + sizeof(UserNameBuffer)-1; for (cptr = "WASD:"; *cptr; *sptr++ = *cptr++); for (cptr = rqptr->RemoteUser; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; UserNameLength = sptr - UserNameBuffer; cptr = VmGetHeap (rqptr, UserNameLength+1); memcpy (cptr, UserNameBuffer, UserNameLength+1); /* requires IMPERSONATE (DETACH) privilege */ itmptr->ile3$w_code = ACME$_REMOTE_USERNAME; itmptr->ile3$w_length = UserNameLength; itmptr->ile3$ps_bufaddr = cptr; itmptr->ile3$ps_retlen_addr = 0; itmptr++; itmptr->ile3$w_code = ACME$_PASSWORD_1; itmptr->ile3$w_length = strlen(rqptr->RemoteUserPassword); itmptr->ile3$ps_bufaddr = rqptr->RemoteUserPassword; itmptr->ile3$ps_retlen_addr = 0; itmptr++; itmptr->ile3$w_code = ACME$_MAPPED_VMS_USERNAME; itmptr->ile3$w_length = sizeof(acmeptr->MappedVmsUserName); itmptr->ile3$ps_bufaddr = acmeptr->MappedVmsUserName; itmptr->ile3$ps_retlen_addr = &acmeptr->MappedVmsUserNameLength; itmptr++; if (WATCHING (rqptr, WATCH_AUTH)) { itmptr->ile3$w_code = ACME$_MAPPING_ACME_NAME; itmptr->ile3$w_length = sizeof(acmeptr->MappingAcmeName); itmptr->ile3$ps_bufaddr = acmeptr->MappingAcmeName; itmptr->ile3$ps_retlen_addr = &acmeptr->MappingAcmeNameLength; itmptr++; } memset (itmptr, 0, sizeof(ILE3)); /* provide required privilege(s) */ if (VMSnok (SetPrvStatus = sys$setprv (1, &PrivMask, 0, 0))) ErrorExitVmsStatus (SetPrvStatus, "sys$setprv()", FI_LI); status = sys$acm (EfnNoWait, FuncCode, 0, &acmeptr->AcmItemList, &acmeptr->AcmIOsb, &AuthAcmeVerifyUserAst, rqptr); if (VMSnok (SetPrvStatus = sys$setprv (0, &PrivMask, 0, 0))) ErrorExitVmsStatus (SetPrvStatus, "sys$setprv()", FI_LI); if (AuthNilAccessExists) if (status == SS$_NOPRIV) if (WATCHING (rqptr, WATCH_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_AUTH, "!AZ requires INSTALL with SECURITY privilege", AUTH_NIL_ACCESS_VMS_ID); if (VMSnok (status)) { /* an error with sys$acm(), fudge status and queue AST manually */ acmeptr->AcmIOsb[0] = acmeptr->AcmIOsb[1] = status; SysDclAst (AuthAcmeVerifyUserAst, rqptr); } /* function completes asynchronously! */ rqptr->rqAuth.AstFunction = rqptr->rqAuth.AstFunctionBuffer; rqptr->rqAuth.FinalStatus = AUTH_PENDING; return (AUTH_PENDING); } /*****************************************************************************/ /* AST delivered from the ACME service. Check the status and adjust to a WASD AUTH value if necessary. If a SYSUAF-equivalent authentication then also call AuthVmsVerifyUser() to check against other WASD restrictions (e.g. rights identifier authentication control), and if then still authenticated also check if the primary password has expired and if it has the redirect to a configured 'change password' URL or deny access. */ AuthAcmeVerifyUserAst (REQUEST_STRUCT* rqptr) { int status; char *cptr; AUTH_ACME *acmeptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_MOD_AUTH, "AuthAcmeVerifyUserAst()"); acmeptr = rqptr->rqAuth.AcmeDataPtr; if (WATCHING (rqptr, WATCH_AUTH)) { for (cptr = acmeptr->MappingAcmeName; *cptr && !isspace(*cptr); cptr++); *cptr = '\0'; acmeptr->MappingAcmeNameLength = cptr - acmeptr->MappingAcmeName; if (VMSok(acmeptr->AcmIOsb[0]) && acmeptr->AcmIOsb[0] == acmeptr->AcmIOsb[1]) { WatchThis (WATCHITM(rqptr), WATCH_AUTH, "ACME doi:\"!AZ\" agent:\"!AZ\" mapped:\"!AZ\" logon:!AZ !&S", acmeptr->TargetDoiName, acmeptr->MappingAcmeName, acmeptr->MappedVmsUserName, AuthSysUafLogonType(rqptr->rqAuth.SysUafLogonType), acmeptr->AcmIOsb[0]); } else if (!acmeptr->AcmIOsb[3] && acmeptr->AcmIOsb[0] == acmeptr->AcmIOsb[1]) { WatchThis (WATCHITM(rqptr), WATCH_AUTH, "ACME doi:\"!AZ\" logon:!AZ !&S", acmeptr->TargetDoiName, AuthSysUafLogonType(rqptr->rqAuth.SysUafLogonType), acmeptr->AcmIOsb[0]); } else { WatchThis (WATCHITM(rqptr), WATCH_AUTH, "ACME doi:\"!AZ\" logon:!AZ sts:!&S sec:!&S id:!UL acme:!&S", acmeptr->TargetDoiName, AuthSysUafLogonType(rqptr->rqAuth.SysUafLogonType), acmeptr->AcmIOsb[0], acmeptr->AcmIOsb[1], acmeptr->AcmIOsb[2], acmeptr->AcmIOsb[3], acmeptr->MappedVmsUserName); WatchDataFormatted ("%!&M\n%!&M\n", acmeptr->AcmIOsb[0], acmeptr->AcmIOsb[1]); } } status = acmeptr->AcmIOsb[0]; /* convert an ACME auth failure into a retryable server auth failure */ if (status == ACME$_AUTHFAILURE) status = AUTH_DENIED_BY_LOGIN; if (VMSok (status) && strsame (acmeptr->TargetDoiName, "VMS", -1)) rqptr->rqAuth.SysUafAuthenticated = true; /* if authentication OK and it effectively was from the SYSUAF */ if (VMSok (status) && rqptr->rqAuth.SysUafAuthenticated) { if (rqptr->rqAuth.RealmPtr[0] == '*') { /* use the authenticating DOI as the realm */ rqptr->rqAuth.RealmPtr = acmeptr->AuthDoiName; rqptr->rqAuth.RealmLength = acmeptr->AuthDoiNameLength; rqptr->rqAuth.RealmPtr[rqptr->rqAuth.RealmLength] = '\0'; } /* check there are no further (WASD-specific) restrictions */ if (VMSok (status = AuthVmsGetUai (rqptr, acmeptr->MappedVmsUserName))) { if (VMSok (status = AuthVmsVerifyUser (rqptr))) { /* authenticated ... user can do anything (the path allows!) */ rqptr->rqAuth.UserCan = AUTH_READWRITE_ACCESS; } } /* if authenticated */ if (VMSok (status)) { if (rqptr->rqAuth.SysUafPwdExpired) { /* password has expired */ if (!strsame (rqptr->rqHeader.RequestUriPtr, INTERNAL_PASSWORD_CHANGE, sizeof(INTERNAL_PASSWORD_CHANGE)-1)) { /* and not in the process of changing it */ if (rqptr->rqPathSet.AuthSysUafPwdExpUrlPtr) cptr = rqptr->rqPathSet.AuthSysUafPwdExpUrlPtr; else if (Config.cfAuth.SysUafPwdExpUrl[0]) cptr = Config.cfAuth.SysUafPwdExpUrl; else cptr = NULL; if (cptr) { /* expired password URL is configured */ if (!strsame (rqptr->rqHeader.RequestUriPtr, cptr, -1)) { /* request URI doesn't match it though, so redirect */ ResponseLocation (rqptr, cptr, -1); status = AUTH_DENIED_BY_REDIRECT; } } else { /* is not configured */ status = AUTH_DENIED_BY_LOGIN; } } } } if (VMSok (status)) { /* buffer the original remote user (the browser-supplied user id) */ strcpy (rqptr->rqAuth.RemoteUser, rqptr->RemoteUser); rqptr->rqAuth.RemoteUserLength = rqptr->RemoteUserLength; /* replace with the ACME mapped username */ strcpy (rqptr->RemoteUser, acmeptr->MappedVmsUserName); rqptr->RemoteUserLength = strlen(acmeptr->MappedVmsUserName); } } rqptr->rqAuth.FinalStatus = status; SysDclAst (AuthorizeRealmCheck, rqptr); } /*****************************************************************************/ /* Change the specified username's ('rqptr->RemoteUser') password in the specified ACME domain ('rqptr->rqAuth.RealmPtr'). It assumes the calling routine HTAdminChangePassword() has performed required preliminary sanity checks. This function is just to perform the change - ASYNCHRONOUSLY! */ AuthAcmeChangePassword ( REQUEST_STRUCT* rqptr, char *PasswordCurrent, char *PasswordNew ) { /* doesn't work using ACME$K_NETWORK (which is sort of understandable) */ static unsigned long AcmeLogonType = ACME$K_LOCAL; static unsigned long NewPasswordFlags = ACMEPWDFLG$M_PASSWORD_1; int len, status; char *cptr, *sptr, *zptr; AUTH_ACME *acmeptr; ILE3 *itmptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_MOD_AUTH, "AuthAcmeChangePassword() !&Z !&Z", rqptr->rqAuth.RealmPtr, rqptr->RemoteUser); if (WATCHING (rqptr, WATCH_RESPONSE)) WatchThis (WATCHITM(rqptr), WATCH_RESPONSE, "CHANGE ACME password"); if (!AuthConfigACME) ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); acmeptr = rqptr->rqAuth.AcmeDataPtr = (AUTH_ACME*)VmGetHeap (rqptr, sizeof(AUTH_ACME)); itmptr = &acmeptr->AcmItemList; if (rqptr->rqAuth.SourceRealm == AUTH_SOURCE_VMS || rqptr->rqAuth.SourceRealm == AUTH_SOURCE_ID || rqptr->rqAuth.SourceRealm == AUTH_SOURCE_WASD_ID || MATCH4 (rqptr->rqAuth.RealmPtr, "VMS\0") || MATCH4 (rqptr->rqAuth.RealmPtr, "VMS-") || MATCH4 (rqptr->rqAuth.RealmPtr, "VMS_")) cptr = "VMS"; else cptr = rqptr->rqAuth.RealmPtr; if (*cptr == '*') { /* use the default DOI(s) ACME$LATEST_ENABLED_AGENT_LIST? */ itmptr->ile3$w_code = ACME$_AUTHENTICATING_DOI_NAME; itmptr->ile3$w_length = sizeof(acmeptr->AuthDoiName)-1; itmptr->ile3$ps_bufaddr = acmeptr->AuthDoiName; itmptr->ile3$ps_retlen_addr = &acmeptr->AuthDoiNameLength; itmptr++; /* just for WATCH purposes */ acmeptr->TargetDoiName[0] = '*'; } else { /* specify the DOI */ zptr = (sptr = acmeptr->TargetDoiName) + sizeof(acmeptr->TargetDoiName)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; acmeptr->TargetDoiNameLength = sptr - acmeptr->TargetDoiName; itmptr->ile3$w_code = ACME$_TARGET_DOI_NAME; itmptr->ile3$w_length = acmeptr->TargetDoiNameLength; itmptr->ile3$ps_bufaddr = acmeptr->TargetDoiName; itmptr->ile3$ps_retlen_addr = 0; itmptr++; } itmptr->ile3$w_code = ACME$_LOGON_TYPE; itmptr->ile3$w_length = sizeof(AcmeLogonType); itmptr->ile3$ps_bufaddr = &AcmeLogonType; itmptr->ile3$ps_retlen_addr = 0; itmptr++; itmptr->ile3$w_code = ACME$_PRINCIPAL_NAME_IN; itmptr->ile3$w_length = rqptr->RemoteUserLength; itmptr->ile3$ps_bufaddr = rqptr->RemoteUser; itmptr->ile3$ps_retlen_addr = 0; itmptr++; len = strlen(PasswordCurrent); cptr = VmGetHeap (rqptr, len+1); strcpy (cptr, PasswordCurrent); itmptr->ile3$w_code = ACME$_PASSWORD_1; itmptr->ile3$w_length = len; itmptr->ile3$ps_bufaddr = cptr; itmptr->ile3$ps_retlen_addr = 0; itmptr++; itmptr->ile3$w_code = ACME$_NEW_PASSWORD_FLAGS; itmptr->ile3$w_length = sizeof(NewPasswordFlags); itmptr->ile3$ps_bufaddr = &NewPasswordFlags; itmptr->ile3$ps_retlen_addr = 0; itmptr++; len = strlen(PasswordNew); cptr = VmGetHeap (rqptr, len+1); strcpy (cptr, PasswordNew); itmptr->ile3$w_code = ACME$_NEW_PASSWORD_1; itmptr->ile3$w_length = len; itmptr->ile3$ps_bufaddr = cptr; itmptr->ile3$ps_retlen_addr = 0; itmptr++; memset (itmptr, 0, sizeof(ILE3)); status = sys$acm (EfnNoWait, ACME$_FC_CHANGE_PASSWORD, 0, &acmeptr->AcmItemList, &acmeptr->AcmIOsb, &AuthAcmeChangePasswordAst, rqptr); if (VMSnok (status)) { /* an error with sys$acm(), fudge status and queue AST manually */ acmeptr->AcmIOsb[0] = acmeptr->AcmIOsb[1] = status; SysDclAst (AuthAcmeChangePasswordAst, rqptr); } } /*****************************************************************************/ /* AST delivered from the ACME service. */ AuthAcmeChangePasswordAst (REQUEST_STRUCT* rqptr) { int status; char *cptr; AUTH_ACME *acmeptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_AUTH)) WatchThis (WATCHITM(rqptr), WATCH_MOD_AUTH, "AuthAcmeChangePasswordAst()"); acmeptr = rqptr->rqAuth.AcmeDataPtr; if (WATCHING (rqptr, WATCH_AUTH)) { for (cptr = acmeptr->MappingAcmeName; *cptr && !isspace(*cptr); cptr++); *cptr = '\0'; acmeptr->MappingAcmeNameLength = cptr - acmeptr->MappingAcmeName; if (VMSok(acmeptr->AcmIOsb[0]) && acmeptr->AcmIOsb[0] == acmeptr->AcmIOsb[1]) { WatchThis (WATCHITM(rqptr), WATCH_AUTH, "ACME doi:\"!AZ\" !&S", acmeptr->TargetDoiName, acmeptr->AcmIOsb[0]); } else if (!acmeptr->AcmIOsb[3] && acmeptr->AcmIOsb[0] == acmeptr->AcmIOsb[1]) { WatchThis (WATCHITM(rqptr), WATCH_AUTH, "ACME doi:\"!AZ\" !&S", acmeptr->TargetDoiName, acmeptr->AcmIOsb[0]); } else { WatchThis (WATCHITM(rqptr), WATCH_AUTH, "ACME doi:\"!AZ\" sts:!&S sec:!&S id:!UL acme:!&S", acmeptr->TargetDoiName, acmeptr->AcmIOsb[0], acmeptr->AcmIOsb[1], acmeptr->AcmIOsb[2], acmeptr->AcmIOsb[3], acmeptr->MappedVmsUserName); WatchDataFormatted ("%!&M\n%!&M\n", acmeptr->AcmIOsb[0], acmeptr->AcmIOsb[1]); } } status = acmeptr->AcmIOsb[0]; if (VMSok (status)) { if (rqptr->rqAuth.RealmPtr[0] == '*') { /* use the authenticating DOI as the realm */ rqptr->rqAuth.RealmPtr = acmeptr->AuthDoiName; rqptr->rqAuth.RealmLength = acmeptr->AuthDoiNameLength; rqptr->rqAuth.RealmPtr[rqptr->rqAuth.RealmLength] = '\0'; } } else { rqptr->rqResponse.HttpStatus = 403; cptr = VmGetHeap (rqptr, 256); FaoToBuffer (cptr, 255, NULL, "!&m.", status); *cptr = TOUP(*cptr); ErrorGeneral (rqptr, cptr, FI_NOLI); } HTAdminChangePasswordEnd (rqptr); } /*****************************************************************************/ /************************/ #else /* #if WASD_ACME */ /************************/ #include "wasd.h" #define WASD_MODULE "AUTHACME" extern char ErrorSanityCheck[]; /* this image is linked without ACME capabilities */ BOOL AuthAcmeLinked = 0; /* just for linkage and sanity checking */ int AuthAcmeVerifyUser (REQUEST_STRUCT* rqptr) { ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); /* keep the compile quiet using a return statement */ return (SS$_BUGCHECK); } AuthAcmeVerifyUserAst (REQUEST_STRUCT* rqptr) { ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); } AuthAcmeChangePassword ( REQUEST_STRUCT *rqptr, char *PasswordCurrent, char *PasswordNew ) { ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); } AuthAcmeChangePasswordAst (REQUEST_STRUCT* rqptr) { ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI); } /*************************/ #endif /* #if WASD_ACME */ /*************************/ /*****************************************************************************/