windows-nt/Source/XPSP1/NT/net/sfm/afp/service/server/security.c
2020-09-26 16:20:57 +08:00

413 lines
10 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************/
/** 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 );
}