#pragma module ACME_EXAMPLE_DOI_ACME "X-6" /**************************************************************************** /* * /* © Copyright 2002-210 Hewlett-Packard Development Company, L.P. * /* * /* RESTRICTED RIGHTS LEGEND * /* * /* Use, duplication or disclosure by the U.S. Government is subject to * /* restrictions as set forth in subparagraph (c)(1)(ii) of the Rights * /* in Technical Data and Computer Software clause in DFARS 252.227-7013. * /* * /* Hewlett-Packard Development Company, L.P * /* 3000 Hanover Street * /* Palo Alto, CA 94304 * /* U.S.A. * /* * /* Rights for non-DOD U.S. Government Departments and Agencies are as * /* set forth in FAR 52.227-19(c)(1,2). * /* * /**************************************************************************** /* **++ ** ** FACILITY: VMS Authentication Server ** ** ABSTRACT: ** ** This module contains the callout routines that compose an ACME ** agent that performs simple username&password authentication in ** the "Independent Model". ** ** For successful authentication: ** 1. the "EXTAUTH" flag must be set in the VMS account ** 2. the first character of the password must be 'a'. (This is ** the password authentication policy) ** **-- ** ** AUTHOR: Takaaki Shinagawa (takaaki.shinagawa@hp.com), ** OpenVMS Security Engineering, Enterprise Systems Group, ** Hewlett-Packard Company ** ** CREATION DATE: 04-Mar-2003 ** ** Modification History: ** ** X-6 SGP0316 Prasad SG 11-FEB-2010 ** - Modified the P1_CREDENT to to similar structure changes ** in ACME_PERSONA_EXT.C (New fields added for storing lengths) ** - Modified the check of Lenght of principal and memory ** size of uppercase_principal from a hardcoded value ** of 16 to P1_PRINCIPAL_NAME_SIZE ** - Modified acme$co_credential() to pass the length ** of different fields in P1_CREDENT ** - Set the p1_credential->pxb_p1$principal correctly ** in acme$co_credential(), so that a "set password" ** works correctly ** - Added routine convertUincodeToAscii() ** ** ** X-5 JAH0467 John A Harney 17-Mar-2004 ** Use the ACME$K_MINOR_ID and ACME$K_MAJOR_ID symbols ** to check the ACM revision level; a cut-n-paste error ** was using ACMEKCV$K_MINOR_ID and ACMEKCV$K_MAJOR_ID. ** */ /* ** Include Files */ #include /* For severity codes */ #include #include #include #include "acme_example_doi.h" #include #include /* ** Local Definitions */ #define _DECLARE_PHASE_EVENT(name) \ DeclarePhaseNotificationEvent (kcb_vector_p, wqe_p, name) #define AgentName "ACME_EXAMPLE DOI" /* Agent Name */ #define YES 1 #define ACME_EXAMPLE_DOI_TARGETED 1 #define NO_AGENT_TARGETED 2 #define ACME_EXAMPLE_DOI_DESIGNATED 1 /* ** ACME Agent Control Callout Routines */ extern int acme$co_agent_initialize(); extern int acme$co_agent_startup(); extern int acme$co_agent_shutdown(); extern int acme$co_agent_standby(); /* ** ACME Authentication & Password Callout Routines */ extern int acme$co_initialize(); extern int acme$co_system_password(); extern int acme$co_announce(); extern int acme$co_autologon(); extern int acme$co_principal_name(); extern int acme$co_accept_principal(); extern int acme$co_map_principal(); extern int acme$co_validate_mapping(); extern int acme$co_ancillary_mech_1(); extern int acme$co_password_1(); extern int acme$co_ancillary_mech_2(); extern int acme$co_password_2(); extern int acme$co_ancillary_mech_3(); extern int acme$co_authenticate(); extern int acme$co_messages(); extern int acme$co_authorize(); extern int acme$co_notices(); extern int acme$co_logon_information(); extern int acme$co_new_password_1(); extern int acme$co_qualify_password_1(); extern int acme$co_new_password_2(); extern int acme$co_qualify_password_2(); extern int acme$co_accept_passwords(); extern int acme$co_set_password(); extern int acme$co_credentials(); extern int acme$co_finish(); /* ** ACME Event & Query Callout Routines */ extern int acme$co_event(); extern int acme$co_query(); /* ** MYACME_CTX contains per-ACME_Agent context information */ typedef struct myacme_ctx { int request_counter; int auth_success_counter; int auth_failure_counter; } MYACME_CTX; #define MYACME_CTX_SIZE sizeof(MYACME_CTX) /* ** MYWQE_CTX contains per-WQE context information */ typedef struct mywqe_ctx { /* ** ACME_EXAMPLE_DOI_TARGETED / NO_AGENT_TARGETED */ int target_status; /* ** ACME_EXAMPLE_DOI_DESIGNATED (if designated) */ int designation_status; int second_co_principal_name; int second_co_password_1; int second_co_new_password_1; int second_co_qualify_password_1; int second_co_logon_information; wchar_t *Principal; /* principal name (in Unicode) */ int PrincipalLength; /* principal name length */ wchar_t *Password; /* password accepted (in Unicode) */ int PasswordLength; /* password length */ wchar_t *NewPassword; /* new password (in Unicode) */ int NewPasswordLength; /* password length */ int PasswordExpired; /* 1 if password expired */ } MYWQE_CTX; #define MYWQE_CTX_SIZE sizeof(MYWQE_CTX) /* ** Sizes of elements in the credential data structure (P1 EXTENSION) */ #define P1_USERNAME_SIZE 32 #define P1_ACCOUNT_NAME_SIZE 32 #define P1_DOMAIN_NAME_SIZE 32 #define P1_DOI_NAME_SIZE 8 #define P1_PRINCIPAL_NAME_SIZE 32 #define P1_EXTENSION_NAME_SIZE 16 /* ** Data structure of the credential (for P1_EXT persona extension) */ typedef struct p1_credential { char pxb_p1$username[P1_USERNAME_SIZE]; /* USERNAME */ char pxb_p1$account[P1_ACCOUNT_NAME_SIZE]; /* ACCOUNT */ char pxb_p1$domain[P1_DOMAIN_NAME_SIZE]; /* DOMAIN */ char pxb_p1$doi[P1_DOI_NAME_SIZE]; /* DOI */ char pxb_p1$principal[P1_PRINCIPAL_NAME_SIZE]; /* PRINCIPAL */ char pxb_p1$extension[P1_EXTENSION_NAME_SIZE]; /* EXTENSION */ unsigned short pxb_p1$username_length; unsigned short pxb_p1$account_length; unsigned short pxb_p1$domain_length; unsigned short pxb_p1$doi_length; unsigned short pxb_p1$principal_length; unsigned short pxb_p1$extension_length; } P1_CREDENT; #define P1_CREDENT_SIZE sizeof(P1_CREDENT) /* ** Unicode messages */ wchar_t PrincipalNamePrompt[] = \ L">> USERNAME (for ACME_EXAMPLE_DOI ACME) >> "; wchar_t PasswordPrompt[] = \ L">> Password (for ACME_EXAMPLE_DOI ACME) >> "; wchar_t NewPasswordPrompt[] = \ L">> New Password (for ACME_EXAMPLE_DOI ACME) >> "; wchar_t NewPasswordPromptV[] = \ L">> Verify New Password (for ACME_EXAMPLE_DOI ACME) >> "; wchar_t LogonMessage[] = \ L"**** Logon Message from ACME_EXAMPLE_DOI ACME Agent ****"; wchar_t QualifyPasswordFailure[] = \ L"**** The New Password was not accepted ****"; /*============================================================================*/ void DeclarePhaseNotificationEvent (); void SendLog (ACMEKCV *, ACMEWQE *, void *); void SendOperator (ACMEKCV *, ACMEWQE *, char *); int FindItemCode (MYWQE_CTX *, ILE3 *, unsigned short int); int Process_Common_Items (MYWQE_CTX *, ILE3 *); int Process_Specific_Items (MYWQE_CTX *, ILE3 *); int convertUincodeToAscii (char* uniStr, unsigned uniStrLen, char*asciiStr, unsigned asciiStrLen); /*============================================================================*/ /*############################################################################# ** ** ACME Agent Control Callout Routines ** #############################################################################*/ /* ** Agent Initialize ** ** acme$co_agent_initialize kcb_vector, acme_context, wqe ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) */ extern int acme$co_agent_initialize ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p ) { ACMERSRC AgentRscBlk; int status; char init_msg[] = "ACME_EXAMPLE_DOI Agent is initialized"; struct dsc$descriptor_s Descriptor = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ /* ** Verify the revision levels of the WQE & KCV. ** Major versions need to be equal and ** minor version need to be greater or equal. ** Otherwise, return ACME$_UNSUPREVLVL. */ if ( (wqe_p-> acmewqe$w_revision_level. acmerevlvl$b_major_id != ACMEWQE$K_MAJOR_ID) || (wqe_p-> acmewqe$w_revision_level. acmerevlvl$b_minor_id < ACMEWQE$K_MINOR_ID) || (kcb_vector_p-> acmekcv$w_acm_revision_level. acmerevlvl$b_major_id != ACME$K_MAJOR_ID) || (kcb_vector_p-> acmekcv$w_acm_revision_level. acmerevlvl$b_minor_id < ACME$K_MINOR_ID) || (kcb_vector_p-> acmekcv$w_revision_level. acmerevlvl$b_major_id != ACMEKCV$K_MAJOR_ID) || (kcb_vector_p-> acmekcv$w_revision_level. acmerevlvl$b_minor_id < ACMEKCV$K_MINOR_ID) ) { /* ** The WQE or the CB Vector is out of rev. ** Sending error logs to the log file is not a good idea ** - Just return bad status. */ return ACME$_UNSUPREVLVL; /* Set bad status */ } /* ** Configure ACME Resource Block (fill in AgentRscBlk) ** (This configuration is optional) */ AgentRscBlk.acmersrc$q_privileges = PRV$M_SYSLCK | PRV$M_SYSNAM; AgentRscBlk.acmersrc$w_size = sizeof(AgentRscBlk); AgentRscBlk.acmersrc$w_revision_level. acmerevlvl$b_major_id = ACMERSRC$K_MAJOR_ID; AgentRscBlk.acmersrc$w_revision_level. acmerevlvl$b_minor_id = ACMERSRC$K_MINOR_ID; AgentRscBlk.acmersrc$l_stack_size = STACK_SIZE_REQUIRED; AgentRscBlk.acmersrc$r_agent_quotas. acmepq$l_memory = sizeof(MYACME_CTX); AgentRscBlk.acmersrc$r_agent_quotas.acmepq$l_channel = 1; AgentRscBlk.acmersrc$r_agent_quotas.acmepq$l_direct_io = 0; AgentRscBlk.acmersrc$r_agent_quotas.acmepq$l_buffer_io_mem = 0; AgentRscBlk.acmersrc$r_agent_quotas.acmepq$l_ast = 1; AgentRscBlk.acmersrc$r_agent_quotas.acmepq$l_tqe = 1; AgentRscBlk.acmersrc$r_agent_quotas.acmepq$l_lock = 0; /* ** Set the identity string (agent name) */ Descriptor.dsc$w_length = strlen(AgentName); Descriptor.dsc$a_pointer = AgentName; /* ** Report ACME identity (in Descriptor) ** & Quota requirements (in AgentRscBlk) ** to ACME server (through WQE) */ status = kcb_vector_p->acmekcv$cb_report_attributes( wqe_p, &Descriptor, &AgentRscBlk); if (FAILURE (status)) /* Failed */ { SendLog (kcb_vector_p, wqe_p, "acme$cb_report_attributes() failed"); return ACME$_FAILURE; } /* ** Set the current status string (init_msg) */ Descriptor.dsc$w_length = strlen(init_msg); Descriptor.dsc$a_pointer = init_msg; /* ** Report ACME activity (current status in Descriptor) to ACME server ** (through WQE) */ status = kcb_vector_p->acmekcv$cb_report_activity( wqe_p, &Descriptor); if (FAILURE (status)) /* Failed */ { SendLog (kcb_vector_p, wqe_p, "acme$cb_report_activity() failed"); return ACME$_FAILURE; } return ACME$_CONTINUE; } /* ** Agent Startup ** ** acme$co_agent_startup kcb_vector, acme_context, wqe ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** x_factor = Concurrency factor ** (read only, passed by reference) */ extern int acme$co_agent_startup ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p ) { MYACME_CTX *myacme_context; int status; _DECLARE_PHASE_EVENT ("acme$co_agent_startup"); SendLog (kcb_vector_p, wqe_p, "Message from acme$co_agent_startup() through SendLog()"); SendOperator (kcb_vector_p, wqe_p, "Message from acme$co_agent_startup() through SendOperator()"); /* ** Allocate ACME-wide memory (MYACME_CTX/acme_context_p) */ status = kcb_vector_p->acmekcv$cb_allocate_acme_vm( wqe_p, &MYACME_CTX_SIZE, acme_context_p); if (FAILURE (status)) /* Failure */ { SendLog (kcb_vector_p, wqe_p, "acme$cb_allocate_acme_vm() failed"); return ACME$_FAILURE; } myacme_context = (MYACME_CTX *)*acme_context_p; /* ** Initialize the counters */ myacme_context->request_counter = 0; myacme_context->auth_success_counter = 0; myacme_context->auth_failure_counter = 0; return ACME$_CONTINUE; } /* ** Agent Shutdown ** ** acme$co_agent_shutdown kcb_vector, acme_context, wqe ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) */ extern int acme$co_agent_shutdown ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p ) { int status; MYACME_CTX *myacme_context = (MYACME_CTX *)*acme_context_p; /* ** Deallocate ACME-wide virtual memory (acme_context_p) */ status = kcb_vector_p->acmekcv$cb_deallocate_acme_vm ( wqe_p, &MYACME_CTX_SIZE, acme_context_p); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_deallocate_acme_vm() failed"); return ACME$_FAILURE; } return ACME$_NORMAL; } /* ** Agent Standby ** ** acme$co_agent_standby kcb_vector, acme_context, wqe ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) */ extern int acme$co_agent_standby ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p ) { return ACME$_CONTINUE; } /*############################################################################# ** ** ACME Authentication & Password Callout Routines ** #############################################################################*/ /* << 1 >> ** acme$co_initialize kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_initialize ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { int status; MYACME_CTX *myacme_context; MYWQE_CTX *mywqe_context; _DECLARE_PHASE_EVENT ("acme$co_initialize"); SendLog (kcb_vector_p, wqe_p, \ "Message from acme$co_initialize() through SendLog()"); SendOperator (kcb_vector_p, wqe_p, \ "Message from acme$co_initialize() through SendOperator()"); /* ** Get MYACME_CTX and increment the counter ** (optional-- example to use acme_context) */ if (*acme_context_p != 0) { myacme_context = (MYACME_CTX *)*acme_context_p; myacme_context->request_counter++; } /* ** If another agent is: ** 1. targeted ** or ** 2. designated DOI, ** ** return ACME$_CONTINUE without allocating mywqe_context. ** ** - In the subsequent callout routines, ** check if wqe_context is empty ** to detect this case (another agent is targeted). */ /* 1. */ if ( (wqe_p->acmewqe$l_target_acme_id.acmeid$v_acme_num != 0) && (wqe_p->acmewqe$l_target_acme_id.acmeid$v_acme_num != wqe_p->acmewqe$l_current_acme_id.acmeid$v_acme_num) ) { SendLog (kcb_vector_p, wqe_p, \ "Agent other than ACME_EXAMPLE_DOI is targeted"); return ACME$_CONTINUE; } /* 2. */ if ((wqe_p->acmewqe$l_designated_acme_id.acmeid$v_acme_num != wqe_p->acmewqe$l_current_acme_id.acmeid$v_acme_num) && (wqe_p->acmewqe$l_designated_acme_id.acmeid$v_acme_num != 0) ) { SendLog (kcb_vector_p, wqe_p, \ "Another agent has set designated DOI"); return ACME$_CONTINUE; } /* ** Allocate request-specific memory (MYWQE_CTX/wqe_context_p) */ status = kcb_vector_p->acmekcv$cb_allocate_wqe_vm ( wqe_p, &MYWQE_CTX_SIZE, wqe_context_p); if(FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, \ "acmekcv$cb_allocate_wqe_vm() failed"); return ACME$_FAILURE; } memset(*wqe_context_p, 0, MYWQE_CTX_SIZE); mywqe_context = (MYWQE_CTX *)*wqe_context_p; /* ** Initialize mywqe_context */ mywqe_context->second_co_principal_name = 0; mywqe_context->second_co_password_1 = 0; mywqe_context->second_co_new_password_1 = 0; mywqe_context->second_co_qualify_password_1 = 0; mywqe_context->Principal = NULL; mywqe_context->PrincipalLength = 0; mywqe_context->Password = NULL; mywqe_context->PasswordLength = 0; mywqe_context->NewPassword = NULL; mywqe_context->NewPasswordLength = 0; mywqe_context->PasswordExpired = 0; /* ** Initialize designation status */ mywqe_context->designation_status = 0; /* ** Determine the target status */ if (wqe_p->acmewqe$l_target_acme_id.acmeid$v_acme_num == 0) { mywqe_context->target_status = NO_AGENT_TARGETED; SendLog (kcb_vector_p, wqe_p, \ "No Agent is targeted (untargeted request)"); } else if (wqe_p->acmewqe$l_target_acme_id.acmeid$v_acme_num == wqe_p->acmewqe$l_current_acme_id.acmeid$v_acme_num) { mywqe_context->target_status = ACME_EXAMPLE_DOI_TARGETED; SendLog (kcb_vector_p, wqe_p, \ "ACME_EXAMPLE_DOI Agent is targeted"); } /* ** Process the common item list */ if (item_list_p != NULL) { status = Process_Common_Items (mywqe_context, item_list_p); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "Process_Common_Items() failed"); return ACME$_FAILURE; } } /* ** Process the ACME-specific item list */ if (acme_item_list_p != NULL) { status = Process_Specific_Items (mywqe_context, acme_item_list_p); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "Process_Common_Items() failed"); return ACME$_FAILURE; } } return ACME$_CONTINUE; } /* << 2 >> ** acme$co_system_password kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_system_password ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_system_password"); SendLog (kcb_vector_p, wqe_p, "Message from acme$co_system_password() through SendLog()"); SendOperator (kcb_vector_p, wqe_p, "Message from acme$co_system_password() through SendOperator()"); return ACME$_CONTINUE; } /* << 3 >> ** acme$co_announce kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_announce ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_announce"); SendLog (kcb_vector_p, wqe_p, \ "Message from acme$co_announce() through SendLog()"); SendOperator (kcb_vector_p, wqe_p, \ "Message from acme$co_announce() through SendOperator()"); return ACME$_CONTINUE; } /* << 4 >> ** acme$co_autologon kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_autologon ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_autologon"); SendLog (kcb_vector_p, wqe_p, \ "Message from acme$co_autologon() through SendLog()"); SendOperator (kcb_vector_p, wqe_p, \ "Message from acme$co_autologon() through SendOperator()"); return ACME$_CONTINUE; } /* << 5 >> ** acme$co_principal_name kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_principal_name ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { int status; ILE3 *pItem = NULL; struct dsc$descriptor_s Descriptor = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ MYWQE_CTX *mywqe_context; _DECLARE_PHASE_EVENT ("acme$co_principal_name"); SendLog (kcb_vector_p, wqe_p, \ "Message from acme$co_principal_name() through SendLog()"); SendOperator (kcb_vector_p, wqe_p, \ "Message from acme$co_principal_name() through SendOperator()"); /* ** If this agent is not participating in this request ** (another agent is targeted or designated ** in the $co_initialize phase) ** or ** If this callout phase has been completed by another agent */ if((*wqe_context_p == 0) || (wqe_p->acmewqe$l_flags.acmewqeflg$v_phase_done)) { return ACME$_CONTINUE; } /* ** if another agent has set designated DOI, skip. ** (necessary to keep checking this flag in every phase ** until $co_accept_principal) */ if ((wqe_p->acmewqe$l_designated_acme_id.acmeid$v_acme_num != wqe_p->acmewqe$l_current_acme_id.acmeid$v_acme_num) && (wqe_p->acmewqe$l_designated_acme_id.acmeid$v_acme_num != 0) ) { return ACME$_CONTINUE; } mywqe_context = (MYWQE_CTX *)*wqe_context_p; /* ** First time of entering this callout routine */ if (!mywqe_context->second_co_principal_name) { /* ** If the ACME$_PRINCIPAL_NAME_IN item code was not initially ** supplied, prompt for principal name. ** Otherwise, move it into the WQE. */ if (!mywqe_context->Principal) { /* ** No principal name was supplied, if dialogue is not ** possible, return INSFDIALSUPPORT. ** Otherwise, queue a dialogue request for ** principal name and return PERFORMDIALOGUE. */ if (!wqe_p->acmewqe$l_dialogue_flags. acmedlogflg$v_input) { SendLog (kcb_vector_p, wqe_p, "No principal & No dialogue"); return ACME$_INSFDIALSUPPORT; } /* ** Dialogue is possible. Load and queue the request. */ Descriptor.dsc$w_length = sizeof(PrincipalNamePrompt); Descriptor.dsc$a_pointer = (char*)&PrincipalNamePrompt; /* ** <> ** Queue dialogue to be sent to the client */ status = kcb_vector_p->acmekcv$cb_queue_dialogue( wqe_p, /* WQE address */ ACMEDLOGFLG$M_INPUT, /* Input Required */ ACME$_PRINCIPAL_NAME_IN, /* requested item */ ACME$K_MAXCHAR_PRINCIPAL_NAME, /* Max size */ &Descriptor, /* Descriptor Address */ 0); if (FAILURE (status)) { switch (status) { case ACME$_DIALOGFULL: SendLog (kcb_vector_p, wqe_p, \ "acmekcv$cb_queue_dialogue() \ failed-- ACME$_DIALOGFULL"); break; case ACME$_INSFDIALSUPPORT: SendLog (kcb_vector_p, wqe_p, \ "acmekcv$cb_queue_dialogue() \ failed-- ACME$_INSFDIALSUPPORT"); break; case ACME$_INVPARAMETER: SendLog (kcb_vector_p, wqe_p, \ "acmekcv$cb_queue_dialogue() \ failed--ACME$_INVPARAMETER"); break; case ACME$_UNSUPPORTED: SendLog (kcb_vector_p, wqe_p, \ "acmekcv$cb_queue_dialogue() \ failed--ACME$_UNSUPPORTED"); break; default: if(status <= 122346500) SendLog (kcb_vector_p, wqe_p, \ "acmekcv$cb_queue_dialogue() \ failed--other reason within \ the range"); else SendLog (kcb_vector_p, wqe_p, \ "acmekcv$cb_queue_dialogue() \ failed--other reason beyond \ the range"); } return ACME$_FAILURE; } /* Set 2nd pass flag */ mywqe_context->second_co_principal_name = 1; /* Perform the dialogue */ return ACME$_PERFORMDIALOGUE; } /* ** If Principal is already provided, ** return ACME$_CONTINUE. */ else { return ACME$_CONTINUE; } } /* ** Second time in this routine ** It is the time to get a principal from the client */ else { if (item_list_p != NULL) { /* ** Check if item code ACME$_PRINCIPAL_NAME_IN is ** in the item list */ status = FindItemCode ( mywqe_context, item_list_p, ACME$_PRINCIPAL_NAME_IN); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "The ItemCode was not found"); return ACME$_FAILURE; } } else { SendLog (kcb_vector_p, wqe_p, "item_list_p was empty"); return ACME$_FAILURE; } if (mywqe_context->Principal == NULL) { SendLog (kcb_vector_p, wqe_p, \ "Principal was not found in MYWQE_CTX"); return ACME$_FAILURE; } /* ** Load principal name & length into Descriptor */ Descriptor.dsc$w_length = mywqe_context->PrincipalLength; Descriptor.dsc$a_pointer = mywqe_context->Principal; /* ** Set the Principal in WQE */ status = kcb_vector_p->acmekcv$cb_set_wqe_parameter( wqe_p, ACMEWQE$K_PRINCIPAL_NAME, &Descriptor); if (FAILURE(status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_parameter() failed"); return ACME$_FAILURE; } /* ** Set the WQE "phase done flag" and return */ status = kcb_vector_p->acmekcv$cb_set_wqe_flag ( wqe_p, ACMEWQEFLG$K_PHASE_DONE); if (FAILURE(status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_flag() failed"); return ACME$_FAILURE; } return ACME$_CONTINUE; } } /* << 6 >> ** ACCEPT_PRINCIPAL phase processing ** ** acme$co_accept_principal kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_accept_principal ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { int status, i; struct dsc$descriptor_s Descriptor = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ MYWQE_CTX *mywqe_context; _DECLARE_PHASE_EVENT ("acme$co_accept_principal"); SendLog (kcb_vector_p, wqe_p, \ "Message from acme$co_accept_principal() through SendLog()"); SendOperator (kcb_vector_p, wqe_p, \ "Message from acme$co_accept_principal() through SendOperator()"); /* ** If this agent is not participating in this request ** (another agent is targeted or designated in the $co_initialize ** phase) ** or ** If this callout phase has been completed by another agent */ if ((*wqe_context_p == 0) || (wqe_p->acmewqe$l_flags.acmewqeflg$v_phase_done) ) return ACME$_CONTINUE; mywqe_context = (MYWQE_CTX *)*wqe_context_p; /* ** if another agent has set designated DOI, skip. ** (necessary to check this flag in every phase until ** $co_accept_principal) */ if ((wqe_p->acmewqe$l_designated_acme_id.acmeid$v_acme_num != wqe_p->acmewqe$l_current_acme_id.acmeid$v_acme_num) && (wqe_p->acmewqe$l_designated_acme_id.acmeid$v_acme_num != 0) ) { return ACME$_CONTINUE; } /* ** Get Principal Name & Length ** This is for the cases when mywqe_context->Principal is empty ** because the CO_PRINCIPAL_NAME phase was completed by ** another Agent (e.g. VMS Agent). */ mywqe_context->Principal = (wchar_t*)wqe_p-> acmewqe$ps_func_dep_params-> acmewqefdx$r_auth_pwd. acmewqeax$r_principal_name. acmewqeitm$ps_pointer; mywqe_context->PrincipalLength = wqe_p-> acmewqe$ps_func_dep_params-> acmewqefdx$r_auth_pwd. acmewqeax$r_principal_name. acmewqeitm$l_length; /* ** Make sure that Principal is stored in the MYWQE_CTX structure. ** (mywqe_context->Principal should be filled in the CO_PRINCIPAL_NAME ** in the dialogue mode) */ if (mywqe_context->Principal == NULL) { SendLog (kcb_vector_p, wqe_p, \ "Principal was not found in MYWQE_CTX \ (co_accept_principal)"); return ACME$_FAILURE; } /*####################################################################*/ /* << Implement a policy to accept a principal name >> ** ** As an example, ** Check if the pricipal can be accepted ** (Example: principal must be <= P1_PRINCIPAL_NAME_SIZE characters) ** ** The string was converted to Unicode by the ACME server. ** As a result, every character becomes 4 bytes. ** (e.g. Principal "SYSTEM" is 6*4 = 24 bytes) */ if ((mywqe_context->PrincipalLength / 4) > P1_PRINCIPAL_NAME_SIZE) { SendLog (kcb_vector_p, wqe_p, "Principal name is longer than 16 chars"); for (i = 0; i < mywqe_context->PrincipalLength; i++) { SendLog (kcb_vector_p, wqe_p, mywqe_context->Principal); mywqe_context->Principal++; } /* ** Set the secondary status code */ status = kcb_vector_p->acmekcv$cb_set_2nd_status ( wqe_p, ACME$_NOSUCHUSER); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_2nd_status() failed"); return ACME$_FAILURE; } return ACME$_AUTHFAILURE; } /*####################################################################*/ /* ** Load principal name & length into Descriptor */ Descriptor.dsc$w_length = mywqe_context->PrincipalLength; Descriptor.dsc$a_pointer = mywqe_context->Principal; /* ** Set the accepted principal name in WQE */ status = kcb_vector_p->acmekcv$cb_set_wqe_parameter( wqe_p, ACMEWQE$K_PRINCIPAL_NAME_OUT, &Descriptor); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_parameter() failed"); return ACME$_FAILURE; } /* ** Declear this is the Designated DOI (Domain of Interpretation) */ status = kcb_vector_p->acmekcv$cb_set_designated_doi(wqe_p); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_designated_doi() failed"); return ACME$_FAILURE; } else { /* This Agent becomes the designated DOI */ SendLog (kcb_vector_p, wqe_p, "ACME_EXAMPLE_DOI becomes the designated DOI Agent"); mywqe_context->designation_status = ACME_EXAMPLE_DOI_DESIGNATED; } /* ** Set the WQE phase done bit and return. */ status = kcb_vector_p->acmekcv$cb_set_wqe_flag( wqe_p, ACMEWQEFLG$K_PHASE_DONE); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_flag() failed"); return ACME$_FAILURE; } return ACME$_CONTINUE; } /* << 7 >> ** ACME$CO_MAP_PRINCIPAL kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_map_principal ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { int status, i; struct dsc$descriptor_s Descriptor = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ MYWQE_CTX *mywqe_context; wchar_t uppercase_principal[P1_PRINCIPAL_NAME_SIZE]; _DECLARE_PHASE_EVENT ("acme$co_map_principal"); SendLog (kcb_vector_p, wqe_p, \ "Message from acme$co_map_principal() through SendLog()"); SendOperator (kcb_vector_p, wqe_p, \ "Message from acme$co_map_principal() through SendOperator()"); /* ** Initialize the buffer for uppercased principal */ for (i == 0; i < P1_PRINCIPAL_NAME_SIZE; i++) uppercase_principal[i] = 0; /* ** If this agent is not participating in this request ** (another agent is targeted or designated in the $co_initialize) ** or ** If this callout phase has been completed by another agent */ if ((*wqe_context_p == 0) || (wqe_p->acmewqe$l_flags.acmewqeflg$v_phase_done) ) { return ACME$_CONTINUE; } mywqe_context = (MYWQE_CTX *)*wqe_context_p; /* ** If this ACME agent is not designated, ** skip the rest (return ACME$_CONTINUE). */ if (mywqe_context->designation_status != ACME_EXAMPLE_DOI_DESIGNATED) { return ACME$_CONTINUE; } /* ** Assuming that the principal name accepted ** in ACME$CO_ACCEPT_PRINCIPAL() ** -- SKIP THE MAPPING ** -- IF THE USER-INPUT PRINCIPAL NAME IS DIFFERENT FROM VMS USERNAME, ** -- IT'S NECESSARY TO IMPLEMENT THE MAPPING. */ /* ** Make sure that Principal is stored in the MYWQE_CTX structure. ** (mywqe_context->Principal should be filled in the CO_PRINCIPAL_NAME ** in the dialogue mode) */ if (mywqe_context->Principal == NULL) { SendLog (kcb_vector_p, wqe_p, \ "Principal was not found in MYWQE_CTX (co_map_principal)"); return ACME$_FAILURE; } /* ** Get Principal Name & Length ** This is for the cases when mywqe_context->Principal is empty ** because the CO_PRINCIPAL_NAME phase was completed by ** another Agent (e.g. VMS Agent). */ mywqe_context->Principal = (wchar_t*)wqe_p-> acmewqe$ps_func_dep_params-> acmewqefdx$r_auth_pwd. acmewqeax$r_principal_name. acmewqeitm$ps_pointer; mywqe_context->PrincipalLength = wqe_p-> acmewqe$ps_func_dep_params-> acmewqefdx$r_auth_pwd. acmewqeax$r_principal_name. acmewqeitm$l_length; /* ** Convert the Principal string to UPPERCASE ** This conversion is necessary because the current ACME server ** doesn't uppercase the principal string. As a result, a ** lowercase principal string causes a mismatch against a VMS ** username (always uppercase) in the ACME server/services ** routines. ** ** As a Unicode character is 4 bytes, PrincipalLength/4 */ for (i = 0; i < (mywqe_context->PrincipalLength)/4; i++) { uppercase_principal[i] = towupper(mywqe_context->Principal[i]); } /* ** Load principal name & length into Descriptor */ Descriptor.dsc$w_length = mywqe_context->PrincipalLength; Descriptor.dsc$a_pointer = uppercase_principal; /* ** Set the VMS username in WQE */ status = kcb_vector_p->acmekcv$cb_set_wqe_parameter( wqe_p, ACMEWQE$K_VMS_USERNAME, &Descriptor); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_parameter() failed"); return ACME$_FAILURE; } /* ** Set the WQE phase done bit and return. */ status = kcb_vector_p->acmekcv$cb_set_wqe_flag( wqe_p, ACMEWQEFLG$K_PHASE_DONE); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_flag() failed"); return ACME$_FAILURE; } return ACME$_CONTINUE; } /* << 8 >> ** VALIDATE_MAPPING phase processing ** ** acme$co_validate_mapping kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_validate_mapping ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_validate_mapping"); return ACME$_CONTINUE; } /* << 9 >> ** ANCILLARY_MECH_1 phase processing ** ** acme$co_ancillary_mech_1 kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_ancillary_mech_1 ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_ancillary_mech_1"); return ACME$_CONTINUE; } /* << 10 >> ** PASSWORD_1 phase processing ** ** acme$co_password_1 kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_password_1 ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { int status; ILE3 *pItem = NULL; struct dsc$descriptor_s Descriptor = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ MYWQE_CTX *mywqe_context; _DECLARE_PHASE_EVENT ("acme$co_password_1"); /* ** If this agent is not participating in this request ** (another agent is targeted or designated in the $co_initialize) ** or ** If this callout phase has been completed by another agent */ if ((*wqe_context_p == 0) || (wqe_p->acmewqe$l_flags.acmewqeflg$v_phase_done) ) { return ACME$_CONTINUE; } /* ** Also check the acmewqeflg$v_preauthenticated flag. ** If the flag has been set, ** skip the rest (return ACME$_AUTHFAILURE). ** If the agent allows the preauthenticated mode, ** ACME$_CONTINUE should be returned, instead. */ if (wqe_p->acmewqe$l_flags.acmewqeflg$v_preauthenticated) return ACME$_AUTHFAILURE; mywqe_context = (MYWQE_CTX *)*wqe_context_p; /* ** If this ACME agent is not designated, ** skip the rest (return ACME$_CONTINUE). */ if (mywqe_context->designation_status != ACME_EXAMPLE_DOI_DESIGNATED) { return ACME$_CONTINUE; } /* ** First Time in this function ** This function will be re-entered if password is not provided in ** the initial item list. So it is necessary to determine whether ** it's the first time or second time. */ if(!mywqe_context->second_co_password_1) { /* ** If password1 is not in the WQE, check to see if input with ** noecho dialogue is possible, if it is, queue a request ** to have the user input the password unechoed. */ if (!mywqe_context->Password) { /* ** If either input or noecho prompting can't be done, ** return INSFDIALSUPPORT. ** Otherwise, prompt for password1. */ if ( (!wqe_p->acmewqe$l_dialogue_flags. acmedlogflg$v_input) /* if not input */ || (!wqe_p->acmewqe$l_dialogue_flags. acmedlogflg$v_noecho) /* not noecho */ ) { return ACME$_INSFDIALSUPPORT; } /* ** Dialogue is possible. Load and queue the request. */ Descriptor.dsc$w_length = sizeof(PasswordPrompt); Descriptor.dsc$a_pointer = (char*)&PasswordPrompt; /* ** Queue dialogue to be sent to the client */ status = kcb_vector_p->acmekcv$cb_queue_dialogue( wqe_p, ACMEDLOGFLG$M_INPUT | ACMEDLOGFLG$M_NOECHO, ACME$_PASSWORD_1, ACME$K_MAXCHAR_PRINCIPAL_NAME, &Descriptor, 0); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_queue_dialogue() failed"); return ACME$_FAILURE; } mywqe_context->second_co_password_1 = 1; return ACME$_PERFORMDIALOGUE; } /* ** If Password is already provided, ** return ACME$_CONTINUE. */ else { return ACME$_CONTINUE; } } /* ** Second time in this function (re-entered) */ else { if (item_list_p != NULL) { /* ** Check if item code ACME$_PASSWORD_1 is ** in the item list */ status = FindItemCode ( mywqe_context, item_list_p, ACME$_PASSWORD_1); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "The ItemCode was not found"); return ACME$_FAILURE; } } else { SendLog (kcb_vector_p, wqe_p, "item_list_p was empty"); return ACME$_FAILURE; } if (mywqe_context->Password == NULL) { SendLog (kcb_vector_p, wqe_p, "Principal was not found in the item lists"); return ACME$_FAILURE; } /* ** Load principal name & length into Descriptor */ Descriptor.dsc$w_length = mywqe_context->PasswordLength; Descriptor.dsc$a_pointer = mywqe_context->Password; /* ** Set the password in WQE */ status = kcb_vector_p->acmekcv$cb_set_wqe_parameter( wqe_p, ACMEWQE$K_PASSWORD_1, &Descriptor); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_parameter() failed"); return ACME$_FAILURE; } /* ** Set the WQE phase done bit and return. */ status = kcb_vector_p->acmekcv$cb_set_wqe_flag( wqe_p, ACMEWQEFLG$K_PHASE_DONE); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_flag() failed"); return ACME$_FAILURE; } } return ACME$_CONTINUE; } /* << 11 >> ** ANCILLARY_MECH_2 phase processing ** ** acme$co_ancillary_mech_2 kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_ancillary_mech_2 ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_ancillary_mech_2"); return ACME$_CONTINUE; } /* << 12 >> ** PASSWORD_2 phase processing ** ** acme$co_password_2 kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_password_2 ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_password_2"); return ACME$_CONTINUE; } /* << 13 >> ** ANCILLARY_MECH_3 phase processing ** ** acme$co_ancillary_mech_3 kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_ancillary_mech_3 ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_ancillary_mech_3"); return ACME$_CONTINUE; } /* << 14 >> ** AUTHENTICATE phase processing ** ** acme$co_authenticate kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_authenticate ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { int status; ILE3 *pItem = NULL; MYACME_CTX *myacme_context; MYWQE_CTX *mywqe_context; _DECLARE_PHASE_EVENT ("acme$co_authenticate"); /* ** If this ACME agent is not participating in this request, ** (another agent is targeted or designated in the $co_initialize) ** return ACME$_CONTINUE. */ if (*wqe_context_p == 0) { return ACME$_CONTINUE; } mywqe_context = (MYWQE_CTX *)*wqe_context_p; /* ** If this ACME agent is not designated, ** skip the rest (return ACME$_CONTINUE). */ if (mywqe_context->designation_status != ACME_EXAMPLE_DOI_DESIGNATED) { return ACME$_CONTINUE; } /* ** Also check the acmewqeflg$v_preauthenticated flag. ** If the flag has been set, skip the rest (return ACME$_AUTHFAILURE). ** If the agent allows the preauthenticated mode, ** ACME$_CONTINUE should be returned, instead. */ if (wqe_p->acmewqe$l_flags.acmewqeflg$v_preauthenticated) return ACME$_AUTHFAILURE; /* ** Get MYACME_CTX ** (optional-- example to use acme_context) */ if (*acme_context_p != 0) { myacme_context = (MYACME_CTX *)*acme_context_p; } /*###################################################################### ** ** Implement the authentication policy here ** ** As an very simple example, ** the authentication policy below is to check the first character ** of the password. ** If the password starts with 'a', the request is authenticated. ** Otherwise, authentication fails. ** **###################################################################### */ /* ** Check if password is provided. */ if (mywqe_context->Password == NULL) return ACME$_FAILURE; if (*mywqe_context->Password == 'a') /* authenticated */ { SendLog (kcb_vector_p, wqe_p, "Authentication succeeded"); /* Optional-- example to use acme_context */ myacme_context->auth_success_counter++; return ACME$_CONTINUE; } else { SendLog (kcb_vector_p, wqe_p, "Authentication failed"); /* Optional-- example to use acme_context */ myacme_context->auth_failure_counter++; return ACME$_AUTHFAILURE; } } /* << 15 >> ** MESSAGES phase processing ** ** acme$co_messages kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_messages ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_messages"); return ACME$_CONTINUE; } /* << 16 >> ** AUTHORIZE phase processing ** ** acme$co_authorize kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_authorize ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_authorize"); return ACME$_CONTINUE; } /* << 17 >> ** NOTICES phase processing ** ** acme$co_notices kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_notices ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_notices"); return ACME$_CONTINUE; } /* << 18 >> ** LOGON_INFORMATION phase processing ** ** acme$co_logon_information kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_logon_information ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { int status; struct dsc$descriptor_s Descriptor = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ MYWQE_CTX *mywqe_context; _DECLARE_PHASE_EVENT ("acme$co_logon_information"); /* ** If wqe_context is 0 (zero), this ACME agent is not participating ** in this request, ** (another agent is targeted or designated in the $co_initialize phase) ** return ACME$_CONTINUE. */ if (*wqe_context_p == 0) return ACME$_CONTINUE; mywqe_context = (MYWQE_CTX *)*wqe_context_p; /* ** If this ACME agent is not designated, ** skip the rest (return ACME$_CONTINUE). */ if (mywqe_context->designation_status != ACME_EXAMPLE_DOI_DESIGNATED) { return ACME$_CONTINUE; } /* ** First Time in this function */ if (!mywqe_context->second_co_logon_information) { /* ** If output dialogue is possible, print out the logon message */ if (wqe_p->acmewqe$l_flags.acmewqeflg$v_dialogue_possible) { Descriptor.dsc$w_length = sizeof(LogonMessage); Descriptor.dsc$a_pointer = (char*)&LogonMessage; /* ** Issue the callback to queue the dialogue request */ status = kcb_vector_p->acmekcv$cb_queue_dialogue ( wqe_p, 0, 0, ACMEMC$K_LOGON_NOTICES, &Descriptor, 0); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_queue_dialogue() failed"); return ACME$_FAILURE; } mywqe_context->second_co_logon_information = 1; return ACME$_PERFORMDIALOGUE; } else return ACME$_CONTINUE; } /* ** Second time in this function (re-entered) */ else { return ACME$_CONTINUE; } } /* << 19 >> ** NEW_PASSWORD_1 phase processing ** ** acme$co_new_password_1 kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_new_password_1 ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { int status; ILE3 *pItem = NULL; struct dsc$descriptor_s Descriptor = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ struct dsc$descriptor_s Descriptor1 = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ struct dsc$descriptor_s Descriptor2 = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ MYWQE_CTX *mywqe_context; _DECLARE_PHASE_EVENT ("acme$co_new_password_1"); /* ** If this agent is not participating in this request ** (another agent is targeted or designated in the $co_initialize) ** or ** If this callout phase has been completed by another agent */ if ((*wqe_context_p == 0) || (wqe_p->acmewqe$l_flags.acmewqeflg$v_phase_done) ) { return ACME$_CONTINUE; } /* ** Also check the acmewqeflg$v_skip_new_password flag. ** If the flag has been set, ** skip the rest (return ACME$_CONTINUE). */ if (wqe_p->acmewqe$l_flags.acmewqeflg$v_skip_new_password) return ACME$_CONTINUE; mywqe_context = (MYWQE_CTX *)*wqe_context_p; /* ** If this ACME agent is not designated, ** skip the rest (return ACME$_CONTINUE). */ if (mywqe_context->designation_status != ACME_EXAMPLE_DOI_DESIGNATED) { return ACME$_CONTINUE; } /* ** If the request in the AUTHENTICATE_PRINCIPAL mode and ** the PasswordExpired flag is not set, ** it is not necessary to prompt for the new password. */ if (((wqe_p->acmewqe$l_function.acmefc$l_fcode_struct & ACMEFC$M_FUNCTION) == ACME$_FC_AUTHENTICATE_PRINCIPAL ) && (mywqe_context->PasswordExpired == 0) ) return ACME$_CONTINUE; /* ** First Time in this function ** This function will be re-entered if password is not provided in ** the initial item list. So it is necessary to determine whether ** it's the first time or second time. */ if(!mywqe_context->second_co_new_password_1) { /* ** If password1 is not in the WQE, check to see if input with ** noecho dialogue is possible, if it is, queue a request ** to have the user input the password unechoed. */ if (!mywqe_context->NewPassword) { /* ** If either input or noecho prompting can't be done, ** return INSFDIALSUPPORT. ** Otherwise, prompt for password1. */ if ( (!wqe_p->acmewqe$l_dialogue_flags. acmedlogflg$v_input) /* if not input */ || (!wqe_p->acmewqe$l_dialogue_flags. acmedlogflg$v_noecho) /* not noecho */ ) { return ACME$_INSFDIALSUPPORT; } /* ** Dialogue is possible. Load and queue the request. */ Descriptor1.dsc$w_length = sizeof(NewPasswordPrompt); Descriptor1.dsc$a_pointer = (char*)&NewPasswordPrompt; Descriptor2.dsc$w_length = sizeof(NewPasswordPromptV); Descriptor2.dsc$a_pointer = (char*)&NewPasswordPromptV; /* ** Queue dialogue to be sent to the client */ status = kcb_vector_p->acmekcv$cb_queue_dialogue( wqe_p, ACMEDLOGFLG$M_INPUT | ACMEDLOGFLG$M_NOECHO, ACME$_NEW_PASSWORD_1, ACME$K_MAXCHAR_PRINCIPAL_NAME, &Descriptor1, &Descriptor2); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_queue_dialogue() failed"); return ACME$_FAILURE; } mywqe_context->second_co_new_password_1 = 1; return ACME$_PERFORMDIALOGUE; } } /* ** Second time in this function (re-entered) */ else { if (item_list_p != NULL) { /* ** Check if item code ACME$_PASSWORD_1 is ** in the item list */ status = FindItemCode ( mywqe_context, item_list_p, ACME$_NEW_PASSWORD_1); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "The ItemCode was not found"); return ACME$_FAILURE; } } else { SendLog (kcb_vector_p, wqe_p, "item_list_p was empty"); return ACME$_FAILURE; } if (mywqe_context->NewPassword == NULL) { SendLog (kcb_vector_p, wqe_p, "Principal was not found in the item lists"); return ACME$_FAILURE; } /* ** Load new password & length into Descriptor */ Descriptor.dsc$w_length = mywqe_context->NewPasswordLength; Descriptor.dsc$a_pointer = mywqe_context->NewPassword; /* ** Set the password in WQE */ status = kcb_vector_p->acmekcv$cb_set_wqe_parameter( wqe_p, ACMEWQE$K_NEW_PASSWORD_1, &Descriptor); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_parameter() failed"); return ACME$_FAILURE; } /* ** Set the WQE phase done bit and return. */ status = kcb_vector_p->acmekcv$cb_set_wqe_flag( wqe_p, ACMEWQEFLG$K_PHASE_DONE); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_flag() failed"); return ACME$_FAILURE; } } return ACME$_CONTINUE; } /* << 20 >> ** QUALIFY_PASSWORD_1 phase processing ** ** acme$co_qualify_password_1 kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_qualify_password_1 ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { int status; MYWQE_CTX *mywqe_context; struct dsc$descriptor_s Descriptor = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ _DECLARE_PHASE_EVENT ("acme$co_qualify_password_1"); /* ** If this agent is not participating in this request ** (another agent is targeted or designated in the $co_initialize) ** or ** If this callout phase has been completed by another agent */ if ((*wqe_context_p == 0) || (wqe_p->acmewqe$l_flags.acmewqeflg$v_phase_done) ) { return ACME$_CONTINUE; } /* ** Also check the acmewqeflg$v_skip_new_password flag. ** If the flag has been set, ** skip the rest (return ACME$_CONTINUE). */ if (wqe_p->acmewqe$l_flags.acmewqeflg$v_skip_new_password) return ACME$_CONTINUE; mywqe_context = (MYWQE_CTX *)*wqe_context_p; /* ** First Time in this function ** This function will be re-entered if password is not provided in ** the initial item list. So it is necessary to determine whether ** it's the first time or second time. */ if(!mywqe_context->second_co_qualify_password_1) { /* ** If this ACME agent is not designated, ** skip the rest (return ACME$_CONTINUE). */ if (mywqe_context->designation_status != ACME_EXAMPLE_DOI_DESIGNATED) { return ACME$_CONTINUE; } /* ** If the request in the AUTHENTICATE_PRINCIPAL mode and ** the PasswordExpired flag is not set, ** it is not necessary to prompt for the new password. */ if (((wqe_p->acmewqe$l_function.acmefc$l_fcode_struct & ACMEFC$M_FUNCTION) == ACME$_FC_AUTHENTICATE_PRINCIPAL ) && (mywqe_context->PasswordExpired == 0) ) return ACME$_CONTINUE; /* ** If the new password is in the WQE context structure, ** As this is a DOI agent, mywqe_context->NewPassword ** should be the same as ACMEWQEAX$R_NEW_PASSWORD_1 ** in the WQE data structure. */ if (mywqe_context->NewPassword != NULL) { /*##################################################### ** ** Implement the new password policy here ** ** As a very simple example, ** the policy below is to check the first character ** of the new password. ** ** If the first character is 'a', the new password is ** accepted. ** **##################################################### */ /* password accepted */ if (*mywqe_context->NewPassword == 'a') { SendLog (kcb_vector_p, wqe_p, "Password accepted"); /* ** Save the new password ** (Not implemented now) */ return ACME$_CONTINUE; } else { SendLog (kcb_vector_p, wqe_p, "Password NOT accepted"); /* ** If output dialogue is possible, ** print out the logon message */ if (wqe_p->acmewqe$l_flags. acmewqeflg$v_dialogue_possible) { Descriptor.dsc$w_length = sizeof(QualifyPasswordFailure); Descriptor.dsc$a_pointer = (char*)&QualifyPasswordFailure; /* ** Issue the callback to queue the dialogue ** request */ status = kcb_vector_p-> acmekcv$cb_queue_dialogue ( wqe_p, 0, 0, ACMEMC$K_PASSWORD_NOTICES, &Descriptor, 0); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_queue_dialogue() failed"); return ACME$_FAILURE; } mywqe_context->second_co_qualify_password_1 = 1; return ACME$_PERFORMDIALOGUE; } } } else { SendLog (kcb_vector_p, wqe_p, "New Password was not found in mywqe_context"); return ACME$_FAILURE; } } /* ** Second time in this function (re-entered) ** [Only when the new password was not accepted] */ else { /* ** Set the WQE phase done bit and return. */ status = kcb_vector_p->acmekcv$cb_set_wqe_flag( wqe_p, ACMEWQEFLG$K_PHASE_DONE); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_set_wqe_flag() failed"); return ACME$_FAILURE; } /* ** Reset the flag used in ACME$CO_NEW_PASSWORD_1() */ mywqe_context->second_co_new_password_1 = 0; /* ** Go back to ACME$CO_NEW_PASSWORD_1() */ /* return ACME$_RETRYPWD; */ return ACME$_FAILURE; } } /* << 21 >> ** NEW_PASSWORD_2 phase processing ** ** acme$co_new_password_2 kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_new_password_2 ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_new_password_2"); return ACME$_CONTINUE; } /* << 22 >> ** QUALIFY_PASSWORD_2 phase processing ** ** acme$co_qualify_password_2 kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_qualify_password_2 ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_qualify_password_2"); return ACME$_CONTINUE; } /* << 23 >> ** ACCEPT_PASSWORD phase processing ** ** acme$co_accept_password kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_accept_password ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_accept_password"); return ACME$_CONTINUE; } /* << 24 >> ** SET_PASSWORD phase processing ** ** acme$co_set_password kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_set_password ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_set_password"); return ACME$_CONTINUE; } /* << 25 >> ** CREDENTIALS phase processing ** ** acme$co_credentials kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_credentials ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { int status; MYWQE_CTX *mywqe_context; struct dsc$descriptor_s Descriptor = { 0, /* length */ DSC$K_DTYPE_T, /* type */ DSC$K_CLASS_S, /* class */ 0}; /* buf address */ P1_CREDENT *p1_credential; const char common_username[] = "ACME_EXAMPLE USERNAME"; const int common_username_len = sizeof(common_username); const char domain[] = "ACME_EXAMPLE DOMAIN"; const int domain_len = sizeof(domain); const char common_principal[] = "SAMPLE_USER"; const int common_principal_len = sizeof(common_principal); const char common_account[] = "ACME_EXAMPLE ACCOUNT"; const int common_account_len = sizeof(common_account); const char p1_extension[] = "P1"; const int p1_extension_len = sizeof(p1_extension); _DECLARE_PHASE_EVENT ("acme$co_credentials"); /* ** If WQE_CTX is 0, this ACME Agent is not participating in ** this request (another agent is targeted or designated in ** the $co_initialize phase), ** return ACME$_CONTINUE */ if (*wqe_context_p == 0) return ACME$_NORMAL; mywqe_context = (MYWQE_CTX *)*wqe_context_p; /* ** If this ACME agent is not designated, ** skip the rest (return ACME$_CONTINUE). */ if (mywqe_context->designation_status != ACME_EXAMPLE_DOI_DESIGNATED) { return ACME$_CONTINUE; } /* ** Continue only when the credential is requested */ if (wqe_p->acmewqe$l_function.acmefc$l_fcode_struct & ACME$M_ACQUIRE_CREDENTIALS) { p1_credential = malloc(P1_CREDENT_SIZE); memset(p1_credential, 0, P1_CREDENT_SIZE); /* USERNAME */ strncpy (p1_credential->pxb_p1$username, common_username, common_username_len); p1_credential->pxb_p1$username_length = common_username_len; /* ACCOUNT */ strncpy (p1_credential->pxb_p1$account, common_account, common_account_len); p1_credential->pxb_p1$account_length = common_account_len; /* DOMAIN */ strncpy (p1_credential->pxb_p1$domain, domain, domain_len); p1_credential->pxb_p1$domain_length = domain_len; /* DOI */ memset (p1_credential->pxb_p1$doi, 0, 8); memcpy (p1_credential->pxb_p1$doi, &wqe_p->acmewqe$l_current_acme_id, 4); p1_credential->pxb_p1$doi_length = 4; /* PRINCIPAL */ p1_credential->pxb_p1$principal_length = convertUincodeToAscii (mywqe_context->Principal, mywqe_context->PrincipalLength, p1_credential->pxb_p1$principal, P1_PRINCIPAL_NAME_SIZE); /* EXTENSION */ strncpy (p1_credential->pxb_p1$extension, p1_extension, p1_extension_len); p1_credential->pxb_p1$extension_length = p1_extension_len; /* ** Use a static string for a credential (just example) ** Actual ACME agent should create credentials unique to ** principals */ Descriptor.dsc$w_length = P1_CREDENT_SIZE; Descriptor.dsc$a_pointer = p1_credential; /* ** Send the credential to the ACM client process */ status = kcb_vector_p->acmekcv$cb_issue_credentials ( wqe_p, 0, &Descriptor); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_issue_credentials() failed"); return status; } } return ACME$_CONTINUE; } /* << 26 >> ** FINISH phase processing ** ** acme$co_finish kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_finish ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list ) { int status; _DECLARE_PHASE_EVENT ("acme$co_finish"); /* ** If WQE_CTX is 0, this ACME Agent is not participating in ** this request (another agent is targeted or designated in ** the $co_initialize phase), ** return ACME$_CONTINUE */ if (*wqe_context_p == 0) return ACME$_NORMAL; /* ** Deallocate WQE context */ status = kcb_vector_p->acmekcv$cb_deallocate_wqe_vm ( wqe_p, &MYWQE_CTX_SIZE, wqe_context_p); if (FAILURE (status)) { SendLog (kcb_vector_p, wqe_p, "acmekcv$cb_deallocate_wqe_vm() failed"); return ACME$_FAILURE; } return ACME$_CONTINUE; } /*############################################################################# ** ** ACME Event & Query Callout Routines ** #############################################################################*/ /* ** QUERY function ** ** acme$co_query kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_query ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_query"); return ACME$_CONTINUE; } /* ** EVENT function ** ** acme$co_event kcb_vector, acme_context, wqe, wqe_context, ** item_list, acme_item_list ** ** kcb_vector = ACM Kernel Callback Vector ** (read only, passed by reference) ** acme_context = Agent specific context ** (modify, passed by reference) ** wqe = ACM Work Queue Entry ** (read only, passed by reference) ** wqe_context = Agent specific request context ** (modify, passed by reference) ** item_list = Agent independent item list ** (read only, passed by reference) ** acme_item_list = Agent specific item list ** (read only, passed by reference) */ extern int acme$co_event ( ACMEKCV *kcb_vector_p, unsigned __int64 *acme_context_p, ACMEWQE *wqe_p, unsigned __int64 *wqe_context_p, ILE3 *item_list_p, ILE3 *acme_item_list_p ) { _DECLARE_PHASE_EVENT ("acme$co_event"); return ACME$_CONTINUE; } /*############################################################################# ** ** User-defined functions used in ** the ACME Authentication & Password Callout Routines ** #############################################################################*/ /* ** Declare a Phase Notification Event ** ** DeclarePhaseNotificationEvent name ** ** name = Null terminated callout routine name string ** (read only, passed by reference) ** */ void DeclarePhaseNotificationEvent ( ACMEKCV *kcb_vector_p, ACMEWQE *wqe_p, char *name ) { wchar_t EventDataUCS[80]; dsc_s_t EventDataUCS_Dsc; int status; swprintf (&EventDataUCS[0], sizeof(EventDataUCS) / sizeof(wchar_t), L"\n (ACME_EXAMPLE_DOI) Phase transistion event - %s", name); EventDataUCS_Dsc.dsc$w_length = wcslen(EventDataUCS) * sizeof(wchar_t); EventDataUCS_Dsc.dsc$b_dtype = DSC$K_DTYPE_T; EventDataUCS_Dsc.dsc$b_class = DSC$K_CLASS_S; EventDataUCS_Dsc.dsc$a_pointer = &EventDataUCS[0]; status = kcb_vector_p->acmekcv$cb_set_phase_event( wqe_p, &EventDataUCS_Dsc); return; } /* ** SendLog ** Functional Description: Print logs in the log file ** ** */ void SendLog ( ACMEKCV *kcb_vector_p, ACMEWQE *wqe_p, void *msg ) { const int msg_vec_size = 80; unsigned int msg_vec[msg_vec_size]; int status; struct dsc$descriptor_s msg_desc; extern ACME_TRACE; msg_desc.dsc$b_class = DSC$K_CLASS_S; /* string descriptor class */ msg_desc.dsc$b_dtype = DSC$K_DTYPE_T; /* data type : ASCII string */ msg_desc.dsc$w_length = strlen(msg); msg_desc.dsc$a_pointer = msg; /* ** == Set values in the message vector == */ /* ** 2 longwords following, new message option bits set in ** the upper word */ msg_vec[0] = (15<<16) | 3; /* ** address of message value: ACME_TRACE defined in ** ACME_EXAMPLE_DOI_MSG.MSG */ msg_vec[1] = &ACME_TRACE; /* ** NO FAO parameter, new message option bits set in the upper word */ msg_vec[2] = (15<<16) | 1; msg_vec[3] = &msg_desc; /* ** Write message into a log file */ status = kcb_vector_p->acmekcv$cb_send_logfile ( wqe_p, msg_vec, 0, 0); } /* ** SendOperator ** Functional Description: Send message to Security Operator ** ** */ void SendOperator ( ACMEKCV *kcb_vector_p, ACMEWQE *wqe_p, char *msg ) { int status; struct dsc$descriptor_s msg_desc; msg_desc.dsc$w_length = strlen(msg); msg_desc.dsc$a_pointer = msg; msg_desc.dsc$b_class = DSC$K_CLASS_S; /* string descriptor class */ msg_desc.dsc$b_dtype = DSC$K_DTYPE_T; /* data type : ASCII string */ /* send message into a log file */ status = kcb_vector_p->acmekcv$cb_send_operator ( wqe_p, &msg_desc); } /* ** FindItemCode ** Functional Description: This internal routine finds an itemcode ** in the item list. If more than one copy of the itemcode is present, ** the information for the last itemcode found is returned. ** ** Inputs: ** MYWQE_CTX - Address of the MYWQE_CTX ** ItemList - Address of item list ** ItemCode - Item Code value to look for ** ** Outputs: ** 1 for Success ** -1 for Failure ** ** Side Effects: ** None ** ** Possible Return Status: ** ACME$_NORMAL - Normal, done processing ** SS$_ITEMNOTFOUND */ int FindItemCode ( MYWQE_CTX *mywqe_ctx, ILE3 *pItemList, unsigned short int ItemCode) { while(1) { switch (ItemCode) { case ACME$_PRINCIPAL_NAME_IN: mywqe_ctx->Principal = pItemList->ile3$ps_bufaddr; mywqe_ctx->PrincipalLength = (int)pItemList->ile3$w_length; return 1; case ACME$_PASSWORD_1: mywqe_ctx->Password = pItemList->ile3$ps_bufaddr; mywqe_ctx->PasswordLength = (int)pItemList->ile3$w_length; return 1; case ACME$_NEW_PASSWORD_1: mywqe_ctx->NewPassword = pItemList->ile3$ps_bufaddr; mywqe_ctx->NewPasswordLength = (int)pItemList->ile3$w_length; return 1; case ACME$_CHAIN: pItemList = pItemList->ile3$ps_bufaddr; return 1; default: /* ** the ItemCode was not found-- ** reached the end of the item list */ if ((pItemList->ile3$w_code == 0) && (pItemList->ile3$w_length == 0)) return -1; else pItemList++; } } } /* ** Process_Common_Items ** Functional Description: This internal routine processes all of ** the items that are on the "Common" item list that this ACME will ** need for authentication and password changes. ** ** Inputs: ** MYWQE_CTX - Address of the MYWQE_CTX ** ItemList - Address of the item list to process ** ** Implicit Inputs: ** all items on the item list ** ** Outputs: ** MYWQE_CTX - Updated with data from item list ** ** Side Effects: ** None ** ** Possible Return Status: ** ACME$_NORMAL - Normal, done processing ** ACME$_BUFFEROVF - Itemlist buffer is incorrect size */ int Process_Common_Items( MYWQE_CTX *mywqe_ctx, ILE3 *pItemList) { while (1) { switch (pItemList->ile3$w_code) { case ACME$_PRINCIPAL_NAME_IN: mywqe_ctx->Principal = pItemList->ile3$ps_bufaddr; mywqe_ctx->PrincipalLength = (int)pItemList->ile3$w_length; pItemList++; break; case ACME$_PASSWORD_1: mywqe_ctx->Password = pItemList->ile3$ps_bufaddr; mywqe_ctx->PasswordLength = (int)pItemList->ile3$w_length; pItemList++; break; case ACME$_NEW_PASSWORD_1: mywqe_ctx->NewPassword = pItemList->ile3$ps_bufaddr; mywqe_ctx->NewPasswordLength = (int)pItemList->ile3$w_length; pItemList++; break; case ACME$_CHAIN: pItemList = pItemList->ile3$ps_bufaddr; break; default: /* Return 1 (success), if it's the end of the item list */ if ((pItemList->ile3$w_code == 0) && (pItemList->ile3$w_length == 0) ) return ACME$_NORMAL; else { pItemList++; break; } } } } /* ** Process_Specific_Items ** Functional Description: This internal routine processes ** the items that are on the "ACME Specific" item list that this ACME will ** need for authentication and password changes. ** ** Inputs: ** MYWQE_CTX - Address of the MYWQE_CTX ** ItemList - Address of the item list to process ** ** Implicit Inputs: ** all items on the item list ** ** Outputs: ** MYWQE_CTX - Updated with data from item list ** ** Side Effects: ** None ** ** Possible Return Status: ** ACME$_NORMAL - Normal, done processing ** ACME$_BUFFEROVF - Itemlist buffer is incorrect size */ int Process_Specific_Items( MYWQE_CTX *mywqe_ctx, ILE3 *pItemList) { while (1) { switch (pItemList->ile3$w_code) { /* ** No item code specific to this ACME is supported right now, ** but list item codes when defining/supporting them. */ default: /* Return 1 (success), if it's the end of the item list */ if ((pItemList->ile3$w_code == 0) && (pItemList->ile3$w_length == 0) ) return ACME$_NORMAL; else { pItemList++; break; } } } } /* ** Converts a Unicode String to ASCII. ** ** Inputs: ** uniStr - The Unicode string ** uniStrLen - Length of Unicode String ** asciiStrLen - size of the asciiStr ** Output: ** asciiStr - The converted string in ASCII format. ** ** Returns: ** The length of the string copied to asciiStr */ int convertUincodeToAscii (char* uniStr, unsigned uniStrLen, char*asciiStr, unsigned asciiStrLen) { iconv_t cd; int status; int asciiLen = asciiStrLen; cd = iconv_open ("ISO8859-1", "UCS-4"); if ((iconv_t)-1 == cd) { perror("Error in iconv_open()"); return 0; } status = iconv (cd, &uniStr, &uniStrLen, &asciiStr, &asciiStrLen); if (-1 == status) { perror("Error in iconv()"); return 0; } iconv_close(cd); return asciiLen - asciiStrLen; }