diff --git a/.gear/admc.spec b/.gear/admc.spec index f9e56d5d..0e228f46 100644 --- a/.gear/admc.spec +++ b/.gear/admc.spec @@ -78,6 +78,7 @@ cd BUILD %_bindir/admc_test_ad_interface %_bindir/admc_test_select_base_widget %_bindir/admc_test_filter_widget +%_bindir/admc_test_security_tab %changelog * Wed May 12 2021 Dmitry Degtyarev 0.5.2-alt1 diff --git a/src/adldap/CMakeLists.txt b/src/adldap/CMakeLists.txt index 6d48cbbd..6e0612b2 100644 --- a/src/adldap/CMakeLists.txt +++ b/src/adldap/CMakeLists.txt @@ -23,11 +23,15 @@ add_library(adldap SHARED ad_object.cpp ad_display.cpp ad_filter.cpp + ad_security.cpp - samba/gp_manage.cpp + samba/gp_manage.c samba/ndr_security.c samba/dom_sid.c samba/replace.c + samba/ndr_misc.c + samba/libsmb_xattr.c + samba/security_descriptor.c adldap.qrc ) diff --git a/src/adldap/ad_config.cpp b/src/adldap/ad_config.cpp index 340537af..47364d0b 100644 --- a/src/adldap/ad_config.cpp +++ b/src/adldap/ad_config.cpp @@ -54,6 +54,7 @@ #define CLASS_ATTRIBUTE_SCHEMA "attributeSchema" #define CLASS_CLASS_SCHEMA "classSchema" +#define CLASS_CONTROL_ACCESS_RIGHT "controlAccessRight" #define FLAG_ATTR_IS_CONSTRUCTED 0x00000004 @@ -284,6 +285,31 @@ void AdConfig::load(AdInterface &ad, const QLocale &locale) { return out; }(); + + d->right_to_guid_map = + [&]() { + QHash out; + + const QString filter = filter_CONDITION(Condition_Equals, ATTRIBUTE_OBJECT_CLASS, CLASS_CONTROL_ACCESS_RIGHT); + + const QList attributes = { + ATTRIBUTE_CN, + ATTRIBUTE_RIGHTS_GUID, + }; + + const QString search_base = extended_rights_dn(); + + const QHash search_results = ad.search(search_base, SearchScope_Children, filter, attributes); + + for (const AdObject &object : search_results.values()) { + const QString cn = object.get_string(ATTRIBUTE_CN); + const QString guid = object.get_string(ATTRIBUTE_RIGHTS_GUID); + + out[cn] = guid; + } + + return out; + }(); } QString AdConfig::domain() const { @@ -306,6 +332,10 @@ QString AdConfig::partitions_dn() const { return QString("CN=Partitions,CN=Configuration,%1").arg(domain_head()); } +QString AdConfig::extended_rights_dn() const { + return QString("CN=Extended-Rights,%1").arg(configuration_dn()); +} + QString AdConfig::get_attribute_display_name(const Attribute &attribute, const ObjectClass &objectClass) const { if (d->attribute_display_names.contains(objectClass) && d->attribute_display_names[objectClass].contains(attribute)) { const QString display_name = d->attribute_display_names[objectClass][attribute]; @@ -525,6 +555,11 @@ bool AdConfig::get_attribute_is_constructed(const QString &attribute) const { return bit_is_set(system_flags, FLAG_ATTR_IS_CONSTRUCTED); } +QString AdConfig::get_right_guid(const QString &right_cn) const { + const QString out = d->right_to_guid_map.value(right_cn, QString()); + return out; +} + // (noncontainer classes) = (all classes) - (container classes) QList AdConfig::get_noncontainer_classes() { QList out = filter_classes; diff --git a/src/adldap/ad_config.h b/src/adldap/ad_config.h index 84898012..0b79797d 100644 --- a/src/adldap/ad_config.h +++ b/src/adldap/ad_config.h @@ -53,6 +53,7 @@ public: QString configuration_dn() const; QString schema_dn() const; QString partitions_dn() const; + QString extended_rights_dn() const; QString get_attribute_display_name(const Attribute &attribute, const ObjectClass &objectClass) const; @@ -81,6 +82,8 @@ public: void limit_edit(QLineEdit *edit, const QString &attribute); + QString get_right_guid(const QString &right_cn) const; + QList get_noncontainer_classes(); private: diff --git a/src/adldap/ad_config_p.h b/src/adldap/ad_config_p.h index 9f8ed09d..98c137d3 100644 --- a/src/adldap/ad_config_p.h +++ b/src/adldap/ad_config_p.h @@ -53,6 +53,8 @@ public: QHash class_schemas; QList add_auxiliary_classes(const QList &object_classes) const; + + QHash right_to_guid_map; }; #endif /* AD_CONFIG_P_H */ diff --git a/src/adldap/ad_defines.h b/src/adldap/ad_defines.h index bab9d541..c297f9be 100644 --- a/src/adldap/ad_defines.h +++ b/src/adldap/ad_defines.h @@ -59,6 +59,7 @@ enum LargeIntegerSubtype { enum AccountOption { AccountOption_Disabled, + AccountOption_CantChangePassword, AccountOption_PasswordExpired, AccountOption_DontExpirePassword, AccountOption_UseDesKey, @@ -87,6 +88,7 @@ enum SystemFlagsBit { SystemFlagsBit_CannotDelete = 0x80000000 }; +#define ATTRIBUTE_CN "cn" #define ATTRIBUTE_USER_ACCOUNT_CONTROL "userAccountControl" #define ATTRIBUTE_LOCKOUT_TIME "lockoutTime" #define ATTRIBUTE_ACCOUNT_EXPIRES "accountExpires" @@ -168,6 +170,7 @@ enum SystemFlagsBit { #define ATTRIBUTE_OTHER_IP_PHONE "otherIpPhone" #define ATTRIBUTE_UPN_SUFFIXES "uPNSuffixes" #define ATTRIBUTE_SECURITY_DESCRIPTOR "nTSecurityDescriptor" +#define ATTRIBUTE_RIGHTS_GUID "rightsGuid" #define CLASS_GROUP "group" #define CLASS_USER "user" @@ -195,6 +198,7 @@ enum SystemFlagsBit { #define CLASS_REMOTE_STORAGE_SERVICE "remoteStorageServicePoint" // NOTE: for schema object #define CLASS_dMD "dMD" +#define CLASS_CONTROL_ACCESS_RIGHT "controlAccessRight" #define LOCKOUT_UNLOCKED_VALUE "0" @@ -217,4 +221,52 @@ enum SystemFlagsBit { const long long MILLIS_TO_100_NANOS = 10000LL; +#define LDAP_SERVER_SD_FLAGS_OID "1.2.840.113556.1.4.801" +#define OWNER_SECURITY_INFORMATION 0x01 +#define GROUP_SECURITY_INFORMATION 0x04 +#define SACL_SECURITY_INFORMATION 0x08 +#define DACL_SECURITY_INFORMATION 0x10 + +enum PermissionState { + PermissionState_None, + PermissionState_Allowed, + PermissionState_Denied, +}; + +enum AcePermission { + AcePermission_FullControl, + AcePermission_Read, + AcePermission_Write, + AcePermission_CreateChild, + AcePermission_DeleteChild, + AcePermission_AllowedToAuthenticate, + AcePermission_ChangePassword, + AcePermission_ReceiveAs, + AcePermission_ResetPassword, + AcePermission_SendAs, + AcePermission_ReadAccountRestrictions, + AcePermission_WriteAccountRestrictions, + AcePermission_ReadGeneralInfo, + AcePermission_WriteGeneralInfo, + AcePermission_ReadGroupMembership, + AcePermission_ReadLogonInfo, + AcePermission_WriteLogonInfo, + AcePermission_ReadPersonalInfo, + AcePermission_WritePersonalInfo, + AcePermission_ReadPhoneAndMailOptions, + AcePermission_WritePhoneAndMailOptions, + AcePermission_ReadPrivateInfo, + AcePermission_WritePrivateInfo, + AcePermission_ReadPublicInfo, + AcePermission_WritePublicInfo, + AcePermission_ReadRemoteAccessInfo, + AcePermission_WriteRemoteAccessInfo, + AcePermission_ReadTerminalServerLicenseServer, + AcePermission_WriteTerminalServerLicenseServer, + AcePermission_ReadWebInfo, + AcePermission_WriteWebInfo, + + AcePermission_COUNT, +}; + #endif /* AD_DEFINES_H */ diff --git a/src/adldap/ad_display.cpp b/src/adldap/ad_display.cpp index 6ce6d1d3..ee67ce37 100644 --- a/src/adldap/ad_display.cpp +++ b/src/adldap/ad_display.cpp @@ -23,6 +23,7 @@ #include "ad_defines.h" #include "ad_utils.h" #include "ad_config.h" +#include "samba/dom_sid.h" #include #include @@ -36,7 +37,6 @@ const qint64 MINUTES_TO_SECONDS = 60LL; const qint64 HOURS_TO_SECONDS = MINUTES_TO_SECONDS * 60LL; const qint64 DAYS_TO_SECONDS = HOURS_TO_SECONDS * 24LL; -QString object_sid_display_value(const QByteArray &sid); QString large_integer_datetime_display_value(const QString &attribute, const QByteArray &bytes, const AdConfig *adconfig); QString datetime_display_value(const QString &attribute, const QByteArray &bytes, const AdConfig *adconfig); QString timespan_display_value(const QByteArray &bytes); @@ -70,6 +70,9 @@ QString attribute_display_value(const QString &attribute, const QByteArray &valu return octet_display_value(value); } } + case AttributeType_NTSecDesc: { + return QCoreApplication::translate("attribute_display", ""); + } default: { return QString(value); } @@ -99,42 +102,17 @@ QString attribute_display_values(const QString &attribute, const QList class QList; QString attribute_display_value(const QString &attribute, const QByteArray &value, const AdConfig *adconfig); QString attribute_display_values(const QString &attribute, const QList &values, const AdConfig *adconfig); +QString object_sid_display_value(const QByteArray &sid_bytes); #endif /* ATTRIBUTE_DISPLAY_H */ diff --git a/src/adldap/ad_interface.cpp b/src/adldap/ad_interface.cpp index 7bad300b..945b2143 100644 --- a/src/adldap/ad_interface.cpp +++ b/src/adldap/ad_interface.cpp @@ -24,9 +24,15 @@ #include "ad_utils.h" #include "ad_object.h" #include "ad_display.h" +#include "ad_config.h" +#include "ad_security.h" #include "samba/ndr_security.h" #include "samba/gp_manage.h" #include "samba/dom_sid.h" +#include "samba/libsmb_xattr.h" +#include "samba/security_descriptor.h" + +#include "ad_filter.h" #include #include @@ -239,6 +245,10 @@ void AdInterface::set_permanent_adconfig(AdConfig *adconfig) { AdInterfacePrivate::s_adconfig = adconfig; } +void AdInterface::set_adconfig(AdConfig *adconfig) { + d->adconfig = adconfig; +} + void AdInterface::set_log_searches(const bool enabled) { AdInterfacePrivate::s_log_searches = enabled; } @@ -277,6 +287,10 @@ void AdInterface::clear_messages() { d->messages.clear(); } +AdConfig *AdInterface::adconfig() const { + return d->adconfig; +} + // Helper f-n for search() // NOTE: cookie is starts as NULL. Then after each while // loop, it is set to the value returned by @@ -289,7 +303,9 @@ bool AdInterfacePrivate::search_paged_internal(const char *base, const int scope LDAPControl **returned_controls = NULL; struct berval *prev_cookie = cookie->cookie; struct berval *new_cookie = NULL; - + BerElement *sd_control_value_be = NULL; + berval *sd_control_value_bv = NULL; + auto cleanup = [&]() { ldap_msgfree(res); @@ -297,8 +313,27 @@ bool AdInterfacePrivate::search_paged_internal(const char *base, const int scope ldap_controls_free(returned_controls); ber_bvfree(prev_cookie); ber_bvfree(new_cookie); + ber_free(sd_control_value_be, 1); + ber_bvfree(sd_control_value_bv); }; + // NOTE: this control is needed so that ldap returns + // security descriptor attribute when we ask for all + // attributes. Otherwise it won't includ the descriptor + // in attributes. This might break something when the + // app is used by a client with not enough rights to get + // some/all parts of the descriptor. Investigate. + LDAPControl sd_control; + const char *sd_control_oid = LDAP_SERVER_SD_FLAGS_OID; + sd_control.ldctl_oid = (char *) sd_control_oid; + const int sd_control_value_int = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION); + sd_control_value_be = ber_alloc_t(LBER_USE_DER); + ber_printf(sd_control_value_be, "{i}", sd_control_value_int); + ber_flatten(sd_control_value_be, &sd_control_value_bv); + sd_control.ldctl_value.bv_len = sd_control_value_bv->bv_len; + sd_control.ldctl_value.bv_val = sd_control_value_bv->bv_val; + sd_control.ldctl_iscritical = (char) 1; + // Create page control const ber_int_t page_size = 1000; const int is_critical = 1; @@ -309,11 +344,12 @@ bool AdInterfacePrivate::search_paged_internal(const char *base, const int scope cleanup(); return false; } - LDAPControl *server_controls[2] = {page_control, NULL}; + LDAPControl *server_controls[3] = {page_control, &sd_control, NULL}; // Perform search const int attrsonly = 0; result = ldap_search_ext_s(ld, base, scope, filter, attributes, attrsonly, server_controls, NULL, NULL, LDAP_NO_LIMIT, &res); + if ((result != LDAP_SUCCESS) && (result != LDAP_PARTIAL_RESULTS)) { // NOTE: it's not really an error for an object to // not exist. For example, sometimes it's needed to @@ -1010,6 +1046,27 @@ bool AdInterface::user_set_account_option(const QString &dn, AccountOption optio bool success = false; switch (option) { + case AccountOption_CantChangePassword: { + const AdObject object = search_object(dn, {ATTRIBUTE_SECURITY_DESCRIPTOR}); + const auto old_security_state = ad_security_get_state_from_object(&object, d->adconfig); + + const QByteArray self_trustee = sid_string_to_bytes(SID_NT_SELF); + + const PermissionState new_permission_state = + [&]() { + if (set) { + return PermissionState_Denied; + } else { + return PermissionState_Allowed; + } + }(); + + const auto new_security_state = ad_security_modify(old_security_state, self_trustee, AcePermission_ChangePassword, new_permission_state); + + success = attribute_replace_security_descriptor(this, dn, new_security_state); + + break; + } case AccountOption_PasswordExpired: { QString pwdLastSet_value; if (set) { @@ -1229,7 +1286,7 @@ bool AdInterface::create_gpo(const QString &display_name, QString &dn_out) { struct ndr_pull *ndr_pull = ndr_pull_init_blob(&blob, tmp_ctx); struct security_descriptor domain_sd; - ndr_security_pull_security_descriptor(ndr_pull, NDR_SCALARS|NDR_BUFFERS, &domain_sd); + ndr_pull_security_descriptor(ndr_pull, NDR_SCALARS|NDR_BUFFERS, &domain_sd); // TODO: not sure why but my // gp_create_gpt_security_descriptor() call creates an @@ -1241,8 +1298,8 @@ bool AdInterface::create_gpo(const QString &display_name, QString &dn_out) { // Create sysvol descriptor from domain descriptor (not // one to one, some modifications are needed) struct security_descriptor *sysvol_sd; - const bool create_sd_success = gp_create_gpt_security_descriptor(tmp_ctx, &domain_sd, &sysvol_sd); - if (!create_sd_success) { + const NTSTATUS create_sd_status = gp_create_gpt_security_descriptor(tmp_ctx, &domain_sd, &sysvol_sd); + if (!NT_STATUS_IS_OK(create_sd_status)) { qDebug() << "Failed to create gpo sd"; return false; } @@ -1582,5 +1639,3 @@ QString AdMessage::text() const { AdMessageType AdMessage::type() const { return m_type; } - - diff --git a/src/adldap/ad_interface.h b/src/adldap/ad_interface.h index 77b0071c..8ee89abc 100644 --- a/src/adldap/ad_interface.h +++ b/src/adldap/ad_interface.h @@ -27,6 +27,8 @@ */ #include +#include +#include #include "ad_defines.h" @@ -35,8 +37,9 @@ class QString; class QByteArray; class QDateTime; class AdObject; -class AdConfig; +class AdConfig; template class QList; +typedef void TALLOC_CTX; enum SearchScope { SearchScope_Object, @@ -110,6 +113,7 @@ public: * override the permanent adconfig. */ static void set_permanent_adconfig(AdConfig *adconfig); + void set_adconfig(AdConfig *adconfig); static void set_log_searches(const bool enabled); @@ -120,6 +124,7 @@ public: QList messages() const; bool any_error_messages() const; void clear_messages(); + AdConfig *adconfig() const; // NOTE: If request attributes list is empty, all attributes are returned diff --git a/src/adldap/ad_object.cpp b/src/adldap/ad_object.cpp index e0c71880..d51db91b 100644 --- a/src/adldap/ad_object.cpp +++ b/src/adldap/ad_object.cpp @@ -22,6 +22,10 @@ #include "ad_utils.h" #include "ad_config.h" +#include "ad_security.h" +#include "ad_display.h" + +#include "samba/ndr_security.h" #include #include @@ -167,8 +171,20 @@ bool AdObject::get_system_flag(const SystemFlagsBit bit) const { } } -bool AdObject::get_account_option(AccountOption option) const { +bool AdObject::get_account_option(AccountOption option, AdConfig *adconfig) const { switch (option) { + case AccountOption_CantChangePassword: { + if (contains(ATTRIBUTE_SECURITY_DESCRIPTOR)) { + const auto security_state = ad_security_get_state_from_object(this, adconfig); + const QByteArray self_trustee = sid_string_to_bytes(SID_NT_SELF); + const PermissionState permission_state = security_state[self_trustee][AcePermission_ChangePassword]; + const bool denied = (permission_state == PermissionState_Denied); + + return denied; + } else { + return false; + } + } case AccountOption_PasswordExpired: { if (contains(ATTRIBUTE_PWD_LAST_SET)) { const QString pwdLastSet_value = get_string(ATTRIBUTE_PWD_LAST_SET); diff --git a/src/adldap/ad_object.h b/src/adldap/ad_object.h index edc1e9cc..7d9bd3ef 100644 --- a/src/adldap/ad_object.h +++ b/src/adldap/ad_object.h @@ -70,7 +70,7 @@ public: bool get_system_flag(const SystemFlagsBit bit) const; - bool get_account_option(AccountOption option) const; + bool get_account_option(AccountOption option, AdConfig *adconfig) const; GroupScope get_group_scope() const; GroupType get_group_type() const; diff --git a/src/adldap/ad_security.cpp b/src/adldap/ad_security.cpp new file mode 100644 index 00000000..b4b434fd --- /dev/null +++ b/src/adldap/ad_security.cpp @@ -0,0 +1,600 @@ +/* + * ADMC - AD Management Center + * + * Copyright (C) 2020-2021 BaseALT Ltd. + * Copyright (C) 2020-2021 Dmitry Degtyarev + * + * 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 "ad_security.h" + +#include "adldap.h" + +#include "samba/ndr_security.h" +#include "samba/dom_sid.h" +#include "samba/libsmb_xattr.h" +#include "samba/security_descriptor.h" + +#include "ad_filter.h" + +#include + +QByteArray dom_sid_to_bytes(const dom_sid &sid); +security_descriptor *ad_security_get_sd(const AdObject *object); +QList ad_security_get_dacl(security_descriptor *sd); +QList ad_security_get_trustee_list_from_sd(security_descriptor *sd); +QList ad_security_get_trustee_list_from_sd(security_descriptor *sd); +QHash> ad_security_get_state_from_sd(security_descriptor *sd, AdConfig *adconfig); + +// TODO: values of SEC_ADS_GENERIC_READ and +// SEC_ADS_GENERIC_WRITE constants don't match with the bits +// that ADUC sets when you enable those permissions in +// security tab. There are some extra bits in these +// constants, took them out as a quick fix. +const QHash ace_permission_to_mask_map = { + {AcePermission_FullControl, SEC_ADS_GENERIC_ALL}, + // {AcePermission_Read, SEC_ADS_GENERIC_READ}, + {AcePermission_Read, (SEC_STD_READ_CONTROL | SEC_ADS_LIST | SEC_ADS_READ_PROP)}, + // {AcePermission_Write, SEC_ADS_GENERIC_WRITE}, + {AcePermission_Write, (SEC_ADS_SELF_WRITE | SEC_ADS_WRITE_PROP)}, + {AcePermission_CreateChild, SEC_ADS_CREATE_CHILD}, + {AcePermission_DeleteChild, SEC_ADS_DELETE_CHILD}, + {AcePermission_AllowedToAuthenticate, SEC_ADS_CONTROL_ACCESS}, + {AcePermission_ChangePassword, SEC_ADS_CONTROL_ACCESS}, + {AcePermission_ReceiveAs, SEC_ADS_CONTROL_ACCESS}, + {AcePermission_ResetPassword, SEC_ADS_CONTROL_ACCESS}, + {AcePermission_SendAs, SEC_ADS_CONTROL_ACCESS}, + {AcePermission_ReadAccountRestrictions, SEC_ADS_READ_PROP}, + {AcePermission_WriteAccountRestrictions, SEC_ADS_WRITE_PROP}, + {AcePermission_ReadGeneralInfo, SEC_ADS_READ_PROP}, + {AcePermission_WriteGeneralInfo, SEC_ADS_WRITE_PROP}, + {AcePermission_ReadGroupMembership, SEC_ADS_READ_PROP}, + {AcePermission_ReadLogonInfo, SEC_ADS_READ_PROP}, + {AcePermission_WriteLogonInfo, SEC_ADS_WRITE_PROP}, + {AcePermission_ReadPersonalInfo, SEC_ADS_READ_PROP}, + {AcePermission_WritePersonalInfo, SEC_ADS_WRITE_PROP}, + {AcePermission_ReadPhoneAndMailOptions, SEC_ADS_READ_PROP}, + {AcePermission_WritePhoneAndMailOptions, SEC_ADS_WRITE_PROP}, + {AcePermission_ReadPrivateInfo, SEC_ADS_READ_PROP}, + {AcePermission_WritePrivateInfo, SEC_ADS_WRITE_PROP}, + {AcePermission_ReadPublicInfo, SEC_ADS_READ_PROP}, + {AcePermission_WritePublicInfo, SEC_ADS_WRITE_PROP}, + {AcePermission_ReadRemoteAccessInfo, SEC_ADS_READ_PROP}, + {AcePermission_WriteRemoteAccessInfo, SEC_ADS_WRITE_PROP}, + {AcePermission_ReadTerminalServerLicenseServer, SEC_ADS_READ_PROP}, + {AcePermission_WriteTerminalServerLicenseServer, SEC_ADS_WRITE_PROP}, + {AcePermission_ReadWebInfo, SEC_ADS_READ_PROP}, + {AcePermission_WriteWebInfo, SEC_ADS_WRITE_PROP}, +}; + +// NOTE: store right's cn value here, then search for it to +// get right's guid, which is compared to ace type. +const QHash ace_permission_to_type_map = { + {AcePermission_AllowedToAuthenticate, "Allowed-To-Authenticate"}, + {AcePermission_ChangePassword, "User-Change-Password"}, + {AcePermission_ReceiveAs, "Receive-As"}, + {AcePermission_ResetPassword, "User-Force-Change-Password"}, + {AcePermission_SendAs, "Send-As"}, + {AcePermission_ReadAccountRestrictions, "User-Account-Restrictions"}, + {AcePermission_WriteAccountRestrictions, "User-Account-Restrictions"}, + {AcePermission_ReadGeneralInfo, "General-Information"}, + {AcePermission_WriteGeneralInfo, "General-Information"}, + {AcePermission_ReadGroupMembership, "Membership"}, + {AcePermission_ReadLogonInfo, "User-Logon"}, + {AcePermission_WriteLogonInfo, "User-Logon"}, + {AcePermission_ReadPersonalInfo, "Personal-Information"}, + {AcePermission_WritePersonalInfo, "Personal-Information"}, + {AcePermission_ReadPhoneAndMailOptions, "Email-Information"}, + {AcePermission_WritePhoneAndMailOptions, "Email-Information"}, + {AcePermission_ReadPrivateInfo, "Private-Information"}, + {AcePermission_WritePrivateInfo, "Private-Information"}, + {AcePermission_ReadPublicInfo, "Public-Information"}, + {AcePermission_WritePublicInfo, "Public-Information"}, + {AcePermission_ReadRemoteAccessInfo, "RAS-Information"}, + {AcePermission_WriteRemoteAccessInfo, "RAS-Information"}, + {AcePermission_ReadTerminalServerLicenseServer, "Terminal-Server-License-Server"}, + {AcePermission_WriteTerminalServerLicenseServer, "Terminal-Server-License-Server"}, + {AcePermission_ReadWebInfo, "Web-Information"}, + {AcePermission_WriteWebInfo, "Web-Information"} +}; + +const QList all_permissions_list = +[]() { + QList out; + + for (int permission_i = 0; permission_i < AcePermission_COUNT; permission_i++) { + const AcePermission permission = (AcePermission) permission_i; + out.append(permission); + } + + return out; +}(); + +const QSet all_permissions = all_permissions_list.toSet(); + +QSet get_permission_set(const uint32_t mask) { + QSet out; + + for (const AcePermission &permission : all_permissions) { + const uint32_t this_mask = ace_permission_to_mask_map[permission]; + + if (this_mask == mask) { + out.insert(permission); + } + } + + return out; +} + +const QSet access_permissions = get_permission_set(SEC_ADS_CONTROL_ACCESS); +const QSet read_prop_permissions = get_permission_set(SEC_ADS_READ_PROP); +const QSet write_prop_permissions = get_permission_set(SEC_ADS_WRITE_PROP); + +QHash> ad_security_modify(const QHash> ¤t, const QByteArray &trustee, const AcePermission permission, const PermissionState new_state) { + QHash> out; + + out = current; + + auto permission_state_set = + [&](const QSet &permission_set, const PermissionState state) { + for (const AcePermission &this_permission : permission_set) { + out[trustee][this_permission] = state; + } + }; + + // + // Apply state change to permission state map + // + out[trustee][permission] = new_state; + + // When children permissions change their parent + // permissions always become None (yes, for each case). + const QSet parent_permissions = + [&]() { + QSet out_set; + + out_set.insert(AcePermission_FullControl); + + if (read_prop_permissions.contains(permission)) { + out_set.insert(AcePermission_Read); + } else if (write_prop_permissions.contains(permission)) { + out_set.insert(AcePermission_Write); + } + + return out_set; + }(); + permission_state_set(parent_permissions, PermissionState_None); + + // When parent permissions become Allowed or Denied, + // their children change to that state as well. + if (new_state != PermissionState_None) { + const QSet child_permissions = + [&]() { + if (permission == AcePermission_FullControl) { + return all_permissions; + } else if (permission == AcePermission_Read) { + return read_prop_permissions; + } else if (permission == AcePermission_Write) { + return write_prop_permissions; + } else { + return QSet(); + } + }(); + + permission_state_set(child_permissions, new_state); + } + + return out; +} + +QString ad_security_get_trustee_name(AdInterface &ad, const QByteArray &trustee) { + // TODO: not sure if these are supposed to be translated? + static const QHash trustee_name_map = { + {SID_WORLD_DOMAIN, "Everyone in Domain"}, + {SID_WORLD, "Everyone"}, + {SID_WORLD, "Everyone"}, + {SID_CREATOR_OWNER_DOMAIN, "CREATOR OWNER DOMAIN"}, + {SID_CREATOR_OWNER, "CREATOR OWNER"}, + {SID_CREATOR_GROUP, "CREATOR GROUP"}, + {SID_OWNER_RIGHTS, "OWNER RIGHTS"}, + {SID_NT_AUTHORITY, "AUTHORITY"}, + {SID_NT_DIALUP, "DIALUP"}, + {SID_NT_NETWORK, "NETWORK"}, + {SID_NT_BATCH, "BATCH"}, + {SID_NT_INTERACTIVE, "INTERACTIVE"}, + {SID_NT_SERVICE, "SERVICE"}, + {SID_NT_ANONYMOUS, "ANONYMOUS LOGON"}, + {SID_NT_PROXY, "PROXY"}, + {SID_NT_ENTERPRISE_DCS, "ENTERPRISE DOMAIN CONTROLLERS"}, + {SID_NT_SELF, "SELF"}, + {SID_NT_AUTHENTICATED_USERS, "Authenticated Users"}, + {SID_NT_RESTRICTED, "RESTRICTED"}, + {SID_NT_TERMINAL_SERVER_USERS, "TERMINAL SERVER USERS"}, + {SID_NT_REMOTE_INTERACTIVE, "REMOTE INTERACTIVE LOGON"}, + {SID_NT_THIS_ORGANISATION, "This Organization"}, + {SID_NT_IUSR, "IUSR"}, + {SID_NT_SYSTEM, "SYSTEM"}, + {SID_NT_LOCAL_SERVICE, "LOCAL SERVICE"}, + {SID_NT_NETWORK_SERVICE, "NETWORK SERVICE"}, + {SID_NT_DIGEST_AUTHENTICATION, "Digest Authentication"}, + {SID_NT_NTLM_AUTHENTICATION, "NTLM Authentication"}, + {SID_NT_SCHANNEL_AUTHENTICATION, "SChannel Authentication"}, + {SID_NT_OTHER_ORGANISATION, "Other Organization"}, + }; + + const QString trustee_string = object_sid_display_value(trustee); + + if (trustee_name_map.contains(trustee_string)) { + return trustee_name_map[trustee_string]; + } else { + // Try to get name of trustee by finding it's DN + const QString filter = filter_CONDITION(Condition_Equals, ATTRIBUTE_OBJECT_SID, trustee_string); + const QList attributes = { + ATTRIBUTE_DISPLAY_NAME, + ATTRIBUTE_SAMACCOUNT_NAME, + }; + const auto trustee_search = ad.search(ad.adconfig()->domain_head(), SearchScope_All, filter, QList()); + if (!trustee_search.isEmpty()) { + // NOTE: this is some weird name selection logic + // but that's how microsoft does it. Maybe need + // to use this somewhere else as well? + const QString name = + [&]() { + const AdObject object = trustee_search.values()[0]; + + if (object.contains(ATTRIBUTE_DISPLAY_NAME)) { + return object.get_string(ATTRIBUTE_DISPLAY_NAME); + } else if (object.contains(ATTRIBUTE_SAMACCOUNT_NAME)) { + return object.get_string(ATTRIBUTE_SAMACCOUNT_NAME); + } else { + return dn_get_name(object.get_dn()); + } + }(); + + return name; + } else { + // Return raw sid as last option + return trustee_string; + } + } +} + +bool attribute_replace_security_descriptor(AdInterface *ad, const QString &dn, const QHash> &descriptor_state_arg) { + const QByteArray new_descriptor_bytes = + [&]() { + // Remove redundancy from permission state + const QHash> state = + [&]() { + QHash> out; + + out = descriptor_state_arg; + + // Remove child permission states. For example if + // "Read" is allowed, then there's no need to + // include any other state for "read prop" + // permissions. + for (const QByteArray &trustee : out.keys()) { + const bool full_control = out[trustee].contains(AcePermission_FullControl) && (out[trustee][AcePermission_FullControl] != PermissionState_None); + const bool read = out[trustee].contains(AcePermission_Read) && (out[trustee][AcePermission_Read] != PermissionState_None); + const bool write = out[trustee].contains(AcePermission_Write) && (out[trustee][AcePermission_Write] != PermissionState_None); + + if (full_control) { + for (const AcePermission &permission : all_permissions) { + if (permission != AcePermission_FullControl) { + out[trustee].remove(permission); + } + } + } else if (read) { + for (const AcePermission &permission : read_prop_permissions) { + if (permission != AcePermission_Read) { + out[trustee].remove(permission); + } + } + } else if (write) { + for (const AcePermission &permission : write_prop_permissions) { + if (permission != AcePermission_Read) { + out[trustee].remove(permission); + } + } + } + } + + return out; + }(); + + TALLOC_CTX* tmp_ctx = talloc_new(NULL); + + // Use original sd as base, only remaking the dacl + const AdObject object = ad->search_object(dn, {ATTRIBUTE_SECURITY_DESCRIPTOR}); + security_descriptor *sd = ad_security_get_sd(&object); + + // Generate new dacl + const QList dacl_qlist = + [&]() { + QList out; + + for (const QByteArray &trustee : state.keys()) { + const QHash permission_map = state[trustee]; + + for (const AcePermission &permission : permission_map.keys()) { + const PermissionState permission_state = permission_map[permission]; + + if (permission_state == PermissionState_None) { + continue; + } + + struct security_ace *ace = talloc(tmp_ctx, struct security_ace); + + const bool object_present = ace_permission_to_type_map.contains(permission); + + ace->type = + [&]() { + if (permission_state == PermissionState_Allowed) { + if (object_present) { + return SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT; + } else { + return SEC_ACE_TYPE_ACCESS_ALLOWED; + } + } else if (permission_state == PermissionState_Denied) { + if (object_present) { + return SEC_ACE_TYPE_ACCESS_DENIED_OBJECT; + } else { + return SEC_ACE_TYPE_ACCESS_DENIED; + } + } + + return SEC_ACE_TYPE_ACCESS_ALLOWED; + }(); + + // TODO: these flags should be set to something + // in some cases, for now just 0 + ace->flags = 0x00; + ace->access_mask = ace_permission_to_mask_map[permission]; + ace->object.object.flags = + [&]() { + if (object_present) { + return SEC_ACE_OBJECT_TYPE_PRESENT; + } else { + return 0; + } + }(); + ace->object.object.type.type = + [&]() { + if (object_present) { + const QString type_name_string = ace_permission_to_type_map[permission]; + const QString type_string = ad->adconfig()->get_right_guid(type_name_string); + const QByteArray type_bytes = guid_string_to_bytes(type_string); + + struct GUID guid; + memcpy(&guid, type_bytes.data(), sizeof(GUID)); + + return guid; + } else { + return GUID(); + } + }(); + memcpy(&ace->trustee, trustee.data(), sizeof(dom_sid)); + + out.append(ace); + } + } + + return out; + }(); + + // Replace dacl + talloc_free(sd->dacl); + sd->dacl = NULL; + for (security_ace *ace : dacl_qlist) { + security_descriptor_dacl_add(sd, ace); + } + qsort(sd->dacl->aces, sd->dacl->num_aces, sizeof(security_ace), ace_compare); + + DATA_BLOB blob; + ndr_push_struct_blob(&blob, tmp_ctx, sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor); + + const QByteArray out = QByteArray((char *) blob.data, blob.length); + + talloc_free(tmp_ctx); + + return out; + }(); + + const bool apply_success = ad->attribute_replace_value(dn, ATTRIBUTE_SECURITY_DESCRIPTOR, new_descriptor_bytes); + + return apply_success; +} + +QList ad_security_get_trustee_list_from_object(const AdObject *object) { + security_descriptor *sd = ad_security_get_sd(object); + + const QList out = ad_security_get_trustee_list_from_sd(sd); + + talloc_free(sd); + + return out; +} + +QHash> ad_security_get_state_from_object(const AdObject *object, AdConfig *adconfig) { + security_descriptor *sd = ad_security_get_sd(object); + + const auto out = ad_security_get_state_from_sd(sd, adconfig); + + talloc_free(sd); + + return out; +} + +QByteArray dom_sid_to_bytes(const dom_sid &sid) { + const QByteArray bytes = QByteArray((char *) &sid, sizeof(struct dom_sid)); + + return bytes; +} + +// NOTE: have to talloc_free() returned sd +security_descriptor *ad_security_get_sd(const AdObject *object) { + const QByteArray descriptor_bytes = object->get_value(ATTRIBUTE_SECURITY_DESCRIPTOR); + DATA_BLOB blob = data_blob_const(descriptor_bytes.data(), descriptor_bytes.size()); + + security_descriptor *sd = talloc(NULL, struct security_descriptor); + + ndr_pull_struct_blob(&blob, sd, sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); + + return sd; +} + +QList ad_security_get_dacl(security_descriptor *sd) { + QList out; + + for (uint32_t i = 0; i < sd->dacl->num_aces; i++) { + security_ace *ace = &sd->dacl->aces[i]; + out.append(ace); + } + + return out; +} + +QList ad_security_get_trustee_list_from_sd(security_descriptor *sd) { + QSet out; + + const QList dacl = ad_security_get_dacl(sd); + for (security_ace *ace : dacl) { + const QByteArray trustee_bytes = dom_sid_to_bytes(ace->trustee); + + out.insert(trustee_bytes); + } + + return out.toList(); +} + +void ad_security_print_acl(security_descriptor *sd, const QByteArray &trustee) { + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + + const QList ace_list = + [&]() { + QList out; + + const QList dacl = ad_security_get_dacl(sd); + for (security_ace *ace : dacl) { + const QByteArray this_trustee_bytes = dom_sid_to_bytes(ace->trustee); + + const bool trustee_match = (this_trustee_bytes == trustee); + if (trustee_match) { + out.append(ace); + } + } + + return out; + }(); + + for (security_ace *ace : ace_list) { + const QString ace_string = + [&]() { + char *ace_cstr = ndr_print_struct_string(tmp_ctx, (ndr_print_fn_t)ndr_print_security_ace, + "ace", ace); + + const QString out = QString(ace_cstr); + + return out; + }(); + + qDebug().noquote() << ace_string; + } + + talloc_free(tmp_ctx); +} + +// TODO: this requiring adconfig is so messy and causes +// other f-ns that use this f-n to require adconfig also. +// Not sure if possible to remove this requirement. +QHash> ad_security_get_state_from_sd(security_descriptor *sd, AdConfig *adconfig) { + QHash> out; + + // Initialize to None by default + const QList trustee_list = ad_security_get_trustee_list_from_sd(sd); + for (const QByteArray &trustee : trustee_list) { + for (const AcePermission &permission : all_permissions) { + out[trustee][permission] = PermissionState_None; + } + } + + // Then go through acl and set allowed/denied permission + // states + const QList dacl = ad_security_get_dacl(sd); + for (security_ace *ace : dacl) { + const QByteArray trustee = dom_sid_to_bytes(ace->trustee); + + for (const AcePermission &permission : all_permissions) { + const uint32_t permission_mask = ace_permission_to_mask_map[permission]; + + const bool mask_match = ((ace->access_mask & permission_mask) == permission_mask); + if (!mask_match) { + continue; + } + + const bool object_match = + [&]() { + const bool object_present = ((ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) != 0); + if (!object_present) { + return false; + } + + const QString rights_guid = + [&]() { + const QString right_cn = ace_permission_to_type_map[permission]; + const QString guid_out = adconfig->get_right_guid(right_cn); + + return guid_out; + }(); + + const QString ace_type_guid = + [&]() { + const GUID type = ace->object.object.type.type; + const QByteArray type_bytes = QByteArray((char *) &type, sizeof(GUID)); + + return attribute_display_value(ATTRIBUTE_OBJECT_GUID, type_bytes, adconfig); + }(); + + return (rights_guid.toLower() == ace_type_guid.toLower()); + }(); + + switch (ace->type) { + case SEC_ACE_TYPE_ACCESS_ALLOWED: { + out[trustee][permission] = PermissionState_Allowed; + break; + } + case SEC_ACE_TYPE_ACCESS_DENIED: { + out[trustee][permission] = PermissionState_Denied; + break; + } + case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: { + if (object_match) { + out[trustee][permission] = PermissionState_Allowed; + } + break; + } + case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: { + if (object_match) { + out[trustee][permission] = PermissionState_Denied; + } + break; + } + default: break; + } + } + } + + return out; +} diff --git a/src/adldap/ad_security.h b/src/adldap/ad_security.h new file mode 100644 index 00000000..38b9648b --- /dev/null +++ b/src/adldap/ad_security.h @@ -0,0 +1,53 @@ +/* + * ADMC - AD Management Center + * + * Copyright (C) 2020-2021 BaseALT Ltd. + * Copyright (C) 2020-2021 Dmitry Degtyarev + * + * 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 . + */ + +/** + * Functions for working with security descriptors. + */ + +#ifndef AD_SECURITY_H +#define AD_SECURITY_H + +#include "ad_defines.h" + +#include +#include +#include +#include + +class AdInterface; +class AdConfig; +class AdObject; + +extern const QHash ace_permission_to_mask_map; +extern const QHash ace_permission_to_type_map; +extern const QList all_permissions_list; +extern const QSet all_permissions; +extern const QSet access_permissions; +extern const QSet read_prop_permissions; +extern const QSet write_prop_permissions; + +QHash> ad_security_modify(const QHash> ¤t, const QByteArray &trustee, const AcePermission permission, const PermissionState new_state); +QString ad_security_get_trustee_name(AdInterface &ad, const QByteArray &trustee); +bool attribute_replace_security_descriptor(AdInterface *ad, const QString &dn, const QHash> &descriptor_state_arg); +QList ad_security_get_trustee_list_from_object(const AdObject *object); +QHash> ad_security_get_state_from_object(const AdObject *object, AdConfig *adconfig); + +#endif /* AD_SECURITY_H */ diff --git a/src/adldap/ad_utils.cpp b/src/adldap/ad_utils.cpp index f1e4409c..6d85479f 100644 --- a/src/adldap/ad_utils.cpp +++ b/src/adldap/ad_utils.cpp @@ -19,8 +19,10 @@ */ #include "ad_utils.h" + #include "ad_config.h" #include "ad_display.h" +#include "samba/dom_sid.h" #include #include @@ -120,6 +122,7 @@ QDateTime datetime_string_to_qdatetime(const QString &attribute, const QString & QString account_option_string(const AccountOption &option) { switch (option) { case AccountOption_Disabled: return QCoreApplication::translate("ad_utils", "Account disabled"); + case AccountOption_CantChangePassword: return QCoreApplication::translate("ad_utils", "User cannot change password"); case AccountOption_PasswordExpired: return QCoreApplication::translate("ad_utils", "User must change password on next logon"); case AccountOption_DontExpirePassword: return QCoreApplication::translate("ad_utils", "Don't expire password"); case AccountOption_UseDesKey: return QCoreApplication::translate("ad_utils", "Store password using reversible encryption"); @@ -133,7 +136,6 @@ QString account_option_string(const AccountOption &option) { } int account_option_bit(const AccountOption &option) { - // NOTE: not all account options can be directly mapped to bits switch (option) { case AccountOption_Disabled: return 0x00000002; @@ -148,6 +150,9 @@ int account_option_bit(const AccountOption &option) { case AccountOption_CantDelegate: return 0x00100000; + // NOTE: not all account options can be directly + // mapped to bits + case AccountOption_CantChangePassword: return 0; case AccountOption_PasswordExpired: return 0; case AccountOption_COUNT: return 0; } @@ -372,3 +377,45 @@ const char *cstr(const QString &qstr) { bool load_adldap_translation(QTranslator &translator, const QLocale &locale) { return translator.load(locale, "adldap", "_", ":/adldap"); } + +QByteArray guid_string_to_bytes(const QString &guid_string) { + const QList segment_list = + [&]() { + QList out; + + const QList string_segment_list = guid_string.split('-'); + + for (const QString &string_segment : string_segment_list) { + const QByteArray segment = QByteArray::fromHex(string_segment.toLatin1()); + out.append(segment); + } + + std::reverse(out[0].begin(), out[0].end()); + std::reverse(out[1].begin(), out[1].end()); + std::reverse(out[2].begin(), out[2].end()); + + return out; + }(); + + const QByteArray guid_bytes = + [&]() { + QByteArray out; + + for (const QByteArray &segment : segment_list) { + out.append(segment); + } + + return out; + }(); + + return guid_bytes; +} + +QByteArray sid_string_to_bytes(const QString &sid_string) { + dom_sid sid; + string_to_sid(&sid, cstr(sid_string)); + + const QByteArray sid_bytes = QByteArray((char *) &sid, sizeof(dom_sid)); + + return sid_bytes; +} diff --git a/src/adldap/ad_utils.h b/src/adldap/ad_utils.h index aea37923..6ef24eb6 100644 --- a/src/adldap/ad_utils.h +++ b/src/adldap/ad_utils.h @@ -79,4 +79,7 @@ const char *cstr(const QString &qstr); // calling this bool load_adldap_translation(QTranslator &translator, const QLocale &locale); +QByteArray guid_string_to_bytes(const QString &guid_string); +QByteArray sid_string_to_bytes(const QString &sid_string); + #endif /* AD_UTILS_H */ diff --git a/src/adldap/samba/dom_sid.c b/src/adldap/samba/dom_sid.c index 99c2ea82..c9c022e1 100644 --- a/src/adldap/samba/dom_sid.c +++ b/src/adldap/samba/dom_sid.c @@ -28,6 +28,410 @@ #include "dom_sid.h" #include "replace.h" +#include "string.h" + +/***************************************************************** + Compare the auth portion of two sids. +*****************************************************************/ + +int dom_sid_compare_auth(const struct dom_sid *sid1, + const struct dom_sid *sid2) +{ + int i; + + if (sid1 == sid2) + return 0; + if (!sid1) + return -1; + if (!sid2) + return 1; + + if (sid1->sid_rev_num != sid2->sid_rev_num) + return sid1->sid_rev_num - sid2->sid_rev_num; + + for (i = 0; i < 6; i++) + if (sid1->id_auth[i] != sid2->id_auth[i]) + return sid1->id_auth[i] - sid2->id_auth[i]; + + return 0; +} + +/***************************************************************** + Compare two sids. +*****************************************************************/ + +int dom_sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2) +{ + int i; + + if (sid1 == sid2) + return 0; + if (!sid1) + return -1; + if (!sid2) + return 1; + + /* Compare most likely different rids, first: i.e start at end */ + if (sid1->num_auths != sid2->num_auths) + return sid1->num_auths - sid2->num_auths; + + for (i = sid1->num_auths-1; i >= 0; --i) + if (sid1->sub_auths[i] != sid2->sub_auths[i]) + return sid1->sub_auths[i] - sid2->sub_auths[i]; + + return dom_sid_compare_auth(sid1, sid2); +} + +/***************************************************************** + Compare two sids. +*****************************************************************/ + +bool dom_sid_equal(const struct dom_sid *sid1, const struct dom_sid *sid2) +{ + return dom_sid_compare(sid1, sid2) == 0; +} + +/***************************************************************** + Add a rid to the end of a sid +*****************************************************************/ + +bool sid_append_rid(struct dom_sid *sid, uint32_t rid) +{ + if (sid->num_auths < ARRAY_SIZE(sid->sub_auths)) { + sid->sub_auths[sid->num_auths++] = rid; + return true; + } + return false; +} + +/* + See if 2 SIDs are in the same domain + this just compares the leading sub-auths +*/ +int dom_sid_compare_domain(const struct dom_sid *sid1, + const struct dom_sid *sid2) +{ + int n, i; + + n = MIN(sid1->num_auths, sid2->num_auths); + + for (i = n-1; i >= 0; --i) + if (sid1->sub_auths[i] != sid2->sub_auths[i]) + return sid1->sub_auths[i] - sid2->sub_auths[i]; + + return dom_sid_compare_auth(sid1, sid2); +} + +/***************************************************************** + Convert a string to a SID. Returns True on success, False on fail. + Return the first character not parsed in endp. +*****************************************************************/ +#define AUTHORITY_MASK (~(0xffffffffffffULL)) + +bool dom_sid_parse_endp(const char *sidstr,struct dom_sid *sidout, + const char **endp) +{ + const char *p; + char *q; + /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ + uint64_t conv; + // int error = 0; + + ZERO_STRUCTP(sidout); + + if ((sidstr[0] != 'S' && sidstr[0] != 's') || sidstr[1] != '-') { + goto format_error; + } + + /* Get the revision number. */ + p = sidstr + 2; + + if (!isdigit(*p)) { + goto format_error; + } + + // NOTE: replaced with strtoul() + // conv = smb_strtoul(p, &q, 10, &error, SMB_STR_STANDARD); + // if (error != 0 || (*q != '-') || conv > UINT8_MAX) { + // goto format_error; + // } + conv = strtoul(p, &q, 10); + sidout->sid_rev_num = (uint8_t) conv; + q++; + + if (!isdigit(*q)) { + goto format_error; + } + + /* get identauth */ + // conv = smb_strtoull(q, &q, 0, &error, SMB_STR_STANDARD); + // if (conv & AUTHORITY_MASK || error != 0) { + // goto format_error; + // } + conv = strtoull(q, &q, 0); + + + /* When identauth >= UINT32_MAX, it's in hex with a leading 0x */ + /* NOTE - the conv value is in big-endian format. */ + sidout->id_auth[0] = (conv & 0xff0000000000ULL) >> 40; + sidout->id_auth[1] = (conv & 0x00ff00000000ULL) >> 32; + sidout->id_auth[2] = (conv & 0x0000ff000000ULL) >> 24; + sidout->id_auth[3] = (conv & 0x000000ff0000ULL) >> 16; + sidout->id_auth[4] = (conv & 0x00000000ff00ULL) >> 8; + sidout->id_auth[5] = (conv & 0x0000000000ffULL); + + sidout->num_auths = 0; + if (*q != '-') { + /* Just id_auth, no subauths */ + goto done; + } + + q++; + + while (true) { + char *end; + + if (!isdigit(*q)) { + goto format_error; + } + + // conv = smb_strtoull(q, &end, 10, &error, SMB_STR_STANDARD); + // if (conv > UINT32_MAX || error != 0) { + // goto format_error; + // } + conv = strtoull(q, &end, 10); + + if (!sid_append_rid(sidout, conv)) { + // DEBUG(3, ("Too many sid auths in %s\n", sidstr)); + return false; + } + + q = end; + if (*q != '-') { + break; + } + q += 1; + } +done: + if (endp != NULL) { + *endp = q; + } + return true; + +format_error: + // DEBUG(3, ("string_to_sid: SID %s is not in a valid format\n", sidstr)); + return false; +} + +bool string_to_sid(struct dom_sid *sidout, const char *sidstr) +{ + return dom_sid_parse(sidstr, sidout); +} + +bool dom_sid_parse(const char *sidstr, struct dom_sid *ret) +{ + return dom_sid_parse_endp(sidstr, ret, NULL); +} + +/* + convert a string to a dom_sid, returning a talloc'd dom_sid +*/ +struct dom_sid *dom_sid_parse_talloc(TALLOC_CTX *mem_ctx, const char *sidstr) +{ + struct dom_sid *ret; + ret = talloc(mem_ctx, struct dom_sid); + if (!ret) { + return NULL; + } + if (!dom_sid_parse(sidstr, ret)) { + talloc_free(ret); + return NULL; + } + + return ret; +} + +/* + convert a string to a dom_sid, returning a talloc'd dom_sid +*/ +struct dom_sid *dom_sid_parse_length(TALLOC_CTX *mem_ctx, const DATA_BLOB *sid) +{ + char p[sid->length+1]; + memcpy(p, sid->data, sid->length); + p[sid->length] = '\0'; + return dom_sid_parse_talloc(mem_ctx, p); +} + +/* + copy a dom_sid structure +*/ +struct dom_sid *dom_sid_dup(TALLOC_CTX *mem_ctx, const struct dom_sid *dom_sid) +{ + struct dom_sid *ret; + int i; + + if (!dom_sid) { + return NULL; + } + + ret = talloc(mem_ctx, struct dom_sid); + if (!ret) { + return NULL; + } + + ret->sid_rev_num = dom_sid->sid_rev_num; + ret->id_auth[0] = dom_sid->id_auth[0]; + ret->id_auth[1] = dom_sid->id_auth[1]; + ret->id_auth[2] = dom_sid->id_auth[2]; + ret->id_auth[3] = dom_sid->id_auth[3]; + ret->id_auth[4] = dom_sid->id_auth[4]; + ret->id_auth[5] = dom_sid->id_auth[5]; + ret->num_auths = dom_sid->num_auths; + + for (i=0;inum_auths;i++) { + ret->sub_auths[i] = dom_sid->sub_auths[i]; + } + + return ret; +} + +/* + add a rid to a domain dom_sid to make a full dom_sid. This function + returns a new sid in the supplied memory context +*/ +struct dom_sid *dom_sid_add_rid(TALLOC_CTX *mem_ctx, + const struct dom_sid *domain_sid, + uint32_t rid) +{ + struct dom_sid *sid; + + sid = dom_sid_dup(mem_ctx, domain_sid); + if (!sid) return NULL; + + if (!sid_append_rid(sid, rid)) { + talloc_free(sid); + return NULL; + } + + return sid; +} + +/* + Split up a SID into its domain and RID part +*/ +NTSTATUS dom_sid_split_rid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid, + struct dom_sid **domain, uint32_t *rid) +{ + if (sid->num_auths == 0) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (domain) { + if (!(*domain = dom_sid_dup(mem_ctx, sid))) { + return NT_STATUS_NO_MEMORY; + } + + (*domain)->num_auths -= 1; + } + + if (rid) { + *rid = sid->sub_auths[sid->num_auths - 1]; + } + + return NT_STATUS_OK; +} + +/* + return true if the 2nd sid is in the domain given by the first sid +*/ +bool dom_sid_in_domain(const struct dom_sid *domain_sid, + const struct dom_sid *sid) +{ + int i; + + if (!domain_sid || !sid) { + return false; + } + + if (sid->num_auths < 2) { + return false; + } + + if (domain_sid->num_auths != (sid->num_auths - 1)) { + return false; + } + + for (i = domain_sid->num_auths-1; i >= 0; --i) { + if (domain_sid->sub_auths[i] != sid->sub_auths[i]) { + return false; + } + } + + return dom_sid_compare_auth(domain_sid, sid) == 0; +} + +bool dom_sid_is_valid_account_domain(const struct dom_sid *sid) +{ + /* + * We expect S-1-5-21-9-8-7, but we don't + * allow S-1-5-21-0-0-0 as this is used + * for claims and compound identities. + * + * With this structure: + * + * struct dom_sid { + * uint8_t sid_rev_num; + * int8_t num_auths; [range(0,15)] + * uint8_t id_auth[6]; + * uint32_t sub_auths[15]; + * } + * + * S-1-5-21-9-8-7 looks like this: + * {1, 4, {0,0,0,0,0,5}, {21,9,8,7,0,0,0,0,0,0,0,0,0,0,0}}; + */ + if (sid == NULL) { + return false; + } + + if (sid->sid_rev_num != 1) { + return false; + } + if (sid->num_auths != 4) { + return false; + } + if (sid->id_auth[5] != 5) { + return false; + } + if (sid->id_auth[4] != 0) { + return false; + } + if (sid->id_auth[3] != 0) { + return false; + } + if (sid->id_auth[2] != 0) { + return false; + } + if (sid->id_auth[1] != 0) { + return false; + } + if (sid->id_auth[0] != 0) { + return false; + } + if (sid->sub_auths[0] != 21) { + return false; + } + if (sid->sub_auths[1] == 0) { + return false; + } + if (sid->sub_auths[2] == 0) { + return false; + } + if (sid->sub_auths[3] == 0) { + return false; + } + + return true; +} /* Convert a dom_sid to a string, printing into a buffer. Return the diff --git a/src/adldap/samba/dom_sid.h b/src/adldap/samba/dom_sid.h index 689c376c..4813817d 100644 --- a/src/adldap/samba/dom_sid.h +++ b/src/adldap/samba/dom_sid.h @@ -1,29 +1,32 @@ /* - * Unix SMB/CIFS implementation. - * Group Policy Object Support - * Copyright (C) Wilco Baan Hofman 2010 - * - * 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 . - */ + Unix SMB/CIFS implementation. + Samba utility functions + + Copyright (C) Stefan (metze) Metzmacher 2002-2004 + Copyright (C) Andrew Tridgell 1992-2004 + Copyright (C) Jeremy Allison 1999 + + 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 . +*/ /* * This file is a copy of private samba sources. Parts of it * were removed or edited. */ -#ifndef DOM_SID_H -#define DOM_SID_H +#ifndef _DOM_SID_H_ +#define _DOM_SID_H_ #ifdef __cplusplus extern "C" { @@ -33,14 +36,93 @@ extern "C" { #include #include +/* Some well-known SIDs */ +extern const struct dom_sid global_sid_World_Domain; +extern const struct dom_sid global_sid_World; +extern const struct dom_sid global_sid_Local_Authority; +extern const struct dom_sid global_sid_Creator_Owner_Domain; +extern const struct dom_sid global_sid_NT_Authority; +extern const struct dom_sid global_sid_Enterprise_DCs; +extern const struct dom_sid global_sid_System; +extern const struct dom_sid global_sid_NULL; +extern const struct dom_sid global_sid_Authenticated_Users; +extern const struct dom_sid global_sid_Network; +extern const struct dom_sid global_sid_Asserted_Identity; +extern const struct dom_sid global_sid_Asserted_Identity_Service; +extern const struct dom_sid global_sid_Asserted_Identity_Authentication_Authority; +extern const struct dom_sid global_sid_Creator_Owner; +extern const struct dom_sid global_sid_Creator_Group; +extern const struct dom_sid global_sid_Owner_Rights; +extern const struct dom_sid global_sid_Anonymous; +extern const struct dom_sid global_sid_Builtin; +extern const struct dom_sid global_sid_Builtin_Administrators; +extern const struct dom_sid global_sid_Builtin_Users; +extern const struct dom_sid global_sid_Builtin_Guests; +extern const struct dom_sid global_sid_Builtin_Power_Users; +extern const struct dom_sid global_sid_Builtin_Account_Operators; +extern const struct dom_sid global_sid_Builtin_Server_Operators; +extern const struct dom_sid global_sid_Builtin_Print_Operators; +extern const struct dom_sid global_sid_Builtin_Backup_Operators; +extern const struct dom_sid global_sid_Builtin_Replicator; +extern const struct dom_sid global_sid_Builtin_PreWin2kAccess; +extern const struct dom_sid global_sid_Unix_Users; +extern const struct dom_sid global_sid_Unix_Groups; +extern const struct dom_sid global_sid_Unix_NFS; +extern const struct dom_sid global_sid_Unix_NFS_Users; +extern const struct dom_sid global_sid_Unix_NFS_Groups; +extern const struct dom_sid global_sid_Unix_NFS_Mode; +extern const struct dom_sid global_sid_Unix_NFS_Other; + +int dom_sid_compare_auth(const struct dom_sid *sid1, + const struct dom_sid *sid2); +int dom_sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2); +int dom_sid_compare_domain(const struct dom_sid *sid1, + const struct dom_sid *sid2); +bool dom_sid_equal(const struct dom_sid *sid1, const struct dom_sid *sid2); +bool sid_append_rid(struct dom_sid *sid, uint32_t rid); +bool string_to_sid(struct dom_sid *sidout, const char *sidstr); +bool dom_sid_parse_endp(const char *sidstr,struct dom_sid *sidout, + const char **endp); +bool dom_sid_parse(const char *sidstr, struct dom_sid *ret); +struct dom_sid *dom_sid_parse_talloc(TALLOC_CTX *mem_ctx, const char *sidstr); +struct dom_sid *dom_sid_parse_length(TALLOC_CTX *mem_ctx, const DATA_BLOB *sid); +struct dom_sid *dom_sid_dup(TALLOC_CTX *mem_ctx, const struct dom_sid *dom_sid); +struct dom_sid *dom_sid_add_rid(TALLOC_CTX *mem_ctx, + const struct dom_sid *domain_sid, + uint32_t rid); +NTSTATUS dom_sid_split_rid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid, + struct dom_sid **domain, uint32_t *rid); +bool dom_sid_in_domain(const struct dom_sid *domain_sid, + const struct dom_sid *sid); +bool dom_sid_is_valid_account_domain(const struct dom_sid *sid); + #define DOM_SID_STR_BUFLEN (15*11+25) char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid); struct dom_sid_buf { char buf[DOM_SID_STR_BUFLEN]; }; char *dom_sid_str_buf(const struct dom_sid *sid, struct dom_sid_buf *dst); +const char *sid_type_lookup(uint32_t sid_type); +const struct security_token *get_system_token(void); +bool sid_compose(struct dom_sid *dst, const struct dom_sid *domain_sid, uint32_t rid); +bool sid_split_rid(struct dom_sid *sid, uint32_t *rid); +bool sid_peek_rid(const struct dom_sid *sid, uint32_t *rid); +bool sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid *sid, uint32_t *rid); +void sid_copy(struct dom_sid *dst, const struct dom_sid *src); +ssize_t sid_parse(const uint8_t *inbuf, size_t len, struct dom_sid *sid); +int sid_compare_domain(const struct dom_sid *sid1, const struct dom_sid *sid2); +NTSTATUS add_sid_to_array(TALLOC_CTX *mem_ctx, const struct dom_sid *sid, + struct dom_sid **sids, uint32_t *num); +NTSTATUS add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const struct dom_sid *sid, + struct dom_sid **sids, uint32_t *num_sids); +void del_sid_from_array(const struct dom_sid *sid, struct dom_sid **sids, + uint32_t *num); +bool add_rid_to_array_unique(TALLOC_CTX *mem_ctx, + uint32_t rid, uint32_t **pp_rids, size_t *p_num); +bool is_null_sid(const struct dom_sid *sid); + #ifdef __cplusplus } #endif -#endif /* DOM_SID_H */ +#endif /*_DOM_SID_H_*/ diff --git a/src/adldap/samba/gp_manage.c b/src/adldap/samba/gp_manage.c new file mode 100644 index 00000000..95204e34 --- /dev/null +++ b/src/adldap/samba/gp_manage.c @@ -0,0 +1,147 @@ +/* + * Unix SMB/CIFS implementation. + * Group Policy Object Support + * Copyright (C) Wilco Baan Hofman 2010 + * + * 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 . + */ + +/* + * This file is a copy of private files from samba source. + * Parts of it were removed or edited. + */ + +#include "gp_manage.h" + +#include "dom_sid.h" +#include "security_descriptor.h" + +#include + +/* + * This file is a copy of private samba sources. Parts of it + * were removed or edited. + */ + +uint32_t gp_ads_to_dir_access_mask(uint32_t access_mask) +{ + uint32_t fs_mask; + + /* Copy the standard access mask */ + fs_mask = access_mask & 0x001F0000; + + /* When READ_PROP and LIST_CONTENTS are set, read access is granted on the GPT */ + if (access_mask & SEC_ADS_READ_PROP && access_mask & SEC_ADS_LIST) { + fs_mask |= SEC_STD_SYNCHRONIZE | SEC_DIR_LIST | SEC_DIR_READ_ATTRIBUTE | + SEC_DIR_READ_EA | SEC_DIR_TRAVERSE; + } + + /* When WRITE_PROP is set, full write access is granted on the GPT */ + if (access_mask & SEC_ADS_WRITE_PROP) { + fs_mask |= SEC_STD_SYNCHRONIZE | SEC_DIR_WRITE_ATTRIBUTE | + SEC_DIR_WRITE_EA | SEC_DIR_ADD_FILE | + SEC_DIR_ADD_SUBDIR; + } + + /* Map CREATE_CHILD to add file and add subdir */ + if (access_mask & SEC_ADS_CREATE_CHILD) + fs_mask |= SEC_DIR_ADD_FILE | SEC_DIR_ADD_SUBDIR; + + /* Map ADS delete child to dir delete child */ + if (access_mask & SEC_ADS_DELETE_CHILD) + fs_mask |= SEC_DIR_DELETE_CHILD; + + return fs_mask; +} + +NTSTATUS gp_create_gpt_security_descriptor(TALLOC_CTX *mem_ctx, struct security_descriptor *ds_sd, struct security_descriptor **ret) { + struct security_descriptor *fs_sd; + NTSTATUS status; + uint32_t i; + + /* Allocate the file system security descriptor */ + fs_sd = talloc(mem_ctx, struct security_descriptor); + NT_STATUS_HAVE_NO_MEMORY(fs_sd); + + /* Copy the basic information from the directory server security descriptor */ + fs_sd->owner_sid = talloc_memdup(fs_sd, ds_sd->owner_sid, sizeof(struct dom_sid)); + if (fs_sd->owner_sid == NULL) { + TALLOC_FREE(fs_sd); + return NT_STATUS_NO_MEMORY; + } + + fs_sd->group_sid = talloc_memdup(fs_sd, ds_sd->group_sid, sizeof(struct dom_sid)); + if (fs_sd->group_sid == NULL) { + TALLOC_FREE(fs_sd); + return NT_STATUS_NO_MEMORY; + } + + fs_sd->type = ds_sd->type; + fs_sd->revision = ds_sd->revision; + + /* Copy the sacl */ + fs_sd->sacl = security_acl_dup(fs_sd, ds_sd->sacl); + if (fs_sd->sacl == NULL) { + TALLOC_FREE(fs_sd); + return NT_STATUS_NO_MEMORY; + } + + /* Copy the dacl */ + fs_sd->dacl = talloc_zero(fs_sd, struct security_acl); + if (fs_sd->dacl == NULL) { + TALLOC_FREE(fs_sd); + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < ds_sd->dacl->num_aces; i++) { + char *trustee = dom_sid_string(fs_sd, &ds_sd->dacl->aces[i].trustee); + struct security_ace *ace; + + /* Don't add the allow for SID_BUILTIN_PREW2K */ + if (!(ds_sd->dacl->aces[i].type & SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) && + strcmp(trustee, SID_BUILTIN_PREW2K) == 0) { + talloc_free(trustee); + continue; + } + + /* Copy the ace from the directory server security descriptor */ + ace = talloc_memdup(fs_sd, &ds_sd->dacl->aces[i], sizeof(struct security_ace)); + if (ace == NULL) { + TALLOC_FREE(fs_sd); + return NT_STATUS_NO_MEMORY; + } + + /* Set specific inheritance flags for within the GPO */ + ace->flags |= SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_CONTAINER_INHERIT; + if (strcmp(trustee, SID_CREATOR_OWNER) == 0) { + ace->flags |= SEC_ACE_FLAG_INHERIT_ONLY; + } + + /* Get a directory access mask from the assigned access mask on the LDAP object */ + ace->access_mask = gp_ads_to_dir_access_mask(ace->access_mask); + + /* Add the ace to the security descriptor DACL */ + status = security_descriptor_dacl_add(fs_sd, ace); + if (!NT_STATUS_IS_OK(status)) { + // DEBUG(0, ("Failed to add a dacl to file system security descriptor\n")); + return status; + } + + /* Clean up the allocated data in this iteration */ + talloc_free(trustee); + } + + *ret = fs_sd; + return NT_STATUS_OK; +} diff --git a/src/adldap/samba/gp_manage.cpp b/src/adldap/samba/gp_manage.cpp deleted file mode 100644 index bf2201b8..00000000 --- a/src/adldap/samba/gp_manage.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * Group Policy Object Support - * Copyright (C) Wilco Baan Hofman 2010 - * - * 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 . - */ - -/* - * This file is a copy of private files from samba source. - * Parts of it were removed or edited. - */ - -#include "gp_manage.h" - -#include "dom_sid.h" - -#include - -#include - -/* - * This file is a copy of private samba sources. Parts of it - * were removed or edited. - */ - -bool security_descriptor_acl_add(struct security_descriptor *sd, - bool add_to_sacl, - const struct security_ace *ace) -{ - struct security_acl *acl = NULL; - - if (add_to_sacl) { - acl = sd->sacl; - } else { - acl = sd->dacl; - } - - if (acl == NULL) { - acl = talloc(sd, struct security_acl); - if (acl == NULL) { - // return NT_STATUS_NO_MEMORY; - return false; - } - acl->revision = SECURITY_ACL_REVISION_NT4; - acl->size = 0; - acl->num_aces = 0; - acl->aces = NULL; - } - - acl->aces = talloc_realloc(acl, acl->aces, - struct security_ace, acl->num_aces+1); - if (acl->aces == NULL) { - // return NT_STATUS_NO_MEMORY; - return false; - } - - acl->aces[acl->num_aces] = *ace; - - switch (acl->aces[acl->num_aces].type) { - case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: - case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: - case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: - case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: - acl->revision = SECURITY_ACL_REVISION_ADS; - break; - default: - break; - } - - acl->num_aces++; - - if (add_to_sacl) { - sd->sacl = acl; - sd->type |= SEC_DESC_SACL_PRESENT; - } else { - sd->dacl = acl; - sd->type |= SEC_DESC_DACL_PRESENT; - } - - // return NT_STATUS_OK; - return true; -} - -/* - add an ACE to the SACL of a security_descriptor -*/ - -bool security_descriptor_sacl_add(struct security_descriptor *sd, - const struct security_ace *ace) -{ - return security_descriptor_acl_add(sd, true, ace); -} - -/* - add an ACE to the DACL of a security_descriptor -*/ - -bool security_descriptor_dacl_add(struct security_descriptor *sd, - const struct security_ace *ace) -{ - return security_descriptor_acl_add(sd, false, ace); -} - -uint32_t gp_ads_to_dir_access_mask(uint32_t access_mask) -{ - uint32_t fs_mask; - - /* Copy the standard access mask */ - fs_mask = access_mask & 0x001F0000; - - /* When READ_PROP and LIST_CONTENTS are set, read access is granted on the GPT */ - if (access_mask & SEC_ADS_READ_PROP && access_mask & SEC_ADS_LIST) { - fs_mask |= SEC_STD_SYNCHRONIZE | SEC_DIR_LIST | SEC_DIR_READ_ATTRIBUTE | - SEC_DIR_READ_EA | SEC_DIR_TRAVERSE; - } - - /* When WRITE_PROP is set, full write access is granted on the GPT */ - if (access_mask & SEC_ADS_WRITE_PROP) { - fs_mask |= SEC_STD_SYNCHRONIZE | SEC_DIR_WRITE_ATTRIBUTE | - SEC_DIR_WRITE_EA | SEC_DIR_ADD_FILE | - SEC_DIR_ADD_SUBDIR; - } - - /* Map CREATE_CHILD to add file and add subdir */ - if (access_mask & SEC_ADS_CREATE_CHILD) - fs_mask |= SEC_DIR_ADD_FILE | SEC_DIR_ADD_SUBDIR; - - /* Map ADS delete child to dir delete child */ - if (access_mask & SEC_ADS_DELETE_CHILD) - fs_mask |= SEC_DIR_DELETE_CHILD; - - return fs_mask; -} - -struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx, - const struct security_acl *oacl) -{ - struct security_acl *nacl; - - if (oacl == NULL) { - return NULL; - } - - if (oacl->aces == NULL && oacl->num_aces > 0) { - return NULL; - } - - nacl = talloc (mem_ctx, struct security_acl); - if (nacl == NULL) { - return NULL; - } - - *nacl = (struct security_acl) { - .revision = oacl->revision, - .size = oacl->size, - .num_aces = oacl->num_aces, - }; - if (nacl->num_aces == 0) { - return nacl; - } - - nacl->aces = (struct security_ace *)talloc_memdup (nacl, oacl->aces, sizeof(struct security_ace) * oacl->num_aces); - if (nacl->aces == NULL) { - goto failed; - } - - return nacl; - - failed: - talloc_free (nacl); - return NULL; - -} - -bool gp_create_gpt_security_descriptor(TALLOC_CTX *mem_ctx, struct security_descriptor *ds_sd, struct security_descriptor **ret) { - struct security_descriptor *fs_sd; - - /* Allocate the file system security descriptor */ - fs_sd = talloc(mem_ctx, struct security_descriptor); - - /* Copy the basic information from the directory server security descriptor */ - fs_sd->owner_sid = (dom_sid *) talloc_memdup(fs_sd, ds_sd->owner_sid, sizeof(struct dom_sid)); - if (fs_sd->owner_sid == NULL) { - TALLOC_FREE(fs_sd); - qDebug() << "Failed to allocated owner sid"; - return false; - } - - fs_sd->group_sid = (dom_sid *) talloc_memdup(fs_sd, ds_sd->group_sid, sizeof(struct dom_sid)); - if (fs_sd->group_sid == NULL) { - TALLOC_FREE(fs_sd); - qDebug() << "Failed to allocated group sid"; - return false; - } - - fs_sd->type = ds_sd->type; - fs_sd->revision = ds_sd->revision; - - /* Copy the sacl */ - fs_sd->sacl = security_acl_dup(fs_sd, ds_sd->sacl); - if (fs_sd->sacl == NULL) { - TALLOC_FREE(fs_sd); - qDebug() << "Failed to allocated sacl"; - return false; - } - - /* Copy the dacl */ - fs_sd->dacl = talloc_zero(fs_sd, struct security_acl); - if (fs_sd->dacl == NULL) { - TALLOC_FREE(fs_sd); - qDebug() << "Failed to allocated dacl"; - return false; - } - - for (uint32_t i = 0; i < ds_sd->dacl->num_aces; i++) { - const char *trustee = dom_sid_string(fs_sd, &ds_sd->dacl->aces[i].trustee); - struct security_ace *ace; - - /* Don't add the allow for SID_BUILTIN_PREW2K */ - if (!(ds_sd->dacl->aces[i].type & SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) && strcmp(trustee, SID_BUILTIN_PREW2K) == 0) { - talloc_free((void *) trustee); - continue; - } - - /* Copy the ace from the directory server security descriptor */ - ace = (security_ace *) talloc_memdup(fs_sd, &ds_sd->dacl->aces[i], sizeof(struct security_ace)); - if (ace == NULL) { - TALLOC_FREE(fs_sd); - qDebug() << "Failed to allocated ace"; - return false; - } - - /* Set specific inheritance flags for within the GPO */ - ace->flags |= SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_CONTAINER_INHERIT; - if (strcmp(trustee, SID_CREATOR_OWNER) == 0) { - ace->flags |= SEC_ACE_FLAG_INHERIT_ONLY; - } - - /* Get a directory access mask from the assigned access mask on the LDAP object */ - ace->access_mask = gp_ads_to_dir_access_mask(ace->access_mask); - - /* Add the ace to the security descriptor DACL */ - const bool dacl_add_success = security_descriptor_dacl_add(fs_sd, ace); - if (!dacl_add_success) { - qDebug() << "Failed to add a dacl to file system security descriptor"; - return false; - } - - /* Clean up the allocated data in this iteration */ - talloc_free((void *) trustee); - } - - *ret = fs_sd; - return true; -} diff --git a/src/adldap/samba/gp_manage.h b/src/adldap/samba/gp_manage.h index 774d5e5b..4a384d14 100644 --- a/src/adldap/samba/gp_manage.h +++ b/src/adldap/samba/gp_manage.h @@ -22,17 +22,21 @@ * were removed or edited. */ +#ifdef __cplusplus +extern "C" { +#endif + #ifndef GP_MANAGE_H #define GP_MANAGE_H -extern "C" { - #include #include #include -}; - -bool gp_create_gpt_security_descriptor(TALLOC_CTX *mem_ctx, struct security_descriptor *ds_sd, struct security_descriptor **ret); +NTSTATUS gp_create_gpt_security_descriptor(TALLOC_CTX *mem_ctx, struct security_descriptor *ds_sd, struct security_descriptor **ret); #endif /* GP_MANAGE_H */ + +#ifdef __cplusplus +} +#endif diff --git a/src/adldap/samba/libsmb_xattr.c b/src/adldap/samba/libsmb_xattr.c new file mode 100644 index 00000000..f4df281e --- /dev/null +++ b/src/adldap/samba/libsmb_xattr.c @@ -0,0 +1,130 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 . +*/ + +/* + * This file is a copy of private samba sources. Parts of it + * were removed or edited. + */ + +#include "samba/dom_sid.h" + +#include "samba/security_descriptor.h" + +#include +#include +#include + +/* + * Sort ACEs according to the documentation at + * http://support.microsoft.com/kb/269175, at least as far as it defines the + * order. + */ + +int ace_compare(void const *ace1_ptr, + void const *ace2_ptr) +{ + const struct security_ace *ace1 = ace1_ptr; + const struct security_ace *ace2 = ace2_ptr; + + bool b1; + bool b2; + + /* If the ACEs are equal, we have nothing more to do. */ + if (security_ace_equal(ace1, ace2)) { + return 0; + } + + /* Inherited follow non-inherited */ + b1 = ((ace1->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0); + b2 = ((ace2->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* + * What shall we do with AUDITs and ALARMs? It's undefined. We'll + * sort them after DENY and ALLOW. + */ + b1 = (ace1->type != SEC_ACE_TYPE_ACCESS_ALLOWED && + ace1->type != SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT && + ace1->type != SEC_ACE_TYPE_ACCESS_DENIED && + ace1->type != SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + b2 = (ace2->type != SEC_ACE_TYPE_ACCESS_ALLOWED && + ace2->type != SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT && + ace2->type != SEC_ACE_TYPE_ACCESS_DENIED && + ace2->type != SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* Allowed ACEs follow denied ACEs */ + b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED || + ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT); + b2 = (ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED || + ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* + * ACEs applying to an entity's object follow those applying to the + * entity itself + */ + b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || + ace1->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + b2 = (ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || + ace2->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* + * If we get this far, the ACEs are similar as far as the + * characteristics we typically care about (those defined by the + * referenced MS document). We'll now sort by characteristics that + * just seems reasonable. + */ + + if (ace1->type != ace2->type) { + return ace2->type - ace1->type; + } + + if (dom_sid_compare(&ace1->trustee, &ace2->trustee)) { + return dom_sid_compare(&ace1->trustee, &ace2->trustee); + } + + if (ace1->flags != ace2->flags) { + return ace1->flags - ace2->flags; + } + + if (ace1->access_mask != ace2->access_mask) { + return ace1->access_mask - ace2->access_mask; + } + + if (ace1->size != ace2->size) { + return ace1->size - ace2->size; + } + + return memcmp(ace1, ace2, sizeof(struct security_ace)); +} diff --git a/src/adldap/samba/libsmb_xattr.h b/src/adldap/samba/libsmb_xattr.h new file mode 100644 index 00000000..c491e64f --- /dev/null +++ b/src/adldap/samba/libsmb_xattr.h @@ -0,0 +1,42 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 . +*/ + +/* + * This file is a copy of private samba sources. Parts of it + * were removed or edited. + */ + +#ifndef LIBSMB_XATTR_H +#define LIBSMB_XATTR_H + +extern "C" { + +struct security_ace; + +int ace_compare(void const *ace1, + void const *ace2); + +}; + +#endif /* LIBSMB_XATTR_H */ diff --git a/src/adldap/samba/misc.h b/src/adldap/samba/misc.h new file mode 100644 index 00000000..c631b61d --- /dev/null +++ b/src/adldap/samba/misc.h @@ -0,0 +1,185 @@ +/* + * Unix SMB/CIFS implementation. + * Group Policy Object Support + * Copyright (C) Wilco Baan Hofman 2010 + * + * 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 . + */ + +/* + * This file is a copy of private samba generated sources. + */ + +/* header auto-generated by pidl */ + +#ifndef _PIDL_HEADER_misc +#define _PIDL_HEADER_misc + +// NOTE: extra headers needed to compile +#include +#include + +#include + +// #include "libcli/util/ntstatus.h" + +#ifndef _HEADER_misc +#define _HEADER_misc + +#define SV_TYPE_ALL ( 0xFFFFFFFF ) +struct GUID { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq[2]; + uint8_t node[6]; +}/* [gensize,noprint,public] */; + +struct ndr_syntax_id { + struct GUID uuid; + uint32_t if_version; +}/* [public] */; + +struct policy_handle { + uint32_t handle_type; + struct GUID uuid; +}/* [public] */; + +enum netr_SchannelType +#ifndef USE_UINT_ENUMS + { + SEC_CHAN_NULL=(int)(0), + SEC_CHAN_LOCAL=(int)(1), + SEC_CHAN_WKSTA=(int)(2), + SEC_CHAN_DNS_DOMAIN=(int)(3), + SEC_CHAN_DOMAIN=(int)(4), + SEC_CHAN_LANMAN=(int)(5), + SEC_CHAN_BDC=(int)(6), + SEC_CHAN_RODC=(int)(7) +} +#else + { __do_not_use_enum_netr_SchannelType=0x7FFFFFFF} +#define SEC_CHAN_NULL ( 0 ) +#define SEC_CHAN_LOCAL ( 1 ) +#define SEC_CHAN_WKSTA ( 2 ) +#define SEC_CHAN_DNS_DOMAIN ( 3 ) +#define SEC_CHAN_DOMAIN ( 4 ) +#define SEC_CHAN_LANMAN ( 5 ) +#define SEC_CHAN_BDC ( 6 ) +#define SEC_CHAN_RODC ( 7 ) +#endif +; + +struct KRB5_EDATA_NTSTATUS { + NTSTATUS ntstatus; + uint32_t unknown1; + uint32_t unknown2; +}/* [public] */; + +enum winreg_Type +#ifndef USE_UINT_ENUMS + { + REG_NONE=(int)(0), + REG_SZ=(int)(1), + REG_EXPAND_SZ=(int)(2), + REG_BINARY=(int)(3), + REG_DWORD=(int)(4), + REG_DWORD_BIG_ENDIAN=(int)(5), + REG_LINK=(int)(6), + REG_MULTI_SZ=(int)(7), + REG_RESOURCE_LIST=(int)(8), + REG_FULL_RESOURCE_DESCRIPTOR=(int)(9), + REG_RESOURCE_REQUIREMENTS_LIST=(int)(10), + REG_QWORD=(int)(11) +} +#else + { __do_not_use_enum_winreg_Type=0x7FFFFFFF} +#define REG_NONE ( 0 ) +#define REG_SZ ( 1 ) +#define REG_EXPAND_SZ ( 2 ) +#define REG_BINARY ( 3 ) +#define REG_DWORD ( 4 ) +#define REG_DWORD_BIG_ENDIAN ( 5 ) +#define REG_LINK ( 6 ) +#define REG_MULTI_SZ ( 7 ) +#define REG_RESOURCE_LIST ( 8 ) +#define REG_FULL_RESOURCE_DESCRIPTOR ( 9 ) +#define REG_RESOURCE_REQUIREMENTS_LIST ( 10 ) +#define REG_QWORD ( 11 ) +#endif +; + +union winreg_Data { + const char * string;/* [case(REG_SZ),flag(LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2)] */ + DATA_BLOB binary;/* [case(REG_BINARY),flag(LIBNDR_FLAG_REMAINING)] */ + uint32_t value;/* [case(REG_DWORD)] */ + const char ** string_array;/* [case(REG_MULTI_SZ),flag(LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2)] */ + uint64_t qword;/* [case(REG_QWORD)] */ + DATA_BLOB data;/* [default,flag(LIBNDR_FLAG_REMAINING)] */ +}/* [flag(LIBNDR_FLAG_LITTLE_ENDIAN),nodiscriminant,public] */; + +union winreg_Data_GPO { + const char * string;/* [case(REG_SZ),flag(LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2)] */ + DATA_BLOB binary;/* [case(REG_BINARY),flag(LIBNDR_FLAG_REMAINING)] */ + uint32_t value;/* [case(REG_DWORD)] */ + uint64_t qword;/* [case(REG_QWORD)] */ + DATA_BLOB data;/* [default,flag(LIBNDR_FLAG_REMAINING)] */ +}/* [flag(LIBNDR_FLAG_LITTLE_ENDIAN),gensize,nodiscriminant,public] */; + +enum netr_SamDatabaseID +#ifndef USE_UINT_ENUMS + { + SAM_DATABASE_DOMAIN=(int)(0), + SAM_DATABASE_BUILTIN=(int)(1), + SAM_DATABASE_PRIVS=(int)(2) +} +#else + { __do_not_use_enum_netr_SamDatabaseID=0x7FFFFFFF} +#define SAM_DATABASE_DOMAIN ( 0 ) +#define SAM_DATABASE_BUILTIN ( 1 ) +#define SAM_DATABASE_PRIVS ( 2 ) +#endif +; + +/* bitmap svcctl_ServerType */ +#define SV_TYPE_WORKSTATION ( 0x00000001 ) +#define SV_TYPE_SERVER ( 0x00000002 ) +#define SV_TYPE_SQLSERVER ( 0x00000004 ) +#define SV_TYPE_DOMAIN_CTRL ( 0x00000008 ) +#define SV_TYPE_DOMAIN_BAKCTRL ( 0x00000010 ) +#define SV_TYPE_TIME_SOURCE ( 0x00000020 ) +#define SV_TYPE_AFP ( 0x00000040 ) +#define SV_TYPE_NOVELL ( 0x00000080 ) +#define SV_TYPE_DOMAIN_MEMBER ( 0x00000100 ) +#define SV_TYPE_PRINTQ_SERVER ( 0x00000200 ) +#define SV_TYPE_DIALIN_SERVER ( 0x00000400 ) +#define SV_TYPE_SERVER_UNIX ( 0x00000800 ) +#define SV_TYPE_NT ( 0x00001000 ) +#define SV_TYPE_WFW ( 0x00002000 ) +#define SV_TYPE_SERVER_MFPN ( 0x00004000 ) +#define SV_TYPE_SERVER_NT ( 0x00008000 ) +#define SV_TYPE_POTENTIAL_BROWSER ( 0x00010000 ) +#define SV_TYPE_BACKUP_BROWSER ( 0x00020000 ) +#define SV_TYPE_MASTER_BROWSER ( 0x00040000 ) +#define SV_TYPE_DOMAIN_MASTER ( 0x00080000 ) +#define SV_TYPE_SERVER_OSF ( 0x00100000 ) +#define SV_TYPE_SERVER_VMS ( 0x00200000 ) +#define SV_TYPE_WIN95_PLUS ( 0x00400000 ) +#define SV_TYPE_DFS_SERVER ( 0x00800000 ) +#define SV_TYPE_ALTERNATE_XPORT ( 0x20000000 ) +#define SV_TYPE_LOCAL_LIST_ONLY ( 0x40000000 ) +#define SV_TYPE_DOMAIN_ENUM ( 0x80000000 ) + +#endif /* _HEADER_misc */ +#endif /* _PIDL_HEADER_misc */ diff --git a/src/adldap/samba/ndr_misc.c b/src/adldap/samba/ndr_misc.c new file mode 100644 index 00000000..48a67246 --- /dev/null +++ b/src/adldap/samba/ndr_misc.c @@ -0,0 +1,890 @@ +/* + * Unix SMB/CIFS implementation. + * Group Policy Object Support + * Copyright (C) Wilco Baan Hofman 2010 + * + * 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 . + */ + +/* + * This file is a copy of private samba generated sources. + */ + +#include "samba/ndr_misc.h" + +/* parser auto-generated by pidl */ + +// #include "includes.h" +// #include "bin/default/librpc/gen_ndr/ndr_misc.h" + +_PUBLIC_ enum ndr_err_code ndr_push_GUID(struct ndr_push *ndr, int ndr_flags, const struct GUID *r) +{ + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->time_low)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->time_mid)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->time_hi_and_version)); + NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->clock_seq, 2)); + NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->node, 6)); + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_GUID(struct ndr_pull *ndr, int ndr_flags, struct GUID *r) +{ + uint32_t size_clock_seq_0 = 0; + uint32_t size_node_0 = 0; + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->time_low)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->time_mid)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->time_hi_and_version)); + size_clock_seq_0 = 2; + NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->clock_seq, size_clock_seq_0)); + size_node_0 = 6; + NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->node, size_node_0)); + NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +static void ndr_print_flags_GUID(struct ndr_print *ndr, const char *name, int unused, const struct GUID *r) +{ + ndr_print_GUID(ndr, name, r); +} + +_PUBLIC_ size_t ndr_size_GUID(const struct GUID *r, int flags) +{ + return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_GUID); +} + +_PUBLIC_ enum ndr_err_code ndr_push_ndr_syntax_id(struct ndr_push *ndr, int ndr_flags, const struct ndr_syntax_id *r) +{ + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_GUID(ndr, NDR_SCALARS, &r->uuid)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->if_version)); + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_ndr_syntax_id(struct ndr_pull *ndr, int ndr_flags, struct ndr_syntax_id *r) +{ + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->uuid)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->if_version)); + NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +static void ndr_print_flags_ndr_syntax_id(struct ndr_print *ndr, const char *name, int unused, const struct ndr_syntax_id *r) +{ + ndr_print_ndr_syntax_id(ndr, name, r); +} + +_PUBLIC_ void ndr_print_ndr_syntax_id(struct ndr_print *ndr, const char *name, const struct ndr_syntax_id *r) +{ + ndr_print_struct(ndr, name, "ndr_syntax_id"); + if (r == NULL) { ndr_print_null(ndr); return; } + ndr->depth++; + ndr_print_GUID(ndr, "uuid", &r->uuid); + ndr_print_uint32(ndr, "if_version", r->if_version); + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_policy_handle(struct ndr_push *ndr, int ndr_flags, const struct policy_handle *r) +{ + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->handle_type)); + NDR_CHECK(ndr_push_GUID(ndr, NDR_SCALARS, &r->uuid)); + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_policy_handle(struct ndr_pull *ndr, int ndr_flags, struct policy_handle *r) +{ + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->handle_type)); + NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->uuid)); + NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +static void ndr_print_flags_policy_handle(struct ndr_print *ndr, const char *name, int unused, const struct policy_handle *r) +{ + ndr_print_policy_handle(ndr, name, r); +} + +_PUBLIC_ void ndr_print_policy_handle(struct ndr_print *ndr, const char *name, const struct policy_handle *r) +{ + ndr_print_struct(ndr, name, "policy_handle"); + if (r == NULL) { ndr_print_null(ndr); return; } + ndr->depth++; + ndr_print_uint32(ndr, "handle_type", r->handle_type); + ndr_print_GUID(ndr, "uuid", &r->uuid); + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_netr_SchannelType(struct ndr_push *ndr, int ndr_flags, enum netr_SchannelType r) +{ + NDR_CHECK(ndr_push_enum_uint1632(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_netr_SchannelType(struct ndr_pull *ndr, int ndr_flags, enum netr_SchannelType *r) +{ + uint16_t v; + NDR_CHECK(ndr_pull_enum_uint1632(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_netr_SchannelType(struct ndr_print *ndr, const char *name, enum netr_SchannelType r) +{ + const char *val = NULL; + + switch (r) { + case SEC_CHAN_NULL: val = "SEC_CHAN_NULL"; break; + case SEC_CHAN_LOCAL: val = "SEC_CHAN_LOCAL"; break; + case SEC_CHAN_WKSTA: val = "SEC_CHAN_WKSTA"; break; + case SEC_CHAN_DNS_DOMAIN: val = "SEC_CHAN_DNS_DOMAIN"; break; + case SEC_CHAN_DOMAIN: val = "SEC_CHAN_DOMAIN"; break; + case SEC_CHAN_LANMAN: val = "SEC_CHAN_LANMAN"; break; + case SEC_CHAN_BDC: val = "SEC_CHAN_BDC"; break; + case SEC_CHAN_RODC: val = "SEC_CHAN_RODC"; break; + } + ndr_print_enum(ndr, name, "ENUM", val, r); +} + +_PUBLIC_ enum ndr_err_code ndr_push_KRB5_EDATA_NTSTATUS(struct ndr_push *ndr, int ndr_flags, const struct KRB5_EDATA_NTSTATUS *r) +{ + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_NTSTATUS(ndr, NDR_SCALARS, r->ntstatus)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->unknown1)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->unknown2)); + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_KRB5_EDATA_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, struct KRB5_EDATA_NTSTATUS *r) +{ + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_NTSTATUS(ndr, NDR_SCALARS, &r->ntstatus)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->unknown1)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->unknown2)); + NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +static void ndr_print_flags_KRB5_EDATA_NTSTATUS(struct ndr_print *ndr, const char *name, int unused, const struct KRB5_EDATA_NTSTATUS *r) +{ + ndr_print_KRB5_EDATA_NTSTATUS(ndr, name, r); +} + +_PUBLIC_ void ndr_print_KRB5_EDATA_NTSTATUS(struct ndr_print *ndr, const char *name, const struct KRB5_EDATA_NTSTATUS *r) +{ + ndr_print_struct(ndr, name, "KRB5_EDATA_NTSTATUS"); + if (r == NULL) { ndr_print_null(ndr); return; } + ndr->depth++; + ndr_print_NTSTATUS(ndr, "ntstatus", r->ntstatus); + ndr_print_uint32(ndr, "unknown1", r->unknown1); + ndr_print_uint32(ndr, "unknown2", r->unknown2); + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_winreg_Type(struct ndr_push *ndr, int ndr_flags, enum winreg_Type r) +{ + NDR_CHECK(ndr_push_enum_uint32(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_winreg_Type(struct ndr_pull *ndr, int ndr_flags, enum winreg_Type *r) +{ + uint32_t v; + NDR_CHECK(ndr_pull_enum_uint32(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_winreg_Type(struct ndr_print *ndr, const char *name, enum winreg_Type r) +{ + const char *val = NULL; + + switch (r) { + case REG_NONE: val = "REG_NONE"; break; + case REG_SZ: val = "REG_SZ"; break; + case REG_EXPAND_SZ: val = "REG_EXPAND_SZ"; break; + case REG_BINARY: val = "REG_BINARY"; break; + case REG_DWORD: val = "REG_DWORD"; break; + case REG_DWORD_BIG_ENDIAN: val = "REG_DWORD_BIG_ENDIAN"; break; + case REG_LINK: val = "REG_LINK"; break; + case REG_MULTI_SZ: val = "REG_MULTI_SZ"; break; + case REG_RESOURCE_LIST: val = "REG_RESOURCE_LIST"; break; + case REG_FULL_RESOURCE_DESCRIPTOR: val = "REG_FULL_RESOURCE_DESCRIPTOR"; break; + case REG_RESOURCE_REQUIREMENTS_LIST: val = "REG_RESOURCE_REQUIREMENTS_LIST"; break; + case REG_QWORD: val = "REG_QWORD"; break; + } + ndr_print_enum(ndr, name, "ENUM", val, r); +} + +_PUBLIC_ enum ndr_err_code ndr_push_winreg_Data(struct ndr_push *ndr, int ndr_flags, const union winreg_Data *r) +{ + uint32_t level; + { + uint32_t _flags_save_UNION = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + /* This token is not used again (except perhaps below in the NDR_BUFFERS case) */ + NDR_CHECK(ndr_push_steal_switch_value(ndr, r, &level)); + NDR_CHECK(ndr_push_union_align(ndr, 8)); + switch (level) { + case REG_NONE: { + break; } + + case REG_SZ: { + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->string)); + ndr->flags = _flags_save_string; + } + break; } + + case REG_EXPAND_SZ: { + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->string)); + ndr->flags = _flags_save_string; + } + break; } + + case REG_BINARY: { + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->binary)); + ndr->flags = _flags_save_DATA_BLOB; + } + break; } + + case REG_DWORD: { + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->value)); + break; } + + case REG_DWORD_BIG_ENDIAN: { + { + uint32_t _flags_save_uint32 = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->value)); + ndr->flags = _flags_save_uint32; + } + break; } + + case REG_MULTI_SZ: { + { + uint32_t _flags_save_string_array = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + NDR_CHECK(ndr_push_string_array(ndr, NDR_SCALARS, r->string_array)); + ndr->flags = _flags_save_string_array; + } + break; } + + case REG_QWORD: { + NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, r->qword)); + break; } + + default: { + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->data)); + ndr->flags = _flags_save_DATA_BLOB; + } + break; } + + } + } + ndr->flags = _flags_save_UNION; + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_winreg_Data(struct ndr_pull *ndr, int ndr_flags, union winreg_Data *r) +{ + uint32_t level; + { + uint32_t _flags_save_UNION = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + /* This token is not used again (except perhaps below in the NDR_BUFFERS case) */ + NDR_CHECK(ndr_pull_steal_switch_value(ndr, r, &level)); + NDR_CHECK(ndr_pull_union_align(ndr, 8)); + switch (level) { + case REG_NONE: { + break; } + + case REG_SZ: { + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->string)); + ndr->flags = _flags_save_string; + } + break; } + + case REG_EXPAND_SZ: { + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->string)); + ndr->flags = _flags_save_string; + } + break; } + + case REG_BINARY: { + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->binary)); + ndr->flags = _flags_save_DATA_BLOB; + } + break; } + + case REG_DWORD: { + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->value)); + break; } + + case REG_DWORD_BIG_ENDIAN: { + { + uint32_t _flags_save_uint32 = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->value)); + ndr->flags = _flags_save_uint32; + } + break; } + + case REG_MULTI_SZ: { + { + uint32_t _flags_save_string_array = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + NDR_CHECK(ndr_pull_string_array(ndr, NDR_SCALARS, &r->string_array)); + ndr->flags = _flags_save_string_array; + } + break; } + + case REG_QWORD: { + NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &r->qword)); + break; } + + default: { + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->data)); + ndr->flags = _flags_save_DATA_BLOB; + } + break; } + + } + } + ndr->flags = _flags_save_UNION; + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_winreg_Data(struct ndr_print *ndr, const char *name, const union winreg_Data *r) +{ + uint32_t level; + { + uint32_t _flags_save_UNION = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); + level = ndr_print_steal_switch_value(ndr, r); + ndr_print_union(ndr, name, level, "winreg_Data"); + switch (level) { + case REG_NONE: + break; + + case REG_SZ: + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + ndr_print_string(ndr, "string", r->string); + ndr->flags = _flags_save_string; + } + break; + + case REG_EXPAND_SZ: + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + ndr_print_string(ndr, "string", r->string); + ndr->flags = _flags_save_string; + } + break; + + case REG_BINARY: + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + ndr_print_DATA_BLOB(ndr, "binary", r->binary); + ndr->flags = _flags_save_DATA_BLOB; + } + break; + + case REG_DWORD: + ndr_print_uint32(ndr, "value", r->value); + break; + + case REG_DWORD_BIG_ENDIAN: + { + uint32_t _flags_save_uint32 = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN); + ndr_print_uint32(ndr, "value", r->value); + ndr->flags = _flags_save_uint32; + } + break; + + case REG_MULTI_SZ: + { + uint32_t _flags_save_string_array = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + ndr_print_string_array(ndr, "string_array", r->string_array); + ndr->flags = _flags_save_string_array; + } + break; + + case REG_QWORD: + ndr_print_hyper(ndr, "qword", r->qword); + break; + + default: + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + ndr_print_DATA_BLOB(ndr, "data", r->data); + ndr->flags = _flags_save_DATA_BLOB; + } + break; + + } + ndr->flags = _flags_save_UNION; + } +} + +_PUBLIC_ enum ndr_err_code ndr_push_winreg_Data_GPO(struct ndr_push *ndr, int ndr_flags, const union winreg_Data_GPO *r) +{ + uint32_t level; + { + uint32_t _flags_save_UNION = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + /* This token is not used again (except perhaps below in the NDR_BUFFERS case) */ + NDR_CHECK(ndr_push_steal_switch_value(ndr, r, &level)); + NDR_CHECK(ndr_push_union_align(ndr, 8)); + switch (level) { + case REG_NONE: { + break; } + + case REG_SZ: { + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->string)); + ndr->flags = _flags_save_string; + } + break; } + + case REG_EXPAND_SZ: { + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->string)); + ndr->flags = _flags_save_string; + } + break; } + + case REG_BINARY: { + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->binary)); + ndr->flags = _flags_save_DATA_BLOB; + } + break; } + + case REG_DWORD: { + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->value)); + break; } + + case REG_DWORD_BIG_ENDIAN: { + { + uint32_t _flags_save_uint32 = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->value)); + ndr->flags = _flags_save_uint32; + } + break; } + + case REG_QWORD: { + NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, r->qword)); + break; } + + default: { + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->data)); + ndr->flags = _flags_save_DATA_BLOB; + } + break; } + + } + } + ndr->flags = _flags_save_UNION; + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_winreg_Data_GPO(struct ndr_pull *ndr, int ndr_flags, union winreg_Data_GPO *r) +{ + uint32_t level; + { + uint32_t _flags_save_UNION = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + /* This token is not used again (except perhaps below in the NDR_BUFFERS case) */ + NDR_CHECK(ndr_pull_steal_switch_value(ndr, r, &level)); + NDR_CHECK(ndr_pull_union_align(ndr, 8)); + switch (level) { + case REG_NONE: { + break; } + + case REG_SZ: { + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->string)); + ndr->flags = _flags_save_string; + } + break; } + + case REG_EXPAND_SZ: { + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->string)); + ndr->flags = _flags_save_string; + } + break; } + + case REG_BINARY: { + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->binary)); + ndr->flags = _flags_save_DATA_BLOB; + } + break; } + + case REG_DWORD: { + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->value)); + break; } + + case REG_DWORD_BIG_ENDIAN: { + { + uint32_t _flags_save_uint32 = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->value)); + ndr->flags = _flags_save_uint32; + } + break; } + + case REG_QWORD: { + NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &r->qword)); + break; } + + default: { + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->data)); + ndr->flags = _flags_save_DATA_BLOB; + } + break; } + + } + } + ndr->flags = _flags_save_UNION; + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_winreg_Data_GPO(struct ndr_print *ndr, const char *name, const union winreg_Data_GPO *r) +{ + uint32_t level; + { + uint32_t _flags_save_UNION = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); + level = ndr_print_steal_switch_value(ndr, r); + ndr_print_union(ndr, name, level, "winreg_Data_GPO"); + switch (level) { + case REG_NONE: + break; + + case REG_SZ: + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + ndr_print_string(ndr, "string", r->string); + ndr->flags = _flags_save_string; + } + break; + + case REG_EXPAND_SZ: + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2); + ndr_print_string(ndr, "string", r->string); + ndr->flags = _flags_save_string; + } + break; + + case REG_BINARY: + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + ndr_print_DATA_BLOB(ndr, "binary", r->binary); + ndr->flags = _flags_save_DATA_BLOB; + } + break; + + case REG_DWORD: + ndr_print_uint32(ndr, "value", r->value); + break; + + case REG_DWORD_BIG_ENDIAN: + { + uint32_t _flags_save_uint32 = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN); + ndr_print_uint32(ndr, "value", r->value); + ndr->flags = _flags_save_uint32; + } + break; + + case REG_QWORD: + ndr_print_hyper(ndr, "qword", r->qword); + break; + + default: + { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); + ndr_print_DATA_BLOB(ndr, "data", r->data); + ndr->flags = _flags_save_DATA_BLOB; + } + break; + + } + ndr->flags = _flags_save_UNION; + } +} + +_PUBLIC_ size_t ndr_size_winreg_Data_GPO(const union winreg_Data_GPO *r, uint32_t level, int flags) +{ + flags |= LIBNDR_FLAG_LITTLE_ENDIAN; + return ndr_size_union(r, flags, level, (ndr_push_flags_fn_t)ndr_push_winreg_Data_GPO); +} + +_PUBLIC_ enum ndr_err_code ndr_push_netr_SamDatabaseID(struct ndr_push *ndr, int ndr_flags, enum netr_SamDatabaseID r) +{ + NDR_CHECK(ndr_push_enum_uint32(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_netr_SamDatabaseID(struct ndr_pull *ndr, int ndr_flags, enum netr_SamDatabaseID *r) +{ + uint32_t v; + NDR_CHECK(ndr_pull_enum_uint32(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_netr_SamDatabaseID(struct ndr_print *ndr, const char *name, enum netr_SamDatabaseID r) +{ + const char *val = NULL; + + switch (r) { + case SAM_DATABASE_DOMAIN: val = "SAM_DATABASE_DOMAIN"; break; + case SAM_DATABASE_BUILTIN: val = "SAM_DATABASE_BUILTIN"; break; + case SAM_DATABASE_PRIVS: val = "SAM_DATABASE_PRIVS"; break; + } + ndr_print_enum(ndr, name, "ENUM", val, r); +} + +_PUBLIC_ enum ndr_err_code ndr_push_svcctl_ServerType(struct ndr_push *ndr, int ndr_flags, uint32_t r) +{ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_svcctl_ServerType(struct ndr_pull *ndr, int ndr_flags, uint32_t *r) +{ + uint32_t v; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_svcctl_ServerType(struct ndr_print *ndr, const char *name, uint32_t r) +{ + ndr_print_uint32(ndr, name, r); + ndr->depth++; + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_WORKSTATION", SV_TYPE_WORKSTATION, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_SERVER", SV_TYPE_SERVER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_SQLSERVER", SV_TYPE_SQLSERVER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_DOMAIN_CTRL", SV_TYPE_DOMAIN_CTRL, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_DOMAIN_BAKCTRL", SV_TYPE_DOMAIN_BAKCTRL, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_TIME_SOURCE", SV_TYPE_TIME_SOURCE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_AFP", SV_TYPE_AFP, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_NOVELL", SV_TYPE_NOVELL, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_DOMAIN_MEMBER", SV_TYPE_DOMAIN_MEMBER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_PRINTQ_SERVER", SV_TYPE_PRINTQ_SERVER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_DIALIN_SERVER", SV_TYPE_DIALIN_SERVER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_SERVER_UNIX", SV_TYPE_SERVER_UNIX, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_NT", SV_TYPE_NT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_WFW", SV_TYPE_WFW, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_SERVER_MFPN", SV_TYPE_SERVER_MFPN, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_SERVER_NT", SV_TYPE_SERVER_NT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_POTENTIAL_BROWSER", SV_TYPE_POTENTIAL_BROWSER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_BACKUP_BROWSER", SV_TYPE_BACKUP_BROWSER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_MASTER_BROWSER", SV_TYPE_MASTER_BROWSER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_DOMAIN_MASTER", SV_TYPE_DOMAIN_MASTER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_SERVER_OSF", SV_TYPE_SERVER_OSF, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_SERVER_VMS", SV_TYPE_SERVER_VMS, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_WIN95_PLUS", SV_TYPE_WIN95_PLUS, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_DFS_SERVER", SV_TYPE_DFS_SERVER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_ALTERNATE_XPORT", SV_TYPE_ALTERNATE_XPORT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_LOCAL_LIST_ONLY", SV_TYPE_LOCAL_LIST_ONLY, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SV_TYPE_DOMAIN_ENUM", SV_TYPE_DOMAIN_ENUM, r); + ndr->depth--; +} + +#ifndef SKIP_NDR_TABLE_misc +static const struct ndr_interface_public_struct misc_public_structs[] = { + { + .name = "GUID", + .struct_size = sizeof(struct GUID ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_GUID, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_GUID, + .ndr_print = (ndr_print_function_t) ndr_print_flags_GUID, + }, + { + .name = "ndr_syntax_id", + .struct_size = sizeof(struct ndr_syntax_id ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_ndr_syntax_id, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_ndr_syntax_id, + .ndr_print = (ndr_print_function_t) ndr_print_flags_ndr_syntax_id, + }, + { + .name = "policy_handle", + .struct_size = sizeof(struct policy_handle ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_policy_handle, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_policy_handle, + .ndr_print = (ndr_print_function_t) ndr_print_flags_policy_handle, + }, + { + .name = "KRB5_EDATA_NTSTATUS", + .struct_size = sizeof(struct KRB5_EDATA_NTSTATUS ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_KRB5_EDATA_NTSTATUS, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_KRB5_EDATA_NTSTATUS, + .ndr_print = (ndr_print_function_t) ndr_print_flags_KRB5_EDATA_NTSTATUS, + }, + { .name = NULL } +}; + +static const struct ndr_interface_call misc_calls[] = { + { .name = NULL } +}; + +static const char * const misc_endpoint_strings[] = { + "ncacn_np:[\\pipe\\misc]", +}; + +static const struct ndr_interface_string_array misc_endpoints = { + .count = 1, + .names = misc_endpoint_strings +}; + +static const char * const misc_authservice_strings[] = { + "host", +}; + +static const struct ndr_interface_string_array misc_authservices = { + .count = 1, + .names = misc_authservice_strings +}; + + +const struct ndr_interface_table ndr_table_misc = { + .name = "misc", + .num_calls = 0, + .calls = misc_calls, + .num_public_structs = 4, + .public_structs = misc_public_structs, + .endpoints = &misc_endpoints, + .authservices = &misc_authservices +}; + +#endif /* SKIP_NDR_TABLE_misc */ diff --git a/src/adldap/samba/ndr_misc.h b/src/adldap/samba/ndr_misc.h new file mode 100644 index 00000000..14a122fc --- /dev/null +++ b/src/adldap/samba/ndr_misc.h @@ -0,0 +1,76 @@ +/* + * Unix SMB/CIFS implementation. + * Group Policy Object Support + * Copyright (C) Wilco Baan Hofman 2010 + * + * 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 . + */ + +/* + * This file is a copy of private samba generated sources. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* header auto-generated by pidl */ + +// #include "librpc/ndr/libndr.h" +// #include "bin/default/librpc/gen_ndr/misc.h" + +#ifndef _HEADER_NDR_misc +#define _HEADER_NDR_misc + +extern const struct ndr_interface_table ndr_table_misc; +#define NDR_MISC_CALL_COUNT (0) +enum ndr_err_code ndr_push_GUID(struct ndr_push *ndr, int ndr_flags, const struct GUID *r); +enum ndr_err_code ndr_pull_GUID(struct ndr_pull *ndr, int ndr_flags, struct GUID *r); +void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *r); +size_t ndr_size_GUID(const struct GUID *r, int flags); +enum ndr_err_code ndr_push_ndr_syntax_id(struct ndr_push *ndr, int ndr_flags, const struct ndr_syntax_id *r); +enum ndr_err_code ndr_pull_ndr_syntax_id(struct ndr_pull *ndr, int ndr_flags, struct ndr_syntax_id *r); +void ndr_print_ndr_syntax_id(struct ndr_print *ndr, const char *name, const struct ndr_syntax_id *r); +enum ndr_err_code ndr_push_policy_handle(struct ndr_push *ndr, int ndr_flags, const struct policy_handle *r); +enum ndr_err_code ndr_pull_policy_handle(struct ndr_pull *ndr, int ndr_flags, struct policy_handle *r); +void ndr_print_policy_handle(struct ndr_print *ndr, const char *name, const struct policy_handle *r); +enum ndr_err_code ndr_push_netr_SchannelType(struct ndr_push *ndr, int ndr_flags, enum netr_SchannelType r); +enum ndr_err_code ndr_pull_netr_SchannelType(struct ndr_pull *ndr, int ndr_flags, enum netr_SchannelType *r); +void ndr_print_netr_SchannelType(struct ndr_print *ndr, const char *name, enum netr_SchannelType r); +enum ndr_err_code ndr_push_KRB5_EDATA_NTSTATUS(struct ndr_push *ndr, int ndr_flags, const struct KRB5_EDATA_NTSTATUS *r); +enum ndr_err_code ndr_pull_KRB5_EDATA_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, struct KRB5_EDATA_NTSTATUS *r); +void ndr_print_KRB5_EDATA_NTSTATUS(struct ndr_print *ndr, const char *name, const struct KRB5_EDATA_NTSTATUS *r); +enum ndr_err_code ndr_push_winreg_Type(struct ndr_push *ndr, int ndr_flags, enum winreg_Type r); +enum ndr_err_code ndr_pull_winreg_Type(struct ndr_pull *ndr, int ndr_flags, enum winreg_Type *r); +void ndr_print_winreg_Type(struct ndr_print *ndr, const char *name, enum winreg_Type r); +enum ndr_err_code ndr_push_winreg_Data(struct ndr_push *ndr, int ndr_flags, const union winreg_Data *r); +enum ndr_err_code ndr_pull_winreg_Data(struct ndr_pull *ndr, int ndr_flags, union winreg_Data *r); +void ndr_print_winreg_Data(struct ndr_print *ndr, const char *name, const union winreg_Data *r); +enum ndr_err_code ndr_push_winreg_Data_GPO(struct ndr_push *ndr, int ndr_flags, const union winreg_Data_GPO *r); +enum ndr_err_code ndr_pull_winreg_Data_GPO(struct ndr_pull *ndr, int ndr_flags, union winreg_Data_GPO *r); +void ndr_print_winreg_Data_GPO(struct ndr_print *ndr, const char *name, const union winreg_Data_GPO *r); +size_t ndr_size_winreg_Data_GPO(const union winreg_Data_GPO *r, uint32_t level, int flags); +enum ndr_err_code ndr_push_netr_SamDatabaseID(struct ndr_push *ndr, int ndr_flags, enum netr_SamDatabaseID r); +enum ndr_err_code ndr_pull_netr_SamDatabaseID(struct ndr_pull *ndr, int ndr_flags, enum netr_SamDatabaseID *r); +void ndr_print_netr_SamDatabaseID(struct ndr_print *ndr, const char *name, enum netr_SamDatabaseID r); +enum ndr_err_code ndr_push_svcctl_ServerType(struct ndr_push *ndr, int ndr_flags, uint32_t r); +enum ndr_err_code ndr_pull_svcctl_ServerType(struct ndr_pull *ndr, int ndr_flags, uint32_t *r); +void ndr_print_svcctl_ServerType(struct ndr_print *ndr, const char *name, uint32_t r); +#endif /* _HEADER_NDR_misc */ + +#ifdef __cplusplus +} +#endif diff --git a/src/adldap/samba/ndr_security.c b/src/adldap/samba/ndr_security.c index 34f02366..b3bf70ef 100644 --- a/src/adldap/samba/ndr_security.c +++ b/src/adldap/samba/ndr_security.c @@ -18,332 +18,598 @@ */ /* - * This file is a copy of private samba sources. Parts of it - * were removed or edited. + * This file is a copy of private samba generated sources. */ -// #include "util/util.h" -#include -#include -#include +#include "samba/ndr_security.h" -#ifndef N_ELEMENTS -#define N_ELEMENTS(arr) (sizeof(arr) / sizeof(arr[0])) -#endif +#include "samba/ndr_misc.h" -static enum ndr_err_code -ndr_pull_GUID(struct ndr_pull *ndr, - int ndr_flags, - struct GUID *r) +static void ndr_print_flags_dom_sid(struct ndr_print *ndr, const char *name, int unused, const struct dom_sid *r) { - uint32_t size_clock_seq_0 = 0; - uint32_t size_node_0 = 0; - NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); - if (ndr_flags & NDR_SCALARS) { - NDR_CHECK(ndr_pull_align(ndr, 4)); - NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->time_low)); - NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->time_mid)); - NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->time_hi_and_version)); - size_clock_seq_0 = 2; - NDR_CHECK(ndr_pull_array_uint8(ndr, - NDR_SCALARS, - r->clock_seq, - size_clock_seq_0)); - size_node_0 = 6; - NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->node, size_node_0)); - NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); - } - if (ndr_flags & NDR_BUFFERS) { - } + ndr_print_dom_sid(ndr, name, r); +} + +static enum ndr_err_code ndr_push_se_privilege(struct ndr_push *ndr, int ndr_flags, uint64_t r) +{ + NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, r)); return NDR_ERR_SUCCESS; } -static enum ndr_err_code -ndr_pull_security_ace_flags(struct ndr_pull *ndr, - int ndr_flags, - uint8_t *r) +static enum ndr_err_code ndr_pull_se_privilege(struct ndr_pull *ndr, int ndr_flags, uint64_t *r) { - uint8_t v; - NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &v)); + uint64_t v; + NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &v)); *r = v; return NDR_ERR_SUCCESS; } - -static enum ndr_err_code -ndr_pull_security_ace_type(struct ndr_pull *ndr, - int ndr_flags, - enum security_ace_type *r) +_PUBLIC_ void ndr_print_se_privilege(struct ndr_print *ndr, const char *name, uint64_t r) { - uint8_t v; - NDR_CHECK(ndr_pull_enum_uint8(ndr, ndr_flags, &v)); - *r = v; + ndr_print_hyper(ndr, name, r); + ndr->depth++; + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_MACHINE_ACCOUNT_BIT", SEC_PRIV_MACHINE_ACCOUNT_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_PRINT_OPERATOR_BIT", SEC_PRIV_PRINT_OPERATOR_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_ADD_USERS_BIT", SEC_PRIV_ADD_USERS_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_DISK_OPERATOR_BIT", SEC_PRIV_DISK_OPERATOR_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_REMOTE_SHUTDOWN_BIT", SEC_PRIV_REMOTE_SHUTDOWN_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_BACKUP_BIT", SEC_PRIV_BACKUP_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_RESTORE_BIT", SEC_PRIV_RESTORE_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_TAKE_OWNERSHIP_BIT", SEC_PRIV_TAKE_OWNERSHIP_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_INCREASE_QUOTA_BIT", SEC_PRIV_INCREASE_QUOTA_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_SECURITY_BIT", SEC_PRIV_SECURITY_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_LOAD_DRIVER_BIT", SEC_PRIV_LOAD_DRIVER_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_SYSTEM_PROFILE_BIT", SEC_PRIV_SYSTEM_PROFILE_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_SYSTEMTIME_BIT", SEC_PRIV_SYSTEMTIME_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_PROFILE_SINGLE_PROCESS_BIT", SEC_PRIV_PROFILE_SINGLE_PROCESS_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_INCREASE_BASE_PRIORITY_BIT", SEC_PRIV_INCREASE_BASE_PRIORITY_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_CREATE_PAGEFILE_BIT", SEC_PRIV_CREATE_PAGEFILE_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_SHUTDOWN_BIT", SEC_PRIV_SHUTDOWN_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_DEBUG_BIT", SEC_PRIV_DEBUG_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_SYSTEM_ENVIRONMENT_BIT", SEC_PRIV_SYSTEM_ENVIRONMENT_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_CHANGE_NOTIFY_BIT", SEC_PRIV_CHANGE_NOTIFY_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_UNDOCK_BIT", SEC_PRIV_UNDOCK_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_ENABLE_DELEGATION_BIT", SEC_PRIV_ENABLE_DELEGATION_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_MANAGE_VOLUME_BIT", SEC_PRIV_MANAGE_VOLUME_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_IMPERSONATE_BIT", SEC_PRIV_IMPERSONATE_BIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint64_t), "SEC_PRIV_CREATE_GLOBAL_BIT", SEC_PRIV_CREATE_GLOBAL_BIT, r); + ndr->depth--; +} + +static enum ndr_err_code ndr_push_lsa_SystemAccessModeFlags(struct ndr_push *ndr, int ndr_flags, uint32_t r) +{ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r)); return NDR_ERR_SUCCESS; } - -static enum ndr_err_code -ndr_pull_security_ace_object_flags(struct ndr_pull *ndr, - int ndr_flags, - uint32_t *r) +static enum ndr_err_code ndr_pull_lsa_SystemAccessModeFlags(struct ndr_pull *ndr, int ndr_flags, uint32_t *r) { uint32_t v; - NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &v)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v)); *r = v; return NDR_ERR_SUCCESS; } +_PUBLIC_ void ndr_print_lsa_SystemAccessModeFlags(struct ndr_print *ndr, const char *name, uint32_t r) +{ + ndr_print_uint32(ndr, name, r); + ndr->depth++; + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_INTERACTIVE", LSA_POLICY_MODE_INTERACTIVE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_NETWORK", LSA_POLICY_MODE_NETWORK, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_BATCH", LSA_POLICY_MODE_BATCH, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_SERVICE", LSA_POLICY_MODE_SERVICE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_PROXY", LSA_POLICY_MODE_PROXY, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_DENY_INTERACTIVE", LSA_POLICY_MODE_DENY_INTERACTIVE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_DENY_NETWORK", LSA_POLICY_MODE_DENY_NETWORK, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_DENY_BATCH", LSA_POLICY_MODE_DENY_BATCH, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_DENY_SERVICE", LSA_POLICY_MODE_DENY_SERVICE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_REMOTE_INTERACTIVE", LSA_POLICY_MODE_REMOTE_INTERACTIVE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_DENY_REMOTE_INTERACTIVE", LSA_POLICY_MODE_DENY_REMOTE_INTERACTIVE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_ALL", LSA_POLICY_MODE_ALL, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "LSA_POLICY_MODE_ALL_NT4", LSA_POLICY_MODE_ALL_NT4, r); + ndr->depth--; +} -static enum ndr_err_code -ndr_pull_security_ace_object_type(struct ndr_pull *ndr, - int ndr_flags, - union security_ace_object_type *r) +_PUBLIC_ enum ndr_err_code ndr_push_security_ace_flags(struct ndr_push *ndr, int ndr_flags, uint8_t r) +{ + NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_ace_flags(struct ndr_pull *ndr, int ndr_flags, uint8_t *r) +{ + uint8_t v; + NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_security_ace_flags(struct ndr_print *ndr, const char *name, uint8_t r) +{ + ndr_print_uint8(ndr, name, r); + ndr->depth++; + ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_OBJECT_INHERIT", SEC_ACE_FLAG_OBJECT_INHERIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_CONTAINER_INHERIT", SEC_ACE_FLAG_CONTAINER_INHERIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_NO_PROPAGATE_INHERIT", SEC_ACE_FLAG_NO_PROPAGATE_INHERIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_INHERIT_ONLY", SEC_ACE_FLAG_INHERIT_ONLY, r); + ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_INHERITED_ACE", SEC_ACE_FLAG_INHERITED_ACE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_VALID_INHERIT", SEC_ACE_FLAG_VALID_INHERIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_SUCCESSFUL_ACCESS", SEC_ACE_FLAG_SUCCESSFUL_ACCESS, r); + ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_FAILED_ACCESS", SEC_ACE_FLAG_FAILED_ACCESS, r); + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_security_ace_type(struct ndr_push *ndr, int ndr_flags, enum security_ace_type r) +{ + NDR_CHECK(ndr_push_enum_uint8(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_ace_type(struct ndr_pull *ndr, int ndr_flags, enum security_ace_type *r) +{ + uint8_t v; + NDR_CHECK(ndr_pull_enum_uint8(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_security_ace_type(struct ndr_print *ndr, const char *name, enum security_ace_type r) +{ + const char *val = NULL; + + switch (r) { + case SEC_ACE_TYPE_ACCESS_ALLOWED: val = "SEC_ACE_TYPE_ACCESS_ALLOWED"; break; + case SEC_ACE_TYPE_ACCESS_DENIED: val = "SEC_ACE_TYPE_ACCESS_DENIED"; break; + case SEC_ACE_TYPE_SYSTEM_AUDIT: val = "SEC_ACE_TYPE_SYSTEM_AUDIT"; break; + case SEC_ACE_TYPE_SYSTEM_ALARM: val = "SEC_ACE_TYPE_SYSTEM_ALARM"; break; + case SEC_ACE_TYPE_ALLOWED_COMPOUND: val = "SEC_ACE_TYPE_ALLOWED_COMPOUND"; break; + case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: val = "SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT"; break; + case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: val = "SEC_ACE_TYPE_ACCESS_DENIED_OBJECT"; break; + case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: val = "SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT"; break; + case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: val = "SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT"; break; + } + ndr_print_enum(ndr, name, "ENUM", val, r); +} + +static enum ndr_err_code ndr_push_security_ace_object_flags(struct ndr_push *ndr, int ndr_flags, uint32_t r) +{ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +static enum ndr_err_code ndr_pull_security_ace_object_flags(struct ndr_pull *ndr, int ndr_flags, uint32_t *r) +{ + uint32_t v; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_security_ace_object_flags(struct ndr_print *ndr, const char *name, uint32_t r) +{ + ndr_print_uint32(ndr, name, r); + ndr->depth++; + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SEC_ACE_OBJECT_TYPE_PRESENT", SEC_ACE_OBJECT_TYPE_PRESENT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT", SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT, r); + ndr->depth--; +} + +static enum ndr_err_code ndr_push_security_ace_object_type(struct ndr_push *ndr, int ndr_flags, const union security_ace_object_type *r) { uint32_t level; - NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); if (ndr_flags & NDR_SCALARS) { /* This token is not used again (except perhaps below in the NDR_BUFFERS case) */ -#ifdef SMB_HAS_NEW_NDR_PULL_STEAL_SWITCH - NDR_CHECK(ndr_pull_steal_switch_value(ndr, r, &level)); -#else - level = ndr_pull_steal_switch_value(ndr, r); -#endif - NDR_CHECK(ndr_pull_union_align(ndr, 4)); + NDR_CHECK(ndr_push_steal_switch_value(ndr, r, &level)); + NDR_CHECK(ndr_push_union_align(ndr, 4)); switch (level) { - case SEC_ACE_OBJECT_TYPE_PRESENT: { - NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->type)); + case SEC_ACE_OBJECT_TYPE_PRESENT: { + NDR_CHECK(ndr_push_GUID(ndr, NDR_SCALARS, &r->type)); break; } - default: { + + default: { break; } + } } return NDR_ERR_SUCCESS; } - -static enum ndr_err_code -ndr_pull_security_ace_object_inherited_type(struct ndr_pull *ndr, - int ndr_flags, - union security_ace_object_inherited_type *r) +static enum ndr_err_code ndr_pull_security_ace_object_type(struct ndr_pull *ndr, int ndr_flags, union security_ace_object_type *r) { uint32_t level; NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); if (ndr_flags & NDR_SCALARS) { /* This token is not used again (except perhaps below in the NDR_BUFFERS case) */ -#ifdef SMB_HAS_NEW_NDR_PULL_STEAL_SWITCH NDR_CHECK(ndr_pull_steal_switch_value(ndr, r, &level)); -#else - level = ndr_pull_steal_switch_value(ndr, r); -#endif NDR_CHECK(ndr_pull_union_align(ndr, 4)); switch (level) { - case SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT: { - NDR_CHECK(ndr_pull_GUID(ndr, - NDR_SCALARS, - &r->inherited_type)); + case SEC_ACE_OBJECT_TYPE_PRESENT: { + NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->type)); break; } - default: { + + default: { break; } + } } return NDR_ERR_SUCCESS; } -static enum ndr_err_code -ndr_pull_security_ace_object(struct ndr_pull *ndr, - int ndr_flags, - struct security_ace_object *r) +_PUBLIC_ void ndr_print_security_ace_object_type(struct ndr_print *ndr, const char *name, const union security_ace_object_type *r) +{ + uint32_t level; + level = ndr_print_steal_switch_value(ndr, r); + ndr_print_union(ndr, name, level, "security_ace_object_type"); + switch (level) { + case SEC_ACE_OBJECT_TYPE_PRESENT: + ndr_print_GUID(ndr, "type", &r->type); + break; + + default: + break; + + } +} + +static enum ndr_err_code ndr_push_security_ace_object_inherited_type(struct ndr_push *ndr, int ndr_flags, const union security_ace_object_inherited_type *r) +{ + uint32_t level; + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + /* This token is not used again (except perhaps below in the NDR_BUFFERS case) */ + NDR_CHECK(ndr_push_steal_switch_value(ndr, r, &level)); + NDR_CHECK(ndr_push_union_align(ndr, 4)); + switch (level) { + case SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT: { + NDR_CHECK(ndr_push_GUID(ndr, NDR_SCALARS, &r->inherited_type)); + break; } + + default: { + break; } + + } + } + return NDR_ERR_SUCCESS; +} + +static enum ndr_err_code ndr_pull_security_ace_object_inherited_type(struct ndr_pull *ndr, int ndr_flags, union security_ace_object_inherited_type *r) +{ + uint32_t level; + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + /* This token is not used again (except perhaps below in the NDR_BUFFERS case) */ + NDR_CHECK(ndr_pull_steal_switch_value(ndr, r, &level)); + NDR_CHECK(ndr_pull_union_align(ndr, 4)); + switch (level) { + case SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT: { + NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->inherited_type)); + break; } + + default: { + break; } + + } + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_security_ace_object_inherited_type(struct ndr_print *ndr, const char *name, const union security_ace_object_inherited_type *r) +{ + uint32_t level; + level = ndr_print_steal_switch_value(ndr, r); + ndr_print_union(ndr, name, level, "security_ace_object_inherited_type"); + switch (level) { + case SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT: + ndr_print_GUID(ndr, "inherited_type", &r->inherited_type); + break; + + default: + break; + + } +} + +static enum ndr_err_code ndr_push_security_ace_object(struct ndr_push *ndr, int ndr_flags, const struct security_ace_object *r) +{ + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_security_ace_object_flags(ndr, NDR_SCALARS, r->flags)); + NDR_CHECK(ndr_push_set_switch_value(ndr, &r->type, r->flags & SEC_ACE_OBJECT_TYPE_PRESENT)); + NDR_CHECK(ndr_push_security_ace_object_type(ndr, NDR_SCALARS, &r->type)); + NDR_CHECK(ndr_push_set_switch_value(ndr, &r->inherited_type, r->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)); + NDR_CHECK(ndr_push_security_ace_object_inherited_type(ndr, NDR_SCALARS, &r->inherited_type)); + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + NDR_CHECK(ndr_push_set_switch_value(ndr, &r->type, r->flags & SEC_ACE_OBJECT_TYPE_PRESENT)); + NDR_CHECK(ndr_push_security_ace_object_type(ndr, NDR_BUFFERS, &r->type)); + NDR_CHECK(ndr_push_set_switch_value(ndr, &r->inherited_type, r->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)); + NDR_CHECK(ndr_push_security_ace_object_inherited_type(ndr, NDR_BUFFERS, &r->inherited_type)); + } + return NDR_ERR_SUCCESS; +} + +static enum ndr_err_code ndr_pull_security_ace_object(struct ndr_pull *ndr, int ndr_flags, struct security_ace_object *r) { NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_pull_align(ndr, 4)); - NDR_CHECK(ndr_pull_security_ace_object_flags - (ndr, NDR_SCALARS, &r->flags)); - NDR_CHECK(ndr_pull_set_switch_value - (ndr, &r->type, r->flags & SEC_ACE_OBJECT_TYPE_PRESENT)); - NDR_CHECK(ndr_pull_security_ace_object_type - (ndr, NDR_SCALARS, &r->type)); - NDR_CHECK(ndr_pull_set_switch_value - (ndr, - &r->inherited_type, - r->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)); - NDR_CHECK(ndr_pull_security_ace_object_inherited_type - (ndr, NDR_SCALARS, &r->inherited_type)); + NDR_CHECK(ndr_pull_security_ace_object_flags(ndr, NDR_SCALARS, &r->flags)); + NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->type, r->flags & SEC_ACE_OBJECT_TYPE_PRESENT)); + NDR_CHECK(ndr_pull_security_ace_object_type(ndr, NDR_SCALARS, &r->type)); + NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->inherited_type, r->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)); + NDR_CHECK(ndr_pull_security_ace_object_inherited_type(ndr, NDR_SCALARS, &r->inherited_type)); NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); } if (ndr_flags & NDR_BUFFERS) { - NDR_CHECK(ndr_pull_set_switch_value - (ndr, - &r->type, - r->flags & SEC_ACE_OBJECT_TYPE_PRESENT)); - NDR_CHECK(ndr_pull_security_ace_object_type - (ndr, NDR_BUFFERS, &r->type)); - NDR_CHECK(ndr_pull_set_switch_value - (ndr, - &r->inherited_type, - r->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)); - NDR_CHECK(ndr_pull_security_ace_object_inherited_type - (ndr, NDR_BUFFERS, &r->inherited_type)); + NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->type, r->flags & SEC_ACE_OBJECT_TYPE_PRESENT)); + NDR_CHECK(ndr_pull_security_ace_object_type(ndr, NDR_BUFFERS, &r->type)); + NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->inherited_type, r->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)); + NDR_CHECK(ndr_pull_security_ace_object_inherited_type(ndr, NDR_BUFFERS, &r->inherited_type)); } return NDR_ERR_SUCCESS; } +_PUBLIC_ void ndr_print_security_ace_object(struct ndr_print *ndr, const char *name, const struct security_ace_object *r) +{ + ndr_print_struct(ndr, name, "security_ace_object"); + if (r == NULL) { ndr_print_null(ndr); return; } + ndr->depth++; + ndr_print_security_ace_object_flags(ndr, "flags", r->flags); + ndr_print_set_switch_value(ndr, &r->type, r->flags & SEC_ACE_OBJECT_TYPE_PRESENT); + ndr_print_security_ace_object_type(ndr, "type", &r->type); + ndr_print_set_switch_value(ndr, &r->inherited_type, r->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT); + ndr_print_security_ace_object_inherited_type(ndr, "inherited_type", &r->inherited_type); + ndr->depth--; +} -static enum ndr_err_code -ndr_pull_security_ace_object_ctr(struct ndr_pull *ndr, - int ndr_flags, - union security_ace_object_ctr *r) +_PUBLIC_ enum ndr_err_code ndr_push_security_ace_object_ctr(struct ndr_push *ndr, int ndr_flags, const union security_ace_object_ctr *r) { uint32_t level; - NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); if (ndr_flags & NDR_SCALARS) { /* This token is not used again (except perhaps below in the NDR_BUFFERS case) */ -#ifdef SMB_HAS_NEW_NDR_PULL_STEAL_SWITCH - NDR_CHECK(ndr_pull_steal_switch_value(ndr, r, &level)); -#else - level = ndr_pull_steal_switch_value(ndr, r); -#endif - NDR_CHECK(ndr_pull_union_align(ndr, 4)); + NDR_CHECK(ndr_push_steal_switch_value(ndr, r, &level)); + NDR_CHECK(ndr_push_union_align(ndr, 4)); switch (level) { - case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: { - NDR_CHECK(ndr_pull_security_ace_object - (ndr, NDR_SCALARS, &r->object)); + case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: { + NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_SCALARS, &r->object)); break; } - case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: { - NDR_CHECK(ndr_pull_security_ace_object - (ndr, NDR_SCALARS, &r->object)); + + case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: { + NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_SCALARS, &r->object)); break; } - case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: { - NDR_CHECK(ndr_pull_security_ace_object - (ndr, NDR_SCALARS, &r->object)); + + case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: { + NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_SCALARS, &r->object)); break; } - case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: { - NDR_CHECK(ndr_pull_security_ace_object - (ndr, NDR_SCALARS, &r->object)); + + case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: { + NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_SCALARS, &r->object)); break; } - default: { + + default: { break; } + } } if (ndr_flags & NDR_BUFFERS) { if (!(ndr_flags & NDR_SCALARS)) { /* We didn't get it above, and the token is not needed after this. */ -#ifdef SMB_HAS_NEW_NDR_PULL_STEAL_SWITCH - NDR_CHECK(ndr_pull_steal_switch_value(ndr, r, &level)); -#else - level = ndr_pull_steal_switch_value(ndr, r); -#endif + NDR_CHECK(ndr_push_steal_switch_value(ndr, r, &level)); } switch (level) { - case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: - NDR_CHECK(ndr_pull_security_ace_object - (ndr, NDR_BUFFERS, &r->object)); + case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: + NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_BUFFERS, &r->object)); break; - case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: - NDR_CHECK(ndr_pull_security_ace_object - (ndr, NDR_BUFFERS, &r->object)); + + case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: + NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_BUFFERS, &r->object)); break; - case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: - NDR_CHECK(ndr_pull_security_ace_object - (ndr, NDR_BUFFERS, &r->object)); + + case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: + NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_BUFFERS, &r->object)); break; - case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: - NDR_CHECK(ndr_pull_security_ace_object - (ndr, NDR_BUFFERS, &r->object)); + + case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: + NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_BUFFERS, &r->object)); break; - default: + + default: break; + } } return NDR_ERR_SUCCESS; } -enum ndr_err_code -ndr_pull_dom_sid(struct ndr_pull *ndr, - int ndr_flags, - struct dom_sid *r) +_PUBLIC_ enum ndr_err_code ndr_pull_security_ace_object_ctr(struct ndr_pull *ndr, int ndr_flags, union security_ace_object_ctr *r) { - uint32_t cntr_sub_auths_0; + uint32_t level; + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); if (ndr_flags & NDR_SCALARS) { - NDR_CHECK(ndr_pull_align(ndr, 4)); - NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num)); - NDR_CHECK(ndr_pull_int8(ndr, NDR_SCALARS, &r->num_auths)); - if (r->num_auths < 0 || r->num_auths > N_ELEMENTS(r->sub_auths)) { - return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range"); - } - NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6)); - memset(&r->sub_auths, 0, sizeof(r->sub_auths)); - for (cntr_sub_auths_0 = 0; - cntr_sub_auths_0 < r->num_auths; - cntr_sub_auths_0++) { - NDR_CHECK(ndr_pull_uint32 - (ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0])); - } - } - return NDR_ERR_SUCCESS; -} + /* This token is not used again (except perhaps below in the NDR_BUFFERS case) */ + NDR_CHECK(ndr_pull_steal_switch_value(ndr, r, &level)); + NDR_CHECK(ndr_pull_union_align(ndr, 4)); + switch (level) { + case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: { + NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_SCALARS, &r->object)); + break; } + + case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: { + NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_SCALARS, &r->object)); + break; } + + case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: { + NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_SCALARS, &r->object)); + break; } + + case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: { + NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_SCALARS, &r->object)); + break; } + + default: { + break; } -static enum ndr_err_code -ndr_pull_security_ace(struct ndr_pull *ndr, - int ndr_flags, - struct security_ace *r) -{ - if (ndr_flags & NDR_SCALARS) { - uint32_t start_ofs = ndr->offset; - uint32_t size = 0; - uint32_t pad = 0; - NDR_CHECK(ndr_pull_align(ndr, 4)); - NDR_CHECK(ndr_pull_security_ace_type(ndr, NDR_SCALARS, &r->type)); - NDR_CHECK(ndr_pull_security_ace_flags(ndr, NDR_SCALARS, &r->flags)); - NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->size)); - NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->access_mask)); - NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->object, r->type)); - NDR_CHECK(ndr_pull_security_ace_object_ctr - (ndr, NDR_SCALARS, &r->object)); - NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, &r->trustee)); - size = ndr->offset - start_ofs; - if (r->size < size) { - return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, - "ndr_pull_security_ace: r->size %u < size %u", - (unsigned)r->size, size); } - pad = r->size - size; - NDR_PULL_NEED_BYTES(ndr, pad); - ndr->offset += pad; } if (ndr_flags & NDR_BUFFERS) { - NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->object, r->type)); - NDR_CHECK(ndr_pull_security_ace_object_ctr - (ndr, NDR_BUFFERS, &r->object)); + if (!(ndr_flags & NDR_SCALARS)) { + /* We didn't get it above, and the token is not needed after this. */ + NDR_CHECK(ndr_pull_steal_switch_value(ndr, r, &level)); + } + switch (level) { + case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: + NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_BUFFERS, &r->object)); + break; + + case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: + NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_BUFFERS, &r->object)); + break; + + case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: + NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_BUFFERS, &r->object)); + break; + + case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: + NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_BUFFERS, &r->object)); + break; + + default: + break; + + } } return NDR_ERR_SUCCESS; } -static enum ndr_err_code -ndr_pull_security_acl_revision(struct ndr_pull *ndr, - int ndr_flags, - enum security_acl_revision *r) +_PUBLIC_ void ndr_print_security_ace_object_ctr(struct ndr_print *ndr, const char *name, const union security_ace_object_ctr *r) +{ + uint32_t level; + level = ndr_print_steal_switch_value(ndr, r); + ndr_print_union(ndr, name, level, "security_ace_object_ctr"); + switch (level) { + case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: + ndr_print_security_ace_object(ndr, "object", &r->object); + break; + + case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: + ndr_print_security_ace_object(ndr, "object", &r->object); + break; + + case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: + ndr_print_security_ace_object(ndr, "object", &r->object); + break; + + case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: + ndr_print_security_ace_object(ndr, "object", &r->object); + break; + + default: + break; + + } +} + +_PUBLIC_ enum ndr_err_code ndr_push_security_ace(struct ndr_push *ndr, int ndr_flags, const struct security_ace *r) +{ + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_security_ace_type(ndr, NDR_SCALARS, r->type)); + NDR_CHECK(ndr_push_security_ace_flags(ndr, NDR_SCALARS, r->flags)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, ndr_size_security_ace(r, ndr->flags))); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->access_mask)); + NDR_CHECK(ndr_push_set_switch_value(ndr, &r->object, r->type)); + NDR_CHECK(ndr_push_security_ace_object_ctr(ndr, NDR_SCALARS, &r->object)); + NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, &r->trustee)); + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + NDR_CHECK(ndr_push_set_switch_value(ndr, &r->object, r->type)); + NDR_CHECK(ndr_push_security_ace_object_ctr(ndr, NDR_BUFFERS, &r->object)); + } + return NDR_ERR_SUCCESS; +} + +static void ndr_print_flags_security_ace(struct ndr_print *ndr, const char *name, int unused, const struct security_ace *r) +{ + ndr_print_security_ace(ndr, name, r); +} + +_PUBLIC_ void ndr_print_security_ace(struct ndr_print *ndr, const char *name, const struct security_ace *r) +{ + ndr_print_struct(ndr, name, "security_ace"); + if (r == NULL) { ndr_print_null(ndr); return; } + ndr->depth++; + ndr_print_security_ace_type(ndr, "type", r->type); + ndr_print_security_ace_flags(ndr, "flags", r->flags); + ndr_print_uint16(ndr, "size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?ndr_size_security_ace(r, ndr->flags):r->size); + ndr_print_uint32(ndr, "access_mask", r->access_mask); + ndr_print_set_switch_value(ndr, &r->object, r->type); + ndr_print_security_ace_object_ctr(ndr, "object", &r->object); + ndr_print_dom_sid(ndr, "trustee", &r->trustee); + ndr->depth--; +} + +static enum ndr_err_code ndr_push_security_acl_revision(struct ndr_push *ndr, int ndr_flags, enum security_acl_revision r) +{ + NDR_CHECK(ndr_push_enum_uint1632(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +static enum ndr_err_code ndr_pull_security_acl_revision(struct ndr_pull *ndr, int ndr_flags, enum security_acl_revision *r) { uint16_t v; - NDR_CHECK(ndr_pull_enum_uint1632(ndr, ndr_flags, &v)); + NDR_CHECK(ndr_pull_enum_uint1632(ndr, NDR_SCALARS, &v)); *r = v; return NDR_ERR_SUCCESS; } +_PUBLIC_ void ndr_print_security_acl_revision(struct ndr_print *ndr, const char *name, enum security_acl_revision r) +{ + const char *val = NULL; -static enum ndr_err_code -ndr_pull_security_acl(struct ndr_pull *ndr, - int ndr_flags, - struct security_acl *r) + switch (r) { + case SECURITY_ACL_REVISION_NT4: val = "SECURITY_ACL_REVISION_NT4"; break; + case SECURITY_ACL_REVISION_ADS: val = "SECURITY_ACL_REVISION_ADS"; break; + } + ndr_print_enum(ndr, name, "ENUM", val, r); +} + +_PUBLIC_ enum ndr_err_code ndr_push_security_acl(struct ndr_push *ndr, int ndr_flags, const struct security_acl *r) +{ + uint32_t cntr_aces_0; + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_security_acl_revision(ndr, NDR_SCALARS, r->revision)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, ndr_size_security_acl(r, ndr->flags))); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->num_aces)); + for (cntr_aces_0 = 0; cntr_aces_0 < (r->num_aces); cntr_aces_0++) { + NDR_CHECK(ndr_push_security_ace(ndr, NDR_SCALARS, &r->aces[cntr_aces_0])); + } + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + for (cntr_aces_0 = 0; cntr_aces_0 < (r->num_aces); cntr_aces_0++) { + NDR_CHECK(ndr_push_security_ace(ndr, NDR_BUFFERS, &r->aces[cntr_aces_0])); + } + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_acl(struct ndr_pull *ndr, int ndr_flags, struct security_acl *r) { uint32_t size_aces_0 = 0; uint32_t cntr_aces_0; - TALLOC_CTX *_mem_save_aces_0; + TALLOC_CTX *_mem_save_aces_0 = NULL; NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_pull_align(ndr, 4)); - NDR_CHECK(ndr_pull_security_acl_revision - (ndr, NDR_SCALARS, &r->revision)); + NDR_CHECK(ndr_pull_security_acl_revision(ndr, NDR_SCALARS, &r->revision)); NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->size)); NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->num_aces)); if (r->num_aces > 2000) { @@ -353,9 +619,8 @@ ndr_pull_security_acl(struct ndr_pull *ndr, NDR_PULL_ALLOC_N(ndr, r->aces, size_aces_0); _mem_save_aces_0 = NDR_PULL_GET_MEM_CTX(ndr); NDR_PULL_SET_MEM_CTX(ndr, r->aces, 0); - for (cntr_aces_0 = 0; cntr_aces_0 < size_aces_0; cntr_aces_0++) { - NDR_CHECK(ndr_pull_security_ace - (ndr, NDR_SCALARS, &r->aces[cntr_aces_0])); + for (cntr_aces_0 = 0; cntr_aces_0 < (size_aces_0); cntr_aces_0++) { + NDR_CHECK(ndr_pull_security_ace(ndr, NDR_SCALARS, &r->aces[cntr_aces_0])); } NDR_PULL_SET_MEM_CTX(ndr, _mem_save_aces_0, 0); NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); @@ -364,81 +629,172 @@ ndr_pull_security_acl(struct ndr_pull *ndr, size_aces_0 = r->num_aces; _mem_save_aces_0 = NDR_PULL_GET_MEM_CTX(ndr); NDR_PULL_SET_MEM_CTX(ndr, r->aces, 0); - for (cntr_aces_0 = 0; cntr_aces_0 < size_aces_0; cntr_aces_0++) { - NDR_CHECK(ndr_pull_security_ace - (ndr, NDR_BUFFERS, &r->aces[cntr_aces_0])); + for (cntr_aces_0 = 0; cntr_aces_0 < (size_aces_0); cntr_aces_0++) { + NDR_CHECK(ndr_pull_security_ace(ndr, NDR_BUFFERS, &r->aces[cntr_aces_0])); } NDR_PULL_SET_MEM_CTX(ndr, _mem_save_aces_0, 0); + for (cntr_aces_0 = 0; cntr_aces_0 < (size_aces_0); cntr_aces_0++) { + } } return NDR_ERR_SUCCESS; } +static void ndr_print_flags_security_acl(struct ndr_print *ndr, const char *name, int unused, const struct security_acl *r) +{ + ndr_print_security_acl(ndr, name, r); +} -static enum ndr_err_code -ndr_pull_security_descriptor_revision(struct ndr_pull *ndr, - int ndr_flags, - enum security_descriptor_revision *r) +_PUBLIC_ void ndr_print_security_acl(struct ndr_print *ndr, const char *name, const struct security_acl *r) +{ + uint32_t cntr_aces_0; + ndr_print_struct(ndr, name, "security_acl"); + if (r == NULL) { ndr_print_null(ndr); return; } + ndr->depth++; + ndr_print_security_acl_revision(ndr, "revision", r->revision); + ndr_print_uint16(ndr, "size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?ndr_size_security_acl(r, ndr->flags):r->size); + ndr_print_uint32(ndr, "num_aces", r->num_aces); + ndr->print(ndr, "%s: ARRAY(%d)", "aces", (int)r->num_aces); + ndr->depth++; + for (cntr_aces_0 = 0; cntr_aces_0 < (r->num_aces); cntr_aces_0++) { + ndr_print_security_ace(ndr, "aces", &r->aces[cntr_aces_0]); + } + ndr->depth--; + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_security_descriptor_revision(struct ndr_push *ndr, int ndr_flags, enum security_descriptor_revision r) +{ + NDR_CHECK(ndr_push_enum_uint8(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_descriptor_revision(struct ndr_pull *ndr, int ndr_flags, enum security_descriptor_revision *r) { uint8_t v; - NDR_CHECK(ndr_pull_enum_uint8(ndr, ndr_flags, &v)); + NDR_CHECK(ndr_pull_enum_uint8(ndr, NDR_SCALARS, &v)); *r = v; return NDR_ERR_SUCCESS; } +_PUBLIC_ void ndr_print_security_descriptor_revision(struct ndr_print *ndr, const char *name, enum security_descriptor_revision r) +{ + const char *val = NULL; + switch (r) { + case SECURITY_DESCRIPTOR_REVISION_1: val = "SECURITY_DESCRIPTOR_REVISION_1"; break; + } + ndr_print_enum(ndr, name, "ENUM", val, r); +} -static enum ndr_err_code -ndr_pull_security_descriptor_type(struct ndr_pull *ndr, - int ndr_flags, - uint16_t *r) +_PUBLIC_ enum ndr_err_code ndr_push_security_descriptor_type(struct ndr_push *ndr, int ndr_flags, uint16_t r) +{ + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_descriptor_type(struct ndr_pull *ndr, int ndr_flags, uint16_t *r) { uint16_t v; - NDR_CHECK(ndr_pull_uint16(ndr, ndr_flags, &v)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &v)); *r = v; return NDR_ERR_SUCCESS; } +_PUBLIC_ void ndr_print_security_descriptor_type(struct ndr_print *ndr, const char *name, uint16_t r) +{ + ndr_print_uint16(ndr, name, r); + ndr->depth++; + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_OWNER_DEFAULTED", SEC_DESC_OWNER_DEFAULTED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_GROUP_DEFAULTED", SEC_DESC_GROUP_DEFAULTED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_PRESENT", SEC_DESC_DACL_PRESENT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_DEFAULTED", SEC_DESC_DACL_DEFAULTED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SACL_PRESENT", SEC_DESC_SACL_PRESENT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SACL_DEFAULTED", SEC_DESC_SACL_DEFAULTED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_TRUSTED", SEC_DESC_DACL_TRUSTED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SERVER_SECURITY", SEC_DESC_SERVER_SECURITY, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_AUTO_INHERIT_REQ", SEC_DESC_DACL_AUTO_INHERIT_REQ, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SACL_AUTO_INHERIT_REQ", SEC_DESC_SACL_AUTO_INHERIT_REQ, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_AUTO_INHERITED", SEC_DESC_DACL_AUTO_INHERITED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SACL_AUTO_INHERITED", SEC_DESC_SACL_AUTO_INHERITED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_PROTECTED", SEC_DESC_DACL_PROTECTED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SACL_PROTECTED", SEC_DESC_SACL_PROTECTED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_RM_CONTROL_VALID", SEC_DESC_RM_CONTROL_VALID, r); + ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SELF_RELATIVE", SEC_DESC_SELF_RELATIVE, r); + ndr->depth--; +} -enum ndr_err_code -ndr_security_pull_security_descriptor(struct ndr_pull *ndr, - int ndr_flags, - struct security_descriptor *r) +_PUBLIC_ enum ndr_err_code ndr_push_security_descriptor(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor *r) +{ + { + uint32_t _flags_save_STRUCT = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 5)); + NDR_CHECK(ndr_push_security_descriptor_revision(ndr, NDR_SCALARS, r->revision)); + NDR_CHECK(ndr_push_security_descriptor_type(ndr, NDR_SCALARS, r->type)); + NDR_CHECK(ndr_push_relative_ptr1(ndr, r->owner_sid)); + NDR_CHECK(ndr_push_relative_ptr1(ndr, r->group_sid)); + NDR_CHECK(ndr_push_relative_ptr1(ndr, r->sacl)); + NDR_CHECK(ndr_push_relative_ptr1(ndr, r->dacl)); + NDR_CHECK(ndr_push_trailer_align(ndr, 5)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->owner_sid) { + NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->owner_sid)); + NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, r->owner_sid)); + NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->owner_sid)); + } + if (r->group_sid) { + NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->group_sid)); + NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, r->group_sid)); + NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->group_sid)); + } + if (r->sacl) { + NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->sacl)); + NDR_CHECK(ndr_push_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->sacl)); + NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->sacl)); + } + if (r->dacl) { + NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->dacl)); + NDR_CHECK(ndr_push_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->dacl)); + NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->dacl)); + } + } + ndr->flags = _flags_save_STRUCT; + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_descriptor(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor *r) { uint32_t _ptr_owner_sid; - TALLOC_CTX *_mem_save_owner_sid_0; + TALLOC_CTX *_mem_save_owner_sid_0 = NULL; uint32_t _ptr_group_sid; - TALLOC_CTX *_mem_save_group_sid_0; + TALLOC_CTX *_mem_save_group_sid_0 = NULL; uint32_t _ptr_sacl; - TALLOC_CTX *_mem_save_sacl_0; + TALLOC_CTX *_mem_save_sacl_0 = NULL; uint32_t _ptr_dacl; - TALLOC_CTX *_mem_save_dacl_0; + TALLOC_CTX *_mem_save_dacl_0 = NULL; { uint32_t _flags_save_STRUCT = ndr->flags; ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_pull_align(ndr, 5)); - NDR_CHECK(ndr_pull_security_descriptor_revision(ndr, - NDR_SCALARS, - &r->revision)); - NDR_CHECK(ndr_pull_security_descriptor_type(ndr, - NDR_SCALARS, - &r->type)); + NDR_CHECK(ndr_pull_security_descriptor_revision(ndr, NDR_SCALARS, &r->revision)); + NDR_CHECK(ndr_pull_security_descriptor_type(ndr, NDR_SCALARS, &r->type)); NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_owner_sid)); if (_ptr_owner_sid) { NDR_PULL_ALLOC(ndr, r->owner_sid); - NDR_CHECK(ndr_pull_relative_ptr1(ndr, - r->owner_sid, - _ptr_owner_sid)); + NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->owner_sid, _ptr_owner_sid)); } else { r->owner_sid = NULL; } NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_group_sid)); if (_ptr_group_sid) { NDR_PULL_ALLOC(ndr, r->group_sid); - NDR_CHECK(ndr_pull_relative_ptr1(ndr, - r->group_sid, - _ptr_group_sid)); + NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->group_sid, _ptr_group_sid)); } else { r->group_sid = NULL; } @@ -491,9 +847,7 @@ ndr_security_pull_security_descriptor(struct ndr_pull *ndr, NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->sacl)); _mem_save_sacl_0 = NDR_PULL_GET_MEM_CTX(ndr); NDR_PULL_SET_MEM_CTX(ndr, r->sacl, 0); - NDR_CHECK(ndr_pull_security_acl(ndr, - NDR_SCALARS|NDR_BUFFERS, - r->sacl)); + NDR_CHECK(ndr_pull_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->sacl)); NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sacl_0, 0); if (ndr->offset > ndr->relative_highest_offset) { ndr->relative_highest_offset = ndr->offset; @@ -506,9 +860,7 @@ ndr_security_pull_security_descriptor(struct ndr_pull *ndr, NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->dacl)); _mem_save_dacl_0 = NDR_PULL_GET_MEM_CTX(ndr); NDR_PULL_SET_MEM_CTX(ndr, r->dacl, 0); - NDR_CHECK(ndr_pull_security_acl(ndr, - NDR_SCALARS|NDR_BUFFERS, - r->dacl)); + NDR_CHECK(ndr_pull_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->dacl)); NDR_PULL_SET_MEM_CTX(ndr, _mem_save_dacl_0, 0); if (ndr->offset > ndr->relative_highest_offset) { ndr->relative_highest_offset = ndr->offset; @@ -520,3 +872,559 @@ ndr_security_pull_security_descriptor(struct ndr_pull *ndr, } return NDR_ERR_SUCCESS; } + +static void ndr_print_flags_security_descriptor(struct ndr_print *ndr, const char *name, int unused, const struct security_descriptor *r) +{ + ndr_print_security_descriptor(ndr, name, r); +} + +_PUBLIC_ void ndr_print_security_descriptor(struct ndr_print *ndr, const char *name, const struct security_descriptor *r) +{ + ndr_print_struct(ndr, name, "security_descriptor"); + if (r == NULL) { ndr_print_null(ndr); return; } + { + uint32_t _flags_save_STRUCT = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); + ndr->depth++; + ndr_print_security_descriptor_revision(ndr, "revision", r->revision); + ndr_print_security_descriptor_type(ndr, "type", r->type); + ndr_print_ptr(ndr, "owner_sid", r->owner_sid); + ndr->depth++; + if (r->owner_sid) { + ndr_print_dom_sid(ndr, "owner_sid", r->owner_sid); + } + ndr->depth--; + ndr_print_ptr(ndr, "group_sid", r->group_sid); + ndr->depth++; + if (r->group_sid) { + ndr_print_dom_sid(ndr, "group_sid", r->group_sid); + } + ndr->depth--; + ndr_print_ptr(ndr, "sacl", r->sacl); + ndr->depth++; + if (r->sacl) { + ndr_print_security_acl(ndr, "sacl", r->sacl); + } + ndr->depth--; + ndr_print_ptr(ndr, "dacl", r->dacl); + ndr->depth++; + if (r->dacl) { + ndr_print_security_acl(ndr, "dacl", r->dacl); + } + ndr->depth--; + ndr->depth--; + ndr->flags = _flags_save_STRUCT; + } +} + +_PUBLIC_ enum ndr_err_code ndr_push_sec_desc_buf(struct ndr_push *ndr, int ndr_flags, const struct sec_desc_buf *r) +{ + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 5)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_size_security_descriptor(r->sd, ndr->flags))); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->sd)); + NDR_CHECK(ndr_push_trailer_align(ndr, 5)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->sd) { + { + struct ndr_push *_ndr_sd; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_sd, 4, -1)); + NDR_CHECK(ndr_push_security_descriptor(_ndr_sd, NDR_SCALARS|NDR_BUFFERS, r->sd)); + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_sd, 4, -1)); + } + } + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_sec_desc_buf(struct ndr_pull *ndr, int ndr_flags, struct sec_desc_buf *r) +{ + uint32_t _ptr_sd; + TALLOC_CTX *_mem_save_sd_0 = NULL; + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 5)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sd_size)); + if (r->sd_size > 262144) { + return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range"); + } + NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_sd)); + if (_ptr_sd) { + NDR_PULL_ALLOC(ndr, r->sd); + } else { + r->sd = NULL; + } + NDR_CHECK(ndr_pull_trailer_align(ndr, 5)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->sd) { + _mem_save_sd_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->sd, 0); + { + struct ndr_pull *_ndr_sd; + NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_sd, 4, -1)); + NDR_CHECK(ndr_pull_security_descriptor(_ndr_sd, NDR_SCALARS|NDR_BUFFERS, r->sd)); + NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_sd, 4, -1)); + } + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sd_0, 0); + } + } + return NDR_ERR_SUCCESS; +} + +static void ndr_print_flags_sec_desc_buf(struct ndr_print *ndr, const char *name, int unused, const struct sec_desc_buf *r) +{ + ndr_print_sec_desc_buf(ndr, name, r); +} + +_PUBLIC_ void ndr_print_sec_desc_buf(struct ndr_print *ndr, const char *name, const struct sec_desc_buf *r) +{ + ndr_print_struct(ndr, name, "sec_desc_buf"); + if (r == NULL) { ndr_print_null(ndr); return; } + ndr->depth++; + ndr_print_uint32(ndr, "sd_size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?ndr_size_security_descriptor(r->sd, ndr->flags):r->sd_size); + ndr_print_ptr(ndr, "sd", r->sd); + ndr->depth++; + if (r->sd) { + ndr_print_security_descriptor(ndr, "sd", r->sd); + } + ndr->depth--; + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_security_GroupAttrs(struct ndr_push *ndr, int ndr_flags, uint32_t r) +{ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_GroupAttrs(struct ndr_pull *ndr, int ndr_flags, uint32_t *r) +{ + uint32_t v; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_security_GroupAttrs(struct ndr_print *ndr, const char *name, uint32_t r) +{ + ndr_print_uint32(ndr, name, r); + ndr->depth++; + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SE_GROUP_MANDATORY", SE_GROUP_MANDATORY, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SE_GROUP_ENABLED_BY_DEFAULT", SE_GROUP_ENABLED_BY_DEFAULT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SE_GROUP_ENABLED", SE_GROUP_ENABLED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SE_GROUP_OWNER", SE_GROUP_OWNER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SE_GROUP_USE_FOR_DENY_ONLY", SE_GROUP_USE_FOR_DENY_ONLY, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SE_GROUP_INTEGRITY", SE_GROUP_INTEGRITY, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SE_GROUP_INTEGRITY_ENABLED", SE_GROUP_INTEGRITY_ENABLED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SE_GROUP_RESOURCE", SE_GROUP_RESOURCE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SE_GROUP_LOGON_ID", SE_GROUP_LOGON_ID, r); + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_security_token(struct ndr_push *ndr, int ndr_flags, const struct security_token *r) +{ + uint32_t cntr_sids_0; + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 8)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->num_sids)); + NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, r->num_sids)); + for (cntr_sids_0 = 0; cntr_sids_0 < (r->num_sids); cntr_sids_0++) { + NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, &r->sids[cntr_sids_0])); + } + NDR_CHECK(ndr_push_se_privilege(ndr, NDR_SCALARS, r->privilege_mask)); + NDR_CHECK(ndr_push_lsa_SystemAccessModeFlags(ndr, NDR_SCALARS, r->rights_mask)); + NDR_CHECK(ndr_push_trailer_align(ndr, 8)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_token(struct ndr_pull *ndr, int ndr_flags, struct security_token *r) +{ + uint32_t size_sids_0 = 0; + uint32_t cntr_sids_0; + TALLOC_CTX *_mem_save_sids_0 = NULL; + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 8)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->num_sids)); + NDR_CHECK(ndr_pull_array_size(ndr, &r->sids)); + size_sids_0 = ndr_get_array_size(ndr, &r->sids); + NDR_PULL_ALLOC_N(ndr, r->sids, size_sids_0); + _mem_save_sids_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->sids, 0); + for (cntr_sids_0 = 0; cntr_sids_0 < (size_sids_0); cntr_sids_0++) { + NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, &r->sids[cntr_sids_0])); + } + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sids_0, 0); + NDR_CHECK(ndr_pull_se_privilege(ndr, NDR_SCALARS, &r->privilege_mask)); + NDR_CHECK(ndr_pull_lsa_SystemAccessModeFlags(ndr, NDR_SCALARS, &r->rights_mask)); + if (r->sids) { + NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->sids, r->num_sids)); + } + NDR_CHECK(ndr_pull_trailer_align(ndr, 8)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +static void ndr_print_flags_security_token(struct ndr_print *ndr, const char *name, int unused, const struct security_token *r) +{ + ndr_print_security_token(ndr, name, r); +} + +_PUBLIC_ void ndr_print_security_token(struct ndr_print *ndr, const char *name, const struct security_token *r) +{ + uint32_t cntr_sids_0; + ndr_print_struct(ndr, name, "security_token"); + if (r == NULL) { ndr_print_null(ndr); return; } + ndr->depth++; + ndr_print_uint32(ndr, "num_sids", r->num_sids); + ndr->print(ndr, "%s: ARRAY(%d)", "sids", (int)r->num_sids); + ndr->depth++; + for (cntr_sids_0 = 0; cntr_sids_0 < (r->num_sids); cntr_sids_0++) { + ndr_print_dom_sid(ndr, "sids", &r->sids[cntr_sids_0]); + } + ndr->depth--; + ndr_print_se_privilege(ndr, "privilege_mask", r->privilege_mask); + ndr_print_lsa_SystemAccessModeFlags(ndr, "rights_mask", r->rights_mask); + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_security_unix_token(struct ndr_push *ndr, int ndr_flags, const struct security_unix_token *r) +{ + uint32_t cntr_groups_0; + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, r->ngroups)); + NDR_CHECK(ndr_push_align(ndr, 8)); + NDR_CHECK(ndr_push_uid_t(ndr, NDR_SCALARS, r->uid)); + NDR_CHECK(ndr_push_gid_t(ndr, NDR_SCALARS, r->gid)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->ngroups)); + for (cntr_groups_0 = 0; cntr_groups_0 < (r->ngroups); cntr_groups_0++) { + NDR_CHECK(ndr_push_gid_t(ndr, NDR_SCALARS, r->groups[cntr_groups_0])); + } + NDR_CHECK(ndr_push_trailer_align(ndr, 8)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_unix_token(struct ndr_pull *ndr, int ndr_flags, struct security_unix_token *r) +{ + uint32_t size_groups_0 = 0; + uint32_t cntr_groups_0; + TALLOC_CTX *_mem_save_groups_0 = NULL; + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_array_size(ndr, &r->groups)); + NDR_CHECK(ndr_pull_align(ndr, 8)); + NDR_CHECK(ndr_pull_uid_t(ndr, NDR_SCALARS, &r->uid)); + NDR_CHECK(ndr_pull_gid_t(ndr, NDR_SCALARS, &r->gid)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->ngroups)); + size_groups_0 = ndr_get_array_size(ndr, &r->groups); + NDR_PULL_ALLOC_N(ndr, r->groups, size_groups_0); + _mem_save_groups_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->groups, 0); + for (cntr_groups_0 = 0; cntr_groups_0 < (size_groups_0); cntr_groups_0++) { + NDR_CHECK(ndr_pull_gid_t(ndr, NDR_SCALARS, &r->groups[cntr_groups_0])); + } + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_groups_0, 0); + if (r->groups) { + NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->groups, r->ngroups)); + } + NDR_CHECK(ndr_pull_trailer_align(ndr, 8)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +static void ndr_print_flags_security_unix_token(struct ndr_print *ndr, const char *name, int unused, const struct security_unix_token *r) +{ + ndr_print_security_unix_token(ndr, name, r); +} + +_PUBLIC_ void ndr_print_security_unix_token(struct ndr_print *ndr, const char *name, const struct security_unix_token *r) +{ + uint32_t cntr_groups_0; + ndr_print_struct(ndr, name, "security_unix_token"); + if (r == NULL) { ndr_print_null(ndr); return; } + ndr->depth++; + ndr_print_uid_t(ndr, "uid", r->uid); + ndr_print_gid_t(ndr, "gid", r->gid); + ndr_print_uint32(ndr, "ngroups", r->ngroups); + ndr->print(ndr, "%s: ARRAY(%d)", "groups", (int)r->ngroups); + ndr->depth++; + for (cntr_groups_0 = 0; cntr_groups_0 < (r->ngroups); cntr_groups_0++) { + ndr_print_gid_t(ndr, "groups", r->groups[cntr_groups_0]); + } + ndr->depth--; + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_security_secinfo(struct ndr_push *ndr, int ndr_flags, uint32_t r) +{ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_secinfo(struct ndr_pull *ndr, int ndr_flags, uint32_t *r) +{ + uint32_t v; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_security_secinfo(struct ndr_print *ndr, const char *name, uint32_t r) +{ + ndr_print_uint32(ndr, name, r); + ndr->depth++; + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_OWNER", SECINFO_OWNER, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_GROUP", SECINFO_GROUP, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_DACL", SECINFO_DACL, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_SACL", SECINFO_SACL, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_LABEL", SECINFO_LABEL, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_ATTRIBUTE", SECINFO_ATTRIBUTE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_SCOPE", SECINFO_SCOPE, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_BACKUP", SECINFO_BACKUP, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_UNPROTECTED_SACL", SECINFO_UNPROTECTED_SACL, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_UNPROTECTED_DACL", SECINFO_UNPROTECTED_DACL, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_PROTECTED_SACL", SECINFO_PROTECTED_SACL, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_PROTECTED_DACL", SECINFO_PROTECTED_DACL, r); + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_LSAP_TOKEN_INFO_INTEGRITY(struct ndr_push *ndr, int ndr_flags, const struct LSAP_TOKEN_INFO_INTEGRITY *r) +{ + { + uint32_t _flags_save_STRUCT = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX); + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->Flags)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->TokenIL)); + NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->MachineId, 32)); + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + ndr->flags = _flags_save_STRUCT; + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_LSAP_TOKEN_INFO_INTEGRITY(struct ndr_pull *ndr, int ndr_flags, struct LSAP_TOKEN_INFO_INTEGRITY *r) +{ + uint32_t size_MachineId_0 = 0; + { + uint32_t _flags_save_STRUCT = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX); + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->Flags)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->TokenIL)); + size_MachineId_0 = 32; + NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->MachineId, size_MachineId_0)); + NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); + } + if (ndr_flags & NDR_BUFFERS) { + } + ndr->flags = _flags_save_STRUCT; + } + return NDR_ERR_SUCCESS; +} + +static void ndr_print_flags_LSAP_TOKEN_INFO_INTEGRITY(struct ndr_print *ndr, const char *name, int unused, const struct LSAP_TOKEN_INFO_INTEGRITY *r) +{ + ndr_print_LSAP_TOKEN_INFO_INTEGRITY(ndr, name, r); +} + +_PUBLIC_ void ndr_print_LSAP_TOKEN_INFO_INTEGRITY(struct ndr_print *ndr, const char *name, const struct LSAP_TOKEN_INFO_INTEGRITY *r) +{ + ndr_print_struct(ndr, name, "LSAP_TOKEN_INFO_INTEGRITY"); + if (r == NULL) { ndr_print_null(ndr); return; } + { + uint32_t _flags_save_STRUCT = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX); + ndr->depth++; + ndr_print_uint32(ndr, "Flags", r->Flags); + ndr_print_uint32(ndr, "TokenIL", r->TokenIL); + ndr_print_array_uint8(ndr, "MachineId", r->MachineId, 32); + ndr->depth--; + ndr->flags = _flags_save_STRUCT; + } +} + +_PUBLIC_ size_t ndr_size_LSAP_TOKEN_INFO_INTEGRITY(const struct LSAP_TOKEN_INFO_INTEGRITY *r, int flags) +{ + flags |= LIBNDR_PRINT_ARRAY_HEX; + return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_LSAP_TOKEN_INFO_INTEGRITY); +} + +_PUBLIC_ enum ndr_err_code ndr_push_kerb_EncTypes(struct ndr_push *ndr, int ndr_flags, uint32_t r) +{ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_kerb_EncTypes(struct ndr_pull *ndr, int ndr_flags, uint32_t *r) +{ + uint32_t v; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_kerb_EncTypes(struct ndr_print *ndr, const char *name, uint32_t r) +{ + ndr_print_uint32(ndr, name, r); + ndr->depth++; + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "KERB_ENCTYPE_DES_CBC_CRC", KERB_ENCTYPE_DES_CBC_CRC, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "KERB_ENCTYPE_DES_CBC_MD5", KERB_ENCTYPE_DES_CBC_MD5, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "KERB_ENCTYPE_RC4_HMAC_MD5", KERB_ENCTYPE_RC4_HMAC_MD5, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96", KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96", KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "KERB_ENCTYPE_FAST_SUPPORTED", KERB_ENCTYPE_FAST_SUPPORTED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED", KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "KERB_ENCTYPE_CLAIMS_SUPPORTED", KERB_ENCTYPE_CLAIMS_SUPPORTED, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED", KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED, r); + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_security_autoinherit(struct ndr_push *ndr, int ndr_flags, uint32_t r) +{ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r)); + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_security_autoinherit(struct ndr_pull *ndr, int ndr_flags, uint32_t *r) +{ + uint32_t v; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v)); + *r = v; + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_security_autoinherit(struct ndr_print *ndr, const char *name, uint32_t r) +{ + ndr_print_uint32(ndr, name, r); + ndr->depth++; + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SEC_DACL_AUTO_INHERIT", SEC_DACL_AUTO_INHERIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SEC_SACL_AUTO_INHERIT", SEC_SACL_AUTO_INHERIT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SEC_DEFAULT_DESCRIPTOR", SEC_DEFAULT_DESCRIPTOR, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SEC_OWNER_FROM_PARENT", SEC_OWNER_FROM_PARENT, r); + ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SEC_GROUP_FROM_PARENT", SEC_GROUP_FROM_PARENT, r); + ndr->depth--; +} + +#ifndef SKIP_NDR_TABLE_security +static const struct ndr_interface_public_struct security_public_structs[] = { + { + .name = "dom_sid", + .struct_size = sizeof(struct dom_sid ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_dom_sid, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_dom_sid, + .ndr_print = (ndr_print_function_t) ndr_print_flags_dom_sid, + }, + { + .name = "security_ace", + .struct_size = sizeof(struct security_ace ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_security_ace, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_security_ace, + .ndr_print = (ndr_print_function_t) ndr_print_flags_security_ace, + }, + { + .name = "security_acl", + .struct_size = sizeof(struct security_acl ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_security_acl, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_security_acl, + .ndr_print = (ndr_print_function_t) ndr_print_flags_security_acl, + }, + { + .name = "security_descriptor", + .struct_size = sizeof(struct security_descriptor ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_security_descriptor, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_security_descriptor, + .ndr_print = (ndr_print_function_t) ndr_print_flags_security_descriptor, + }, + { + .name = "sec_desc_buf", + .struct_size = sizeof(struct sec_desc_buf ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_sec_desc_buf, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_sec_desc_buf, + .ndr_print = (ndr_print_function_t) ndr_print_flags_sec_desc_buf, + }, + { + .name = "security_token", + .struct_size = sizeof(struct security_token ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_security_token, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_security_token, + .ndr_print = (ndr_print_function_t) ndr_print_flags_security_token, + }, + { + .name = "security_unix_token", + .struct_size = sizeof(struct security_unix_token ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_security_unix_token, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_security_unix_token, + .ndr_print = (ndr_print_function_t) ndr_print_flags_security_unix_token, + }, + { + .name = "LSAP_TOKEN_INFO_INTEGRITY", + .struct_size = sizeof(struct LSAP_TOKEN_INFO_INTEGRITY ), + .ndr_push = (ndr_push_flags_fn_t) ndr_push_LSAP_TOKEN_INFO_INTEGRITY, + .ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_LSAP_TOKEN_INFO_INTEGRITY, + .ndr_print = (ndr_print_function_t) ndr_print_flags_LSAP_TOKEN_INFO_INTEGRITY, + }, + { .name = NULL } +}; + +static const struct ndr_interface_call security_calls[] = { + { .name = NULL } +}; + +static const char * const security_endpoint_strings[] = { + "ncacn_np:[\\pipe\\security]", +}; + +static const struct ndr_interface_string_array security_endpoints = { + .count = 1, + .names = security_endpoint_strings +}; + +static const char * const security_authservice_strings[] = { + "host", +}; + +static const struct ndr_interface_string_array security_authservices = { + .count = 1, + .names = security_authservice_strings +}; + + +const struct ndr_interface_table ndr_table_security = { + .name = "security", + .syntax_id = { + {0xcbf7d408,0x2d6c,0x11e2,{0xae,0x5b},{0x0b,0x56,0x92,0x79,0x0e,0x18}}, + NDR_SECURITY_VERSION + }, + .helpstring = NDR_SECURITY_HELPSTRING, + .num_calls = 0, + .calls = security_calls, + .num_public_structs = 8, + .public_structs = security_public_structs, + .endpoints = &security_endpoints, + .authservices = &security_authservices +}; + +#endif /* SKIP_NDR_TABLE_security */ diff --git a/src/adldap/samba/ndr_security.h b/src/adldap/samba/ndr_security.h index c799f979..e715f9e3 100644 --- a/src/adldap/samba/ndr_security.h +++ b/src/adldap/samba/ndr_security.h @@ -18,13 +18,9 @@ */ /* - * This file is a copy of private samba sources. Parts of it - * were removed or edited. + * This file is a copy of private samba sources. */ -#ifndef NDR_SECURITY_H -#define NDR_SECURITY_H - #ifdef __cplusplus extern "C" { #endif @@ -32,13 +28,85 @@ extern "C" { #include #include -enum ndr_err_code -ndr_security_pull_security_descriptor(struct ndr_pull *ndr, - int ndr_flags, - struct security_descriptor *r); +/* header auto-generated by pidl */ + +// #include "librpc/ndr/libndr.h" +// #include "bin/default/librpc/gen_ndr/security.h" + +#ifndef _HEADER_NDR_security +#define _HEADER_NDR_security + +#define NDR_SECURITY_UUID "cbf7d408-2d6c-11e2-ae5b-0b5692790e18" +#define NDR_SECURITY_VERSION 0.0 +#define NDR_SECURITY_NAME "security" +#define NDR_SECURITY_HELPSTRING NULL +extern const struct ndr_interface_table ndr_table_security; +#define NDR_SECURITY_CALL_COUNT (0) +enum ndr_err_code ndr_push_dom_sid(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *r); +enum ndr_err_code ndr_pull_dom_sid(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *r); +void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *r); +size_t ndr_size_dom_sid(const struct dom_sid *r, int flags); +void ndr_print_se_privilege(struct ndr_print *ndr, const char *name, uint64_t r); +void ndr_print_lsa_SystemAccessModeFlags(struct ndr_print *ndr, const char *name, uint32_t r); +enum ndr_err_code ndr_push_security_ace_flags(struct ndr_push *ndr, int ndr_flags, uint8_t r); +enum ndr_err_code ndr_pull_security_ace_flags(struct ndr_pull *ndr, int ndr_flags, uint8_t *r); +void ndr_print_security_ace_flags(struct ndr_print *ndr, const char *name, uint8_t r); +enum ndr_err_code ndr_push_security_ace_type(struct ndr_push *ndr, int ndr_flags, enum security_ace_type r); +enum ndr_err_code ndr_pull_security_ace_type(struct ndr_pull *ndr, int ndr_flags, enum security_ace_type *r); +void ndr_print_security_ace_type(struct ndr_print *ndr, const char *name, enum security_ace_type r); +void ndr_print_security_ace_object_flags(struct ndr_print *ndr, const char *name, uint32_t r); +void ndr_print_security_ace_object_type(struct ndr_print *ndr, const char *name, const union security_ace_object_type *r); +void ndr_print_security_ace_object_inherited_type(struct ndr_print *ndr, const char *name, const union security_ace_object_inherited_type *r); +void ndr_print_security_ace_object(struct ndr_print *ndr, const char *name, const struct security_ace_object *r); +enum ndr_err_code ndr_push_security_ace_object_ctr(struct ndr_push *ndr, int ndr_flags, const union security_ace_object_ctr *r); +enum ndr_err_code ndr_pull_security_ace_object_ctr(struct ndr_pull *ndr, int ndr_flags, union security_ace_object_ctr *r); +void ndr_print_security_ace_object_ctr(struct ndr_print *ndr, const char *name, const union security_ace_object_ctr *r); +enum ndr_err_code ndr_push_security_ace(struct ndr_push *ndr, int ndr_flags, const struct security_ace *r); +enum ndr_err_code ndr_pull_security_ace(struct ndr_pull *ndr, int ndr_flags, struct security_ace *r); +void ndr_print_security_ace(struct ndr_print *ndr, const char *name, const struct security_ace *r); +size_t ndr_size_security_ace(const struct security_ace *r, int flags); +void ndr_print_security_acl_revision(struct ndr_print *ndr, const char *name, enum security_acl_revision r); +enum ndr_err_code ndr_push_security_acl(struct ndr_push *ndr, int ndr_flags, const struct security_acl *r); +enum ndr_err_code ndr_pull_security_acl(struct ndr_pull *ndr, int ndr_flags, struct security_acl *r); +void ndr_print_security_acl(struct ndr_print *ndr, const char *name, const struct security_acl *r); +size_t ndr_size_security_acl(const struct security_acl *r, int flags); +enum ndr_err_code ndr_push_security_descriptor_revision(struct ndr_push *ndr, int ndr_flags, enum security_descriptor_revision r); +enum ndr_err_code ndr_pull_security_descriptor_revision(struct ndr_pull *ndr, int ndr_flags, enum security_descriptor_revision *r); +void ndr_print_security_descriptor_revision(struct ndr_print *ndr, const char *name, enum security_descriptor_revision r); +enum ndr_err_code ndr_push_security_descriptor_type(struct ndr_push *ndr, int ndr_flags, uint16_t r); +enum ndr_err_code ndr_pull_security_descriptor_type(struct ndr_pull *ndr, int ndr_flags, uint16_t *r); +void ndr_print_security_descriptor_type(struct ndr_print *ndr, const char *name, uint16_t r); +enum ndr_err_code ndr_push_security_descriptor(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor *r); +enum ndr_err_code ndr_pull_security_descriptor(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor *r); +void ndr_print_security_descriptor(struct ndr_print *ndr, const char *name, const struct security_descriptor *r); +size_t ndr_size_security_descriptor(const struct security_descriptor *r, int flags); +enum ndr_err_code ndr_push_sec_desc_buf(struct ndr_push *ndr, int ndr_flags, const struct sec_desc_buf *r); +enum ndr_err_code ndr_pull_sec_desc_buf(struct ndr_pull *ndr, int ndr_flags, struct sec_desc_buf *r); +void ndr_print_sec_desc_buf(struct ndr_print *ndr, const char *name, const struct sec_desc_buf *r); +enum ndr_err_code ndr_push_security_GroupAttrs(struct ndr_push *ndr, int ndr_flags, uint32_t r); +enum ndr_err_code ndr_pull_security_GroupAttrs(struct ndr_pull *ndr, int ndr_flags, uint32_t *r); +void ndr_print_security_GroupAttrs(struct ndr_print *ndr, const char *name, uint32_t r); +enum ndr_err_code ndr_push_security_token(struct ndr_push *ndr, int ndr_flags, const struct security_token *r); +enum ndr_err_code ndr_pull_security_token(struct ndr_pull *ndr, int ndr_flags, struct security_token *r); +void ndr_print_security_token(struct ndr_print *ndr, const char *name, const struct security_token *r); +enum ndr_err_code ndr_push_security_unix_token(struct ndr_push *ndr, int ndr_flags, const struct security_unix_token *r); +enum ndr_err_code ndr_pull_security_unix_token(struct ndr_pull *ndr, int ndr_flags, struct security_unix_token *r); +void ndr_print_security_unix_token(struct ndr_print *ndr, const char *name, const struct security_unix_token *r); +enum ndr_err_code ndr_push_security_secinfo(struct ndr_push *ndr, int ndr_flags, uint32_t r); +enum ndr_err_code ndr_pull_security_secinfo(struct ndr_pull *ndr, int ndr_flags, uint32_t *r); +void ndr_print_security_secinfo(struct ndr_print *ndr, const char *name, uint32_t r); +enum ndr_err_code ndr_push_LSAP_TOKEN_INFO_INTEGRITY(struct ndr_push *ndr, int ndr_flags, const struct LSAP_TOKEN_INFO_INTEGRITY *r); +enum ndr_err_code ndr_pull_LSAP_TOKEN_INFO_INTEGRITY(struct ndr_pull *ndr, int ndr_flags, struct LSAP_TOKEN_INFO_INTEGRITY *r); +void ndr_print_LSAP_TOKEN_INFO_INTEGRITY(struct ndr_print *ndr, const char *name, const struct LSAP_TOKEN_INFO_INTEGRITY *r); +size_t ndr_size_LSAP_TOKEN_INFO_INTEGRITY(const struct LSAP_TOKEN_INFO_INTEGRITY *r, int flags); +enum ndr_err_code ndr_push_kerb_EncTypes(struct ndr_push *ndr, int ndr_flags, uint32_t r); +enum ndr_err_code ndr_pull_kerb_EncTypes(struct ndr_pull *ndr, int ndr_flags, uint32_t *r); +void ndr_print_kerb_EncTypes(struct ndr_print *ndr, const char *name, uint32_t r); +enum ndr_err_code ndr_push_security_autoinherit(struct ndr_push *ndr, int ndr_flags, uint32_t r); +enum ndr_err_code ndr_pull_security_autoinherit(struct ndr_pull *ndr, int ndr_flags, uint32_t *r); +void ndr_print_security_autoinherit(struct ndr_print *ndr, const char *name, uint32_t r); +#endif /* _HEADER_NDR_security */ #ifdef __cplusplus } #endif - -#endif /* NDR_SECURITY_H */ diff --git a/src/adldap/samba/replace.h b/src/adldap/samba/replace.h index 5cb2c729..4c08d367 100644 --- a/src/adldap/samba/replace.h +++ b/src/adldap/samba/replace.h @@ -35,6 +35,7 @@ #include #include +#include #ifndef __PRI64_PREFIX # if __WORDSIZE == 64 && ! defined __APPLE__ @@ -57,6 +58,11 @@ # define PRIu64 __PRI64_PREFIX "u" #endif +#ifndef HAVE_MEMSET_S +#define memset_s rep_memset_s +int rep_memset_s(void *dest, size_t destsz, int ch, size_t count); +#endif + #define strlcpy rep_strlcpy size_t rep_strlcpy(char *d, const char *s, size_t bufsize); @@ -68,4 +74,28 @@ size_t rep_strlcpy(char *d, const char *s, size_t bufsize); #define MAX(a,b) ((a)>(b)?(a):(b)) #endif +/** + * Work out how many elements there are in a static array. + */ +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +/** + * Zero a structure. + */ +#define ZERO_STRUCT(x) memset_s((char *)&(x), sizeof(x), 0, sizeof(x)) + +/** + * Zero a structure given a pointer to the structure. + */ +#define ZERO_STRUCTP(x) do { \ + if ((x) != NULL) { \ + memset_s((char *)(x), sizeof(*(x)), 0, sizeof(*(x))); \ + } \ +} while(0) + +/** + * Zero a structure given a pointer to the structure - no zero check + */ +#define ZERO_STRUCTPN(x) memset_s((char *)(x), sizeof(*(x)), 0, sizeof(*(x))) + #endif /* _LIBREPLACE_REPLACE_H */ diff --git a/src/adldap/samba/security_descriptor.c b/src/adldap/samba/security_descriptor.c new file mode 100644 index 00000000..f663fa45 --- /dev/null +++ b/src/adldap/samba/security_descriptor.c @@ -0,0 +1,705 @@ +/* + Unix SMB/CIFS implementation. + + security descriptror utility functions + + Copyright (C) Andrew Tridgell 2004 + + 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 . +*/ + +/* + * This file is a copy of private samba sources. Parts of it + * were removed or edited. + */ + +#include "security_descriptor.h" + +#include "dom_sid.h" +#include + +/* + return a blank security descriptor (no owners, dacl or sacl) +*/ +struct security_descriptor *security_descriptor_initialise(TALLOC_CTX *mem_ctx) +{ + struct security_descriptor *sd; + + sd = talloc(mem_ctx, struct security_descriptor); + if (!sd) { + return NULL; + } + + sd->revision = SD_REVISION; + /* we mark as self relative, even though it isn't while it remains + a pointer in memory because this simplifies the ndr code later. + All SDs that we store/emit are in fact SELF_RELATIVE + */ + sd->type = SEC_DESC_SELF_RELATIVE; + + sd->owner_sid = NULL; + sd->group_sid = NULL; + sd->sacl = NULL; + sd->dacl = NULL; + + return sd; +} + +struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx, + const struct security_acl *oacl) +{ + struct security_acl *nacl; + + if (oacl == NULL) { + return NULL; + } + + if (oacl->aces == NULL && oacl->num_aces > 0) { + return NULL; + } + + nacl = talloc (mem_ctx, struct security_acl); + if (nacl == NULL) { + return NULL; + } + + *nacl = (struct security_acl) { + .revision = oacl->revision, + .size = oacl->size, + .num_aces = oacl->num_aces, + }; + if (nacl->num_aces == 0) { + return nacl; + } + + nacl->aces = (struct security_ace *)talloc_memdup (nacl, oacl->aces, sizeof(struct security_ace) * oacl->num_aces); + if (nacl->aces == NULL) { + goto failed; + } + + return nacl; + + failed: + talloc_free (nacl); + return NULL; + +} + +struct security_acl *security_acl_concatenate(TALLOC_CTX *mem_ctx, + const struct security_acl *acl1, + const struct security_acl *acl2) +{ + struct security_acl *nacl; + uint32_t i; + + if (!acl1 && !acl2) + return NULL; + + if (!acl1){ + nacl = security_acl_dup(mem_ctx, acl2); + return nacl; + } + + if (!acl2){ + nacl = security_acl_dup(mem_ctx, acl1); + return nacl; + } + + nacl = talloc (mem_ctx, struct security_acl); + if (nacl == NULL) { + return NULL; + } + + nacl->revision = acl1->revision; + nacl->size = acl1->size + acl2->size; + nacl->num_aces = acl1->num_aces + acl2->num_aces; + + if (nacl->num_aces == 0) + return nacl; + + nacl->aces = (struct security_ace *)talloc_array (mem_ctx, struct security_ace, acl1->num_aces+acl2->num_aces); + if ((nacl->aces == NULL) && (nacl->num_aces > 0)) { + goto failed; + } + + for (i = 0; i < acl1->num_aces; i++) + nacl->aces[i] = acl1->aces[i]; + for (i = 0; i < acl2->num_aces; i++) + nacl->aces[i + acl1->num_aces] = acl2->aces[i]; + + return nacl; + + failed: + talloc_free (nacl); + return NULL; + +} + +/* + talloc and copy a security descriptor + */ +struct security_descriptor *security_descriptor_copy(TALLOC_CTX *mem_ctx, + const struct security_descriptor *osd) +{ + struct security_descriptor *nsd; + + nsd = talloc_zero(mem_ctx, struct security_descriptor); + if (!nsd) { + return NULL; + } + + if (osd->owner_sid) { + nsd->owner_sid = dom_sid_dup(nsd, osd->owner_sid); + if (nsd->owner_sid == NULL) { + goto failed; + } + } + + if (osd->group_sid) { + nsd->group_sid = dom_sid_dup(nsd, osd->group_sid); + if (nsd->group_sid == NULL) { + goto failed; + } + } + + if (osd->sacl) { + nsd->sacl = security_acl_dup(nsd, osd->sacl); + if (nsd->sacl == NULL) { + goto failed; + } + } + + if (osd->dacl) { + nsd->dacl = security_acl_dup(nsd, osd->dacl); + if (nsd->dacl == NULL) { + goto failed; + } + } + + nsd->revision = osd->revision; + nsd->type = osd->type; + + return nsd; + + failed: + talloc_free(nsd); + + return NULL; +} + +NTSTATUS security_descriptor_for_client(TALLOC_CTX *mem_ctx, + const struct security_descriptor *ssd, + uint32_t sec_info, + uint32_t access_granted, + struct security_descriptor **_csd) +{ + struct security_descriptor *csd = NULL; + uint32_t access_required = 0; + + *_csd = NULL; + + if (sec_info & (SECINFO_OWNER|SECINFO_GROUP)) { + access_required |= SEC_STD_READ_CONTROL; + } + if (sec_info & SECINFO_DACL) { + access_required |= SEC_STD_READ_CONTROL; + } + if (sec_info & SECINFO_SACL) { + access_required |= SEC_FLAG_SYSTEM_SECURITY; + } + + if (access_required & (~access_granted)) { + return NT_STATUS_ACCESS_DENIED; + } + + /* + * make a copy... + */ + csd = security_descriptor_copy(mem_ctx, ssd); + if (csd == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* + * ... and remove everthing not wanted + */ + + if (!(sec_info & SECINFO_OWNER)) { + TALLOC_FREE(csd->owner_sid); + csd->type &= ~SEC_DESC_OWNER_DEFAULTED; + } + if (!(sec_info & SECINFO_GROUP)) { + TALLOC_FREE(csd->group_sid); + csd->type &= ~SEC_DESC_GROUP_DEFAULTED; + } + if (!(sec_info & SECINFO_DACL)) { + TALLOC_FREE(csd->dacl); + csd->type &= ~( + SEC_DESC_DACL_PRESENT | + SEC_DESC_DACL_DEFAULTED| + SEC_DESC_DACL_AUTO_INHERIT_REQ | + SEC_DESC_DACL_AUTO_INHERITED | + SEC_DESC_DACL_PROTECTED | + SEC_DESC_DACL_TRUSTED); + } + if (!(sec_info & SECINFO_SACL)) { + TALLOC_FREE(csd->sacl); + csd->type &= ~( + SEC_DESC_SACL_PRESENT | + SEC_DESC_SACL_DEFAULTED | + SEC_DESC_SACL_AUTO_INHERIT_REQ | + SEC_DESC_SACL_AUTO_INHERITED | + SEC_DESC_SACL_PROTECTED | + SEC_DESC_SERVER_SECURITY); + } + + *_csd = csd; + return NT_STATUS_OK; +} + +/* + add an ACE to an ACL of a security_descriptor +*/ + +static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd, + bool add_to_sacl, + const struct security_ace *ace) +{ + struct security_acl *acl = NULL; + + if (add_to_sacl) { + acl = sd->sacl; + } else { + acl = sd->dacl; + } + + if (acl == NULL) { + acl = talloc(sd, struct security_acl); + if (acl == NULL) { + return NT_STATUS_NO_MEMORY; + } + acl->revision = SECURITY_ACL_REVISION_NT4; + acl->size = 0; + acl->num_aces = 0; + acl->aces = NULL; + } + + acl->aces = talloc_realloc(acl, acl->aces, + struct security_ace, acl->num_aces+1); + if (acl->aces == NULL) { + return NT_STATUS_NO_MEMORY; + } + + acl->aces[acl->num_aces] = *ace; + + switch (acl->aces[acl->num_aces].type) { + case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: + case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: + case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: + case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: + acl->revision = SECURITY_ACL_REVISION_ADS; + break; + default: + break; + } + + acl->num_aces++; + + if (add_to_sacl) { + sd->sacl = acl; + sd->type |= SEC_DESC_SACL_PRESENT; + } else { + sd->dacl = acl; + sd->type |= SEC_DESC_DACL_PRESENT; + } + + return NT_STATUS_OK; +} + +/* + add an ACE to the SACL of a security_descriptor +*/ + +NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd, + const struct security_ace *ace) +{ + return security_descriptor_acl_add(sd, true, ace); +} + +/* + add an ACE to the DACL of a security_descriptor +*/ + +NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd, + const struct security_ace *ace) +{ + return security_descriptor_acl_add(sd, false, ace); +} + +/* + delete the ACE corresponding to the given trustee in an ACL of a + security_descriptor +*/ + +static NTSTATUS security_descriptor_acl_del(struct security_descriptor *sd, + bool sacl_del, + const struct dom_sid *trustee) +{ + uint32_t i; + bool found = false; + struct security_acl *acl = NULL; + + if (sacl_del) { + acl = sd->sacl; + } else { + acl = sd->dacl; + } + + if (acl == NULL) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* there can be multiple ace's for one trustee */ + for (i=0;inum_aces;i++) { + if (dom_sid_equal(trustee, &acl->aces[i].trustee)) { + memmove(&acl->aces[i], &acl->aces[i+1], + sizeof(acl->aces[i]) * (acl->num_aces - (i+1))); + acl->num_aces--; + if (acl->num_aces == 0) { + acl->aces = NULL; + } + found = true; + } + } + + if (!found) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + acl->revision = SECURITY_ACL_REVISION_NT4; + + for (i=0;inum_aces;i++) { + switch (acl->aces[i].type) { + case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: + case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: + case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: + case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: + acl->revision = SECURITY_ACL_REVISION_ADS; + return NT_STATUS_OK; + default: + break; /* only for the switch statement */ + } + } + + return NT_STATUS_OK; +} + +/* + delete the ACE corresponding to the given trustee in the DACL of a + security_descriptor +*/ + +NTSTATUS security_descriptor_dacl_del(struct security_descriptor *sd, + const struct dom_sid *trustee) +{ + return security_descriptor_acl_del(sd, false, trustee); +} + +/* + delete the ACE corresponding to the given trustee in the SACL of a + security_descriptor +*/ + +NTSTATUS security_descriptor_sacl_del(struct security_descriptor *sd, + const struct dom_sid *trustee) +{ + return security_descriptor_acl_del(sd, true, trustee); +} + +/* + compare two security ace structures +*/ +bool security_ace_equal(const struct security_ace *ace1, + const struct security_ace *ace2) +{ + if (ace1 == ace2) { + return true; + } + if ((ace1 == NULL) || (ace2 == NULL)) { + return false; + } + if (ace1->type != ace2->type) { + return false; + } + if (ace1->flags != ace2->flags) { + return false; + } + if (ace1->access_mask != ace2->access_mask) { + return false; + } + if (!dom_sid_equal(&ace1->trustee, &ace2->trustee)) { + return false; + } + + return true; +} + + +/* + compare two security acl structures +*/ +bool security_acl_equal(const struct security_acl *acl1, + const struct security_acl *acl2) +{ + uint32_t i; + + if (acl1 == acl2) return true; + if (!acl1 || !acl2) return false; + if (acl1->revision != acl2->revision) return false; + if (acl1->num_aces != acl2->num_aces) return false; + + for (i=0;inum_aces;i++) { + if (!security_ace_equal(&acl1->aces[i], &acl2->aces[i])) return false; + } + return true; +} + +/* + compare two security descriptors. +*/ +bool security_descriptor_equal(const struct security_descriptor *sd1, + const struct security_descriptor *sd2) +{ + if (sd1 == sd2) return true; + if (!sd1 || !sd2) return false; + if (sd1->revision != sd2->revision) return false; + if (sd1->type != sd2->type) return false; + + if (!dom_sid_equal(sd1->owner_sid, sd2->owner_sid)) return false; + if (!dom_sid_equal(sd1->group_sid, sd2->group_sid)) return false; + if (!security_acl_equal(sd1->sacl, sd2->sacl)) return false; + if (!security_acl_equal(sd1->dacl, sd2->dacl)) return false; + + return true; +} + +/* + compare two security descriptors, but allow certain (missing) parts + to be masked out of the comparison +*/ +bool security_descriptor_mask_equal(const struct security_descriptor *sd1, + const struct security_descriptor *sd2, + uint32_t mask) +{ + if (sd1 == sd2) return true; + if (!sd1 || !sd2) return false; + if (sd1->revision != sd2->revision) return false; + if ((sd1->type & mask) != (sd2->type & mask)) return false; + + if (!dom_sid_equal(sd1->owner_sid, sd2->owner_sid)) return false; + if (!dom_sid_equal(sd1->group_sid, sd2->group_sid)) return false; + if ((mask & SEC_DESC_DACL_PRESENT) && !security_acl_equal(sd1->dacl, sd2->dacl)) return false; + if ((mask & SEC_DESC_SACL_PRESENT) && !security_acl_equal(sd1->sacl, sd2->sacl)) return false; + + return true; +} + + +static struct security_descriptor *security_descriptor_appendv(struct security_descriptor *sd, + bool add_ace_to_sacl, + va_list ap) +{ + const char *sidstr; + + while ((sidstr = va_arg(ap, const char *))) { + struct dom_sid *sid; + struct security_ace *ace = talloc_zero(sd, struct security_ace); + NTSTATUS status; + + if (ace == NULL) { + talloc_free(sd); + return NULL; + } + ace->type = va_arg(ap, unsigned int); + ace->access_mask = va_arg(ap, unsigned int); + ace->flags = va_arg(ap, unsigned int); + sid = dom_sid_parse_talloc(ace, sidstr); + if (sid == NULL) { + talloc_free(sd); + return NULL; + } + ace->trustee = *sid; + if (add_ace_to_sacl) { + status = security_descriptor_sacl_add(sd, ace); + } else { + status = security_descriptor_dacl_add(sd, ace); + } + /* TODO: check: would talloc_free(ace) here be correct? */ + if (!NT_STATUS_IS_OK(status)) { + talloc_free(sd); + return NULL; + } + } + + return sd; +} + +struct security_descriptor *security_descriptor_append(struct security_descriptor *sd, + ...) +{ + va_list ap; + + va_start(ap, sd); + sd = security_descriptor_appendv(sd, false, ap); + va_end(ap); + + return sd; +} + +static struct security_descriptor *security_descriptor_createv(TALLOC_CTX *mem_ctx, + uint16_t sd_type, + const char *owner_sid, + const char *group_sid, + bool add_ace_to_sacl, + va_list ap) +{ + struct security_descriptor *sd; + + sd = security_descriptor_initialise(mem_ctx); + if (sd == NULL) { + return NULL; + } + + sd->type |= sd_type; + + if (owner_sid) { + sd->owner_sid = dom_sid_parse_talloc(sd, owner_sid); + if (sd->owner_sid == NULL) { + talloc_free(sd); + return NULL; + } + } + if (group_sid) { + sd->group_sid = dom_sid_parse_talloc(sd, group_sid); + if (sd->group_sid == NULL) { + talloc_free(sd); + return NULL; + } + } + + return security_descriptor_appendv(sd, add_ace_to_sacl, ap); +} + +/* + create a security descriptor using string SIDs. This is used by the + torture code to allow the easy creation of complex ACLs + This is a varargs function. The list of DACL ACEs ends with a NULL sid. + + Each ACE contains a set of 4 parameters: + SID, ACCESS_TYPE, MASK, FLAGS + + a typical call would be: + + sd = security_descriptor_dacl_create(mem_ctx, + sd_type_flags, + mysid, + mygroup, + SID_NT_AUTHENTICATED_USERS, + SEC_ACE_TYPE_ACCESS_ALLOWED, + SEC_FILE_ALL, + SEC_ACE_FLAG_OBJECT_INHERIT, + NULL); + that would create a sd with one DACL ACE +*/ + +struct security_descriptor *security_descriptor_dacl_create(TALLOC_CTX *mem_ctx, + uint16_t sd_type, + const char *owner_sid, + const char *group_sid, + ...) +{ + struct security_descriptor *sd = NULL; + va_list ap; + va_start(ap, group_sid); + sd = security_descriptor_createv(mem_ctx, sd_type, owner_sid, + group_sid, false, ap); + va_end(ap); + + return sd; +} + +struct security_descriptor *security_descriptor_sacl_create(TALLOC_CTX *mem_ctx, + uint16_t sd_type, + const char *owner_sid, + const char *group_sid, + ...) +{ + struct security_descriptor *sd = NULL; + va_list ap; + va_start(ap, group_sid); + sd = security_descriptor_createv(mem_ctx, sd_type, owner_sid, + group_sid, true, ap); + va_end(ap); + + return sd; +} + +struct security_ace *security_ace_create(TALLOC_CTX *mem_ctx, + const char *sid_str, + enum security_ace_type type, + uint32_t access_mask, + uint8_t flags) + +{ + struct security_ace *ace; + bool ok; + + ace = talloc_zero(mem_ctx, struct security_ace); + if (ace == NULL) { + return NULL; + } + + ok = dom_sid_parse(sid_str, &ace->trustee); + if (!ok) { + talloc_free(ace); + return NULL; + } + ace->type = type; + ace->access_mask = access_mask; + ace->flags = flags; + + return ace; +} + +/******************************************************************* + Check for MS NFS ACEs in a sd +*******************************************************************/ +bool security_descriptor_with_ms_nfs(const struct security_descriptor *psd) +{ + int i; + + if (psd->dacl == NULL) { + return false; + } + + for (i = 0; i < psd->dacl->num_aces; i++) { + // if (dom_sid_compare_domain( + // &global_sid_Unix_NFS, + // &psd->dacl->aces[i].trustee) == 0) { + // return true; + // } + } + + return false; +} diff --git a/src/adldap/samba/security_descriptor.h b/src/adldap/samba/security_descriptor.h new file mode 100644 index 00000000..5dd5ce3f --- /dev/null +++ b/src/adldap/samba/security_descriptor.h @@ -0,0 +1,105 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + + Copyright (C) 2009 Jelmer Vernooij + + 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 . +*/ + +/* + * This file is a copy of private samba sources. Parts of it + * were removed or edited. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __SECURITY_DESCRIPTOR_H__ +#define __SECURITY_DESCRIPTOR_H__ + +#include +#include + +struct security_descriptor *security_descriptor_initialise(TALLOC_CTX *mem_ctx); +struct security_descriptor *security_descriptor_copy(TALLOC_CTX *mem_ctx, + const struct security_descriptor *osd); +NTSTATUS security_descriptor_for_client(TALLOC_CTX *mem_ctx, + const struct security_descriptor *ssd, + uint32_t sec_info, + uint32_t access_granted, + struct security_descriptor **_csd); +NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd, + const struct security_ace *ace); +NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd, + const struct security_ace *ace); +NTSTATUS security_descriptor_dacl_del(struct security_descriptor *sd, + const struct dom_sid *trustee); +NTSTATUS security_descriptor_sacl_del(struct security_descriptor *sd, + const struct dom_sid *trustee); +bool security_ace_equal(const struct security_ace *ace1, + const struct security_ace *ace2); +bool security_acl_equal(const struct security_acl *acl1, + const struct security_acl *acl2); +bool security_descriptor_equal(const struct security_descriptor *sd1, + const struct security_descriptor *sd2); +bool security_descriptor_mask_equal(const struct security_descriptor *sd1, + const struct security_descriptor *sd2, + uint32_t mask); +struct security_descriptor *security_descriptor_append(struct security_descriptor *sd, + ...); +struct security_descriptor *security_descriptor_dacl_create(TALLOC_CTX *mem_ctx, + uint16_t sd_type, + const char *owner_sid, + const char *group_sid, + ...); +struct security_descriptor *security_descriptor_sacl_create(TALLOC_CTX *mem_ctx, + uint16_t sd_type, + const char *owner_sid, + const char *group_sid, + ...); +struct security_ace *security_ace_create(TALLOC_CTX *mem_ctx, + const char *sid_str, + enum security_ace_type type, + uint32_t access_mask, + uint8_t flags); + +struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx, + const struct security_acl *oacl); + +struct security_acl *security_acl_concatenate(TALLOC_CTX *mem_ctx, + const struct security_acl *acl1, + const struct security_acl *acl2); + +uint32_t map_generic_rights_ds(uint32_t access_mask); + +struct security_descriptor *create_security_descriptor(TALLOC_CTX *mem_ctx, + struct security_descriptor *parent_sd, + struct security_descriptor *creator_sd, + bool is_container, + struct GUID *object_list, + uint32_t inherit_flags, + struct security_token *token, + struct dom_sid *default_owner, /* valid only for DS, NULL for the other RSs */ + struct dom_sid *default_group, /* valid only for DS, NULL for the other RSs */ + uint32_t (*generic_map)(uint32_t access_mask)); + +bool security_descriptor_with_ms_nfs(const struct security_descriptor *psd); + +#endif /* __SECURITY_DESCRIPTOR_H__ */ + +#ifdef __cplusplus +} +#endif diff --git a/src/admc/CMakeLists.txt b/src/admc/CMakeLists.txt index c6071c4e..a4da4c44 100644 --- a/src/admc/CMakeLists.txt +++ b/src/admc/CMakeLists.txt @@ -96,6 +96,7 @@ set(ADMC_SOURCES tabs/telephones_tab.cpp tabs/profile_tab.cpp tabs/managed_by_tab.cpp + tabs/security_tab.cpp multi_tabs/properties_multi_tab.cpp multi_tabs/general_multi_tab.cpp diff --git a/src/admc/console_types/console_object.cpp b/src/admc/console_types/console_object.cpp index 0ad6b08f..5fa4b332 100644 --- a/src/admc/console_types/console_object.cpp +++ b/src/admc/console_types/console_object.cpp @@ -113,7 +113,7 @@ void console_object_item_data_load(QStandardItem *item, const AdObject &object) const bool cannot_delete = object.get_system_flag(SystemFlagsBit_CannotDelete); item->setData(cannot_delete, ObjectRole_CannotDelete); - const bool account_disabled = object.get_account_option(AccountOption_Disabled); + const bool account_disabled = object.get_account_option(AccountOption_Disabled, g_adconfig); item->setData(account_disabled, ObjectRole_AccountDisabled); } diff --git a/src/admc/create_object_dialog.cpp b/src/admc/create_object_dialog.cpp index 05ee95cd..46db5f06 100644 --- a/src/admc/create_object_dialog.cpp +++ b/src/admc/create_object_dialog.cpp @@ -81,9 +81,9 @@ CreateObjectDialog::CreateObjectDialog(const QString &parent_dn_arg, const QStri const QList options = { AccountOption_PasswordExpired, + AccountOption_CantChangePassword, AccountOption_DontExpirePassword, - AccountOption_Disabled - // TODO: AccountOption_CannotChangePass + AccountOption_Disabled, }; QMap option_edits; AccountOptionEdit::make_many(options, &option_edits, &all_edits, this); diff --git a/src/admc/edits/account_option_edit.cpp b/src/admc/edits/account_option_edit.cpp index cbceac60..33cd16b0 100644 --- a/src/admc/edits/account_option_edit.cpp +++ b/src/admc/edits/account_option_edit.cpp @@ -19,8 +19,11 @@ */ #include "edits/account_option_edit.h" + #include "adldap.h" #include "utils.h" +#include "globals.h" + #include #include #include @@ -81,7 +84,7 @@ AccountOptionEdit::AccountOptionEdit(const AccountOption option_arg, QListsetChecked(option_is_set); } @@ -136,14 +139,9 @@ void account_option_setup_conflicts(const QHash &che }); }; - // NOTE: only setup conflicts for options that exist - // TODO: AccountOption_CantChangePassword. Once security - // descriptor manipulation is implemented, it should be - // evident how to do this. See link: - // https://docs.microsoft.com/en-us/windows/win32/adsi/modifying-user-cannot-change-password-ldap-provider?redirectedfrom=MSDN const QList other_two_options = { AccountOption_DontExpirePassword, - // AccountOption_CantChangePassword, + AccountOption_CantChangePassword, }; for (auto other_option : other_two_options) { diff --git a/src/admc/multi_edits/account_option_multi_edit.cpp b/src/admc/multi_edits/account_option_multi_edit.cpp index e0adfaba..d61b13c7 100644 --- a/src/admc/multi_edits/account_option_multi_edit.cpp +++ b/src/admc/multi_edits/account_option_multi_edit.cpp @@ -21,6 +21,7 @@ #include "multi_edits/account_option_multi_edit.h" #include "edits/account_option_edit.h" +#include "globals.h" #include #include @@ -92,7 +93,7 @@ bool AccountOptionMultiEdit::apply_internal(AdInterface &ad, const QString &targ for (const AccountOption &option : check_map.keys()) { QCheckBox *check = check_map[option]; - const bool current_option_state = object.get_account_option(option); + const bool current_option_state = object.get_account_option(option, g_adconfig); const bool new_option_state = check->isChecked(); const bool option_changed = (new_option_state != current_option_state); if (option_changed) { diff --git a/src/admc/properties_dialog.cpp b/src/admc/properties_dialog.cpp index fd0a5c7e..06a8eb2f 100644 --- a/src/admc/properties_dialog.cpp +++ b/src/admc/properties_dialog.cpp @@ -19,6 +19,7 @@ */ #include "properties_dialog.h" + #include "tabs/properties_tab.h" #include "tabs/attributes_tab.h" #include "tabs/membership_tab.h" @@ -32,12 +33,14 @@ #include "tabs/telephones_tab.h" #include "tabs/profile_tab.h" #include "tabs/managed_by_tab.h" +#include "tabs/security_tab.h" #include "adldap.h" #include "globals.h" #include "settings.h" #include "status.h" #include "utils.h" #include "tab_widget.h" +#include "console_types/console_object.h" #include #include @@ -176,6 +179,10 @@ PropertiesDialog::PropertiesDialog(const QString &target_arg) add_tab(new OrganizationTab(), tr("Organization")); add_tab(new TelephonesTab(), tr("Telephones")); add_tab(new ProfileTab(), tr("Profile")); + + if (advanced_view_ON) { + add_tab(new SecurityTab(), tr("Security")); + } } if (object.is_class(CLASS_GROUP)) { add_tab(new MembersTab(), tr("Members")); @@ -334,6 +341,7 @@ void PropertiesDialog::reset() { if (ad_failed(ad)) { return; } + const AdObject object = ad.search_object(target); for (auto tab : tabs) { diff --git a/src/admc/tabs/account_tab.cpp b/src/admc/tabs/account_tab.cpp index dcd0b785..408a2468 100644 --- a/src/admc/tabs/account_tab.cpp +++ b/src/admc/tabs/account_tab.cpp @@ -29,6 +29,11 @@ // TODO: logon hours, logon computers +// NOTE: the "can't change password" checkbox does not +// affect the permission in the security tab, even though +// they control the same thing. And vice versa. Too +// complicated to implement so this is a WONTFIX. + AccountTab::AccountTab(AdInterface &ad) { auto upn_edit = new UpnEdit(&edits, ad, this); diff --git a/src/admc/tabs/security_tab.cpp b/src/admc/tabs/security_tab.cpp new file mode 100644 index 00000000..a2d4d845 --- /dev/null +++ b/src/admc/tabs/security_tab.cpp @@ -0,0 +1,419 @@ +/* + * ADMC - AD Management Center + * + * Copyright (C) 2020 BaseALT Ltd. + * + * 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 "tabs/security_tab.h" + +#include "adldap.h" +#include "ad_security.h" +#include "utils.h" +#include "globals.h" +#include "select_object_dialog.h" + +#include "samba/ndr_security.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum TrusteeItemRole { + TrusteeItemRole_Sid = Qt::UserRole, +}; + +#define trS(x) QCoreApplication::translate("Security", x) +const QHash ace_permission_to_name_map = { + {AcePermission_FullControl, trS("Full control")}, + {AcePermission_Read, trS("Read")}, + {AcePermission_Write, trS("Write")}, + {AcePermission_CreateChild, trS("Create child")}, + {AcePermission_DeleteChild, trS("Delete child")}, + {AcePermission_AllowedToAuthenticate, trS("Allowed to authenticate")}, + {AcePermission_ChangePassword, trS("Change password")}, + {AcePermission_ReceiveAs, trS("Receive as")}, + {AcePermission_ResetPassword, trS("Reset password")}, + {AcePermission_SendAs, trS("Send as")}, + {AcePermission_ReadAccountRestrictions, trS("Read Account restrictions")}, + {AcePermission_WriteAccountRestrictions, trS("Write Account restrictions")}, + {AcePermission_ReadGeneralInfo, trS("Read general info")}, + {AcePermission_WriteGeneralInfo, trS("Write general info")}, + {AcePermission_ReadGroupMembership, trS("Read group membership")}, + {AcePermission_ReadLogonInfo, trS("Read logon info")}, + {AcePermission_WriteLogonInfo, trS("Write logon info")}, + {AcePermission_ReadPersonalInfo, trS("Read personal info")}, + {AcePermission_WritePersonalInfo, trS("Write personal info")}, + {AcePermission_ReadPhoneAndMailOptions, trS("Read phone and mail options")}, + {AcePermission_WritePhoneAndMailOptions, trS("Write phone and mail options")}, + {AcePermission_ReadPrivateInfo, trS("Read private info")}, + {AcePermission_WritePrivateInfo, trS("Write private info")}, + {AcePermission_ReadPublicInfo, trS("Read public info")}, + {AcePermission_WritePublicInfo, trS("Write public info")}, + {AcePermission_ReadRemoteAccessInfo, trS("Read remote access info")}, + {AcePermission_WriteRemoteAccessInfo, trS("Write remote access info")}, + {AcePermission_ReadTerminalServerLicenseServer, trS("Read terminal server license server")}, + {AcePermission_WriteTerminalServerLicenseServer, trS("Write terminal server license server")}, + {AcePermission_ReadWebInfo, trS("Read web info")}, + {AcePermission_WriteWebInfo, trS("Write web info")}, +}; + +SecurityTab::SecurityTab() { + ignore_item_changed_signal = false; + + trustee_model = new QStandardItemModel(0, 1, this); + + trustee_view = new QTreeView(this); + trustee_view->setHeaderHidden(true); + trustee_view->setModel(trustee_model); + trustee_view->setEditTriggers(QAbstractItemView::NoEditTriggers); + trustee_view->sortByColumn(0, Qt::AscendingOrder); + trustee_view->setSortingEnabled(true); + trustee_view->setSelectionMode(QAbstractItemView::SingleSelection); + + auto trustee_buttonbox = new QDialogButtonBox(); + auto add_trustee_button = trustee_buttonbox->addButton(tr("Add"), QDialogButtonBox::ActionRole); + auto remove_trustee_button = trustee_buttonbox->addButton(tr("Remove"), QDialogButtonBox::ActionRole); + + ace_model = new QStandardItemModel(0, AceColumn_COUNT, this); + set_horizontal_header_labels_from_map(ace_model, { + {AceColumn_Name, tr("Name")}, + {AceColumn_Allowed, tr("Allowed")}, + {AceColumn_Denied, tr("Denied")}, + }); + + // Fill ace model + for (const AcePermission &permission : all_permissions_list) { + const QList row = make_item_row(AceColumn_COUNT); + + const QString mask_string = ace_permission_to_name_map[permission]; + row[AceColumn_Name]->setText(mask_string); + + row[AceColumn_Allowed]->setCheckable(true); + row[AceColumn_Denied]->setCheckable(true); + + row[0]->setData(permission, AcePermissionItemRole_Permission); + + ace_model->appendRow(row); + } + + permission_item_map = + [&]() { + QHash> out; + + for (int row = 0; row < ace_model->rowCount(); row++) { + QStandardItem *main_item = ace_model->item(row, 0); + const AcePermission permission = (AcePermission) main_item->data(AcePermissionItemRole_Permission).toInt(); + + const QList column_list = { + AceColumn_Allowed, + AceColumn_Denied, + }; + + for (const AceColumn &column : column_list) { + QStandardItem *item = ace_model->item(row, column); + out[permission][column] = item; + } + } + + return out; + }(); + + ace_view = new QTreeView(this); + ace_view->setModel(ace_model); + ace_view->setEditTriggers(QAbstractItemView::NoEditTriggers); + ace_view->setColumnWidth(AceColumn_Name, 400); + + trustee_label = new QLabel(); + + const auto layout = new QVBoxLayout(); + setLayout(layout); + layout->addWidget(trustee_view); + layout->addWidget(trustee_buttonbox); + layout->addWidget(trustee_label); + layout->addWidget(ace_view); + + connect( + trustee_view->selectionModel(), &QItemSelectionModel::currentChanged, + this, &SecurityTab::load_trustee_acl); + connect( + ace_model, &QStandardItemModel::itemChanged, + this, &SecurityTab::on_item_changed); + connect( + add_trustee_button, &QAbstractButton::clicked, + this, &SecurityTab::add_trustee); + connect( + remove_trustee_button, &QAbstractButton::clicked, + this, &SecurityTab::remove_trustee); +} + +void SecurityTab::load(AdInterface &ad, const AdObject &object) { + trustee_model->removeRows(0, trustee_model->rowCount()); + + // Add items to trustee model + const QList trustee_list = ad_security_get_trustee_list_from_object(&object); + for (const QByteArray &trustee : trustee_list) { + add_trustee_item(trustee, ad); + } + + trustee_model->sort(0, Qt::AscendingOrder); + + permission_state_map = ad_security_get_state_from_object(&object, g_adconfig); + + original_permission_state_map = permission_state_map; + + // Select first index + // NOTE: load_trustee_acl() is called because setCurrentIndex + // emits "current change" signal + trustee_view->selectionModel()->setCurrentIndex(trustee_model->index(0, 0), QItemSelectionModel::Current | QItemSelectionModel::ClearAndSelect); + + PropertiesTab::load(ad, object); +} + +void SecurityTab::load_trustee_acl() { + const QString label_text = + [&]() { + const QModelIndex current_index = trustee_view->currentIndex(); + QStandardItem *current_item = trustee_model->itemFromIndex(current_index); + const QString trustee_name = current_item->text(); + const QString text = QString("Permissions for %1").arg(trustee_name); + + return text; + }(); + + trustee_label->setText(label_text); + + apply_current_state_to_items(); +} + +void SecurityTab::on_item_changed(QStandardItem *item) { + // NOTE: in some cases we need to ignore this signal + if (ignore_item_changed_signal) { + return; + } + + const AceColumn column = (AceColumn) item->column(); + + const bool incorrect_column = (column != AceColumn_Allowed && column != AceColumn_Denied); + if (incorrect_column) { + return; + } + + const AcePermission permission = + [&]() { + QStandardItem *main_item = ace_model->item(item->row(), 0); + const AcePermission out = (AcePermission) main_item->data(AcePermissionItemRole_Permission).toInt(); + + return out; + }(); + + const PermissionState new_state = + [&]() { + const bool checked = (item->checkState() == Qt::Checked); + const bool allowed = (column == AceColumn_Allowed); + + if (checked) { + if (allowed) { + return PermissionState_Allowed; + } else { + return PermissionState_Denied; + } + } else { + // NOTE: the case of opposite column being + // checked while this one becomes unchecked is + // impossible, so ignore it + return PermissionState_None; + } + }(); + + const QByteArray trustee = + [&]() { + const QModelIndex current_index = trustee_view->currentIndex(); + QStandardItem *current_item = trustee_model->itemFromIndex(current_index); + const QByteArray out = current_item->data(TrusteeItemRole_Sid).toByteArray(); + + return out; + }(); + + permission_state_map = ad_security_modify(permission_state_map, trustee, permission, new_state); + apply_current_state_to_items(); + + emit edited(); +} + +QStandardItem *SecurityTab::get_item(const AcePermission permission, const AceColumn column) { + return permission_item_map[permission][column]; +} + +bool SecurityTab::set_trustee(const QString &trustee_name) { + const QList item_list = trustee_model->findItems(trustee_name); + + if (item_list.isEmpty()) { + return false; + } + + const QStandardItem *item = item_list[0]; + trustee_view->setCurrentIndex(item->index()); + + return true; +} + +bool SecurityTab::apply(AdInterface &ad, const QString &target) { + const bool modified = (original_permission_state_map != permission_state_map); + if (!modified) { + return true; + } + + const bool apply_success = attribute_replace_security_descriptor(&ad, target, permission_state_map); + + original_permission_state_map = permission_state_map; + + return apply_success; +} + +void SecurityTab::add_trustee() { + auto dialog = new SelectObjectDialog({CLASS_USER, CLASS_GROUP}, SelectObjectDialogMultiSelection_Yes, this); + + QObject::connect( + dialog, &SelectObjectDialog::accepted, + [=]() { + AdInterface ad; + if (ad_failed(ad)) { + return; + } + + const QList selected_list = dialog->get_selected(); + + const QList current_sid_string_list = + [&]() { + QList out; + + for (int row = 0; row < trustee_model->rowCount(); row++) { + QStandardItem *item = trustee_model->item(row, 0); + const QByteArray sid = item->data(TrusteeItemRole_Sid).toByteArray(); + const QString sid_string = object_sid_display_value(sid); + + out.append(sid_string); + } + + return out; + }(); + + bool added_anything = false; + + for (const QString &dn : selected_list) { + const AdObject object = ad.search_object(dn, {ATTRIBUTE_OBJECT_SID}); + const QByteArray sid = object.get_value(ATTRIBUTE_OBJECT_SID); + const QString sid_string = object_sid_display_value(sid); + + const bool trustee_already_in_list = (current_sid_string_list.contains(sid_string)); + if (trustee_already_in_list) { + continue; + } + + add_trustee_item(sid, ad); + added_anything = true; + } + + if (added_anything) { + trace(); + + emit edited(); + } + + const bool failed_to_add_because_already_exists = (!added_anything && !selected_list.isEmpty()); + if (failed_to_add_because_already_exists) { + trace(); + QMessageBox::warning(this, tr("Error"), tr("Failed to add some trustee's because they are already in the list.")); + } + }); + + dialog->open(); +} + +void SecurityTab::remove_trustee() { + QItemSelectionModel *selection_model = trustee_view->selectionModel(); + const QList selected_list = persistent_index_list(selection_model->selectedRows()); + + for (const QPersistentModelIndex &index : selected_list) { + const QByteArray sid = index.data(TrusteeItemRole_Sid).toByteArray(); + permission_state_map.remove(sid); + + trustee_model->removeRow(index.row()); + } + + if (!selected_list.isEmpty()) { + emit edited(); + } +} + +void SecurityTab::add_trustee_item(const QByteArray &sid, AdInterface &ad) { + auto item = new QStandardItem(); + + const QString name = ad_security_get_trustee_name(ad, sid); + item->setText(name); + + item->setData(sid, TrusteeItemRole_Sid); + + trustee_model->appendRow(item); +} + +// NOTE: a flag is set to avoid triggering on_item_changed() +// slot due to setCheckState() calls. Otherwise it would +// recurse and do all kinds of bad stuff. +void SecurityTab::apply_current_state_to_items() { + ignore_item_changed_signal = true; + + const QByteArray trustee = + [&]() { + const QModelIndex current_index = trustee_view->currentIndex(); + QStandardItem *current_item = trustee_model->itemFromIndex(current_index); + const QByteArray out = current_item->data(TrusteeItemRole_Sid).toByteArray(); + + return out; + }(); + + for (const AcePermission &permission : all_permissions) { + QStandardItem *allowed = permission_item_map[permission][AceColumn_Allowed]; + QStandardItem *denied = permission_item_map[permission][AceColumn_Denied]; + const PermissionState state = permission_state_map[trustee][permission]; + + switch (state) { + case PermissionState_None: { + allowed->setCheckState(Qt::Unchecked); + denied->setCheckState(Qt::Unchecked); + break; + }; + case PermissionState_Allowed: { + allowed->setCheckState(Qt::Checked); + denied->setCheckState(Qt::Unchecked); + break; + } + case PermissionState_Denied: { + allowed->setCheckState(Qt::Unchecked); + denied->setCheckState(Qt::Checked); + break; + } + } + } + + ignore_item_changed_signal = false; +} diff --git a/src/admc/tabs/security_tab.h b/src/admc/tabs/security_tab.h new file mode 100644 index 00000000..2ccf6977 --- /dev/null +++ b/src/admc/tabs/security_tab.h @@ -0,0 +1,84 @@ +/* + * ADMC - AD Management Center + * + * Copyright (C) 2020 BaseALT Ltd. + * + * 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 SECURITY_TAB_H +#define SECURITY_TAB_H + +#include "tabs/properties_tab.h" + +#include "ad_defines.h" + +class QTreeView; +class QStandardItemModel; +class QStandardItem; +class QLabel; + +enum AceColumn { + AceColumn_Name, + AceColumn_Allowed, + AceColumn_Denied, + + AceColumn_COUNT, +}; + +enum AcePermissionItemRole { + AcePermissionItemRole_Permission = Qt::UserRole, +}; + +extern const QList all_permissions_list; +extern const QSet all_permissions; +extern const QSet access_permissions; +extern const QSet read_prop_permissions; +extern const QSet write_prop_permissions; +extern const QHash ace_permission_to_name_map; + +class SecurityTab final : public PropertiesTab { +Q_OBJECT + +public: + SecurityTab(); + void load(AdInterface &ad, const AdObject &object) override; + bool apply(AdInterface &ad, const QString &target) override; + + // NOTE: f-ns for testings + QStandardItem *get_item(const AcePermission permission, const AceColumn column); + bool set_trustee(const QString &trustee_name); + +private slots: + void load_trustee_acl(); + void on_item_changed(QStandardItem *item); + +private: + QTreeView *trustee_view; + QStandardItemModel *trustee_model; + QTreeView *ace_view; + QStandardItemModel *ace_model; + QLabel *trustee_label; + QHash> permission_item_map; + QHash> original_permission_state_map; + QHash> permission_state_map; + bool ignore_item_changed_signal; + + void add_trustee(); + void remove_trustee(); + void add_trustee_item(const QByteArray &sid, AdInterface &ad); + void apply_current_state_to_items(); +}; + +#endif /* SECURITY_TAB_H */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a5d4b4a8..80690e31 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -41,6 +41,7 @@ set(TEST_TARGETS admc_test_gplink admc_test_select_base_widget admc_test_filter_widget + admc_test_security_tab ) foreach(target ${TEST_TARGETS}) diff --git a/tests/admc_test.cpp b/tests/admc_test.cpp index 0578f8c9..aeb6a6c3 100644 --- a/tests/admc_test.cpp +++ b/tests/admc_test.cpp @@ -43,6 +43,12 @@ void ADMCTest::initTestCase() { g_adconfig->load(ad, QLocale(QLocale::English)); AdInterface::set_permanent_adconfig(g_adconfig); + // TODO: temp band-aid. A proper solution would be to + // switch to using a pointer for AD and then + // initializing it here after loading adconfig. This way + // set_adconfig() won't be needed. + ad.set_adconfig(g_adconfig); + // Cleanup before all tests in-case this test suite was // previously interrupted and a cleanup wasn't performed cleanup(); diff --git a/tests/admc_test.h b/tests/admc_test.h index 8c59bf63..276a54b8 100644 --- a/tests/admc_test.h +++ b/tests/admc_test.h @@ -52,7 +52,7 @@ public slots: // cleanup() are special slots called by QTest. // Called before first test - void initTestCase(); + virtual void initTestCase(); // Called after last test void cleanupTestCase(); diff --git a/tests/admc_test_ad_interface.cpp b/tests/admc_test_ad_interface.cpp index 3ac95241..957e26b1 100644 --- a/tests/admc_test_ad_interface.cpp +++ b/tests/admc_test_ad_interface.cpp @@ -147,7 +147,7 @@ void ADMCTestAdInterface::user_set_account_option() { const bool success = ad.user_set_account_option(user_dn, option, true); const AdObject object = ad.search_object(user_dn); - const bool option_set = object.get_account_option(option); + const bool option_set = object.get_account_option(option, ad.adconfig()); QVERIFY(option_set); } } diff --git a/tests/admc_test_object_menu.cpp b/tests/admc_test_object_menu.cpp index b3b11e49..b6e4f067 100644 --- a/tests/admc_test_object_menu.cpp +++ b/tests/admc_test_object_menu.cpp @@ -325,7 +325,7 @@ void ADMCTestObjectMenu::object_menu_disable_enable_account() { // Check that final disabled state has changed const AdObject object = ad.search_object(dn); - const bool final_disabled_state = object.get_account_option(AccountOption_Disabled); + const bool final_disabled_state = object.get_account_option(AccountOption_Disabled, ad.adconfig()); const bool disabled_state_changed = (final_disabled_state != initial_disabled_state); const QString error_text = diff --git a/tests/admc_test_security_tab.cpp b/tests/admc_test_security_tab.cpp new file mode 100644 index 00000000..a81e5333 --- /dev/null +++ b/tests/admc_test_security_tab.cpp @@ -0,0 +1,335 @@ +/* + * ADMC - AD Management Center + * + * Copyright (C) 2020 BaseALT Ltd. + * + * 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 "admc_test_security_tab.h" + +#include "tabs/security_tab.h" +#include "samba/ndr_security.h" + +#include +#include +#include +#include +#include + +void ADMCTestSecurityTab::init() { + ADMCTest::init(); + + security_tab = new SecurityTab(); + + // Create test user + const QString name = TEST_USER; + test_user_dn = test_object_dn(name, CLASS_USER); + const bool create_success = ad.object_add(test_user_dn, CLASS_USER); + QVERIFY(create_success); + + const AdObject object = ad.search_object(test_user_dn); + + security_tab->load(ad, object); + + auto layout = new QVBoxLayout(); + parent_widget->setLayout(layout); + layout->addWidget(security_tab); + + parent_widget->show(); + QVERIFY(QTest::qWaitForWindowExposed(parent_widget, 1000)); +} + +// NOTE: just checking that the default security descriptor +// is laoded correctly. Creating custom security descriptors +// is too complicated at the moment. +void ADMCTestSecurityTab::load() { + auto test_allowed = + [&](const QString &trustee_name, const QSet allowed_set) { + QVERIFY(security_tab->set_trustee(trustee_name)); + + const QSet none_set = all_permissions - allowed_set; + QVERIFY2(state_is(allowed_set, PermissionState_Allowed), qPrintable(trustee_name)); + QVERIFY2(state_is(none_set, PermissionState_None), qPrintable(trustee_name)); + }; + + test_allowed("Account Operators", all_permissions); + + test_allowed("Administrators", + [&]() { + QSet out = all_permissions; + out -= AcePermission_FullControl; + out -= AcePermission_DeleteChild; + + return out; + }()); + + test_allowed("Authenticated Users", + [&]() { + QSet out; + out += AcePermission_ReadGeneralInfo; + out += AcePermission_ReadPersonalInfo; + out += AcePermission_ReadPublicInfo; + out += AcePermission_ReadWebInfo; + + return out; + }()); + + test_allowed("Cert Publishers", {}); + + test_allowed("Domain Admins", all_permissions); + + test_allowed("ENTERPRISE DOMAIN CONTROLLERS", {}); + + test_allowed("Enterprise Admins", all_permissions); + + test_allowed("Everyone", + [&]() { + QSet out; + out += AcePermission_ChangePassword; + + return out; + }()); + + test_allowed("Pre-Windows 2000 Compatible Access", + [&]() { + QSet out; + out += AcePermission_ReadAccountRestrictions; + out += AcePermission_ReadGeneralInfo; + out += AcePermission_ReadGroupMembership; + out += AcePermission_ReadLogonInfo; + out += AcePermission_ReadRemoteAccessInfo; + + return out; + }()); + + test_allowed("RAS and IAS Servers", + [&]() { + QSet out; + out += AcePermission_ReadAccountRestrictions; + out += AcePermission_ReadGroupMembership; + out += AcePermission_ReadLogonInfo; + out += AcePermission_ReadRemoteAccessInfo; + + return out; + }()); + + test_allowed("SELF", + [&]() { + QSet out; + out += AcePermission_Read; + out += read_prop_permissions; + out += AcePermission_ChangePassword; + out += AcePermission_ReceiveAs; + out += AcePermission_SendAs; + out += AcePermission_WritePersonalInfo; + out += AcePermission_WritePhoneAndMailOptions; + out += AcePermission_WritePrivateInfo; + out += AcePermission_WriteWebInfo; + + return out; + }()); + + test_allowed("SYSTEM", all_permissions); + + test_allowed("Terminal Server License Servers", + [&]() { + QSet out; + out += AcePermission_ReadTerminalServerLicenseServer; + out += AcePermission_WriteTerminalServerLicenseServer; + + return out; + }()); + + test_allowed("Windows Authorization Access Group", {}); +} + +// When you allow some perm then deny it, the allow checkbox +// should become unchecked, aka they are exclusive. +void ADMCTestSecurityTab::allow_then_deny() { + uncheck_all_permissions(); + + // NOTE: permission doesn't matter, just picked some random one + const AcePermission permission = AcePermission_SendAs; + set_permission_state({permission}, AceColumn_Allowed, Qt::Checked); + QVERIFY(state_is({permission}, PermissionState_Allowed)); + + set_permission_state({permission}, AceColumn_Denied, Qt::Checked); + QVERIFY(state_is({permission}, PermissionState_Denied)); +} + +// Allowing full should allow every permission +void ADMCTestSecurityTab::allow_full() { + uncheck_all_permissions(); + + QVERIFY(state_is(all_permissions, PermissionState_None)); + + set_permission_state({AcePermission_FullControl}, AceColumn_Allowed, Qt::Checked); + + QVERIFY(state_is(all_permissions, PermissionState_Allowed)); +} + +// Allowing full and denying read, should allow everything +// except read permissions which should be denied. +void ADMCTestSecurityTab::allow_full_deny_read() { + uncheck_all_permissions(); + + set_permission_state({AcePermission_FullControl}, AceColumn_Allowed, Qt::Checked); + set_permission_state({AcePermission_Read}, AceColumn_Denied, Qt::Checked); + + QVERIFY(state_is({AcePermission_FullControl}, PermissionState_None)); + QVERIFY(state_is(access_permissions, PermissionState_Allowed)); + QVERIFY(state_is(write_prop_permissions, PermissionState_Allowed)); + + QVERIFY(state_is({AcePermission_Read}, PermissionState_Denied)); + QVERIFY(state_is(read_prop_permissions, PermissionState_Denied)); +} + +// Unchecking read while full is allowed, should uncheck +// full and nothing else. +void ADMCTestSecurityTab::allow_full_uncheck_read() { + uncheck_all_permissions(); + + set_permission_state({AcePermission_FullControl}, AceColumn_Allowed, Qt::Checked); + set_permission_state({AcePermission_Read}, AceColumn_Allowed, Qt::Unchecked); + + QVERIFY(state_is({AcePermission_FullControl}, PermissionState_None)); + QVERIFY(state_is(access_permissions, PermissionState_Allowed)); + QVERIFY(state_is(write_prop_permissions, PermissionState_Allowed)); + QVERIFY(state_is(read_prop_permissions, PermissionState_Allowed)); + + QVERIFY(state_is({AcePermission_Read}, PermissionState_None)); +} + +// Unchecking a read prop while read is allowed, should +// uncheck read and nothing else. +void ADMCTestSecurityTab::allow_read_uncheck_read_prop() { + uncheck_all_permissions(); + + set_permission_state({AcePermission_Read}, AceColumn_Allowed, Qt::Checked); + set_permission_state({AcePermission_ReadWebInfo}, AceColumn_Allowed, Qt::Unchecked); + + QVERIFY(state_is({AcePermission_Read}, PermissionState_None)); + + QVERIFY(state_is((read_prop_permissions - QSet{AcePermission_ReadWebInfo}), PermissionState_Allowed)); +} + +// Denying a read prop while read is allowed, should +// uncheck read and deny that permission. +void ADMCTestSecurityTab::allow_read_deny_read_prop() { + uncheck_all_permissions(); + + set_permission_state({AcePermission_Read}, AceColumn_Allowed, Qt::Checked); + set_permission_state({AcePermission_ReadWebInfo}, AceColumn_Denied, Qt::Checked); + + QVERIFY(state_is({AcePermission_Read}, PermissionState_None)); + QVERIFY(state_is({AcePermission_ReadWebInfo}, PermissionState_Denied)); + + QVERIFY(state_is((read_prop_permissions - QSet{AcePermission_ReadWebInfo}), PermissionState_Allowed)); +} + +void ADMCTestSecurityTab::apply() { + QVERIFY(security_tab->set_trustee("Cert Publishers")); + + // Check/uncheck some permissions in the tab + const QSet allowed_set = { + AcePermission_CreateChild, + AcePermission_ReadPersonalInfo, + }; + const QSet denied_set = { + AcePermission_WriteWebInfo, + AcePermission_WritePersonalInfo, + AcePermission_DeleteChild, + }; + const QSet none_set = all_permissions - allowed_set - denied_set; + uncheck_all_permissions(); + set_permission_state(allowed_set, AceColumn_Allowed, Qt::Checked); + set_permission_state(denied_set, AceColumn_Denied, Qt::Checked); + + + // Apply + const bool apply_success = security_tab->apply(ad, test_user_dn); + QVERIFY(apply_success); + + // Reload tab + const AdObject updated_object = ad.search_object(test_user_dn); + security_tab->load(ad, updated_object); + + // Verify that state loaded correctly + QVERIFY(security_tab->set_trustee("Cert Publishers")); + QVERIFY(state_is(allowed_set, PermissionState_Allowed)); + QVERIFY(state_is(denied_set, PermissionState_Denied)); + QVERIFY(state_is(none_set, PermissionState_None)); +} + +void ADMCTestSecurityTab::uncheck_all_permissions() { + set_permission_state(all_permissions, AceColumn_Allowed, Qt::Unchecked); + set_permission_state(all_permissions, AceColumn_Denied, Qt::Unchecked); +} + +bool ADMCTestSecurityTab::state_is(const QSet &permission_set, const PermissionState state) const { + const QSet &checked_columns = + [&]() -> QSet { + switch (state) { + case PermissionState_Allowed: return {AceColumn_Allowed}; + case PermissionState_Denied: return {AceColumn_Denied}; + case PermissionState_None: return {}; + } + return {}; + }(); + + for (const AcePermission &permission : permission_set) { + const QList column_list = { + AceColumn_Allowed, + AceColumn_Denied, + }; + + for (const AceColumn &column : column_list) { + QStandardItem *item = security_tab->get_item(permission, column); + + const bool should_be_checked = checked_columns.contains(column); + const bool is_checked = (item->checkState() == Qt::Checked); + const bool state_is_correct = (is_checked == should_be_checked); + + if (!state_is_correct) { + const QString permission_name = ace_permission_to_name_map[permission]; + const QString column_name = + [&]() { + switch (column) { + case AceColumn_Allowed: return "Allowed"; + case AceColumn_Denied: return "Denied"; + default: break; + } + + return "unknown"; + }(); + + qInfo().noquote() << QString("Incorrect state:\n\tpermission = %1\n\tcolumn = %2\n\tcurrent state = %3\n\tcorrect state = %4").arg(permission_name, column_name, QString::number(is_checked), QString::number(should_be_checked)); + + return false; + } + } + } + + return true; +} + +void ADMCTestSecurityTab::set_permission_state(const QSet &permission_set, const AceColumn column, const Qt::CheckState state) { + for (const AcePermission &permission : permission_set) { + QStandardItem *item = security_tab->get_item(permission, column); + item->setCheckState(state); + } +} + +QTEST_MAIN(ADMCTestSecurityTab) diff --git a/tests/admc_test_security_tab.h b/tests/admc_test_security_tab.h new file mode 100644 index 00000000..35a76531 --- /dev/null +++ b/tests/admc_test_security_tab.h @@ -0,0 +1,53 @@ +/* + * ADMC - AD Management Center + * + * Copyright (C) 2020 BaseALT Ltd. + * + * 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 ADMC_TEST_SECURITY_TAB_H +#define ADMC_TEST_SECURITY_TAB_H + +#include "admc_test.h" + +#include "tabs/security_tab.h" + +class SecurityTab; + +class ADMCTestSecurityTab : public ADMCTest { +Q_OBJECT + +private slots: + void init() override; + + void load(); + void allow_then_deny(); + void allow_full(); + void allow_full_deny_read(); + void allow_full_uncheck_read(); + void allow_read_uncheck_read_prop(); + void allow_read_deny_read_prop(); + void apply(); + +private: + SecurityTab *security_tab; + QString test_user_dn; + + void uncheck_all_permissions(); + void set_permission_state(const QSet &permission_set, const AceColumn column, const Qt::CheckState state); + bool state_is(const QSet &permission_set, const PermissionState state) const; +}; + +#endif /* ADMC_TEST_SECURITY_TAB_H */