/*++ MAPUSER.CXX Copyright (C) 1999 Microsoft Corporation, all rights reserved. DESCRIPTION: code for MapUser() Created, May 21, 1999 by DavidCHR. --*/ #include "everything.hxx" extern "C" { #include // alloca #include "..\keytab2\keytab\ldlib\delegtools.h" } static CHAR AltSecId[] = "AltSecurityIdentities"; static CHAR AltSecPrefix[] = "KERBEROS:"; static CHAR PreQuery[] = "(objectClass=user)"; /* For performance reasons, we should query an indexed type */ NTSTATUS MapUserInDirectory( IN LPWSTR Principal, IN OPTIONAL LPWSTR Account ) { LPSTR Attributes[] = { NULL }; // request no attributes PCHAR PrincValues[] = { NULL, NULL }; LDAPModA TheMod = { LDAP_MOD_DELETE, AltSecId, PrincValues }; PLDAPModA Mods[] = { &TheMod, NULL }; CHAR SearchBuffer [ UNLEN + 100 ]; /* The most we could have to search for is UNLEN (for either the principalname or the accountname) + 100 for the semantics of the query */ NTSTATUS ret = STATUS_INTERNAL_ERROR; LPSTR ObjectDn; ULONG lderr; if ( ( lstrcmpW( Principal, L"*" ) == 0 ) || ( Account && ( lstrcmpW( Account, L"*" ) == 0 ) ) ) { printf( "Wildcard account mappings are not supported" " at the domain level.\n" ); return STATUS_NOT_SUPPORTED; } if ( ConnectedToDsa() ) { if ( Account ) { // changing the attribute -- search for the account wsprintfA( SearchBuffer, "(& %hs (samAccountName=%ws))", PreQuery, Account ); } else { // deleting the attribute -- search for the attr wsprintfA( SearchBuffer, "(& %hs (%hs=%hs%ws))", PreQuery, AltSecId, AltSecPrefix, Principal ); } if ( LdapSearchForUniqueDnA( GlobalLdap, SearchBuffer, Attributes, &ObjectDn, NULL ) ) { PrincValues[ 0 ] = (PCHAR) alloca( lstrlenW( Principal ) + 30 ); if ( !PrincValues[ 0 ] ) { return STATUS_NO_MEMORY; /* NOTE: 73954: This leaks, but the app terminates immediately afterwards, so we don't actually care. */ } wsprintfA( PrincValues[ 0 ], "%hs%ws", AltSecPrefix, Principal ); if ( Account ) { TheMod.mod_op = LDAP_MOD_ADD; } else { TheMod.mod_op = LDAP_MOD_DELETE; } lderr = ldap_modify_sA( GlobalLdap, ObjectDn, Mods ); // special-case output here: switch( lderr ) { case LDAP_SUCCESS: printf( "Mapping %hs successfully.\n", Account ? "created" : "deleted" ); ret = STATUS_SUCCESS; break; default: printf( "Failed to %hs %hs on %hs; error 0x%x.\n", Account ? "set" : "delete", AltSecId, ObjectDn, lderr ); ret = STATUS_UNSUCCESSFUL; break; } free( ObjectDn ); } else { printf( "Could not locate the account mapping in the directory.\n" ); } } return ret; } NTSTATUS MapUserInRegistry( IN LPWSTR Principal, IN OPTIONAL LPWSTR Account ) { DWORD RegErr; HKEY KerbHandle = NULL; HKEY UserListHandle = NULL; DWORD Disposition; RegErr = OpenKerberosKey(&KerbHandle); if (RegErr) { goto Cleanup; } RegErr = RegCreateKeyEx( KerbHandle, L"UserList", 0, NULL, 0, // no options KEY_CREATE_SUB_KEY | KEY_SET_VALUE, NULL, &UserListHandle, &Disposition ); if (RegErr) { printf("Failed to create UserList key: %d\n",RegErr); goto Cleanup; } if ( Account && Account[0] ) { RegErr = RegSetValueEx( UserListHandle, Principal, 0, REG_SZ, (PBYTE) Account, (wcslen(Account) + 1) * sizeof(WCHAR) ); if (RegErr) { printf("Failed to set name mapping value: %d\n",RegErr); goto Cleanup; } } else { /* if no second parameter was supplied, delete the mapping. */ RegErr = RegDeleteValue( UserListHandle, Principal ); switch( RegErr ) { case ERROR_PATH_NOT_FOUND: case ERROR_FILE_NOT_FOUND: RegErr = ERROR_SUCCESS; // fallthrough to success case case ERROR_SUCCESS: break; default: printf( "Failed to delete mapping for %ws: error 0x%x.\n", Principal, RegErr ); goto Cleanup; } } Cleanup: if (KerbHandle) { RegCloseKey(KerbHandle); } if (UserListHandle) { RegCloseKey(UserListHandle); } if (RegErr) { return(STATUS_UNSUCCESSFUL); } return(STATUS_SUCCESS); } NTSTATUS MapUser( IN LPWSTR * Parameters ) { return ( GlobalDomainSetting ? MapUserInDirectory : MapUserInRegistry )( Parameters[ 0 ], Parameters[ 1 ] ); }