1
0
mirror of https://github.com/altlinux/admc.git synced 2025-03-12 12:58:20 +03:00

Merge pull request #210 from altlinux/security-tab

Security tab
This commit is contained in:
Dmitry Degtyarev 2021-06-09 18:02:29 +04:00 committed by GitHub
commit 7048f9da03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 5893 additions and 618 deletions

View File

@ -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 <kevl@altlinux.org> 0.5.2-alt1

View File

@ -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
)

View File

@ -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<QString, QString> out;
const QString filter = filter_CONDITION(Condition_Equals, ATTRIBUTE_OBJECT_CLASS, CLASS_CONTROL_ACCESS_RIGHT);
const QList<QString> attributes = {
ATTRIBUTE_CN,
ATTRIBUTE_RIGHTS_GUID,
};
const QString search_base = extended_rights_dn();
const QHash<QString, AdObject> 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<QString> AdConfig::get_noncontainer_classes() {
QList<QString> out = filter_classes;

View File

@ -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<QString> get_noncontainer_classes();
private:

View File

@ -53,6 +53,8 @@ public:
QHash<ObjectClass, AdObject> class_schemas;
QList<ObjectClass> add_auxiliary_classes(const QList<QString> &object_classes) const;
QHash<QString, QString> right_to_guid_map;
};
#endif /* AD_CONFIG_P_H */

View File

@ -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 */

View File

@ -23,6 +23,7 @@
#include "ad_defines.h"
#include "ad_utils.h"
#include "ad_config.h"
#include "samba/dom_sid.h"
#include <QString>
#include <QDateTime>
@ -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", "<BINARY VALUE>");
}
default: {
return QString(value);
}
@ -99,42 +102,17 @@ QString attribute_display_values(const QString &attribute, const QList<QByteArra
}
}
// TODO: replace with some library if possible. Maybe one of samba's libs has this.
// NOTE: https://ldapwiki.com/wiki/ObjectSID
QString object_sid_display_value(const QByteArray &sid) {
QString string = "S-";
// byte[0] - revision level
const int revision = sid[0];
string += QString::number(revision);
// byte[1] - count of sub-authorities
const int sub_authority_count = sid[1] & 0xFF;
// byte(2-7) - authority 48 bit Big-Endian
long authority = 0;
for (int i = 2; i <= 7; i++) {
authority |= ((long)sid[i]) << (8 * (5 - (i - 2)));
}
string += "-" + QString::number(authority);
// TODO: not sure if authority is supposed to be formatted as hex or not. Currently it matches how ADUC displays it.
// byte(8-...)
// sub-authorities 32 bit Little-Endian
int offset = 8;
const int bytes = 4;
for (int i = 0; i < sub_authority_count; i++) {
long sub_authority = 0;
for (int j = 0; j < bytes; j++) {
sub_authority |= (long)(sid[offset + j] & 0xFF) << (8 * j);
}
QString object_sid_display_value(const QByteArray &sid_bytes) {
dom_sid *sid = (dom_sid *) sid_bytes.data();
string += "-" + QString::number(sub_authority);
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
offset += bytes;
}
const char *sid_cstr = dom_sid_string(tmp_ctx, sid);
const QString out = QString(sid_cstr);
return string;
talloc_free(tmp_ctx);
return out;
}
QString large_integer_datetime_display_value(const QString &attribute, const QByteArray &value, const AdConfig *adconfig) {

View File

@ -33,5 +33,6 @@ template <typename T> class QList;
QString attribute_display_value(const QString &attribute, const QByteArray &value, const AdConfig *adconfig);
QString attribute_display_values(const QString &attribute, const QList<QByteArray> &values, const AdConfig *adconfig);
QString object_sid_display_value(const QByteArray &sid_bytes);
#endif /* ATTRIBUTE_DISPLAY_H */

View File

@ -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 <ldap.h>
#include <lber.h>
@ -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;
}

View File

@ -27,6 +27,8 @@
*/
#include <QCoreApplication>
#include <QHash>
#include <QSet>
#include "ad_defines.h"
@ -35,8 +37,9 @@ class QString;
class QByteArray;
class QDateTime;
class AdObject;
class AdConfig;
class AdConfig;
template <typename T> 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<AdMessage> messages() const;
bool any_error_messages() const;
void clear_messages();
AdConfig *adconfig() const;
// NOTE: If request attributes list is empty, all attributes are returned

View File

@ -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 <algorithm>
#include <QMap>
@ -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);

View File

@ -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;

600
src/adldap/ad_security.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <QDebug>
QByteArray dom_sid_to_bytes(const dom_sid &sid);
security_descriptor *ad_security_get_sd(const AdObject *object);
QList<security_ace *> ad_security_get_dacl(security_descriptor *sd);
QList<QByteArray> ad_security_get_trustee_list_from_sd(security_descriptor *sd);
QList<QByteArray> ad_security_get_trustee_list_from_sd(security_descriptor *sd);
QHash<QByteArray, QHash<AcePermission, PermissionState>> 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<AcePermission, uint32_t> 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<AcePermission, QString> 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<AcePermission> all_permissions_list =
[]() {
QList<AcePermission> 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<AcePermission> all_permissions = all_permissions_list.toSet();
QSet<AcePermission> get_permission_set(const uint32_t mask) {
QSet<AcePermission> 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<AcePermission> access_permissions = get_permission_set(SEC_ADS_CONTROL_ACCESS);
const QSet<AcePermission> read_prop_permissions = get_permission_set(SEC_ADS_READ_PROP);
const QSet<AcePermission> write_prop_permissions = get_permission_set(SEC_ADS_WRITE_PROP);
QHash<QByteArray, QHash<AcePermission, PermissionState>> ad_security_modify(const QHash<QByteArray, QHash<AcePermission, PermissionState>> &current, const QByteArray &trustee, const AcePermission permission, const PermissionState new_state) {
QHash<QByteArray, QHash<AcePermission, PermissionState>> out;
out = current;
auto permission_state_set =
[&](const QSet<AcePermission> &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<AcePermission> parent_permissions =
[&]() {
QSet<AcePermission> 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<AcePermission> 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<AcePermission>();
}
}();
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<QString, QString> 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<QString> attributes = {
ATTRIBUTE_DISPLAY_NAME,
ATTRIBUTE_SAMACCOUNT_NAME,
};
const auto trustee_search = ad.search(ad.adconfig()->domain_head(), SearchScope_All, filter, QList<QString>());
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<QByteArray, QHash<AcePermission, PermissionState>> &descriptor_state_arg) {
const QByteArray new_descriptor_bytes =
[&]() {
// Remove redundancy from permission state
const QHash<QByteArray, QHash<AcePermission, PermissionState>> state =
[&]() {
QHash<QByteArray, QHash<AcePermission, PermissionState>> 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<security_ace *> dacl_qlist =
[&]() {
QList<security_ace *> out;
for (const QByteArray &trustee : state.keys()) {
const QHash<AcePermission, PermissionState> 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<QByteArray> ad_security_get_trustee_list_from_object(const AdObject *object) {
security_descriptor *sd = ad_security_get_sd(object);
const QList<QByteArray> out = ad_security_get_trustee_list_from_sd(sd);
talloc_free(sd);
return out;
}
QHash<QByteArray, QHash<AcePermission, PermissionState>> 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<security_ace *> ad_security_get_dacl(security_descriptor *sd) {
QList<security_ace *> 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<QByteArray> ad_security_get_trustee_list_from_sd(security_descriptor *sd) {
QSet<QByteArray> out;
const QList<security_ace *> 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<security_ace *> ace_list =
[&]() {
QList<security_ace *> out;
const QList<security_ace *> 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<QByteArray, QHash<AcePermission, PermissionState>> ad_security_get_state_from_sd(security_descriptor *sd, AdConfig *adconfig) {
QHash<QByteArray, QHash<AcePermission, PermissionState>> out;
// Initialize to None by default
const QList<QByteArray> 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<security_ace *> 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;
}

53
src/adldap/ad_security.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/**
* Functions for working with security descriptors.
*/
#ifndef AD_SECURITY_H
#define AD_SECURITY_H
#include "ad_defines.h"
#include <QByteArray>
#include <QString>
#include <QHash>
#include <QSet>
class AdInterface;
class AdConfig;
class AdObject;
extern const QHash<AcePermission, uint32_t> ace_permission_to_mask_map;
extern const QHash<AcePermission, QString> ace_permission_to_type_map;
extern const QList<AcePermission> all_permissions_list;
extern const QSet<AcePermission> all_permissions;
extern const QSet<AcePermission> access_permissions;
extern const QSet<AcePermission> read_prop_permissions;
extern const QSet<AcePermission> write_prop_permissions;
QHash<QByteArray, QHash<AcePermission, PermissionState>> ad_security_modify(const QHash<QByteArray, QHash<AcePermission, PermissionState>> &current, 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<QByteArray, QHash<AcePermission, PermissionState>> &descriptor_state_arg);
QList<QByteArray> ad_security_get_trustee_list_from_object(const AdObject *object);
QHash<QByteArray, QHash<AcePermission, PermissionState>> ad_security_get_state_from_object(const AdObject *object, AdConfig *adconfig);
#endif /* AD_SECURITY_H */

View File

@ -19,8 +19,10 @@
*/
#include "ad_utils.h"
#include "ad_config.h"
#include "ad_display.h"
#include "samba/dom_sid.h"
#include <ldap.h>
#include <krb5.h>
@ -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<QByteArray> segment_list =
[&]() {
QList<QByteArray> out;
const QList<QString> 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;
}

View File

@ -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 */

View File

@ -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;i<dom_sid->num_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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
/*
* 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 <util/data_blob.h>
#include <gen_ndr/security.h>
/* 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_*/

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*
* 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 <string.h>
/*
* 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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*
* 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 <string.h>
#include <QDebug>
/*
* 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;
}

View File

@ -22,17 +22,21 @@
* were removed or edited.
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef GP_MANAGE_H
#define GP_MANAGE_H
extern "C" {
#include <ndr.h>
#include <gen_ndr/security.h>
#include <talloc.h>
};
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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*
* 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 <ndr.h>
#include <gen_ndr/security.h>
#include <string.h>
/*
* 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));
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*
* 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 */

185
src/adldap/samba/misc.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*
* 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 <util/data_blob.h>
#include <core/ntstatus.h>
#include <stdint.h>
// #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 */

890
src/adldap/samba/ndr_misc.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*
* 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 */

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*
* This file is a copy of private samba generated sources.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <ndr.h>
/* 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

File diff suppressed because it is too large Load Diff

View File

@ -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 <ndr.h>
#include <gen_ndr/security.h>
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 */

View File

@ -35,6 +35,7 @@
#include <stddef.h>
#include <inttypes.h>
#include <ctype.h>
#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 */

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*
* 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 <string.h>
/*
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;i<acl->num_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;i<acl->num_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;i<acl1->num_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;
}

View File

@ -0,0 +1,105 @@
/*
Unix SMB/CIFS implementation.
Samba utility functions
Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
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 <http://www.gnu.org/licenses/>.
*/
/*
* 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 <ndr.h>
#include <gen_ndr/security.h>
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

View File

@ -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

View File

@ -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);
}

View File

@ -81,9 +81,9 @@ CreateObjectDialog::CreateObjectDialog(const QString &parent_dn_arg, const QStri
const QList<AccountOption> options = {
AccountOption_PasswordExpired,
AccountOption_CantChangePassword,
AccountOption_DontExpirePassword,
AccountOption_Disabled
// TODO: AccountOption_CannotChangePass
AccountOption_Disabled,
};
QMap<AccountOption, AccountOptionEdit *> option_edits;
AccountOptionEdit::make_many(options, &option_edits, &all_edits, this);

View File

@ -19,8 +19,11 @@
*/
#include "edits/account_option_edit.h"
#include "adldap.h"
#include "utils.h"
#include "globals.h"
#include <QCheckBox>
#include <QLineEdit>
#include <QComboBox>
@ -81,7 +84,7 @@ AccountOptionEdit::AccountOptionEdit(const AccountOption option_arg, QList<Attri
}
void AccountOptionEdit::load_internal(AdInterface &ad, const AdObject &object) {
const bool option_is_set = object.get_account_option(option);
const bool option_is_set = object.get_account_option(option, g_adconfig);
check->setChecked(option_is_set);
}
@ -136,14 +139,9 @@ void account_option_setup_conflicts(const QHash<AccountOption, QCheckBox *> &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<AccountOption> other_two_options = {
AccountOption_DontExpirePassword,
// AccountOption_CantChangePassword,
AccountOption_CantChangePassword,
};
for (auto other_option : other_two_options) {

View File

@ -21,6 +21,7 @@
#include "multi_edits/account_option_multi_edit.h"
#include "edits/account_option_edit.h"
#include "globals.h"
#include <QCheckBox>
#include <QFormLayout>
@ -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) {

View File

@ -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 <QAction>
#include <QLabel>
@ -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) {

View File

@ -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);

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <QVBoxLayout>
#include <QDebug>
#include <QTreeView>
#include <QStandardItemModel>
#include <QLabel>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QPersistentModelIndex>
#include <QMessageBox>
enum TrusteeItemRole {
TrusteeItemRole_Sid = Qt::UserRole,
};
#define trS(x) QCoreApplication::translate("Security", x)
const QHash<AcePermission, QString> 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<QStandardItem *> 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<AcePermission, QHash<AceColumn, QStandardItem *>> 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<AceColumn> 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<QByteArray> 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<QStandardItem *> 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<QString> selected_list = dialog->get_selected();
const QList<QString> current_sid_string_list =
[&]() {
QList<QString> 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<QPersistentModelIndex> 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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<AcePermission> all_permissions_list;
extern const QSet<AcePermission> all_permissions;
extern const QSet<AcePermission> access_permissions;
extern const QSet<AcePermission> read_prop_permissions;
extern const QSet<AcePermission> write_prop_permissions;
extern const QHash<AcePermission, QString> 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<AcePermission, QHash<AceColumn, QStandardItem *>> permission_item_map;
QHash<QByteArray, QHash<AcePermission, PermissionState>> original_permission_state_map;
QHash<QByteArray, QHash<AcePermission, PermissionState>> 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 */

View File

@ -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})

View File

@ -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();

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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 =

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "admc_test_security_tab.h"
#include "tabs/security_tab.h"
#include "samba/ndr_security.h"
#include <QVBoxLayout>
#include <QComboBox>
#include <QPushButton>
#include <QTreeView>
#include <QStandardItemModel>
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<AcePermission> allowed_set) {
QVERIFY(security_tab->set_trustee(trustee_name));
const QSet<AcePermission> 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<AcePermission> out = all_permissions;
out -= AcePermission_FullControl;
out -= AcePermission_DeleteChild;
return out;
}());
test_allowed("Authenticated Users",
[&]() {
QSet<AcePermission> 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<AcePermission> out;
out += AcePermission_ChangePassword;
return out;
}());
test_allowed("Pre-Windows 2000 Compatible Access",
[&]() {
QSet<AcePermission> 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<AcePermission> out;
out += AcePermission_ReadAccountRestrictions;
out += AcePermission_ReadGroupMembership;
out += AcePermission_ReadLogonInfo;
out += AcePermission_ReadRemoteAccessInfo;
return out;
}());
test_allowed("SELF",
[&]() {
QSet<AcePermission> 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<AcePermission> 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>{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>{AcePermission_ReadWebInfo}), PermissionState_Allowed));
}
void ADMCTestSecurityTab::apply() {
QVERIFY(security_tab->set_trustee("Cert Publishers"));
// Check/uncheck some permissions in the tab
const QSet<AcePermission> allowed_set = {
AcePermission_CreateChild,
AcePermission_ReadPersonalInfo,
};
const QSet<AcePermission> denied_set = {
AcePermission_WriteWebInfo,
AcePermission_WritePersonalInfo,
AcePermission_DeleteChild,
};
const QSet<AcePermission> 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<AcePermission> &permission_set, const PermissionState state) const {
const QSet<AceColumn> &checked_columns =
[&]() -> QSet<AceColumn> {
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<AceColumn> 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<AcePermission> &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)

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<AcePermission> &permission_set, const AceColumn column, const Qt::CheckState state);
bool state_is(const QSet<AcePermission> &permission_set, const PermissionState state) const;
};
#endif /* ADMC_TEST_SECURITY_TAB_H */