555 lines
13 KiB
C
555 lines
13 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
radmin.c (remote admin)
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This file exercises the various NetAdminTools API.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Dan Lafferty (danl) 19-Sept-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode -Win32
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h> // needed for windows.h when I have nt.h
|
|||
|
#include <windows.h>
|
|||
|
|
|||
|
#include <stdlib.h> // atoi
|
|||
|
#include <stdio.h> // printf
|
|||
|
#include <tstr.h> // STRICMP
|
|||
|
|
|||
|
#include <ntseapi.h> // SECURITY_DESCRIPTOR_CONTROL
|
|||
|
#include <srvsvc.h>
|
|||
|
#include <filesec.h> // NetpGetFileSecurity, NetpSetFileSecurity
|
|||
|
|
|||
|
//
|
|||
|
// DataStructures
|
|||
|
//
|
|||
|
|
|||
|
typedef struct _TEST_SID {
|
|||
|
UCHAR Revision;
|
|||
|
UCHAR SubAuthorityCount;
|
|||
|
UCHAR IdentifierAuthority[6];
|
|||
|
ULONG SubAuthority[10];
|
|||
|
} TEST_SID, *PTEST_SID, *LPTEST_SID;
|
|||
|
|
|||
|
typedef struct _TEST_ACL {
|
|||
|
UCHAR AclRevision;
|
|||
|
UCHAR Sbz1;
|
|||
|
USHORT AclSize;
|
|||
|
UCHAR Dummy1[];
|
|||
|
} TEST_ACL, *PTEST_ACL;
|
|||
|
|
|||
|
typedef struct _TEST_SECURITY_DESCRIPTOR {
|
|||
|
UCHAR Revision;
|
|||
|
UCHAR Sbz1;
|
|||
|
SECURITY_DESCRIPTOR_CONTROL Control;
|
|||
|
PTEST_SID Owner;
|
|||
|
PTEST_SID Group;
|
|||
|
PTEST_ACL Sacl;
|
|||
|
PTEST_ACL Dacl;
|
|||
|
} TEST_SECURITY_DESCRIPTOR, *PTEST_SECURITY_DESCRIPTOR;
|
|||
|
|
|||
|
//
|
|||
|
// GLOBALS
|
|||
|
//
|
|||
|
|
|||
|
TEST_SID OwnerSid = {
|
|||
|
1, 5,
|
|||
|
1,2,3,4,5,6,
|
|||
|
0x999, 0x888, 0x777, 0x666, 0x12345678};
|
|||
|
|
|||
|
TEST_SID GroupSid = {
|
|||
|
1, 5,
|
|||
|
1,2,3,4,5,6,
|
|||
|
0x999, 0x888, 0x777, 0x666, 0x12345678};
|
|||
|
|
|||
|
TEST_ACL SaclAcl = { 1, 2, 4+1, 3};
|
|||
|
TEST_ACL DaclAcl = { 1, 2, 4+5, 4, 4, 4, 4, 4, };
|
|||
|
|
|||
|
TEST_SECURITY_DESCRIPTOR TestSd = {
|
|||
|
1, 2, 0x3333,
|
|||
|
&OwnerSid,
|
|||
|
&GroupSid,
|
|||
|
&SaclAcl,
|
|||
|
NULL };
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Function Prototypes
|
|||
|
//
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
TestGetFileSec(
|
|||
|
LPTSTR ServerName,
|
|||
|
LPTSTR FileName
|
|||
|
);
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
TestSetFileSec(
|
|||
|
LPTSTR ServerName,
|
|||
|
LPTSTR FileName
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
Usage(VOID);
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
DisplaySecurityDescriptor(
|
|||
|
PTEST_SECURITY_DESCRIPTOR pSecDesc
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
MakeArgsUnicode (
|
|||
|
DWORD argc,
|
|||
|
PCHAR argv[]
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
ConvertToUnicode(
|
|||
|
OUT LPWSTR *UnicodeOut,
|
|||
|
IN LPSTR AnsiIn
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID __cdecl
|
|||
|
main (
|
|||
|
DWORD argc,
|
|||
|
PUCHAR argv[]
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allows manual testing of the AdminTools API.
|
|||
|
|
|||
|
radmin GetNameFromSid - calls NetpGetNameFromSid
|
|||
|
radmin SetFileSec - calls NetpSetFileSecurity
|
|||
|
|
|||
|
etc...
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD status;
|
|||
|
LPTSTR FileName;
|
|||
|
LPTSTR *FixArgv;
|
|||
|
LPTSTR pServerName;
|
|||
|
DWORD argIndex;
|
|||
|
|
|||
|
//
|
|||
|
// Make the arguments unicode if necessary.
|
|||
|
//
|
|||
|
#ifdef UNICODE
|
|||
|
|
|||
|
if (!MakeArgsUnicode(argc, argv)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
FixArgv = (LPTSTR *)argv;
|
|||
|
argIndex = 1;
|
|||
|
pServerName = NULL;
|
|||
|
|
|||
|
if (STRNCMP (FixArgv[1], TEXT("\\\\"), 2) == 0) {
|
|||
|
pServerName = FixArgv[1];
|
|||
|
argIndex = 2;
|
|||
|
}
|
|||
|
if (argc < 2) {
|
|||
|
printf("ERROR: \n");
|
|||
|
Usage();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (STRICMP (FixArgv[argIndex], TEXT("GetFileSec")) == 0) {
|
|||
|
if (argc > argIndex ) {
|
|||
|
FileName = FixArgv[argIndex+1];
|
|||
|
}
|
|||
|
else {
|
|||
|
FileName = NULL;
|
|||
|
}
|
|||
|
status = TestGetFileSec(pServerName,FileName);
|
|||
|
}
|
|||
|
|
|||
|
else if (STRICMP (FixArgv[argIndex], TEXT("SetFileSec")) == 0) {
|
|||
|
if (argc > argIndex ) {
|
|||
|
FileName = FixArgv[argIndex+1];
|
|||
|
}
|
|||
|
else {
|
|||
|
FileName = NULL;
|
|||
|
}
|
|||
|
status = TestSetFileSec(pServerName,FileName);
|
|||
|
}
|
|||
|
|
|||
|
else {
|
|||
|
printf("[sc] Unrecognized Command\n");
|
|||
|
Usage();
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
TestGetFileSec(
|
|||
|
LPTSTR ServerName,
|
|||
|
LPTSTR FileName
|
|||
|
)
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
SECURITY_INFORMATION secInfo;
|
|||
|
PTEST_SECURITY_DESCRIPTOR pSecurityDescriptor;
|
|||
|
LPBYTE pDest;
|
|||
|
DWORD Length;
|
|||
|
|
|||
|
if (FileName == NULL ) {
|
|||
|
FileName = TEXT("Dan.txt");
|
|||
|
}
|
|||
|
|
|||
|
// secInfo = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
|||
|
// DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION);
|
|||
|
secInfo = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
|||
|
DACL_SECURITY_INFORMATION );
|
|||
|
|
|||
|
status = NetpGetFileSecurity(
|
|||
|
FileName, // FileName,
|
|||
|
secInfo, // pRequestedInformation,
|
|||
|
(PSECURITY_DESCRIPTOR *)&pSecurityDescriptor, // pSecurityDescriptor,
|
|||
|
&Length); // pnLength
|
|||
|
|
|||
|
if (status != NO_ERROR) {
|
|||
|
printf("NetpGetFileSecurity Failed %d,0x%x\n",status,status);
|
|||
|
}
|
|||
|
else{
|
|||
|
|
|||
|
pDest = (LPBYTE) pSecurityDescriptor;
|
|||
|
|
|||
|
if (!IsValidSecurityDescriptor(pSecurityDescriptor)) {
|
|||
|
printf("FAILURE: SECURITY DESCRIPTOR IS INVALID\n");
|
|||
|
}
|
|||
|
else {
|
|||
|
printf("SUCCESS: SECURITY DESCRIPTOR IS VALID\n");
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Make the self-releative SD absolute for display.
|
|||
|
//
|
|||
|
pSecurityDescriptor->Owner = (PTEST_SID)(pDest + (DWORD)pSecurityDescriptor->Owner);
|
|||
|
pSecurityDescriptor->Group = (PTEST_SID)(pDest + (DWORD)pSecurityDescriptor->Group);
|
|||
|
pSecurityDescriptor->Sacl = (PTEST_ACL)(pDest + (DWORD)pSecurityDescriptor->Sacl);
|
|||
|
pSecurityDescriptor->Dacl = (PTEST_ACL)(pDest + (DWORD)pSecurityDescriptor->Dacl);
|
|||
|
pSecurityDescriptor->Control &= (~SE_SELF_RELATIVE);
|
|||
|
|
|||
|
if (pSecurityDescriptor->Sacl == (PTEST_ACL)pDest) {
|
|||
|
pSecurityDescriptor->Sacl = NULL;
|
|||
|
}
|
|||
|
if (pSecurityDescriptor->Dacl == (PTEST_ACL)pDest) {
|
|||
|
pSecurityDescriptor->Dacl = NULL;
|
|||
|
}
|
|||
|
|
|||
|
printf("Size of Security Descriptor = %ld \n",Length);
|
|||
|
DisplaySecurityDescriptor(pSecurityDescriptor);
|
|||
|
}
|
|||
|
|
|||
|
return (NO_ERROR);
|
|||
|
}
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
TestSetFileSec(
|
|||
|
LPTSTR ServerName,
|
|||
|
LPTSTR FileName
|
|||
|
)
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
SECURITY_INFORMATION secInfo;
|
|||
|
|
|||
|
|
|||
|
if (FileName == NULL ) {
|
|||
|
FileName = TEXT("Dan.txt");
|
|||
|
}
|
|||
|
|
|||
|
secInfo = 0x55555555;
|
|||
|
|
|||
|
status = NetpSetFileSecurity(
|
|||
|
FileName, // FileName,
|
|||
|
secInfo, // pRequestedInformation,
|
|||
|
(PSECURITY_DESCRIPTOR)&TestSd); // pSecurityDescriptor,
|
|||
|
|
|||
|
if (status != NO_ERROR) {
|
|||
|
printf("NetpSetFileSecurity Failed %d,0x%x\n",status,status);
|
|||
|
}
|
|||
|
return (NO_ERROR);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
Usage(VOID)
|
|||
|
{
|
|||
|
|
|||
|
printf("USAGE:\n");
|
|||
|
printf("radmin <server> <function>\n");
|
|||
|
printf("Functions: GetFileSec, SetFileSec...\n\n");
|
|||
|
|
|||
|
printf("SYNTAX EXAMPLES \n");
|
|||
|
|
|||
|
printf("radmin \\\\DANL2 GetFileSec - calls NetpGetFileSecurity on \\DANL2\n");
|
|||
|
printf("radmin \\\\DANL2 SetFileSec - calls NetpSetFileSecurity on \\DANL2\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// ***************************************************************************
|
|||
|
VOID
|
|||
|
DisplaySecurityDescriptor(
|
|||
|
PTEST_SECURITY_DESCRIPTOR pSecDesc
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
DWORD i;
|
|||
|
DWORD numAces;
|
|||
|
|
|||
|
if (!IsValidSecurityDescriptor(pSecDesc)) {
|
|||
|
printf("FAILURE: SECURITY DESCRIPTOR IS INVALID\n");
|
|||
|
}
|
|||
|
|
|||
|
printf("[ADT]:Security Descriptor Received\n");
|
|||
|
printf("\tSECURITY_DESCRIPTOR HEADER:\n");
|
|||
|
printf("\tRevision: %d\n", pSecDesc->Revision);
|
|||
|
printf("\tSbz1: 0x%x\n", pSecDesc->Sbz1);
|
|||
|
printf("\tControl: 0x%x\n", pSecDesc->Control);
|
|||
|
|
|||
|
//-------------------
|
|||
|
// OWNER SID
|
|||
|
//-------------------
|
|||
|
printf("\n\tOWNER_SID\n");
|
|||
|
printf("\t\tRevision: %u\n",pSecDesc->Owner->Revision);
|
|||
|
printf("\t\tSubAuthorityCount: %u\n",pSecDesc->Owner->SubAuthorityCount);
|
|||
|
|
|||
|
printf("\t\tIdentifierAuthority: ");
|
|||
|
for(i=0; i<6; i++) {
|
|||
|
printf("%u ",pSecDesc->Owner->IdentifierAuthority[i]);
|
|||
|
}
|
|||
|
printf("\n");
|
|||
|
|
|||
|
printf("\t\tSubAuthority: ");
|
|||
|
for(i=0; i<pSecDesc->Group->SubAuthorityCount; i++) {
|
|||
|
printf("0x%x ",pSecDesc->Owner->SubAuthority[i]);
|
|||
|
}
|
|||
|
printf("\n");
|
|||
|
|
|||
|
//-------------------
|
|||
|
// GROUP SID
|
|||
|
//-------------------
|
|||
|
printf("\n\tGROUP_SID\n");
|
|||
|
printf("\t\tRevision: %u\n",pSecDesc->Group->Revision);
|
|||
|
printf("\t\tSubAuthorityCount: %u\n",pSecDesc->Group->SubAuthorityCount);
|
|||
|
|
|||
|
printf("\t\tIdentifierAuthority: ");
|
|||
|
for(i=0; i<6; i++) {
|
|||
|
printf("%u ",pSecDesc->Group->IdentifierAuthority[i]);
|
|||
|
}
|
|||
|
printf("\n");
|
|||
|
|
|||
|
printf("\t\tSubAuthority: ");
|
|||
|
for(i=0; i<pSecDesc->Group->SubAuthorityCount; i++) {
|
|||
|
printf("0x%x ",pSecDesc->Group->SubAuthority[i]);
|
|||
|
}
|
|||
|
printf("\n");
|
|||
|
|
|||
|
if (pSecDesc->Sacl != NULL) {
|
|||
|
printf("\n\tSYSTEM_ACL\n");
|
|||
|
printf("\t\tRevision: %d\n",pSecDesc->Sacl->AclRevision);
|
|||
|
printf("\t\tSbz1: %d\n",pSecDesc->Sacl->Sbz1);
|
|||
|
printf("\t\tAclSize: %d\n",pSecDesc->Sacl->AclSize);
|
|||
|
printf("\t\tACE: %u\n",(unsigned short)pSecDesc->Sacl->Dummy1[0]);
|
|||
|
}
|
|||
|
else {
|
|||
|
printf("\n\tSYSTEM_ACL = NULL\n");
|
|||
|
}
|
|||
|
|
|||
|
if (pSecDesc->Dacl != NULL) {
|
|||
|
printf("\n\tDISCRETIONARY_ACL\n");
|
|||
|
printf("\t\tRevision: %d\n",pSecDesc->Dacl->AclRevision);
|
|||
|
printf("\t\tSbz1: %d\n",pSecDesc->Dacl->Sbz1);
|
|||
|
printf("\t\tAclSize: %d\n",pSecDesc->Dacl->AclSize);
|
|||
|
|
|||
|
numAces = pSecDesc->Dacl->AclSize - 4;
|
|||
|
|
|||
|
for (i=0; i<numAces; i++) {
|
|||
|
//
|
|||
|
// NOTE: I couldn't get this to print out the right value in DOS16.
|
|||
|
// So I gave up. It puts the 04 into the AL register and then
|
|||
|
// clears the AH register, then pushes AX (both parts). But when
|
|||
|
// it prints, it only prints 0.
|
|||
|
//
|
|||
|
printf("\t\tACE%u: %u\n",i,(unsigned short)pSecDesc->Dacl->Dummy1[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
printf("\n\tDISCRETIONARY_ACL = NULL\n");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
MakeArgsUnicode (
|
|||
|
DWORD argc,
|
|||
|
PCHAR argv[]
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
|
|||
|
//
|
|||
|
// ScConvertToUnicode allocates storage for each string.
|
|||
|
// We will rely on process termination to free the memory.
|
|||
|
//
|
|||
|
for(i=0; i<argc; i++) {
|
|||
|
|
|||
|
if(!ConvertToUnicode( (LPWSTR *)&(argv[i]), argv[i])) {
|
|||
|
printf("Couldn't convert argv[%d] to unicode\n",i);
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
ConvertToUnicode(
|
|||
|
OUT LPWSTR *UnicodeOut,
|
|||
|
IN LPSTR AnsiIn
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function translates an AnsiString into a Unicode string.
|
|||
|
A new string buffer is created by this function. If the call to
|
|||
|
this function is successful, the caller must take responsibility for
|
|||
|
the unicode string buffer that was allocated by this function.
|
|||
|
The allocated buffer should be free'd with a call to LocalFree.
|
|||
|
|
|||
|
NOTE: This function allocates memory for the Unicode String.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AnsiIn - This is a pointer to an ansi string that is to be converted.
|
|||
|
|
|||
|
UnicodeOut - This is a pointer to a location where the pointer to the
|
|||
|
unicode string is to be placed.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - The conversion was successful.
|
|||
|
|
|||
|
FALSE - The conversion was unsuccessful. In this case a buffer for
|
|||
|
the unicode string was not allocated.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
NTSTATUS ntStatus;
|
|||
|
DWORD bufSize;
|
|||
|
UNICODE_STRING unicodeString;
|
|||
|
ANSI_STRING ansiString;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a buffer for the unicode string.
|
|||
|
//
|
|||
|
|
|||
|
bufSize = (strlen(AnsiIn)+1) * sizeof(WCHAR);
|
|||
|
|
|||
|
*UnicodeOut = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (UINT)bufSize);
|
|||
|
|
|||
|
if (*UnicodeOut == NULL) {
|
|||
|
printf("ScConvertToUnicode:LocalAlloc Failure %ld\n",GetLastError());
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the string structures
|
|||
|
//
|
|||
|
RtlInitAnsiString( &ansiString, AnsiIn);
|
|||
|
|
|||
|
unicodeString.Buffer = *UnicodeOut;
|
|||
|
unicodeString.MaximumLength = (USHORT)bufSize;
|
|||
|
unicodeString.Length = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Call the conversion function.
|
|||
|
//
|
|||
|
ntStatus = RtlAnsiStringToUnicodeString (
|
|||
|
&unicodeString, // Destination
|
|||
|
&ansiString, // Source
|
|||
|
(BOOLEAN)FALSE); // Allocate the destination
|
|||
|
|
|||
|
if (!NT_SUCCESS(ntStatus)) {
|
|||
|
|
|||
|
printf("ScConvertToUnicode:RtlAnsiStringToUnicodeString Failure %lx\n",
|
|||
|
ntStatus);
|
|||
|
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the pointer location with the unicode string buffer pointer.
|
|||
|
//
|
|||
|
*UnicodeOut = unicodeString.Buffer;
|
|||
|
|
|||
|
return(TRUE);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|