/*++ REALMFLAGS.CXX Copyright (C) 1999 Microsoft Corporation, all rights reserved. DESCRIPTION: realm-flag manipulation code. Created, Jan 10, 2000 by DavidCHR. CONTENTS: CompareFlagIds VerboselyPrintAndRemoveFlagsById LookupRealmFlagByName PrintAndRemoveFlagNames SearchRealmFlagListByAttribute CompareFlagNames --*/ #include "everything.hxx" typedef struct { ULONG Id; // from kerberos\client2\mitutil.h LPWSTR Name; // short string identifier LPSTR Explanation; // what this flag does. LPSTR MoreExplanation; // if you have to run to the next line. } KERB_REALM_FLAG_MAPPING, *PKERB_REALM_FLAG_MAPPING; /* These flags are defined in kerberos\client2\mitutil.h. However, there's other gunk in there that I'd rather not copy out so I'll just duplicate them. I'd consider auto-generating code fragments from the file to keep this file instantly up-to-date, but it wouldn't be guaranteed to provide human readable information */ KERB_REALM_FLAG_MAPPING KerbRealmFlagMappings[] = { /* The order of "none" in the list is important. It must be before any of the other flags so that code that handles multiple flags as a mask will not hit this unless the whole mask is zero. */ { 0x0, L"None", "No Realm Flags" }, { 0x1, L"SendAddress", "Include IP numbers within tickets.", "Useful for solving SOME compatibility issues." }, { 0x2, L"TcpSupported", "Indicates that this realm supports TCP.", "(as opposed to just UDP)" }, { 0x4, L"Delegate", "Everyone in this realm is trusted for delegation" }, { 0x8, L"NcSupported", "This realm supports Name Canonicalization" }, }; ULONG RealmFlagCount = ( sizeof( KerbRealmFlagMappings ) / sizeof( KerbRealmFlagMappings[ 0 ] ) ); /* NOTES on REALMLISTCOMPAREFUNCTION: If your REALMLISTCOMPAREFUNCTION is designed to return multiple mappings or interpret multiple mappings (e.g. as a mask), then you must special case "None" in the array above. Otherwise, your output may include "none", which doesn't make any sense. */ typedef BOOL REALMLISTCOMPAREFUNCTION( IN PVOID, // pvAttribute IN PKERB_REALM_FLAG_MAPPING ); /*++************************************************************** NAME: CompareFlagIds compares a flag map to a flag id. pvAttribute is a pointer to the desired flag id. RETURNS: TRUE if this is the correct flagid FALSE otherwise. CREATED: Jan 10, 2000 CALLED BY: SearchRealmFlagListByAttribute FREE WITH: n/a -- no resources are allocated **************************************************************--*/ BOOL // REALMLISTCOMPAREFUNCTION CompareFlagIds( IN PVOID pvAttribute, IN PKERB_REALM_FLAG_MAPPING pMap ) { return ( pMap->Id == *(( PULONG ) pvAttribute) ); } /*++************************************************************** NAME: CompareFlagNames Compares a mapping to a string for the flagname. RETURNS: TRUE if this mapping corresponds to the given string FALSE otherwise. CREATED: Jan 10, 2000 CALLED BY: SearchRealmFlagListByAttribute FREE WITH: n/a -- no resources are allocated **************************************************************--*/ BOOL // REALMLISTCOMPAREFUNCTION CompareFlagNames( IN PVOID pvAttribute, IN PKERB_REALM_FLAG_MAPPING pMap ) { return ( 0 == _wcsicmp( (LPWSTR) pvAttribute, pMap->Name ) ); } /*++************************************************************** NAME: PrintAndRemoveFlagsById if the flag id matches, it is removed from the passed-in value, and the flagname is printed. MODIFIES: pvAttribute -- may be stripped of a bit TAKES: pvAttribute -- flagId to check pMap -- table entry to check against RETURNS: TRUE if pvAttribute is zero (stop searching) FALSE otherwise (keep searching) CREATED: Jan 10, 2000 CALLED BY: SearchRealmFlagListByAttribute FREE WITH: n/a -- no resources are allocated **************************************************************--*/ BOOL PrintAndRemoveFlagsById( IN PVOID pvAttribute, IN PKERB_REALM_FLAG_MAPPING pMap ) { if ( !pMap->Id ) { /* We special-case "none" so that we only print it if there are no other flags-- if other flags exist, "none" will be skipped over in the array */ if ( !*(( PULONG ) pvAttribute ) ) { printf( " %ws", pMap->Name ); return TRUE; } else { return FALSE; } } if ( ( *(( PULONG ) pvAttribute) & pMap->Id ) == pMap->Id ) { *( (PULONG) pvAttribute ) &= ~pMap->Id; printf( " %ws", pMap->Name ); } return *( (PULONG) pvAttribute ) == 0; } /*++************************************************************** NAME: VerboselyPrintAndRemoveFlagsById like PrintAndRemoveFlagsById, but it also dumps the flag id and explanation field. LOGGING: lots of it. CREATED: Jan 10, 2000 CALLED BY: SearchRealmFlagListByAttribute FREE WITH: n/a -- no resources are allocated **************************************************************--*/ BOOL VerboselyPrintAndRemoveFlagsById( IN PVOID pvAttribute, IN PKERB_REALM_FLAG_MAPPING pMap ) { #if 0 if ( !pMap->Id ) { /* We special-case "none" so that we only print it if there are no other flags-- if other flags exist, "none" will be skipped over in the array */ if ( !*(( PULONG ) pvAttribute ) ) { printf( "0x%02x %ws \t%hs\n", pMap->Id, pMap->Name, pMap->Explanation ); return TRUE; } else { return FALSE; } } #endif if ( ( *(( PULONG ) pvAttribute) & pMap->Id ) == pMap->Id ) { *( (PULONG) pvAttribute ) &= ~pMap->Id; printf( "0x%02x %-12ws %hs\n", pMap->Id, pMap->Name, pMap->Explanation ); if ( pMap->MoreExplanation ) { printf( "%-17hs %hs\n", "", pMap->MoreExplanation ); } } return *( (PULONG) pvAttribute ) == 0; } /*++************************************************************** NAME: SearchRealmFlagListByAttribute searches the realmlist for a particular attribute. MODIFIES: ppMapping -- receives the given mapping. TAKES: pvAttribute -- attribute value to search for pFunc -- function to use to find it RETURNS: TRUE if the value could be found FALSE otherwise. LASTERROR: not set LOGGING: none CREATED: Jan 10, 2000 LOCKING: none CALLED BY: anyone FREE WITH: n/a -- no resources are allocated **************************************************************--*/ BOOL SearchRealmFlagListByAttribute( IN PVOID pvAttribute, IN REALMLISTCOMPAREFUNCTION *pFunc, OUT PKERB_REALM_FLAG_MAPPING *ppMapping ) { ULONG i; PKERB_REALM_FLAG_MAPPING pMapping = &KerbRealmFlagMappings[ 0 ]; for ( i = 0 ; i < RealmFlagCount ; i ++, pMapping++ ) { if ( pFunc( pvAttribute, pMapping ) ) { if ( ppMapping ) *ppMapping = pMapping; return TRUE; } } return FALSE; } /*++************************************************************** NAME: LookupRealmFlagByName given a name, maps it to a realm flag mapping structure MODIFIES: ppMapping -- receives the entry pointer TAKES: RealmFlagName -- name for which to search RETURNS: TRUE if the realmflag could be found. FALSE otherwise. LASTERROR: LOGGING: CREATED: Jan 10, 2000 LOCKING: CALLED BY: anyone FREE WITH: n/a -- no resources are allocated **************************************************************--*/ BOOL LookupRealmFlagByName( IN LPWSTR RealmFlagName, OUT PKERB_REALM_FLAG_MAPPING *ppMapping ) { return SearchRealmFlagListByAttribute( RealmFlagName, CompareFlagNames, ppMapping ); } VOID PrintRealmFlags( IN ULONG RealmFlags ) { ULONG i; ULONG ioFlags = RealmFlags; if ( RealmFlags == 0 ) { printf( " none" ); } else { if ( !SearchRealmFlagListByAttribute( &ioFlags, PrintAndRemoveFlagsById, NULL ) ) { printf( " [unknown" ); if ( ioFlags != RealmFlags ) { printf( ": 0x%x", ioFlags ); } printf( "]" ); } } } NTSTATUS ListRealmFlags( LPWSTR * Ignored) { ULONG RealmFlags = ~0; printf( "\n" "Ksetup knows the following realm flags: \n" ); SearchRealmFlagListByAttribute( &RealmFlags, VerboselyPrintAndRemoveFlagsById, NULL ); printf( "\n" ); exit( 0 ); /* Jump out. */ return STATUS_SUCCESS; } NTSTATUS GetRealmFlags( IN LPWSTR RealmName, OUT PULONG pulRealmFlags ) { HKEY hKey; NTSTATUS N = STATUS_UNSUCCESSFUL; DWORD dwErr, Type, Len = sizeof( *pulRealmFlags ); dwErr = OpenSubKey( &RealmName, &hKey ); if ( dwErr == ERROR_SUCCESS ) { dwErr = RegQueryValueEx( hKey, KERB_DOMAIN_REALM_FLAGS_VALUE, NULL, // mbz &Type, (LPBYTE) pulRealmFlags, &Len ); switch ( dwErr ) { case ERROR_SUCCESS: N = STATUS_SUCCESS; break; case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: /* 453545: if the realm flags aren't specified, don't complain about it. */ N = STATUS_SUCCESS; *pulRealmFlags = 0; break; default: printf( "Failed to query %ws for %ws: 0x%x\n", KERB_DOMAIN_REALM_FLAGS_VALUE, RealmName, dwErr ); } RegCloseKey( hKey ); } // else error has already been printed. return N; } NTSTATUS SetRealmFlags( IN LPWSTR RealmName, IN ULONG ulRealmFlags ) { HKEY hKey; NTSTATUS N = STATUS_UNSUCCESSFUL; DWORD dwErr, Len = sizeof( ulRealmFlags ); dwErr = OpenSubKey( &RealmName, &hKey ); if ( dwErr == ERROR_SUCCESS ) { dwErr = RegSetValueEx( hKey, KERB_DOMAIN_REALM_FLAGS_VALUE, NULL, // mbz REG_DWORD, (LPBYTE) &ulRealmFlags, Len ); switch ( dwErr ) { case ERROR_SUCCESS: DEBUGPRINT( DEBUG_REGISTRY, ( "Set Realm Flags for %ws to 0x%x\n", RealmName, ulRealmFlags ) ) ; N = STATUS_SUCCESS; break; default: printf( "Failed to write %ws for %ws: 0x%x\n", KERB_DOMAIN_REALM_FLAGS_VALUE, RealmName, dwErr ); } RegCloseKey( hKey ); } // else error has already been printed. return N; } NTSTATUS ResolveRealmFlags( IN LPWSTR *Params, IN OUT PULONG pulFlags ) { ULONG id; LPWSTR Cursor, *pFlagCursor = Params; PKERB_REALM_FLAG_MAPPING pMap; NTSTATUS N = STATUS_SUCCESS; do { DEBUGPRINT( DEBUG_OPTIONS, ( "Checking realmflag \"%ws\"...\n", *pFlagCursor ) ); // first, try to convert to hex. id = wcstoul( *pFlagCursor, &Cursor, 0 ); // use defaults if ( *Cursor != '\0' ) { if ( !LookupRealmFlagByName( *pFlagCursor, &pMap ) ) { printf( "Unknown Realm Flag: \"%ws\"\n", *pFlagCursor ); N = STATUS_INVALID_PARAMETER; break; } else { id = pMap->Id; } } // otherwise, the work's already been done. pFlagCursor++; *pulFlags |= id; } while( *pFlagCursor != NULL ); return N; } NTSTATUS SetRealmFlags( IN LPWSTR *Params ) { LPWSTR RealmName = Params[ 0 ]; ULONG RealmFlags = 0; NTSTATUS N = STATUS_SUCCESS; // 279621: this was uninitialized. if( Params[1] != NULL ) { N = ResolveRealmFlags( Params+1, &RealmFlags ); if ( NT_SUCCESS( N ) ) { N = SetRealmFlags( RealmName, RealmFlags ); } } else // Clear all realm flags { SetRealmFlags( RealmName, 0 ); } return N; } NTSTATUS AddRealmFlags( IN LPWSTR *Params ) { LPWSTR RealmName = Params[ 0 ]; ULONG RealmFlags = 0; NTSTATUS N; N = GetRealmFlags( RealmName, &RealmFlags ); if ( NT_SUCCESS( N ) ) { N = ResolveRealmFlags( Params+1, &RealmFlags ); if ( NT_SUCCESS( N ) ) { N = SetRealmFlags( RealmName, RealmFlags ); } } return N; } NTSTATUS DelRealmFlags( IN LPWSTR *Params ) { LPWSTR RealmName = Params[ 0 ]; ULONG RealmFlags = 0; ULONG DeleteFlags = 0; NTSTATUS N; N = GetRealmFlags( RealmName, &RealmFlags ); if ( NT_SUCCESS( N ) ) { N = ResolveRealmFlags( Params+1, &DeleteFlags ); if ( NT_SUCCESS( N ) ) { N = SetRealmFlags( RealmName, RealmFlags &~ DeleteFlags ); } } return N; }