return wbcRequestResponse(WINBINDD_CCACHE_SAVE, &request, &response);
}
+
+
+/* Confirm the user is permitted to login by checkign with winbindd */
+wbcErr wbcCheckAccount(const char *user,
+ struct wbcAuthErrorInfo **error)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ strncpy(request.data.username, user,
+ sizeof(request.data.username)-1);
+
+ wbc_status = wbcRequestResponse(WINBINDD_PAM_ACCOUNT, &request, &response);
+
+ if (response.data.auth.nt_status != 0) {
+ if (error) {
+ wbc_status = wbc_create_error_info(&response,
+ error);
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ wbc_status = WBC_ERR_AUTH_ERROR;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+done:
+ return wbc_status;
+}
**/
wbcErr wbcCredentialSave(const char *user, const char *password);
+/**
+ * @brief Confirm the user is permitted to login by checking with winbindd
+ *
+ * @param *user Username
+ *
+ * @return #wbcErr
+ **/
+wbcErr wbcCheckAccount(const char *user,
+ struct wbcAuthErrorInfo **error);
+
+
/**********************************************************
* Resolve functions
**********************************************************/
/*
* Checks if a user has an account
*
- * return values:
- * 1 = User not found
- * 0 = OK
- * -1 = System error
+ * return values: PAM errors
+ *
*/
static int valid_user(struct pwb_context *ctx,
const char *user)
* sure it's really a winbind user, this is important when stacking PAM
* modules in the 'account' or 'password' facility. */
+ int ret;
wbcErr wbc_status;
struct passwd *pwd = NULL;
- struct passwd *wb_pwd = NULL;
+ struct wbcAuthErrorInfo *error = NULL;
pwd = getpwnam(user);
if (pwd == NULL) {
return 1;
}
- wbc_status = wbcGetpwnam(user, &wb_pwd);
- wbcFreeMemory(wb_pwd);
+ wbc_status = wbcCheckAccount(user, &error);
if (!WBC_ERROR_IS_OK(wbc_status)) {
- _pam_log(ctx, LOG_DEBUG, "valid_user: wbcGetpwnam gave %s\n",
+ _pam_log(ctx, LOG_DEBUG, "valid_user: wbcCheckAccount gave %s\n",
wbcErrorString(wbc_status));
}
- switch (wbc_status) {
- case WBC_ERR_UNKNOWN_USER:
- return 1;
- case WBC_ERR_SUCCESS:
- return 0;
- default:
- break;
- }
- return -1;
+ ret = wbc_auth_error_to_pam_error(ctx, error, wbc_status,
+ user, "wbcCheckAccount");
+
+ wbcFreeMemory(error);
+ return ret;
}
static char *_pam_delete(register char *xx)
/* check if this is really a user in winbindd, not only in NSS */
ret = valid_user(ctx, user);
- switch (ret) {
- case 1:
- ret = PAM_USER_UNKNOWN;
- goto out;
- case -1:
- ret = PAM_SYSTEM_ERR;
- goto out;
- default:
- break;
- }
/*
* obtain and verify the current password (OLDAUTHTOK) for
return true;
}
+static bool wbinfo_check_account(const char *account)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcAuthErrorInfo *error = NULL;
+
+ if (!account) {
+ d_printf("checking the account requires an argument\n");
+ return false;
+ }
+
+ wbc_status = wbcCheckAccount(account, &error);
+
+ d_printf("checking the account %s as permitted to log in %s\n",
+ account,
+ WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
+
+ if (wbc_status == WBC_ERR_AUTH_ERROR) {
+ d_fprintf(stderr,
+ "error code was %s (0x%x)\nerror messsage was: %s\n",
+ error->nt_string,
+ error->nt_status,
+ error->display_string);
+ wbcFreeMemory(error);
+ }
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return false;
+ }
+
+ return true;
+}
+
/* Save creds with winbind */
static bool wbinfo_ccache_save(char *username)
OPT_LOGOFF,
OPT_LOGOFF_USER,
OPT_LOGOFF_UID,
- OPT_LANMAN
+ OPT_LANMAN,
+ OPT_CHECK_ACCOUNT
};
int main(int argc, char **argv, char **envp)
{ "change-user-password", 0, POPT_ARG_STRING, &string_arg, OPT_CHANGE_USER_PASSWORD, "Change the password for a user", NULL },
{ "ntlmv2", 0, POPT_ARG_NONE, 0, OPT_NTLMV2, "Use NTLMv2 cryptography for user authentication", NULL},
{ "lanman", 0, POPT_ARG_NONE, 0, OPT_LANMAN, "Use lanman cryptography for user authentication", NULL},
+ { "check-account", 0, POPT_ARG_STRING, &string_arg, OPT_CHECK_ACCOUNT, "Check if nominated account is permitted to log in", NULL},
POPT_COMMON_VERSION
POPT_TABLEEND
};
case OPT_LOGOFF_USER:
case OPT_LOGOFF_UID:
break;
+ case OPT_CHECK_ACCOUNT:
+ if (!wbinfo_check_account(string_arg)) {
+ goto done;
+ }
+ break;
default:
d_fprintf(stderr, "Invalid option\n");
poptPrintHelp(pc, stderr, 0);
* removed WINBINDD_REMOVE_MAPPING
* 26: added WINBINDD_DC_INFO
* 27: added WINBINDD_LOOKUPSIDS
+ * 28: added WINBINDD_PAM_ACCOUNT
*/
-#define WINBIND_INTERFACE_VERSION 27
+#define WINBIND_INTERFACE_VERSION 28
/* Have to deal with time_t being 4 or 8 bytes due to structure alignment.
On a 64bit Linux box, we have to support a constant structure size
WINBINDD_PAM_CHAUTHTOK,
WINBINDD_PAM_LOGOFF,
WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,
+ WINBINDD_PAM_ACCOUNT,
/* List various things */
winbindd/winbindd_util.o \
winbindd/winbindd_cache.o \
winbindd/winbindd_pam.o \
+ winbindd/winbindd_pam_account.o \
winbindd/winbindd_misc.o \
winbindd/winbindd_cm.o \
winbindd/winbindd_wins_byip.o \
const char *lp_workgroup(void);
const char *lp_realm(void);
const char *lp_dnsdomain(void);
+const char *lp_orgunit(void);
const char *lp_afs_username_map(void);
int lp_afs_token_lifetime(void);
char *lp_log_nt_token_command(void);
hyper primary_gid;
dom_sid user_sid;
dom_sid group_sid;
+ [string,charset(UTF8)] char *dn;
} wbint_userinfo;
NTSTATUS wbint_QueryUser(
[in] dom_sid *sid,
+ [in] uint32 flags,
[out] wbint_userinfo *info
);
.flags = FLAG_ADVANCED,
},
#endif
+ {
+ .label = "orgunit",
+ .type = P_USTRING,
+ .p_class = P_GLOBAL,
+ .offset = GLOBAL_VAR(szOrgUnit),
+ .special = NULL,
+ .enum_list = NULL,
+ .flags = FLAG_ADVANCED,
+ },
{
.label = "default service",
.type = P_STRING,
FN_GLOBAL_CONST_STRING(lp_netbios_scope, szNetbiosScope)
FN_GLOBAL_CONST_STRING(lp_realm, szRealmUpper)
FN_GLOBAL_CONST_STRING(lp_dnsdomain, szDnsDomain)
+FN_GLOBAL_CONST_STRING(lp_orgunit, szOrgUnit)
FN_GLOBAL_CONST_STRING(lp_afs_username_map, szAfsUsernameMap)
FN_GLOBAL_INTEGER(lp_afs_token_lifetime, iAfsTokenLifetime)
FN_GLOBAL_STRING(lp_log_nt_token_command, szLogNtTokenCommand)
#Didn't pass yet# "--domain-users",
"--domain-groups",
"--name-to-sid=$DC_USERNAME",
+ "--check-account=$DOMAIN\\\\$DC_USERNAME",
"--name-to-sid=$DOMAIN\\\\$DC_USERNAME",
#Didn't pass yet# "--user-info=$USERNAME",
"--user-groups=$DOMAIN\\\\$DC_USERNAME",
state->ev = ev;
state->pw = pw;
- subreq = wb_queryuser_send(state, ev, &state->sid);
+ subreq = wb_queryuser_send(state, ev, &state->sid, 0);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
- const struct dom_sid *user_sid)
+ const struct dom_sid *user_sid,
+ uint32_t flags)
{
struct tevent_req *req, *subreq;
struct wb_queryuser_state *state;
}
subreq = dcerpc_wbint_QueryUser_send(state, ev, dom_child_handle(domain),
- &state->sid, state->info);
+ &state->sid, flags, state->info);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
{ WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
winbindd_pam_chng_pswd_auth_crap_send,
winbindd_pam_chng_pswd_auth_crap_recv },
+ { WINBINDD_PAM_ACCOUNT, "PAM_ACCOUNT",
+ winbindd_pam_account_send, winbindd_pam_account_recv },
{ WINBINDD_WINS_BYIP, "WINS_BYIP",
winbindd_wins_byip_send, winbindd_wins_byip_recv },
{ WINBINDD_WINS_BYNAME, "WINS_BYNAME",
uint32_t rid; /* domain-relative RID */
};
+#define WB_QUERY_USER_FLAG_MUST_DN 1
+
/* per-domain methods. This is how LDAP vs RPC is selected
*/
struct winbindd_methods {
NTSTATUS (*query_user)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const struct dom_sid *user_sid,
+ uint32_t flags,
struct wbint_userinfo *user_info);
/* lookup all groups that a user is a member of. The backend
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const struct dom_sid *sid,
+ uint32_t flags,
struct wbint_userinfo *info)
{
ADS_STRUCT *ads = NULL;
DEBUG(8,("query_user: No incoming trust from domain %s\n",
domain->name));
+ if (flags & WB_QUERY_USER_FLAG_MUST_DN) {
+ DEBUG(1,("query_user: No incoming trust from domain %s and DN required by caller\n",
+ domain->name));
+
+ return NT_STATUS_INVALID_DOMAIN_STATE;
+ }
+
/* We still need to generate some basic information
about the user even if we cannot contact the
domain. Most of this stuff we can deduce. */
*/
ads_name = ads_pull_string(ads, mem_ctx, msg, "name");
+ info->dn = ads_get_dn(ads, mem_ctx, msg);
+
ads_msgfree(ads, msg);
msg = NULL;
centry_put_uint32(centry, info->primary_gid);
centry_put_sid(centry, &info->user_sid);
centry_put_sid(centry, &info->group_sid);
+ centry_put_string(centry, info->dn);
centry_end(centry, "U/%s", sid_to_fstring(sid_string,
&info->user_sid));
DEBUG(10,("wcache_save_user: %s (acct_name %s)\n", sid_string, info->acct_name));
(*info)[i].shell = centry_string(centry, mem_ctx);
centry_sid(centry, &(*info)[i].user_sid);
centry_sid(centry, &(*info)[i].group_sid);
+ (*info)[i].dn = centry_string(centry, mem_ctx);
}
do_cached:
centry_put_string(centry, (*info)[i].shell);
centry_put_sid(centry, &(*info)[i].user_sid);
centry_put_sid(centry, &(*info)[i].group_sid);
+ centry_put_string(centry, (*info)[i].dn);
if (domain->backend && domain->backend->consistent) {
/* when the backend is consistent we can pre-prime some mappings */
wcache_save_name_to_sid(domain, NT_STATUS_OK,
NTSTATUS wcache_query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const struct dom_sid *user_sid,
+ uint32_t flags,
struct wbint_userinfo *info)
{
struct winbind_cache *cache = get_cache(domain);
info->primary_gid = centry_uint32(centry);
centry_sid(centry, &info->user_sid);
centry_sid(centry, &info->group_sid);
+ info->dn = centry_string(centry, mem_ctx);
+
+ if (info->dn == NULL && (flags & WB_QUERY_USER_FLAG_MUST_DN)) {
+ /* If the caller said they must get the DN, then we must not return an entry without it */
+ status = NT_STATUS_NOT_FOUND;
+ }
}
DEBUG(10,("query_user: [Cached] - cached info for domain %s status: "
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const struct dom_sid *user_sid,
+ uint32_t flags,
struct wbint_userinfo *info)
{
NTSTATUS status;
bool old_status;
old_status = domain->online;
- status = wcache_query_user(domain, mem_ctx, user_sid, info);
+ status = wcache_query_user(domain, mem_ctx, user_sid, flags, info);
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
return status;
}
DEBUG(10,("query_user: [Cached] - doing backend query for info for domain %s\n",
domain->name ));
- status = domain->backend->query_user(domain, mem_ctx, user_sid, info);
+ status = domain->backend->query_user(domain, mem_ctx, user_sid, flags, info);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
!domain->online &&
old_status) {
NTSTATUS cache_status;
- cache_status = wcache_query_user(domain, mem_ctx, user_sid, info);
+ cache_status = wcache_query_user(domain, mem_ctx, user_sid, flags, info);
return cache_status;
}
}
(void)centry_uint32(centry);
(void)centry_sid(centry, &sid);
(void)centry_sid(centry, &sid);
+ (void)centry_string(centry, mem_ctx);
centry_free(centry);
}
status = domain->methods->query_user(domain, p->mem_ctx, r->in.sid,
+ r->in.flags,
r->out.info);
reset_cm_connection_on_error(domain, status);
return status;
/* Lookup user information from a rid or username. */
static NTSTATUS msrpc_query_user(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *user_sid,
- struct wbint_userinfo *user_info)
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t flags,
+ struct wbint_userinfo *user_info)
{
struct rpc_pipe_client *samr_pipe;
struct policy_handle dom_pol;
DEBUG(3,("msrpc_query_user sid=%s\n", sid_string_dbg(user_sid)));
+ if (flags & WB_QUERY_USER_FLAG_MUST_DN) {
+ DEBUG(1,("query_user: Domain %s is not ADS and DN required by caller\n",
+ domain->name));
+
+ return NT_STATUS_INVALID_DOMAIN_STATE;
+ }
+
tmp_ctx = talloc_stackframe();
if (tmp_ctx == NULL) {
return NT_STATUS_NO_MEMORY;
--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_PAM_ACCOUNT
+ Copyright (C) Volker Lendecke 2009
+ Copyright (C) Andrew Bartlett 2012
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include <ldb.h>
+#include "include/ads.h"
+#include "passdb/lookup_sid.h" /* only for LOOKUP_NAME_NO_NSS flag */
+
+struct winbindd_pam_account_state {
+ struct tevent_context *ev;
+ fstring domname;
+ fstring username;
+ struct dom_sid sid;
+ enum lsa_SidType type;
+ struct wbint_userinfo *userinfo;
+};
+
+static void winbindd_pam_account_lookupname_done(struct tevent_req *subreq);
+static void winbindd_pam_account_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_pam_account_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_cli_state *cli,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_pam_account_state *state;
+ char *domuser, *mapped_user;
+ NTSTATUS status;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_pam_account_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+
+ /* Ensure null termination */
+ request->data.username[sizeof(request->data.username)-1]='\0';
+
+ DEBUG(3, ("pam_account %s\n", request->data.username));
+
+ domuser = request->data.username;
+
+ status = normalize_name_unmap(state, domuser, &mapped_user);
+
+ if (NT_STATUS_IS_OK(status)
+ || NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
+ /* normalize_name_unmapped did something */
+ domuser = mapped_user;
+ }
+
+ if (!parse_domain_user(domuser, state->domname, state->username)) {
+ DEBUG(5, ("Could not parse domain user: %s\n", domuser));
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = wb_lookupname_send(state, ev, state->domname, state->username,
+ LOOKUP_NAME_NO_NSS);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_pam_account_lookupname_done,
+ req);
+ return req;
+}
+
+static void winbindd_pam_account_lookupname_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_pam_account_state *state = tevent_req_data(
+ req, struct winbindd_pam_account_state);
+ NTSTATUS status;
+ uint32_t flags = 0;
+
+ const char *orgunit = lp_orgunit();
+
+ if (orgunit && *orgunit && strequal(state->domname, lp_workgroup())) {
+ flags = WB_QUERY_USER_FLAG_MUST_DN;
+ }
+
+ status = wb_lookupname_recv(subreq, &state->sid, &state->type);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ subreq = wb_queryuser_send(state, state->ev, &state->sid, flags);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, winbindd_pam_account_done, req);
+}
+
+static void winbindd_pam_account_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_pam_account_state *state = tevent_req_data(
+ req, struct winbindd_pam_account_state);
+ NTSTATUS status;
+
+ status = wb_queryuser_recv(subreq, state, &state->userinfo);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+static NTSTATUS winbindd_pam_account_recv_helper(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct ldb_dn *account_dn;
+ struct ldb_dn *orgunit_dn;
+ char *domain_dn_str;
+ struct ldb_context *ldb;
+ const char *orgunit = lp_orgunit();
+
+ struct winbindd_pam_account_state *state = tevent_req_data(
+ req, struct winbindd_pam_account_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not check DN for user %s\\%s: %s\n",
+ state->domname, state->username, nt_errstr(status)));
+ return status;
+ }
+
+ if (orgunit == NULL || *orgunit == '\0') {
+ DEBUG(7,("winbindd_pam_account: no orgunit restriction specified -- "
+ "allowing pam_account() for %s\\%s.\n",
+ state->domname, state->username));
+ return NT_STATUS_OK;
+ }
+
+ if (strequal(state->domname, lp_netbios_name())) {
+ DEBUG(7,("winbindd_pam_account: local SAM domain -- "
+ "allowing pam_account() for %s\\%s.\n",
+ state->domname, state->username));
+ return NT_STATUS_OK;
+ }
+
+ if (!strequal(state->domname, lp_workgroup())) {
+ DEBUG(7,("winbindd_pam_account: Not primary domain -- "
+ "rejecting pam_account() for %s\\%s.\n",
+ state->domname, state->username));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ ldb = ldb_init(NULL, NULL);
+
+ /* Finally do the OU check */
+ domain_dn_str = ads_build_dn(lp_realm());
+
+ if (domain_dn_str == NULL) {
+ talloc_free(ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ orgunit_dn = ldb_dn_new(ldb, ldb, domain_dn_str);
+
+ free(domain_dn_str);
+
+ account_dn = ldb_dn_new(ldb, ldb, state->userinfo->dn);
+ if (!account_dn) {
+ talloc_free(ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+ /* For now, this only handles one level of org unit */
+ if (!ldb_dn_add_child_fmt(orgunit_dn, "ou=%s", orgunit)) {
+ talloc_free(ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* FINALLY, we can check if the user is in that OU! */
+
+ if (ldb_dn_compare_base(orgunit_dn, account_dn) == 0) {
+ DEBUG(7, ("User %s allowed to log in, as they are within %s\n",
+ ldb_dn_get_linearized(account_dn),
+ ldb_dn_get_linearized(orgunit_dn)));
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(2, ("User %s not allowed to log in, as they are not within %s\n",
+ ldb_dn_get_linearized(account_dn),
+ ldb_dn_get_linearized(orgunit_dn)));
+ return NT_STATUS_ACCESS_DENIED;
+}
+
+NTSTATUS winbindd_pam_account_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ NTSTATUS status = winbindd_pam_account_recv_helper(req, response);
+ set_auth_errors(response, status);
+ return status;
+}
NTSTATUS wcache_query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const struct dom_sid *user_sid,
+ uint32_t flags,
struct wbint_userinfo *info);
NTSTATUS wcache_lookup_useraliases(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
struct winbindd_cli_state *state) ;
enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state);
+void winbindd_pam_account(struct winbindd_cli_state *state);
+enum winbindd_result winbindd_dual_pam_account(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state) ;
+
/* The following definitions come from winbindd/winbindd_util.c */
struct winbindd_domain *domain_list(void);
struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
- const struct dom_sid *user_sid);
+ const struct dom_sid *user_sid,
+ uint32_t flags);
NTSTATUS wb_queryuser_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
struct wbint_userinfo **pinfo);
struct rpc_pipe_client **samr_pipe,
struct policy_handle *samr_domain_hnd);
+struct tevent_req *winbindd_pam_account_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_cli_state *cli,
+ struct winbindd_request *request);
+NTSTATUS winbindd_pam_account_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
#endif /* _WINBINDD_PROTO_H_ */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const struct dom_sid *user_sid,
+ uint32_t flags,
struct wbint_userinfo *user_info)
{
NTSTATUS result;
result = msrpc_methods.query_user(domain, mem_ctx, user_sid,
+ flags,
user_info);
if (reconnect_need_retry(result))
result = msrpc_methods.query_user(domain, mem_ctx, user_sid,
- user_info);
+ flags, user_info);
return result;
}
dst->homedir = NULL;
dst->shell = NULL;
+ dst->dn = NULL;
sid_compose(&dst->user_sid, domain_sid, rid);
user_info->homedir = NULL;
user_info->shell = NULL;
+ user_info->dn = NULL;
user_info->primary_gid = (gid_t)-1;
return NT_STATUS_OK;
static NTSTATUS sam_query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const struct dom_sid *user_sid,
+ uint32_t flags,
struct wbint_userinfo *user_info)
{
struct rpc_pipe_client *samr_pipe;
DEBUG(3,("sam_query_user\n"));
+ if (flags & WB_QUERY_USER_FLAG_MUST_DN) {
+ DEBUG(1,("query_user: local domain %s is not ADS and DN required by caller\n",
+ domain->name));
+
+ return NT_STATUS_INVALID_DOMAIN_STATE;
+ }
+
ZERO_STRUCT(dom_pol);
/* Paranoia check */
static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const struct dom_sid *group_sid,
- enum lsa_SidType type,
+ enum lsa_SidType type,
uint32_t *pnum_names,
struct dom_sid **psid_mem,
char ***pnames,
/* Lookup user information from a rid or username. */
static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *user_sid,
- struct wbint_userinfo *user_info)
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t flags,
+ struct wbint_userinfo *user_info)
{
return NT_STATUS_NO_SUCH_USER;
}
winbindd/winbindd_pam_auth.c
winbindd/winbindd_pam_logoff.c
winbindd/winbindd_pam_chauthtok.c
+ winbindd/winbindd_pam_account.c
winbindd/winbindd_pam_auth_crap.c
winbindd/winbindd_pam_chng_pswd_auth_crap.c'''
RPC_NCACN_NP
RPC_PIPE_REGISTER
WB_REQTRANS
+ ldb
''',
enabled=bld.env.build_winbind,
install_path='${SBINDIR}',