#include "includes.h"
#include "winbindd.h"
-#include "../librpc/gen_ndr/cli_netlogon.h"
+#include "rpc_client/rpc_client.h"
+#include "../librpc/gen_ndr/ndr_netlogon_c.h"
+#include "../libds/common/flags.h"
+#include "ads.h"
+#include "secrets.h"
+#include "../libcli/ldap/ldap_ndr.h"
+#include "../libcli/security/security.h"
+#include "../libds/common/flag_mapping.h"
+#include "passdb.h"
#ifdef HAVE_ADS
}
}
- /* we don't want this to affect the users ccache */
- setenv("KRB5CCNAME", "MEMORY:winbind_ccache", 1);
-
ads = ads_init(domain->alt_name, domain->name, NULL);
if (!ads) {
DEBUG(1,("ads_init for domain %s failed\n", domain->name));
return NULL;
}
+ /* we don't want ads operations to affect the default ccache */
+ ads->auth.ccache_name = SMB_STRDUP("MEMORY:winbind_ccache");
+
/* the machine acct password might have change - fetch it every time */
SAFE_FREE(ads->auth.password);
return NULL;
}
ads->auth.realm = SMB_STRDUP( ads->server.realm );
- strupper_m( ads->auth.realm );
+ if (!strupper_m( ads->auth.realm )) {
+ ads_destroy( &ads );
+ return NULL;
+ }
}
else {
struct winbindd_domain *our_domain = domain;
if ( our_domain->alt_name[0] != '\0' ) {
ads->auth.realm = SMB_STRDUP( our_domain->alt_name );
- strupper_m( ads->auth.realm );
+ if (!strupper_m( ads->auth.realm )) {
+ ads_destroy( &ads );
+ return NULL;
+ }
}
else
ads->auth.realm = SMB_STRDUP( lp_realm() );
static NTSTATUS query_user_list(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_entries,
- struct wbint_userinfo **info)
+ struct wbint_userinfo **pinfo)
{
ADS_STRUCT *ads = NULL;
const char *attrs[] = { "*", NULL };
}
rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
- if (!ADS_ERR_OK(rc) || !res) {
+ if (!ADS_ERR_OK(rc)) {
DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
+ status = ads_ntstatus(rc);
+ } else if (!res) {
+ DEBUG(1,("query_user_list ads_search returned NULL res\n"));
+
goto done;
}
goto done;
}
- (*info) = TALLOC_ZERO_ARRAY(mem_ctx, struct wbint_userinfo, count);
- if (!*info) {
+ (*pinfo) = talloc_zero_array(mem_ctx, struct wbint_userinfo, count);
+ if (!*pinfo) {
status = NT_STATUS_NO_MEMORY;
goto done;
}
- i = 0;
+ count = 0;
for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
- const char *name;
- const char *gecos = NULL;
- const char *homedir = NULL;
- const char *shell = NULL;
+ struct wbint_userinfo *info = &((*pinfo)[count]);
uint32 group;
uint32 atype;
- struct dom_sid user_sid;
- gid_t primary_gid = (gid_t)-1;
if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
ds_atype_map(atype) != SID_NAME_USER) {
continue;
}
- name = ads_pull_username(ads, mem_ctx, msg);
-
- if ( ads_pull_sid( ads, msg, "objectSid", &user_sid ) ) {
- status = nss_get_info_cached( domain, &user_sid, mem_ctx,
- ads, msg, &homedir, &shell, &gecos,
- &primary_gid );
- }
-
- if (gecos == NULL) {
- gecos = ads_pull_string(ads, mem_ctx, msg, "name");
- }
+ info->acct_name = ads_pull_username(ads, mem_ctx, msg);
+ info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
+ info->homedir = NULL;
+ info->shell = NULL;
+ info->primary_gid = (gid_t)-1;
if (!ads_pull_sid(ads, msg, "objectSid",
- &(*info)[i].user_sid)) {
- DEBUG(1,("No sid for %s !?\n", name));
+ &info->user_sid)) {
+ DEBUG(1, ("No sid for %s !?\n", info->acct_name));
continue;
}
+
if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) {
- DEBUG(1,("No primary group for %s !?\n", name));
+ DEBUG(1, ("No primary group for %s !?\n",
+ info->acct_name));
continue;
}
+ sid_compose(&info->group_sid, &domain->sid, group);
- (*info)[i].acct_name = name;
- (*info)[i].full_name = gecos;
- (*info)[i].homedir = homedir;
- (*info)[i].shell = shell;
- (*info)[i].primary_gid = primary_gid;
- sid_compose(&(*info)[i].group_sid, &domain->sid, group);
- i++;
+ count += 1;
+ }
+
+ (*num_entries) = count;
+ ads_msgfree(ads, res);
+
+ for (i=0; i<count; i++) {
+ struct wbint_userinfo *info = &((*pinfo)[i]);
+ const char *gecos = NULL;
+ gid_t primary_gid = (gid_t)-1;
+
+ status = nss_get_info_cached(domain, &info->user_sid, mem_ctx,
+ &info->homedir, &info->shell,
+ &gecos, &primary_gid);
+ if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * Deliberately ignore this error, there might be more
+ * users to fill
+ */
+ continue;
+ }
+
+ if (gecos != NULL) {
+ info->full_name = gecos;
+ }
+ info->primary_gid = primary_gid;
}
- (*num_entries) = i;
status = NT_STATUS_OK;
DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries)));
done:
- if (res)
- ads_msgfree(ads, res);
-
return status;
}
static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_entries,
- struct acct_info **info)
+ struct wb_acct_info **info)
{
ADS_STRUCT *ads = NULL;
const char *attrs[] = {"userPrincipalName", "sAMAccountName",
}
rc = ads_search_retry(ads, &res, filter, attrs);
- if (!ADS_ERR_OK(rc) || !res) {
+ if (!ADS_ERR_OK(rc)) {
+ status = ads_ntstatus(rc);
DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
goto done;
+ } else if (!res) {
+ DEBUG(1,("enum_dom_groups ads_search returned NULL res\n"));
+ goto done;
}
count = ads_count_replies(ads, res);
goto done;
}
- (*info) = TALLOC_ZERO_ARRAY(mem_ctx, struct acct_info, count);
+ (*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
if (!*info) {
status = NT_STATUS_NO_MEMORY;
goto done;
static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_entries,
- struct acct_info **info)
+ struct wb_acct_info **info)
{
/*
* This is a stub function only as we returned the domain
uint32 group_rid;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
struct netr_SamInfo3 *user = NULL;
- gid_t gid;
+ gid_t gid = -1;
int ret;
char *ads_name;
info->homedir = NULL;
info->shell = NULL;
- info->primary_gid = (gid_t)-1;
/* try netsamlogon cache first */
- if ( (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL )
+ if ( (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL )
{
DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
sid_string_dbg(sid)));
info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string);
info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string);
- nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL,
+ nss_get_info_cached( domain, sid, mem_ctx,
&info->homedir, &info->shell, &info->full_name,
&gid );
info->primary_gid = gid;
/* Try to fill in what the nss_info backend can do */
- nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL,
+ nss_get_info_cached( domain, sid, mem_ctx,
&info->homedir, &info->shell, &info->full_name,
&gid);
info->primary_gid = gid;
- status = NT_STATUS_OK;
- goto done;
+ return NT_STATUS_OK;
}
/* no cache...do the query */
if ( (ads = ads_cached_connection(domain)) == NULL ) {
domain->last_status = NT_STATUS_SERVER_DISABLED;
- goto done;
+ return NT_STATUS_SERVER_DISABLED;
}
- sidstr = sid_binstring(talloc_tos(), sid);
+ sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
ret = asprintf(&ldap_exp, "(objectSid=%s)", sidstr);
TALLOC_FREE(sidstr);
if (ret == -1) {
- status = NT_STATUS_NO_MEMORY;
- goto done;
+ return NT_STATUS_NO_MEMORY;
}
rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
SAFE_FREE(ldap_exp);
- if (!ADS_ERR_OK(rc) || !msg) {
+ if (!ADS_ERR_OK(rc)) {
DEBUG(1,("query_user(sid=%s) ads_search: %s\n",
sid_string_dbg(sid), ads_errstr(rc)));
- goto done;
+ return ads_ntstatus(rc);
+ } else if (!msg) {
+ DEBUG(1,("query_user(sid=%s) ads_search returned NULL res\n",
+ sid_string_dbg(sid)));
+ return NT_STATUS_INTERNAL_ERROR;
}
count = ads_count_replies(ads, msg);
if (count != 1) {
DEBUG(1,("query_user(sid=%s): Not found\n",
sid_string_dbg(sid)));
- goto done;
+ ads_msgfree(ads, msg);
+ return NT_STATUS_NO_SUCH_USER;
}
info->acct_name = ads_pull_username(ads, mem_ctx, msg);
if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
DEBUG(1,("No primary group for %s !?\n",
sid_string_dbg(sid)));
- goto done;
+ ads_msgfree(ads, msg);
+ return NT_STATUS_NO_SUCH_USER;
}
-
sid_copy(&info->user_sid, sid);
sid_compose(&info->group_sid, &domain->sid, group_rid);
* nss_get_info_cached call. nss_get_info_cached might destroy
* the ads struct, potentially invalidating the ldap message.
*/
-
ads_name = ads_pull_string(ads, mem_ctx, msg, "name");
ads_msgfree(ads, msg);
msg = NULL;
- status = nss_get_info_cached( domain, sid, mem_ctx, ads, msg,
+ status = nss_get_info_cached( domain, sid, mem_ctx,
&info->homedir, &info->shell, &info->full_name,
&gid);
info->primary_gid = gid;
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("nss_get_info_cached failed: %s\n",
nt_errstr(status)));
- goto done;
+ return status;
}
if (info->full_name == NULL) {
status = NT_STATUS_OK;
DEBUG(3,("ads query_user gave %s\n", info->acct_name));
-done:
- return status;
+ return NT_STATUS_OK;
}
/* Lookup groups a user is a member of - alternate method, for when
TALLOC_CTX *mem_ctx,
const char *user_dn,
struct dom_sid *primary_group,
- size_t *p_num_groups, struct dom_sid **user_sids)
+ uint32_t *p_num_groups, struct dom_sid **user_sids)
{
ADS_STATUS rc;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
ADS_STRUCT *ads;
const char *group_attrs[] = {"objectSid", NULL};
char *escaped_dn;
- size_t num_groups = 0;
+ uint32_t num_groups = 0;
DEBUG(3,("ads: lookup_usergroups_member\n"));
rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
- if (!ADS_ERR_OK(rc) || !res) {
+ if (!ADS_ERR_OK(rc)) {
DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
return ads_ntstatus(rc);
+ } else if (!res) {
+ DEBUG(1,("lookup_usergroups ads_search returned NULL res\n"));
+ return NT_STATUS_INTERNAL_ERROR;
}
+
count = ads_count_replies(ads, res);
*user_sids = NULL;
TALLOC_CTX *mem_ctx,
const char *user_dn,
struct dom_sid *primary_group,
- size_t *p_num_groups,
+ uint32_t *p_num_groups,
struct dom_sid **user_sids)
{
ADS_STATUS rc;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
ADS_STRUCT *ads;
const char *attrs[] = {"memberOf", NULL};
- size_t num_groups = 0;
+ uint32_t num_groups = 0;
struct dom_sid *group_sids = NULL;
int i;
char **strings = NULL;
goto done;
}
- group_sids = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, num_strings + 1);
+ group_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_strings + 1);
if (!group_sids) {
status = NT_STATUS_NO_MEMORY;
goto done;
struct dom_sid primary_group;
uint32 primary_group_rid;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
- size_t num_groups = 0;
+ uint32_t num_groups = 0;
DEBUG(3,("ads: lookup_usergroups\n"));
*p_num_groups = 0;
status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
&primary_group,
&num_groups, user_sids);
- *p_num_groups = (uint32)num_groups;
+ *p_num_groups = num_groups;
if (NT_STATUS_IS_OK(status)) {
goto done;
}
status = lookup_usergroups_member(domain, mem_ctx, user_dn,
&primary_group,
&num_groups, user_sids);
- *p_num_groups = (uint32)num_groups;
+ *p_num_groups = num_groups;
goto done;
}
goto done;
}
- if ((sidbinstr = sid_binstring(talloc_tos(), group_sid)) == NULL) {
+ if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
status = NT_STATUS_NO_MEMORY;
goto done;
}
* cache. Only the rest is passed to the lsa_lookup_sids call. */
if (num_members) {
- (*sid_mem) = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, num_members);
- (*names) = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_members);
- (*name_types) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_members);
- (sid_mem_nocache) = TALLOC_ZERO_ARRAY(tmp_ctx, struct dom_sid, num_members);
+ (*sid_mem) = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
+ (*names) = talloc_zero_array(mem_ctx, char *, num_members);
+ (*name_types) = talloc_zero_array(mem_ctx, uint32, num_members);
+ (sid_mem_nocache) = talloc_zero_array(tmp_ctx, struct dom_sid, num_members);
if ((members == NULL) || (*sid_mem == NULL) ||
(*names == NULL) || (*name_types == NULL) ||
struct netr_DomainTrustList *trusts)
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ WERROR werr;
int i;
uint32 flags;
struct rpc_pipe_client *cli;
int ret_count;
+ struct dcerpc_binding_handle *b;
DEBUG(3,("ads: trusted_domains\n"));
return NT_STATUS_UNSUCCESSFUL;
}
- result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
+ b = cli->binding_handle;
+
+ result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
cli->desthost,
flags,
trusts,
- NULL);
+ &werr);
if (!NT_STATUS_IS_OK(result)) {
return result;
}
+
+ if (!W_ERROR_IS_OK(werr)) {
+ return werror_to_ntstatus(werr);
+ }
if (trusts->count == 0) {
return NT_STATUS_OK;
}