mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
413 lines
10 KiB
413 lines
10 KiB
/********************************************************************/
|
|
/** Copyright(c) 1989 Microsoft Corporation. **/
|
|
/********************************************************************/
|
|
|
|
//***
|
|
//
|
|
// Filename: security.c
|
|
//
|
|
// Description: This module contains code that will create and delete the
|
|
// security object. It will also contain access checking calls.
|
|
//
|
|
// History:
|
|
// June 21,1992. NarenG Created original version.
|
|
//
|
|
// NOTE: ??? The lpdwAccessStatus parameter for AccessCheckAndAuditAlarm
|
|
// returns junk. ???
|
|
//
|
|
#include "afpsvcp.h"
|
|
|
|
typedef struct _AFP_SECURITY_OBJECT {
|
|
|
|
LPWSTR lpwsObjectName;
|
|
LPWSTR lpwsObjectType;
|
|
GENERIC_MAPPING GenericMapping;
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor;
|
|
|
|
} AFP_SECURITY_OBJECT, PAFP_SECURITY_OBJECT;
|
|
|
|
static AFP_SECURITY_OBJECT AfpSecurityObject;
|
|
|
|
#define AFPSVC_SECURITY_OBJECT TEXT("AfpSvcAdminApi");
|
|
#define AFPSVC_SECURITY_OBJECT_TYPE TEXT("Security");
|
|
|
|
|
|
|
|
//**
|
|
//
|
|
// Call: AfpSecObjCreate
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
// ERROR_NOT_ENOUGH_MEMORY
|
|
// non-zero returns from security functions
|
|
//
|
|
// Description: This procedure will set up the security object that will
|
|
// be used to check to see if an RPC client is an administrator
|
|
// for the local machine.
|
|
//
|
|
DWORD
|
|
AfpSecObjCreate(
|
|
VOID
|
|
)
|
|
{
|
|
PSID pAdminSid = NULL;
|
|
PSID pLocalSystemSid = NULL;
|
|
PSID pServerOpSid = NULL;
|
|
PSID pPwrUserSid = NULL;
|
|
PACL pDacl = NULL;
|
|
HANDLE hProcessToken = NULL;
|
|
PULONG pSubAuthority;
|
|
SID_IDENTIFIER_AUTHORITY SidIdentifierNtAuth = SECURITY_NT_AUTHORITY;
|
|
SECURITY_DESCRIPTOR SecurityDescriptor;
|
|
DWORD dwRetCode;
|
|
DWORD cbDaclSize;
|
|
|
|
|
|
// Set up security object
|
|
//
|
|
AfpSecurityObject.lpwsObjectName = AFPSVC_SECURITY_OBJECT;
|
|
AfpSecurityObject.lpwsObjectType = AFPSVC_SECURITY_OBJECT_TYPE;
|
|
|
|
// Generic mapping structure for the security object
|
|
// All generic access types are allowed API access.
|
|
//
|
|
AfpSecurityObject.GenericMapping.GenericRead = STANDARD_RIGHTS_READ |
|
|
AFPSVC_ALL_ACCESS;
|
|
|
|
AfpSecurityObject.GenericMapping.GenericWrite = STANDARD_RIGHTS_WRITE |
|
|
AFPSVC_ALL_ACCESS;
|
|
|
|
AfpSecurityObject.GenericMapping.GenericExecute =
|
|
STANDARD_RIGHTS_EXECUTE |
|
|
AFPSVC_ALL_ACCESS;
|
|
|
|
AfpSecurityObject.GenericMapping.GenericAll = AFPSVC_ALL_ACCESS;
|
|
|
|
// The do - while(FALSE) statement is used so that the break statement
|
|
// maybe used insted of the goto statement, to execute a clean up and
|
|
// and exit action.
|
|
//
|
|
do {
|
|
|
|
dwRetCode = NO_ERROR;
|
|
|
|
// Set up the SID for the admins that will be allowed to have
|
|
// access. This SID will have 2 sub-authorities
|
|
// SECURITY_BUILTIN_DOMAIN_RID and DOMAIN_ALIAS_ADMIN_RID.
|
|
//
|
|
pAdminSid = (PSID)LocalAlloc( LPTR, GetSidLengthRequired( 2 ) );
|
|
|
|
if ( pAdminSid == NULL ) {
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if ( !InitializeSid( pAdminSid, &SidIdentifierNtAuth, 2 ) )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Set the sub-authorities
|
|
//
|
|
pSubAuthority = GetSidSubAuthority( pAdminSid, 0 );
|
|
*pSubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
|
|
|
|
pSubAuthority = GetSidSubAuthority( pAdminSid, 1 );
|
|
*pSubAuthority = DOMAIN_ALIAS_RID_ADMINS;
|
|
|
|
// Create the server operators SID
|
|
//
|
|
pServerOpSid = (PSID)LocalAlloc( LPTR, GetSidLengthRequired( 2 ) );
|
|
|
|
if ( pServerOpSid == NULL )
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if ( !InitializeSid( pServerOpSid, &SidIdentifierNtAuth, 2 ) )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Set the sub-authorities
|
|
//
|
|
pSubAuthority = GetSidSubAuthority( pServerOpSid, 0 );
|
|
*pSubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
|
|
|
|
pSubAuthority = GetSidSubAuthority( pServerOpSid, 1 );
|
|
*pSubAuthority = DOMAIN_ALIAS_RID_SYSTEM_OPS;
|
|
|
|
//
|
|
// Create the Power user operators SID
|
|
//
|
|
pPwrUserSid = (PSID)LocalAlloc( LPTR, GetSidLengthRequired( 2 ) );
|
|
|
|
if ( pPwrUserSid == NULL )
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if ( !InitializeSid( pPwrUserSid, &SidIdentifierNtAuth, 2 ) )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Set the sub-authorities
|
|
//
|
|
pSubAuthority = GetSidSubAuthority( pPwrUserSid, 0 );
|
|
*pSubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
|
|
|
|
pSubAuthority = GetSidSubAuthority( pPwrUserSid, 1 );
|
|
*pSubAuthority = DOMAIN_ALIAS_RID_POWER_USERS;
|
|
|
|
// Create the LocalSystemSid which will be the owner and the primary
|
|
// group of the security object.
|
|
//
|
|
pLocalSystemSid = (PSID)LocalAlloc( LPTR, GetSidLengthRequired( 1 ) );
|
|
|
|
if ( pLocalSystemSid == NULL )
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if ( !InitializeSid( pLocalSystemSid, &SidIdentifierNtAuth, 1 ) )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Set the sub-authorities
|
|
//
|
|
pSubAuthority = GetSidSubAuthority( pLocalSystemSid, 0 );
|
|
*pSubAuthority = SECURITY_LOCAL_SYSTEM_RID;
|
|
|
|
// Set up the DACL that will allow admins with the above SID all access
|
|
// It should be large enough to hold all ACEs.
|
|
//
|
|
cbDaclSize = sizeof(ACL) + ( sizeof(ACCESS_ALLOWED_ACE) * 2 ) +
|
|
GetLengthSid(pAdminSid) + GetLengthSid(pServerOpSid) + GetLengthSid(pPwrUserSid);
|
|
|
|
if ( (pDacl = (PACL)LocalAlloc( LPTR, cbDaclSize ) ) == NULL )
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if ( !InitializeAcl( pDacl, cbDaclSize, ACL_REVISION2 ) )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Add the ACE to the DACL
|
|
//
|
|
if ( !AddAccessAllowedAce( pDacl,
|
|
ACL_REVISION2,
|
|
AFPSVC_ALL_ACCESS, // What the admin can do
|
|
pAdminSid ))
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
if ( !AddAccessAllowedAce( pDacl,
|
|
ACL_REVISION2,
|
|
AFPSVC_ALL_ACCESS, // What the admin can do
|
|
pServerOpSid ))
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
if ( !AddAccessAllowedAce( pDacl,
|
|
ACL_REVISION2,
|
|
AFPSVC_ALL_ACCESS, // What the power user can do
|
|
pPwrUserSid ))
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Create the security descriptor an put the DACL in it.
|
|
//
|
|
if ( !InitializeSecurityDescriptor( &SecurityDescriptor, 1 ))
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
if ( !SetSecurityDescriptorDacl( &SecurityDescriptor,
|
|
TRUE,
|
|
pDacl,
|
|
FALSE ) )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
|
|
// Set owner for the descriptor
|
|
//
|
|
if ( !SetSecurityDescriptorOwner( &SecurityDescriptor,
|
|
pLocalSystemSid,
|
|
FALSE ) )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
|
|
// Set group for the descriptor
|
|
//
|
|
if ( !SetSecurityDescriptorGroup( &SecurityDescriptor,
|
|
pLocalSystemSid,
|
|
FALSE ) )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Get token for the current process
|
|
//
|
|
if ( !OpenProcessToken( GetCurrentProcess(),
|
|
TOKEN_QUERY,
|
|
&hProcessToken ))
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Create a security object. This is really just a security descriptor
|
|
// is self-relative form. This procedure will allocate memory for this
|
|
// security descriptor and copy all in the information passed in. This
|
|
// allows us to free all dynamic memory allocated.
|
|
//
|
|
if ( !CreatePrivateObjectSecurity(
|
|
NULL,
|
|
&SecurityDescriptor,
|
|
&(AfpSecurityObject.pSecurityDescriptor),
|
|
FALSE,
|
|
hProcessToken,
|
|
&(AfpSecurityObject.GenericMapping)
|
|
))
|
|
dwRetCode = GetLastError();
|
|
|
|
} while( FALSE );
|
|
|
|
|
|
// Free up the dynamic memory
|
|
//
|
|
if ( pLocalSystemSid != NULL )
|
|
LocalFree( pLocalSystemSid );
|
|
|
|
if ( pAdminSid != NULL )
|
|
LocalFree( pAdminSid );
|
|
|
|
if ( pServerOpSid != NULL )
|
|
LocalFree( pServerOpSid );
|
|
|
|
if ( pPwrUserSid != NULL )
|
|
LocalFree( pPwrUserSid );
|
|
|
|
if ( pDacl != NULL )
|
|
LocalFree( pDacl );
|
|
|
|
if ( hProcessToken != NULL )
|
|
CloseHandle( hProcessToken );
|
|
|
|
return( dwRetCode );
|
|
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: AfpSecObjDelete
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
// non-zero returns from security functions
|
|
//
|
|
// Description: Will destroy a valid security descriptor.
|
|
//
|
|
DWORD
|
|
AfpSecObjDelete( VOID )
|
|
{
|
|
if ( !IsValidSecurityDescriptor( AfpSecurityObject.pSecurityDescriptor))
|
|
return( NO_ERROR );
|
|
|
|
if (!DestroyPrivateObjectSecurity( &AfpSecurityObject.pSecurityDescriptor))
|
|
return( GetLastError() );
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: AfpSecObjAccessCheck
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
// non-zero returns from security functions
|
|
//
|
|
// Description: This procedure will first impersonate the client, then
|
|
// check to see if the client has the desired access to the
|
|
// security object. If he/she does then the AccessStatus
|
|
// variable will be set to NO_ERROE otherwise it will be
|
|
// set to ERROR_ACCESS_DENIED. It will the revert to self and
|
|
// return.
|
|
//
|
|
DWORD
|
|
AfpSecObjAccessCheck( IN DWORD DesiredAccess,
|
|
OUT LPDWORD lpdwAccessStatus
|
|
)
|
|
{
|
|
DWORD dwRetCode;
|
|
ACCESS_MASK GrantedAccess;
|
|
BOOL fGenerateOnClose;
|
|
|
|
// Impersonate the client
|
|
//
|
|
dwRetCode = RpcImpersonateClient( NULL );
|
|
|
|
if ( dwRetCode != RPC_S_OK )
|
|
return( I_RpcMapWin32Status( dwRetCode ));
|
|
|
|
dwRetCode = AccessCheckAndAuditAlarm(
|
|
AFP_SERVICE_NAME,
|
|
NULL,
|
|
AfpSecurityObject.lpwsObjectType,
|
|
AfpSecurityObject.lpwsObjectName,
|
|
AfpSecurityObject.pSecurityDescriptor,
|
|
DesiredAccess,
|
|
&(AfpSecurityObject.GenericMapping),
|
|
FALSE,
|
|
&GrantedAccess,
|
|
(LPBOOL)lpdwAccessStatus,
|
|
&fGenerateOnClose
|
|
);
|
|
|
|
RpcRevertToSelf();
|
|
|
|
if ( !dwRetCode )
|
|
return( GetLastError() );
|
|
|
|
// Check if desired access == granted Access
|
|
//
|
|
if ( DesiredAccess != GrantedAccess )
|
|
{
|
|
AFP_PRINT(( "SFMSVC: AfpSecObjAccessCheck: granted = 0x%x, desired = 0x%x\n",
|
|
GrantedAccess,DesiredAccess));
|
|
*lpdwAccessStatus = ERROR_ACCESS_DENIED;
|
|
}
|
|
else
|
|
{
|
|
*lpdwAccessStatus = NO_ERROR;
|
|
}
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|