diff --git a/src/adldap/ad_defines.h b/src/adldap/ad_defines.h index 825b6209e..d68e59bfa 100644 --- a/src/adldap/ad_defines.h +++ b/src/adldap/ad_defines.h @@ -149,6 +149,10 @@ enum SystemFlagsBit { #define ATTRIBUTE_MAX_PWD_AGE "maxPwdAge" #define ATTRIBUTE_MIN_PWD_AGE "minPwdAge" #define ATTRIBUTE_LOCKOUT_DURATION "lockoutDuration" +#define ATTRIBUTE_PWD_PROPERTIES "pwdProperties" +#define ATTRIBUTE_PWD_HISTORY_LENGTH "pwdHistoryLength" +#define ATTRIBUTE_MIN_PWD_LENGTH "minPwdLength" +#define ATTRIBUTE_LOCKOUT_THRESHOLD "lockoutThreshold" #define ATTRIBUTE_IS_CRITICAL_SYSTEM_OBJECT "isCriticalSystemObject" #define ATTRIBUTE_GPC_FILE_SYS_PATH "gPCFileSysPath" #define ATTRIBUTE_GPC_FUNCTIONALITY_VERSION "gpCFunctionalityVersion" @@ -407,6 +411,13 @@ const long long MILLIS_TO_100_NANOS = 10000LL; #define ETYPES_AES128_CTS_HMAC_SHA1_96 0x00000008 #define ETYPES_AES256_CTS_HMAC_SHA1_96 0x00000010 +#define SAM_MASK_DOMAIN_PASSWORD_COMPLEX 1 +#define SAM_MASK_DOMAIN_PASSWORD_NO_ANON_CHANGE 2 +#define SAM_MASK_DOMAIN_PASSWORD_NO_CLEAR_CHANGE 4 +#define SAM_MASK_DOMAIN_LOCKOUT_ADMINS 8 +#define SAM_MASK_DOMAIN_PASSWORD_STORE_CLEARTEXT 16 +#define SAM_MASK_DOMAIN_REFUSE_PASSWORD_CHANGE 32 + enum SearchScope { SearchScope_Object, SearchScope_Children, diff --git a/src/admc/CMakeLists.txt b/src/admc/CMakeLists.txt index b1e0c9197..a644cdbda 100644 --- a/src/admc/CMakeLists.txt +++ b/src/admc/CMakeLists.txt @@ -254,6 +254,7 @@ set(ADMC_SOURCES console_impls/policy_ou_impl.cpp console_impls/found_policy_impl.cpp console_impls/domain_info_impl.cpp + console_impls/password_settings_impl.cpp permission_control_widgets/permissions_widget.cpp permission_control_widgets/creation_deletion_permissions_widget.cpp diff --git a/src/admc/admc_en.ts b/src/admc/admc_en.ts index 3afdd52bf..55e141c79 100644 --- a/src/admc/admc_en.ts +++ b/src/admc/admc_en.ts @@ -15,8 +15,9 @@ - Copyright (C) 2022 BaseALT Ltd. - + Copyright (C) 2025 BaseALT Ltd. + Copyright (C) 2022 BaseALT Ltd. + @@ -105,50 +106,60 @@ - + Account disabled - + User cannot change password - + User must change password on next logon - + Don't expire password - + Store password using reversible encryption - + Smartcard is required for interactive logon - + Account is sensitive and cannot be delegated - + Use Kerberos DES encryption types for this account - + Don't require Kerberos pre-authentication + + + Password settings: + + + + + PLACEHOLDER + + AddressMultiTab @@ -214,12 +225,12 @@ AllPoliciesFolderImpl - + Create policy - + Name @@ -227,23 +238,23 @@ AttributeDialog - + View - + Edit - + %1 Multi-Valued %2 This is a dialog title for attribute editors. Example: "Edit Multi-Valued String" - + Attribute: %1 @@ -261,7 +272,17 @@ - + + Loads optional attribute values + + + + + Load optional attributes + + + + Filter @@ -269,20 +290,25 @@ AttributesTabEdit - + Name - + Value - + Type + + + Copy + + AttributesTabFilterMenu @@ -348,7 +374,7 @@ - + Failed to open changelog file. @@ -403,33 +429,93 @@ - Host: - + Domain: + - - No hosts found. - + + Get hosts from default kerberos credential cache. + + + + + Default: + + + + + Get custom domain hosts. + + + + + CUSTOM.DOMAIN.COM + - - Select: + + Find hosts + + + + + Restore defaults + + + + + No hosts found. - + Custom: - + + never + + + + + hard + + + + + demand + + + + + allow + + + + + try + + + + Error - - Select or enter a host. - + + Select a host. + + + + + You are connected to DC without PDC-Emulator role. Group policy editing is prohibited by the setting. + + + + + You are connected to DC without PDC-Emulator role. Group policy editing is available. + @@ -468,42 +554,42 @@ ConsoleWidget - + Copy - + Cut - + Rename - + Delete - + Paste - + Print - + Refresh - + Properties @@ -511,17 +597,17 @@ CreateComputerDialog - + Create Computer - + Name: - + Logon name (pre-Windows 2000): @@ -529,61 +615,66 @@ CreateContactDialog - + Create Contact - + First name: - + Last name: - + Initials: - + Full name: - + Display name: + + + Middle name: + + CreateGroupDialog - + Create Group - + Name: - + Group name (pre-Windows 2000): Logon name (pre-Windows 2000): - + Group scope: - + Group type: @@ -591,17 +682,17 @@ CreateOUDialog - + Create OU - + Name: - + Protect against deletion @@ -609,41 +700,69 @@ CreateObjectHelper - + Failed to create object %1 - + Object %1 was created + + CreatePSODialog + + + Password settings object creation + + + + + Protect against deletion + + + + + At least one password setting (except precedence) should not be default + + + + + Failed to create password settings object %1 + + + + + Password settings object %1 has been successfully created. + + + CreatePolicyDialog - + Create Policy Create GPO - + Name: - + New Group Policy Object - + Error - + Group Policy Object with this name already exists. @@ -651,28 +770,28 @@ CreateQueryFolderDialog - + Create Query Folder Create query folder - + Name: - + Description: - + New folder - + New Folder @@ -680,7 +799,7 @@ CreateQueryItemDialog - + Create Query @@ -688,287 +807,579 @@ CreateSharedFolderDialog - + Create Shared Folder - + Name: - + Network path: - CreateUserDialog + CreateSiteDialog - - Create User - + + Create site + - - First name: - + + Name: + - - Last name: - + + Select the site link object for this site. + - - Full name: - + + Chain name + - - Initials: - + + Transport + + + + CreateSitesLinkDialog - - Logon name: - + + Create sites link + - - Logon name (pre-Windows 2000): - + + Name: + - - Password: - + + PLACEHOLDER + - - Confirm password: - + + Site link object must link two or more sites + - - Show password - + + Create site link + - - Account options: - + + Link bridge object must link two or more site links + - - User must change password on next logon - + + Create site link bridge + - - User cannot change password - + + Site link object must link at least two sites + - - Don't expire password - + + Link bridge object must link at least two site links + - - Account disabled - + + Error + - - Create %1 - + + Failed to create site link object %1 + - - - CustomizeColumnsDialog - - Customize Columns - + + Failed to create site link bridge object %1 + - - - DelegationTab - - Do not trust for delegation - + + Site link object %1 has been successfully created. + - - Trust for delegation to any service using Kerberos - + + Site link bridge object %1 has been successfully created. + - EditQueryFolderDialog - - - Edit Query Folder - Edit query folder - - + CreateSubnetDialog - - Name: - + + Create subnet + - - Description: - + + Enter the prefix in network prefix notation (address/prefix length). Both IPv4 and IPv6 subnet prefixes are supported. + - - - EditQueryItemDialog - - Edit Query - + + IPv4 example: 172.16.0.0/16 + - - - EditQueryItemWidget - - Recursive search - + + IPv6 example: 2001:db8:abcd:0001::/64 + - - Name: - + + Prefix: + - - Description: - + + Active Directory prefix name: + - - Search in: - + + Site object: + - - Filter: - + + Failed to create subnet object %1 + - - Edit filter - + + Subnet object %1 has been successfully created. + - ErrorLogDialog + CreateUserDialog - - Errors Occured + + Create User - - - ErrorTab - - Failed to load object information. Check your connection. + + First name: - - - ExpiryWidget - - Never + + Last name: - - End of: + + Full name: - - - FSMODialog - - Operations Masters + + Initials: - - Domain DNS + + Logon name: - - Forest DNS + + Logon name (pre-Windows 2000): - - PDC Emulation + + Password: - - Schema + + Confirm password: - - Domain Naming + + Show password - - Infrastructure - + + Middle Name: + - - Rid Allocation + + Account options: - - - FSMOTab - - Current master: + + User must change password on next logon - - Change to: + + User cannot change password - - Change + + Don't expire password - - Error + + Account disabled - - This machine is already a master for this role. Switch to a different machine in Connection Options to change master. + + Create %1 - FilterDialog + CreationDeletionPermissionsWidget + + + Create + + + + + + objects + + + + + Delete + + + + + Undefined + + + + + CustomizeColumnsDialog + + + Customize Columns + + + + + DelegationPermissionsWidget + + + Name + + + + + Assigned + + + + + DelegationTab + + + Do not trust for delegation + + + + + Trust for delegation to any service using Kerberos + + + + + DomainInfoImpl + + + Edit FSMO roles + + + + + Open connection options + + + + + Name + + + + + Host not found + + + + + Active directory managment center [ + + + + + Connected to host + + + + + DomainInfoResultsWidget + + + Form + Form + + + + Domain about + + + + + + + + + + PLACEHOLDER + + + + + Domain functionality level: + + + + + Sites count: + + + + + Forest functionality level: + + + + + Domain schema version: + + + + + Domain controllers count: + + + + + Domain controller version: + + + + + Undefined + + + + + EditQueryFolderDialog + + + Edit Query Folder + Edit query folder + + + + + Name: + + + + + Description: + + + + + EditQueryItemDialog + + + Edit Query + + + + + EditQueryItemWidget + + + Recursive search + + + + + Name: + + + + + Description: + + + + + Search in: + + + + + Filter: + + + + + Edit filter + + + + + ErrorLogDialog + + + Errors Occured + + + + + ErrorTab + + + Failed to load object information. Check your connection. + + + + + ExpiryWidget + + + Never + + + + + End of: + + + + + FSMODialog + + + Operations Masters + + + + + Edit policies only under PDC Emulator connection + + + + + Warning! If unchecking this option, group policy edition will be allowed on domain controllers that do not have the PDC-Emulator role. + + + + + Domain DNS + + + + + Forest DNS + + + + + PDC Emulation + + + + + Schema + + + + + Domain Naming + + + + + Infrastructure + + + + + Rid Allocation + + + + + FSMOTab + + + Current master: + + + + + Change to: + + + + + Change + + + + + Error + + + + + This machine is already a master for this role. Switch to a different machine in Connection Options to change master. + + + + + FilterDialog Edit Filter @@ -1065,17 +1476,17 @@ FindObjectDialog - + Find Objects - + &Action - + &View @@ -1083,105 +1494,105 @@ FindPolicyDialog - + Dialog - + Search item: - + Condition: - + Value: - + Add - + Filters: - + Remove - - + + Clear - + Find - + Stop - + &Action - + &View - - + + Name - - + + GUID - + &Icons - + &List - + &Detail - + &Customize Columns - + &Description Bar - + Find results @@ -1202,57 +1613,57 @@ FindWidget - + Find - + Stop - + Clear - + Search in: - + &Icons Icons - + &List List - + &Detail Detail - + &Customize Columns Customize Columns - + &Description Bar Description Bar - + Find results @@ -1260,36 +1671,92 @@ FoundPolicyImpl - + Add link... - + Edit... + + FsmoTableWidget + + + Form + Form + + + + FSMO roles + + + + + FSMO role + + + + + Host + + + + + Role capture + + + + + + Capture + + + + + + + Captured + + + + + FSMO capture + + + + + Take over the role + + + + + Failed to capture role + + + GeneralComputerTab - + Logon name (pre-Windows 2000): - + DNS Host Name: - + Description: Description - + Location: @@ -1297,33 +1764,33 @@ GeneralGroupTab - + Group name (pre-Windows 2000): Logon name (pre-Windows 2000): - + Description: - + E-mail: - + Notes: - + Group Scope: - + Group Type: @@ -1331,32 +1798,32 @@ GeneralOUTab - + Description: - + Street Address: - + City: - + State/Province: - + ZIP/Postal Code: - + Country: @@ -1382,7 +1849,7 @@ GeneralOtherTab - + Description: @@ -1390,27 +1857,27 @@ GeneralPolicyTab - + Created: - + Modified: - + User version: - + Computer version: - + Unique ID: @@ -1426,16 +1893,39 @@ GeneralSharedFolderTab - + Description: - + Keywords + + GeneralSiteTab + + + Form + Form + + + + PLACEHOLDER + + + + + Description: + + + + + Subnets: + + + GeneralUserMultiTab @@ -1482,73 +1972,341 @@ GeneralUserTab - + Description: - + First Name: - + Last Name: - + Display Name: - + Initials: - - E-mail Address: - + + E-mail Address: + + + + + Office Location: + + + + + Telephone Number: + + + + + Web Page Address: + + + + + + Other... + + + + + Middle Name: + + + + + GroupPolicyTab + + + Inherited Policies + + + + + Block policy inheritance + + + + + HexNumberAttributeDialog + + + Dialog + + + + + 0x + + + + + InheritedPoliciesWidget + + + Priority + + + + + Name + + + + + Location + + + + + KrbAuthDialog + + + Kerberos authentication + + + + + Principal: + + + + + user@REALM + + + + + Password: + + + + + Show password + Show password + + + + Ticket available + + + + + Use system credentials + + + + + System cache + + + + + Sign in + + + + + PLACEHOLDER + + + + + Remember credentials + + + + + Enter your Kerberos principal + + + + + Account already in use + + + + + Enter the password + + + + + Authentication failed + + + + + Failed to find system credentials + + + + + LAPSTab + + + Password: + + + + + Password expires: + + + + + Reset expiry + + + + + LAPSV2Tab + + + Form + Form + + + + LAPS local admin account password: + LAPS local admin account password: + + + + Current LAPS password expiration: + Current LAPS password expiration: + + + + Local Administrator Password Solution + Local Administrator Password Solution + + + + Set new LAPS password expiration: + Set new LAPS password expiration: + + + + Show password + Show password + + + + Expire now + Expire now + + + + Copy password + Copy password + + + + LAPS local admin account name: + LAPS local admin account name: + + + + Failed to decode LAPS data. + Failed to decode LAPS data. + + + + Verify that you have the necessary permissions to access LAPS attributes! + Verify that you have the necessary permissions to access LAPS attributes! + + + + LinkedPoliciesWidget + + + Form + Form + + + + Remove link + + + + + Move up + + + + + Move down + + + + + Set all + + + + + Unset all + + + + + Edit... + + + + + Order + - - Office Location: - + + Name + - - Telephone Number: - + + Enforced + - - Web Page Address: - + + Disabled + - - - Other... - + + Organizational unit + - - - LAPSTab - - Password: - + + 's link orders have been succesfuly changed. + - - Password expires: - + + Not found + - - Reset expiry - + + The GPO for this link could not be found. It maybe have been recently created and is being replicated or it could have been deleted. + @@ -1592,86 +2350,33 @@ - - New value: - - - - - Add - - - - - Remove - - - - - Values: - - - - - LogonHoursDialog - - - Edit Logon Hours - - - - - Logon allowed: - - - - - Logon denied: - - - - - Sunday - - - - - Monday - - - - - Tuesday - - - - - Wednesday - + + On all computers + - - Thursday - + + Only on specified computers + - - Friday - + + In the 'Computer Name' field, enter the NetBIOS name or domain name (DNS name) of the computer. + - - Saturday - + + Computer name: + - - Local time + + Add - - UTC time + + Remove @@ -1684,314 +2389,371 @@ - + &Action Action - + &View View - + + &Theme + + + + &Preferences Preferences - + &Language Language - + &Help Help - + Tool Bar - + Message Log - + &Connection Options Connection Options - + &Quit Quit - + Ctrl+Q - + &Manual Manual - + Manual (Alt + 8) - + Alt+8 - + &Changelog Changelog - + &About ADMC About ADMC - + &Icons Icons - + &List List - + &Detail Detail - + &Console Tree Console Tree - + Description &Bar Description Bar - + C&ustomize Columns... Customize Columns... - + &Filter Objects... Filter Objects... - + &Advanced Features Advanced Features - + &Confirm Actions Confirm Actions - + &Put Last Name Before First Name Put Last Name Before First Name - + &Log Searches Log Searches - + &Timestamps in Message Log Timestamps in Message Log - + &Show Non-Container Objects in Console Tree Show Non-Container Objects in Console Tree - + Navigate Back (Alt + -) - + Navigate Forward (Alt + =) - + Refresh (Alt + 9) - + Alt+9 - + Show Login - + &Operations Masters Operations Masters - + Create user - + Create user (Alt + 7) - + Alt+7 - + Create group - + Create group (Alt + 6) - + Alt+6 - + Create organization unit - + Create organization unit (Alt + 5) - + Alt+5 - + + Load optional attribute values + + + + + Show middle name when creating + + + + + Change user + + + + + Use system credentials on start + + + + + Logout + + + + + Show login window on startup + + + + Navigate Up - + Alt+0 - + Navigate Back - + Alt+- - + Navigate Forward - + Alt+= - + Refresh - + + + Authentication required + + + + + Connected to host + + + + Info - + Restart the app to switch to the selected language. + + + You are connected to DC without PDC-Emulator role + + + + + Logged in successfully + + MainWindowConnectionError - Connection Error - + Connection error + Connection Error + - + Failed to connect to domain. - + Retry - + Connection Options - + Quit @@ -2105,32 +2867,32 @@ - + Add Member - + Add to Group - + Can't remove because this group is a primary group to selected user. - + Can't remove because selected group is a primary group to this user. - + Error - + Primary group: @@ -2156,115 +2918,150 @@ ObjectImpl - + User &User - + Computer &Computer - + OU &OU - + Group - + Shared Folder - + inetOrgPerson - + Contact - + Find... - + Move... - + Add to group... - + Enable - + Disable - + Reset password - + Reset account - + Edit UPN suffixes - + New - + + Create subnet + + + + + Create site + + + + + Create site link + + + + + Create site link bridge + + + + [Filtering enabled] - + Are you sure you want to delete this object? - + + Are you sure you want to delete these objects? + + + + + It contains other objects. + + + + + Containers to be deleted contain other objects. + + + + Add to Group - + Edit UPN Suffixes - + Are you sure you want to reset this account? - + Query may be out of date @@ -2307,11 +3104,6 @@ Protect against deletion: - - - Block inheritance: - - OctetAttributeDialog @@ -2336,27 +3128,27 @@ - + Error - + Input must be strings of 2 hexadecimal digits separated by spaces. Example: "0a 00 b5 ff" - + Input must be strings of 8 binary digits separated by spaces. Example: "01010010 01000010 01000010" - + Input must be strings of 3 decimal digits (0-255) separated by spaces. Example: "010 000 191" - + Input must be strings of 3 octal digits (0-377) separated by spaces.. Example: "070 343 301" @@ -2415,14 +3207,135 @@ OrganizationTabEdit - - Name - + + Name + + + + + Folder + + + + + PSOAppliedEdit + + + Default + + + + + Not found + + + + + (directly) + + + + + (via group membership) + + + + + PSOEditWidget + + + Form + Form + + + + Password Settings + + + + + Name: + + + + + Minimum password length: + + + + + Failed log on attempts allowed: + + + + + Minimum password age (days): + + + + + Account lockout duration (mins): + + + + + Enable complexity requirements + + + + + Store passwords using reversible encryption + + + + + Precedence: + + + + + Password history length: + + + + + Reset account lockout after (mins): + + + + + Maximum password age (days): + + + + + Apply to user/grop + + + + + Add... + + + + + Remove + + + + + Global password settings + + + + + Password settings + - - Folder - + + Add applied users/group + @@ -2467,62 +3380,108 @@ PasswordEdit - + Passwords don't match! - - - + + + Error - + Password cannot be empty. - + Password contains invalid characters + + PasswordSettingsImpl + + + Create password settings object + + + + + PermissionsWidget + + + Name + + + + + Allowed + + + + + Denied + + + + + There are no rights for this class of objects + + + PolicyImpl - + Add link... - + Edit... - + + Enforced + + + + + Disabled + + + + Incorrect permissions detected - + Permissions for this policy's GPT don't match the permissions for it's GPC object. Would you like to update GPT permissions? - + Are you sure you want to unlink this policy from the OU? Note that the actual policy object won't be deleted. - + + Are you sure you want to delete these policies and all their links? + + + + Are you sure you want to delete this policy and all of it's links? - + Add Link @@ -2530,37 +3489,37 @@ PolicyOUImpl - + Create OU - + Create a GPO and link to this OU - + Link existing GPO - + Find GPO - + Block inheritance - + All policies - + Name @@ -2568,75 +3527,40 @@ PolicyOUResultsWidget - - Remove link - - - - - Move up - - - - - Move down - - - - - Order - - - - - Name - - - - - Enforced - - - - - Disabled - - - - - Not found - + + Linked policies + - - The GPO for this link could not be found. It maybe have been recently created and is being replicated or it could have been deleted. - + + Inherited policies + PolicyResultsWidget - + Delete link - + Location - + Enforced - + Disabled - + Path @@ -2644,7 +3568,7 @@ PolicyRootImpl - + Name @@ -2688,89 +3612,95 @@ PropertiesDialog - - + + Properties - + %1 Properties "%1" Properties - + General - + Object - + Attributes - + Account - + Organization - + Telephones - + Profile - + + Group policy + + + + + LAPS - + Security - + Members - + Member of - + Managed by - + Operating System - + Delegation - + Address @@ -2778,33 +3708,33 @@ PropertiesMultiDialog - + Properties for Multiple Objects - - + + General - + Account - + Address - + Profile - + Organization @@ -2812,17 +3742,17 @@ PropertiesWarningDialog - + Warning - + You're switching to attributes tab, while another tab has unapplied changes. Choose to apply or discard those changes. - + You're switching from attributes tab, while it has unapplied changes. Choose to apply or discard those changes. @@ -2830,10 +3760,26 @@ QObject - + + Confirm action + + + Password settings container is not available + + + + + Sites container is not available + + + + + Sites + + Can't set "%1" when "%2" is set. @@ -2844,47 +3790,134 @@ Error + + + + Creation is not available + + + + + + ADMC is connected to DC without the PDC-Emulator role - group policy creation is prohibited by the setting. Connect to PDC-Emulator? + + + + + Deletion is not available + + + + + ADMC is connected to DC without the PDC-Emulator role - group policy deletion is prohibited by the setting. Connect to PDC-Emulator? + + + + + Edition is not available + + + + + ADMC is connected to DC without the PDC-Emulator role - group policy editing is prohibited by the setting. Connect to PDC-Emulator? + + + + + Failed to start GPUI. Check that it's installed. + + + + + Loading... + + + + + PDC-Emulator is connected + + + + + Could not open a theme: + + + + + (System) + + + + + Theme from settings not found. System theme is set. + + + + + Enabled + + + + + User configuration disabled + + + + + Computer configuration disabled + + + + + Disabled + + + + + Undefined GPO status + + QueryFolderImpl - + Query folder - + Query item - + New - + Edit - + &Import query... - - + + Error - + Can't cut and paste query folder into itself. - + There's already an item with this name. @@ -2892,30 +3925,54 @@ QueryItemImpl - + Edit... - + Export query... + + ReadWritePermissionsWidget + + + Write + + + + + + property + + + + + Read + + + + + Undefined + + + RenameGroupDialog - + Rename Group - + Name: - + Group name (pre-Windows 2000): Logon name (pre-Windows 2000): @@ -2924,12 +3981,12 @@ RenameObjectHelper - + Object %1 was renamed. - + Failed to rename object %1 @@ -2937,12 +3994,12 @@ RenameOtherDialog - + Rename Object - + Name: @@ -2950,12 +4007,12 @@ RenamePolicyDialog - + Rename Policy - + Name: @@ -2963,53 +4020,172 @@ RenameUserDialog - + Rename User - - Display name: - Display name - + + Display name: + Display name + + + + + First name: + + + + + Last name: + + + + + Full name: + + + + + Logon name: + + + + + Logon name (pre-Windows 2000): + + + + + ResultsWidgetBase + + + Form + Form + + + + Edit... + + + + + Cancel + + + + + Apply + + + + + SDDLViewDialog + + + SDDL view + + + + + Security descriptor (SDDL) + + + + + Show descriptor for current trustee + + + + + Failed to get SDDL formatted security descriptor + + + + + : Domain sid parse failed + + + + + : SDDL encode failed + + + + + SamNameEdit + + + Input field for Logon name (pre-Windows 2000) contains one or more of the following illegal characters: @ " [ ] : ; | = + * ? < > / \ , + + + + + Error + + + + + ScheduleHoursDialog + + + Edit Schedule Hours + + + + + UTC time + + + + + Local time + + + + + Logon allowed: + + + + + Logon denied: + - - First name: - + + Sunday + - - Last name: - + + Monday + - - Full name: - + + Tuesday + - - Logon name: - + + Wednesday + - - Logon name (pre-Windows 2000): - + + Thursday + - - - SamNameEdit - - Input field for Logon name (pre-Windows 2000) contains one or more of the following illegal characters: @ " [ ] : ; | = + * ? < > / \ , - + + Friday + - - Error - + + Saturday + @@ -3038,57 +4214,114 @@ SecurityTab - + + Users and Groups + + + + Add... - + Add well-known trustee... - + Remove - + Permissions - - - SecurityTabEdit - - Name - + + Applied to: + - - Allowed - + + Clear all + - - Denied - + + Common + + + + + Extended + + + + + Creation/deletion + + + + + Read/write + + + + + Task delegation + + + + + More... + + + + + Show descriptor in SDDL + + + + + Rollback to the previous descriptor + + + + + This object + + + + + This object and all child objects + + + + + All child objects + - + + Child objects: + + + + Add Trustee - + - + Error - + - + Failed to add some trustee's because they are already in the list. - + @@ -3116,21 +4349,26 @@ SelectContainerDialog - + Select Container Select a container + + + Failed to define suitable containers + + SelectObjectAdvancedDialog - + Select Object - + &View @@ -3138,85 +4376,85 @@ SelectObjectDialog - + Select Object - + Add - + Name - + Type - + Folder - + Remove - + Advanced - + Classes: - + Search in: - + Name: - + Selected objects: - - - - + + + + Error - + You must select at least one object. - + Failed to find any matches. - + Selected object is already in the list. - + This selection accepts only one object. Remove extra objects to proceed. @@ -3224,12 +4462,12 @@ SelectObjectMatchDialog - + Select Match - + There are multiple matches. Select one or more to add to the list. @@ -3237,7 +4475,7 @@ SelectPolicyDialog - + Select Policy @@ -3250,6 +4488,122 @@ + + SitesLinkCommonWidget + + + Form + Form + + + + Description: + + + + + + PLACEHOLDER + + + + + Add >> + + + + + << Remove + + + + + Sites not in this site link + + + + + Sites in this site link + + + + + Site links not included in this bridge + + + + + Site links included in this bridge + + + + + SitesLinkEdit + + + Site link object must link at least two sites + + + + + Link bridge object must link at least two site links + + + + + Error + + + + + SitesLinkGeneralTab + + + Form + Form + + + + PLACEHOLDER + + + + + SitesLinkPartWidget + + + Form + Form + + + + Cost: + + + + + Replicate every + + + + + min + + + + + Change the schedule ... + + + + + SitesLinkWidget + + + Form + Form + + StringListEdit @@ -3266,6 +4620,34 @@ + + SubnetEditWidget + + + Form + Form + + + + Sites: + + + + + Prefix: + + + + + Description: + + + + + Location: + + + TelephonesTab @@ -3308,6 +4690,19 @@ + + TimeSpanAttributeDialog + + + Dialog + + + + + d:hh:mm:ss or (never) / (none) + + + UnlockEdit @@ -3338,7 +4733,7 @@ country_widget - + None @@ -3346,7 +4741,7 @@ object_impl - + %n object(s) %n object @@ -3357,20 +4752,28 @@ object_impl.cpp - + Failed to connect to server while searching for objects. - + Could not load all objects. Increase object display limit in Filter Options or reduce number of objects by applying a filter. Filter Options is accessible from main window's menubar via the "View" menu. + + password_settings_impl + + + Password settings + + + policy_root_impl - + Group Policy Objects @@ -3378,7 +4781,7 @@ query - + Saved Queries @@ -3386,30 +4789,36 @@ query.cpp - + Name may not be empty - - - - + + + + + Error - + + Could not open a query file. + + + + There's already an item with this name. - + Names cannot contain "/". - + Query file is corrupted. @@ -3417,12 +4826,12 @@ query_folder.cpp - + Name - + Description @@ -3430,7 +4839,7 @@ query_folder_impl.cpp - + Are you sure you want to delete this item? @@ -3438,18 +4847,18 @@ query_item_impl.cpp - + Import Query - - + + JSON (*.json) - + Export Query @@ -3457,72 +4866,14 @@ utils.cpp - + Input field for Name contains one or more of the following illegal characters: # , + " \ < > ; = (leading space) (trailing space) (leading question mark) - + Error - - LAPSV2Tab - - - Form - Form - - - - LAPS local admin account password: - LAPS local admin account password: - - - - Current LAPS password expiration: - Current LAPS password expiration: - - - - Local Administrator Password Solution - Local Administrator Password Solution - - - - Set new LAPS password expiration: - Set new LAPS password expiration: - - - - Show password - Show password - - - - Expire now - Expire now - - - - Copy password - Copy password - - - - LAPS local admin account name: - LAPS local admin account name: - - - - Failed to decode LAPS data. - Failed to decode LAPS data. - - - - Verify that you have the necessary permissions to access LAPS attributes! - Verify that you have the necessary permissions to access LAPS attributes! - - diff --git a/src/admc/admc_ru.ts b/src/admc/admc_ru.ts index e654f5b15..a55453a8b 100644 --- a/src/admc/admc_ru.ts +++ b/src/admc/admc_ru.ts @@ -1,6 +1,6 @@ - + AboutDialog @@ -106,47 +106,47 @@ Параметры учётной записи: - + Account disabled Учётная запись отключена - + User cannot change password Пользователь не может изменить пароль - + User must change password on next logon Пользователь должен сменить пароль при следующем входе в систему - + Don't expire password Пароль не истекает - + Store password using reversible encryption Хранить пароль с использованием обратимого шифрования - + Smartcard is required for interactive logon Смарт-карта необходима для интерактивного входа в систему - + Account is sensitive and cannot be delegated Учётная запись является конфиденциальной и не может быть делегирована - + Use Kerberos DES encryption types for this account Использовать Kerberos DES тип шифрования для этой учетной записи - + Don't require Kerberos pre-authentication Не требовать предварительной аутентификации Kerberos @@ -225,41 +225,36 @@ AllPoliciesFolderImpl - + Create policy Создать политику - + Name Имя - - - PDC-Emulator is connected - Подключено к PDC-Emulator - AttributeDialog - + View Просмотреть - + Edit Изменить - + %1 Multi-Valued %2 This is a dialog title for attribute editors. Example: "Edit Multi-Valued String" %1 %2 (Многозначный) - + Attribute: %1 Атрибут: %1 @@ -295,17 +290,17 @@ AttributesTabEdit - + Name Имя - + Value Значение - + Type Тип @@ -314,19 +309,6 @@ Copy Копировать - - Edit - Изменить - - - View - Просмотреть - - - %1 Multi-Valued %2 - This is a dialog title for attribute editors. Example: "Edit Multi-Valued String" - %1 %2 (Многозначный) - AttributesTabFilterMenu @@ -392,7 +374,7 @@ Журнал изменений - + Failed to open changelog file. Не удалось открыть файл журнала изменений. @@ -483,19 +465,11 @@ Restore defaults По умолчанию - - Host: - Хост: - No hosts found. Хосты не найдены. - - Select: - Выбрать: - Custom: @@ -506,10 +480,6 @@ Error Ошибка - - Select or enter a host. - Выберите или введите хост. - never @@ -541,12 +511,12 @@ Выберите хост. - + You are connected to DC without PDC-Emulator role. Group policy editing is prohibited by the setting. Вы подключены к КД без роли PDC-Emulator - редактирование групповых политик запрещено настройкой. - + You are connected to DC without PDC-Emulator role. Group policy editing is available. Вы подключены к КД без роли PDC-Emulator - редактирование групповых политик доступно. @@ -587,42 +557,42 @@ ConsoleWidget - + Copy Копировать - + Cut Вырезать - + Rename Переименовать - + Delete Удалить - + Paste Вставить - + Print Напечатать - + Refresh Обновить - + Properties Свойства @@ -630,17 +600,17 @@ CreateComputerDialog - + Create Computer Создать рабочую станцию - + Name: Имя: - + Logon name (pre-Windows 2000): Имя для входа (до Windows 2000): @@ -648,32 +618,32 @@ CreateContactDialog - + Create Contact Создать контакт - + First name: Имя: - + Last name: Фамилия: - + Initials: Инициалы: - + Full name: Полное имя: - + Display name: Отображаемое имя: @@ -686,28 +656,28 @@ CreateGroupDialog - + Create Group Создать группу - + Name: Имя: - + Group name (pre-Windows 2000): Logon name (pre-Windows 2000): Имя группы (до Windows 2000): - + Group scope: Область группы: - + Group type: Тип группы: @@ -715,17 +685,17 @@ CreateOUDialog - + Create OU Создать подразделение - + Name: Имя: - + Protect against deletion Защитить от удаления @@ -733,12 +703,12 @@ CreateObjectHelper - + Failed to create object %1 Не удалось создать объект %1 - + Object %1 was created Объект %1 был создан @@ -774,28 +744,28 @@ CreatePolicyDialog - + Create Policy Create GPO Создать групповую политику - + Name: Имя: - + New Group Policy Object Новый объект групповой политики - + Error Ошибка - + Group Policy Object with this name already exists. Объект групповой политики с этим именем уже существует. @@ -803,28 +773,28 @@ CreateQueryFolderDialog - + Create Query Folder Create query folder Создать папку запроса - + Name: Имя: - + Description: Описание: - + New folder Новая папка - + New Folder Новая папка @@ -832,7 +802,7 @@ CreateQueryItemDialog - + Create Query Создать запрос @@ -840,17 +810,17 @@ CreateSharedFolderDialog - + Create Shared Folder Создать общую папку - + Name: Имя: - + Network path: Сетевой путь: @@ -921,37 +891,37 @@ Создать мост связи сайтов - + Site link object must link at least two sites Связь сайтов должна связывать минимум два сайта - + Link bridge object must link at least two site links Мост связей доложен связывать минимум две связи сайтов - + Error Ошибка - + Failed to create site link object %1 Не удалось создать объект связи сайтов %1 - + Failed to create site link bridge object %1 Не удалось создать объект мост связи сайтов %1 - + Site link object %1 has been successfully created. Объект связи сайтов %1 успешно создан. - + Site link bridge object %1 has been successfully created. Объект мост связей %1 сайтов успешно создан. @@ -1067,27 +1037,27 @@ Параметры учётной записи: - + User must change password on next logon Пользователь должен сменить пароль при следующем входе в систему - + User cannot change password Пользователь не может изменить пароль - + Don't expire password Пароль не истекает - + Account disabled Учётная запись отключена - + Create %1 Создать объект - %1 @@ -1126,42 +1096,6 @@ DelegationPermissionsWidget - - Common tasks delegation - Делегирование обычных задач - - - Create/delete child objects - Создание/удаление дочерних объектов - - - Read/write properties - Чтение/запись свойств - - - Create - Создание - - - objects - объектов - - - Delete - Удаление - - - Write - Запись - - - property - свойства - - - Read - Чтение - Name @@ -1189,32 +1123,32 @@ DomainInfoImpl - + Edit FSMO roles Изменить FSMO роли - + Open connection options Параметры подключения - + Name Имя - + Host not found Хост не найден - + Active directory managment center [ Центр управления Active Directory [ - + Connected to host Подключено к хосту @@ -1222,7 +1156,7 @@ DomainInfoResultsWidget - + Form @@ -1237,54 +1171,42 @@ Количество сайтов: - + Domain controllers count: Количество контроллеров домена: - + Domain schema version: Версия схемы домена: - + Domain functionality level: Режим работы домена: - + Domain controller version: Версия контроллера домена: - + Forest functionality level: Режим работы леса: - - - + + + + + + PLACEHOLDER - - Servers - Серверы - - - - FSMO roles - FSMO роли - - - - Failed to get objects count - Не удалось получить количество объектов - - - + Undefined Не определено @@ -1292,18 +1214,18 @@ EditQueryFolderDialog - + Edit Query Folder Edit query folder Изменить папку запроса - + Name: Имя: - + Description: Описание: @@ -1311,7 +1233,7 @@ EditQueryItemDialog - + Edit Query Изменить запрос @@ -1319,32 +1241,32 @@ EditQueryItemWidget - + Recursive search Рекурсивный поиск - + Name: Имя: - + Description: Описание: - + Search in: Искать в: - + Filter: Фильтр: - + Edit filter Изменить фильтр @@ -1381,7 +1303,7 @@ FSMODialog - + Operations Masters Мастера Операций @@ -1401,32 +1323,32 @@ DNS домена - + Forest DNS DNS леса - + PDC Emulation PDC эмуляция - + Schema Схема - + Domain Naming Имена домена - + Infrastructure Инфраструктура - + Rid Allocation RID распределение @@ -1434,27 +1356,27 @@ FSMOTab - + Current master: Текущий мастер: - + Change to: Изменить на: - + Change Изменить - + Error Ошибка - + This machine is already a master for this role. Switch to a different machine in Connection Options to change master. Эта машина уже является мастером этой роли. Переключитесь на другой компьютер в опциях подключения, чтобы изменить мастер. @@ -1557,17 +1479,17 @@ FindObjectDialog - + Find Objects Поиск объектов - + &Action &Действие - + &View &Вид @@ -1575,105 +1497,105 @@ FindPolicyDialog - + Dialog - + Search item: Элемент поиска: - + Condition: Состояние: - + Value: Значение: - + Add Добавить - + Filters: Фильтры: - + Remove Удалить - - + + Clear Очистить - + Find Поиск - + Stop Остановить - + &Action &Действие - + &View &Вид - - + + Name Имя - - + + GUID GUID - + &Icons &Значки - + &List &Список - + &Detail &Подробно - + &Customize Columns &Настроить колонки - + &Description Bar &Область описания - + Find results Результаты поиска @@ -1694,57 +1616,57 @@ FindWidget - + Find Поиск - + Stop Остановить - + Clear Очистить - + Search in: Искать в: - + &Icons Icons &Значки - + &List List &Список - + &Detail Detail &Подробно - + &Customize Columns Customize Columns &Настроить колонки - + &Description Bar Description Bar &Область описания - + Find results Результаты поиска @@ -1752,12 +1674,12 @@ FoundPolicyImpl - + Add link... Добавить связь... - + Edit... Изменить... @@ -1821,23 +1743,23 @@ GeneralComputerTab - + Logon name (pre-Windows 2000): Имя для входа (до Windows 2000): - + DNS Host Name: Имя узла DNS: - + Description: Description Описание: - + Location: Местонахождение: @@ -1845,33 +1767,33 @@ GeneralGroupTab - + Group name (pre-Windows 2000): Logon name (pre-Windows 2000): Имя группы (до Windows 2000): - + Description: Описание: - + E-mail: Электронная почта: - + Notes: Примечания: - + Group Scope: Область группы: - + Group Type: Тип группы: @@ -1879,32 +1801,32 @@ GeneralOUTab - + Description: Описание: - + Street Address: Адрес: - + City: Город: - + State/Province: Регион: - + ZIP/Postal Code: Почтовый индекс: - + Country: Страна: @@ -1930,7 +1852,7 @@ GeneralOtherTab - + Description: Описание: @@ -1938,27 +1860,27 @@ GeneralPolicyTab - + Created: Создан: - + Modified: Изменен: - + User version: Пользовательская версия: - + Computer version: Машинная версия: - + Unique ID: Уникальный ID: @@ -1974,12 +1896,12 @@ GeneralSharedFolderTab - + Description: Описание: - + Keywords Ключевые слова @@ -2053,53 +1975,53 @@ GeneralUserTab - + Description: Описание: - + First Name: Имя: - + Last Name: Фамилия: - + Display Name: Отображаемое имя: - + Initials: Инициалы: - + E-mail Address: Электронная почта: - + Office Location: Расположение офиса: - + Telephone Number: Номер телефона: - + Web Page Address: Адрес веб-страницы: - - + + Other... Другие... @@ -2117,33 +2039,41 @@ Наследуемые политики - + Block policy inheritance Заблокировать наследование политик + + HexNumberAttributeDialog + + + Dialog + + + + + 0x + + + InheritedPoliciesWidget - + Priority Приоритет - + Name Имя - + Location Местонахождение - - - Status - Статус - KrbAuthDialog @@ -2158,22 +2088,22 @@ Принципал: - + Password: Пароль: - + Show password Показать пароль - + user@REALM - + Ticket available Билет доступен @@ -2193,7 +2123,7 @@ Войти - + PLACEHOLDER @@ -2203,27 +2133,27 @@ Запомнить учётные данные - + Enter your Kerberos principal Введите принципал Kerberos - + Account already in use Аккаунт уже используется - + Enter the password Введите пароль - + Authentication failed Аутентификация не удалась - + Failed to find system credentials Не удалость найти системные учётные данные @@ -2307,22 +2237,22 @@ LinkedPoliciesWidget - + Form - + Remove link Удалить связь - + Move up Переместить вверх - + Move down Переместить вниз @@ -2347,37 +2277,37 @@ Порядок - + Name Имя - + Enforced Принудительно - + Disabled Отключено - + Organizational unit Порядки связей подразделения - + 's link orders have been succesfuly changed. были успешно изменены. - + Not found Не найдено - + The GPO for this link could not be found. It maybe have been recently created and is being replicated or it could have been deleted. Не удалось найти объект групповой политики для этой связи. Возможно, он был недавно создан и реплицируется или был удалён. @@ -2422,10 +2352,6 @@ Edit Logon Computers Компьютеры для входа в систему - - New value: - Новое значение: - On all computers @@ -2452,77 +2378,10 @@ Добавить - + Remove Удалить - - Values: - Значения: - - - - LogonHoursDialog - - - Edit Logon Hours - Изменить время входа - - - - Logon allowed: - Вход разрешен: - - - - Logon denied: - Вход запрещён: - - - - Sunday - Воскресенье - - - - Monday - Понедельник - - - - Tuesday - Вторник - - - - Wednesday - Среда - - - - Thursday - Четверг - - - - Friday - Пятница - - - - Saturday - Суббота - - - - Local time - Местное время - - - - UTC time - Время UTC - MainWindow @@ -2533,272 +2392,272 @@ &Файл - + &Action Action &Действие - + &View View &Вид - + &Theme Theme &Тема - + &Preferences Preferences &Настройки - + &Language Language &Язык - + &Help Help &Помощь - + Tool Bar Панель инструментов - + Message Log Журнал сообщений - + &Connection Options Connection Options &Параметры подключения - + &Quit Quit &Выйти - + Ctrl+Q Ctrl+Q - + &Manual Manual &Руководство - + Manual (Alt + 8) Помощь (Alt + 8) - + Alt+8 Alt+8 - + &Changelog Changelog &Журнал изменений - + &About ADMC About ADMC &О приложении ADMC - + &Icons Icons &Значки - + &List List &Список - + &Detail Detail &Подробно - + &Console Tree Console Tree &Дерево консоли - + Description &Bar Description Bar &Область описания - + C&ustomize Columns... Customize Columns... &Настроить колонки... - + &Filter Objects... Filter Objects... &Фильтровать объекты... - + &Advanced Features Advanced Features &Дополнительные возможности - + &Confirm Actions Confirm Actions &Подтверждать действия - + &Put Last Name Before First Name Put Last Name Before First Name &Ставить фамилию перед именем - + &Log Searches Log Searches &Вносить информацию о поиске в журнал сообщений - + &Timestamps in Message Log Timestamps in Message Log &Метки времени в журнале сообщений - + &Show Non-Container Objects in Console Tree Show Non-Container Objects in Console Tree П&оказывать неконтейнерные объекты в дереве консоли - + Navigate Back (Alt + -) Назад (Alt + -) - + Navigate Forward (Alt + =) Вперед (Alt + =) - + Refresh (Alt + 9) Обновить (Alt + 9) - + Alt+9 Alt+9 - + Show Login Показывать логин - + &Operations Masters Operations Masters &Мастера Операций - + Create user Создать пользователя - + Create user (Alt + 7) Создать пользователя (Alt + 7) - + Alt+7 Alt+7 - + Create group Создать группу - + Create group (Alt + 6) Создать группу (Alt + 6) - + Alt+6 Alt+6 - + Create organization unit Создать подразделение - + Create organization unit (Alt + 5) Создать подразделение (Alt + 5) - + Alt+5 Alt+5 - + Load optional attribute values Загружать значения необязательных атрибутов - + Show middle name when creating Показывать отчество при создании - + Change user Сменить пользователя - + Use system credentials on start Системные учётные данные при старте - + Logout Выход из аккаунта @@ -2813,62 +2672,63 @@ Наверх - + Alt+0 Alt+0 - + Navigate Back Назад - + Alt+- Alt+- - + Navigate Forward Вперед - + Alt+= Alt+= - + Refresh Обновить - + Info Информация - + Restart the app to switch to the selected language. Для переключения на выбранный язык необходимо перезапустить приложение. - + You are connected to DC without PDC-Emulator role Вы подключены к КД без роли PDC-Emulator - + Logged in successfully Вход выполнен - + + Authentication required Требуется аутентификация - + Connected to host Подключено к хосту @@ -2882,22 +2742,22 @@ Ошибка соединения - + Failed to connect to domain. Не удалось подключиться к домену. - + Retry Подключиться - + Connection Options Параметры подключения - + Quit Выйти @@ -3011,32 +2871,32 @@ Папка - + Add Member Добавить участника - + Add to Group Добавить в группу - + Can't remove because this group is a primary group to selected user. Не удалось удалить группу, так как она является основной для выбранного пользователя. - + Can't remove because selected group is a primary group to this user. Не удалось удалить выбранную группу, так как она является основной для этого пользователя. - + Error Ошибка - + Primary group: Основная группа: @@ -3062,155 +2922,150 @@ ObjectImpl - + User &User Пользователь - + Computer &Computer Компьютер - + OU &OU Подразделение - + Group Группа - + Shared Folder Общая папка - + inetOrgPerson inetOrgPerson - + Contact Контакт - + Find... Найти... - + Move... Переместить... - + Add to group... Добавить в группу... - + Enable Включить - + Disable Отключить - + Reset password Сбросить пароль - + Reset account Сбросить учётную запись - + Edit UPN suffixes Изменить суффиксы UPN - - Create password setting object - Создать объект парольных настроек - - - + Create subnet Создать подсеть - + Create site Создать сайт - + Create site link Создать связь сайтов - + Create site link bridge Создать мост связей сайтов - + New Создать - + [Filtering enabled] [Фильтр включён] - + Are you sure you want to delete this object? Удалить этот объект? - + Are you sure you want to delete these objects? Удалить эти объекты? - + It contains other objects. Он содержит другие объекты. - + Containers to be deleted contain other objects. Удаляемые контейнеры содержат другие объекты. - + Add to Group Добавить в группу - + Edit UPN Suffixes Изменить суффиксы UPN - + Are you sure you want to reset this account? Вы точно хотите сбросить эту учетную запись? - + Query may be out of date Запрос может быть устаревшим @@ -3253,11 +3108,6 @@ Protect against deletion: Защитить от удаления: - - - Block inheritance: - Блокировать наследование: - OctetAttributeDialog @@ -3282,27 +3132,27 @@ Восьмеричный - + Error Ошибка - + Input must be strings of 2 hexadecimal digits separated by spaces. Example: "0a 00 b5 ff" Ввод должен состоять из строки, содержащей две шестнадцатеричные цифры, разделённые пробелами. Пример: "0a 00 b5 ff" - + Input must be strings of 8 binary digits separated by spaces. Example: "01010010 01000010 01000010" Ввод должен состоять из строки, содержащей восемь двоичных цифр, разделённых пробелами. Пример: "01010010 01000010 01000010" - + Input must be strings of 3 decimal digits (0-255) separated by spaces. Example: "010 000 191" Ввод должен состоять из строки, содержащей три десятичные цифры (0–255), разделённые пробелами. Пример: "010 000 191" - + Input must be strings of 3 octal digits (0-377) separated by spaces.. Example: "070 343 301" Ввод должен состоять из строки, содержащей три восьмеричные цифры (0–377), разделённые пробелами. Пример: "070 343 301" @@ -3402,12 +3252,12 @@ - + Account lockout duration (mins): Длительность блокировки учетной записи (минуты): - + Name: Имя: @@ -3422,92 +3272,74 @@ Минимальная длина пароля: - + Enable complexity requirements Включить требования сложности - + Store passwords using reversible encryption Хранить пароли, используя обратимое шифрование - + Precedence: Приоритет: - + Apply to user/grop Применить к пользователю/группе - + Add... Добавить... - + Remove Удалить - + Minimum password age (days): Минимальный срок действия пароля (дни): - + Reset account lockout after (mins): Время до сброса блокировки (минуты): - - PSO precedence should be greater than 0 - Приоритет должен быть больше 0 - - - + Maximum password age (days): Максимальный срок действия пароля (дни): - + Password history length: Длина истории паролей: - + Failed log on attempts allowed: Разрешено неудачных попыток входа: - - Add applied users/group - Добавить применяемых пользователей/группы - - - - PSOResultsWidget - - - Form - + + Global password settings + Глобальные параметры паролей - - Edit... - Изменить... + + Password settings + Парольная политика - - Cancel - Отменить - - - - Apply - Применить + + Add applied users/group + Добавить применяемых пользователей/группы @@ -3552,28 +3384,36 @@ PasswordEdit - + Passwords don't match! Пароли не совпадают! - - - + + + Error Ошибка - + Password cannot be empty. Пароль не может быть пустым. - + Password contains invalid characters Пароль содержит недопустимые символы + + PasswordSettingsImpl + + + Create password settings object + Создать парольную политику (PSO) + + PermissionsWidget @@ -3592,7 +3432,7 @@ Запрещено - + There are no rights for this class of objects Нет прав для данного класса объектов @@ -3600,37 +3440,37 @@ PolicyImpl - + Add link... Добавить связь... - + Edit... Изменить... - + Enforced Принудительно - + Disabled Отключено - + Incorrect permissions detected Обнаружены неверные разрешения - + Permissions for this policy's GPT don't match the permissions for it's GPC object. Would you like to update GPT permissions? Разрешения шаблона групповой политики у данной политики не совпадают с разрешениями её объекта контейнера групповой политики. Обновить разрешения шаблона групповой политики? - + Are you sure you want to unlink this policy from the OU? Note that the actual policy object won't be deleted. Удалить связь между политикой и подразделением? Обратите внимание, что сама политика не будет удалена. @@ -3645,32 +3485,7 @@ Удалить эту политику и все её связи? - - Failed to delete group policy - Не удалось удалить групповую политику - - - - : this is a critical policy - : данная политика является критической - - - - Failed to delete the following group policies: - - Не удалось удалить следующие групповые политики: - - - - (critical policy) - (критическая политика) - - - Failed to delete some group policies - Не удалось удалить некоторые групповые политики - - - + Add Link Добавление связи @@ -3678,100 +3493,50 @@ PolicyOUImpl - + Create OU Создать подразделение - + Create a GPO and link to this OU Создать политику и связать с этим подразделением - + Link existing GPO Связать существующую политику - + Find GPO Найти объект групповой политики - + Block inheritance Блокировать наследование - + All policies Все политики - + Name Имя - - - PDC-Emulator is connected - Подключено к PDC-Emulator - PolicyOUResultsWidget - - Remove link - Удалить связь - - - - Move up - Переместить вверх - - - - Move down - Переместить вниз - - - - Order - Порядок - - - - Name - Имя - - - - Enforced - Принудительно - - - - Disabled - Отключено - - - - Not found - Не найдено - - - - The GPO for this link could not be found. It maybe have been recently created and is being replicated or it could have been deleted. - Не удалось найти объект групповой политики для этой связи. Возможно, он был недавно создан и реплицируется или был удалён. - - - + Linked policies Привязанные политики - + Inherited policies Inherited Наследуемые политики @@ -3780,43 +3545,35 @@ PolicyResultsWidget - + Delete link Удалить связь - + Location Местонахождение - + Enforced Принудительно - + Disabled Отключено - + Path Путь - - Incorrect permissions detected - Обнаружены неверные разрешения - - - Permissions for this policy's GPT don't match the permissions for it's GPC object. Would you like to update GPT permissions? - Разрешения шаблона групповой политики у данной политики не совпадают с разрешениями её объекта контейнера групповой политики. Обновить разрешения шаблона групповой политики? - PolicyRootImpl - + Name Имя @@ -3860,94 +3617,95 @@ PropertiesDialog - - + + Properties Свойства - + %1 Properties "%1" Properties %1 — свойства - + General Общее - + Object Объект - + Attributes Атрибуты - + Account Учётная запись - + Organization Организация - + Telephones Телефоны - + Profile Профиль - + Group policy Групповая политика - + + LAPS LAPS - + Security Безопасность - + Members Участники - + Member of Группы - + Managed by Руководство - + Operating System Операционная система - + Delegation Делегирование - + Address Адрес @@ -3955,33 +3713,33 @@ PropertiesMultiDialog - + Properties for Multiple Objects Свойства для нескольких объектов - - + + General Общее - + Account Учётная запись - + Address Адрес - + Profile Профиль - + Organization Организация @@ -3989,17 +3747,17 @@ PropertiesWarningDialog - + Warning Предупреждение - + You're switching to attributes tab, while another tab has unapplied changes. Choose to apply or discard those changes. При переключении на вкладку атрибутов на предыдущей вкладке не были применены изменения. Выберите, применить или отменить эти изменения. - + You're switching from attributes tab, while it has unapplied changes. Choose to apply or discard those changes. На вкладке атрибутов не были применены изменения. Выберите, применить или отменить эти изменения. @@ -4007,47 +3765,48 @@ QObject - + + Confirm action Подтверждение действия - - Failed to find password settings container - Не удалось найти контейнер парольных настроек + + Password settings container is not available + - - Fine-grained password policies - Детализированные политики паролей + + Sites container is not available + - + Sites Сайты - + Enabled Включено - + User configuration disabled Параметры конфигурации пользователя отключены - + Computer configuration disabled Параметры конфигурации компьютера отключены - + Disabled Отключено - + Undefined GPO status Статус не определён @@ -4062,65 +3821,64 @@ Ошибка + Failed to start GPUI. Check that it's installed. Не удалось запустить GPUI. Проверьте установлен ли он. - - + + Creation is not available Создание не доступно - - + + ADMC is connected to DC without the PDC-Emulator role - group policy creation is prohibited by the setting. Connect to PDC-Emulator? ADMC подключен к КД без роли PDC-Emulator - создание групповых политик запрещено настройкой. Подключиться к PDC-контроллеру? - + Edition is not available Редактирование не доступно - + ADMC is connected to DC without the PDC-Emulator role - group policy editing is prohibited by the setting. Connect to PDC-Emulator? ADMC подключен к КД без роли PDC-Emulator - редактирование групповых политик запрещено настройкой. Подключиться к PDC-контроллеру? - + PDC-Emulator is connected Подключено к PDC-Emulator - + Deletion is not available Удаление не доступно - + ADMC is connected to DC without the PDC-Emulator role - group policy deletion is prohibited by the setting. Connect to PDC-Emulator? ADMC подключен к КД без роли PDC-Emulator - удаление групповых политик запрещено настройкой. Подключиться к PDC-контроллеру? - Theme from settings not found. Fallback theme is set. - Тема, указанная в настройках, не найдена. Установлена тема по умолчанию. - - - + Theme from settings not found. System theme is set. Тема, указанная в настройках, не найдена. Установлена системная тема. - + (System) (Системная) + Loading... Загрузка... + Could not open a theme: Невозможно загрузить тему: @@ -4128,43 +3886,43 @@ QueryFolderImpl - + Query folder Папка запросов - + Query item Элемент запроса - + New Создать - + Edit Изменить - + &Import query... &Импортировать запрос... - - + + Error Ошибка - + Can't cut and paste query folder into itself. Невозможно вырезать и вставить папку запросов в саму себя. - + There's already an item with this name. Элемент с этим именем уже существует. @@ -4172,12 +3930,12 @@ QueryItemImpl - + Edit... Изменить... - + Export query... Экспортировать запрос... @@ -4209,17 +3967,17 @@ RenameGroupDialog - + Rename Group Переименовать группу - + Name: Имя: - + Group name (pre-Windows 2000): Logon name (pre-Windows 2000): Имя группы (до Windows 2000): @@ -4228,12 +3986,12 @@ RenameObjectHelper - + Object %1 was renamed. Объект %1 был переименован. - + Failed to rename object %1 Не удалось переименовать объект %1 @@ -4241,12 +3999,12 @@ RenameOtherDialog - + Rename Object Переименовать объект - + Name: Имя: @@ -4254,12 +4012,12 @@ RenamePolicyDialog - + Rename Policy Переименовать политику - + Name: Имя: @@ -4267,38 +4025,38 @@ RenameUserDialog - + Rename User Переименовать пользователя - + Display name: Display name Отображаемое имя: - + First name: Имя: - + Last name: Фамилия: - + Full name: Полное имя: - + Logon name: Имя для входа: - + Logon name (pre-Windows 2000): Имя для входа (до Windows 2000): @@ -4466,22 +4224,22 @@ Пользователи и группы - + Add... Добавить... - + Add well-known trustee... Добавить известное доверенное лицо... - + Remove Удалить - + Permissions Разрешения @@ -4501,22 +4259,22 @@ Обычные - + Extended Расширенные - + Creation/deletion Создание/удаление - + Read/write Чтение/запись - + Task delegation Делегирование задач @@ -4525,10 +4283,6 @@ More... Дополнительно... - - Delegation - Делегирование - Show descriptor in SDDL @@ -4545,65 +4299,32 @@ Этот объект - + This object and all child objects Этот объект и все дочерние объекты - + All child objects Все дочерние объекты - + Child objects: Дочерние объекты: - - Add Trustee - Добавить доверенное лицо - - - - Error - Ошибка - - - - Failed to add some trustee's because they are already in the list. - Не удалось добавить некоторых доверенных лиц, так как они уже имеются в списке. - - - - SecurityTabEdit - - - Name - Имя - - - - Allowed - Разрешено - - - - Denied - Запрещено - - - + Add Trustee Добавить доверенное лицо - + Error Ошибка - + Failed to add some trustee's because they are already in the list. Не удалось добавить некоторых доверенных лиц, так как они уже имеются в списке. @@ -4633,7 +4354,7 @@ SelectContainerDialog - + Select Container Select a container Выбор контейнера @@ -4647,12 +4368,12 @@ SelectObjectAdvancedDialog - + Select Object Выбор объекта - + &View &Вид @@ -4660,85 +4381,85 @@ SelectObjectDialog - + Select Object Выбор объекта - + Add Добавить - + Name Имя - + Type Тип - + Folder Папка - + Remove Удалить - + Advanced Продвинутый - + Classes: Классы: - + Search in: Искать в: - + Name: Имя: - + Selected objects: Выбранные объекты: - - - - + + + + Error Ошибка - + You must select at least one object. Требуется выбрать хотя бы один объект. - + Failed to find any matches. Совпадений не найдено. - + Selected object is already in the list. Выбранный объект уже имеется в списке. - + This selection accepts only one object. Remove extra objects to proceed. Здесь можно выбрать только один объект. Для продолжения уберите лишние объекты. @@ -4746,12 +4467,12 @@ SelectObjectMatchDialog - + Select Match Выбор совпадения - + There are multiple matches. Select one or more to add to the list. Было найдено несколько совпадений. Выберите одно или несколько совпадений для добавления в список. @@ -4759,7 +4480,7 @@ SelectPolicyDialog - + Select Policy Выбрать политику @@ -4801,22 +4522,22 @@ << Убрать - + Sites not in this site link Сайты не в этой связи - + Sites in this site link Сайты в этой связи - + Site links not included in this bridge Связи сайтов не в этом мосте - + Site links included in this bridge Связи сайтов в этом мосте @@ -4824,17 +4545,17 @@ SitesLinkEdit - + Site link object must link at least two sites Связь должна связывать минимум два сайта - + Link bridge object must link at least two site links Мост должен связывать минимум две связи сайтов - + Error Ошибка @@ -5017,7 +4738,7 @@ country_widget - + None Нет @@ -5025,7 +4746,7 @@ object_impl - + %n object(s) %n объект @@ -5037,20 +4758,28 @@ object_impl.cpp - + Failed to connect to server while searching for objects. Не удалось подключиться к серверу во время поиска объектов. - + Could not load all objects. Increase object display limit in Filter Options or reduce number of objects by applying a filter. Filter Options is accessible from main window's menubar via the "View" menu. Не удалось загрузить все объекты. Увеличьте лимит отображения объектов в опциях или уменьшите количество объектов, применив фильтр. Параметры фильтра доступны в меню «Вид». + + password_settings_impl + + + Password settings + Параметры паролей + + policy_root_impl - + Group Policy Objects Объекты групповой политики @@ -5058,7 +4787,7 @@ query - + Saved Queries Сохранённые запросы @@ -5066,35 +4795,36 @@ query.cpp - + Name may not be empty Имя не может быть пустым - - - - + + + + + Error Ошибка - + There's already an item with this name. Элемент с этим именем уже существует. - + Names cannot contain "/". Имена не могут содержать «/». - + Query file is corrupted. Файл запроса повреждён. - + Could not open a query file. Невозможно открыть файл запроса. @@ -5102,12 +4832,12 @@ query_folder.cpp - + Name Имя - + Description Описание @@ -5115,7 +4845,7 @@ query_folder_impl.cpp - + Are you sure you want to delete this item? Удалить этот элемент? @@ -5123,18 +4853,18 @@ query_item_impl.cpp - + Import Query Импортировать запрос - - + + JSON (*.json) JSON (*.json) - + Export Query Экспортировать запрос @@ -5142,12 +4872,12 @@ utils.cpp - + Input field for Name contains one or more of the following illegal characters: # , + " \ < > ; = (leading space) (trailing space) (leading question mark) Поле ввода "Имя" содержит один или несколько из следующих недопустимых символов: # , + " \ < > ; = (пробел в начале) (пробел в конце) (? в начале) - + Error Ошибка diff --git a/src/admc/console_impls/item_type.h b/src/admc/console_impls/item_type.h index 71181d43f..17bcfdbb6 100644 --- a/src/admc/console_impls/item_type.h +++ b/src/admc/console_impls/item_type.h @@ -34,6 +34,7 @@ enum ItemType { ItemType_FindPolicy, ItemType_FoundPolicy, ItemType_DomainInfo, + ItemType_PasswordSettings, ItemType_LAST, }; diff --git a/src/admc/console_impls/object_impl/console_object_operations.cpp b/src/admc/console_impls/object_impl/console_object_operations.cpp index 3e25314d9..4ed90b9d3 100644 --- a/src/admc/console_impls/object_impl/console_object_operations.cpp +++ b/src/admc/console_impls/object_impl/console_object_operations.cpp @@ -613,17 +613,17 @@ bool ConsoleObjectTreeOperations::console_object_deletion_dialog(ConsoleWidget * } void ConsoleObjectTreeOperations::console_tree_add_password_settings(ConsoleWidget *console, AdInterface &ad) { + QStandardItem *password_settings_root = console->add_scope_item(ItemType_PasswordSettings, console->domain_info_index())[0]; + password_settings_root->setText(QCoreApplication::translate("password_settings_impl", "Password settings")); + password_settings_root->setIcon(g_icon_manager->item_icon(ItemIcon_Password_Settings_Object)); + password_settings_root->setDragEnabled(false); const QString filter = filter_CONDITION(Condition_Equals, ATTRIBUTE_OBJECT_CLASS, CLASS_PSO_CONTAINER); auto search_results = ad.search(g_adconfig->domain_dn(), SearchScope_All, filter, {}); const QString err = QObject::tr("Password settings container is not available"); - if (search_results.isEmpty() || search_results.values()[0].is_empty()) { - g_status->add_message(err, StatusType_Info); - return; + if (!search_results.isEmpty() && !search_results.values()[0].is_empty()) { + console_object_item_data_load(password_settings_root, search_results.values()[0]); } - - const int pso_container_sort_idx = 3; - console_tree_add_root_child(console, search_results.values()[0], pso_container_sort_idx, - QObject::tr("Fine-grained password policies")); + console->set_item_sort_index(password_settings_root->index(), 3); } QString ConsoleObjectTreeOperations::console_object_count_string(ConsoleWidget *console, const QModelIndex &index) { diff --git a/src/admc/console_impls/object_impl/object_impl.cpp b/src/admc/console_impls/object_impl/object_impl.cpp index 89dcadbea..9ade1417d 100755 --- a/src/admc/console_impls/object_impl/object_impl.cpp +++ b/src/admc/console_impls/object_impl/object_impl.cpp @@ -212,22 +212,11 @@ void ObjectImpl::activate(const QModelIndex &index) { } QList ObjectImpl::get_all_custom_actions() const { - QList out = { - new_action, - find_action, - add_to_group_action, - enable_action, - disable_action, - reset_password_action, - reset_account_action, - edit_upn_suffixes_action, - move_action, - create_pso_action, - create_subnet_action, - create_site_action, - create_site_link_action, - create_site_link_bridge_action - }; + QList out = {new_action, find_action, add_to_group_action, + enable_action, disable_action, reset_password_action, + reset_account_action, edit_upn_suffixes_action, move_action, + create_subnet_action, create_site_action, create_site_link_action, + create_site_link_bridge_action}; return out; } @@ -247,7 +236,6 @@ QSet ObjectImpl::get_custom_actions(const QModelIndex &index, const b const bool is_group = (object_class == CLASS_GROUP); const bool is_domain = (object_class == CLASS_DOMAIN); const bool is_computer = (object_class == CLASS_COMPUTER); - const bool is_pso_container = (object_class == CLASS_PSO_CONTAINER); const bool is_sites_container = (object_class == CLASS_SITES_CONTAINER); const bool is_subnet_container = (object_class == CLASS_SUBNET_CONTAINER); const bool is_site_links_container = (object_class == CLASS_INTER_SITE_TRANSPORT); @@ -285,10 +273,6 @@ QSet ObjectImpl::get_custom_actions(const QModelIndex &index, const b out.insert(edit_upn_suffixes_action); } - if (is_pso_container) { - out.insert(create_pso_action); - } - if (is_sites_container) { out.insert(create_site_action); } @@ -1003,14 +987,12 @@ void ObjectImpl::setup_actions() { new_menu->addAction(action); } - create_pso_action = new QAction(tr("Create password setting object"), this); create_subnet_action = new QAction(tr("Create subnet"), this); create_site_action = new QAction(tr("Create site"), this); create_site_link_action = new QAction(tr("Create site link"), this); create_site_link_bridge_action = new QAction(tr("Create site link bridge"), this); QHash all_create_action_map {standard_create_action_map}; - all_create_action_map[CLASS_PSO] = create_pso_action; all_create_action_map[CLASS_SUBNET] = create_subnet_action; all_create_action_map[CLASS_SITE] = create_site_action; all_create_action_map[CLASS_SITE_LINK] = create_site_link_action; diff --git a/src/admc/console_impls/object_impl/object_impl.h b/src/admc/console_impls/object_impl/object_impl.h index 647b2cbc7..f2435ef92 100644 --- a/src/admc/console_impls/object_impl/object_impl.h +++ b/src/admc/console_impls/object_impl/object_impl.h @@ -136,7 +136,6 @@ private slots: QAction *reset_account_action; QAction *edit_upn_suffixes_action; QAction *new_action; - QAction *create_pso_action; QAction *create_subnet_action; QAction *create_site_action; QAction *create_site_link_action; diff --git a/src/admc/console_impls/password_settings_impl.cpp b/src/admc/console_impls/password_settings_impl.cpp new file mode 100644 index 000000000..28dd2b3bf --- /dev/null +++ b/src/admc/console_impls/password_settings_impl.cpp @@ -0,0 +1,127 @@ +/* + * ADMC - AD Management Center + * + * Copyright (C) 2020-2026 BaseALT Ltd. + * Copyright (C) 2026 Yuri Kozyrev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "console_impls/password_settings_impl.h" + +#include "ad_defines.h" +#include "adldap.h" +#include "console_impls/item_type.h" +#include "console_impls/object_impl/object_impl.h" +#include "console_impls/policy_impl.h" +#include "console_widget/results_view.h" +#include "create_dialogs/create_policy_dialog.h" +#include "fsmo/fsmo_utils.h" +#include "globals.h" +#include "object_impl/console_object_operations.h" +#include "results_widgets/pso_results_widget/pso_results_widget.h" +#include "status.h" +#include "utils.h" + +#include +#include +#include +#include + +PasswordSettingsImpl::PasswordSettingsImpl(ConsoleWidget *console_arg) +: ConsoleImpl(console_arg) { + results_widget = new PSOResultsWidget(console_arg); + + create_pso_action = + new QAction(tr("Create password settings object"), this); + + connect(create_pso_action, &QAction::triggered, this, [this]() { + const QString parent_dn = get_selected_target_dn( + console, ItemType_PasswordSettings, ObjectRole_DN); + ConsoleObjectTreeOperations::console_object_create( + {console}, CLASS_PSO, parent_dn); + }); +} + +void PasswordSettingsImpl::fetch(const QModelIndex &index) { + AdInterface ad; + if (ad_failed(ad, console)) { + return; + } + + //TODO:(kozyrevid) refactor this cast and other like it + dynamic_cast(results_widget) + ->update(global_password_settings()); + + QHash results = ad.search( + g_adconfig->pso_container_dn(), SearchScope_All, "", QStringList()); + is_PSO_container_available = !results.isEmpty(); + results.removeIf([](QHash::iterator object) { + return object.value().get_string(ATTRIBUTE_OBJECT_CLASS) == + CLASS_PSO_CONTAINER; + }); + + ConsoleObjectTreeOperations::add_objects_to_console( + console, results.values(), index); +} + +void PasswordSettingsImpl::refresh(const QList &index_list) { + const QModelIndex index = index_list[0]; + + console->delete_children(index); + fetch(index); +} + +QList PasswordSettingsImpl::get_all_custom_actions() const { + return {create_pso_action}; +} + +QSet PasswordSettingsImpl::get_custom_actions( + const QModelIndex &index, const bool single_selection) const { + UNUSED_ARG(index); + UNUSED_ARG(single_selection); + + auto all_actions = get_all_custom_actions(); + return {all_actions.begin(), all_actions.end()}; +} + +QSet PasswordSettingsImpl::get_disabled_custom_actions( + const QModelIndex &index, const bool single_selection) const { + UNUSED_ARG(index); + UNUSED_ARG(single_selection); + + return is_PSO_container_available ? QSet{} : + QSet{create_pso_action}; +} + +QSet PasswordSettingsImpl::get_standard_actions( + const QModelIndex &index, const bool single_selection) const { + UNUSED_ARG(index); + UNUSED_ARG(single_selection); + + return {StandardAction_Refresh, StandardAction_Properties}; +} + +QList PasswordSettingsImpl::column_labels() const { + return ConsoleObjectTreeOperations::object_impl_column_labels(); +} + +QList PasswordSettingsImpl::default_columns() const { + return ConsoleObjectTreeOperations::object_impl_default_columns(); +} + +void PasswordSettingsImpl::properties(const QList &index_list) { + ConsoleObjectTreeOperations::console_object_properties( + {console}, index_list, ObjectRole_DN, {CLASS_PSO_CONTAINER}); +} diff --git a/src/admc/console_impls/password_settings_impl.h b/src/admc/console_impls/password_settings_impl.h new file mode 100644 index 000000000..14c2e5efb --- /dev/null +++ b/src/admc/console_impls/password_settings_impl.h @@ -0,0 +1,61 @@ +/* + * ADMC - AD Management Center + * + * Copyright (C) 2020-2026 BaseALT Ltd. + * Copyright (C) 2026 Yuri Kozyrev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef PASSWORD_SETTINGS_IMPL_H +#define PASSWORD_SETTINGS_IMPL_H + +#include "console_widget/console_impl.h" +#include "console_widget/console_widget.h" + +class AdObject; +class AdInterface; + +/** + * @class + * @brief Impl for Password Settings Container. Displays global password + * settings for the domain they are applied whenever no PSO can't be used. + */ +class PasswordSettingsImpl final : public ConsoleImpl { + Q_OBJECT + +public: + PasswordSettingsImpl(ConsoleWidget *console_arg); + + void fetch(const QModelIndex &index) override; + void refresh(const QList &index_list) override; + void properties(const QList &index_list) override; + + QList get_all_custom_actions() const override; + QSet get_custom_actions( + const QModelIndex &index, const bool single_selection) const override; + QSet get_disabled_custom_actions( + const QModelIndex &index, const bool single_selection) const override; + QSet get_standard_actions( + const QModelIndex &index, const bool single_selection) const override; + + QList column_labels() const override; + QList default_columns() const override; + +private: + QAction *create_pso_action; + bool is_PSO_container_available = false; +}; + +#endif /* PASSWORD_SETTINGS_IMPL_H */ diff --git a/src/admc/console_widget/console_impl.h b/src/admc/console_widget/console_impl.h index d4f32c335..9faaa4532 100644 --- a/src/admc/console_widget/console_impl.h +++ b/src/admc/console_widget/console_impl.h @@ -141,7 +141,6 @@ class ConsoleImpl : public QObject { void set_results_view(ResultsView *view); void set_results_widget(QWidget *widget); -private: ResultsView *results_view; QWidget *results_widget; }; diff --git a/src/admc/main_window.cpp b/src/admc/main_window.cpp index 63f39384c..4c62be0ec 100644 --- a/src/admc/main_window.cpp +++ b/src/admc/main_window.cpp @@ -20,6 +20,7 @@ */ #include "main_window.h" +#include "console_impls/password_settings_impl.h" #include "ui_main_window.h" #include "about_dialog.h" @@ -483,6 +484,9 @@ void MainWindow::init_on_connect(AdInterface &ad) { auto policy_impl = new PolicyImpl(ui->console); ui->console->register_impl(ItemType_Policy, policy_impl); + auto pso_impl = new PasswordSettingsImpl(ui->console); + ui->console->register_impl(ItemType_PasswordSettings, pso_impl); + auto query_item_impl = new QueryItemImpl(ui->console); ui->console->register_impl(ItemType_QueryItem, query_item_impl); diff --git a/src/admc/results_widgets/pso_results_widget/pso_edit_widget.cpp b/src/admc/results_widgets/pso_results_widget/pso_edit_widget.cpp index cc9acb73b..0c398ccc3 100644 --- a/src/admc/results_widgets/pso_results_widget/pso_edit_widget.cpp +++ b/src/admc/results_widgets/pso_results_widget/pso_edit_widget.cpp @@ -18,6 +18,7 @@ */ #include "pso_edit_widget.h" +#include "ad_defines.h" #include "ui_pso_edit_widget.h" #include "ad_interface.h" #include "ad_object.h" @@ -26,14 +27,17 @@ #include "managers/icon_manager.h" #include "status.h" #include "globals.h" +#include "ad_config.h" +#include "utils.h" #include -// #include - PSOEditWidget::PSOEditWidget(QWidget *parent) : QWidget(parent), ui(new Ui::PSOEditWidget) { +/** +* @brief Creates PSOEditWidget and initializes it with global values +*/ ui->setupUi(this); @@ -45,94 +49,88 @@ PSOEditWidget::PSOEditWidget(QWidget *parent) : connect(ui->add_button, &QPushButton::clicked, this, &PSOEditWidget::on_add); connect(ui->remove_button, &QPushButton::clicked, this, &PSOEditWidget::on_remove); - update_defaults(); - default_setting_values = pso_settings_values(); + update_fields(global_password_settings()); } PSOEditWidget::~PSOEditWidget() { delete ui; } +/** +* @brief Sets fields of PSOEditWidget according to a given object +* @param passwd_settings_obj The object with new values +* @details Object can be a PSO or object representing global password settings +* those types of objects are distiguished based on objects' CN, if CN is present +* the object is considered to be a PSO, othervise it's treated as global +* settings object. If settings are global the following fields are not +* displayed: name, precedence and list of users policy is applied to +*/ void PSOEditWidget::update(const AdObject &passwd_settings_obj) { - ui->name_edit->setText(passwd_settings_obj.get_string(ATTRIBUTE_CN)); - ui->name_edit->setReadOnly(true); - - ui->precedence_spinbox->setValue(passwd_settings_obj.get_int(ATTRIBUTE_MS_DS_PASSWORD_SETTINGS_PRECEDENCE)); - ui->min_passwd_len_spinbox->setValue(passwd_settings_obj.get_int(ATTRIBUTE_MS_DS_MIN_PASSWORD_LENGTH)); - ui->history_length_spinbox->setValue(passwd_settings_obj.get_int(ATTRIBUTE_MS_DS_PASSWORD_HISTORY_LENGTH)); - ui->logon_attempts_spinbox->setValue(passwd_settings_obj.get_int(ATTRIBUTE_MS_DS_LOCKOUT_THRESHOLD)); - - ui->lockout_duration_spinbox->setValue(spinbox_timespan_units(passwd_settings_obj, ATTRIBUTE_MS_DS_LOCKOUT_DURATION)); - ui->reset_lockout_spinbox->setValue(spinbox_timespan_units(passwd_settings_obj, ATTRIBUTE_MS_DS_LOCKOUT_OBSERVATION_WINDOW)); - ui->min_age_spinbox->setValue(spinbox_timespan_units(passwd_settings_obj, ATTRIBUTE_MS_DS_MIN_PASSWORD_AGE)); - ui->max_age_spinbox->setValue(spinbox_timespan_units(passwd_settings_obj, ATTRIBUTE_MS_DS_MAX_PASSWORD_AGE)); - - ui->complexity_req_checkbox->setChecked(passwd_settings_obj.get_bool(ATTRIBUTE_MS_DS_PASSWORD_COMPLEXITY_ENABLED)); - ui->store_passwd_checkbox->setChecked(passwd_settings_obj.get_bool(ATTRIBUTE_MS_DS_PASSWORD_REVERSIBLE_ENCRYPTION_ENABLED)); - - ui->applied_list_widget->clear(); - dn_applied_list = passwd_settings_obj.get_strings(ATTRIBUTE_PSO_APPLIES_TO); - - if (dn_applied_list.isEmpty()) { - ui->remove_button->setDisabled(true); - return; - } - - AdInterface ad; - if (!ad.is_connected()) { - return; + if (is_global != !passwd_settings_obj.contains(ATTRIBUTE_CN)) { + is_global = !passwd_settings_obj.contains(ATTRIBUTE_CN); + ui->name_edit->setVisible(!is_global); + ui->name_label->setVisible(!is_global); + ui->precedence_label->setVisible(!is_global); + ui->precedence_spinbox->setVisible(!is_global); + ui->groupBox->setVisible(!is_global); + ui->line->setVisible(!is_global); + ui->groupBox_2->setTitle(is_global ? tr("Global password settings") : + tr("Password settings")); } - for (const QString &dn : dn_applied_list) { - AdObject applied_object = ad.search_object(dn, {ATTRIBUTE_OBJECT_CATEGORY}); - if (applied_object.is_empty()) { - continue; - } - QListWidgetItem *item = new QListWidgetItem(g_icon_manager->object_icon(applied_object), - dn_get_name(dn), - ui->applied_list_widget); - item->setData(AppliedItemRole_DN, dn); - } + update_fields(passwd_settings_obj); } +/** +* @brief Returns current values of widget fieds set by the user +* @return Hashmap of new values +*/ QHash> PSOEditWidget::pso_settings_values() { using namespace std::chrono; QHash> settings; - settings[ATTRIBUTE_CN] = {ui->name_edit->text().trimmed().toUtf8()}; + settings[replace_attribute(ATTRIBUTE_CN)] = {ui->name_edit->text().trimmed().toUtf8()}; - settings[ATTRIBUTE_MS_DS_PASSWORD_SETTINGS_PRECEDENCE] = {QByteArray::number(ui->precedence_spinbox->value())}; - settings[ATTRIBUTE_MS_DS_MIN_PASSWORD_LENGTH] = {QByteArray::number(ui->min_passwd_len_spinbox->value())}; - settings[ATTRIBUTE_MS_DS_PASSWORD_HISTORY_LENGTH] = {QByteArray::number(ui->history_length_spinbox->value())}; - settings[ATTRIBUTE_MS_DS_LOCKOUT_THRESHOLD] = {QByteArray::number(ui->logon_attempts_spinbox->value())}; + settings[replace_attribute(ATTRIBUTE_MS_DS_PASSWORD_SETTINGS_PRECEDENCE)] = {QByteArray::number(ui->precedence_spinbox->value())}; + settings[replace_attribute(ATTRIBUTE_MS_DS_MIN_PASSWORD_LENGTH)] = {QByteArray::number(ui->min_passwd_len_spinbox->value())}; + settings[replace_attribute(ATTRIBUTE_MS_DS_PASSWORD_HISTORY_LENGTH)] = {QByteArray::number(ui->history_length_spinbox->value())}; + settings[replace_attribute(ATTRIBUTE_MS_DS_LOCKOUT_THRESHOLD)] = {QByteArray::number(ui->logon_attempts_spinbox->value())}; - settings[ATTRIBUTE_MS_DS_LOCKOUT_DURATION] = { + settings[replace_attribute(ATTRIBUTE_MS_DS_LOCKOUT_DURATION)] = { QByteArray::number(-duration_cast( - minutes(ui->lockout_duration_spinbox->value())).count() * MILLIS_TO_100_NANOS) - }; - settings[ATTRIBUTE_MS_DS_LOCKOUT_OBSERVATION_WINDOW] = { + minutes(ui->lockout_duration_spinbox->value())) + .count() * + MILLIS_TO_100_NANOS)}; + settings[replace_attribute(ATTRIBUTE_MS_DS_LOCKOUT_OBSERVATION_WINDOW)] = { QByteArray::number(-duration_cast( minutes(ui->reset_lockout_spinbox->value())).count() * MILLIS_TO_100_NANOS) }; - settings[ATTRIBUTE_MS_DS_MIN_PASSWORD_AGE] = { + settings[replace_attribute(ATTRIBUTE_MS_DS_MIN_PASSWORD_AGE)] = { QByteArray::number(-duration_cast( - hours(24 * ui->min_age_spinbox->value())).count() * MILLIS_TO_100_NANOS) - }; - settings[ATTRIBUTE_MS_DS_MAX_PASSWORD_AGE] = { + hours(24 * ui->min_age_spinbox->value())) + .count() * + MILLIS_TO_100_NANOS)}; + settings[replace_attribute(ATTRIBUTE_MS_DS_MAX_PASSWORD_AGE)] = { QByteArray::number(-duration_cast( - hours(24 * ui->max_age_spinbox->value())).count() * MILLIS_TO_100_NANOS) - }; + hours(24 * ui->max_age_spinbox->value())) + .count() * + MILLIS_TO_100_NANOS)}; - settings[ATTRIBUTE_MS_DS_PASSWORD_COMPLEXITY_ENABLED] = { - QString(ui->complexity_req_checkbox->isChecked() ? LDAP_BOOL_TRUE : - LDAP_BOOL_FALSE).toUtf8() - }; - settings[ATTRIBUTE_MS_DS_PASSWORD_REVERSIBLE_ENCRYPTION_ENABLED] = { - QString(ui->store_passwd_checkbox->isChecked() ? LDAP_BOOL_TRUE : - LDAP_BOOL_FALSE).toUtf8() - }; + if (is_global) { + settings[ATTRIBUTE_PWD_PROPERTIES] = {QByteArray::number(ui->complexity_req_checkbox->isChecked() * SAM_MASK_DOMAIN_PASSWORD_COMPLEX + + ui->store_passwd_checkbox->isChecked() * SAM_MASK_DOMAIN_PASSWORD_STORE_CLEARTEXT)}; + } else { + settings[ATTRIBUTE_MS_DS_PASSWORD_COMPLEXITY_ENABLED] = { + QString(ui->complexity_req_checkbox->isChecked() ? LDAP_BOOL_TRUE : + LDAP_BOOL_FALSE) + .toUtf8()}; + settings[ATTRIBUTE_MS_DS_PASSWORD_REVERSIBLE_ENCRYPTION_ENABLED] = { + QString(ui->store_passwd_checkbox->isChecked() ? LDAP_BOOL_TRUE : + LDAP_BOOL_FALSE) + .toUtf8()}; + } if (dn_applied_list.isEmpty()) { settings[ATTRIBUTE_PSO_APPLIES_TO] = QList(); @@ -146,6 +144,10 @@ QHash> PSOEditWidget::pso_settings_values() { } QHash > PSOEditWidget::pso_settings_string_values() { +/** +* @brief Returns current values of widget fieds set by the user +* @return Hashmap of new values +*/ QHash> string_value_settings; QHash> byte_value_settings = pso_settings_values(); @@ -160,27 +162,37 @@ QHash > PSOEditWidget::pso_settings_string_values() { return string_value_settings; } +/** +* @brief Returns list of users to which the PSO applies +*/ QStringList PSOEditWidget::applied_dn_list() const { return dn_applied_list; } +/** +* @brief Returns the name edit object +*/ QLineEdit *PSOEditWidget::name_line_edit() { return ui->name_edit; } +/** +* @brief Compares current field values to their respective defaults (global +* settings) +*/ bool PSOEditWidget::settings_are_default() { auto current_values = pso_settings_values(); const QStringList excluded_attrs = { ATTRIBUTE_CN, ATTRIBUTE_MS_DS_PASSWORD_SETTINGS_PRECEDENCE, - ATTRIBUTE_APPLIES_TO - }; - for (const QString &attr : default_setting_values.keys()) { + ATTRIBUTE_APPLIES_TO}; + auto defaults = global_password_settings().get_attributes_data(); + for (const QString &attr : defaults.keys()) { if (excluded_attrs.contains(attr)) { continue; } - if (default_setting_values[attr] != current_values[attr]) { + if (defaults[pso_attributes_to_global_attributes[attr]] != current_values[attr]) { return false; } } @@ -188,24 +200,6 @@ bool PSOEditWidget::settings_are_default() { return true; } -void PSOEditWidget::update_defaults() { - // TODO: Get defaults from Default Domain Policy. - - ui->min_passwd_len_spinbox->setValue(7); - ui->history_length_spinbox->setValue(24); - ui->logon_attempts_spinbox->setValue(0); - - ui->lockout_duration_spinbox->setValue(30); - ui->reset_lockout_spinbox->setValue(30); - ui->min_age_spinbox->setValue(1); - ui->max_age_spinbox->setValue(42); - - ui->complexity_req_checkbox->setChecked(true); - ui->store_passwd_checkbox->setChecked(false); - - ui->applied_list_widget->clear(); -} - void PSOEditWidget::on_add() { auto dialog = new SelectObjectDialog({CLASS_USER, CLASS_GROUP}, SelectObjectDialogMultiSelection_Yes, this); dialog->setWindowTitle(tr("Add applied users/group")); @@ -231,6 +225,7 @@ void PSOEditWidget::on_remove() { void PSOEditWidget::set_read_only(bool read_only) { QList spinbox_children = findChildren(QString(), Qt::FindChildrenRecursively); + ui->name_edit->setReadOnly(true); for (auto spinbox : spinbox_children) { spinbox->setReadOnly(read_only); } @@ -247,20 +242,95 @@ void PSOEditWidget::set_read_only(bool read_only) { } int PSOEditWidget::spinbox_timespan_units(const AdObject &obj, const QString &attribute) { +/** +* @brief Reads specified timespan attribute from given PSO object and converts +* it to apropriate units +* @param obj PSO object to read attribute from +* @param attribute The attribute to retrieve +* @return Attribute value in specified units +*/ using namespace std::chrono; qint64 hundred_nanos = -obj.get_value(attribute).toLongLong(); milliseconds msecs(hundred_nanos / MILLIS_TO_100_NANOS); - if (attribute == ATTRIBUTE_MS_DS_LOCKOUT_OBSERVATION_WINDOW || attribute == ATTRIBUTE_MS_DS_LOCKOUT_DURATION) { + if (attribute == + replace_attribute(ATTRIBUTE_MS_DS_LOCKOUT_OBSERVATION_WINDOW) || + attribute == replace_attribute(ATTRIBUTE_MS_DS_LOCKOUT_DURATION)) { int mins = duration_cast(msecs).count(); return mins; } - if (attribute == ATTRIBUTE_MS_DS_MIN_PASSWORD_AGE || attribute == ATTRIBUTE_MS_DS_MAX_PASSWORD_AGE) { + if (attribute == replace_attribute(ATTRIBUTE_MS_DS_MIN_PASSWORD_AGE) || + attribute == replace_attribute(ATTRIBUTE_MS_DS_MAX_PASSWORD_AGE)) { int days = duration_cast(msecs).count() / 24; return days; } return 0; } + +/** +* @brief Deduces apropriate attribute name from PSO atribute name based on +* whether or not PSO is global. Basicaly method converts PSO attributes to +* global password settings attributes if needed +* @param attribute_name Initial attribute to be converted +* @return The apropriate attribute considering object type +*/ +QString PSOEditWidget::replace_attribute(QString attribute_name) { + return is_global ? (pso_attributes_to_global_attributes.contains(attribute_name) ? + pso_attributes_to_global_attributes[attribute_name] : + QString()) : + attribute_name; +}; + +/** +* @brief Sets fields of PSOEditWidget according to a given object +* @param passwd_settings_obj The object with new values +*/ +void PSOEditWidget::update_fields(const AdObject &passwd_settings_obj) { + ui->name_edit->setText(passwd_settings_obj.get_string(replace_attribute(ATTRIBUTE_CN))); + + ui->precedence_spinbox->setValue(passwd_settings_obj.get_int(replace_attribute(ATTRIBUTE_MS_DS_PASSWORD_SETTINGS_PRECEDENCE))); + ui->min_passwd_len_spinbox->setValue(passwd_settings_obj.get_int(replace_attribute(ATTRIBUTE_MS_DS_MIN_PASSWORD_LENGTH))); + ui->history_length_spinbox->setValue(passwd_settings_obj.get_int(replace_attribute(ATTRIBUTE_MS_DS_PASSWORD_HISTORY_LENGTH))); + ui->logon_attempts_spinbox->setValue(passwd_settings_obj.get_int(replace_attribute(ATTRIBUTE_MS_DS_LOCKOUT_THRESHOLD))); + + ui->lockout_duration_spinbox->setValue(spinbox_timespan_units(passwd_settings_obj, replace_attribute(ATTRIBUTE_MS_DS_LOCKOUT_DURATION))); + ui->reset_lockout_spinbox->setValue(spinbox_timespan_units(passwd_settings_obj, replace_attribute(ATTRIBUTE_MS_DS_LOCKOUT_OBSERVATION_WINDOW))); + ui->min_age_spinbox->setValue(spinbox_timespan_units(passwd_settings_obj, replace_attribute(ATTRIBUTE_MS_DS_MIN_PASSWORD_AGE))); + ui->max_age_spinbox->setValue(spinbox_timespan_units(passwd_settings_obj, replace_attribute(ATTRIBUTE_MS_DS_MAX_PASSWORD_AGE))); + + if (is_global) { + int pwd_properties = passwd_settings_obj.get_int(ATTRIBUTE_PWD_PROPERTIES); + ui->complexity_req_checkbox->setChecked(pwd_properties & SAM_MASK_DOMAIN_PASSWORD_COMPLEX); + ui->store_passwd_checkbox->setChecked(pwd_properties & SAM_MASK_DOMAIN_PASSWORD_STORE_CLEARTEXT); + } else { + ui->complexity_req_checkbox->setChecked(passwd_settings_obj.get_bool(ATTRIBUTE_MS_DS_PASSWORD_COMPLEXITY_ENABLED)); + ui->store_passwd_checkbox->setChecked(passwd_settings_obj.get_bool(ATTRIBUTE_MS_DS_PASSWORD_REVERSIBLE_ENCRYPTION_ENABLED)); + } + + ui->applied_list_widget->clear(); + dn_applied_list = passwd_settings_obj.get_strings(ATTRIBUTE_PSO_APPLIES_TO); + + if (dn_applied_list.isEmpty()) { + ui->remove_button->setDisabled(true); + return; + } + + AdInterface ad; + if (!ad.is_connected()) { + return; + } + + for (const QString &dn : dn_applied_list) { + AdObject applied_object = ad.search_object(dn, {ATTRIBUTE_OBJECT_CATEGORY}); + if (applied_object.is_empty()) { + continue; + } + QListWidgetItem *item = new QListWidgetItem(g_icon_manager->object_icon(applied_object), + dn_get_name(dn), + ui->applied_list_widget); + item->setData(AppliedItemRole_DN, dn); + } +} diff --git a/src/admc/results_widgets/pso_results_widget/pso_edit_widget.h b/src/admc/results_widgets/pso_results_widget/pso_edit_widget.h index f9fbb962a..61290e768 100644 --- a/src/admc/results_widgets/pso_results_widget/pso_edit_widget.h +++ b/src/admc/results_widgets/pso_results_widget/pso_edit_widget.h @@ -22,6 +22,8 @@ #include +#include "ad_defines.h" + namespace Ui { class PSOEditWidget; } @@ -32,6 +34,11 @@ class QLineEdit; class QSpinBox; class QCheckBox; +/** + * @class PSOEditWidget + * @brief Used to represent password settings including global settings and PSOs + * in PSOResultsWidget and new PSO being created in CreatePSOWidget +*/ class PSOEditWidget final : public QWidget { Q_OBJECT @@ -40,7 +47,6 @@ class PSOEditWidget final : public QWidget { ~PSOEditWidget(); void update(const AdObject &passwd_settings_obj); - void update_defaults(); void set_read_only(bool read_only); /*! @@ -60,11 +66,23 @@ class PSOEditWidget final : public QWidget { private: Ui::PSOEditWidget *ui; QStringList dn_applied_list; - QHash> default_setting_values; + bool is_global; + QHash pso_attributes_to_global_attributes = { + {ATTRIBUTE_MS_DS_MIN_PASSWORD_LENGTH, ATTRIBUTE_MIN_PWD_LENGTH}, + {ATTRIBUTE_MS_DS_PASSWORD_HISTORY_LENGTH, ATTRIBUTE_PWD_HISTORY_LENGTH}, + {ATTRIBUTE_MS_DS_LOCKOUT_THRESHOLD, ATTRIBUTE_LOCKOUT_THRESHOLD}, + {ATTRIBUTE_MS_DS_LOCKOUT_DURATION, ATTRIBUTE_LOCKOUT_DURATION}, + {ATTRIBUTE_MS_DS_LOCKOUT_OBSERVATION_WINDOW, ATTRIBUTE_LOCKOUT_OBSERVATION_WINDOW}, + {ATTRIBUTE_MS_DS_MIN_PASSWORD_AGE, ATTRIBUTE_MIN_PWD_AGE}, + {ATTRIBUTE_MS_DS_MAX_PASSWORD_AGE, ATTRIBUTE_MAX_PWD_AGE}}; void on_add(); void on_remove(); + void update_fields(const AdObject &passwd_settings_obj); + + QString replace_attribute(QString attribute_name); + /*! * Returns appropriate timespan unit value depending on given attribute. * It is used to fill password timespan setting checkboxes. diff --git a/src/admc/results_widgets/pso_results_widget/pso_results_widget.cpp b/src/admc/results_widgets/pso_results_widget/pso_results_widget.cpp index e948d823c..a529ee9a1 100644 --- a/src/admc/results_widgets/pso_results_widget/pso_results_widget.cpp +++ b/src/admc/results_widgets/pso_results_widget/pso_results_widget.cpp @@ -25,13 +25,16 @@ #include "../ui_results_widget_base.h" #include -// #include - PSOResultsWidget::PSOResultsWidget(QWidget *parent) : ResultsWidgetBase(parent), pso_edit_widget(new PSOEditWidget(this)) { ui->verticalLayout->addWidget(pso_edit_widget); + + ui->edit_button->setDisabled(true); + ui->cancel_button->setDisabled(true); + ui->apply_button->setDisabled(true); + pso_edit_widget->set_read_only(true); } void PSOResultsWidget::update(const QModelIndex &index) { diff --git a/src/admc/utils.cpp b/src/admc/utils.cpp index 5b20b65b0..f2be54ffd 100755 --- a/src/admc/utils.cpp +++ b/src/admc/utils.cpp @@ -495,3 +495,22 @@ bool creds_is_saved(const QString &username) { remembered_users.toStringList().contains(username); return saved; } + +/** +* @brief Gets global password settings as AD object +* @return An AD object representing global password settings +*/ +AdObject global_password_settings() { + AdInterface ad; + if (!ad.is_connected()) { + return AdObject(); + } + return ad.search_object(g_adconfig->domain_dn(), {ATTRIBUTE_PWD_PROPERTIES, + ATTRIBUTE_PWD_HISTORY_LENGTH, + ATTRIBUTE_MIN_PWD_LENGTH, + ATTRIBUTE_MIN_PWD_AGE, + ATTRIBUTE_MAX_PWD_AGE, + ATTRIBUTE_LOCKOUT_DURATION, + ATTRIBUTE_LOCKOUT_THRESHOLD, + ATTRIBUTE_LOCKOUT_OBSERVATION_WINDOW}); +} diff --git a/src/admc/utils.h b/src/admc/utils.h index db346ef55..88695a50e 100755 --- a/src/admc/utils.h +++ b/src/admc/utils.h @@ -139,4 +139,6 @@ QString current_dc_dns_host_name(AdInterface &ad); bool creds_is_saved(const QString &username); +AdObject global_password_settings(); + #endif /* UTILS_H */