Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

458 lines
10 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
roshare.c
Abstract:
This program is a quick-and-dirty app that allows a readonly ACL to
be placed on a local server share. The ACL allows everyone Read
access only.
Author:
Chuck Lenzmeier (chuckl) 20-Sep-1992
Revision History:
--*/
#define UNICODE 1
#define VERBOSE 0
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <lm.h>
#include <stdio.h>
//#include <string.h>
#define MAX_NAMES 60
BOOL
FindSid(
LPTSTR Name,
PSID *Sid
);
VOID
DumpSid(
LPTSTR String,
PISID Sid
);
BOOL
ConstructAcl(
PACL *acl,
LPTSTR Names[],
ULONG Index
);
__cdecl
main (
int argc,
char *argv[]
)
{
ANSI_STRING ansiShareName;
UNICODE_STRING shareName;
LPSHARE_INFO_502 shi502;
SECURITY_DESCRIPTOR desc;
DWORD aclBuffer[256/4];
PACL acl = (PACL)aclBuffer;
SID_IDENTIFIER_AUTHORITY worldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
PSID sid;
ACCESS_MASK mask;
int i;
BOOL ok;
NTSTATUS status;
DWORD error;
DWORD parmerr;
LPTSTR Names[MAX_NAMES];
BOOL ExplicitNames = FALSE;
ULONG Index;
//
// Make sure at least one share name was specified.
//
if ( argc < 2 ) goto usage;
//
// Initialize the security descriptor and the ACL.
//
ok = InitializeSecurityDescriptor( &desc, SECURITY_DESCRIPTOR_REVISION );
if ( !ok ) {
error = GetLastError();
printf( "InitializeSecurityDescriptor failed: %d\n", error );
return error;
}
ok = InitializeAcl( acl, 256, ACL_REVISION );
if ( !ok ) {
error = GetLastError();
printf( "InitializeAcl failed: %d\n", error );
return error;
}
//
// Check to see if there are any usernames specified for
// the ACL.
//
if ( _stricmp( argv[1], "-u") == 0 ) {
#if VERBOSE
printf("Processing names\n");
#endif
ExplicitNames = TRUE;
i=2; // skip the argument
Index = 0;
while ( (_stricmp(argv[i], "-s") != 0) && (Index < MAX_NAMES)) {
Names[Index++] = (LPTSTR)argv[i++];
}
if ( Index > 0 ) {
ok = ConstructAcl( &acl, Names, Index );
if ( !ok ) {
fprintf(stderr, "Unable to create ACL, quitting\n");
return( ERROR_INVALID_PARAMETER );
}
} else {
goto usage;
}
} else {
#if VERBOSE
printf("No names\n");
#endif
//
// Get the SID for World (aka Everyone).
//
ok = AllocateAndInitializeSid(
&worldSidAuthority,
1,
SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
&sid
);
if ( !ok ) {
error = GetLastError();
printf( "AllocateAndInitializeSid failed: %d\n", error );
return error;
}
//
// Add an ACE that allows World read access.
//
mask = GENERIC_READ | GENERIC_EXECUTE;
ok = AddAccessAllowedAce( acl, ACL_REVISION, mask, sid );
if ( !ok ) {
error = GetLastError();
printf( "AddAccessAllowedAce failed: %d\n", error );
return error;
}
}
//
// Associate the ACL with the security descriptor.
//
ok = SetSecurityDescriptorDacl( &desc, TRUE, acl, FALSE );
if ( !ok ) {
error = GetLastError();
printf( "SetSecurityDescriptorDacl failed: %d\n", error );
return error;
}
//
// For each share in the argument list, add the ACL to the share.
// Note that this will override a preexisting ACL.
//
for ( i = (ExplicitNames ? i+1 : 1) ; i < argc; i++ ) {
//
// Convert the share name to Unicode.
//
RtlInitAnsiString( &ansiShareName, argv[i] );
status = RtlAnsiStringToUnicodeString(
&shareName,
&ansiShareName,
TRUE
);
if ( !NT_SUCCESS(status) ) {
printf( "Error converting string %s to Unicode: %x\n",
argv[i], status );
continue;
}
//
// Get the current share information. If the share doesn't
// exist, continue with the next one in the list.
//
error = NetShareGetInfo(
NULL,
shareName.Buffer,
502,
(LPBYTE *)&shi502 );
if ( error == NERR_NetNameNotFound ) {
printf( "Share %s doesn't exist\n", argv[i] );
continue;
}
if ( error == ERROR_ACCESS_DENIED ) {
printf( "Access denied. Log in as an admin or power user\n" );
break;
}
if ( error != NO_ERROR ) {
printf( "Unable to get info for share %s: %d\n",
argv[i], error );
continue;
}
//
// Change the security descriptor for the share and set the new
// information.
//
shi502->shi502_security_descriptor = &desc;
error = NetShareSetInfo(
NULL,
shareName.Buffer,
502,
(LPBYTE)shi502,
&parmerr
);
if ( error == NERR_NetNameNotFound ) {
printf( "Share %s doesn't exist\n", argv[i] );
continue;
}
if ( error == ERROR_ACCESS_DENIED ) {
printf( "Access denied. Log in as an admin or power user\n" );
break;
}
if ( error != NO_ERROR ) {
printf( "Unable to set info for share %s: %d, %d\n",
argv[i], error, parmerr );
continue;
}
printf( "Readonly ACL added to share %s\n", argv[i] );
} // for ( i = 1; i < argc; i++ )
return NO_ERROR;
usage:
printf( "Usage: %s [-u domain\\name1 [domain\\name2]... -s ] share [share]...\n", argv[0] );
return ERROR_INVALID_PARAMETER;
}
BOOL
FindSid(
LPTSTR Name,
PSID *Sid
)
{
DWORD SidLength = 0;
TCHAR DomainName[256];
DWORD DomainNameLength = 256;
SID_NAME_USE Use;
BOOL Result;
UNICODE_STRING UName;
ANSI_STRING AName;
NTSTATUS status;
printf("\nName: %s\n",Name);
//
// Convert name to unicode
//
RtlInitAnsiString( &AName, (PCSZ)Name );
status = RtlAnsiStringToUnicodeString(
&UName,
&AName,
TRUE
);
if ( !NT_SUCCESS(status) ) {
printf( "Error converting string %s to Unicode: %x\n",
Name, status );
return( FALSE );
}
Result = LookupAccountName(
NULL,
UName.Buffer,
(PSID)NULL,
&SidLength,
DomainName,
&DomainNameLength,
&Use
);
if ( !Result && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) ) {
*Sid = LocalAlloc( 0, SidLength );
Result = LookupAccountName(
NULL,
UName.Buffer,
*Sid,
&SidLength,
DomainName,
&DomainNameLength,
&Use
);
if ( !Result) {
printf("2nd Lookup %s failed, error = %d\n",Name,GetLastError());
} else {
#if VERBOSE
DumpSid( "2nd Lookup worked\n", (PISID)(*Sid) );
#endif
}
} else {
printf("1st Lookup %s failed, error = %d\n",Name,GetLastError());
}
return( Result );
}
#if VERBOSE
VOID
DumpSid(
LPTSTR String,
PISID Sid
)
{
char tab[80];
int i;
PULONG psa;
printf(String);
memset(tab, ' ', strlen(String));
tab[strlen(String)] = 0;
printf( "Revision : %d\n"
"%s"
"SubAuthorityCount : %d\n"
"%s"
"IdentifierAuthority : %d-%d-%d-%d-%d-%d\n",
Sid->Revision,
tab,
Sid->SubAuthorityCount,
tab,
((PUCHAR)&Sid->IdentifierAuthority)[0],
((PUCHAR)&Sid->IdentifierAuthority)[1],
((PUCHAR)&Sid->IdentifierAuthority)[2],
((PUCHAR)&Sid->IdentifierAuthority)[3],
((PUCHAR)&Sid->IdentifierAuthority)[4],
((PUCHAR)&Sid->IdentifierAuthority)[5]
);
psa = (PULONG)&Sid->SubAuthority;
for (i=0; i<(int)Sid->SubAuthorityCount; ++i) {
printf(
"%s"
"SubAuthority : %d\n",
tab,
*psa++
);
}
}
#endif
BOOL
ConstructAcl(
PACL *acl,
LPTSTR Names[],
ULONG Index
)
{
ULONG i;
PSID Sids[MAX_NAMES];
ULONG TotalSidLength = 0;
ULONG TotalAclLength = 0;
BOOL Result;
DWORD error;
for ( i=0; i<Index ; i++) {
Result = FindSid( Names[i], &Sids[i] );
if ( !Result ) {
fprintf(stderr, "Unable to map name %s, quitting\n", Names[i]);
return( FALSE );
} else {
TotalSidLength += GetLengthSid( Sids[i] );
}
}
//
// This is a slight overestimate
//
TotalAclLength = TotalSidLength +
sizeof( ACL ) +
Index * sizeof( ACCESS_ALLOWED_ACE );
*acl = LocalAlloc( 0, TotalAclLength );
if ( *acl == NULL ) {
fprintf(stderr, "Out of memory\n");
return( FALSE );
}
Result = InitializeAcl( *acl, TotalAclLength, ACL_REVISION );
//
// This should not fail
//
if ( !Result ) {
error = GetLastError();
fprintf( stderr, "InitializeAcl failed: %d\n", error );
return FALSE;
}
for ( i=0; i<Index ; i++) {
Result = AddAccessAllowedAce( *acl,
ACL_REVISION,
GENERIC_READ | GENERIC_EXECUTE,
Sids[i]
);
if ( !Result ) {
error = GetLastError();
fprintf( stderr, "AddAccessAllowedAce failed: %d\n", error );
return FALSE;
}
}
return( TRUE );
}