/**************************************************************************** PROGRAM: TOKEDIT.C PURPOSE: Displays and allows the user to edit the contents of a token ****************************************************************************/ #include "PVIEWP.h" #include "string.h" INT_PTR APIENTRY TokenEditDlgProc(HWND, UINT, WPARAM, LPARAM); INT_PTR APIENTRY MoreDlgProc(HWND, UINT, WPARAM, LPARAM); BOOL TokenEditDlgInit(HWND); BOOL TokenEditDlgEnd(HWND, BOOL); BOOL EnablePrivilege(HWND, BOOL); BOOL EnableGroup(HWND, BOOL); BOOL SetDefaultOwner(HWND); BOOL SetPrimaryGroup(HWND); BOOL MoreDlgInit(HWND hDlg, LPARAM lParam); BOOL DisplayMyToken(HWND); /**************************************************************************** FUNCTION: EditToken PURPOSE: Displays and allows the user to edit a token RETURNS: TRUE on success, FALSE on failure ****************************************************************************/ BOOL EditToken( HWND hwndParent, HANDLE Token, LPWSTR Name ) { DLGPROC lpProc; int Result; HANDLE hMyToken; HANDLE Instance; hMyToken = OpenMyToken(Token, Name); if (hMyToken == NULL) { return(FALSE); } // // Get the application instance handle // Instance = (HANDLE)(NtCurrentPeb()->ImageBaseAddress); ASSERT(Instance != 0); lpProc = (DLGPROC)MakeProcInstance(TokenEditDlgProc, Instance); Result = (int)DialogBoxParam(Instance,(LPSTR)IDD_MAIN, hwndParent, lpProc, (LPARAM)hMyToken); FreeProcInstance(lpProc); return(TRUE); } /**************************************************************************** FUNCTION: TokenEditDlgProc(HWND, unsigned, WORD, LONG) PURPOSE: Processes messages MESSAGES: WM_COMMAND - application menu (About dialog box) WM_DESTROY - destroy window COMMENTS: ****************************************************************************/ INT_PTR APIENTRY TokenEditDlgProc(hDlg, message, wParam, lParam) HWND hDlg; UINT message; WPARAM wParam; LPARAM lParam; { DLGPROC lpProc; HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA); switch (message) { case WM_INITDIALOG: SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); if (!TokenEditDlgInit(hDlg)) { // Failed to initialize dialog, get out EndDialog(hDlg, FALSE); } return (TRUE); case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: // we're done, drop through to quit dialog.... case IDCANCEL: TokenEditDlgEnd(hDlg, LOWORD(wParam) == IDOK); EndDialog(hDlg, TRUE); return TRUE; case IDB_DISABLEPRIVILEGE: case IDB_ENABLEPRIVILEGE: EnablePrivilege(hDlg, LOWORD(wParam) == IDB_ENABLEPRIVILEGE); return(TRUE); case IDB_DISABLEGROUP: case IDB_ENABLEGROUP: EnableGroup(hDlg, LOWORD(wParam) == IDB_ENABLEGROUP); return(TRUE); case IDC_DEFAULTOWNER: SetDefaultOwner(hDlg); return(TRUE); case IDC_PRIMARYGROUP: SetPrimaryGroup(hDlg); return(TRUE); case IDB_MORE: { HANDLE Instance = (HANDLE)(NtCurrentPeb()->ImageBaseAddress); lpProc = (DLGPROC)MakeProcInstance(MoreDlgProc, Instance); DialogBoxParam(Instance,(LPSTR)IDD_MORE, hDlg, lpProc, (LPARAM)hMyToken); FreeProcInstance(lpProc); return(TRUE); } case IDB_DEFAULT_DACL: { HANDLE Token = ((PMYTOKEN)hMyToken)->Token; LPWSTR Name = ((PMYTOKEN)hMyToken)->Name; EditTokenDefaultDacl(hDlg, Token, Name); return(TRUE); } default: // We didn't process this message return FALSE; } break; default: // We didn't process this message return FALSE; } // We processed the message return TRUE; } /**************************************************************************** FUNCTION: TokenEditDlgInit(HWND) PURPOSE: Initialises the controls in the main dialog window. RETURNS: TRUE on success, FALSE if dialog should be terminated. ****************************************************************************/ BOOL TokenEditDlgInit( HWND hDlg ) { HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA); WCHAR string[MAX_STRING_LENGTH]; HCURSOR OldCursor; if (!LsaInit()) { DbgPrint("PVIEW - LsaInit failed\n"); return(FALSE); } OldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); DisplayMyToken(hDlg); SetCursor(OldCursor); // // Set the dialog caption appropriately // GetWindowTextW(hDlg, string, sizeof(string)/sizeof(*string)); lstrcatW(string, L" for <"); lstrcatW(string, ((PMYTOKEN)hMyToken)->Name); lstrcatW(string, L">"); SetWindowTextW(hDlg, string); return(TRUE); } /**************************************************************************** FUNCTION: TokenEditDlgEnd(HWND) PURPOSE: Do whatever we have to do to clean up when dialog ends RETURNS: TRUE on success, FALSE on failure. ****************************************************************************/ BOOL TokenEditDlgEnd( HWND hDlg, BOOL fSaveChanges) { HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA); BOOL Success; Success = CloseMyToken(hDlg, hMyToken, fSaveChanges); LsaTerminate(); return(Success); } /**************************************************************************** FUNCTION: DisplayMyToken PURPOSE: Reads data out of mytoken and puts in dialog controls. RETURNS: TRUE on success, FALSE on failure ****************************************************************************/ BOOL DisplayMyToken( HWND hDlg ) { HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA); PMYTOKEN pMyToken = (PMYTOKEN)hMyToken; CHAR string[MAX_STRING_BYTES]; UINT GroupIndex; UINT PrivIndex; // // Groups // if (pMyToken->Groups != NULL) { for (GroupIndex=0; GroupIndex < pMyToken->Groups->GroupCount; GroupIndex++ ) { PSID Sid = pMyToken->Groups->Groups[GroupIndex].Sid; ULONG Attributes = pMyToken->Groups->Groups[GroupIndex].Attributes; USHORT ControlID; if (Attributes & SE_GROUP_ENABLED) { ControlID = IDL_ENABLEDGROUPS; } else { ControlID = IDL_DISABLEDGROUPS; } if (SID2Name(Sid, string, MAX_STRING_BYTES)) { // Add to disable or enabled group box AddLBItem(hDlg, ControlID, string, GroupIndex); // Add this group to default owner combo box if it's valid if (Attributes & SE_GROUP_OWNER) { AddCBItem(hDlg, IDC_DEFAULTOWNER, string, (LPARAM)Sid); } // Add this group to primary group combo box AddCBItem(hDlg, IDC_PRIMARYGROUP, string, (LPARAM)Sid); } else { DbgPrint("PVIEW: Failed to convert Group sid to string\n"); } } } else { DbgPrint("PVIEW : No group info in mytoken\n"); } // // User ID // if (pMyToken->UserId != NULL) { PSID Sid = pMyToken->UserId->User.Sid; if (SID2Name(Sid, string, MAX_STRING_BYTES)) { // Set user-name static text SetDlgItemText(hDlg, IDS_USERID, string); // Add to default owner combo box AddCBItem(hDlg, IDC_DEFAULTOWNER, string, (LPARAM)Sid); // Add to primary group combo box AddCBItem(hDlg, IDC_PRIMARYGROUP, string, (LPARAM)Sid); } else { DbgPrint("PVIEW: Failed to convert User ID SID to string\n"); } } else { DbgPrint("PVIEW: No user id in mytoken\n"); } // // Default Owner // if (pMyToken->DefaultOwner != NULL) { PSID Sid = pMyToken->DefaultOwner->Owner; if (SID2Name(Sid, string, MAX_STRING_BYTES)) { INT iItem; iItem = FindCBSid(hDlg, IDC_DEFAULTOWNER, Sid); if (iItem >= 0) { SendMessage(GetDlgItem(hDlg, IDC_DEFAULTOWNER), CB_SETCURSEL, iItem, 0); } else { DbgPrint("PVIEW: Default Owner is not userID or one of our groups\n"); } } else { DbgPrint("PVIEW: Failed to convert Default Owner SID to string\n"); } } else { DbgPrint("PVIEW: No default owner in mytoken\n"); } // // Primary group // if (pMyToken->PrimaryGroup != NULL) { PSID Sid = pMyToken->PrimaryGroup->PrimaryGroup; if (SID2Name(Sid, string, MAX_STRING_BYTES)) { INT iItem; iItem = FindCBSid(hDlg, IDC_PRIMARYGROUP, Sid); if (iItem < 0) { // Group is not already in combo-box, add it iItem = AddCBItem(hDlg, IDC_PRIMARYGROUP, string, (LPARAM)Sid); } // Select the primary group SendMessage(GetDlgItem(hDlg, IDC_PRIMARYGROUP), CB_SETCURSEL, iItem, 0); } else { DbgPrint("PVIEW: Failed to convert primary group SID to string\n"); } } else { DbgPrint("PVIEW: No primary group in mytoken\n"); } // // Privileges // if (pMyToken->Privileges != NULL) { for (PrivIndex=0; PrivIndex < pMyToken->Privileges->PrivilegeCount; PrivIndex++ ) { LUID Privilege = pMyToken->Privileges->Privileges[PrivIndex].Luid; ULONG Attributes = pMyToken->Privileges->Privileges[PrivIndex].Attributes; USHORT ControlID; if (Attributes & SE_PRIVILEGE_ENABLED) { ControlID = IDL_ENABLEDPRIVILEGES; } else { ControlID = IDL_DISABLEDPRIVILEGES; } if (PRIV2Name(Privilege, string, MAX_STRING_BYTES)) { // Add this privelege to the appropriate list-box AddLBItem(hDlg, ControlID, string, PrivIndex); } else { DbgPrint("PVIEW: Failed to convert privilege to string\n"); } } } else { DbgPrint("PVIEW: No privilege info in mytoken\n"); } return(TRUE); } /**************************************************************************** FUNCTION: EnablePrivilege(HWND, fEnable) PURPOSE: Enables or disables one or more privileges. If fEnable = TRUE, the selected privileges in the disabled privilege control are enabled. Vice versa for fEnable = FALSE RETURNS: TRUE on success, FALSE on failure ****************************************************************************/ BOOL EnablePrivilege( HWND hDlg, BOOL fEnable) { HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA); PMYTOKEN pMyToken = (PMYTOKEN)hMyToken; HWND hwndFrom; HWND hwndTo; USHORT idFrom; USHORT idTo; INT cItems; PINT pItems; PTOKEN_PRIVILEGES Privileges; Privileges = pMyToken->Privileges; if (Privileges == NULL) { return(FALSE); } // Calculate source and destination controls // if (fEnable) { idFrom = IDL_DISABLEDPRIVILEGES; idTo = IDL_ENABLEDPRIVILEGES; } else { idFrom = IDL_ENABLEDPRIVILEGES; idTo = IDL_DISABLEDPRIVILEGES; } hwndFrom = GetDlgItem(hDlg, idFrom); hwndTo = GetDlgItem(hDlg, idTo); // Find how many items are selected // cItems = (INT)SendMessage(hwndFrom, LB_GETSELCOUNT, 0, 0); if (cItems <= 0) { // No items selected return(TRUE); } // Allocate space for the item array // pItems = Alloc(cItems * sizeof(*pItems)); if (pItems == NULL) { return(FALSE); } // Read the selected items into the array // cItems = (INT)SendMessage(hwndFrom, LB_GETSELITEMS, (WPARAM)cItems, (LPARAM)pItems); if (cItems == LB_ERR) { // Something went wrong Free(pItems); return(FALSE); } while (cItems-- > 0) { INT iItem; UINT PrivIndex; UCHAR PrivilegeName[MAX_STRING_BYTES]; iItem = pItems[cItems]; // Read the item index from the selected item array // Read the text and data from the source item // PrivIndex = (UINT)SendMessage(hwndFrom, LB_GETITEMDATA, iItem, 0); SendMessage(hwndFrom, LB_GETTEXT, iItem, (LPARAM)PrivilegeName); // Delete item from source control // SendMessage(hwndFrom, LB_DELETESTRING, iItem, 0); // Add privilege to destination control // iItem = (INT)SendMessage(hwndTo, LB_ADDSTRING, 0, (LPARAM)PrivilegeName); SendMessage(hwndTo, LB_SETITEMDATA, iItem, (LPARAM)PrivIndex); // Modify global data structure to reflect change // if (fEnable) { Privileges->Privileges[PrivIndex].Attributes |= SE_PRIVILEGE_ENABLED; } else { Privileges->Privileges[PrivIndex].Attributes &= ~SE_PRIVILEGE_ENABLED; } } // Free up space allocated for selected item array Free(pItems); return(TRUE); } /**************************************************************************** FUNCTION: EnableGroup(HWND, fEnable) PURPOSE: Enables or disables one or more selected groups. If fEnable = TRUE, the selected groups in the disabled group control are enabled. If fEnable = FALSE the selected groups in the enabled group control are disabled. RETURNS: TRUE on success, FALSE on failure ****************************************************************************/ BOOL EnableGroup( HWND hDlg, BOOL fEnable) { HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA); PMYTOKEN pMyToken = (PMYTOKEN)hMyToken; HWND hwndFrom; HWND hwndTo; USHORT idFrom; USHORT idTo; INT cItems; PINT pItems; PTOKEN_GROUPS Groups; Groups = pMyToken->Groups; if (Groups == NULL) { return(FALSE); } // Calculate source and destination controls // if (fEnable) { idFrom = IDL_DISABLEDGROUPS; idTo = IDL_ENABLEDGROUPS; } else { idFrom = IDL_ENABLEDGROUPS; idTo = IDL_DISABLEDGROUPS; } hwndFrom = GetDlgItem(hDlg, idFrom); hwndTo = GetDlgItem(hDlg, idTo); // Find how many items are selected // cItems = (INT)SendMessage(hwndFrom, LB_GETSELCOUNT, 0, 0); if (cItems <= 0) { // No items selected return(TRUE); } // Allocate space for the item array // pItems = Alloc(cItems * sizeof(*pItems)); if (pItems == NULL) { return(FALSE); } // Read the selected items into the array // cItems = (INT)SendMessage(hwndFrom, LB_GETSELITEMS, (WPARAM)cItems, (LPARAM)pItems); if (cItems == LB_ERR) { // Something went wrong Free(pItems); return(FALSE); } while (cItems-- > 0) { INT iItem; UINT GroupIndex; UCHAR GroupName[MAX_STRING_BYTES]; iItem = pItems[cItems]; // Read the item index from the selected item array // Read the text and data from the source item // GroupIndex = (UINT)SendMessage(hwndFrom, LB_GETITEMDATA, iItem, 0); SendMessage(hwndFrom, LB_GETTEXT, iItem, (LPARAM)GroupName); // Check it's not a mandatory group (Can-not be disabled) // if (Groups->Groups[GroupIndex].Attributes & SE_GROUP_MANDATORY) { CHAR buf[256]; strcpy(buf, "'"); strcat(buf, GroupName); strcat(buf, "' is a mandatory group and cannot be disabled"); MessageBox(hDlg, buf, NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK); continue; // skip to next group } // Delete item from source control // SendMessage(hwndFrom, LB_DELETESTRING, iItem, 0); // Add item to destination control // iItem = (INT)SendMessage(hwndTo, LB_ADDSTRING, 0, (LPARAM)GroupName); SendMessage(hwndTo, LB_SETITEMDATA, iItem, (LONG)GroupIndex); // Modify global data structure to reflect change // if (fEnable) { Groups->Groups[GroupIndex].Attributes |= SE_GROUP_ENABLED; } else { Groups->Groups[GroupIndex].Attributes &= ~SE_GROUP_ENABLED; } } // Free up space allocated for selected item array Free(pItems); return(TRUE); } /**************************************************************************** FUNCTION: SetDefaultOwner() PURPOSE: Sets the default owner to the new value selected by the user. RETURNS: TRUE on success, FALSE on failure ****************************************************************************/ BOOL SetDefaultOwner( HWND hDlg) { HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA); PMYTOKEN pMyToken = (PMYTOKEN)hMyToken; HWND hwnd; INT iItem; PTOKEN_OWNER DefaultOwner; DefaultOwner = pMyToken->DefaultOwner; if (DefaultOwner == NULL) { return(FALSE); } hwnd = GetDlgItem(hDlg, IDC_DEFAULTOWNER); iItem = (INT)SendMessage(hwnd, CB_GETCURSEL, 0, 0); if (iItem == CB_ERR) { // No selection ? return(FALSE); } // Modify global data structure to reflect change DefaultOwner->Owner = (PSID)SendMessage(hwnd, CB_GETITEMDATA, iItem, 0); return(TRUE); } /**************************************************************************** FUNCTION: SetPrimaryGroup() PURPOSE: Sets the primary group to the new value selected by the user. RETURNS: TRUE on success, FALSE on failure ****************************************************************************/ BOOL SetPrimaryGroup( HWND hDlg) { HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA); PMYTOKEN pMyToken = (PMYTOKEN)hMyToken; HWND hwnd; INT iItem; PTOKEN_PRIMARY_GROUP PrimaryGroup; PrimaryGroup = pMyToken->PrimaryGroup; if (PrimaryGroup == NULL) { return(FALSE); } hwnd = GetDlgItem(hDlg, IDC_PRIMARYGROUP); iItem = (INT)SendMessage(hwnd, CB_GETCURSEL, 0, 0); if (iItem == CB_ERR) { // No selection ? return(FALSE); } // Modify global data structure to reflect change PrimaryGroup->PrimaryGroup = (PSID)SendMessage(hwnd, CB_GETITEMDATA, iItem, 0); return(TRUE); } /**************************************************************************** FUNCTION: MoreDlgProc(HWND, UINT, WPARAM, LPARAM) PURPOSE: Processes messages ****************************************************************************/ INT_PTR APIENTRY MoreDlgProc(hDlg, message, wParam, lParam) HWND hDlg; UINT message; WPARAM wParam; LPARAM lParam; { HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA); switch (message) { case WM_INITDIALOG: if (!MoreDlgInit(hDlg, lParam)) { // Failed to initialize dialog, get out EndDialog(hDlg, FALSE); } return (TRUE); case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: // we're done, drop through to quit dialog.... case IDCANCEL: EndDialog(hDlg, TRUE); return TRUE; break; default: // We didn't process this message return FALSE; break; } break; default: // We didn't process this message return FALSE; } // We processed the message return TRUE; } /**************************************************************************** FUNCTION: MoreDlgInit(HWND) PURPOSE: Initialises the controls in the more dialog window. RETURNS: TRUE on success, FALSE on failure ****************************************************************************/ BOOL MoreDlgInit( HWND hDlg, LPARAM lParam ) { TCHAR string[MAX_STRING_LENGTH]; HANDLE hMyToken = (HANDLE)lParam; PMYTOKEN pMyToken = (PMYTOKEN)hMyToken; PTOKEN_STATISTICS Statistics; PTOKEN_GROUPS Restrictions ; UINT GroupIndex; Statistics = pMyToken->TokenStats; if (Statistics == NULL) { DbgPrint("PVIEW: No token statistics in mytoken\n"); return(FALSE); } wsprintf(string, "0x%lx-%lx", pMyToken->TokenStats->AuthenticationId.HighPart, pMyToken->TokenStats->AuthenticationId.LowPart); SetDlgItemText(hDlg, IDS_LOGONSESSION, string); if (LUID2String(Statistics->TokenId, string, MAX_STRING_BYTES)) { SetDlgItemText(hDlg, IDS_TOKENID, string); } else { DbgPrint("PVIEW: Failed to convert tokenid luid to string\n"); } if (Time2String(Statistics->ExpirationTime, string, MAX_STRING_BYTES)) { SetDlgItemText(hDlg, IDS_EXPIRATIONTIME, string); } else { DbgPrint("PVIEW: Failed to convert expiration time to string\n"); } if (TokenType2String(Statistics->TokenType, string, MAX_STRING_BYTES)) { SetDlgItemText(hDlg, IDS_TOKENTYPE, string); } else { DbgPrint("PVIEW: Failed to convert token type to string\n"); } if (Statistics->TokenType == TokenPrimary) { SetDlgItemText(hDlg, IDS_IMPERSONATION, "N/A"); } else { if (ImpersonationLevel2String(Statistics->ImpersonationLevel, string, MAX_STRING_BYTES)) { SetDlgItemText(hDlg, IDS_IMPERSONATION, string); } else { DbgPrint("PVIEW: Failed to convert impersonation level to string\n"); } } if (Dynamic2String(Statistics->DynamicCharged, string, MAX_STRING_BYTES)) { SetDlgItemText(hDlg, IDS_DYNAMICCHARGED, string); } else { DbgPrint("PVIEW: Failed to convert dynamic charged to string\n"); } if (Dynamic2String(Statistics->DynamicAvailable, string, MAX_STRING_BYTES)) { SetDlgItemText(hDlg, IDS_DYNAMICAVAILABLE, string); } else { DbgPrint("PVIEW: Failed to convert dynamic available to string\n"); } if (LUID2String(Statistics->ModifiedId, string, MAX_STRING_BYTES)) { SetDlgItemText(hDlg, IDS_MODIFIEDID, string); } else { DbgPrint("PVIEW: Failed to convert modifiedid luid to string\n"); } Restrictions = pMyToken->RestrictedSids ; if ( Restrictions && (Restrictions->GroupCount) ) { for (GroupIndex=0; GroupIndex < Restrictions->GroupCount; GroupIndex++ ) { PSID Sid = Restrictions->Groups[GroupIndex].Sid; ULONG Attributes = Restrictions->Groups[GroupIndex].Attributes; if (SID2Name(Sid, string, MAX_STRING_BYTES)) { // Add to disable or enabled group box AddLBItem(hDlg, IDS_RESTRICTEDSIDS, string, GroupIndex); } else { DbgPrint("PVIEW: Failed to convert Group sid to string\n"); } } } else { AddLBItem( hDlg, IDS_RESTRICTEDSIDS, TEXT("None"), 0 ); } return(TRUE); }