summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/Makefile.in6
-rw-r--r--source/include/ads_protos.h95
-rw-r--r--source/include/gpo.h22
-rw-r--r--source/include/includes.h5
-rw-r--r--source/libads/ads_status.c32
-rw-r--r--source/libads/ads_struct.c4
-rw-r--r--source/libads/kerberos_verify.c4
-rw-r--r--source/libads/krb5_errs.c1
-rw-r--r--source/libads/krb5_setpw.c4
-rw-r--r--source/libads/ldap.c254
-rw-r--r--source/libads/ldap_printer.c7
-rw-r--r--source/libads/ldap_schema.c8
-rw-r--r--source/libads/ldap_user.c3
-rw-r--r--source/libads/ldap_utils.c41
-rw-r--r--source/libads/sasl.c9
-rw-r--r--source/libgpo/gpo_fetch.c194
-rw-r--r--source/libgpo/gpo_filesync.c225
-rw-r--r--source/libgpo/gpo_ldap.c (renamed from source/libads/gpo.c)129
-rw-r--r--source/libgpo/gpo_parse.c299
-rw-r--r--source/libgpo/gpo_util.c (renamed from source/libads/gpo_util.c)196
-rw-r--r--source/libsmb/clirap2.c58
-rw-r--r--source/utils/debug2html.c4
-rw-r--r--source/utils/log2pcaphex.c4
-rw-r--r--source/utils/net_ads.c706
-rw-r--r--source/utils/net_ads_gpo.c132
-rw-r--r--source/utils/net_dns.c192
-rw-r--r--source/utils/net_groupmap.c17
-rw-r--r--source/utils/net_rap.c30
-rw-r--r--source/utils/net_rpc.c4
-rw-r--r--source/utils/net_rpc_rights.c4
-rw-r--r--source/utils/net_rpc_service.c2
-rw-r--r--source/utils/net_util.c2
32 files changed, 2184 insertions, 509 deletions
diff --git a/source/Makefile.in b/source/Makefile.in
index adeb9b1b1dd..eb5cea522fa 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -260,6 +260,10 @@ LIBADDNS_OBJ0 = libaddns/dnsrecord.o libaddns/dnsutils.o libaddns/dnssock.o \
libaddns/dnsgss.o libaddns/dnsmarshall.o
LIBADDNS_OBJ = $(LIBADDNS_OBJ0) $(TALLOC_OBJ)
+LIBGPO_OBJ0 = libgpo/gpo_ldap.o libgpo/gpo_parse.o libgpo/gpo_util.o \
+ libgpo/gpo_fetch.o libgpo/gpo_filesync.o
+LIBGPO_OBJ = $(LIBGPO_OBJ0)
+
LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
libads/krb5_setpw.o libads/ldap_user.o \
libads/ads_struct.o libads/kerberos_keytab.o \
@@ -590,7 +594,7 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_domain.o utils/net_help.o \
utils/net_rpc_service.o utils/net_rpc_registry.o utils/net_usershare.o \
utils/netlookup.o utils/net_sam.o utils/net_rpc_shell.o \
utils/net_util.o utils/net_rpc_sh_acct.o utils/net_rpc_audit.o \
- utils/passwd_util.o
+ utils/passwd_util.o utils/net_dns.o utils/net_ads_gpo.o
NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
diff --git a/source/include/ads_protos.h b/source/include/ads_protos.h
new file mode 100644
index 00000000000..b5f323774d3
--- /dev/null
+++ b/source/include/ads_protos.h
@@ -0,0 +1,95 @@
+/*
+ * Prototypes for ads
+ */
+
+void ads_msgfree(ADS_STRUCT *ads, LDAPMessage *msg);
+char *ads_get_dn(ADS_STRUCT *ads, LDAPMessage *msg);
+char *ads_get_dn_canonical(ADS_STRUCT *ads, LDAPMessage *msg);
+
+char *ads_pull_string(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg,
+ const char *field);
+char **ads_pull_strings(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field,
+ size_t *num_values);
+char **ads_pull_strings_range(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field,
+ char **current_strings,
+ const char **next_attribute,
+ size_t *num_strings,
+ BOOL *more_strings);
+BOOL ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
+ uint32 *v);
+BOOL ads_pull_guid(ADS_STRUCT *ads, LDAPMessage *msg, struct GUID *guid);
+BOOL ads_pull_sid(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
+ DOM_SID *sid);
+int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field, DOM_SID **sids);
+BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field, SEC_DESC **sd);
+char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg);
+int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg,
+ const char *field,
+ enum ads_extended_dn_flags flags,
+ DOM_SID **sids);
+
+ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *machine);
+ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *printer,
+ const char *servername);
+ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res);
+ADS_STATUS ads_find_user_acct(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *user);
+
+ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
+ const char *expr,
+ const char **attrs, LDAPMessage **res);
+ADS_STATUS ads_search(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *expr, const char **attrs);
+ADS_STATUS ads_search_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn, const char **attrs);
+ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res);
+ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, LDAPMessage **res);
+ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path,
+ int scope,
+ const char *expr,
+ const char **attrs, LDAPMessage **res);
+ADS_STATUS ads_do_search_retry_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res);
+ADS_STATUS ads_search_retry(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *expr, const char **attrs);
+ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn,
+ const char **attrs);
+ADS_STATUS ads_search_retry_extended_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn,
+ const char **attrs,
+ enum ads_extended_dn_flags flags);
+ADS_STATUS ads_search_retry_sid(ADS_STRUCT *ads, LDAPMessage **res,
+ const DOM_SID *sid,
+ const char **attrs);
+
+
+LDAPMessage *ads_first_entry(ADS_STRUCT *ads, LDAPMessage *res);
+LDAPMessage *ads_next_entry(ADS_STRUCT *ads, LDAPMessage *res);
+void ads_process_results(ADS_STRUCT *ads, LDAPMessage *res,
+ BOOL(*fn)(char *, void **, void *),
+ void *data_area);
+void ads_dump(ADS_STRUCT *ads, LDAPMessage *res);
+
+ADS_STATUS ads_parse_gpo(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *res,
+ const char *gpo_dn,
+ struct GROUP_POLICY_OBJECT *gpo);
diff --git a/source/include/gpo.h b/source/include/gpo.h
index 65c96c31e6b..c3ae20dd20b 100644
--- a/source/include/gpo.h
+++ b/source/include/gpo.h
@@ -20,11 +20,11 @@
enum GPO_LINK_TYPE {
- GP_LINK_UNKOWN,
- GP_LINK_MACHINE,
- GP_LINK_SITE,
- GP_LINK_DOMAIN,
- GP_LINK_OU
+ GP_LINK_UNKOWN = 0,
+ GP_LINK_MACHINE = 1,
+ GP_LINK_SITE = 2,
+ GP_LINK_DOMAIN = 3,
+ GP_LINK_OU = 4
};
/* GPO_OPTIONS */
@@ -35,11 +35,12 @@ enum GPO_LINK_TYPE {
#define GPO_LIST_FLAG_MACHINE 0x00000001
#define GPO_LIST_FLAG_SITEONLY 0x00000002
+#define GPO_VERSION_USER(x) (x >> 16)
+#define GPO_VERSION_MACHINE(x) (x & 0xffff)
+
struct GROUP_POLICY_OBJECT {
uint32 options; /* GPFLAGS_* */
uint32 version;
- uint16 version_user;
- uint16 version_machine;
const char *ds_path;
const char *file_sys_path;
const char *display_name;
@@ -62,8 +63,8 @@ struct GROUP_POLICY_OBJECT {
/* 'gPOptions', maybe a bitmask as well */
enum GPO_INHERIT {
- GPOPTIONS_INHERIT,
- GPOPTIONS_BLOCK_INHERITANCE
+ GPOPTIONS_INHERIT = 0,
+ GPOPTIONS_BLOCK_INHERITANCE = 1
};
/* 'flags' in a 'groupPolicyContainer' object */
@@ -89,3 +90,6 @@ struct GP_EXT {
char **snapins;
char **snapins_guid;
};
+
+#define GPO_CACHE_DIR "gpo_cache"
+#define GPT_INI "GPT.INI"
diff --git a/source/include/includes.h b/source/include/includes.h
index 9301f356e13..ea639d28a9b 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -627,6 +627,7 @@ typedef int BOOL;
#include "nt_status.h"
#include "ads.h"
+#include "gpo.h"
#include "ads_dns.h"
#include "interfaces.h"
#include "trans2.h"
@@ -771,6 +772,10 @@ enum flush_reason_enum {
#include "proto.h"
#endif
+#ifdef HAVE_LDAP
+#include "ads_protos.h"
+#endif
+
/* We need this after proto.h to reference GetTimeOfDay(). */
#include "smbprofile.h"
diff --git a/source/libads/ads_status.c b/source/libads/ads_status.c
index 536ef766e37..017d38c6001 100644
--- a/source/libads/ads_status.c
+++ b/source/libads/ads_status.c
@@ -69,25 +69,29 @@ ADS_STATUS ads_build_nt_error(enum ads_error_type etype,
*/
NTSTATUS ads_ntstatus(ADS_STATUS status)
{
- if (status.error_type == ENUM_ADS_ERROR_NT){
+ switch (status.error_type) {
+ case ENUM_ADS_ERROR_NT:
return status.err.nt_status;
- }
+ case ENUM_ADS_ERROR_SYSTEM:
+ return map_nt_error_from_unix(status.err.rc);
#ifdef HAVE_LDAP
- if ((status.error_type == ENUM_ADS_ERROR_LDAP)
- && (status.err.rc == LDAP_NO_MEMORY)) {
- return NT_STATUS_NO_MEMORY;
- }
+ case ENUM_ADS_ERROR_LDAP:
+ if (status.err.rc == LDAP_SUCCESS) {
+ return NT_STATUS_OK;
+ }
+ return NT_STATUS_LDAP(status.err.rc);
#endif
#ifdef HAVE_KRB5
- if (status.error_type == ENUM_ADS_ERROR_KRB5) {
- if (status.err.rc == KRB5KDC_ERR_PREAUTH_FAILED) {
- return NT_STATUS_LOGON_FAILURE;
- } else if (status.err.rc == KRB5_KDC_UNREACH) {
- return NT_STATUS_NO_LOGON_SERVERS;
- }
- }
+ case ENUM_ADS_ERROR_KRB5:
+ return krb5_to_nt_status(status.err.rc);
#endif
- if (ADS_ERR_OK(status)) return NT_STATUS_OK;
+ default:
+ break;
+ }
+
+ if (ADS_ERR_OK(status)) {
+ return NT_STATUS_OK;
+ }
return NT_STATUS_UNSUCCESSFUL;
}
diff --git a/source/libads/ads_struct.c b/source/libads/ads_struct.c
index 7a03a2a80f6..130d86b8dc8 100644
--- a/source/libads/ads_struct.c
+++ b/source/libads/ads_struct.c
@@ -42,7 +42,7 @@ char *ads_build_path(const char *realm, const char *sep, const char *field, int
len = (numbits+1)*(strlen(field)+1) + strlen(r) + 1;
- ret = SMB_MALLOC(len);
+ ret = (char *)SMB_MALLOC(len);
if (!ret)
return NULL;
@@ -136,6 +136,8 @@ void ads_destroy(ADS_STRUCT **ads)
SAFE_FREE((*ads)->config.realm);
SAFE_FREE((*ads)->config.bind_path);
SAFE_FREE((*ads)->config.ldap_server_name);
+ SAFE_FREE((*ads)->config.server_site_name);
+ SAFE_FREE((*ads)->config.client_site_name);
SAFE_FREE((*ads)->schema.posix_uidnumber_attr);
SAFE_FREE((*ads)->schema.posix_gidnumber_attr);
diff --git a/source/libads/kerberos_verify.c b/source/libads/kerberos_verify.c
index 3aa0860809d..dc2f2a1e788 100644
--- a/source/libads/kerberos_verify.c
+++ b/source/libads/kerberos_verify.c
@@ -101,7 +101,7 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
if (strequal(entry_princ_s, valid_princ_formats[i])) {
number_matched_principals++;
p_packet->length = ticket->length;
- p_packet->data = (krb5_pointer)ticket->data;
+ p_packet->data = (char *)ticket->data;
*pp_tkt = NULL;
ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, p_packet,
@@ -228,7 +228,7 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
/* CIFS doesn't use addresses in tickets. This would break NAT. JRA */
p_packet->length = ticket->length;
- p_packet->data = (krb5_pointer)ticket->data;
+ p_packet->data = (char *)ticket->data;
/* We need to setup a auth context with each possible encoding type in turn. */
for (i=0;enctypes[i];i++) {
diff --git a/source/libads/krb5_errs.c b/source/libads/krb5_errs.c
index e73482522b8..38d34f86769 100644
--- a/source/libads/krb5_errs.c
+++ b/source/libads/krb5_errs.c
@@ -55,6 +55,7 @@ static const struct {
#if defined(KRB5KRB_ERR_RESPONSE_TOO_BIG)
{KRB5KRB_ERR_RESPONSE_TOO_BIG, NT_STATUS_PROTOCOL_UNREACHABLE},
#endif
+ {KRB5KDC_ERR_NONE, NT_STATUS_OK},
{0, NT_STATUS_OK}
};
diff --git a/source/libads/krb5_setpw.c b/source/libads/krb5_setpw.c
index 07e6320c266..c7a4b982db4 100644
--- a/source/libads/krb5_setpw.c
+++ b/source/libads/krb5_setpw.c
@@ -667,7 +667,9 @@ kerb_prompter(krb5_context ctx, void *data,
memset(prompts[0].reply->data, 0, prompts[0].reply->length);
if (prompts[0].reply->length > 0) {
if (data) {
- strncpy(prompts[0].reply->data, data, prompts[0].reply->length-1);
+ strncpy(prompts[0].reply->data,
+ (const char *)data,
+ prompts[0].reply->length-1);
prompts[0].reply->length = strlen(prompts[0].reply->data);
} else {
prompts[0].reply->length = 0;
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index 79b82a06c37..f65ae02ede3 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -222,7 +222,7 @@ BOOL ads_try_connect(ADS_STRUCT *ads, const char *server )
ads->config.client_site_name =
SMB_STRDUP(cldap_reply.client_site_name);
}
-
+
ads->server.workgroup = SMB_STRDUP(cldap_reply.netbios_domain);
ads->ldap_port = LDAP_PORT;
@@ -241,7 +241,7 @@ BOOL ads_try_connect(ADS_STRUCT *ads, const char *server )
disabled
**********************************************************************/
-static BOOL ads_find_dc(ADS_STRUCT *ads)
+static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
{
const char *c_realm;
int count, i=0;
@@ -249,6 +249,7 @@ static BOOL ads_find_dc(ADS_STRUCT *ads)
pstring realm;
BOOL got_realm = False;
BOOL use_own_domain = False;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
/* if the realm and workgroup are both empty, assume they are ours */
@@ -279,7 +280,7 @@ again:
if ( !c_realm || !*c_realm ) {
DEBUG(0,("ads_find_dc: no realm or workgroup! Don't know what to do\n"));
- return False;
+ return NT_STATUS_INVALID_PARAMETER; /* rather need MISSING_PARAMETER ... */
}
}
@@ -288,16 +289,17 @@ again:
DEBUG(6,("ads_find_dc: looking for %s '%s'\n",
(got_realm ? "realm" : "domain"), realm));
- if ( !NT_STATUS_IS_OK(get_sorted_dc_list(realm, &ip_list, &count, got_realm))) {
+ status = get_sorted_dc_list(realm, &ip_list, &count, got_realm);
+ if (!NT_STATUS_IS_OK(status)) {
/* fall back to netbios if we can */
if ( got_realm && !lp_disable_netbios() ) {
got_realm = False;
goto again;
}
- return False;
+ return status;
}
-
+
/* if we fail this loop, then giveup since all the IP addresses returned were dead */
for ( i=0; i<count; i++ ) {
fstring server;
@@ -329,7 +331,7 @@ again:
if ( ads_try_connect(ads, server) ) {
SAFE_FREE(ip_list);
- return True;
+ return NT_STATUS_OK;
}
/* keep track of failures */
@@ -338,7 +340,7 @@ again:
SAFE_FREE(ip_list);
- return False;
+ return NT_STATUS_NO_LOGON_SERVERS;
}
@@ -351,6 +353,7 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
{
int version = LDAP_VERSION3;
ADS_STATUS status;
+ NTSTATUS ntstatus;
ads->last_attempt = time(NULL);
ads->ld = NULL;
@@ -362,11 +365,12 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
goto got_connection;
}
- if (ads_find_dc(ads)) {
+ ntstatus = ads_find_dc(ads);
+ if (NT_STATUS_IS_OK(ntstatus)) {
goto got_connection;
}
- return ADS_ERROR_SYSTEM(errno?errno:ENOENT);
+ return ADS_ERROR_NT(ntstatus);
got_connection:
DEBUG(3,("Connected to LDAP server %s\n", inet_ntoa(ads->ldap_ip)));
@@ -459,7 +463,8 @@ static struct berval *dup_berval(TALLOC_CTX *ctx, const struct berval *in_val)
if (in_val->bv_len == 0) return value;
value->bv_len = in_val->bv_len;
- value->bv_val = TALLOC_MEMDUP(ctx, in_val->bv_val, in_val->bv_len);
+ value->bv_val = (char *)TALLOC_MEMDUP(ctx, in_val->bv_val,
+ in_val->bv_len);
return value;
}
@@ -538,10 +543,12 @@ static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals)
* @param cookie The paged results cookie to be returned on subsequent calls
* @return status of search
**/
-ADS_STATUS ads_do_paged_search_args(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void *args, void **res,
- int *count, void **cookie)
+static ADS_STATUS ads_do_paged_search_args(ADS_STRUCT *ads,
+ const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res,
+ int *count, struct berval **cookie)
{
int rc, i, version;
char *utf8_expr, *utf8_path, **search_attrs;
@@ -714,10 +721,10 @@ done:
return ADS_ERROR(rc);
}
-ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void **res,
- int *count, void **cookie)
+static ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, LDAPMessage **res,
+ int *count, struct berval **cookie)
{
return ads_do_paged_search_args(ads, bind_path, scope, expr, attrs, NULL, res, count, cookie);
}
@@ -734,11 +741,12 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
* @param res ** which will contain results - free res* with ads_msgfree()
* @return status of search
**/
-ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void *args, void **res)
+ ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res)
{
- void *cookie = NULL;
+ struct berval *cookie = NULL;
int count = 0;
ADS_STATUS status;
@@ -751,7 +759,7 @@ ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
#ifdef HAVE_LDAP_ADD_RESULT_ENTRY
while (cookie) {
- void *res2 = NULL;
+ LDAPMessage *res2 = NULL;
ADS_STATUS status2;
LDAPMessage *msg, *next;
@@ -777,9 +785,9 @@ ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
return status;
}
-ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void **res)
+ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, LDAPMessage **res)
{
return ads_do_search_all_args(ads, bind_path, scope, expr, attrs, NULL, res);
}
@@ -801,10 +809,10 @@ ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path,
BOOL(*fn)(char *, void **, void *),
void *data_area)
{
- void *cookie = NULL;
+ struct berval *cookie = NULL;
int count = 0;
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
status = ads_do_paged_search(ads, bind_path, scope, expr, attrs, &res,
&count, &cookie);
@@ -837,9 +845,9 @@ ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path,
* @param res ** which will contain results - free res* with ads_msgfree()
* @return status of search
**/
-ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
- const char *expr,
- const char **attrs, void **res)
+ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
+ const char *expr,
+ const char **attrs, LDAPMessage **res)
{
int rc;
char *utf8_expr, *utf8_path, **search_attrs = NULL;
@@ -901,9 +909,8 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
* @param attrs Attributes to retrieve
* @return status of search
**/
-ADS_STATUS ads_search(ADS_STRUCT *ads, void **res,
- const char *expr,
- const char **attrs)
+ ADS_STATUS ads_search(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *expr, const char **attrs)
{
return ads_do_search(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
expr, attrs, res);
@@ -917,11 +924,11 @@ ADS_STATUS ads_search(ADS_STRUCT *ads, void **res,
* @param attrs Attributes to retrieve
* @return status of search
**/
-ADS_STATUS ads_search_dn(ADS_STRUCT *ads, void **res,
- const char *dn,
- const char **attrs)
+ ADS_STATUS ads_search_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn, const char **attrs)
{
- return ads_do_search(ads, dn, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, res);
+ return ads_do_search(ads, dn, LDAP_SCOPE_BASE, "(objectclass=*)",
+ attrs, res);
}
/**
@@ -929,7 +936,7 @@ ADS_STATUS ads_search_dn(ADS_STRUCT *ads, void **res,
* @param ads connection to ads server
* @param msg Search results to free
**/
-void ads_msgfree(ADS_STRUCT *ads, void *msg)
+ void ads_msgfree(ADS_STRUCT *ads, LDAPMessage *msg)
{
if (!msg) return;
ldap_msgfree(msg);
@@ -951,7 +958,7 @@ void ads_memfree(ADS_STRUCT *ads, void *mem)
* @param msg Search result
* @return dn string
**/
-char *ads_get_dn(ADS_STRUCT *ads, void *msg)
+ char *ads_get_dn(ADS_STRUCT *ads, LDAPMessage *msg)
{
char *utf8_dn, *unix_dn;
@@ -977,7 +984,7 @@ char *ads_get_dn(ADS_STRUCT *ads, void *msg)
* @param msg Search result
* @return dn string
**/
-char *ads_get_dn_canonical(ADS_STRUCT *ads, void *msg)
+ char *ads_get_dn_canonical(ADS_STRUCT *ads, LDAPMessage *msg)
{
#ifdef HAVE_LDAP_DN2AD_CANONICAL
return ldap_dn2ad_canonical(ads_get_dn(ads, msg));
@@ -1015,7 +1022,8 @@ char *ads_parent_dn(const char *dn)
* @param host Hostname to search for
* @return status of search
**/
-ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, void **res, const char *machine)
+ ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *machine)
{
ADS_STATUS status;
char *expr;
@@ -1059,8 +1067,9 @@ ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx)
*/
static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods,
int mod_op, const char *name,
- const void **invals)
+ const void *_invals)
{
+ const void **invals = (const void **)_invals;
int curmod;
LDAPMod **modlist = (LDAPMod **) *mods;
struct berval **ber_values = NULL;
@@ -1123,8 +1132,7 @@ ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods,
if (!val)
return ads_modlist_add(ctx, mods, LDAP_MOD_DELETE, name, NULL);
- return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, name,
- (const void **) values);
+ return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, name, values);
}
/**
@@ -1292,8 +1300,9 @@ char *ads_ou_string(ADS_STRUCT *ads, const char *org_unit)
char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid)
{
ADS_STATUS status;
- void *res = NULL;
- char *base, *wkn_dn = NULL, *ret = NULL, **wkn_dn_exp = NULL, **bind_dn_exp = NULL;
+ LDAPMessage *res = NULL;
+ char *base, *wkn_dn = NULL, *ret = NULL, **wkn_dn_exp = NULL,
+ **bind_dn_exp = NULL;
const char *attrs[] = {"distinguishedName", NULL};
int new_ln, wkn_ln, bind_ln, i;
@@ -1387,7 +1396,8 @@ char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid)
ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
const char *name, const char **vals)
{
- return ads_modlist_add(ctx, mods, LDAP_MOD_ADD, name, (const void **) vals);
+ return ads_modlist_add(ctx, mods, LDAP_MOD_ADD, name,
+ (const void *) vals);
}
/**
@@ -1410,7 +1420,7 @@ uint32 ads_get_kvno(ADS_STRUCT *ads, const char *machine_name)
if (asprintf(&filter, "(samAccountName=%s$)", machine_name) == -1) {
return kvno;
}
- ret = ads_search(ads, (void**)(void *)&res, filter, attrs);
+ ret = ads_search(ads, &res, filter, attrs);
SAFE_FREE(filter);
if (!ADS_ERR_OK(ret) && ads_count_replies(ads, res)) {
DEBUG(1,("ads_get_kvno: Computer Account For %s not found.\n", machine_name));
@@ -1464,7 +1474,7 @@ ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machin
ADS_STATUS ret = ADS_ERROR(LDAP_SUCCESS);
char *dn_string = NULL;
- ret = ads_find_machine_acct(ads, (void **)(void *)&res, machine_name);
+ ret = ads_find_machine_acct(ads, &res, machine_name);
if (!ADS_ERR_OK(ret) || ads_count_replies(ads, res) != 1) {
DEBUG(5,("ads_clear_service_principal_names: WARNING: Host Account for %s not found... skipping operation.\n", machine_name));
DEBUG(5,("ads_clear_service_principal_names: WARNING: Service Principals for %s have NOT been cleared.\n", machine_name));
@@ -1533,7 +1543,7 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n
char *dn_string = NULL;
const char *servicePrincipalName[3] = {NULL, NULL, NULL};
- ret = ads_find_machine_acct(ads, (void **)(void *)&res, machine_name);
+ ret = ads_find_machine_acct(ads, &res, machine_name);
if (!ADS_ERR_OK(ret) || ads_count_replies(ads, res) != 1) {
DEBUG(1,("ads_add_service_principal_name: WARNING: Host Account for %s not found... skipping operation.\n",
machine_name));
@@ -1768,6 +1778,7 @@ static BOOL ads_dump_field(char *field, void **values, void *data_area)
{"tokenGroups", False, dump_sid},
{"tokenGroupsNoGCAcceptable", False, dump_sid},
{"tokengroupsGlobalandUniversal", False, dump_sid},
+ {"mS-DS-CreatorSID", False, dump_sid},
{NULL, True, NULL}
};
int i;
@@ -1800,7 +1811,7 @@ static BOOL ads_dump_field(char *field, void **values, void *data_area)
* @param res Results to dump
**/
-void ads_dump(ADS_STRUCT *ads, void *res)
+ void ads_dump(ADS_STRUCT *ads, LDAPMessage *res)
{
ads_process_results(ads, res, ads_dump_field, NULL);
}
@@ -1816,11 +1827,11 @@ void ads_dump(ADS_STRUCT *ads, void *res)
* @param fn Function for processing each result
* @param data_area user-defined area to pass to function
**/
-void ads_process_results(ADS_STRUCT *ads, void *res,
- BOOL(*fn)(char *, void **, void *),
- void *data_area)
+ void ads_process_results(ADS_STRUCT *ads, LDAPMessage *res,
+ BOOL(*fn)(char *, void **, void *),
+ void *data_area)
{
- void *msg;
+ LDAPMessage *msg;
TALLOC_CTX *ctx;
if (!(ctx = talloc_init("ads_process_results")))
@@ -1885,9 +1896,9 @@ int ads_count_replies(ADS_STRUCT *ads, void *res)
* @param res Results of search
* @return first entry from result
**/
-void *ads_first_entry(ADS_STRUCT *ads, void *res)
+ LDAPMessage *ads_first_entry(ADS_STRUCT *ads, LDAPMessage *res)
{
- return (void *)ldap_first_entry(ads->ld, (LDAPMessage *)res);
+ return ldap_first_entry(ads->ld, res);
}
/**
@@ -1896,9 +1907,9 @@ void *ads_first_entry(ADS_STRUCT *ads, void *res)
* @param res Results of search
* @return next entry from result
**/
-void *ads_next_entry(ADS_STRUCT *ads, void *res)
+ LDAPMessage *ads_next_entry(ADS_STRUCT *ads, LDAPMessage *res)
{
- return (void *)ldap_next_entry(ads->ld, (LDAPMessage *)res);
+ return ldap_next_entry(ads->ld, res);
}
/**
@@ -1909,8 +1920,8 @@ void *ads_next_entry(ADS_STRUCT *ads, void *res)
* @param field Attribute to retrieve
* @return Result string in talloc context
**/
-char *ads_pull_string(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx, void *msg, const char *field)
+ char *ads_pull_string(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg,
+ const char *field)
{
char **values;
char *ret = NULL;
@@ -1940,9 +1951,9 @@ char *ads_pull_string(ADS_STRUCT *ads,
* @param field Attribute to retrieve
* @return Result strings in talloc context
**/
-char **ads_pull_strings(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx, void *msg, const char *field,
- size_t *num_values)
+ char **ads_pull_strings(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field,
+ size_t *num_values)
{
char **values;
char **ret = NULL;
@@ -1985,13 +1996,13 @@ char **ads_pull_strings(ADS_STRUCT *ads,
* @param more_values Are there more values to get?
* @return Result strings in talloc context
**/
-char **ads_pull_strings_range(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx,
- void *msg, const char *field,
- char **current_strings,
- const char **next_attribute,
- size_t *num_strings,
- BOOL *more_strings)
+ char **ads_pull_strings_range(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field,
+ char **current_strings,
+ const char **next_attribute,
+ size_t *num_strings,
+ BOOL *more_strings)
{
char *attr;
char *expected_range_attrib, *range_attr;
@@ -2108,8 +2119,8 @@ char **ads_pull_strings_range(ADS_STRUCT *ads,
* @param v Pointer to int to store result
* @return boolean inidicating success
*/
-BOOL ads_pull_uint32(ADS_STRUCT *ads,
- void *msg, const char *field, uint32 *v)
+ BOOL ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
+ uint32 *v)
{
char **values;
@@ -2133,8 +2144,7 @@ BOOL ads_pull_uint32(ADS_STRUCT *ads,
* @param guid 37-byte area to receive text guid
* @return boolean indicating success
**/
-BOOL ads_pull_guid(ADS_STRUCT *ads,
- void *msg, struct GUID *guid)
+ BOOL ads_pull_guid(ADS_STRUCT *ads, LDAPMessage *msg, struct GUID *guid)
{
char **values;
UUID_FLAT flat_guid;
@@ -2163,8 +2173,8 @@ BOOL ads_pull_guid(ADS_STRUCT *ads,
* @param sid Pointer to sid to store result
* @return boolean inidicating success
*/
-BOOL ads_pull_sid(ADS_STRUCT *ads,
- void *msg, const char *field, DOM_SID *sid)
+ BOOL ads_pull_sid(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
+ DOM_SID *sid)
{
struct berval **values;
BOOL ret = False;
@@ -2190,8 +2200,8 @@ BOOL ads_pull_sid(ADS_STRUCT *ads,
* @param sids pointer to sid array to allocate
* @return the count of SIDs pulled
**/
-int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
- void *msg, const char *field, DOM_SID **sids)
+ int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field, DOM_SID **sids)
{
struct berval **values;
BOOL ret;
@@ -2234,8 +2244,8 @@ int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
* @param sd Pointer to *SEC_DESC to store result (talloc()ed)
* @return boolean inidicating success
*/
-BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
- void *msg, const char *field, SEC_DESC **sd)
+ BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field, SEC_DESC **sd)
{
struct berval **values;
prs_struct ps;
@@ -2267,7 +2277,8 @@ BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
* @param msg Results of search
* @return the username
*/
-char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, void *msg)
+ char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg)
{
#if 0 /* JERRY */
char *ret, *p;
@@ -2297,7 +2308,7 @@ ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn)
{
const char *attrs[] = {"highestCommittedUSN", NULL};
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
status = ads_do_search_retry(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
if (!ADS_ERR_OK(status))
@@ -2344,7 +2355,7 @@ ADS_STATUS ads_current_time(ADS_STRUCT *ads)
{
const char *attrs[] = {"currentTime", NULL};
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
char *timestr;
TALLOC_CTX *ctx;
ADS_STRUCT *ads_s = ads;
@@ -2409,7 +2420,7 @@ ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32 *val)
{
const char *attrs[] = {"domainFunctionality", NULL};
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
ADS_STRUCT *ads_s = ads;
*val = DS_DOMAIN_FUNCTION_2000;
@@ -2465,7 +2476,7 @@ done:
ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid)
{
const char *attrs[] = {"objectSid", NULL};
- void *res;
+ LDAPMessage *res;
ADS_STATUS rc;
rc = ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_BASE, "(objectclass=*)",
@@ -2490,7 +2501,7 @@ ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid)
ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_name)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *dn, *service_name;
const char *attrs[] = { "dsServiceName", NULL };
@@ -2501,9 +2512,12 @@ ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_n
service_name = ads_pull_string(ads, mem_ctx, res, "dsServiceName");
if (service_name == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
}
+ ads_msgfree(ads, res);
+
/* go up three levels */
dn = ads_parent_dn(ads_parent_dn(ads_parent_dn(service_name)));
if (dn == NULL) {
@@ -2515,8 +2529,6 @@ ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_n
return ADS_ERROR(LDAP_NO_MEMORY);
}
- ads_msgfree(ads, res);
-
return status;
/*
dsServiceName: CN=NTDS Settings,CN=W2K3DC,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=ber,DC=suse,DC=de
@@ -2534,7 +2546,7 @@ ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_n
ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *computer_name, const char **site_dn)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *parent, *config_context, *filter;
const char *attrs[] = { "configurationNamingContext", NULL };
char *dn;
@@ -2551,37 +2563,45 @@ ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const c
config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
if (config_context == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
filter = talloc_asprintf(mem_ctx, "(cn=%s)", computer_name);
if (filter == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
+ ads_msgfree(ads, res);
+
status = ads_do_search(ads, config_context, LDAP_SCOPE_SUBTREE, filter, NULL, &res);
if (!ADS_ERR_OK(status)) {
return status;
}
if (ads_count_replies(ads, res) != 1) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
dn = ads_get_dn(ads, res);
if (dn == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
/* go up three levels */
parent = ads_parent_dn(ads_parent_dn(ads_parent_dn(dn)));
if (parent == NULL) {
+ ads_msgfree(ads, res);
ads_memfree(ads, dn);
return ADS_ERROR(LDAP_NO_MEMORY);
}
*site_dn = talloc_strdup(mem_ctx, parent);
if (*site_dn == NULL) {
+ ads_msgfree(ads, res);
ads_memfree(ads, dn);
ADS_ERROR(LDAP_NO_MEMORY);
}
@@ -2603,7 +2623,7 @@ ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const c
ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **suffixes, size_t *num_suffixes)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *config_context, *base;
const char *attrs[] = { "configurationNamingContext", NULL };
const char *attrs2[] = { "uPNSuffixes", NULL };
@@ -2632,7 +2652,7 @@ ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **suffixe
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
- suffixes = ads_pull_strings(ads, mem_ctx, &res, "uPNSuffixes", num_suffixes);
+ suffixes = ads_pull_strings(ads, mem_ctx, res, "uPNSuffixes", num_suffixes);
if (suffixes == NULL) {
ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
@@ -2729,12 +2749,12 @@ BOOL ads_get_sid_from_extended_dn(TALLOC_CTX *mem_ctx,
* @param sids pointer to sid array to allocate
* @return the count of SIDs pulled
**/
-int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx,
- void *msg,
- const char *field,
- enum ads_extended_dn_flags flags,
- DOM_SID **sids)
+ int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg,
+ const char *field,
+ enum ads_extended_dn_flags flags,
+ DOM_SID **sids)
{
int i;
size_t dn_count;
@@ -2776,7 +2796,7 @@ char* ads_get_dnshostname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine
int count = 0;
char *name = NULL;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, global_myname());
+ status = ads_find_machine_acct(ads, &res, global_myname());
if (!ADS_ERR_OK(status)) {
DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n",
global_myname()));
@@ -2808,20 +2828,20 @@ char* ads_get_upn( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name )
int count = 0;
char *name = NULL;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, global_myname());
+ status = ads_find_machine_acct(ads, &res, global_myname());
if (!ADS_ERR_OK(status)) {
- DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n",
+ DEBUG(0,("ads_get_upn: Failed to find account for %s\n",
global_myname()));
goto out;
}
if ( (count = ads_count_replies(ads, res)) != 1 ) {
- DEBUG(1,("ads_get_dnshostname: %d entries returned!\n", count));
+ DEBUG(1,("ads_get_upn: %d entries returned!\n", count));
goto out;
}
if ( (name = ads_pull_string(ads, ctx, res, "userPrincipalName")) == NULL ) {
- DEBUG(0,("ads_get_dnshostname: No userPrincipalName attribute!\n"));
+ DEBUG(2,("ads_get_upn: No userPrincipalName attribute!\n"));
}
out:
@@ -2840,7 +2860,7 @@ char* ads_get_samaccountname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *mach
int count = 0;
char *name = NULL;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, global_myname());
+ status = ads_find_machine_acct(ads, &res, global_myname());
if (!ADS_ERR_OK(status)) {
DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n",
global_myname()));
@@ -2918,6 +2938,8 @@ ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name,
}
#endif
+#ifdef HAVE_LDAP
+
/**
* Delete a machine from the realm
* @param ads connection to ads server
@@ -2927,7 +2949,8 @@ ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name,
ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
{
ADS_STATUS status;
- void *res, *msg;
+ void *msg;
+ LDAPMessage *res;
char *hostnameDN, *host;
int rc;
LDAPControl ldap_control;
@@ -2944,11 +2967,13 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
status = ads_find_machine_acct(ads, &res, host);
if (!ADS_ERR_OK(status)) {
DEBUG(0, ("Host account for %s does not exist.\n", host));
+ SAFE_FREE(host);
return status;
}
msg = ads_first_entry(ads, res);
if (!msg) {
+ SAFE_FREE(host);
return ADS_ERROR_SYSTEM(ENOENT);
}
@@ -2963,13 +2988,14 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
if (rc != LDAP_SUCCESS) {
const char *attrs[] = { "cn", NULL };
- void *msg_sub;
+ LDAPMessage *msg_sub;
/* we only search with scope ONE, we do not expect any further
* objects to be created deeper */
- status = ads_do_search_retry(ads, hostnameDN, LDAP_SCOPE_ONELEVEL,
- "(objectclass=*)", attrs, &res);
+ status = ads_do_search_retry(ads, hostnameDN,
+ LDAP_SCOPE_ONELEVEL,
+ "(objectclass=*)", attrs, &res);
if (!ADS_ERR_OK(status)) {
SAFE_FREE(host);
@@ -3001,8 +3027,9 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
}
/* there should be no subordinate objects anymore */
- status = ads_do_search_retry(ads, hostnameDN, LDAP_SCOPE_ONELEVEL,
- "(objectclass=*)", attrs, &res);
+ status = ads_do_search_retry(ads, hostnameDN,
+ LDAP_SCOPE_ONELEVEL,
+ "(objectclass=*)", attrs, &res);
if (!ADS_ERR_OK(status) || ( (ads_count_replies(ads, res)) > 0 ) ) {
SAFE_FREE(host);
@@ -3025,6 +3052,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
status = ads_find_machine_acct(ads, &res, host);
if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
DEBUG(3, ("Failed to remove host account.\n"));
+ SAFE_FREE(host);
return status;
}
@@ -3032,3 +3060,5 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
return status;
}
#endif
+
+#endif
diff --git a/source/libads/ldap_printer.c b/source/libads/ldap_printer.c
index 2d2664979cd..f5168b05af0 100644
--- a/source/libads/ldap_printer.c
+++ b/source/libads/ldap_printer.c
@@ -27,8 +27,9 @@
Note that results "res" may be allocated on return so that the
results can be used. It should be freed using ads_msgfree.
*/
-ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res,
- const char *printer, const char *servername)
+ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *printer,
+ const char *servername)
{
ADS_STATUS status;
char *srv_dn, **srv_cn, *s;
@@ -63,7 +64,7 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res,
return status;
}
-ADS_STATUS ads_find_printers(ADS_STRUCT *ads, void **res)
+ ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
{
const char *ldap_expr;
const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
diff --git a/source/libads/ldap_schema.c b/source/libads/ldap_schema.c
index e63a888b5b9..b4a512cbfe2 100644
--- a/source/libads/ldap_schema.c
+++ b/source/libads/ldap_schema.c
@@ -29,7 +29,7 @@ ADS_STATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
char ***OIDs_out, char ***names, size_t *count)
{
ADS_STATUS status;
- void *res = NULL;
+ LDAPMessage *res = NULL;
LDAPMessage *msg;
char *expr = NULL;
const char *attrs[] = { "lDAPDisplayName", "attributeId", NULL };
@@ -111,7 +111,7 @@ const char *ads_get_attrname_by_oid(ADS_STRUCT *ads, const char *schema_path, TA
{
ADS_STATUS rc;
int count = 0;
- void *res = NULL;
+ LDAPMessage *res = NULL;
char *expr = NULL;
const char *attrs[] = { "lDAPDisplayName", NULL };
char *result;
@@ -155,7 +155,7 @@ failed:
static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *schema;
const char *attrs[] = { "schemaNamingContext", NULL };
@@ -165,10 +165,12 @@ static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **s
}
if ( (schema = ads_pull_string(ads, mem_ctx, res, "schemaNamingContext")) == NULL ) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
}
if ( (*schema_path = talloc_strdup(mem_ctx, schema)) == NULL ) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
diff --git a/source/libads/ldap_user.c b/source/libads/ldap_user.c
index 3ff6acc9e83..66d94d29d3a 100644
--- a/source/libads/ldap_user.c
+++ b/source/libads/ldap_user.c
@@ -25,7 +25,8 @@
/*
find a user account
*/
-ADS_STATUS ads_find_user_acct(ADS_STRUCT *ads, void **res, const char *user)
+ ADS_STATUS ads_find_user_acct(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *user)
{
ADS_STATUS status;
char *ldap_exp;
diff --git a/source/libads/ldap_utils.c b/source/libads/ldap_utils.c
index 03ae94150f4..e6855674d17 100644
--- a/source/libads/ldap_utils.c
+++ b/source/libads/ldap_utils.c
@@ -29,7 +29,8 @@
*/
static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind_path, int scope,
const char *expr,
- const char **attrs, void *args, void **res)
+ const char **attrs, void *args,
+ LDAPMessage **res)
{
ADS_STATUS status = ADS_SUCCESS;
int count = 3;
@@ -116,41 +117,41 @@ static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind
return status;
}
-ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope,
- const char *expr,
- const char **attrs, void **res)
+ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, LDAPMessage **res)
{
return ads_do_search_retry_internal(ads, bind_path, scope, expr, attrs, NULL, res);
}
-ADS_STATUS ads_do_search_retry_args(ADS_STRUCT *ads, const char *bind_path, int scope,
- const char *expr,
- const char **attrs, void *args, void **res)
+ ADS_STATUS ads_do_search_retry_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res)
{
return ads_do_search_retry_internal(ads, bind_path, scope, expr, attrs, args, res);
}
-ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res,
- const char *expr,
- const char **attrs)
+ ADS_STATUS ads_search_retry(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *expr, const char **attrs)
{
return ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
expr, attrs, res);
}
-ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, void **res,
- const char *dn,
- const char **attrs)
+ ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn,
+ const char **attrs)
{
return ads_do_search_retry(ads, dn, LDAP_SCOPE_BASE,
"(objectclass=*)", attrs, res);
}
-ADS_STATUS ads_search_retry_extended_dn(ADS_STRUCT *ads, void **res,
- const char *dn,
- const char **attrs,
- enum ads_extended_dn_flags flags)
+ ADS_STATUS ads_search_retry_extended_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn,
+ const char **attrs,
+ enum ads_extended_dn_flags flags)
{
ads_control args;
@@ -162,9 +163,9 @@ ADS_STATUS ads_search_retry_extended_dn(ADS_STRUCT *ads, void **res,
"(objectclass=*)", attrs, &args, res);
}
-ADS_STATUS ads_search_retry_sid(ADS_STRUCT *ads, void **res,
- const DOM_SID *sid,
- const char **attrs)
+ ADS_STATUS ads_search_retry_sid(ADS_STRUCT *ads, LDAPMessage **res,
+ const DOM_SID *sid,
+ const char **attrs)
{
char *dn, *sid_string;
ADS_STATUS status;
diff --git a/source/libads/sasl.c b/source/libads/sasl.c
index 52a0f0b165c..c3f496938ac 100644
--- a/source/libads/sasl.c
+++ b/source/libads/sasl.c
@@ -348,7 +348,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
goto failed;
}
- cred.bv_val = output_token.value;
+ cred.bv_val = (char *)output_token.value;
cred.bv_len = output_token.length;
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL,
@@ -389,6 +389,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
#if 0
file_save("sasl_gssapi.dat", output_token.value, output_token.length);
#endif
+
if (p) {
max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3];
}
@@ -396,7 +397,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
gss_release_buffer(&minor_status, &output_token);
output_token.value = SMB_MALLOC(strlen(ads->config.bind_path) + 8);
- p = output_token.value;
+ p = (uint8 *)output_token.value;
*p++ = 1; /* no sign & seal selection */
/* choose the same size as the server gave us */
@@ -418,7 +419,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
free(output_token.value);
- cred.bv_val = input_token.value;
+ cred.bv_val = (char *)input_token.value;
cred.bv_len = input_token.length;
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL,
@@ -452,7 +453,7 @@ ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
char **values;
ADS_STATUS status;
int i, j;
- void *res;
+ LDAPMessage *res;
/* get a list of supported SASL mechanisms */
status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
diff --git a/source/libgpo/gpo_fetch.c b/source/libgpo/gpo_fetch.c
new file mode 100644
index 00000000000..3347a36b07e
--- /dev/null
+++ b/source/libgpo/gpo_fetch.c
@@ -0,0 +1,194 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Group Policy Object Support
+ * Copyright (C) Guenther Deschner 2005-2006
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+/****************************************************************
+ explode the GPO CIFS URI into their components
+****************************************************************/
+
+NTSTATUS ads_gpo_explode_filesyspath(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *file_sys_path,
+ char **server,
+ char **service,
+ char **nt_path,
+ char **unix_path)
+{
+ fstring tok;
+ pstring path;
+
+ *server = NULL;
+ *service = NULL;
+ *nt_path = NULL;
+ *unix_path = NULL;
+
+ if (!next_token(&file_sys_path, tok, "\\", sizeof(tok))) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((*server = talloc_strdup(mem_ctx, tok)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!next_token(&file_sys_path, tok, "\\", sizeof(tok))) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((*service = talloc_strdup(mem_ctx, tok)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ((*nt_path = talloc_asprintf(mem_ctx, "\\%s", file_sys_path)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ pstrcpy(path, lock_path(GPO_CACHE_DIR));
+ pstrcat(path, "/");
+ pstrcat(path, file_sys_path);
+ pstring_sub(path, "\\", "/");
+
+ if ((*unix_path = talloc_strdup(mem_ctx, path)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+ prepare the local disc storage for "unix_path"
+****************************************************************/
+
+NTSTATUS ads_gpo_prepare_local_store(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *unix_path)
+{
+ const char *top_dir = lock_path(GPO_CACHE_DIR);
+ char *current_dir;
+ fstring tok;
+
+ current_dir = talloc_strdup(mem_ctx, top_dir);
+ NT_STATUS_HAVE_NO_MEMORY(current_dir);
+
+ if ((mkdir(top_dir, 0644)) < 0 && errno != EEXIST) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ while (next_token(&unix_path, tok, "/", sizeof(tok))) {
+
+ if (strequal(tok, GPO_CACHE_DIR)) {
+ break;
+ }
+ }
+
+ while (next_token(&unix_path, tok, "/", sizeof(tok))) {
+
+ current_dir = talloc_asprintf_append(current_dir, "/%s", tok);
+ NT_STATUS_HAVE_NO_MEMORY(current_dir);
+
+ if ((mkdir(current_dir, 0644)) < 0 && errno != EEXIST) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+ download a full GPO via CIFS
+****************************************************************/
+
+NTSTATUS ads_fetch_gpo_files(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ struct cli_state *cli,
+ struct GROUP_POLICY_OBJECT *gpo)
+{
+ NTSTATUS result;
+ char *server, *service, *nt_path, *unix_path, *nt_ini_path, *unix_ini_path;
+
+ result = ads_gpo_explode_filesyspath(ads, mem_ctx, gpo->file_sys_path,
+ &server, &service, &nt_path, &unix_path);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ result = ads_gpo_prepare_local_store(ads, mem_ctx, unix_path);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ unix_ini_path = talloc_asprintf(mem_ctx, "%s/%s", unix_path, GPT_INI);
+ nt_ini_path = talloc_asprintf(mem_ctx, "%s\\%s", nt_path, GPT_INI);
+ if (!unix_path || !nt_ini_path) {
+ result = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+
+ result = gpo_copy_file(mem_ctx, cli, nt_ini_path, unix_ini_path);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ result = gpo_sync_directories(mem_ctx, cli, nt_path, unix_path);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ result = NT_STATUS_OK;
+
+ out:
+ return result;
+}
+
+/****************************************************************
+ get the locally stored gpt.ini version number
+****************************************************************/
+
+NTSTATUS ads_gpo_get_sysvol_gpt_version(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *unix_path,
+ uint32 *sysvol_version,
+ char **display_name)
+{
+ NTSTATUS status;
+ uint32 version;
+ char *local_path = NULL;
+ char *name = NULL;
+
+ local_path = talloc_asprintf(mem_ctx, "%s/%s", unix_path, GPT_INI);
+ NT_STATUS_HAVE_NO_MEMORY(local_path);
+
+ status = parse_gpt_ini(mem_ctx, local_path, &version, &name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("ads_gpo_get_sysvol_gpt_version: failed to parse ini [%s]: %s\n",
+ unix_path, nt_errstr(status)));
+ return status;
+ }
+
+ if (sysvol_version) {
+ *sysvol_version = version;
+ }
+
+ if (name && *display_name) {
+ *display_name = talloc_strdup(mem_ctx, name);
+ }
+
+ return NT_STATUS_OK;
+}
diff --git a/source/libgpo/gpo_filesync.c b/source/libgpo/gpo_filesync.c
new file mode 100644
index 00000000000..e97562c93f3
--- /dev/null
+++ b/source/libgpo/gpo_filesync.c
@@ -0,0 +1,225 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Group Policy Object Support
+ * Copyright (C) Guenther Deschner 2006
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+struct sync_context {
+ TALLOC_CTX *mem_ctx;
+ struct cli_state *cli;
+ char *remote_path;
+ char *local_path;
+ pstring mask;
+ uint16 attribute;
+};
+
+static void gpo_sync_func(const char *mnt,
+ file_info *info,
+ const char *mask,
+ void *state);
+
+NTSTATUS gpo_copy_file(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli,
+ const char *nt_path,
+ const char *unix_path)
+{
+ NTSTATUS result;
+ int fnum;
+ int fd = 0;
+ char *data = NULL;
+ static int io_bufsize = 64512;
+ int read_size = io_bufsize;
+ off_t start = 0;
+ off_t nread = 0;
+
+ if ((fnum = cli_open(cli, nt_path, O_RDONLY, DENY_NONE)) == -1) {
+ result = NT_STATUS_NO_SUCH_FILE;
+ goto out;
+ }
+
+ if ((fd = sys_open(unix_path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
+ result = map_nt_error_from_unix(errno);
+ goto out;
+ }
+
+ if ((data = (char *)SMB_MALLOC(read_size)) == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+
+ while (1) {
+
+ int n = cli_read(cli, fnum, data, nread + start, read_size);
+
+ if (n <= 0)
+ break;
+
+ if (write(fd, data, n) != n) {
+ break;
+ }
+
+ nread += n;
+ }
+
+ result = NT_STATUS_OK;
+
+ out:
+ SAFE_FREE(data);
+ if (fnum) {
+ cli_close(cli, fnum);
+ }
+ if (fd) {
+ close(fd);
+ }
+
+ return result;
+}
+
+/****************************************************************
+ copy dir
+****************************************************************/
+
+static NTSTATUS gpo_copy_dir(const char *unix_path)
+{
+ if ((mkdir(unix_path, 0644)) < 0 && errno != EEXIST) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+ sync files
+****************************************************************/
+
+static BOOL gpo_sync_files(struct sync_context *ctx)
+{
+ DEBUG(3,("calling cli_list with mask: %s\n", ctx->mask));
+
+ if (cli_list(ctx->cli, ctx->mask, ctx->attribute, gpo_sync_func, ctx) == -1) {
+ DEBUG(1,("listing [%s] failed with error: %s\n",
+ ctx->mask, cli_errstr(ctx->cli)));
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************
+ syncronisation call back
+****************************************************************/
+
+static void gpo_sync_func(const char *mnt,
+ file_info *info,
+ const char *mask,
+ void *state)
+{
+ NTSTATUS result;
+ struct sync_context *ctx;
+ fstring nt_filename, unix_filename;
+ fstring nt_dir, unix_dir;
+ char *old_nt_dir, *old_unix_dir;
+
+ ctx = (struct sync_context *)state;
+
+ if (strequal(info->name, ".") || strequal(info->name, "..")) {
+ return;
+ }
+
+ DEBUG(5,("gpo_sync_func: got mask: [%s], name: [%s]\n",
+ mask, info->name));
+
+ if (info->mode & aDIR) {
+
+ DEBUG(3,("got dir: [%s]\n", info->name));
+
+ fstrcpy(nt_dir, ctx->remote_path);
+ fstrcat(nt_dir, "\\");
+ fstrcat(nt_dir, info->name);
+
+ fstrcpy(unix_dir, ctx->local_path);
+ fstrcat(unix_dir, "/");
+ fstrcat(unix_dir, info->name);
+
+ result = gpo_copy_dir(unix_dir);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(1,("failed to copy dir: %s\n", nt_errstr(result)));
+ }
+
+ old_nt_dir = ctx->remote_path;
+ ctx->remote_path = nt_dir;
+
+ old_unix_dir = ctx->local_path;
+ ctx->local_path = talloc_strdup(ctx->mem_ctx, unix_dir);
+
+ pstrcpy(ctx->mask, nt_dir);
+ pstrcat(ctx->mask, "\\*");
+
+ if (!gpo_sync_files(ctx)) {
+ DEBUG(0,("could not sync files\n"));
+ }
+
+ ctx->remote_path = old_nt_dir;
+ ctx->local_path = old_unix_dir;
+ return;
+ }
+
+ DEBUG(3,("got file: [%s]\n", info->name));
+
+ fstrcpy(nt_filename, ctx->remote_path);
+ fstrcat(nt_filename, "\\");
+ fstrcat(nt_filename, info->name);
+
+ fstrcpy(unix_filename, ctx->local_path);
+ fstrcat(unix_filename, "/");
+ fstrcat(unix_filename, info->name);
+
+ result = gpo_copy_file(ctx->mem_ctx, ctx->cli, nt_filename, unix_filename);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(1,("failed to copy file: %s\n", nt_errstr(result)));
+ }
+}
+
+
+/****************************************************************
+ list a remote directory and download recursivly
+****************************************************************/
+
+NTSTATUS gpo_sync_directories(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli,
+ const char *nt_path,
+ const char *local_path)
+{
+ struct sync_context ctx;
+
+ ctx.mem_ctx = mem_ctx;
+ ctx.cli = cli;
+ ctx.remote_path = CONST_DISCARD(char *, nt_path);
+ ctx.local_path = CONST_DISCARD(char *, local_path);
+ ctx.attribute = (aSYSTEM | aHIDDEN | aDIR);
+
+ pstrcpy(ctx.mask, nt_path);
+ pstrcat(ctx.mask, "\\*");
+
+ if (!gpo_sync_files(&ctx)) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ return NT_STATUS_OK;
+}
diff --git a/source/libads/gpo.c b/source/libgpo/gpo_ldap.c
index 9cf7aae9770..13ec80f2ad2 100644
--- a/source/libads/gpo.c
+++ b/source/libgpo/gpo_ldap.c
@@ -20,12 +20,18 @@
#include "includes.h"
+#ifdef HAVE_LDAP
+
+/****************************************************************
+ parse the raw extension string into a GP_EXT structure
+****************************************************************/
+
ADS_STATUS ads_parse_gp_ext(TALLOC_CTX *mem_ctx,
const char *extension_raw,
struct GP_EXT *gp_ext)
{
char **ext_list;
- char **ext_strings;
+ char **ext_strings = NULL;
int i;
DEBUG(20,("ads_parse_gp_ext: %s\n", extension_raw));
@@ -129,6 +135,10 @@ parse_error:
return ADS_ERROR(LDAP_NO_MEMORY);
}
+/****************************************************************
+ parse the raw link string into a GP_LINK structure
+****************************************************************/
+
ADS_STATUS ads_parse_gplink(TALLOC_CTX *mem_ctx,
const char *gp_link_raw,
uint32 options,
@@ -204,6 +214,10 @@ parse_error:
return ADS_ERROR(LDAP_NO_MEMORY);
}
+/****************************************************************
+ helper call to get a GP_LINK structure from a linkdn
+****************************************************************/
+
ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
const char *link_dn,
@@ -211,7 +225,7 @@ ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
{
ADS_STATUS status;
const char *attrs[] = {"gPLink", "gPOptions", NULL};
- void *res = NULL;
+ LDAPMessage *res = NULL;
const char *gp_link;
uint32 gp_options;
@@ -236,6 +250,7 @@ ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
}
+ /* perfectly leggal to have no options */
if (!ads_pull_uint32(ads, res, "gPOptions", &gp_options)) {
DEBUG(10,("ads_get_gpo_link: no 'gPOptions' attribute found\n"));
gp_options = 0;
@@ -246,6 +261,10 @@ ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
return ads_parse_gplink(mem_ctx, gp_link, gp_options, gp_link_struct);
}
+/****************************************************************
+ helper call to add a gp link
+****************************************************************/
+
ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
const char *link_dn,
@@ -254,11 +273,10 @@ ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
{
ADS_STATUS status;
const char *attrs[] = {"gPLink", NULL};
- void *res = NULL;
+ LDAPMessage *res = NULL;
const char *gp_link, *gp_link_new;
ADS_MODLIST mods;
-
/* although ADS allows to set anything here, we better check here if
* the gpo_dn is sane */
@@ -274,6 +292,7 @@ ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
if (ads_count_replies(ads, res) != 1) {
DEBUG(10,("ads_add_gpo_link: no result\n"));
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
@@ -284,14 +303,11 @@ ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link, gpo_dn, gpo_opt);
}
- if (gp_link_new == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ads_msgfree(ads, res);
+ ADS_ERROR_HAVE_NO_MEMORY(gp_link_new);
mods = ads_init_mods(mem_ctx);
- if (mods == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(mods);
status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
if (!ADS_ERR_OK(status)) {
@@ -301,6 +317,10 @@ ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
return ads_gen_mod(ads, link_dn, mods);
}
+/****************************************************************
+ helper call to delete add a gp link
+****************************************************************/
+
/* untested & broken */
ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
@@ -309,7 +329,7 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
{
ADS_STATUS status;
const char *attrs[] = {"gPLink", NULL};
- void *res = NULL;
+ LDAPMessage *res = NULL;
const char *gp_link, *gp_link_new = NULL;
ADS_MODLIST mods;
@@ -332,6 +352,7 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
if (ads_count_replies(ads, res) != 1) {
DEBUG(10,("ads_delete_gpo_link: no result\n"));
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
@@ -341,16 +362,13 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
}
/* find link to delete */
-// gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link, gpo_dn, gpo_opt);
+ /* gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link, gpo_dn, gpo_opt); */
- if (gp_link_new == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ads_msgfree(ads, res);
+ ADS_ERROR_HAVE_NO_MEMORY(gp_link_new);
mods = ads_init_mods(mem_ctx);
- if (mods == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(mods);
status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
if (!ADS_ERR_OK(status)) {
@@ -360,70 +378,57 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
return ads_gen_mod(ads, link_dn, mods);
}
-ADS_STATUS ads_parse_gpo(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx,
- void *res,
- const char *gpo_dn,
- struct GROUP_POLICY_OBJECT *gpo)
+/****************************************************************
+ parse a GROUP_POLICY_OBJECT structure from an LDAPMessage result
+****************************************************************/
+
+ ADS_STATUS ads_parse_gpo(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *res,
+ const char *gpo_dn,
+ struct GROUP_POLICY_OBJECT *gpo)
{
ZERO_STRUCTP(gpo);
- if (res == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(res);
if (gpo_dn) {
gpo->ds_path = talloc_strdup(mem_ctx, gpo_dn);
} else {
gpo->ds_path = ads_get_dn(ads, res);
}
- if (gpo->ds_path == NULL) {
- ads_msgfree(ads, res);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+
+ ADS_ERROR_HAVE_NO_MEMORY(gpo->ds_path);
if (!ads_pull_uint32(ads, res, "versionNumber", &gpo->version)) {
- ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
- /* split here for convenience */
- gpo->version_user = gpo->version >> 16;
- gpo->version_machine = gpo->version & 0xffff;
-
/* sure ??? */
if (!ads_pull_uint32(ads, res, "flags", &gpo->options)) {
- ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
gpo->file_sys_path = ads_pull_string(ads, mem_ctx, res, "gPCFileSysPath");
- if (gpo->file_sys_path == NULL) {
- ads_msgfree(ads, res);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(gpo->file_sys_path);
gpo->display_name = ads_pull_string(ads, mem_ctx, res, "displayName");
- if (gpo->display_name == NULL) {
- ads_msgfree(ads, res);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(gpo->display_name);
gpo->name = ads_pull_string(ads, mem_ctx, res, "name");
- if (gpo->name == NULL) {
- ads_msgfree(ads, res);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(gpo->name);
/* ???, this is optional to have and what does it depend on, the 'flags' ?) */
gpo->machine_extensions = ads_pull_string(ads, mem_ctx, res, "gPCMachineExtensionNames");
gpo->user_extensions = ads_pull_string(ads, mem_ctx, res, "gPCUserExtensionNames");
- ads_msgfree(ads, res);
-
return ADS_ERROR(LDAP_SUCCESS);
}
+/****************************************************************
+ get a GROUP_POLICY_OBJECT structure based on different input paramters
+****************************************************************/
+
ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
const char *gpo_dn,
@@ -432,7 +437,7 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
struct GROUP_POLICY_OBJECT *gpo)
{
ADS_STATUS status;
- void *res = NULL;
+ LDAPMessage *res = NULL;
char *dn;
const char *filter;
const char *attrs[] = { "cn", "displayName", "flags", "gPCFileSysPath",
@@ -460,9 +465,7 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
"(&(objectclass=groupPolicyContainer)(%s=%s))",
display_name ? "displayName" : "name",
display_name ? display_name : guid_name);
- if (filter == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(filter);
status = ads_do_search_all(ads, ads->config.bind_path,
LDAP_SCOPE_SUBTREE, filter,
@@ -476,21 +479,27 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
if (ads_count_replies(ads, res) != 1) {
DEBUG(10,("ads_get_gpo: no result\n"));
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
dn = ads_get_dn(ads, res);
if (dn == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
status = ads_parse_gpo(ads, mem_ctx, res, dn, gpo);
-
+ ads_msgfree(ads, res);
ads_memfree(ads, dn);
return status;
}
+/****************************************************************
+ add a gplink to the GROUP_POLICY_OBJECT linked list
+****************************************************************/
+
ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
struct GROUP_POLICY_OBJECT **gpo_list,
@@ -522,9 +531,7 @@ ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
}
new_gpo = TALLOC_P(mem_ctx, struct GROUP_POLICY_OBJECT);
- if (new_gpo == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(new_gpo);
ZERO_STRUCTP(new_gpo);
@@ -545,6 +552,10 @@ ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
return ADS_ERROR(LDAP_SUCCESS);
}
+/****************************************************************
+ get the full list of GROUP_POLICY_OBJECTs for a given dn
+****************************************************************/
+
ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
const char *dn,
@@ -678,3 +689,5 @@ ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
return ADS_ERROR(LDAP_SUCCESS);
}
+
+#endif /* HAVE_LDAP */
diff --git a/source/libgpo/gpo_parse.c b/source/libgpo/gpo_parse.c
new file mode 100644
index 00000000000..ec272bf238b
--- /dev/null
+++ b/source/libgpo/gpo_parse.c
@@ -0,0 +1,299 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Group Policy Object Support
+ * Copyright (C) Guenther Deschner 2005-2006
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+#include "iniparser/src/iniparser.h"
+
+/****************************************************************
+ parse the local gpt.ini file
+****************************************************************/
+
+#define GPT_INI_SECTION_GENERAL "General"
+#define GPT_INI_PARAMETER_VERSION "Version"
+#define GPT_INI_PARAMETER_DISPLAYNAME "displayName"
+
+NTSTATUS parse_gpt_ini(TALLOC_CTX *mem_ctx, const char *filename, uint32 *version, char **display_name)
+{
+ NTSTATUS result;
+ uint32 v;
+ char *name = NULL;
+ dictionary *d;
+
+ d = iniparser_load(filename);
+ if (d == NULL) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if ((name = iniparser_getstring(d, GPT_INI_SECTION_GENERAL
+ ":"GPT_INI_PARAMETER_DISPLAYNAME, NULL)) == NULL) {
+ /* the default domain policy and the default domain controller
+ * policy never have a displayname in their gpt.ini file */
+ DEBUG(10,("parse_gpt_ini: no name in %s\n", filename));
+ }
+
+ if (name && display_name) {
+ *display_name = talloc_strdup(mem_ctx, name);
+ if (*display_name == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+ }
+
+ if ((v = iniparser_getint(d, GPT_INI_SECTION_GENERAL
+ ":"GPT_INI_PARAMETER_VERSION, Undefined)) == Undefined) {
+ DEBUG(10,("parse_gpt_ini: no version\n"));
+ result = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto out;
+ }
+
+ if (version) {
+ *version = v;
+ }
+
+ result = NT_STATUS_OK;
+ out:
+ if (d) {
+ iniparser_freedict(d);
+ }
+
+ return result;
+}
+
+#if 0 /* not yet */
+
+/****************************************************************
+ parse the Version section from gpttmpl file
+****************************************************************/
+
+#define GPTTMPL_SECTION_VERSION "Version"
+#define GPTTMPL_PARAMETER_REVISION "Revision"
+#define GPTTMPL_PARAMETER_SIGNATURE "signature"
+#define GPTTMPL_CHICAGO "$CHICAGO$" /* whatever this is good for... */
+#define GPTTMPL_SECTION_UNICODE "Unicode"
+#define GPTTMPL_PARAMETER_UNICODE "Unicode"
+
+static NTSTATUS parse_gpttmpl(dictionary *d, uint32 *version_out)
+{
+ const char *signature = NULL;
+ uint32 version;
+
+ if ((signature = iniparser_getstring(d, GPTTMPL_SECTION_VERSION
+ ":"GPTTMPL_PARAMETER_SIGNATURE, NULL)) == NULL) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (!strequal(signature, GPTTMPL_CHICAGO)) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if ((version = iniparser_getint(d, GPTTMPL_SECTION_VERSION
+ ":"GPTTMPL_PARAMETER_REVISION, Undefined)) == Undefined) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (version_out) {
+ *version_out = version;
+ }
+
+ /* treat that as boolean */
+ if ((!iniparser_getboolean(d, GPTTMPL_SECTION_UNICODE
+ ":"GPTTMPL_PARAMETER_UNICODE, Undefined)) == Undefined) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+ parse the "System Access" section from gpttmpl file
+****************************************************************/
+
+#define GPTTMPL_SECTION_SYSTEM_ACCESS "System Access"
+#define GPTTMPL_PARAMETER_MINPWDAGE "MinimumPasswordAge"
+#define GPTTMPL_PARAMETER_MAXPWDAGE "MaximumPasswordAge"
+#define GPTTMPL_PARAMETER_MINPWDLEN "MinimumPasswordLength"
+#define GPTTMPL_PARAMETER_PWDCOMPLEX "PasswordComplexity"
+#define GPTTMPL_PARAMETER_PWDHISTORY "PasswordHistorySize"
+#define GPTTMPL_PARAMETER_LOCKOUTCOUNT "LockoutBadCount"
+
+static NTSTATUS parse_gpttmpl_system_access(const char *filename)
+{
+ NTSTATUS status;
+ dictionary *d = NULL;
+ uint32 pwd_min_age, pwd_max_age, pwd_min_len, pwd_history;
+ uint32 lockout_count;
+ BOOL pwd_complex;
+ uint32 version;
+
+ d = iniparser_load(filename);
+ if (d == NULL) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ status = parse_gpttmpl(d, &version);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ status = NT_STATUS_INVALID_PARAMETER;
+
+ if ((pwd_min_age = iniparser_getint(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_MINPWDAGE, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ if ((pwd_max_age = iniparser_getint(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_MINPWDAGE, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ if ((pwd_min_len = iniparser_getint(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_MINPWDLEN, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ if ((pwd_complex = iniparser_getboolean(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_PWDCOMPLEX, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ if ((pwd_history = iniparser_getint(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_PWDHISTORY, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ if ((lockout_count = iniparser_getint(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_LOCKOUTCOUNT, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ /* TODO ?
+ RequireLogonToChangePassword = 0
+ ForceLogoffWhenHourExpire = 0
+ ClearTextPassword = 0
+ */
+
+ status = NT_STATUS_OK;
+
+ out:
+ if (d) {
+ iniparser_freedict(d);
+ }
+
+ return status;
+}
+
+/****************************************************************
+ parse the "Kerberos Policy" section from gpttmpl file
+****************************************************************/
+
+#define GPTTMPL_SECTION_KERBEROS_POLICY "Kerberos Policy"
+#define GPTTMPL_PARAMETER_MAXTKTAGE "MaxTicketAge"
+#define GPTTMPL_PARAMETER_MAXRENEWAGE "MaxRenewAge"
+#define GPTTMPL_PARAMETER_MAXTGSAGE "MaxServiceAge"
+#define GPTTMPL_PARAMETER_MAXCLOCKSKEW "MaxClockSkew"
+#define GPTTMPL_PARAMETER_TKTVALIDATECLIENT "TicketValidateClient"
+
+static NTSTATUS parse_gpttmpl_kerberos_policy(const char *filename)
+{
+ NTSTATUS status;
+ dictionary *d = NULL;
+ uint32 tkt_max_age, tkt_max_renew, tgs_max_age, max_clock_skew;
+ BOOL tkt_validate;
+ uint32 version;
+
+ d = iniparser_load(filename);
+ if (d == NULL) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ status = parse_gpttmpl(d, &version);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ status = NT_STATUS_INVALID_PARAMETER;
+
+ if ((tkt_max_age = iniparser_getint(d, GPTTMPL_SECTION_KERBEROS_POLICY
+ ":"GPTTMPL_PARAMETER_MAXTKTAGE, Undefined)) != Undefined) {
+ goto out;
+ }
+
+ if ((tkt_max_renew = iniparser_getint(d, GPTTMPL_SECTION_KERBEROS_POLICY
+ ":"GPTTMPL_PARAMETER_MAXRENEWAGE, Undefined)) != Undefined) {
+ goto out;
+ }
+
+ if ((tgs_max_age = iniparser_getint(d, GPTTMPL_SECTION_KERBEROS_POLICY
+ ":"GPTTMPL_PARAMETER_MAXTGSAGE, Undefined)) != Undefined) {
+ goto out;
+ }
+
+ if ((max_clock_skew = iniparser_getint(d, GPTTMPL_SECTION_KERBEROS_POLICY
+ ":"GPTTMPL_PARAMETER_MAXCLOCKSKEW, Undefined)) != Undefined) {
+ goto out;
+ }
+
+ if ((tkt_validate = iniparser_getboolean(d, GPTTMPL_SECTION_KERBEROS_POLICY
+ ":"GPTTMPL_PARAMETER_TKTVALIDATECLIENT, Undefined)) != Undefined) {
+ goto out;
+ }
+
+ status = NT_STATUS_OK;
+
+ out:
+ if (d) {
+ iniparser_freedict(d);
+ }
+
+ return status;
+}
+
+#endif
+
+/*
+
+perfectly parseable with iniparser:
+
+{GUID}/Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf
+
+
+[Unicode]
+Unicode=yes
+[System Access]
+MinimumPasswordAge = 1
+MaximumPasswordAge = 42
+MinimumPasswordLength = 7
+PasswordComplexity = 1
+PasswordHistorySize = 24
+LockoutBadCount = 0
+RequireLogonToChangePassword = 0
+ForceLogoffWhenHourExpire = 0
+ClearTextPassword = 0
+[Kerberos Policy]
+MaxTicketAge = 10
+MaxRenewAge = 7
+MaxServiceAge = 600
+MaxClockSkew = 5
+TicketValidateClient = 1
+[Version]
+signature="$CHICAGO$"
+Revision=1
+*/
diff --git a/source/libads/gpo_util.c b/source/libgpo/gpo_util.c
index 8f913c19714..bd11becad03 100644
--- a/source/libads/gpo_util.c
+++ b/source/libgpo/gpo_util.c
@@ -1,7 +1,7 @@
/*
* Unix SMB/CIFS implementation.
* Group Policy Object Support
- * Copyright (C) Guenther Deschner 2005
+ * Copyright (C) Guenther Deschner 2005-2006
*
* 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
@@ -20,10 +20,12 @@
#include "includes.h"
+#ifdef HAVE_LDAP
+
#define DEFAULT_DOMAIN_POLICY "Default Domain Policy"
#define DEFAULT_DOMAIN_CONTROLLERS_POLICY "Default Domain Controllers Policy"
-/* should we store a parsed guid ? UUID_FLAT guid; */
+/* should we store a parsed guid ? */
struct gpo_table {
const char *name;
const char *guid_string;
@@ -35,6 +37,7 @@ struct snapin_table {
ADS_STATUS (*snapin_fn)(ADS_STRUCT *, TALLOC_CTX *mem_ctx, const char *, const char *);
};
+#if 0 /* unused */
static struct gpo_table gpo_default_policy[] = {
{ DEFAULT_DOMAIN_POLICY,
"31B2F340-016D-11D2-945F-00C04FB984F9" },
@@ -42,7 +45,7 @@ static struct gpo_table gpo_default_policy[] = {
"6AC1786C-016F-11D2-945F-00C04fB984F9" },
{ NULL, NULL }
};
-
+#endif
/* the following is seen in gPCMachineExtensionNames or gPCUserExtensionNames */
@@ -125,6 +128,19 @@ static const char *guid_string_to_name(const char *guid_string, struct gpo_table
return NULL;
}
+static const char *snapin_guid_string_to_name(const char *guid_string,
+ struct snapin_table *table)
+{
+ int i;
+ for (i = 0; table[i].guid_string; i++) {
+ if (strequal(guid_string, table[i].guid_string)) {
+ return table[i].name;
+ }
+ }
+ return NULL;
+}
+
+#if 0 /* unused */
static const char *default_gpo_name_to_guid_string(const char *name)
{
return name_to_guid_string(name, gpo_default_policy);
@@ -134,6 +150,7 @@ static const char *default_gpo_guid_string_to_name(const char *guid)
{
return guid_string_to_name(guid, gpo_default_policy);
}
+#endif
const char *cse_gpo_guid_string_to_name(const char *guid)
{
@@ -147,34 +164,34 @@ static const char *cse_gpo_name_to_guid_string(const char *name)
const char *cse_snapin_gpo_guid_string_to_name(const char *guid)
{
- return guid_string_to_name(guid, gpo_cse_snapin_extensions);
+ return snapin_guid_string_to_name(guid, gpo_cse_snapin_extensions);
}
-void dump_gp_ext(struct GP_EXT *gp_ext)
+void dump_gp_ext(struct GP_EXT *gp_ext, int debuglevel)
{
- int lvl = 10;
+ int lvl = debuglevel;
int i;
if (gp_ext == NULL) {
return;
}
- DEBUG(lvl,("---------------------\n\n"));
- DEBUGADD(lvl,("name:\t\t\t%s\n", gp_ext->gp_extension));
+ DEBUG(lvl,("\t---------------------\n\n"));
+ DEBUGADD(lvl,("\tname:\t\t\t%s\n", gp_ext->gp_extension));
for (i=0; i< gp_ext->num_exts; i++) {
- DEBUGADD(lvl,("extension:\t\t\t%s\n", gp_ext->extensions_guid[i]));
- DEBUGADD(lvl,("extension (name):\t\t\t%s\n", gp_ext->extensions[i]));
+ DEBUGADD(lvl,("\textension:\t\t\t%s\n", gp_ext->extensions_guid[i]));
+ DEBUGADD(lvl,("\textension (name):\t\t\t%s\n", gp_ext->extensions[i]));
- DEBUGADD(lvl,("snapin:\t\t\t%s\n", gp_ext->snapins_guid[i]));
- DEBUGADD(lvl,("snapin (name):\t\t\t%s\n", gp_ext->snapins[i]));
+ DEBUGADD(lvl,("\tsnapin:\t\t\t%s\n", gp_ext->snapins_guid[i]));
+ DEBUGADD(lvl,("\tsnapin (name):\t\t\t%s\n", gp_ext->snapins[i]));
}
}
-void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo)
+void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo, int debuglevel)
{
- int lvl = 1;
+ int lvl = debuglevel;
if (gpo == NULL) {
return;
@@ -185,8 +202,10 @@ void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo)
DEBUGADD(lvl,("name:\t\t\t%s\n", gpo->name));
DEBUGADD(lvl,("displayname:\t\t%s\n", gpo->display_name));
DEBUGADD(lvl,("version:\t\t%d (0x%08x)\n", gpo->version, gpo->version));
- DEBUGADD(lvl,("version_user:\t\t%d (0x%04x)\n", gpo->version_user, gpo->version_user));
- DEBUGADD(lvl,("version_machine:\t%d (0x%04x)\n", gpo->version_machine, gpo->version_machine));
+ DEBUGADD(lvl,("version_user:\t\t%d (0x%04x)\n", GPO_VERSION_USER(gpo->version),
+ GPO_VERSION_USER(gpo->version)));
+ DEBUGADD(lvl,("version_machine:\t%d (0x%04x)\n", GPO_VERSION_MACHINE(gpo->version),
+ GPO_VERSION_MACHINE(gpo->version)));
DEBUGADD(lvl,("filesyspath:\t\t%s\n", gpo->file_sys_path));
DEBUGADD(lvl,("dspath:\t\t%s\n", gpo->ds_path));
@@ -232,7 +251,7 @@ void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo)
if (!ADS_ERR_OK(status)) {
return;
}
- dump_gp_ext(&gp_ext);
+ dump_gp_ext(&gp_ext, lvl);
}
if (gpo->user_extensions) {
@@ -246,7 +265,7 @@ void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo)
if (!ADS_ERR_OK(status)) {
return;
}
- dump_gp_ext(&gp_ext);
+ dump_gp_ext(&gp_ext, lvl);
}
};
@@ -302,7 +321,7 @@ void dump_gplink(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct GP_LINK *gp_link)
DEBUG(lvl,("get gpo for %s failed: %s\n", gp_link->link_names[i], ads_errstr(status)));
return;
}
- dump_gpo(mem_ctx, &gpo);
+ dump_gpo(mem_ctx, &gpo, lvl);
}
}
}
@@ -445,11 +464,9 @@ ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
struct GROUP_POLICY_OBJECT *gpo_list;
const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
char *filter, *dn;
- void *res = NULL;
+ LDAPMessage *res = NULL;
uint32 uac;
- return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
-
filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", hostname);
if (filter == NULL) {
return ADS_ERROR(LDAP_NO_MEMORY);
@@ -464,27 +481,37 @@ ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
}
if (ads_count_replies(ads, res) != 1) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
dn = ads_get_dn(ads, res);
if (dn == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
+ ads_msgfree(ads, res);
+ ads_memfree(ads, dn);
return ADS_ERROR(LDAP_NO_MEMORY);
}
+ ads_msgfree(ads, res);
+
if (!(uac & UF_WORKSTATION_TRUST_ACCOUNT)) {
+ ads_memfree(ads, dn);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
status = ads_get_gpo_list(ads, mem_ctx, dn, GPO_LIST_FLAG_MACHINE, &gpo_list);
if (!ADS_ERR_OK(status)) {
+ ads_memfree(ads, dn);
return status;
}
+ ads_memfree(ads, dn);
+
status = gpo_process_gpo_list(ads, mem_ctx, &gpo_list,
cse_gpo_name_to_guid_string("Security"),
GPO_LIST_FLAG_MACHINE);
@@ -494,3 +521,128 @@ ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
return ADS_ERROR(LDAP_SUCCESS);
}
+
+/****************************************************************
+ check wether the version number in a GROUP_POLICY_OBJECT match those of the
+ locally stored version. If not, fetch the required policy via CIFS
+****************************************************************/
+
+NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ struct GROUP_POLICY_OBJECT *gpo,
+ struct cli_state **cli_out)
+{
+ NTSTATUS result;
+ char *server, *share, *nt_path, *unix_path;
+ uint32 sysvol_gpt_version = 0;
+ char *display_name;
+ struct cli_state *cli = NULL;
+
+ result = ads_gpo_explode_filesyspath(ads, mem_ctx, gpo->file_sys_path,
+ &server, &share, &nt_path, &unix_path);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ result = ads_gpo_get_sysvol_gpt_version(ads, mem_ctx,
+ unix_path,
+ &sysvol_gpt_version,
+ &display_name);
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_FILE)) {
+ DEBUG(10,("check_refresh_gpo: failed to get local gpt version: %s\n",
+ nt_errstr(result)));
+ goto out;
+ }
+
+ while (gpo->version > sysvol_gpt_version) {
+
+ DEBUG(1,("check_refresh_gpo: need to refresh GPO\n"));
+
+ if (*cli_out == NULL) {
+
+ result = cli_full_connection(&cli, global_myname(),
+ server, /* ads->config.ldap_server_name, */
+ NULL, 0,
+ share, "A:",
+ ads->auth.user_name, NULL, ads->auth.password,
+ CLI_FULL_CONNECTION_USE_KERBEROS,
+ Undefined, NULL);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("check_refresh_gpo: failed to connect: %s\n", nt_errstr(result)));
+ goto out;
+ }
+
+ *cli_out = cli;
+ }
+
+ result = ads_fetch_gpo_files(ads, mem_ctx, *cli_out, gpo);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ result = ads_gpo_get_sysvol_gpt_version(ads, mem_ctx,
+ unix_path,
+ &sysvol_gpt_version,
+ &display_name);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("check_refresh_gpo: failed to get local gpt version: %s\n",
+ nt_errstr(result)));
+ goto out;
+ }
+
+ if (gpo->version == sysvol_gpt_version) {
+ break;
+ }
+ }
+
+ DEBUG(10,("Name:\t\t\t%s\n", gpo->display_name));
+ DEBUGADD(10,("sysvol GPT version:\t%d (user: %d, machine: %d)\n",
+ sysvol_gpt_version,
+ GPO_VERSION_USER(sysvol_gpt_version),
+ GPO_VERSION_MACHINE(sysvol_gpt_version)));
+ DEBUGADD(10,("LDAP GPO version:\t%d (user: %d, machine: %d)\n",
+ gpo->version,
+ GPO_VERSION_USER(gpo->version),
+ GPO_VERSION_MACHINE(gpo->version)));
+
+ result = NT_STATUS_OK;
+
+ out:
+ return result;
+
+}
+
+/****************************************************************
+ check wether the version numbers in the gpo_list match the locally stored, if
+ not, go and get each required GPO via CIFS
+ ****************************************************************/
+
+NTSTATUS check_refresh_gpo_list(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ struct GROUP_POLICY_OBJECT *gpo_list)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct cli_state *cli = NULL;
+ struct GROUP_POLICY_OBJECT *gpo;
+
+ for (gpo = gpo_list; gpo; gpo = gpo->next) {
+
+ result = check_refresh_gpo(ads, mem_ctx, gpo, &cli);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+ }
+
+ result = NT_STATUS_OK;
+
+ out:
+ if (cli) {
+ cli_shutdown(cli);
+ }
+
+ return result;
+}
+
+#endif /* HAVE_LDAP */
diff --git a/source/libsmb/clirap2.c b/source/libsmb/clirap2.c
index 147683689d6..d6a44f4ea22 100644
--- a/source/libsmb/clirap2.c
+++ b/source/libsmb/clirap2.c
@@ -220,7 +220,7 @@ int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo )
/* Allocate data. */
data_size = MAX(soffset + strlen(grinfo->comment) + 1, 1024);
- data = SMB_MALLOC(data_size);
+ data = SMB_MALLOC_ARRAY(char, data_size);
if (!data) {
DEBUG (1, ("Malloc fail\n"));
return -1;
@@ -1414,6 +1414,62 @@ BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
return(res == 0 || res == ERRmoredata);
}
+BOOL cli_get_server_name(TALLOC_CTX *mem_ctx, struct cli_state *cli,
+ char **servername)
+{
+ char *rparam = NULL;
+ char *rdata = NULL;
+ unsigned int rdrcnt,rprcnt;
+ char *p;
+ char param[WORDSIZE /* api number */
+ +sizeof(RAP_WserverGetInfo_REQ) /* req string */
+ +sizeof(RAP_SERVER_INFO_L1) /* return string */
+ +WORDSIZE /* info level */
+ +WORDSIZE]; /* buffer size */
+ BOOL res = False;
+ fstring tmp;
+
+ /* send a SMBtrans command with api NetServerGetInfo */
+ p = make_header(param, RAP_WserverGetInfo,
+ RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
+ PUTWORD(p, 1); /* info level */
+ PUTWORD(p, CLI_BUFFER_SIZE);
+
+ if (!cli_api(cli,
+ param, PTR_DIFF(p,param), 8, /* params, length, max */
+ NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
+ &rparam, &rprcnt, /* return params, return size */
+ &rdata, &rdrcnt /* return data, return size */
+ )) {
+ goto failed;
+ }
+
+ if (GETRES(rparam) != 0) {
+ goto failed;
+ }
+
+ if (rdrcnt < 16) {
+ DEBUG(10, ("invalid data count %d, expected >= 16\n", rdrcnt));
+ goto failed;
+ }
+
+ if (pull_ascii(tmp, rdata, sizeof(tmp)-1, 16, STR_TERMINATE) == -1) {
+ DEBUG(10, ("pull_ascii failed\n"));
+ goto failed;
+ }
+
+ if (!(*servername = talloc_strdup(mem_ctx, tmp))) {
+ DEBUG(1, ("talloc_strdup failed\n"));
+ goto failed;
+ }
+
+ res = True;
+
+ failed:
+ SAFE_FREE(rparam);
+ SAFE_FREE(rdata);
+ return res;
+}
/*************************************************************************
*
diff --git a/source/utils/debug2html.c b/source/utils/debug2html.c
index bec4d81ae2b..6d1b2b25352 100644
--- a/source/utils/debug2html.c
+++ b/source/utils/debug2html.c
@@ -145,6 +145,8 @@ static void newblock( dbg_Token old, dbg_Token newtok )
case dbg_lineno:
(void)printf( ")" );
break;
+ default:
+ break;
}
switch( newtok )
@@ -158,6 +160,8 @@ static void newblock( dbg_Token old, dbg_Token newtok )
case dbg_lineno:
(void)printf( "(" );
break;
+ default:
+ break;
}
} /* newblock */
diff --git a/source/utils/log2pcaphex.c b/source/utils/log2pcaphex.c
index 24412cbe85e..aa68cf09c96 100644
--- a/source/utils/log2pcaphex.c
+++ b/source/utils/log2pcaphex.c
@@ -142,7 +142,7 @@ void print_netbios_packet(FILE *out, unsigned char *data, long length, long actu
long newlen;
newlen = length+sizeof(HDR_IP)+sizeof(HDR_TCP);
- newdata = malloc(newlen);
+ newdata = (unsigned char *)malloc(newlen);
HDR_IP.packet_length = htons(newlen);
HDR_TCP.window = htons(0x2000);
@@ -165,7 +165,7 @@ void read_log_msg(FILE *in, unsigned char **_buffer, long *buffersize, long *dat
int tmp; long i;
assert(fscanf(in, " size=%ld\n", buffersize));
*buffersize+=4; /* for netbios */
- buffer = malloc(*buffersize);
+ buffer = (unsigned char *)malloc(*buffersize);
memset(buffer, 0, *buffersize);
/* NetBIOS */
buffer[0] = 0x00;
diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index acd181c54a0..82c57e8723d 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -4,6 +4,7 @@
Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
+ Copyright (C) 2006 Gerald (Jerry) Carter (jerry@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
@@ -27,37 +28,37 @@
int net_ads_usage(int argc, const char **argv)
{
- d_printf(
-"\nnet ads join <org_unit>"\
-"\n\tjoins the local machine to a ADS realm\n"\
-"\nnet ads leave"\
-"\n\tremoves the local machine from a ADS realm\n"\
-"\nnet ads testjoin"\
-"\n\ttests that an exiting join is OK\n"\
-"\nnet ads user"\
-"\n\tlist, add, or delete users in the realm\n"\
-"\nnet ads group"\
-"\n\tlist, add, or delete groups in the realm\n"\
-"\nnet ads info"\
-"\n\tshows some info on the server\n"\
-"\nnet ads status"\
-"\n\tdump the machine account details to stdout\n"
-"\nnet ads lookup"\
-"\n\tperform a CLDAP search on the server\n"
-"\nnet ads password <username@realm> <password> -Uadmin_username@realm%%admin_pass"\
-"\n\tchange a user's password using an admin account"\
-"\n\t(note: use realm in UPPERCASE, prompts if password is obmitted)\n"\
-"\nnet ads changetrustpw"\
-"\n\tchange the trust account password of this machine in the AD tree\n"\
-"\nnet ads printer [info | publish | remove] <printername> <servername>"\
-"\n\t lookup, add, or remove directory entry for a printer\n"\
-"\nnet ads search"\
-"\n\tperform a raw LDAP search and dump the results\n"
-"\nnet ads dn"\
-"\n\tperform a raw LDAP search and dump attributes of a particular DN\n"
-"\nnet ads keytab"\
-"\n\tcreates and updates the kerberos system keytab file\n"
- );
+ d_printf("join [createupn[=principal]] [createcomputer=<org_unit>]\n");
+ d_printf(" Join the local machine to a ADS realm\n");
+ d_printf("leave\n");
+ d_printf(" Remove the local machine from a ADS realm\n");
+ d_printf("testjoin\n");
+ d_printf(" Validates the machine account in the domain\n");
+ d_printf("user\n");
+ d_printf(" List, add, or delete users in the realm\n");
+ d_printf("group\n");
+ d_printf(" List, add, or delete groups in the realm\n");
+ d_printf("info\n");
+ d_printf(" Displays details regarding a specific AD server\n");
+ d_printf("status\n");
+ d_printf(" Display details regarding the machine's account in AD\n");
+ d_printf("lookup\n");
+ d_printf(" Performs CLDAP query of AD domain controllers\n");
+ d_printf("password <username@realm> <password> -Uadmin_username@realm%%admin_pass\n");
+ d_printf(" Change a user's password using an admin account\n");
+ d_printf(" (note: use realm in UPPERCASE, prompts if password is obmitted)\n");
+ d_printf("changetrustpw\n");
+ d_printf(" Change the trust account password of this machine in the AD tree\n");
+ d_printf("printer [info | publish | remove] <printername> <servername>\n");
+ d_printf(" Lookup, add, or remove directory entry for a printer\n");
+ d_printf("{search,dn,sid}\n");
+ d_printf(" Issue LDAP search queries using a general filter, by DN, or by SID\n");
+ d_printf("keytab\n");
+ d_printf(" Manage a local keytab file based on the machine account in AD\n");
+ d_printf("dns\n");
+ d_printf(" Issue a dynamic DNS update request the server's hostname\n");
+ d_printf(" (using the machine credentials)\n");
+
return -1;
}
@@ -85,7 +86,7 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads)
return -1;
}
- d_printf("Information for Domain Controller: %s\n\n",
+ d_printf("Information for Domain Controller: %s\n\n",
inet_ntoa(ads->ldap_ip));
d_printf("Response Type: ");
@@ -100,29 +101,29 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads)
d_printf("0x%x\n", reply.type);
break;
}
- d_printf("GUID: %s\n",
- smb_uuid_string_static(smb_uuid_unpack_static(reply.guid)));
+ d_printf("GUID: %s\n",
+ smb_uuid_string_static(smb_uuid_unpack_static(reply.guid)));
d_printf("Flags:\n"
- "\tIs a PDC: %s\n"
- "\tIs a GC of the forest: %s\n"
- "\tIs an LDAP server: %s\n"
- "\tSupports DS: %s\n"
- "\tIs running a KDC: %s\n"
- "\tIs running time services: %s\n"
- "\tIs the closest DC: %s\n"
- "\tIs writable: %s\n"
- "\tHas a hardware clock: %s\n"
- "\tIs a non-domain NC serviced by LDAP server: %s\n",
- (reply.flags & ADS_PDC) ? "yes" : "no",
- (reply.flags & ADS_GC) ? "yes" : "no",
- (reply.flags & ADS_LDAP) ? "yes" : "no",
- (reply.flags & ADS_DS) ? "yes" : "no",
- (reply.flags & ADS_KDC) ? "yes" : "no",
- (reply.flags & ADS_TIMESERV) ? "yes" : "no",
- (reply.flags & ADS_CLOSEST) ? "yes" : "no",
- (reply.flags & ADS_WRITABLE) ? "yes" : "no",
- (reply.flags & ADS_GOOD_TIMESERV) ? "yes" : "no",
- (reply.flags & ADS_NDNC) ? "yes" : "no");
+ "\tIs a PDC: %s\n"
+ "\tIs a GC of the forest: %s\n"
+ "\tIs an LDAP server: %s\n"
+ "\tSupports DS: %s\n"
+ "\tIs running a KDC: %s\n"
+ "\tIs running time services: %s\n"
+ "\tIs the closest DC: %s\n"
+ "\tIs writable: %s\n"
+ "\tHas a hardware clock: %s\n"
+ "\tIs a non-domain NC serviced by LDAP server: %s\n",
+ (reply.flags & ADS_PDC) ? "yes" : "no",
+ (reply.flags & ADS_GC) ? "yes" : "no",
+ (reply.flags & ADS_LDAP) ? "yes" : "no",
+ (reply.flags & ADS_DS) ? "yes" : "no",
+ (reply.flags & ADS_KDC) ? "yes" : "no",
+ (reply.flags & ADS_TIMESERV) ? "yes" : "no",
+ (reply.flags & ADS_CLOSEST) ? "yes" : "no",
+ (reply.flags & ADS_WRITABLE) ? "yes" : "no",
+ (reply.flags & ADS_GOOD_TIMESERV) ? "yes" : "no",
+ (reply.flags & ADS_NDNC) ? "yes" : "no");
printf("Forest:\t\t\t%s\n", reply.forest);
printf("Domain:\t\t\t%s\n", reply.domain);
@@ -134,8 +135,8 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads)
if (*reply.unk) printf("Unk:\t\t\t%s\n", reply.unk);
if (*reply.user_name) printf("User name:\t%s\n", reply.user_name);
- printf("Server Site Name:\t\t%s\n", reply.server_site_name);
- printf("Client Site Name:\t\t%s\n", reply.client_site_name);
+ printf("Server Site Name :\t\t%s\n", reply.server_site_name);
+ printf("Client Site Name :\t\t%s\n", reply.client_site_name);
d_printf("NT Version: %d\n", reply.version);
d_printf("LMNT Token: %.2x\n", reply.lmnt_token);
@@ -144,6 +145,7 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads)
return 0;
}
+
/*
this implements the CLDAP based netlogon lookup requests
for finding the domain controller of a ADS domain
@@ -152,7 +154,7 @@ static int net_ads_lookup(int argc, const char **argv)
{
ADS_STRUCT *ads;
- if ((ads = ads_startup_nobind(False)) == NULL) {
+ if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) {
d_fprintf(stderr, "Didn't find the cldap server!\n");
return -1;
}
@@ -171,7 +173,7 @@ static int net_ads_info(int argc, const char **argv)
{
ADS_STRUCT *ads;
- if ((ads = ads_startup_nobind(False)) == NULL) {
+ if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) {
d_fprintf(stderr, "Didn't find the ldap server!\n");
return -1;
}
@@ -207,9 +209,9 @@ static void use_in_memory_ccache(void) {
setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
}
-static ADS_STRUCT *ads_startup_int(BOOL only_own_domain, uint32 auth_flags)
+static ADS_STATUS ads_startup_int(BOOL only_own_domain, uint32 auth_flags, ADS_STRUCT **ads_ret)
{
- ADS_STRUCT *ads;
+ ADS_STRUCT *ads = NULL;
ADS_STATUS status;
BOOL need_password = False;
BOOL second_time = False;
@@ -219,13 +221,15 @@ static ADS_STRUCT *ads_startup_int(BOOL only_own_domain, uint32 auth_flags)
BOOL closest_dc = False;
BOOL site_matches = False;
- /* lp_realm() should be handled by a command line param,
+ /* lp_realm() should be handled by a command line param,
However, the join requires that realm be set in smb.conf
and compares our realm with the remote server's so this is
ok until someone needs more flexibility */
+ *ads_ret = NULL;
+
retry_connect:
- if (only_own_domain) {
+ if (only_own_domain) {
realm = lp_realm();
} else {
realm = assume_own_realm();
@@ -243,18 +247,24 @@ retry_connect:
retry:
if (!opt_password && need_password && !opt_machine_pass) {
- char *prompt;
+ char *prompt = NULL;
asprintf(&prompt,"%s's password: ", opt_user_name);
+ if (!prompt) {
+ ads_destroy(&ads);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
opt_password = getpass(prompt);
free(prompt);
}
if (opt_password) {
use_in_memory_ccache();
+ SAFE_FREE(ads->auth.password);
ads->auth.password = smb_xstrdup(opt_password);
}
ads->auth.flags |= auth_flags;
+ SAFE_FREE(ads->auth.user_name);
ads->auth.user_name = smb_xstrdup(opt_user_name);
/*
@@ -263,9 +273,10 @@ retry:
* This is only used to establish the connection.
*/
if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
- *cp++ = '\0';
- ads->auth.realm = smb_xstrdup(cp);
- strupper_m(ads->auth.realm);
+ *cp++ = '\0';
+ SAFE_FREE(ads->auth.realm);
+ ads->auth.realm = smb_xstrdup(cp);
+ strupper_m(ads->auth.realm);
}
status = ads_connect(ads);
@@ -276,7 +287,7 @@ retry:
NT_STATUS_NO_LOGON_SERVERS)) {
DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
ads_destroy(&ads);
- return NULL;
+ return status;
}
if (!need_password && !second_time) {
@@ -284,8 +295,8 @@ retry:
second_time = True;
goto retry;
} else {
- DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
- return NULL;
+ ads_destroy(&ads);
+ return status;
}
}
@@ -309,22 +320,24 @@ retry:
namecache_delete(ads->server.workgroup, 0x1C);
ads_destroy(&ads);
+ ads = NULL;
- goto retry_connect;
+ goto retry_connect;
}
}
- return ads;
+ *ads_ret = ads;
+ return status;
}
-ADS_STRUCT *ads_startup(BOOL only_own_domain)
+ADS_STATUS ads_startup(BOOL only_own_domain, ADS_STRUCT **ads)
{
- return ads_startup_int(only_own_domain, 0);
+ return ads_startup_int(only_own_domain, 0, ads);
}
-ADS_STRUCT *ads_startup_nobind(BOOL only_own_domain)
+ADS_STATUS ads_startup_nobind(BOOL only_own_domain, ADS_STRUCT **ads)
{
- return ads_startup_int(only_own_domain, ADS_AUTH_NO_BIND);
+ return ads_startup_int(only_own_domain, ADS_AUTH_NO_BIND, ads);
}
/*
@@ -343,10 +356,10 @@ static int net_ads_check_int(const char *realm, const char *workgroup, const cha
ads->auth.flags |= ADS_AUTH_NO_BIND;
- status = ads_connect(ads);
- if ( !ADS_ERR_OK(status) ) {
- return -1;
- }
+ status = ads_connect(ads);
+ if ( !ADS_ERR_OK(status) ) {
+ return -1;
+ }
ads_destroy(&ads);
return 0;
@@ -361,7 +374,6 @@ int net_ads_check(void)
{
return net_ads_check_int(NULL, opt_workgroup, opt_host);
}
-
/*
determine the netbios workgroup name for a domain
*/
@@ -370,16 +382,16 @@ static int net_ads_workgroup(int argc, const char **argv)
ADS_STRUCT *ads;
struct cldap_netlogon_reply reply;
- if ((ads = ads_startup_nobind(False)) == NULL) {
+ if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) {
d_fprintf(stderr, "Didn't find the cldap server!\n");
return -1;
}
-
+
if (!ads->config.realm) {
ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup);
ads->ldap_port = 389;
}
-
+
if ( !ads_cldap_netlogon( inet_ntoa(ads->ldap_ip), ads->server.realm, &reply ) ) {
d_fprintf(stderr, "CLDAP query failed!\n");
return -1;
@@ -388,11 +400,12 @@ static int net_ads_workgroup(int argc, const char **argv)
d_printf("Workgroup: %s\n", reply.netbios_domain);
ads_destroy(&ads);
-
+
return 0;
}
+
static BOOL usergrp_display(char *field, void **values, void *data_area)
{
char **disp_fields = (char **) data_area;
@@ -431,13 +444,13 @@ static int ads_user_add(int argc, const char **argv)
ADS_STRUCT *ads;
ADS_STATUS status;
char *upn, *userdn;
- void *res=NULL;
+ LDAPMessage *res=NULL;
int rc = -1;
char *ou_str = NULL;
if (argc < 1) return net_ads_user_usage(argc, argv);
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -508,7 +521,7 @@ static int ads_user_info(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS rc;
- void *res;
+ LDAPMessage *res;
const char *attrs[] = {"memberOf", NULL};
char *searchstring=NULL;
char **grouplist;
@@ -519,15 +532,15 @@ static int ads_user_info(int argc, const char **argv)
}
escaped_user = escape_ldap_string_alloc(argv[0]);
-
- if (!(ads = ads_startup(False))) {
- return -1;
- }
if (!escaped_user) {
d_fprintf(stderr, "ads_user_info: failed to escape user %s\n", argv[0]);
- ads_destroy(&ads);
- return -1;
+ return -1;
+ }
+
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
+ SAFE_FREE(escaped_user);
+ return -1;
}
asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
@@ -537,10 +550,12 @@ static int ads_user_info(int argc, const char **argv)
if (!ADS_ERR_OK(rc)) {
d_fprintf(stderr, "ads_search: %s\n", ads_errstr(rc));
ads_destroy(&ads);
+ SAFE_FREE(escaped_user);
return -1;
}
- grouplist = ldap_get_values(ads->ld, res, "memberOf");
+ grouplist = ldap_get_values((LDAP *)ads->ld,
+ (LDAPMessage *)res, "memberOf");
if (grouplist) {
int i;
@@ -555,6 +570,7 @@ static int ads_user_info(int argc, const char **argv)
ads_msgfree(ads, res);
ads_destroy(&ads);
+ SAFE_FREE(escaped_user);
return 0;
}
@@ -562,20 +578,20 @@ static int ads_user_delete(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS rc;
- void *res = NULL;
+ LDAPMessage *res = NULL;
char *userdn;
if (argc < 1) {
return net_ads_user_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
rc = ads_find_user_acct(ads, &res, argv[0]);
if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
- DEBUG(0, ("User %s does not exist\n", argv[0]));
+ d_printf("User %s does not exist.\n", argv[0]);
ads_msgfree(ads, res);
ads_destroy(&ads);
return -1;
@@ -610,7 +626,7 @@ int net_ads_user(int argc, const char **argv)
char *disp_fields[2] = {NULL, NULL};
if (argc == 0) {
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -625,7 +641,7 @@ int net_ads_user(int argc, const char **argv)
shortattrs, usergrp_display,
disp_fields);
ads_destroy(&ads);
- return 0;
+ return ADS_ERR_OK(rc) ? 0 : -1;
}
return net_run_function(argc, argv, func, net_ads_user_usage);
@@ -640,7 +656,7 @@ static int ads_group_add(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS status;
- void *res=NULL;
+ LDAPMessage *res=NULL;
int rc = -1;
char *ou_str = NULL;
@@ -648,7 +664,7 @@ static int ads_group_add(int argc, const char **argv)
return net_ads_group_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -692,20 +708,20 @@ static int ads_group_delete(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS rc;
- void *res = NULL;
+ LDAPMessage *res = NULL;
char *groupdn;
if (argc < 1) {
return net_ads_group_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
rc = ads_find_user_acct(ads, &res, argv[0]);
if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
- DEBUG(0, ("Group %s does not exist\n", argv[0]));
+ d_printf("Group %s does not exist.\n", argv[0]);
ads_msgfree(ads, res);
ads_destroy(&ads);
return -1;
@@ -739,7 +755,7 @@ int net_ads_group(int argc, const char **argv)
char *disp_fields[2] = {NULL, NULL};
if (argc == 0) {
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -754,7 +770,7 @@ int net_ads_group(int argc, const char **argv)
disp_fields);
ads_destroy(&ads);
- return 0;
+ return ADS_ERR_OK(rc) ? 0 : -1;
}
return net_run_function(argc, argv, func, net_ads_group_usage);
}
@@ -763,9 +779,9 @@ static int net_ads_status(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS rc;
- void *res;
+ LDAPMessage *res;
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
@@ -803,7 +819,7 @@ static int net_ads_leave(int argc, const char **argv)
struct cli_state *cli = NULL;
TALLOC_CTX *ctx;
DOM_SID *dom_sid = NULL;
- char *short_domain_name = NULL;
+ char *short_domain_name = NULL;
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
@@ -811,28 +827,26 @@ static int net_ads_leave(int argc, const char **argv)
}
if (!(ctx = talloc_init("net_ads_leave"))) {
- DEBUG(0, ("Could not initialise talloc context\n"));
+ d_fprintf(stderr, "Could not initialise talloc context.\n");
return -1;
}
- /* The finds a DC and takes care of getting the
+ /* The finds a DC and takes care of getting the
user creds if necessary */
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
/* make RPC calls here */
- if ( !NT_STATUS_IS_OK(connect_to_ipc_krb5(&cli, &ads->ldap_ip,
+ if ( !NT_STATUS_IS_OK(connect_to_ipc_krb5(&cli, &ads->ldap_ip,
ads->config.ldap_server_name)) )
{
goto done;
}
-
- if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli,
- &short_domain_name, &dom_sid )) )
- {
+
+ if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, &short_domain_name, &dom_sid )) ) {
goto done;
}
@@ -840,7 +854,7 @@ static int net_ads_leave(int argc, const char **argv)
status = netdom_leave_domain(ctx, cli, dom_sid);
- /* Ty and delete it via LDAP - the old way we used to. */
+ /* Try and delete it via LDAP - the old way we used to. */
adsret = ads_leave_realm(ads, global_myname());
if (ADS_ERR_OK(adsret)) {
@@ -861,7 +875,7 @@ static int net_ads_leave(int argc, const char **argv)
done:
- if ( cli )
+ if ( cli )
cli_shutdown(cli);
ads_destroy(&ads);
@@ -870,23 +884,25 @@ done:
return ret;
}
-static int net_ads_join_ok(void)
+static NTSTATUS net_ads_join_ok(void)
{
ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
- return -1;
+ return NT_STATUS_ACCESS_DENIED;
}
net_use_machine_password();
- if (!(ads = ads_startup(True))) {
- return -1;
+ status = ads_startup(True, &ads);
+ if (!ADS_ERR_OK(status)) {
+ return ads_ntstatus(status);
}
ads_destroy(&ads);
- return 0;
+ return NT_STATUS_OK;
}
/*
@@ -894,11 +910,14 @@ static int net_ads_join_ok(void)
*/
int net_ads_testjoin(int argc, const char **argv)
{
+ NTSTATUS status;
use_in_memory_ccache();
/* Display success or failure */
- if (net_ads_join_ok() != 0) {
- fprintf(stderr,"Join to domain is not valid\n");
+ status = net_ads_join_ok();
+ if (!NT_STATUS_IS_OK(status)) {
+ fprintf(stderr,"Join to domain is not valid: %s\n",
+ get_friendly_nt_error_msg(status));
return -1;
}
@@ -910,62 +929,66 @@ int net_ads_testjoin(int argc, const char **argv)
Simple configu checks before beginning the join
********************************************************************/
-static int check_ads_config( void )
+static NTSTATUS check_ads_config( void )
{
if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
d_printf("Host is not configured as a member server.\n");
- return -1;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
}
if (strlen(global_myname()) > 15) {
d_printf("Our netbios name can be at most 15 chars long, "
- "\"%s\" is %u chars long\n",
- global_myname(), (unsigned int)strlen(global_myname()));
- return -1;
+ "\"%s\" is %u chars long\n", global_myname(),
+ (unsigned int)strlen(global_myname()));
+ return NT_STATUS_NAME_TOO_LONG;
}
if ( lp_security() == SEC_ADS && !*lp_realm()) {
d_fprintf(stderr, "realm must be set in in smb.conf for ADS "
"join to succeed.\n");
- return -1;
+ return NT_STATUS_INVALID_PARAMETER;
}
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
- return -1;
+ /* This is a good bet for failure of secrets_init ... */
+ return NT_STATUS_ACCESS_DENIED;
}
-
- return 0;
+
+ return NT_STATUS_OK;
}
/*******************************************************************
Do the domain join
********************************************************************/
-static int net_join_domain( TALLOC_CTX *ctx, const char *servername,
- struct in_addr *ip, char **domain, DOM_SID **dom_sid, const char *password )
+static NTSTATUS net_join_domain(TALLOC_CTX *ctx, const char *servername,
+ struct in_addr *ip, char **domain,
+ DOM_SID **dom_sid,
+ const char *password)
{
- int ret = -1;
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
struct cli_state *cli = NULL;
- if ( !NT_STATUS_IS_OK(connect_to_ipc_krb5(&cli, ip, servername)) )
+ ret = connect_to_ipc_krb5(&cli, ip, servername);
+ if ( !NT_STATUS_IS_OK(ret) ) {
goto done;
-
- if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, domain, dom_sid )) )
+ }
+
+ ret = netdom_get_domain_sid( ctx, cli, domain, dom_sid );
+ if ( !NT_STATUS_IS_OK(ret) ) {
goto done;
+ }
- saf_store( *domain, cli->desthost );
+ /* cli->server_domain is not filled in when using krb5
+ session setups */
- if ( !NT_STATUS_IS_OK(netdom_join_domain( ctx, cli, *dom_sid,
- password, ND_TYPE_AD )) )
- {
- goto done;
- }
+ saf_store( *domain, cli->desthost );
- ret = 0;
+ ret = netdom_join_domain( ctx, cli, *dom_sid, password, ND_TYPE_AD );
done:
- if ( cli )
+ if ( cli )
cli_shutdown(cli);
return ret;
@@ -994,11 +1017,9 @@ static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
/* Find our DN */
- status = ads_find_machine_acct(ads_s, (void **)(void *)&res, machine_name);
- if (!ADS_ERR_OK(status)) {
- DEBUG(1,("net_set_machine_spn: could not find machine account\n"));
+ status = ads_find_machine_acct(ads_s, &res, machine_name);
+ if (!ADS_ERR_OK(status))
return status;
- }
if ( (count = ads_count_replies(ads_s, res)) != 1 ) {
DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
@@ -1066,7 +1087,7 @@ static ADS_STATUS net_set_machine_upn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s, const
/* Find our DN */
- status = ads_find_machine_acct(ads_s, (void **)(void *)&res, machine_name);
+ status = ads_find_machine_acct(ads_s, &res, machine_name);
if (!ADS_ERR_OK(status))
return status;
@@ -1120,7 +1141,7 @@ static ADS_STATUS net_precreate_machine_acct( ADS_STRUCT *ads, const char *ou )
return ADS_ERROR(LDAP_NO_MEMORY);
}
- rc = ads_search_dn(ads, (void **)&res, dn, NULL);
+ rc = ads_search_dn(ads, &res, dn, NULL);
ads_msgfree(ads, res);
if (ADS_ERR_OK(rc)) {
@@ -1160,7 +1181,7 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
/* go ahead and setup the default salt */
if ( (std_salt = kerberos_standard_des_salt()) == NULL ) {
- DEBUG(0,("net_derive_salting_principal: failed to obtain stanard DES salt\n"));
+ d_fprintf(stderr, "net_derive_salting_principal: failed to obtain stanard DES salt\n");
return False;
}
@@ -1173,7 +1194,7 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
char *upn;
int count;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, machine_name);
+ status = ads_find_machine_acct(ads, &res, machine_name);
if (!ADS_ERR_OK(status)) {
return False;
}
@@ -1194,7 +1215,88 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
return kerberos_secrets_store_des_salt( salt );
}
-/*********************************************************
+/*******************************************************************
+ Send a DNS update request
+*******************************************************************/
+
+#if defined(WITH_DNS_UPDATES)
+#include "dns.h"
+DNS_ERROR DoDNSUpdate(ADS_STRUCT *ads, char *pszServerName,
+ const char *pszDomainName,
+ const char *pszHostName,
+ const struct in_addr *iplist, int num_addrs );
+
+
+static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
+ const char *machine_name,
+ const struct in_addr *addrs,
+ int num_addrs)
+{
+ struct dns_rr_ns *nameservers = NULL;
+ int ns_count = 0;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ DNS_ERROR dns_err;
+ fstring dns_server;
+ const char *dnsdomain;
+
+ if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
+ d_printf("No DNS domain configured for %s. "
+ "Unable to perform DNS Update.\n", machine_name);
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
+ dnsdomain++;
+
+ status = ads_dns_lookup_ns( ctx, dnsdomain, &nameservers, &ns_count );
+ if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
+ DEBUG(3,("net_ads_join: Failed to find name server for the %s "
+ "realm\n", ads->config.realm));
+ goto done;
+ }
+
+ /* Now perform the dns update - we'll try non-secure and if we fail,
+ we'll follow it up with a secure update */
+
+ fstrcpy( dns_server, nameservers[0].hostname );
+
+ dns_err = DoDNSUpdate(ads, dns_server, dnsdomain, machine_name, addrs, num_addrs);
+ if (!ERR_DNS_IS_OK(dns_err)) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ }
+
+done:
+ return status;
+ }
+
+static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads)
+{
+ int num_addrs;
+ struct in_addr *iplist = NULL;
+ fstring machine_name;
+ NTSTATUS status;
+
+ name_to_fqdn( machine_name, global_myname() );
+ strlower_m( machine_name );
+
+ /* Get our ip address (not the 127.0.0.x address but a real ip
+ * address) */
+
+ num_addrs = get_my_ip_address( &iplist );
+ if ( num_addrs <= 0 ) {
+ DEBUG(4,("net_ads_join: Failed to find my non-loopback IP "
+ "addresses!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ status = net_update_dns_internal(mem_ctx, ads, machine_name,
+ iplist, num_addrs);
+ SAFE_FREE( iplist );
+ return status;
+}
+#endif
+
+
+/*******************************************************************
utility function to parse an integer parameter from
"parameter = value"
**********************************************************/
@@ -1231,22 +1333,27 @@ int net_ads_join(int argc, const char **argv)
{
ADS_STRUCT *ads = NULL;
ADS_STATUS status;
+ NTSTATUS nt_status;
char *machine_account = NULL;
char *short_domain_name = NULL;
char *tmp_password, *password;
- TALLOC_CTX *ctx;
+ TALLOC_CTX *ctx = NULL;
DOM_SID *domain_sid = NULL;
BOOL createupn = False;
const char *machineupn = NULL;
const char *create_in_ou = NULL;
int i;
- if ( check_ads_config() != 0 ) {
+ nt_status = check_ads_config();
+ if (!NT_STATUS_IS_OK(nt_status)) {
d_fprintf(stderr, "Invalid configuration. Exiting....\n");
goto fail;
}
- if ( (ads = ads_startup(True)) == NULL ) {
+ status = ads_startup(True, &ads);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
+ nt_status = ads_ntstatus(status);
goto fail;
}
@@ -1254,11 +1361,13 @@ int net_ads_join(int argc, const char **argv)
d_fprintf(stderr, "realm of remote server (%s) and realm in smb.conf "
"(%s) DO NOT match. Aborting join\n", ads->config.realm,
lp_realm());
+ nt_status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
if (!(ctx = talloc_init("net_ads_join"))) {
- DEBUG(0, ("Could not initialise talloc context\n"));
+ d_fprintf(stderr, "Could not initialise talloc context.\n");
+ nt_status = NT_STATUS_NO_MEMORY;
goto fail;
}
@@ -1272,11 +1381,13 @@ int net_ads_join(int argc, const char **argv)
else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
d_fprintf(stderr, "Please supply a valid OU path\n");
+ nt_status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
}
else {
d_fprintf(stderr, "Bad option: %s\n", argv[i]);
+ nt_status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
}
@@ -1289,6 +1400,9 @@ int net_ads_join(int argc, const char **argv)
if ( !ADS_ERR_OK(status) ) {
d_fprintf( stderr, "Failed to pre-create the machine object "
"in OU %s.\n", argv[0]);
+ DEBUG(1, ("error calling net_precreate_machine_acct: %s\n",
+ ads_errstr(status)));
+ nt_status = ads_ntstatus(status);
goto fail;
}
}
@@ -1298,13 +1412,14 @@ int net_ads_join(int argc, const char **argv)
tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
password = talloc_strdup(ctx, tmp_password);
- if ( net_join_domain( ctx, ads->config.ldap_server_name, &ads->ldap_ip,
- &short_domain_name, &domain_sid, password ) != 0 )
- {
- d_fprintf(stderr, "Failed to join domain!\n");
+ nt_status = net_join_domain(ctx, ads->config.ldap_server_name,
+ &ads->ldap_ip, &short_domain_name, &domain_sid, password);
+ if ( !NT_STATUS_IS_OK(nt_status) ) {
+ DEBUG(1, ("call of net_join_domain failed: %s\n",
+ get_friendly_nt_error_msg(nt_status)));
goto fail;
}
-
+
/* Check the short name of the domain */
if ( !strequal(lp_workgroup(), short_domain_name) ) {
@@ -1324,6 +1439,9 @@ int net_ads_join(int argc, const char **argv)
if ( (netdom_store_machine_account( lp_workgroup(), domain_sid, password ) == -1)
|| (netdom_store_machine_account( short_domain_name, domain_sid, password ) == -1) )
{
+ /* issue an internal error here for now.
+ * everything else would mean changing tdb routines. */
+ nt_status = NT_STATUS_INTERNAL_ERROR;
goto fail;
}
@@ -1339,7 +1457,7 @@ int net_ads_join(int argc, const char **argv)
status = net_set_machine_spn( ctx, ads );
if ( !ADS_ERR_OK(status) ) {
- d_fprintf(stderr, "Failed to set servicePrincipalNames (%s). Please ensure that\n", ads_errstr(status));
+ d_fprintf(stderr, "Failed to set servicePrincipalNames. Please ensure that\n");
d_fprintf(stderr, "the DNS domain of this server matches the AD domain,\n");
d_fprintf(stderr, "Or rejoin with using Domain Admin credentials.\n");
@@ -1355,6 +1473,7 @@ int net_ads_join(int argc, const char **argv)
netdom_store_machine_account( lp_workgroup(), domain_sid, "" );
netdom_store_machine_account( short_domain_name, domain_sid, "" );
+ nt_status = ads_ntstatus(status);
goto fail;
}
@@ -1384,7 +1503,31 @@ int net_ads_join(int argc, const char **argv)
DEBUG(1,("Error creating host keytab!\n"));
}
- d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
+#if defined(WITH_DNS_UPDATES)
+ /* We enter this block with user creds */
+ ads_kdestroy( NULL );
+ ads_destroy(&ads);
+ ads = NULL;
+
+ if ( (ads = ads_init( lp_realm(), NULL, NULL )) != NULL ) {
+ /* kinit with the machine password */
+
+ use_in_memory_ccache();
+ asprintf( &ads->auth.user_name, "%s$", global_myname() );
+ ads->auth.password = secrets_fetch_machine_password(
+ lp_workgroup(), NULL, NULL );
+ ads->auth.realm = SMB_STRDUP( lp_realm() );
+ ads_kinit_password( ads );
+ }
+
+ if ( !ads || !NT_STATUS_IS_OK(net_update_dns( ctx, ads )) ) {
+ d_fprintf( stderr, "DNS update failed!\n" );
+ }
+
+ /* exit from this block using machine creds */
+#endif
+
+ d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->server.realm);
SAFE_FREE(machine_account);
TALLOC_FREE( ctx );
@@ -1393,10 +1536,159 @@ int net_ads_join(int argc, const char **argv)
return 0;
fail:
+ /* issue an overall failure message at the end. */
+ d_printf("Failed to join domain: %s\n", get_friendly_nt_error_msg(nt_status));
+
+ SAFE_FREE(machine_account);
+ TALLOC_FREE( ctx );
+ ads_destroy(&ads);
+
+ return -1;
+
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static int net_ads_dns_usage(int argc, const char **argv)
+{
+#if defined(WITH_DNS_UPDATES)
+ d_printf("net ads dns <command>\n");
+ d_printf("Valid commands:\n");
+ d_printf(" register Issue a dynamic DNS update request for our hostname\n");
+
+ return 0;
+#else
+ d_fprintf(stderr, "DNS update support not enabled at compile time!\n");
+ return -1;
+#endif
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static int net_ads_dns_register(int argc, const char **argv)
+{
+#if defined(WITH_DNS_UPDATES)
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ TALLOC_CTX *ctx;
+ fstring name;
+ int num_addrs;
+ struct in_addr *iplist = NULL;
+
+#ifdef DEVELOPER
+ talloc_enable_leak_report();
+#endif
+
+ if (argc > 2) {
+ d_fprintf(stderr, "net ads dns register <name> <ip>\n");
+ return -1;
+ }
+
+ if (!(ctx = talloc_init("net_ads_dns"))) {
+ d_fprintf(stderr, "Could not initialise talloc context\n");
+ return -1;
+ }
+
+ if (argc > 0) {
+ fstrcpy(name, argv[0]);
+ } else {
+ name_to_fqdn(name, global_myname());
+ }
+ strlower_m(name);
+
+ if (argc > 1) {
+ if (!(iplist = SMB_MALLOC_ARRAY(struct in_addr, 1))) {
+ d_fprintf(stderr, "net_ads_dns_register: malloc "
+ "failed\n");
+ return -1;
+ }
+ if (inet_aton(argv[1], iplist) == 0) {
+ d_fprintf(stderr, "net_ads_dns_register: %s is not "
+ "a valid IP address\n", argv[1]);
+ SAFE_FREE(iplist);
+ return -1;
+ }
+ num_addrs = 1;
+ } else {
+ num_addrs = get_my_ip_address( &iplist );
+ if ( num_addrs <= 0 ) {
+ d_fprintf(stderr, "net_ads_dns_regiser: Failed to "
+ "find my non-loopback IP addresses!\n");
+ return -1;
+ }
+ }
+
+ status = ads_startup_nobind(True, &ads);
+ if ( !ADS_ERR_OK(status) ) {
+ DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
+ TALLOC_FREE(ctx);
+ return -1;
+ }
+
+ if ( !NT_STATUS_IS_OK(net_update_dns_internal(ctx, ads, name,
+ iplist, num_addrs)) ) {
+ d_fprintf( stderr, "DNS update failed!\n" );
+ ads_destroy( &ads );
+ TALLOC_FREE( ctx );
+ SAFE_FREE(iplist);
+ return -1;
+ }
+
+ d_fprintf( stderr, "Successfully registered hostname with DNS\n" );
+
ads_destroy(&ads);
+ TALLOC_FREE( ctx );
+ SAFE_FREE(iplist);
+
+ return 0;
+#else
+ d_fprintf(stderr, "DNS update support not enabled at compile time!\n");
return -1;
+#endif
+}
+
+#if defined(WITH_DNS_UPDATES)
+DNS_ERROR do_gethostbyname(const char *server, const char *host);
+#endif
+
+static int net_ads_dns_gethostbyname(int argc, const char **argv)
+{
+#if defined(WITH_DNS_UPDATES)
+ DNS_ERROR err;
+
+#ifdef DEVELOPER
+ talloc_enable_leak_report();
+#endif
+
+ if (argc != 2) {
+ d_fprintf(stderr, "net ads dns gethostbyname <server> "
+ "<name>\n");
+ return -1;
+ }
+
+ err = do_gethostbyname(argv[0], argv[1]);
+
+ d_printf("do_gethostbyname returned %d\n", ERROR_DNS_V(err));
+#endif
+ return 0;
+}
+
+static int net_ads_dns(int argc, const char *argv[])
+{
+ struct functable func[] = {
+ {"REGISTER", net_ads_dns_register},
+ {"GETHOSTBYNAME", net_ads_dns_gethostbyname},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, net_ads_dns_usage);
}
+/*******************************************************************
+ ********************************************************************/
+
int net_ads_printer_usage(int argc, const char **argv)
{
d_printf(
@@ -1414,13 +1706,16 @@ int net_ads_printer_usage(int argc, const char **argv)
return -1;
}
+/*******************************************************************
+ ********************************************************************/
+
static int net_ads_printer_search(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS rc;
- void *res = NULL;
+ LDAPMessage *res = NULL;
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -1451,9 +1746,9 @@ static int net_ads_printer_info(int argc, const char **argv)
ADS_STRUCT *ads;
ADS_STATUS rc;
const char *servername, *printername;
- void *res = NULL;
+ LDAPMessage *res = NULL;
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -1511,9 +1806,9 @@ static int net_ads_printer_publish(int argc, const char **argv)
TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
ADS_MODLIST mods = ads_init_mods(mem_ctx);
char *prt_dn, *srv_dn, **srv_cn;
- void *res = NULL;
+ LDAPMessage *res = NULL;
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
@@ -1559,14 +1854,24 @@ static int net_ads_printer_publish(int argc, const char **argv)
return -1;
}
- srv_dn = ldap_get_dn(ads->ld, res);
+ srv_dn = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res);
srv_cn = ldap_explode_dn(srv_dn, 1);
asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status);
- get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
- printername);
+ if (!pipe_hnd) {
+ d_fprintf(stderr, "Unable to open a connnection to the spoolss pipe on %s\n",
+ servername);
+ ads_destroy(&ads);
+ return -1;
+ }
+
+ if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
+ printername))) {
+ ads_destroy(&ads);
+ return -1;
+ }
rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
if (!ADS_ERR_OK(rc)) {
@@ -1587,9 +1892,9 @@ static int net_ads_printer_remove(int argc, const char **argv)
ADS_STATUS rc;
const char *servername;
char *prt_dn;
- void *res = NULL;
+ LDAPMessage *res = NULL;
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
@@ -1685,7 +1990,7 @@ static int net_ads_password(int argc, const char **argv)
/* use the realm so we can eventually change passwords for users
in realms other than default */
- if (!(ads = ads_init(realm, opt_workgroup, NULL))) {
+ if (!(ads = ads_init(realm, opt_workgroup, opt_host))) {
return -1;
}
@@ -1736,25 +2041,25 @@ int net_ads_changetrustpw(int argc, const char **argv)
use_in_memory_ccache();
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
fstrcpy(my_name, global_myname());
strlower_m(my_name);
- asprintf(&host_principal, "%s@%s", my_name, ads->config.realm);
- d_printf("Changing password for principal: HOST/%s\n", host_principal);
+ asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm);
+ d_printf("Changing password for principal: %s\n", host_principal);
ret = ads_change_trust_account_password(ads, host_principal);
if (!ADS_ERR_OK(ret)) {
- d_fprintf(stderr, "Password change failed :-( ...\n");
+ d_fprintf(stderr, "Password change failed: %s\n", ads_errstr(ret));
ads_destroy(&ads);
SAFE_FREE(host_principal);
return -1;
}
- d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
+ d_printf("Password change for principal %s succeeded.\n", host_principal);
if (lp_use_kerberos_keytab()) {
d_printf("Attempting to update system keytab with new password.\n");
@@ -1795,13 +2100,13 @@ static int net_ads_search(int argc, const char **argv)
ADS_STATUS rc;
const char *ldap_exp;
const char **attrs;
- void *res = NULL;
+ LDAPMessage *res = NULL;
if (argc < 1) {
return net_ads_search_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -1855,13 +2160,13 @@ static int net_ads_dn(int argc, const char **argv)
ADS_STATUS rc;
const char *dn;
const char **attrs;
- void *res = NULL;
+ LDAPMessage *res = NULL;
if (argc < 1) {
return net_ads_dn_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -1904,6 +2209,7 @@ static int net_ads_sid_usage(int argc, const char **argv)
return -1;
}
+
/*
general ADS search function. Useful in diagnosing problems in ADS
*/
@@ -1913,14 +2219,14 @@ static int net_ads_sid(int argc, const char **argv)
ADS_STATUS rc;
const char *sid_string;
const char **attrs;
- void *res = NULL;
+ LDAPMessage *res = NULL;
DOM_SID sid;
if (argc < 1) {
return net_ads_sid_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -1938,7 +2244,7 @@ static int net_ads_sid(int argc, const char **argv)
d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
ads_destroy(&ads);
return -1;
- }
+ }
d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
@@ -1951,6 +2257,7 @@ static int net_ads_sid(int argc, const char **argv)
return 0;
}
+
static int net_ads_keytab_usage(int argc, const char **argv)
{
d_printf(
@@ -1976,7 +2283,7 @@ static int net_ads_keytab_flush(int argc, const char **argv)
int ret;
ADS_STRUCT *ads;
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
ret = ads_keytab_flush(ads);
@@ -1991,7 +2298,7 @@ static int net_ads_keytab_add(int argc, const char **argv)
ADS_STRUCT *ads;
d_printf("Processing principals to add...\n");
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
for (i = 0; i < argc; i++) {
@@ -2006,7 +2313,7 @@ static int net_ads_keytab_create(int argc, const char **argv)
ADS_STRUCT *ads;
int ret;
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
ret = ads_keytab_create_default(ads);
@@ -2041,12 +2348,11 @@ int net_ads_help(int argc, const char **argv)
{"SEARCH", net_ads_search_usage},
{"INFO", net_ads_info},
{"JOIN", net_ads_join_usage},
-#if 0
+ {"DNS", net_ads_dns_usage},
{"LEAVE", net_ads_leave},
{"STATUS", net_ads_status},
{"PASSWORD", net_ads_password},
{"CHANGETRUSTPW", net_ads_changetrustpw},
-#endif
{NULL, NULL}
};
@@ -2063,6 +2369,7 @@ int net_ads(int argc, const char **argv)
{"STATUS", net_ads_status},
{"USER", net_ads_user},
{"GROUP", net_ads_group},
+ {"DNS", net_ads_dns},
{"PASSWORD", net_ads_password},
{"CHANGETRUSTPW", net_ads_changetrustpw},
{"PRINTER", net_ads_printer},
@@ -2072,6 +2379,7 @@ int net_ads(int argc, const char **argv)
{"WORKGROUP", net_ads_workgroup},
{"LOOKUP", net_ads_lookup},
{"KEYTAB", net_ads_keytab},
+ {"GPO", net_ads_gpo},
{"HELP", net_ads_help},
{NULL, NULL}
};
@@ -2138,4 +2446,4 @@ int net_ads(int argc, const char **argv)
return net_ads_usage(argc, argv);
}
-#endif
+#endif /* WITH_ADS */
diff --git a/source/utils/net_ads_gpo.c b/source/utils/net_ads_gpo.c
index fec6fb88fa2..1865aee3d41 100644
--- a/source/utils/net_ads_gpo.c
+++ b/source/utils/net_ads_gpo.c
@@ -29,9 +29,9 @@ static int net_ads_gpo_usage(int argc, const char **argv)
"net ads gpo <COMMAND>\n"\
"<COMMAND> can be either:\n"\
" ADDLINK Link a container to a GPO\n"\
-" APPLY Apply all GPOs\n"\
-" DELETELINK Delete a gPLink from a container\n"\
-" EFFECTIVE Lists all GPOs assigned to a machine\n"\
+/* " APPLY Apply all GPOs\n"\ */
+/* " DELETELINK Delete a gPLink from a container\n"\ */
+" REFRESH Lists all GPOs assigned to an account and downloads them\n"\
" GETGPO Lists specified GPO\n"\
" GETLINK Lists gPLink of a containter\n"\
" HELP Prints this help message\n"\
@@ -41,24 +41,27 @@ static int net_ads_gpo_usage(int argc, const char **argv)
return -1;
}
-static int net_ads_gpo_effective(int argc, const char **argv)
+static int net_ads_gpo_refresh(int argc, const char **argv)
{
TALLOC_CTX *mem_ctx;
ADS_STRUCT *ads;
ADS_STATUS status;
- const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
- void *res = NULL;
+ const char *attrs[] = { "userAccountControl", NULL };
+ LDAPMessage *res = NULL;
const char *filter;
char *dn = NULL;
struct GROUP_POLICY_OBJECT *gpo_list;
uint32 uac = 0;
uint32 flags = 0;
+ struct GROUP_POLICY_OBJECT *gpo;
+ NTSTATUS result;
if (argc < 1) {
+ printf("usage: net ads gpo refresh <username|machinename>\n");
return -1;
}
- mem_ctx = talloc_init("net_ads_gpo_effective");
+ mem_ctx = talloc_init("net_ads_gpo_refresh");
if (mem_ctx == NULL) {
return -1;
}
@@ -68,7 +71,8 @@ static int net_ads_gpo_effective(int argc, const char **argv)
goto out;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -98,7 +102,7 @@ static int net_ads_gpo_effective(int argc, const char **argv)
flags |= GPO_LIST_FLAG_MACHINE;
}
- printf("%s: '%s' has dn: '%s'\n",
+ printf("\n%s: '%s' has dn: '%s'\n\n",
(uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user",
argv[0], dn);
@@ -107,19 +111,34 @@ static int net_ads_gpo_effective(int argc, const char **argv)
goto out;
}
- printf("unsorted full dump of all GPOs for this machine:\n");
+ if (!NT_STATUS_IS_OK(result = check_refresh_gpo_list(ads, mem_ctx, gpo_list))) {
+ printf("failed to refresh GPOs: %s\n", nt_errstr(result));
+ goto out;
+ }
- {
- struct GROUP_POLICY_OBJECT *gpo = gpo_list;
+ for (gpo = gpo_list; gpo; gpo = gpo->next) {
- for (gpo = gpo_list; gpo; gpo = gpo->next) {
- dump_gpo(mem_ctx, gpo);
+ char *server, *share, *nt_path, *unix_path;
+
+ printf("--------------------------------------\n");
+ printf("Name:\t\t\t%s\n", gpo->display_name);
+ printf("LDAP GPO version:\t%d (user: %d, machine: %d)\n",
+ gpo->version,
+ GPO_VERSION_USER(gpo->version),
+ GPO_VERSION_MACHINE(gpo->version));
+
+ result = ads_gpo_explode_filesyspath(ads, mem_ctx, gpo->file_sys_path,
+ &server, &share, &nt_path, &unix_path);
+ if (!NT_STATUS_IS_OK(result)) {
+ printf("got: %s\n", nt_errstr(result));
}
+
+ printf("GPO stored on server: %s, share: %s\n", server, share);
+ printf("\tremote path:\t%s\n", nt_path);
+ printf("\tlocal path:\t%s\n", unix_path);
}
- printf("sorted full dump of all GPOs valid for this machine:\n");
-
-out:
+ out:
ads_memfree(ads, dn);
ads_msgfree(ads, res);
@@ -132,24 +151,36 @@ static int net_ads_gpo_list(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS status;
- void *res = NULL;
+ LDAPMessage *res = NULL;
int num_reply = 0;
- void *msg = NULL;
+ LDAPMessage *msg = NULL;
struct GROUP_POLICY_OBJECT gpo;
TALLOC_CTX *mem_ctx;
+ char *dn;
+ const char *attrs[] = {
+ "versionNumber",
+ "flags",
+ "gPCFileSysPath",
+ "displayName",
+ "name",
+ "gPCMachineExtensionNames",
+ "gPCUserExtensionNames",
+ NULL
+ };
mem_ctx = talloc_init("net_ads_gpo_list");
if (mem_ctx == NULL) {
return -1;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
status = ads_do_search_all(ads, ads->config.bind_path,
LDAP_SCOPE_SUBTREE,
- "(objectclass=groupPolicyContainer)", NULL, &res);
+ "(objectclass=groupPolicyContainer)", attrs, &res);
if (!ADS_ERR_OK(status)) {
d_printf("search failed: %s\n", ads_errstr(status));
goto out;
@@ -161,16 +192,21 @@ static int net_ads_gpo_list(int argc, const char **argv)
/* dump the results */
for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
-
- status = ads_parse_gpo(ads, mem_ctx, msg, ads_get_dn(ads, msg), &gpo);
+
+ if ((dn = ads_get_dn(ads, msg)) == NULL) {
+ goto out;
+ }
+
+ status = ads_parse_gpo(ads, mem_ctx, msg, dn, &gpo);
if (!ADS_ERR_OK(status)) {
d_printf("parse failed: %s\n", ads_errstr(status));
+ ads_memfree(ads, dn);
goto out;
}
- dump_gpo(mem_ctx, &gpo);
-
+ dump_gpo(mem_ctx, &gpo, 1);
+ ads_memfree(ads, dn);
}
out:
@@ -182,13 +218,15 @@ out:
return 0;
}
+#if 0 /* not yet */
+
static int net_ads_gpo_apply(int argc, const char **argv)
{
TALLOC_CTX *mem_ctx;
ADS_STRUCT *ads;
ADS_STATUS status;
const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
- void *res = NULL;
+ LDAPMessage *res = NULL;
const char *filter;
char *dn = NULL;
struct GROUP_POLICY_OBJECT *gpo_list;
@@ -196,6 +234,7 @@ static int net_ads_gpo_apply(int argc, const char **argv)
uint32 flags = 0;
if (argc < 1) {
+ printf("usage: net ads gpo apply <username|machinename>\n");
return -1;
}
@@ -209,7 +248,8 @@ static int net_ads_gpo_apply(int argc, const char **argv)
goto out;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -263,6 +303,7 @@ out:
return 0;
}
+#endif
static int net_ads_gpo_get_link(int argc, const char **argv)
{
@@ -272,6 +313,7 @@ static int net_ads_gpo_get_link(int argc, const char **argv)
struct GP_LINK gp_link;
if (argc < 1) {
+ printf("usage: net ads gpo getlink <linkname>\n");
return -1;
}
@@ -280,7 +322,8 @@ static int net_ads_gpo_get_link(int argc, const char **argv)
return -1;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -307,6 +350,7 @@ static int net_ads_gpo_add_link(int argc, const char **argv)
TALLOC_CTX *mem_ctx;
if (argc < 2) {
+ printf("usage: net ads gpo addlink <linkdn> <gpodn> [options]\n");
return -1;
}
@@ -319,7 +363,8 @@ static int net_ads_gpo_add_link(int argc, const char **argv)
gpo_opt = atoi(argv[2]);
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -336,6 +381,8 @@ out:
return 0;
}
+#if 0 /* broken */
+
static int net_ads_gpo_delete_link(int argc, const char **argv)
{
ADS_STRUCT *ads;
@@ -351,7 +398,8 @@ static int net_ads_gpo_delete_link(int argc, const char **argv)
return -1;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -368,15 +416,17 @@ out:
return 0;
}
+#endif
+
static int net_ads_gpo_get_gpo(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS status;
TALLOC_CTX *mem_ctx;
struct GROUP_POLICY_OBJECT gpo;
- uint32 sysvol_gpt_version;
if (argc < 1) {
+ printf("usage: net ads gpo getgpo <gpo>\n");
return -1;
}
@@ -385,7 +435,8 @@ static int net_ads_gpo_get_gpo(int argc, const char **argv)
return -1;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -400,14 +451,7 @@ static int net_ads_gpo_get_gpo(int argc, const char **argv)
goto out;
}
- dump_gpo(mem_ctx, &gpo);
-
- status = ADS_ERROR_NT(ads_gpo_get_sysvol_gpt_version(ads, mem_ctx, gpo.file_sys_path, &sysvol_gpt_version));
- if (!ADS_ERR_OK(status)) {
- goto out;
- }
-
- printf("sysvol GPT version: %d\n", sysvol_gpt_version);
+ dump_gpo(mem_ctx, &gpo, 1);
out:
talloc_destroy(mem_ctx);
@@ -420,17 +464,17 @@ int net_ads_gpo(int argc, const char **argv)
{
struct functable func[] = {
{"LIST", net_ads_gpo_list},
- {"EFFECTIVE", net_ads_gpo_effective},
+ {"REFRESH", net_ads_gpo_refresh},
{"ADDLINK", net_ads_gpo_add_link},
- {"DELETELINK", net_ads_gpo_delete_link},
+ /* {"DELETELINK", net_ads_gpo_delete_link}, */
{"GETLINK", net_ads_gpo_get_link},
{"GETGPO", net_ads_gpo_get_gpo},
{"HELP", net_ads_gpo_usage},
- {"APPLY", net_ads_gpo_apply},
+ /* {"APPLY", net_ads_gpo_apply}, */
{NULL, NULL}
};
return net_run_function(argc, argv, func, net_ads_gpo_usage);
}
-#endif
+#endif /* HAVE_ADS */
diff --git a/source/utils/net_dns.c b/source/utils/net_dns.c
new file mode 100644
index 00000000000..d372211a5ff
--- /dev/null
+++ b/source/utils/net_dns.c
@@ -0,0 +1,192 @@
+
+/*
+ Samba Unix/Linux Dynamic DNS Update
+ net ads commands
+
+ Copyright (C) Krishna Ganugapati (krishnag@centeris.com) 2006
+ Copyright (C) Gerald Carter 2006
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "utils/net.h"
+#include "dns.h"
+
+#if defined(WITH_DNS_UPDATES)
+
+/*********************************************************************
+*********************************************************************/
+
+DNS_ERROR DoDNSUpdate(ADS_STRUCT *ads, char *pszServerName,
+ const char *pszDomainName, const char *pszHostName,
+ const struct in_addr *iplist, int num_addrs )
+{
+ DNS_ERROR err;
+ struct dns_connection *conn;
+ TALLOC_CTX *mem_ctx;
+ OM_uint32 minor;
+ struct dns_update_request *req, *resp;
+
+ if ( (num_addrs <= 0) || !iplist ) {
+ return ERROR_DNS_INVALID_PARAMETER;
+ }
+
+ if (!(mem_ctx = talloc_init("DoDNSUpdate"))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ err = dns_open( pszServerName, DNS_TCP, mem_ctx, &conn );
+ if (!ERR_DNS_IS_OK(err)) {
+ goto error;
+ }
+
+ /*
+ * Probe if everything's fine
+ */
+
+ err = dns_create_probe(mem_ctx, pszDomainName, pszHostName,
+ num_addrs, iplist, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_update_transaction(mem_ctx, conn, req, &resp);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ if (dns_response_code(resp->flags) == DNS_NO_ERROR) {
+ TALLOC_FREE(mem_ctx);
+ return ERROR_DNS_SUCCESS;
+ }
+
+ /*
+ * First try without signing
+ */
+
+ err = dns_create_update_request(mem_ctx, pszDomainName, pszHostName,
+ iplist[0].s_addr, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_update_transaction(mem_ctx, conn, req, &resp);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ if (dns_response_code(resp->flags) == DNS_NO_ERROR) {
+ TALLOC_FREE(mem_ctx);
+ return ERROR_DNS_SUCCESS;
+ }
+
+ /*
+ * Okay, we have to try with signing
+ */
+ {
+ ADS_STRUCT *ads_s;
+ gss_ctx_id_t gss_context;
+ int res;
+ char *keyname;
+
+ if (!(keyname = dns_generate_keyname( mem_ctx ))) {
+ err = ERROR_DNS_NO_MEMORY;
+ goto error;
+ }
+
+ if (!(ads_s = ads_init(ads->server.realm, ads->server.workgroup,
+ ads->server.ldap_server))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ /* kinit with the machine password */
+ setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
+ asprintf( &ads_s->auth.user_name, "%s$", global_myname() );
+ ads_s->auth.password = secrets_fetch_machine_password(
+ lp_workgroup(), NULL, NULL );
+ ads_s->auth.realm = SMB_STRDUP( lp_realm() );
+ res = ads_kinit_password( ads_s );
+ ads_destroy(&ads_s);
+ if (res) {
+ err = ERROR_DNS_GSS_ERROR;
+ goto error;
+ }
+
+ err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
+ keyname, &gss_context );
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_sign_update(req, gss_context, keyname,
+ "gss.microsoft.com", time(NULL), 3600);
+
+ gss_delete_sec_context(&minor, &gss_context, GSS_C_NO_BUFFER);
+
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_update_transaction(mem_ctx, conn, req, &resp);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = (dns_response_code(resp->flags) == DNS_NO_ERROR) ?
+ ERROR_DNS_SUCCESS : ERROR_DNS_UPDATE_FAILED;
+ }
+
+
+error:
+ TALLOC_FREE(mem_ctx);
+ return err;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+int get_my_ip_address( struct in_addr **ips )
+{
+ struct iface_struct nics[MAX_INTERFACES];
+ int i, n;
+ struct in_addr loopback_ip = *interpret_addr2("127.0.0.1");
+ struct in_addr *list;
+ int count = 0;
+
+ /* find the first non-loopback address from our list of interfaces */
+
+ n = get_interfaces(nics, MAX_INTERFACES);
+
+ if ( (list = SMB_MALLOC_ARRAY( struct in_addr, n )) == NULL ) {
+ return -1;
+ }
+
+ for ( i=0; i<n; i++ ) {
+ if ( nics[i].ip.s_addr != loopback_ip.s_addr ) {
+ memcpy( &list[count++], &nics[i].ip, sizeof( struct in_addr ) );
+ }
+ }
+ *ips = list;
+
+ return count;
+}
+
+DNS_ERROR do_gethostbyname(const char *server, const char *host)
+{
+ struct dns_connection *conn;
+ struct dns_request *req, *resp;
+ DNS_ERROR err;
+
+ err = dns_open(server, DNS_UDP, NULL, &conn);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_create_query(conn, host, QTYPE_A, DNS_CLASS_IN, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_transaction(conn, conn, req, &resp);
+
+ error:
+ TALLOC_FREE(conn);
+ return err;
+}
+
+#endif /* defined(WITH_DNS_UPDATES) */
diff --git a/source/utils/net_groupmap.c b/source/utils/net_groupmap.c
index 64156844119..ad1a141cfc5 100644
--- a/source/utils/net_groupmap.c
+++ b/source/utils/net_groupmap.c
@@ -192,7 +192,15 @@ static int net_groupmap_add(int argc, const char **argv)
uint32 rid = 0;
gid_t gid;
int i;
- const char *name_type = "domain group";
+ GROUP_MAP map;
+
+ const char *name_type;
+
+ ZERO_STRUCT(map);
+
+ /* Default is domain group. */
+ map.sid_name_use = SID_NAME_DOM_GRP;
+ name_type = "domain group";
/* get the options */
for ( i=0; i<argc; i++ ) {
@@ -271,7 +279,6 @@ static int net_groupmap_add(int argc, const char **argv)
}
{
- GROUP_MAP map;
if (pdb_getgrgid(&map, gid)) {
d_printf("Unix group %s already mapped to SID %s\n",
unixgrp, sid_string_static(&map.sid));
@@ -325,7 +332,7 @@ static int net_groupmap_add(int argc, const char **argv)
}
d_printf("Successfully added group %s to the mapping db as a %s\n",
- ntgroup, name_type);
+ ntgroup, name_type);
return 0;
}
@@ -424,13 +431,13 @@ static int net_groupmap_modify(int argc, const char **argv)
if (sid_type == SID_NAME_UNKNOWN) {
d_fprintf(stderr, "Can't map to an unknown group type.\n");
return -1;
- }
+ }
if (map.sid_name_use == SID_NAME_WKN_GRP) {
d_fprintf(stderr, "You can only change between domain and local groups.\n");
return -1;
}
-
+
map.sid_name_use=sid_type;
/* Change comment if new one */
diff --git a/source/utils/net_rap.c b/source/utils/net_rap.c
index ef5df435357..9084122d680 100644
--- a/source/utils/net_rap.c
+++ b/source/utils/net_rap.c
@@ -407,12 +407,40 @@ int net_rap_server_usage(int argc, const char **argv)
net_common_flags_usage(argc, argv);
return -1;
}
+
+static int net_rap_server_name(int argc, const char *argv[])
+{
+ struct cli_state *cli;
+ char *name;
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ if (!cli_get_server_name(NULL, cli, &name)) {
+ d_fprintf(stderr, "cli_get_server_name failed\n");
+ cli_shutdown(cli);
+ return -1;
+ }
+
+ d_printf("Server name = %s\n", name);
+
+ TALLOC_FREE(name);
+ cli_shutdown(cli);
+ return 0;
+}
int net_rap_server(int argc, const char **argv)
{
struct cli_state *cli;
int ret;
-
+
+ if (argc > 0) {
+ if (!strequal(argv[0], "name")) {
+ return net_rap_server_usage(argc-1, argv+1);
+ }
+ return net_rap_server_name(argc, argv);
+ }
+
if (!(cli = net_make_ipc_connection(0)))
return -1;
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index 7595428e246..a112643d6de 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -2011,7 +2011,7 @@ static NTSTATUS get_sid_from_name(struct cli_state *cli,
enum lsa_SidType *type)
{
DOM_SID *sids = NULL;
- uint32 *types = NULL;
+ enum lsa_SidType *types = NULL;
struct rpc_pipe_client *pipe_hnd;
POLICY_HND lsa_pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -2717,7 +2717,7 @@ static NTSTATUS rpc_list_alias_members(struct rpc_pipe_client *pipe_hnd,
DOM_SID *alias_sids;
char **domains;
char **names;
- uint32 *types;
+ enum lsa_SidType *types;
int i;
result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, domain_pol,
diff --git a/source/utils/net_rpc_rights.c b/source/utils/net_rpc_rights.c
index 0dd28c3ac67..11c4991e7d7 100644
--- a/source/utils/net_rpc_rights.c
+++ b/source/utils/net_rpc_rights.c
@@ -29,7 +29,7 @@ static NTSTATUS sid_to_name(struct rpc_pipe_client *pipe_hnd,
fstring name)
{
POLICY_HND pol;
- uint32 *sid_types;
+ enum lsa_SidType *sid_types;
NTSTATUS result;
char **domains, **names;
@@ -60,7 +60,7 @@ static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd,
DOM_SID *sid, const char *name)
{
POLICY_HND pol;
- uint32 *sid_types;
+ enum lsa_SidType *sid_types;
NTSTATUS result;
DOM_SID *sids;
diff --git a/source/utils/net_rpc_service.c b/source/utils/net_rpc_service.c
index 27127a1c3f9..58a5b27f400 100644
--- a/source/utils/net_rpc_service.c
+++ b/source/utils/net_rpc_service.c
@@ -80,7 +80,7 @@ static WERROR watch_service_state(struct rpc_pipe_client *pipe_hnd,
d_printf(".");
i++;
- usleep( 100 );
+ sys_usleep( 100 );
}
d_printf("\n");
diff --git a/source/utils/net_util.c b/source/utils/net_util.c
index d8becebf0dd..be39a754656 100644
--- a/source/utils/net_util.c
+++ b/source/utils/net_util.c
@@ -39,7 +39,7 @@ NTSTATUS net_rpc_lookup_name(TALLOC_CTX *mem_ctx, struct cli_state *cli,
NTSTATUS result = NT_STATUS_OK;
const char **dom_names;
DOM_SID *sids;
- uint32_t *types;
+ enum lsa_SidType *types;
ZERO_STRUCT(pol);