summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2008-02-04 18:18:36 +0100
committerStefan Metzmacher <metze@samba.org>2008-02-13 13:30:16 +0100
commitb397b5cb8f0a9ca5d5b2fa3349635a4cebd81779 (patch)
treed6fa22db6ae0bda245600228caba9ee254c3b856
parent5fb87ff3efc56de954ea08d286c90fbaaf99ea0a (diff)
downloadsamba-b397b5cb8f0a9ca5d5b2fa3349635a4cebd81779.tar.gz
samba-b397b5cb8f0a9ca5d5b2fa3349635a4cebd81779.tar.bz2
samba-b397b5cb8f0a9ca5d5b2fa3349635a4cebd81779.zip
auth_winbind: use wbcAuthenticateUserEx()
smbd doesn't need $(WBCOMMON_OBJ) anymore, it works with any libwbclient.so now and may talk to an older winbindd. metze (This used to be commit e3435930a307cff3066fe2047ed8c5c48911f001)
-rw-r--r--source3/Makefile.in5
-rw-r--r--source3/auth/auth_util.c233
-rw-r--r--source3/auth/auth_winbind.c113
3 files changed, 279 insertions, 72 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index f91bdf5c10..e1a6436365 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -640,9 +640,8 @@ SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
$(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \
$(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) \
$(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \
- $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
- $(BUILDOPT_OBJ) $(SMBLDAP_OBJ) $(LDB_OBJ) $(LIBNET_OBJ) \
- $(WBCOMMON_OBJ) @LIBWBCLIENT_STATIC@
+ $(REGISTRY_OBJ) $(POPT_LIB_OBJ) $(BUILDOPT_OBJ) \
+ $(SMBLDAP_OBJ) $(LDB_OBJ) $(LIBNET_OBJ) @LIBWBCLIENT_STATIC@
PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/print_aix.o \
printing/print_cups.o printing/print_generic.o \
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index ce47e94eb5..6efd31d574 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -1654,6 +1654,239 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
+/*****************************************************************************
+ Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
+******************************************************************************/
+
+NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
+ const char *sent_nt_username,
+ const char *domain,
+ const struct wbcAuthUserInfo *info,
+ auth_serversupplied_info **server_info)
+{
+ char zeros[16];
+
+ NTSTATUS nt_status = NT_STATUS_OK;
+ char *found_username = NULL;
+ const char *nt_domain;
+ const char *nt_username;
+ struct samu *sam_account = NULL;
+ DOM_SID user_sid;
+ DOM_SID group_sid;
+ bool username_was_mapped;
+ uint32_t i;
+
+ uid_t uid = (uid_t)-1;
+ gid_t gid = (gid_t)-1;
+
+ auth_serversupplied_info *result;
+
+ result = make_server_info(NULL);
+ if (result == NULL) {
+ DEBUG(4, ("make_server_info failed!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /*
+ Here is where we should check the list of
+ trusted domains, and verify that the SID
+ matches.
+ */
+
+ memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid));
+ memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid));
+
+ if (info->account_name) {
+ nt_username = talloc_strdup(result, info->account_name);
+ } else {
+ /* If the server didn't give us one, just use the one we sent
+ * them */
+ nt_username = talloc_strdup(result, sent_nt_username);
+ }
+ if (!nt_username) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (info->domain_name) {
+ nt_domain = talloc_strdup(result, info->domain_name);
+ } else {
+ /* If the server didn't give us one, just use the one we sent
+ * them */
+ nt_domain = talloc_strdup(result, domain);
+ }
+ if (!nt_domain) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* try to fill the SAM account.. If getpwnam() fails, then try the
+ add user script (2.2.x behavior).
+
+ We use the _unmapped_ username here in an attempt to provide
+ consistent username mapping behavior between kerberos and NTLM[SSP]
+ authentication in domain mode security. I.E. Username mapping
+ should be applied to the fully qualified username
+ (e.g. DOMAIN\user) and not just the login name. Yes this means we
+ called map_username() unnecessarily in make_user_info_map() but
+ that is how the current code is designed. Making the change here
+ is the least disruptive place. -- jerry */
+
+ if ( !(sam_account = samu_new( result )) ) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* this call will try to create the user if necessary */
+
+ nt_status = fill_sam_account(result, nt_domain, sent_nt_username,
+ &found_username, &uid, &gid, sam_account,
+ &username_was_mapped);
+
+ /* if we still don't have a valid unix account check for
+ 'map to guest = bad uid' */
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ TALLOC_FREE( result );
+ if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
+ make_server_info_guest(server_info);
+ return NT_STATUS_OK;
+ }
+ return nt_status;
+ }
+
+ if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (!pdb_set_fullname(sam_account, info->full_name, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_logon_script(sam_account, info->logon_script, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_profile_path(sam_account, info->profile_path, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_homedir(sam_account, info->home_directory, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_dir_drive(sam_account, info->home_drive, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_acct_ctrl(sam_account, info->acct_flags, PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_pass_last_set_time(
+ sam_account,
+ nt_time_to_unix(info->pass_last_set_time),
+ PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_pass_can_change_time(
+ sam_account,
+ nt_time_to_unix(info->pass_can_change_time),
+ PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_pass_must_change_time(
+ sam_account,
+ nt_time_to_unix(info->pass_must_change_time),
+ PDB_CHANGED)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* save this here to _net_sam_logon() doesn't fail (it assumes a
+ valid struct samu) */
+
+ result->sam_account = sam_account;
+ result->unix_name = talloc_strdup(result, found_username);
+
+ result->login_server = talloc_strdup(result, info->logon_server);
+
+ /* Fill in the unix info we found on the way */
+
+ result->uid = uid;
+ result->gid = gid;
+
+ /* Create a 'combined' list of all SIDs we might want in the SD */
+
+ result->num_sids = info->num_sids - 2;
+ result->sids = talloc_array(result, DOM_SID, result->num_sids);
+ if (result->sids == NULL) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i < result->num_sids; i++) {
+ memcpy(&result->sids[i], &info->sids[i+2].sid, sizeof(result->sids[i]));
+ }
+
+ /* ensure we are never given NULL session keys */
+
+ ZERO_STRUCT(zeros);
+
+ if (memcmp(info->user_session_key, zeros, sizeof(zeros)) == 0) {
+ result->user_session_key = data_blob_null;
+ } else {
+ result->user_session_key = data_blob_talloc(
+ result, info->user_session_key,
+ sizeof(info->user_session_key));
+ }
+
+ if (memcmp(info->lm_session_key, zeros, 8) == 0) {
+ result->lm_session_key = data_blob_null;
+ } else {
+ result->lm_session_key = data_blob_talloc(
+ result, info->lm_session_key,
+ sizeof(info->lm_session_key));
+ }
+
+ result->was_mapped = username_was_mapped;
+
+ *server_info = result;
+
+ return NT_STATUS_OK;
+}
+
/***************************************************************************
Free a user_info struct
***************************************************************************/
diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c
index b24aa3a75b..26a1b7f101 100644
--- a/source3/auth/auth_winbind.c
+++ b/source3/auth/auth_winbind.c
@@ -25,31 +25,6 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
-static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response *response, NET_USER_INFO_3 *info3)
-{
- uint8 *info3_ndr;
- size_t len = response->length - sizeof(struct winbindd_response);
- prs_struct ps;
- if (len > 0) {
- info3_ndr = (uint8 *)response->extra_data.data;
- if (!prs_init(&ps, len, mem_ctx, UNMARSHALL)) {
- return NT_STATUS_NO_MEMORY;
- }
- prs_copy_data_in(&ps, (char *)info3_ndr, len);
- prs_set_offset(&ps,0);
- if (!net_io_user_info3("", info3, &ps, 1, 3, False)) {
- DEBUG(2, ("get_info3_from_ndr: could not parse info3 struct!\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
- prs_mem_free(&ps);
-
- return NT_STATUS_OK;
- } else {
- DEBUG(2, ("get_info3_from_ndr: No info3 struct found!\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-}
-
/* Authenticate a user with a challenge/response */
static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
@@ -58,11 +33,11 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
const auth_usersupplied_info *user_info,
auth_serversupplied_info **server_info)
{
- struct winbindd_request request;
- struct winbindd_response response;
- NSS_STATUS result;
NTSTATUS nt_status;
- NET_USER_INFO_3 info3;
+ wbcErr wbc_status;
+ struct wbcAuthUserParams params;
+ struct wbcAuthUserInfo *info = NULL;
+ struct wbcAuthErrorInfo *err = NULL;
if (!user_info) {
return NT_STATUS_INVALID_PARAMETER;
@@ -82,36 +57,34 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
/* Send off request */
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
+ params.account_name = user_info->smb_name;
+ params.domain_name = user_info->domain;
+ params.workstation_name = user_info->wksta_name;
- request.flags = WBFLAG_PAM_INFO3_NDR;
+ params.flags = 0;
+ params.parameter_control= user_info->logon_parameters;
- request.data.auth_crap.logon_parameters = user_info->logon_parameters;
+ params.level = WBC_AUTH_USER_LEVEL_RESPONSE;
- fstrcpy(request.data.auth_crap.user, user_info->smb_name);
- fstrcpy(request.data.auth_crap.domain, user_info->domain);
- fstrcpy(request.data.auth_crap.workstation, user_info->wksta_name);
+ memcpy(params.password.response.challenge,
+ auth_context->challenge.data,
+ sizeof(params.password.response.challenge));
- memcpy(request.data.auth_crap.chal, auth_context->challenge.data, sizeof(request.data.auth_crap.chal));
-
- request.data.auth_crap.lm_resp_len = MIN(user_info->lm_resp.length,
- sizeof(request.data.auth_crap.lm_resp));
- request.data.auth_crap.nt_resp_len = MIN(user_info->nt_resp.length,
- sizeof(request.data.auth_crap.nt_resp));
-
- memcpy(request.data.auth_crap.lm_resp, user_info->lm_resp.data,
- request.data.auth_crap.lm_resp_len);
- memcpy(request.data.auth_crap.nt_resp, user_info->nt_resp.data,
- request.data.auth_crap.nt_resp_len);
+ params.password.response.nt_length = user_info->nt_resp.length;
+ params.password.response.nt_data = user_info->nt_resp.data;
+ params.password.response.lm_length = user_info->lm_resp.length;
+ params.password.response.lm_data = user_info->lm_resp.data;
/* we are contacting the privileged pipe */
become_root();
- result = winbindd_priv_request_response(WINBINDD_PAM_AUTH_CRAP,
- &request, &response);
+ wbc_status = wbcAuthenticateUserEx(&params, &info, &err);
unbecome_root();
- if ( result == NSS_STATUS_UNAVAIL ) {
+ if (wbc_status == WBC_ERR_NO_MEMORY) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (wbc_status == WBC_ERR_WINBIND_NOT_AVAILABLE) {
struct auth_methods *auth_method =
(struct auth_methods *)my_private_data;
@@ -123,27 +96,29 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
DEBUG(0,("check_winbind_security: ERROR! my_private_data == NULL!\n"));
}
- nt_status = NT_STATUS(response.data.auth.nt_status);
-
- if (result == NSS_STATUS_SUCCESS && response.extra_data.data) {
- if (NT_STATUS_IS_OK(nt_status)) {
- if (NT_STATUS_IS_OK(nt_status = get_info3_from_ndr(mem_ctx, &response, &info3))) {
- nt_status = make_server_info_info3(mem_ctx,
- user_info->smb_name, user_info->domain,
- server_info, &info3);
- }
-
- if (NT_STATUS_IS_OK(nt_status)) {
- if (user_info->was_mapped) {
- (*server_info)->was_mapped = user_info->was_mapped;
- }
- }
- }
- } else if (NT_STATUS_IS_OK(nt_status)) {
- nt_status = NT_STATUS_NO_LOGON_SERVERS;
+ if (wbc_status == WBC_ERR_AUTH_ERROR) {
+ nt_status = NT_STATUS(err->nt_status);
+ wbcFreeMemory(err);
+ return nt_status;
+ }
+
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return NT_STATUS_LOGON_FAILURE;
+ }
+
+ nt_status = make_server_info_wbcAuthUserInfo(mem_ctx,
+ user_info->smb_name,
+ user_info->domain,
+ info, server_info);
+ wbcFreeMemory(info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ if (user_info->was_mapped) {
+ (*server_info)->was_mapped = user_info->was_mapped;
}
- SAFE_FREE(response.extra_data.data);
return nt_status;
}