Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

258 lines
7.1 KiB

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
MkSecAtt.c
Abstract:
ReplMakeSecurityAttributes() creates a security descriptor containing:
- the security (including ACLs, owner, group)
This is used by ReplCopyFile() and ReplCopyDirectoryItself().
Author:
John Rogers (JohnRo) 08-Apr-1993
Environment:
User mode only. Uses Win32 APIs.
Requires ANSI C extensions: slash-slash comments, long external names.
Tab size is set to 4.
Revision History:
08-Apr-1993 JohnRo
Created for RAID 1938: Replicator un-ACLs files when not given
enough permission.
04-Jun-1993 JohnRo
RAID 12473: Changed to handle ReplMakeFileSecurity not supported on
downlevel exporter.
10-May-1995 JonN
RAID 11829: Clients of ReplMakeSecurityAttributes free DestSecurityAttr
but not DestSecurityAttr->lpSecurityDescriptor. Changed allocations
to place lpSecurityDescriptor in the same memory block as
DestSecurityAttr.
--*/
// These must be included first:
#include <windows.h> // IN, LPTSTR, PSECURITY_ATTRIBUTES, etc.
#include <lmcons.h> // NET_API_STATUS, PATHLEN, etc.
// These may be included in any order:
#include <lmerr.h> // NERR_InternalError, NO_ERROR.
#include <netdebug.h> // NetpKdPrint(), FORMAT_ equates, etc.
#include <netlib.h> // NetpMemoryAllocate(), etc.
#include <prefix.h> // PREFIX_ equates.
#include <repldefs.h> // IF_DEBUG(), my prototype, USE_ equates, etc.
#include <tstr.h> // TCHAR_EOS, STRLEN().
#define REPL_ROUND_UP(x) (sizeof(DWORD) * (((x) + sizeof(DWORD) - 1) / sizeof(DWORD)))
#define BASE_SECURITY_ATTR_SIZE REPL_ROUND_UP(sizeof( SECURITY_ATTRIBUTES ))
NET_API_STATUS
ReplMakeSecurityAttributes(
IN LPCTSTR SourcePath,
OUT PSECURITY_ATTRIBUTES * DestSecurityAttrPtr // alloc and set ptr
)
/*++
Routine Description:
ReplMakeSecurityAttributes builds an security descriptor in memory.
It is make to be a clone of the source file or directory.
Arguments:
SourcePath - Points to the path of a file or directory to be used as
the original security info (ACL, owner, group). This path is
typically a UNC name, for instance:
\\server\REPL$\dir\file
This routine assumes that the source file or directory exists.
DestSecurityAttrPtr - Points to a pointer which be filled-in by this
routine. (This routine will allocate memory; the caller must free
with NetpMemoryFree or equivalent.) On error, this will be set to
NULL.
Return Value:
NET_API_STATUS
Note that ERROR_NOT_SUPPORTED is a reasonable value to return for
downlevel exporters.
Threads:
Used by client and syncer threads.
--*/
{
NET_API_STATUS ApiStatus;
PSECURITY_ATTRIBUTES DestSecurityAttr = NULL;
#ifdef USE_UNC_GETFILESEC
PSECURITY_DESCRIPTOR SourceSecurityDesc = NULL;
DWORD SourceSecurityDescSize;
#endif
//
// Check for caller errors.
//
if (SourcePath == NULL) {
ApiStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if ((*SourcePath) == TCHAR_EOS) {
ApiStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if (STRLEN(SourcePath) > PATHLEN) {
ApiStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
#ifdef USE_UNC_GETFILESEC
//
// Find out how much memory we need for source security attributes.
//
if (!GetFileSecurity(
(LPTSTR) SourcePath,
REPL_SECURITY_TO_COPY, // requested info flags
NULL, // don't have a buffer yet
0, // size of sec desc buffer so far
& SourceSecurityDescSize // size needed
)) {
// GetFileSecurity failed. Why?
ApiStatus = (NET_API_STATUS) GetLastError();
NetpAssert( ApiStatus != NO_ERROR );
if (ApiStatus == ERROR_INSUFFICIENT_BUFFER) {
NetpAssert(
SourceSecurityDescSize > sizeof(SECURITY_DESCRIPTOR) );
} else if ( (ApiStatus==ERROR_NOT_SUPPORTED)
|| (ApiStatus==ERROR_INVALID_PARAMETER) ) {
// Just downlevel master, so set default security and continue.
ApiStatus = ERROR_NOT_SUPPORTED;
goto Cleanup;
} else {
NetpKdPrint(( PREFIX_REPL_CLIENT
"ReplMakeSecurityAttributes: GetFileSecurity(1st) failed "
FORMAT_API_STATUS ".\n", ApiStatus ));
goto Cleanup;
}
} else {
NetpKdPrint(( PREFIX_REPL_CLIENT
"ReplMakeSecurityAttributes: GetFileSecurity claims to have "
"worked with 0 size and NULL pointer!\n" ));
ApiStatus = NERR_InternalError;
goto Cleanup;
}
//
// Allocate memory for both the destination and source security attributes
// structures. The source security structure is at the end of the same
// memory block.
//
DestSecurityAttr = NetpMemoryAllocate(
BASE_SECURITY_ATTR_SIZE + SourceSecurityDescSize );
if (DestSecurityAttr == NULL) {
ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
SourceSecurityDesc = (PSECURITY_DESCRIPTOR)
(((ULONG)DestSecurityAttr)+BASE_SECURITY_ATTR_SIZE);
DestSecurityAttr->lpSecurityDescriptor = SourceSecurityDesc;
if (!GetFileSecurity(
(LPTSTR) SourcePath,
REPL_SECURITY_TO_COPY, // requested info flags
SourceSecurityDesc,
SourceSecurityDescSize, // size of sec desc buffer
& SourceSecurityDescSize // size needed
)) {
// GetFileSecurity failed again! Why?
ApiStatus = (NET_API_STATUS) GetLastError();
NetpAssert( ApiStatus != NO_ERROR );
NetpKdPrint(( PREFIX_REPL_CLIENT
"ReplMakeSecurityAttributes: GetFileSecurity(2nd) failed "
FORMAT_API_STATUS ".\n", ApiStatus ));
goto Cleanup;
}
//
// Build security attributes so that directory we create will
// have the right security (ACLs, owner, group).
//
DestSecurityAttr->nLength = sizeof(SECURITY_ATTRIBUTES);
DestSecurityAttr->bInheritHandle = FALSE;
ApiStatus = NO_ERROR;
#else // not USE_UNC_GETFILESEC
BUGBUG; // how do we do this without UNC GetFileSecurity?
ApiStatus = ERROR_NOT_SUPPORTED;
#endif // not USE_UNC_GETFILESEC
Cleanup:
//
// Set vars for caller.
//
if (ApiStatus == NO_ERROR) {
*DestSecurityAttrPtr = DestSecurityAttr;
} else {
*DestSecurityAttrPtr = NULL;
if (DestSecurityAttr != NULL) {
NetpMemoryFree( DestSecurityAttr );
}
} // error occurred.
// Note that ERROR_NOT_SUPPORTED is a reasonable value to return for
// downlevel exporters.
IF_DEBUG( SYNC ) {
NetpKdPrint(( PREFIX_REPL_CLIENT
"ReplMakeSecurityAttributes: returning status of "
FORMAT_API_STATUS " reading security from '"
FORMAT_LPTSTR "'.\n",
ApiStatus, SourcePath ));
}
return (ApiStatus);
}