/* Editor Settings: expandtabs and use 4 spaces for indentation
 * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
 */

/*
 * Copyright Likewise Software    2004-2008
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.  You should have received a copy of the GNU General
 * Public License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
 * TERMS AS WELL.  IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
 * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
 * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
 * GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE.  IF YOU
 * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
 * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
 * license@likewisesoftware.com
 */

/*
 * Copyright (C) Likewise Software. All rights reserved.
 *
 * Module Name:
 *
 *        lsaprovider.h
 *
 * Abstract:
 *
 *        Likewise Security and Authentication Subsystem (LSASS)
 *
 *        Authentication Provider Interface
 *
 * Authors: Krishna Ganugapati (krishnag@likewisesoftware.com)
 *          Sriram Nambakam (snambakam@likewisesoftware.com)
 */

/**
 * @file lsa/provider.h
 * @brief Server provider API
 */

#ifndef __LSAPROVIDER_H__
#define __LSAPROVIDER_H__

/**
 * @defgroup lsaprovider Server Provider interface
 * @ingroup oem
 * @brief Server provider interface
 *
 * This API defines the interface a server provider backend module must implement.
 *
 * The initial entry point is defined by #LSA_SYMBOL_NAME_INITIALIZE_PROVIDER
 * and has a prototype of #PFNINITIALIZEPROVIDER().  The corresponding
 * shutdown method is #PFNSHUTDOWNPROVIDER().  Lsass can link providers
 * statically as well as dynamically.  If you use this, you will need
 * to redefine the entry point name and add your provider to the static
 * providers table.  Search for the @a ENABLE_STATIC_PROVIDERS macro
 * for details on how and where to do this.
 *
 * Before invoking any specific method on behalf of a client, the server
 * will invoke #PFNOPENHANDLE() to create a provider context specific
 * to the client connection and it will invoke #PFNCLOSEHANDLE()
 * afterwards to destroy it.
 *
 * Most methods which return dynamically allocated results do not have
 * corresponding free methods.  Dynamically allocated results should
 * be allocated with the @a LwAllocate functions, such as
 * @a LwAllocateMemory() and @a LwAllocateString(), in the lwadvapi
 * component.
 */

/*@{*/

#include <lsa/lsa.h>
#include <lsa/lsapstore-types.h>

/**
 * @brief Shutdown provider method
 *
 * Method to shutdown the provider.
 */
typedef VOID (*PFNSHUTDOWNPROVIDER)(
    VOID
    );

/**
 * @brief Close provider connection method
 *
 * Method to close the connection to a provider.  Closes
 * a connection between a client and a provider that was
 * opened with #PFNOPENHANDLE().
 *
 * @param[in,out] hProvider   Handle to the provider context.
 */
typedef VOID  (*PFNCLOSEHANDLE)(HANDLE hProvider);

typedef DWORD (*PFNSERVICESDOMAIN)(
                        PCSTR pszDomain,
                        BOOLEAN* pbServicesDomain);

/**
 * @brief Authenticate user method (PAM semantics)
 *
 * Method to authenticate a user with PAM semantics.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] pParams         Authentication parameters.
 * @param[out] ppPamAuthInfo  Set to information about the authenticated user on success.
 * The result should be freed with #LsaFreeAuthUserPamInfo().
 *
 * @retval ERROR_SUCCESS Success.
 * @retval ERROR_LOGON_FAILURE Generic logon failure.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_USER Provider does not recognize user.
 * Other providers will be tried.
 * @retval LW_ERROR_PASSWORD_MISMATCH Incorrect password.
 * @retval ... Error.
 */
typedef DWORD (*PFNAUTHENTICATEUSERPAM)(
                        HANDLE hProvider,
                        PLSA_AUTH_USER_PAM_PARAMS pParams,
                        PLSA_AUTH_USER_PAM_INFO* ppPamAuthInfo
                        );

/**
 * @brief Authenticate user extended method
 *
 * Method to authenticate a user by various mechanisms, such as
 * plain-text password or an NTLM challenge-response pair.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] pUserParams Authentication parameters.
 * @param[out] ppUserInfo Set to information about the authenticated user on success.
 *
 * @retval ERROR_SUCCESS Success.
 * @retval ERROR_LOGON_FAILURE Generic logon failure.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_USER Provider does not recognize user.
 * Other providers will be tried.
 * @retval LW_ERROR_PASSWORD_MISMATCH Incorrect password.
 * @retval ... Error.
 */
typedef DWORD (*PFNAUTHENTICATEUSEREX)(
                        HANDLE hProvider,
                        PLSA_AUTH_USER_PARAMS pUserParams,
                        PLSA_AUTH_USER_INFO *ppUserInfo,
                        PLSA_ASYNC_CONTROL_BLOCK pAsyncBlock,
                        PLSA_STATUS_BLOCK pStatusBlock
                        );

typedef DWORD (*PFNVALIDATEUSER)(
                        HANDLE hProvider,
                        PCSTR  pszLoginId,
                        PCSTR  pszPassword
                        );

typedef DWORD (*PFNCHECKUSERINLIST)(
                        HANDLE hProvider,
                        PCSTR  pszLoginId,
                        PCSTR  pszListName);

typedef DWORD (*PFNCHANGEPASSWORD) (
                        HANDLE hProvider,
                        PCSTR  pszLoginId,
                        PCSTR  pszPassword,
                        PCSTR  pszOldPassword
                        );

typedef DWORD (*PFNSETPASSWORD) (
                        HANDLE hProvider,
                        PCSTR  pszLoginId,
                        PCSTR  pszPassword
                        );

typedef DWORD (*PFNOPENSESSION) (
                        HANDLE hProvider,
                        PCSTR  pszLoginId
                        );

typedef DWORD (*PFNCLOSESESSION) (
                        HANDLE hProvider,
                        PCSTR  pszLoginId
                        );

typedef DWORD (*PFNLOOKUP_NSS_ARTEFACT_BY_KEY)(
                        HANDLE hProvider,
                        PCSTR  pszKeyName,
                        PCSTR  pszMapName,
                        DWORD  dwInfoLevel,
                        LSA_NIS_MAP_QUERY_FLAGS dwFlags,
                        PVOID* ppNSSArtefactInfo
                        );

typedef DWORD (*PFNBEGIN_ENUM_NSS_ARTEFACTS)(
                        HANDLE  hProvider,
                        DWORD   dwInfoLevel,
                        PCSTR   pszMapName,
                        LSA_NIS_MAP_QUERY_FLAGS dwFlags,
                        PHANDLE phResume
                        );

typedef DWORD (*PFNENUMNSS_ARTEFACTS) (
                        HANDLE  hProvider,
                        HANDLE  hResume,
                        DWORD   dwMaxNumGroups,
                        PDWORD  pdwGroupsFound,
                        PVOID** pppGroupInfoList
                        );

typedef VOID (*PFNEND_ENUM_NSS_ARTEFACTS)(
                        HANDLE hProvider,
                        HANDLE hResume
                        );

/**
 * @brief Get provider status method
 *
 * Method to get the provider's status.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[out] ppAuthProviderStatus Set to information about
 * the provider's state.
 * The result should be freed with #PFNFREE_STATUS().
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFNGET_STATUS)(
                HANDLE hProvider,
                PLSA_AUTH_PROVIDER_STATUS* ppAuthProviderStatus
                );

/**
 * @brief Free provider status information method
 *
 * Method to free the provider's status information.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in,out] pAuthProviderStatus Set to information about the
 * provider's state.
 */
typedef VOID (*PFNFREE_STATUS)(
                PLSA_AUTH_PROVIDER_STATUS pAuthProviderStatus
                );

/**
 * @brief Perform provider-specific method
 *
 * Method to make a provider-specific call.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] peerUid         The client's UID.
 * @param[in] peerGid         The client's GID.
 * @param[in] dwIoControlCode The call opcode.
 * @param[in] dwInputBufferSize The size of the input buffer.
 * @param[in] pInputBuffer The call input buffer.
 * @param[out] pdwOutputBufferSize Optional, set to the size
 * of the output buffer returned from the call.
 * @param[out] ppOutputBuffer Optional, set to the output buffer
 * returned from the call.
 *
 * @return A provider-specific error code.
 */
typedef DWORD (*PFNPROVIDER_IO_CONTROL) (
                HANDLE hProvider,
                uid_t  peerUid,
                gid_t  peerGID,
                DWORD  dwIoControlCode,
                DWORD  dwInputBufferSize,
                PVOID  pInputBuffer,
                DWORD* pdwOutputBufferSize,
                PVOID* ppOutputBuffer
                );

/**
 * @brief Provider initial entry point name
 *
 * Name of the symbol that Lsass will search for in the provider
 * after dynamically loading it.  The provider must export this
 * symbol which should have a function prototype corresponding to
 * the signature of #PFNINITIALIZEPROVIDER defined above.
 */
#define LSA_SYMBOL_NAME_INITIALIZE_PROVIDER "LsaInitializeProvider"

//
// New Interfaces
//

//
// Lookup objects.
//
// Objects returned in same order as query with NULL
// entries for objects that are not found.
//
/**
 * @brief Resolve security objects method
 *
 * Method to resolve a homogeneous list of keys to a list of security
 * objects of equal length.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] FindFlags Flags that can modify query behavior.
 * @param[in] ObjectType The type of object to return.  If #LSA_OBJECT_TYPE_UNDEFINED,
 * any type of object matching the query will be returned.
 * @param[in] QueryType The type of key to query by.
 * @param[in] dwCount The number of keys to search for.
 * @param[in] QueryList A list of keys to search for.
 * @param[out] pppObjects On success, set to an array of security object pointers equal in
 * length to the query list.  Each element of the array may be NULL if the key could not be found.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFN_LSA_PROVIDER_FIND_OBJECTS)(
    IN HANDLE hProvider,
    IN LSA_FIND_FLAGS FindFlags,
    IN OPTIONAL LSA_OBJECT_TYPE ObjectType,
    IN LSA_QUERY_TYPE QueryType,
    IN DWORD dwCount,
    IN LSA_QUERY_LIST QueryList,
    OUT PLSA_SECURITY_OBJECT** pppObjects
    );

//
// Enumerate Users/Groups
//
/**
 * @brief Begin object enumeration method
 *
 * Method to return a handle that can be used to enumerate all
 * security objects
 * matching the query criteria.  The handle should be freed with
 * #PFN_LSA_PROVIDER_CLOSE_ENUM().
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[out] phEnum Set to a handle which can be subsequently used with #PFN_LSA_PROVIDER_ENUM_OBJECTS()
 * to retrieve results.
 * @param[in] FindFlags Flags that can modify query behavior.
 * @param[in] ObjectType The type of object to enumerate.  If #LSA_OBJECT_TYPE_UNDEFINED,
 * all enumerable objects will be returned.
 * @param[in] pszDomainName An optional domain name to further filter results.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFN_LSA_PROVIDER_OPEN_ENUM_OBJECTS)(
    IN HANDLE hProvider,
    OUT PHANDLE phEnum,
    IN LSA_FIND_FLAGS FindFlags,
    IN LSA_OBJECT_TYPE ObjectType,
    IN OPTIONAL PCSTR pszDomainName
    );

/**
 * @brief Begin object enumeration with filter method
 *
 * Method to return a handle that can be used to enumerate all
 * security objects
 * matching the query criteria.  The handle should be freed with
 * #PFN_LSA_PROVIDER_CLOSE_ENUM().
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[out] phEnum Set to a handle which can be subsequently used with #PFN_LSA_PROVIDER_ENUM_OBJECTS()
 * to retrieve results.
 * @param[in] FindFlags Flags that can modify query behavior.
 * @param[in] ObjectType The type of object to enumerate.  If #LSA_OBJECT_TYPE_UNDEFINED,
 * all enumerable objects will be returned.
 * @param[in] pszDomainName An optional domain name to further filter results.
 * @param[in] FilterType The type of filter to use.
 * @param[in] pFilter The filter string (may be omitted if FilterType is #LSA_FILTER_TYPE_NONE).
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD(*PFN_LSA_PROVIDER_OPEN_ENUM_OBJECTS_FILTER)(
    IN HANDLE hProvider,
    OUT PHANDLE phEnum,
    IN LSA_FIND_FLAGS FindFlags,
    IN LSA_OBJECT_TYPE ObjectType,
    IN OPTIONAL PCSTR pszDomainName,
    IN LSA_FILTER_TYPE FilterType,
    IN OPTIONAL PCSTR pszFilter
    );

/**
 * @brief Enumerate objects method
 *
 * Method to return objects from an in-progress enumeration.
 *
 * So long as there are no errors the provider should return either
 * @a LW_ERROR_SUCCESS if there are objects to return or
 * @a ERROR_NO_ITEMS if there are no more objects to return.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] hEnum An enumeration handle from #PFN_LSA_PROVIDER_OPEN_ENUM_OBJECTS().
 * @param[in] dwMaxObjectsCount The maximum number of objects to return.
 * @param[out] pdwObjectsCount Set to the length of the returned list.
 * @param[out] pppObjects Set to a list of returned security objects.
 * Unlike #PFN_LSA_PROVIDER_FIND_OBJECTS(), entries will not be NULL.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval ERROR_NO_MORE_ITEMS There are no more objects to enumerate.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFN_LSA_PROVIDER_ENUM_OBJECTS)(
    IN HANDLE hEnum,
    IN DWORD dwMaxObjectsCount,
    OUT PDWORD pdwObjectsCount,
    OUT PLSA_SECURITY_OBJECT** pppObjects
    );

//
// Enumerate members of a group.
//
//
/**
 * @brief Begin member enumeration method
 *
 * Method to return a handle that can be used to enumerate all
 * direct members of a group.
 * The returned SIDs may represent users or other groups.
 * The handle should be freed with #PFN_LSA_PROVIDER_CLOSE_ENUM().
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[out] phEnum Set to a handle which can be subsequently used with #LsaEnumMembers()
 * to retrieve results.
 * @param[in] FindFlags Flags that can modify query behavior.
 * @param[in] pszSid The SID of the group to enumerate as a printed string.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_GROUP A group with the specified SID did not exist.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_OBJECT An object with the specified SID did not exist.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFN_LSA_PROVIDER_OPEN_ENUM_MEMBERS)(
    IN HANDLE hProvider,
    OUT PHANDLE phEnum,
    IN LSA_FIND_FLAGS FindFlags,
    IN PCSTR pszSid
    );

/**
 * @brief Enumerate members method
 *
 * Method to return member SIDs from an in-progress member enumeration.
 * The returned list should be freed with #LsaFreeSidList().
 *
 * So long as there are no errors the provider should return either
 * @a LW_ERROR_SUCCESS if there are objects to return or
 * @a ERROR_NO_ITEMS if there are no more objects to return.
 *
 * @param[in] hEnum An enumeration handle from
 * #PFN_LSA_PROVIDER_OPEN_ENUM_MEMBERS().
 * @param[in] dwMaxMemberSidCount The maximum number of SIDs to return.
 * @param[out] pdwMemberSidCount Set to the length of the returned list.
 * @param[out] pppszMemberSids Set to a list of returned member SIDs in
 * printed form.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval ERROR_NO_MORE_ITEMS There are no more objects to enumerate.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFN_LSA_PROVIDER_ENUM_MEMBERS)(
    IN HANDLE hEnum,
    IN DWORD dwMaxMemberSidCount,
    OUT PDWORD pdwMemberSidCount,
    OUT PSTR** pppszMemberSids
    );

/**
 * @brief Query group membership of objects method
 *
 * Method that, given a list of object SIDs, returns a list of group SIDs
 * of which the specified objects are direct or transitive members.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] FindFlags Flags that can modify query behavior.
 * @param[in] dwSidCount The number of SIDs passed.
 * @param[in] ppszSids The list of SIDs.
 * @param[out] pdwGroupSidCount Set to the number of group SIDs returned.
 * @param[out] pppszGroupSids Set to an array containing group SIDs in printed form.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_GROUP A group with the specified SID did not exist.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_OBJECT An object with the specified SID did not exist.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_USER A user with the specified SID did not exist.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFN_LSA_PROVIDER_QUERY_MEMBER_OF)(
    IN HANDLE hProvider,
    IN LSA_FIND_FLAGS FindFlags,
    IN DWORD dwSidCount,
    IN PSTR* ppszSids,
    OUT PDWORD pdwGroupSidCount,
    OUT PSTR** pppszGroupSids
    );

//
// Close any enumeration handle.
//
/**
 * @brief Close enumeration handle method
 *
 * Method to close any enumeration handle opened with an
 * enumeration function.
 *
 * @param[in,out] hEnum The enum handle to close.
 */
typedef VOID (*PFN_LSA_PROVIDER_CLOSE_ENUM)(
    IN OUT HANDLE hEnum
    );

/**
 * @brief Modify local user method
 *
 * Method to modify a local user account according to the
 * settings in @a pUserModInfo.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] pUserModInfo The modification specification.
 *
 * @retval ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_USER Provider does not recognize user.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFNMODIFYUSER_2)(
    HANDLE hProvider,
    PLSA_USER_MOD_INFO_2 pUserModInfo
    );

/**
 * @brief Delete local user or group method
 *
 * Method to delete a local user or group object.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] pszSid The SID of the object to delete.
 *
 * @retval ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_GROUP A group with the specified SID did not exist.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_OBJECT An object with the specified SID did not exist.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_USER A user with the specified SID did not exist.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFNDELETEOBJECT) (
    HANDLE hProvider,
    PCSTR pszSid
    );

/**
 * @brief Modify local group method
 *
 * Method to modify a local group according to the settings
 * in @a pGroupModInfo.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] pGroupModInfo The modification specification.
 *
 * @retval ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval LW_ERROR_NO_SUCH_GROUP A group with the specified SID did not exist.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFNMODIFYGROUP_2) (
    HANDLE hProvider,
    PLSA_GROUP_MOD_INFO_2 pGroupModInfo
    );

/**
 * @brief Add new local user account method
 *
 * Method to add a new local user object according to the
 * settings in @a pUserAddInfo.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] pUserInfo The new group specification.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFNADDUSER_2) (
    HANDLE hProvider,
    PLSA_USER_ADD_INFO pUserInfo
    );

/**
 * @brief Add new local group method
 *
 * Method to add a new local group object according to the
 * settings in @a pGroupAddInfo.
 *
 * @param[in] hProvider       Handle to the provider context.
 * @param[in] pGroupAddInfo The new group specification.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval LW_ERROR_NOT_HANDLED Provider cannot handle request.
 * Other providers will be tried.
 * @retval ... Error.
 */
typedef DWORD (*PFNADDGROUP_2) (
    HANDLE hProvider,
    PLSA_GROUP_ADD_INFO pGroupInfo
    );

/**
 * @brief Open provider connection method
 *
 * Method to open a connection to a provider.  This method
 * is used before any other client request to establish
 * a connection between the client and the provider.
 * #PFNCLOSEHANDLE() is used to close the connection.
 *
 * If the provider needs information about the client,
 * such as the client's UID or GID, this method should
 * call #LsaSrvGetClientId to obtain the information
 * from the server context and store it in the provider
 * context.
 *
 * Whether a provider implements the concept of instances is
 * optional.  If a provider has multiple instances, such as the
 * AD provider with multi-tenancy enabled, then @a pszInstance
 * is used to target a particular instance.  If the provider
 * implements instances, then the provider should save the
 * instance's identity in the provider context.  Otherwise the
 * provider may ignore @a pszInstance.
 *
 * @param[in] hServer      Handle to the server context.
 * @param[in] pszInstance  Optional provider instance.
 * @param[out] phProvider  Set to the handle to the provider context.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval ... Error.
 */
typedef DWORD (*PFNOPENHANDLE)(
    HANDLE hServer,
    PCSTR pszInstance,
    PHANDLE phProvider
    );

typedef DWORD (*PFN_LSA_PROVIDER_GET_SMARTCARD_USER_OBJECT)(
    IN HANDLE hProvider,
    OUT PLSA_SECURITY_OBJECT* ppObject,
    OUT PSTR* ppszSmartCardReader
    );

typedef DWORD (*PFN_LSA_PROVIDER_GET_MACHINE_ACCOUNT_INFO_A)(
    IN OPTIONAL PCSTR DnsDomainName,
    OUT PLSA_MACHINE_ACCOUNT_INFO_A* ppAccountInfo
    );

typedef DWORD (*PFN_LSA_PROVIDER_GET_MACHINE_ACCOUNT_INFO_W)(
    IN OPTIONAL PCSTR DnsDomainName,
    OUT PLSA_MACHINE_ACCOUNT_INFO_W* ppAccountInfo
    );

typedef DWORD (*PFN_LSA_PROVIDER_GET_MACHINE_PASSWORD_INFO_A)(
    IN OPTIONAL PCSTR DnsDomainName,
    OUT PLSA_MACHINE_PASSWORD_INFO_A* ppPasswordInfo
    );

typedef DWORD (*PFN_LSA_PROVIDER_GET_MACHINE_PASSWORD_INFO_W)(
    IN OPTIONAL PCSTR DnsDomainName,
    OUT PLSA_MACHINE_PASSWORD_INFO_W* ppPasswordInfo
    );

/**
 * @brief Provider method table
 *
 * Primary interface/contract between the Lsass service and a provider.
 *
 * Most methods are required.  If a provider does not support a
 * method, it should implement a stub which returns @a LW_ERROR_NOT_HANDLED.
 *
 * One of #pfnOpenEnumObjects and #pfnOpenEnumObjectsFilter must be
 * provided.  If the provider does not implement filtering, the dispatch
 * layer will do it instead.
 */
typedef struct _LSA_PROVIDER_FUNCTION_TABLE {

    /**
     * @brief Resolve security objects method
     */
    PFN_LSA_PROVIDER_FIND_OBJECTS pfnFindObjects;
    //
    // Deprecates:
    //
    // PFNLOOKUPUSERBYNAME            pfnLookupUserByName;
    // PFNLOOKUPUSERBYID              pfnLookupUserById;
    // PFNLOOKUPGROUPBYNAME           pfnLookupGroupByName;
    // PFNLOOKUPGROUPBYID             pfnLookupGroupById;
    // PFNGETNAMESBYSIDLIST           pfnGetNamesBySidList;
    //
    // Adds:
    //
    // FindUserBySid
    // FindGroupBySid
    // FindUserByBn
    // FindGroupByDn
    //

    // One of the following two must be provided.  If
    // the provider does not implement filtering, the dispatch
    // layer will do it instead.
    /**
     * @brief Begin object enumeration method
     */
    PFN_LSA_PROVIDER_OPEN_ENUM_OBJECTS pfnOpenEnumObjects;
    /**
     * @brief Begin object enumeration with filter method
     */
    PFN_LSA_PROVIDER_OPEN_ENUM_OBJECTS_FILTER pfnOpenEnumObjectsFilter;
    //
    // Deprecates:
    //
    // PFNBEGIN_ENUM_USERS            pfnBeginEnumUsers;
    // PFNBEGIN_ENUM_GROUPS           pfnBeginEnumGroups;
    //

    /**
     * @brief Begin member enumeration method
     */
    PFN_LSA_PROVIDER_OPEN_ENUM_MEMBERS pfnOpenEnumGroupMembers;
    //
    // Adds:
    //
    // BeginEnumUserGroups (paging functionality)
    // BeginEnumGroupMembers (paging functionality)
    //

    /**
     * @brief Close enumeration handle method
     */
    PFN_LSA_PROVIDER_CLOSE_ENUM pfnCloseEnum;
    //
    // Deprecates:
    //
    // PFNEND_ENUM_USERS              pfnEndEnumUsers;
    // PFNEND_ENUM_GROUPS             pfnEndEnumGroups;
    //
    // Adds:
    //
    // EndEnumUserGroups (paging functionality)
    // EndEnumGroupMembers (paging functionality)
    //

    /**
     * @brief Enumerate objects method
     */
    PFN_LSA_PROVIDER_ENUM_OBJECTS pfnEnumObjects;
    /**
     * @brief Enumerate members method
     */
    PFN_LSA_PROVIDER_ENUM_MEMBERS pfnEnumGroupMembers;
    /**
     * @brief Query group membership of objects method
     */
    PFN_LSA_PROVIDER_QUERY_MEMBER_OF pfnQueryMemberOf;
    //
    // Deprecates:
    //
    // PFNENUMUSERS                   pfnEnumUsers;
    // PFNGETGROUPSFORUSER            pfnGetGroupsForUser;
    // PFNENUMGROUPS                  pfnEnumGroups;
    // PFNGETGROUPMEMBERSHIPBYPROV    pfnGetGroupMembershipByProvider;
    // group nfo level 1
    //
    // Adds:
    //
    // ability to get members of groups as something other than aliases.
    //

    /**
     * @brief Undocumented
     */
    PFN_LSA_PROVIDER_GET_SMARTCARD_USER_OBJECT pfnGetSmartCardUserObject;

    // All of the pfnGetMachine*Info{,W}() calls are optional
    /**
     * @brief Undocumented, optional
     */
    PFN_LSA_PROVIDER_GET_MACHINE_ACCOUNT_INFO_A pfnGetMachineAccountInfoA;
    /**
     * @brief Undocumented, optional
     */
    PFN_LSA_PROVIDER_GET_MACHINE_ACCOUNT_INFO_W pfnGetMachineAccountInfoW;
    /**
     * @brief Undocumented, optional
     */
    PFN_LSA_PROVIDER_GET_MACHINE_PASSWORD_INFO_A pfnGetMachinePasswordInfoA;
    /**
     * @brief Undocumented, optional
     */
    PFN_LSA_PROVIDER_GET_MACHINE_PASSWORD_INFO_W pfnGetMachinePasswordInfoW;

#if 1
    //
    // Untouched for now -- will at least change type names for readability/consistency.
    //
    /**
     * @brief Shutdown provider method
     */
    PFNSHUTDOWNPROVIDER            pfnShutdownProvider; // ok
    /**
     * @brief Open provider connection method
     */
    PFNOPENHANDLE                  pfnOpenHandle; // we should be able to get rid of this and just pass in a LSA_PROVIDER_HANDLE that is created by SRV/API but that provider can attach context.
    PFNCLOSEHANDLE                 pfnCloseHandle; // "
    /**
     * @brief Undocumented
     */
    PFNSERVICESDOMAIN              pfnServicesDomain; // is it necessary?  if we can lookup domains, it is not.
    /**
     * @brief Authenticate user method (PAM semantics)
     */
    PFNAUTHENTICATEUSERPAM         pfnAuthenticateUserPam; // ok
    /**
     * @brief Authenticate user extended method
     */
    PFNAUTHENTICATEUSEREX          pfnAuthenticateUserEx; // ok
    /**
     * @brief Undocumented
     */
    PFNVALIDATEUSER                pfnValidateUser; // This can be combined with the below (removing password)
    /**
     * @brief Undocumented
     */
    PFNCHECKUSERINLIST             pfnCheckUserInList; // see above
    /**
     * @brief Undocumented
     */
    PFNCHANGEPASSWORD              pfnChangePassword; // ok
    /**
     * @brief Undocumented
     */
    PFNSETPASSWORD                 pfnSetPassword; // ok -- local only unless we support set password protocol to set password as domain admin

    // local only?:
    /**
     * @brief Add new local user account method
     */
    PFNADDUSER_2                   pfnAddUser;
    /**
     * @brief Modify local user method
     */
    PFNMODIFYUSER_2                pfnModifyUser;
    /**
     * @brief Delete local user or group method
     */
    PFNDELETEOBJECT                pfnDeleteObject;
    /**
     * @brief Add new local group method
     */
    PFNADDGROUP_2                  pfnAddGroup;
    /**
     * @brief Modify local group method
     */
    PFNMODIFYGROUP_2               pfnModifyGroup;

    // PAM
    /**
     * @brief Undocumented
     */
    PFNOPENSESSION                 pfnOpenSession;
    /**
     * @brief Undocumented
     */
    PFNCLOSESESSION                pfnCloseSession;

    // NSS -- pretty good, perhaps module info level/flags?
    /**
     * @brief Undocumented
     */
    PFNLOOKUP_NSS_ARTEFACT_BY_KEY  pfnLookupNSSArtefactByKey;
    /**
     * @brief Undocumented
     */
    PFNBEGIN_ENUM_NSS_ARTEFACTS    pfnBeginEnumNSSArtefacts;
    /**
     * @brief Undocumented
     */
    PFNENUMNSS_ARTEFACTS           pfnEnumNSSArtefacts;
    /**
     * @brief Undocumented
     */
    PFNEND_ENUM_NSS_ARTEFACTS      pfnEndEnumNSSArtefacts; // can use new close enum function

    /**
     * @brief Get provider status method
     */
    PFNGET_STATUS                  pfnGetStatus;
    /**
     * @brief Free provider status information method
     */
    PFNFREE_STATUS                 pfnFreeStatus;

    /**
     * @brief Perform provider-specific method
     */
    PFNPROVIDER_IO_CONTROL         pfnProviderIoControl; // fix interface wrt uid/gid stuff
#endif

} LSA_PROVIDER_FUNCTION_TABLE;

/**
 * @brief Provider method table pointer
 *
 * Pointer to an #LSA_PROVIDER_FUNCTION_TABLE.
 */
typedef LSA_PROVIDER_FUNCTION_TABLE* PLSA_PROVIDER_FUNCTION_TABLE;

/**
 * @brief Lsass provider init entry point
 *
 * Function prototype of the main entry point within the lsass
 * provider. The lsass service invokes this function after
 * dynamically loading the provider. The provider is expected
 * to return an interface table of methods which are called during
 * various phases of request processing by lsass.
 *
 * @param[out] ppszProviderName  The provider's name.
 * @param[out] ppFnTable         Set to the function table.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval ... Error.
 */
typedef DWORD (*PFNINITIALIZEPROVIDER)(
    OUT PCSTR* ppszProviderName,
    OUT PLSA_PROVIDER_FUNCTION_TABLE* ppFnTable
    );

/**
 * @brief Static provider table entry
 */
typedef struct _LSA_STATIC_PROVIDER {
    /**
     * @brief Provider name
     */
    PCSTR pszId;
    /**
     * @brief Static provider entry point
     */
    PFNINITIALIZEPROVIDER pInitialize;
} LSA_STATIC_PROVIDER;

/**
 * @brief Static provider table entry pointer
 *
 * Pointer to an #LSA_STATIC_PROVIDER.
 */
typedef LSA_STATIC_PROVIDER* PLSA_STATIC_PROVIDER;

/*@}*/

#endif /* __LSAPROVIDER_H__ */

/*
local variables:
mode: c
c-basic-offset: 4
indent-tabs-mode: nil
tab-width: 4
end:
*/
