mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
Add nt_token_check_sid convenience function. Map NT_USER_TOKEN to struct security_token. Fix build errors.
Signed-off-by: Günther Deschner <gd@samba.org>
This commit is contained in:
parent
ff33d50fab
commit
68ff179b29
@ -586,7 +586,7 @@ NTSTATUS init_gp_extensions(TALLOC_CTX *mem_ctx)
|
||||
}
|
||||
|
||||
if (!reg_ctx) {
|
||||
struct nt_user_token *token;
|
||||
NT_USER_TOKEN *token;
|
||||
|
||||
token = registry_create_system_token(mem_ctx);
|
||||
NT_STATUS_HAVE_NO_MEMORY(token);
|
||||
@ -670,7 +670,7 @@ void debug_gpext_header(int lvl,
|
||||
NTSTATUS process_gpo_list_with_extension(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32_t flags,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct GROUP_POLICY_OBJECT *gpo_list,
|
||||
const char *extension_guid,
|
||||
const char *snapin_guid)
|
||||
@ -684,7 +684,7 @@ NTSTATUS process_gpo_list_with_extension(ADS_STRUCT *ads,
|
||||
NTSTATUS gpext_process_extension(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32_t flags,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct registry_key *root_key,
|
||||
struct GROUP_POLICY_OBJECT *gpo,
|
||||
const char *extension_guid,
|
||||
|
@ -65,7 +65,7 @@ struct gp_extension_methods {
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32_t flags,
|
||||
struct registry_key *root_key,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct GROUP_POLICY_OBJECT *gpo,
|
||||
const char *extension_guid,
|
||||
const char *snapin_guid);
|
||||
@ -73,7 +73,7 @@ struct gp_extension_methods {
|
||||
NTSTATUS (*process_group_policy2)(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32_t flags,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct GROUP_POLICY_OBJECT *gpo_list,
|
||||
const char *extension_guid);
|
||||
|
||||
@ -109,14 +109,14 @@ void debug_gpext_header(int lvl,
|
||||
NTSTATUS process_gpo_list_with_extension(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32_t flags,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct GROUP_POLICY_OBJECT *gpo_list,
|
||||
const char *extension_guid,
|
||||
const char *snapin_guid);
|
||||
NTSTATUS gpext_process_extension(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32_t flags,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct registry_key *root_key,
|
||||
struct GROUP_POLICY_OBJECT *gpo,
|
||||
const char *extension_guid,
|
||||
|
17
libgpo/gpo.h
17
libgpo/gpo.h
@ -153,7 +153,7 @@ struct gp_registry_entries {
|
||||
};
|
||||
|
||||
struct gp_registry_context {
|
||||
const struct nt_user_token *token;
|
||||
const NT_USER_TOKEN *token;
|
||||
const char *path;
|
||||
struct registry_key *curr_key;
|
||||
};
|
||||
@ -169,12 +169,14 @@ struct cli_state;
|
||||
/* The following definitions come from libgpo/gpo_fetch.c */
|
||||
|
||||
NTSTATUS gpo_explode_filesyspath(TALLOC_CTX *mem_ctx,
|
||||
const char *cache_path,
|
||||
const char *file_sys_path,
|
||||
char **server,
|
||||
char **service,
|
||||
char **nt_path,
|
||||
char **unix_path);
|
||||
NTSTATUS gpo_fetch_files(TALLOC_CTX *mem_ctx,
|
||||
const char *cache_path,
|
||||
struct cli_state *cli,
|
||||
struct GROUP_POLICY_OBJECT *gpo);
|
||||
NTSTATUS gpo_get_sysvol_gpt_version(TALLOC_CTX *mem_ctx,
|
||||
@ -209,18 +211,18 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
|
||||
ADS_STATUS ads_get_sid_token(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *dn,
|
||||
struct nt_user_token **token);
|
||||
NT_USER_TOKEN **token);
|
||||
ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *dn,
|
||||
uint32_t flags,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct GROUP_POLICY_OBJECT **gpo_list);
|
||||
|
||||
/* The following definitions come from libgpo/gpo_sec.c */
|
||||
|
||||
NTSTATUS gpo_apply_security_filtering(const struct GROUP_POLICY_OBJECT *gpo,
|
||||
const struct nt_user_token *token);
|
||||
const NT_USER_TOKEN *token);
|
||||
|
||||
/* The following definitions come from libgpo/gpo_util.c */
|
||||
|
||||
@ -239,19 +241,20 @@ void dump_gpo_list(ADS_STRUCT *ads,
|
||||
void dump_gplink(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct GP_LINK *gp_link);
|
||||
ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct registry_key *root_key,
|
||||
struct GROUP_POLICY_OBJECT *gpo,
|
||||
const char *extension_guid_filter,
|
||||
uint32_t flags);
|
||||
ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct GROUP_POLICY_OBJECT *gpo_list,
|
||||
const char *extensions_guid_filter,
|
||||
uint32_t flags);
|
||||
NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *cache_path,
|
||||
uint32_t flags,
|
||||
struct GROUP_POLICY_OBJECT *gpo,
|
||||
struct cli_state **cli_out);
|
||||
@ -271,7 +274,7 @@ NTSTATUS gp_find_file(TALLOC_CTX *mem_ctx,
|
||||
ADS_STATUS gp_get_machine_token(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *dn,
|
||||
struct nt_user_token **token);
|
||||
NT_USER_TOKEN **token);
|
||||
|
||||
|
||||
#include "../libgpo/gpext/gpext.h"
|
||||
|
@ -26,6 +26,7 @@
|
||||
****************************************************************/
|
||||
|
||||
NTSTATUS gpo_explode_filesyspath(TALLOC_CTX *mem_ctx,
|
||||
const char *cache_path,
|
||||
const char *file_sys_path,
|
||||
char **server,
|
||||
char **service,
|
||||
@ -61,11 +62,15 @@ NTSTATUS gpo_explode_filesyspath(TALLOC_CTX *mem_ctx,
|
||||
|
||||
if ((path = talloc_asprintf(mem_ctx,
|
||||
"%s/%s",
|
||||
cache_path(GPO_CACHE_DIR),
|
||||
cache_path,
|
||||
file_sys_path)) == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
#if _SAMBA_BUILD_ == 4
|
||||
path = string_sub_talloc(mem_ctx, path, "\\", "/");
|
||||
#else
|
||||
path = talloc_string_sub(mem_ctx, path, "\\", "/");
|
||||
#endif
|
||||
if (!path) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
@ -82,16 +87,16 @@ NTSTATUS gpo_explode_filesyspath(TALLOC_CTX *mem_ctx,
|
||||
****************************************************************/
|
||||
|
||||
static NTSTATUS gpo_prepare_local_store(TALLOC_CTX *mem_ctx,
|
||||
const char *cache_path,
|
||||
const char *unix_path)
|
||||
{
|
||||
const char *top_dir = cache_path(GPO_CACHE_DIR);
|
||||
char *current_dir;
|
||||
char *tok;
|
||||
|
||||
current_dir = talloc_strdup(mem_ctx, top_dir);
|
||||
current_dir = talloc_strdup(mem_ctx, cache_path);
|
||||
NT_STATUS_HAVE_NO_MEMORY(current_dir);
|
||||
|
||||
if ((mkdir(top_dir, 0644)) < 0 && errno != EEXIST) {
|
||||
if ((mkdir(cache_path, 0644)) < 0 && errno != EEXIST) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
@ -118,6 +123,7 @@ static NTSTATUS gpo_prepare_local_store(TALLOC_CTX *mem_ctx,
|
||||
****************************************************************/
|
||||
|
||||
NTSTATUS gpo_fetch_files(TALLOC_CTX *mem_ctx,
|
||||
const char *cache_path,
|
||||
struct cli_state *cli,
|
||||
struct GROUP_POLICY_OBJECT *gpo)
|
||||
{
|
||||
@ -125,12 +131,12 @@ NTSTATUS gpo_fetch_files(TALLOC_CTX *mem_ctx,
|
||||
char *server, *service, *nt_path, *unix_path;
|
||||
char *nt_ini_path, *unix_ini_path;
|
||||
|
||||
result = gpo_explode_filesyspath(mem_ctx, gpo->file_sys_path,
|
||||
result = gpo_explode_filesyspath(mem_ctx, cache_path, gpo->file_sys_path,
|
||||
&server, &service, &nt_path,
|
||||
&unix_path);
|
||||
NT_STATUS_NOT_OK_RETURN(result);
|
||||
|
||||
result = gpo_prepare_local_store(mem_ctx, unix_path);
|
||||
result = gpo_prepare_local_store(mem_ctx, cache_path, unix_path);
|
||||
NT_STATUS_NOT_OK_RETURN(result);
|
||||
|
||||
unix_ini_path = talloc_asprintf(mem_ctx, "%s/%s", unix_path, GPT_INI);
|
||||
|
@ -551,7 +551,7 @@ static ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
|
||||
struct GP_LINK *gp_link,
|
||||
enum GPO_LINK_TYPE link_type,
|
||||
bool only_add_forced_gpos,
|
||||
const struct nt_user_token *token)
|
||||
const NT_USER_TOKEN *token)
|
||||
{
|
||||
ADS_STATUS status;
|
||||
int i;
|
||||
@ -618,7 +618,7 @@ static ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
|
||||
ADS_STATUS ads_get_sid_token(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *dn,
|
||||
struct nt_user_token **token)
|
||||
NT_USER_TOKEN **token)
|
||||
{
|
||||
ADS_STATUS status;
|
||||
DOM_SID object_sid;
|
||||
@ -627,7 +627,7 @@ ADS_STATUS ads_get_sid_token(ADS_STRUCT *ads,
|
||||
size_t num_ad_token_sids = 0;
|
||||
DOM_SID *token_sids;
|
||||
size_t num_token_sids = 0;
|
||||
struct nt_user_token *new_token = NULL;
|
||||
NT_USER_TOKEN *new_token = NULL;
|
||||
int i;
|
||||
|
||||
status = ads_get_tokensids(ads, mem_ctx, dn,
|
||||
@ -709,7 +709,7 @@ ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *dn,
|
||||
uint32_t flags,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct GROUP_POLICY_OBJECT **gpo_list)
|
||||
{
|
||||
/* (L)ocal (S)ite (D)omain (O)rganizational(U)nit */
|
||||
|
@ -18,9 +18,13 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "libcli/security/dom_sid.h"
|
||||
#if _SAMBA_BUILD_ == 4
|
||||
#include "libgpo/ads_convenience.h"
|
||||
#include "librpc/gen_ndr/security.h"
|
||||
#include "librpc/gen_ndr/ndr_misc.h"
|
||||
#include "../libgpo/gpo.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************
|
||||
****************************************************************/
|
||||
@ -75,7 +79,11 @@ static bool gpo_sd_check_agp_object(const struct security_ace *ace)
|
||||
|
||||
static bool gpo_sd_check_agp_access_bits(uint32_t access_mask)
|
||||
{
|
||||
#if _SAMBA_BUILD_ == 4
|
||||
return (access_mask & SEC_ADS_CONTROL_ACCESS);
|
||||
#else
|
||||
return (access_mask & SEC_RIGHTS_EXTENDED);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -96,14 +104,18 @@ static bool gpo_sd_check_read_access_bits(uint32_t access_mask)
|
||||
****************************************************************/
|
||||
|
||||
static NTSTATUS gpo_sd_check_ace_denied_object(const struct security_ace *ace,
|
||||
const struct nt_user_token *token)
|
||||
const NT_USER_TOKEN *token)
|
||||
{
|
||||
char *sid_str;
|
||||
|
||||
if (gpo_sd_check_agp_object(ace) &&
|
||||
gpo_sd_check_agp_access_bits(ace->access_mask) &&
|
||||
nt_token_check_sid(&ace->trustee, token)) {
|
||||
sid_str = dom_sid_string(NULL, &ace->trustee);
|
||||
DEBUG(10,("gpo_sd_check_ace_denied_object: "
|
||||
"Access denied as of ace for %s\n",
|
||||
sid_string_dbg(&ace->trustee)));
|
||||
sid_str));
|
||||
talloc_free(sid_str);
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
@ -114,14 +126,19 @@ static NTSTATUS gpo_sd_check_ace_denied_object(const struct security_ace *ace,
|
||||
****************************************************************/
|
||||
|
||||
static NTSTATUS gpo_sd_check_ace_allowed_object(const struct security_ace *ace,
|
||||
const struct nt_user_token *token)
|
||||
const NT_USER_TOKEN *token)
|
||||
{
|
||||
char *sid_str;
|
||||
|
||||
if (gpo_sd_check_agp_object(ace) &&
|
||||
gpo_sd_check_agp_access_bits(ace->access_mask) &&
|
||||
nt_token_check_sid(&ace->trustee, token)) {
|
||||
sid_str = dom_sid_string(NULL, &ace->trustee);
|
||||
DEBUG(10,("gpo_sd_check_ace_allowed_object: "
|
||||
"Access granted as of ace for %s\n",
|
||||
sid_string_dbg(&ace->trustee)));
|
||||
sid_str));
|
||||
talloc_free(sid_str);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -132,7 +149,7 @@ static NTSTATUS gpo_sd_check_ace_allowed_object(const struct security_ace *ace,
|
||||
****************************************************************/
|
||||
|
||||
static NTSTATUS gpo_sd_check_ace(const struct security_ace *ace,
|
||||
const struct nt_user_token *token)
|
||||
const NT_USER_TOKEN *token)
|
||||
{
|
||||
switch (ace->type) {
|
||||
case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
|
||||
@ -148,7 +165,7 @@ static NTSTATUS gpo_sd_check_ace(const struct security_ace *ace,
|
||||
****************************************************************/
|
||||
|
||||
NTSTATUS gpo_apply_security_filtering(const struct GROUP_POLICY_OBJECT *gpo,
|
||||
const struct nt_user_token *token)
|
||||
const NT_USER_TOKEN *token)
|
||||
{
|
||||
struct security_descriptor *sd = gpo->security_descriptor;
|
||||
struct security_acl *dacl = NULL;
|
||||
|
@ -441,7 +441,7 @@ static bool gpo_get_gp_ext_from_gpo(TALLOC_CTX *mem_ctx,
|
||||
|
||||
ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct registry_key *root_key,
|
||||
struct GROUP_POLICY_OBJECT *gpo,
|
||||
const char *extension_guid_filter,
|
||||
@ -498,7 +498,7 @@ ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads,
|
||||
|
||||
static ADS_STATUS gpo_process_gpo_list_by_ext(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct registry_key *root_key,
|
||||
struct GROUP_POLICY_OBJECT *gpo_list,
|
||||
const char *extensions_guid,
|
||||
@ -536,7 +536,7 @@ static ADS_STATUS gpo_process_gpo_list_by_ext(ADS_STRUCT *ads,
|
||||
|
||||
ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const struct nt_user_token *token,
|
||||
const NT_USER_TOKEN *token,
|
||||
struct GROUP_POLICY_OBJECT *gpo_list,
|
||||
const char *extensions_guid_filter,
|
||||
uint32_t flags)
|
||||
@ -557,7 +557,7 @@ ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
|
||||
if (!gp_ext_list) {
|
||||
return ADS_ERROR_NT(NT_STATUS_DLL_INIT_FAILED);
|
||||
}
|
||||
|
||||
#if 0 /* Needs to be replaced with new patchfile_preg calls */
|
||||
/* get the key here */
|
||||
if (flags & GPO_LIST_FLAG_MACHINE) {
|
||||
werr = gp_init_reg_ctx(mem_ctx, KEY_HKLM, REG_KEY_WRITE,
|
||||
@ -568,6 +568,7 @@ ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
|
||||
token,
|
||||
®_ctx);
|
||||
}
|
||||
#endif
|
||||
if (!W_ERROR_IS_OK(werr)) {
|
||||
gp_free_reg_ctx(reg_ctx);
|
||||
return ADS_ERROR_NT(werror_to_ntstatus(werr));
|
||||
@ -619,6 +620,7 @@ ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
|
||||
|
||||
NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *cache_path,
|
||||
uint32_t flags,
|
||||
struct GROUP_POLICY_OBJECT *gpo,
|
||||
struct cli_state **cli_out)
|
||||
@ -632,7 +634,7 @@ NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
|
||||
char *display_name = NULL;
|
||||
struct cli_state *cli = NULL;
|
||||
|
||||
result = gpo_explode_filesyspath(mem_ctx, gpo->file_sys_path,
|
||||
result = gpo_explode_filesyspath(mem_ctx, cache_path, gpo->file_sys_path,
|
||||
&server, &share, &nt_path, &unix_path);
|
||||
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
@ -683,7 +685,7 @@ NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
|
||||
*cli_out = cli;
|
||||
}
|
||||
|
||||
result = gpo_fetch_files(mem_ctx, *cli_out, gpo);
|
||||
result = gpo_fetch_files(mem_ctx, cache_path, *cli_out, gpo);
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
goto out;
|
||||
}
|
||||
@ -852,9 +854,9 @@ NTSTATUS gp_find_file(TALLOC_CTX *mem_ctx,
|
||||
ADS_STATUS gp_get_machine_token(ADS_STRUCT *ads,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *dn,
|
||||
struct nt_user_token **token)
|
||||
NT_USER_TOKEN **token)
|
||||
{
|
||||
struct nt_user_token *ad_token = NULL;
|
||||
NT_USER_TOKEN *ad_token = NULL;
|
||||
ADS_STATUS status;
|
||||
NTSTATUS ntstatus;
|
||||
|
||||
|
@ -235,6 +235,31 @@ ADS_STATUS ads_build_nt_error(NTSTATUS nt_status)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool nt_token_check_sid( const struct dom_sid *sid, const NT_USER_TOKEN *token)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!sid || !token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dom_sid_equal(sid, token->user_sid)) {
|
||||
return true;
|
||||
}
|
||||
if (dom_sid_equal(sid, token->group_sid)) {
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < token->num_sids; i++) {
|
||||
if (dom_sid_equal(sid, token->sids[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
FIXME
|
||||
Stub write functions, these do not do anything, though they should. -- Wilco
|
||||
|
@ -47,6 +47,9 @@ typedef struct {
|
||||
struct ldb_context *ldbctx;
|
||||
} ADS_STRUCT;
|
||||
|
||||
|
||||
typedef struct security_token NT_USER_TOKEN;
|
||||
|
||||
typedef struct ldb_result LDAPMessage;
|
||||
typedef void ** ADS_MODLIST;
|
||||
|
||||
@ -85,6 +88,7 @@ ADS_STATUS ads_msgfree(ADS_STRUCT *ads, LDAPMessage *res);
|
||||
NTSTATUS ads_ntstatus(ADS_STATUS status);
|
||||
ADS_STATUS ads_build_ldap_error(int ldb_error);
|
||||
ADS_STATUS ads_build_nt_error(NTSTATUS nt_status);
|
||||
bool nt_token_check_sid( const struct dom_sid *sid, const NT_USER_TOKEN *token);
|
||||
ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx);
|
||||
ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods, const char *name, const char *val);
|
||||
ADS_STATUS ads_gen_mod(ADS_STRUCT *ads, const char *mod_dn, ADS_MODLIST mods);
|
||||
|
Loading…
Reference in New Issue
Block a user