There are four main aspects to the interface:
int
or gnt
files). The pathname of each module is specified in the ESF Manager's configuration; for security reasons, if it is not absolute, it is interpreted relative to the default directory, which is the "bin" (on Windows) or "lib" (on Unix) subdirectory of the product installation directory. (So, for example, an ESM Module specified as myesm
in the configuration could refer to product_dir\Base\Bin\myesm.dll
on Windows or $COBDIR/lib/myesm.cso
on Unix.) int
or gnt
code) so that it exports an initial entry point that conforms to the definition given below (see Initial Entry Point). ESF Manager will call this entry point each time it loads the ESM Module. This page also describes return codes for the various functions and what parts of the interface can be omitted from an ESM Module's implementation.
For COBOL loadable files (int
or gnt
modules), this is the beginning of the procedure division. For DLLs and CSOs, the initial entry point is set when the object is linked. If you are using the cbllink
program on Windows, the initial entry point is set with the -m
option; for the cob
command on Unix, use the -e
option. For other tools, consult your documentation.
/some/path/some_mod_t.so
, ESF will look for an entry point named some_mod_t
, and then for one named some_mod
.
copy "saf-esm.cpy" replacing ==()== by ==esm== ... procedure division returning by reference esm-proc-table *> see SafPTab
Implementing the ESM Module interface is a matter of creating the functions specified by the interface and setting the appropriate pointers to them in the procedure table.
You do not have to implement all of the functions; see Omitting Optional Procedures. Set process table entries to the null
(0) pointer value to indicate that an ESM Module does not implement the associated procedure.
New procedures may be added to the table in future releases. The procedure table includes a version number field (SafPTab::Version) which tells the ESF Manager what procedures are listed in the ESM Module's procedure table.
Init
procedure is used to initialize and configure the ESM Module. Typically a module will use this function to connect to its ESM. It's also how ESF Manager passes the module its configuration data and pointers to the functions of the ESM API, which are services ESM Modules can use for various purposes.
#include "safmgr.h" #include "saf-esm.h" mf_uns32 Init(const mf_uns32 *Index, struct cas_esm_config_internal *Config, const struct SafEsmApi *Api, void *Reserved)
copy ??? ... entry "Init" using by reference esm-index by reference esm-cfg by reference esm-api
[in] | Index | Points to an area containing the index of this ESM in the ESM list, starting from 0. |
[in] | Config | Points to a cas_esm_config_internal structure containing the module's configuration data. |
[in] | Api | Points to a SafEsmApi structure containing pointers to the ESM API service functions that the module can call. |
Reserved | Reserved for future use. |
Init
procedure should return zero for success, non-zero for error. See Return Codes for Other Procedures.static mf_uns32 Init(const mf_uns32 *Index, struct cas_esm_config_internal *Config, const struct SafEsmApi *Api, void *Reserved) { static const char *InitMsg = "OS ESM initialized" , *AllocFailMsg = "Could not allocate storage" , *LogonFailMsg = "Unrecognized logon type specified in configuration" , *ShmFailMsg = "Could not allocate shared memory"; unsigned char *SptKey = NULL; mf_uns32 Ret; size_t SptKeyLen; int SafRC; struct SafStore *CustConfig; /* Save the SAF Manager ESM Module API information */ if (! Api || Api->VerMajor != SafESM_API_VER_MAJ) return SafESMRC_PARAM; ModAPI = *Api; /* Parse custom configuration and get options */ if (ModAPI.ParseConfig && Config && Config->config && *Config->config) { SafRC = ModAPI.ParseConfig(Config->config, &CustConfig, NULL); if (! SafRC) { char *CfgVal, *End; long LongVal; int HaveSecret = 0; /* See if an alternate domain is configured */ SafRC = ModAPI.QueryConfig ( CustConfig , "Operation" , "Domain" , &CfgVal , NULL ); if (! SafRC) DftDomain = CfgVal; /* See if logon type is specified */ SafRC = ModAPI.QueryConfig ( CustConfig , "Operation" , "Type" , &CfgVal , NULL ); if (! SafRC) { if (OsSTRCMP_CI(CfgVal, ==, "network")) LogonType = LOGON32_LOGON_NETWORK; else if (OsSTRCMP_CI(CfgVal, ==, "interactive")) LogonType = LOGON32_LOGON_INTERACTIVE; else { if (ModAPI.Log) ModAPI.Log ( 1010 , 8 , LogonFailMsg , (mf_uns32)strlen(LogonFailMsg) , NULL ); return SafESMRC_EXTERNAL; }
Info
procedure is used by ESF Manager to query the ESM Module for identifying information (a string, typically containing a name and version) and the version of the ESM Module interface that it supports.
#include "saf-esm.h" mf_uns32 Info(const char **Name, mf_uns32 *IFVersion, const unsigned char **Signature, void *Reserved)
01 esm-name pointer.
01 esm-if-version pic x(4) comp-5.
78 esm-if-ver value 1.
01 esm-signature pointer.
01 esm-reserved pointer.
...
entry "Info" using by reference esm-name esm-if-version
by value esm-signature esm-reserved
[out] | Name | Module name string. Set this to the address of a null-terminated string containing any information the ESM Module would like to use for identification. |
[out] | IFVersion | Interface version. Set this to the interface version the module is compiled with (SafESM_IF_VER in C). Currently this is 1. |
Signature | Reserved for future use. | |
Reserved | Reserved for future use. |
Info
procedure should return zero for success, non-zero for error. See Return Codes for Other Procedures.static mf_uns32 Info(const char **Name, mf_uns32 *IFVersion, const unsigned char **Signature, void *Reserved) { *Name = "OS ESM version " OsVERSION_STRING; *IFVersion = SafESM_IF_VER; return 0; }
Verify
procedure is invoked to process an ESF API VERIFY (user authentication) request.The parameter to the Verify procedure is the ESF API control block. Some ESM Modules (particularly those written in COBOL) may use this parameter exclusively. Other ESM Modules (particularly those written in C or C++) may want to use the ExtractVerifyStrings service provided by ESF Manager to get C-style nul-terminated copies of the variable-length string data in the parameter block.
#include "safapi.h" #include "saf-esm.h" mf_uns32 Verify(struct safpb_parameter_block *Request, void *Reserved)
copy "safapi.cpy" replacing ==()== by ==saf== ... entry "Verify" using by reference saf-safpb-parameter-block
[in,out] | Request | The Safpb_Parameter_Block structure containing the request as passed to the ESF API. |
Reserved | Reserved for future use. |
There is also a string called "Group". This is a short (up to 8 characters) string which can optionally be included in the Verify request. With some ESMs, if a group is specified, they may grant additional permissions for the session if the Verify request succeeds and additional checks (typically, that the user is a member of the group) pass. Other ESMs ignore this information. See User Groups and the Signon Group.
This mode is also useful if there is a lower-priority ESM Module which needs to update the ACEE following successful verification.
ESM Modules can determine whether another module has already verified the user by checking whether the safpb_api_rc field still has the value saf78_SAF_RC_NOT_COMPLETE (4).
Auth
procedure is invoked to process an ESF API AUTH (resource access authorization) request.The parameter to the Auth procedure is the ESF API control block. Some ESM Modules (particularly those written in COBOL) may use this parameter exclusively. Other ESM Modules (particularly those written in C or C++) may want to use the ExtractAuthStrings service provided by ESF Manager to get C-style nul-terminated copies of the variable-length string data in the parameter block.
#include "safapi.h" #include "saf-esm.h" mf_uns32 Auth(struct safpb_parameter_block *Request, void *Reserved)
copy "safapi.cpy" replacing ==()== by ==saf== ... entry "Auth" using by reference saf-safpb-parameter-block
[in,out] | Request | The Safpb_Parameter_Block structure containing the request as passed to the ESF API. |
Reserved | Reserved for future use. |
Auth
procedure is invoked to process an ESF API XAUTH (extended resource access authorization) request. (XAUTH is similar to AUTH but uses a set of independent permissions rather than a single permission level. It is used by some non-MTO facilities, such as MFDS.)The parameter to the XAuth procedure is the ESF API control block. Some ESM Modules (particularly those written in COBOL) may use this parameter exclusively. Other ESM Modules (particularly those written in C or C++) may want to use the ExtractAuthStrings service provided by ESF Manager to get C-style nul-terminated copies of the variable-length string data in the parameter block.
#include "safapi.h" #include "saf-esm.h" mf_uns32 XAuth(struct safpb_parameter_block *Request, void *Reserved)
copy "safapi.cpy" replacing ==()== by ==saf== ... entry "XAuth" using by reference saf-safpb-parameter-block
[in,out] | Request | The Safpb_Parameter_Block structure containing the request as passed to the ESF API. |
Reserved | Reserved for future use. |
Update
procedure is invoked to process an ESF API UPDATE (administrative update notification) request. These requests tell ESF that the security definitions in an External Security Manager have been changed, and ESF should update any cached or internal data that may be affected. See External Administrative Update Notification for more information.The parameters to the Update procedure are an update-type indicator and the ESF API control block containing the request.
The update-type indicator is an integer that tells the ESM module whether this is a normal update, or if the Update callback is being invoked to tell the module that one or more updates have been handled by other processes. In the latter case, the module does not need to update any shared information (for example, data in shared memory), but does need to clear out any relevant local information. Only modules running in a multiprocess, shared-memory environment (currently, this means running under CAS) will receive update calls of this type.
The type codes are:
#include "safapi.h" #include "saf-esm.h" mf_uns32 Update(mf_s32 Type, struct safpb_parameter_block *Request, void *Reserved)
copy "safapi.cpy" replacing ==()== by ==saf== 01 saf-update-type pic x(4) comp-5. ... entry "Update" using by value saf-update-type by reference saf-safpb-parameter-block
[in] | Type | The request type; see ESF ESM Update Request Types. |
[in,out] | Request | The Safpb_Parameter_Block structure containing the request as passed to the ESF API. |
Reserved | Reserved for future use. |
Exit
procedure is invoked when the calling process is about to exit. The module can use this opportunity to perform any final cleanup, detatch from its ESM, etc.
#include "saf-esm.h" mf_uns32 Exit(const mf_uns32 *Index, void *Reserved)
entry "Exit" using by reference esm-index
[in] | Index | Points to an area containing the index of this ESM in the ESM list, starting from 0. |
Reserved | Reserved for future use. |
Exit
procedure should return zero for success, non-zero for error. See Return Codes for Other Procedures.static mf_uns32 Exit(const mf_uns32 *Index, void *Reserved) { static const char *ExitMsg = "MLDAP ESM exiting"; struct MldInstance *Instance = NULL; Log(1002, 0, ExitMsg, strlen(ExitMsg), NULL); if (Index) Instance = &MldInstance[*Index]; if (Instance && Instance->MldapHandle) { m_ldap_unbind(Instance->MldapHandle); Instance->MldapHandle = NULL; } return 0; }
Admin
procedure is invoked to process an ESF Admin request. ESF Admin is an API provided by ESF to present a consistent interface for administrative actions, such as adding users, on External Security Managers. Not all ESMs will provide a programmatic interface for administrative updates, so some ESM Modules will not be able to implement the Admin
procedure, and many modules will only support some possible ESF Admin requests. Also, it's likely that for security reasons an administrator will only grant limited permissions to an ESM Module (typically through the credentials it presents to the ESM when it connects), so even if an ESM Module implementes Admin
it may not be able to process requests successfully, based on its configuration.The parameter to the Admin procedure is the ESF API control block. The Admin request section of the control block is used for Admin requests. It contains a count of arguments and a pointer to an argument table, which is an array of struct safadmin_argtbl. Each structure has a keyword and value string pair; these name/value pairs describe the parameters for the requested action.
The specific action being requested is identified by the safpb_type field of the control block. See ESF API Admin Subcommands.
Currently, in order to get the definitions for the ESF Admin API, you must define saf78_SAFADMIN_DATA_AREAS
before including safapi.h.
Further details to be provided.
#define saf78_SAFADMIN_DATA_AREAS #include "safapi.h" #include "saf-esm.h" mf_uns32 Admin(struct safpb_parameter_block *Request, void *Reserved)
copy "safapi.cpy" replacing ==()== by ==saf== ... entry "Admin" using by reference saf-safpb-parameter-block
[in,out] | Request | The Safpb_Parameter_Block structure containing the request as passed to the ESF API. |
Reserved | Reserved for future use. |
ESM Module procedures return a 32-bit integer value which indicates success or failure, and for most functions can indicate additional information as well.
Note that this means that Verify
should return zero even if the user's credentials were incorrect, and Auth
/ XAuth
should return zero even if the requested access is denied. They indicate the success or failure of the caller's security request within the ESF API paramerer block, as described below.
Verify
, Auth
, XAuth
, and Admin
procedures can return the values described for the other ESM Module procedures; see ESM Module Procedure Return Codes.Micro Focus recommends that ESM Module authors consider codes 1-999 reserved for future use; this range will be used to define additional standard return codes.
Verify
, Auth
, XAuth
, and Admin
indicate that a request was granted, was denied, or could not be processed (and in some cases indicate additional information such as password expiration) by setting values in the ESF API parameter block.
Result codes go in three one-byte values in the RETCODES structure in the parameter block. There are three fields, labelled safpb_api_rc
, safpb_mgr_return
, and safpb_mgr_reason
. The safpb_api_rc
codes depend on the function (Verify
/ Auth
/ XAuth
) being invoked; the other two codes depend on the value of safpb_api_rc
. Various valid combinations are listed in safapi.h.
Verify
request, the most common result code triplets are listed in the table below. These will generally be suitable for most ESM Modules. For an explanation of the response classes (Allow, Deny, Fail, and Unknown), see the section ESF API Calls.
rc | return | reason | Meaning |
saf78_SAF_RC_SUCCESS (0) | saf78_RC_NORMAL (0) | saf78_RS_NORMAL (0) | Verification succeeded, no additional information (this is an Allow result) |
saf78_SAF_RC_NOT_COMPLETE (4) | saf78_RC_NO_DECISION (0) | saf78_RS_ESM_NOT_CALLED (0) | The ESM Module does not implement this procedure, or it has decided that this request does not apply to it (this is an Unknown result) |
saf78_SAF_RC_NOT_COMPLETE (4) | saf78_RC_NO_USER_PROFILE (4) | saf78_RS_NORMAL (0) | The ESM does not have a record for this user (this is an Unknown result) |
saf78_SAF_RC_FAILURE (8) | saf78_RC_NORMAL (0) | saf78_RS_NORMAL (0) | The ESM rejected this request, and does not wish to provide any additional information (note this is a Deny result, not a Fail result, despite the name of the associated constant). This code can be used if the organization's security policy requires not revealing information about why a signon request was denied. |
saf78_SAF_RC_FAILURE (8) | saf78_RC_PWRD_INVALID (8) | saf78_RS_NORMAL (0) | Verification failed because the supplied password was incorrect (this is a Deny result) |
saf78_SAF_RC_FAILURE (8) | saf78_RC_PWRD_EXPIRED (12) | saf78_RS_NORMAL (0) | Verification failed because the supplied password has expired (this is a Deny result). Some ESM Modules will accept the request if it is repeated with a new password supplied in the optional new-password field. |
saf78_SAF_RC_FAILURE (8) | saf78_RC_PWRD_CHANGE_ERR (16) | saf78_RS_NORMAL (0) | Verification failed because the supplied new password was not accepted by the ESM (this is a Deny result) |
saf78_SAF_RC_FAILURE (8) | saf78_RC_USER_REVOKED (28) | saf78_RS_NORMAL (0) | Verification failed because signon is disabled for the user's account (this is a Deny result) |
saf78_SAF_RC_FAILURE (8) | saf78_RC_DATABASE_ERROR (92) | saf78_RS_NORMAL (0) | Verification failed because the ESM Module or its associated ESM was unable to process the request (this is a Fail result) |
Auth
or XAuth
request, the most common result code triplets are listed in the table below. These will generally be suitable for most ESM Modules. For an explanation of the response classes (Allow, Deny, Fail, and Unknown), see the section ESF API Calls.
Note that there is a special type of Auth
/ XAuth
call that does not request specific access; instead, it asks the ESM to determine what access the user is permitted to the given resource. The caller uses the saf78_TYPE_ATTR_STATUS_ACC flag in the Safpb_Parameter_Block::safpb_type field to request this information. If successful, an Auth
call of this type will return the user's permission level for the object as part of the return code (see below). The XAuth
function, on the other hand, returns the information in the request-specific part of the parameter block.
rc | return | reason | Meaning |
saf78_SAF_RC_SUCCESS (0) | saf78_RC_USER_IS_AUTH (0) | saf78_RS_NORMAL (0) | Authorization is granted, no additional information (this is an Allow result) |
saf78_SAF_RC_SUCCESS (0) | saf78_RC_ACCESS_INFO (20) | saf78_RS_ACCESS_{NONE (0), READ (4), UPDATE (8), CONTROL (12), ALTER (16)} | (Auth only) The user has the specified level of access to the resource |
saf78_SAF_RC_NOT_COMPLETE (4) | saf78_RC_NO_DECISION (0) | saf78_RS_ESM_NOT_CALLED (0) | The ESM Module does not implement this procedure, or it has decided that this request does not apply to it (this is an Unknown result) |
saf78_SAF_RC_NOT_COMPLETE (4) | saf78_RC_RESOURCE_NOT_PROT (4) | saf78_RS_NO_RESOURCE_PROF (0) | The ESM does not have a record for this resource (this is an Unknown result) |
saf78_SAF_RC_FAILURE (8) | saf78_RC_USER_NOT_AUTH (8) | saf78_RS_NORMAL (0) | Authorization is denied (this is a Deny result) |
saf78_SAF_RC_FAILURE (8) | saf78_RC_DATABASE_ERROR (92) | saf78_RS_NORMAL (0) | Authorization failed because the ESM Module or its associated ESM was unable to process the request (this is a Fail result) |
Admin
request, the most common result code triplets are listed in the table below. These will generally be suitable for most ESM Modules.
An Admin
request can succeed or fail, or it can be ignored if the ESM Module does not implement the requested administration subcommand. (If the module determines that it cannot process the request because of an unsuitable or missing parameter, it can fail or ignore the request as the author feels is appropriate.) So the return codes below are classified as Success, Failure, or Ignored results.
rc | return | reason | Meaning |
saf78_SAF_RC_SUCCESS (0) | saf78_RC_NORMAL (0) | saf78_RS_NORMAL (0) | The request was processed, no additional information (this is a Success result) |
saf78_SAF_RC_NOT_COMPLETE (4) | saf78_RC_NO_DECISION (0) | saf78_RS_ESM_NOT_CALLED (0) | The ESM Module does not implement this procedure (this is an Ignored result) |
saf78_SAF_RC_NOT_COMPLETE (4) | saf78_RC_NO_DECISION (0) | saf78_RS_ESM_DECLINED (4) | The ESM Module declined to process the request (this is an Ignored result) |
saf78_SAF_RC_NOT_COMPLETE (4) | saf78_RC_KEYWORD_ERROR (4) | saf78_RS_KEYWORD_UNKNOWN (4) | The request specified a parameter keyword that the ESM Module does not recognize (this is an Ignored result) |
saf78_SAF_RC_FAILURE (8) | saf78_RC_VALUE_ERROR (4) | saf78_RS_VALUE_INVALID (4) | The request specified a parameter value that is not valid for this ESM Module or its ESM (this is a Failure result) |
saf78_SAF_RC_FAILURE (8) | saf78_RC_VALUE_ERROR (4) | saf78_RS_VALUE_LENGTH (8) | The request specified a parameter value that was too long or short for this ESM Module or its ESM (this is a Failure result) |
saf78_SAF_RC_FAILURE (8) | saf78_RC_DATABASE_ERROR (92) | saf78_RS_NORMAL (0) | The ESM Module or its associated ESM was unable to process the request (this is a Failure result) |
Init
, Info
, Update
, Status
, Control
, and Exit
), zero means normal success and any non-zero value indicates an error or some other unusual condition.For the currently-defined return codes, see ESM Module Procedure Return Codes.
The range 1000-1999 is reserved for user-defined codes.
null
to indicate that it does not support that function; the ESF Manager will only call functions that a module implements.Here are the effects of leaving each of the procedures unimplemented:
Update
procedure to tell an ESM Module that ESF has been notified of an administrative update. This usually means that an administrator has used some other tool to change the security configuration in an external security repository, so the ESM Module may need to discard cached information, reconnect to its ESM, or take some other action specific to that ESM. Many ESM Modules will not need to implement this procedure.
Status
procedure lets the ESF Manager query an ESM Module for status information, such as the state of its connection to its ESM. If a module omits this procedure, ESF Manager will simply report what it knows about the module's status (whether it is in use or not, basically).
Admin
procedure is used to make administrative requests from ES components (such as the MFDS administration user interface) to ESMs. ESM Modules may implement Admin
to integrate ESM administration with ES administration. If they omit this procedure, administrators will have to make updates to the ESM (such as adding new users) using the tools provided with the ESM.