/*++ 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 #include #include #include #include #include //#include #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