mirror of
https://github.com/altlinux/admc.git
synced 2025-03-12 12:58:20 +03:00
commit
7048f9da03
@ -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
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
600
src/adldap/ad_security.cpp
Normal 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>> ¤t, 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
53
src/adldap/ad_security.h
Normal 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>> ¤t, const QByteArray &trustee, const AcePermission permission, const PermissionState new_state);
|
||||
QString ad_security_get_trustee_name(AdInterface &ad, const QByteArray &trustee);
|
||||
bool attribute_replace_security_descriptor(AdInterface *ad, const QString &dn, const QHash<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 */
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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_*/
|
||||
|
147
src/adldap/samba/gp_manage.c
Normal file
147
src/adldap/samba/gp_manage.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
130
src/adldap/samba/libsmb_xattr.c
Normal file
130
src/adldap/samba/libsmb_xattr.c
Normal 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));
|
||||
}
|
42
src/adldap/samba/libsmb_xattr.h
Normal file
42
src/adldap/samba/libsmb_xattr.h
Normal 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
185
src/adldap/samba/misc.h
Normal 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
890
src/adldap/samba/ndr_misc.c
Normal 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 */
|
76
src/adldap/samba/ndr_misc.h
Normal file
76
src/adldap/samba/ndr_misc.h
Normal 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
@ -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 */
|
||||
|
@ -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 */
|
||||
|
705
src/adldap/samba/security_descriptor.c
Normal file
705
src/adldap/samba/security_descriptor.c
Normal 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;
|
||||
}
|
105
src/adldap/samba/security_descriptor.h
Normal file
105
src/adldap/samba/security_descriptor.h
Normal 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
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
419
src/admc/tabs/security_tab.cpp
Normal file
419
src/admc/tabs/security_tab.cpp
Normal 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;
|
||||
}
|
84
src/admc/tabs/security_tab.h
Normal file
84
src/admc/tabs/security_tab.h
Normal 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 */
|
@ -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})
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 =
|
||||
|
335
tests/admc_test_security_tab.cpp
Normal file
335
tests/admc_test_security_tab.cpp
Normal 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)
|
53
tests/admc_test_security_tab.h
Normal file
53
tests/admc_test_security_tab.h
Normal 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 */
|
Loading…
x
Reference in New Issue
Block a user