diff options
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); |