From 61116049cabc292c2f2d570af4d68ddc537b91f5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 3 Jul 2003 14:36:42 +0000 Subject: This patch takes the work the jerry did for beta2, and generalises it: - The 'not implmented' checks are now done by all auth modules - the ntdomain/trustdomain/winbind modules are more presise as to what domain names they can and cannot handle - The become_root() calls are now around the winbind pipe opening only, not the entire auth call - The unix username is kept seperate from the NT username, removing the need for 'clean off the domain\' in parse_net.c - All sid->uid translations are now validated with getpwuid() to put a very basic stop to logins with 'half deleted' accounts. Andrew Bartlett (This used to be commit 85f88191b9927cc434645ef4c1eaf5ec0e8af2ec) --- source3/auth/auth.c | 21 ++++++------ source3/auth/auth_builtin.c | 5 +-- source3/auth/auth_domain.c | 6 ++-- source3/auth/auth_rhosts.c | 7 ++-- source3/auth/auth_server.c | 4 +-- source3/auth/auth_util.c | 79 ++++++++++++++++++++++++++++++++++----------- source3/auth/auth_winbind.c | 14 ++++++-- 7 files changed, 92 insertions(+), 44 deletions(-) (limited to 'source3/auth') diff --git a/source3/auth/auth.c b/source3/auth/auth.c index d99b00d4a7..9f109dc66e 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -203,8 +203,8 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { - - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + /* if all the modules say 'not for me' this is reasonable */ + NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER; const char *pdb_username; auth_methods *auth_method; TALLOC_CTX *mem_ctx; @@ -269,12 +269,8 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, } talloc_destroy(mem_ctx); - - /* this sucks. Somehow we have to know if an authentication module is - authoritative for a user. Fixme!!! --jerry */ - - if ( NT_STATUS_IS_OK(nt_status) || - NT_STATUS_V(nt_status) == NT_STATUS_V(NT_STATUS_WRONG_PASSWORD) ) + + if ( NT_STATUS_IS_OK(nt_status)) { break; } @@ -463,8 +459,13 @@ NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context) break; case SEC_USER: if (lp_encrypted_passwords()) { - DEBUG(5,("Making default auth method list for security=user, encrypt passwords = yes\n")); - auth_method_list = str_list_make("guest sam", NULL); + if ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC)) { + DEBUG(5,("Making default auth method list for DC, security=user, encrypt passwords = yes\n")); + auth_method_list = str_list_make("guest sam winbind:trustdomain", NULL); + } else { + DEBUG(5,("Making default auth method list for standalone security=user, encrypt passwords = yes\n")); + auth_method_list = str_list_make("guest sam", NULL); + } } else { DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n")); auth_method_list = str_list_make("guest unix", NULL); diff --git a/source3/auth/auth_builtin.c b/source3/auth/auth_builtin.c index 5a9b5534ab..0358836793 100644 --- a/source3/auth/auth_builtin.c +++ b/source3/auth/auth_builtin.c @@ -38,7 +38,8 @@ static NTSTATUS check_guest_security(const struct auth_context *auth_context, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + /* mark this as 'not for me' */ + NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; if (!(user_info->internal_username.str && *user_info->internal_username.str)) { @@ -133,7 +134,7 @@ static NTSTATUS check_fixed_challenge_security(const struct auth_context *auth_c const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_NOT_IMPLEMENTED; } /**************************************************************************** diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 80320d8266..56bd6b9aca 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -266,7 +266,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, * password file. */ - if(is_myname(user_info->domain.str)) { + if(strequal(get_global_sam_name(), user_info->domain.str)) { DEBUG(3,("check_ntdomain_security: Requested domain was for this machine.\n")); return NT_STATUS_NOT_IMPLEMENTED; } @@ -346,7 +346,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte * Check that the requested domain is not our own machine name or domain name. */ - if( is_myname(user_info->domain.str) || strequal(lp_workgroup(), user_info->domain.str) ) { + if( strequal(get_global_sam_name(), user_info->domain.str)) { DEBUG(3,("check_trustdomain_security: Requested domain [%s] was for this machine.\n", user_info->domain.str)); return NT_STATUS_NOT_IMPLEMENTED; @@ -358,7 +358,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte user is known to us and does not exist */ if ( !is_trusted_domain( user_info->domain.str ) ) - return NT_STATUS_NO_SUCH_USER; + return NT_STATUS_NOT_IMPLEMENTED; /* * Get the trusted account password for the trusted domain diff --git a/source3/auth/auth_rhosts.c b/source3/auth/auth_rhosts.c index 8fec760e21..e2c6f0b06a 100644 --- a/source3/auth/auth_rhosts.c +++ b/source3/auth/auth_rhosts.c @@ -162,7 +162,7 @@ static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_contex const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; SAM_ACCOUNT *account = NULL; if (!NT_STATUS_IS_OK(nt_status = auth_get_sam_account(user_info->internal_username.str, @@ -174,7 +174,6 @@ static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_contex nt_status = make_server_info_sam(server_info, account); } else { pdb_free_sam(&account); - nt_status = NT_STATUS_LOGON_FAILURE; } return nt_status; @@ -203,7 +202,7 @@ static NTSTATUS check_rhosts_security(const struct auth_context *auth_context, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; SAM_ACCOUNT *account = NULL; pstring rhostsfile; const char *home; @@ -223,12 +222,10 @@ static NTSTATUS check_rhosts_security(const struct auth_context *auth_context, nt_status = make_server_info_sam(server_info, account); } else { pdb_free_sam(&account); - nt_status = NT_STATUS_LOGON_FAILURE; } unbecome_root(); } else { pdb_free_sam(&account); - nt_status = NT_STATUS_LOGON_FAILURE; } return nt_status; diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c index 2a1e4a48d9..af0848e12a 100644 --- a/source3/auth/auth_server.c +++ b/source3/auth/auth_server.c @@ -222,7 +222,7 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context static fstring baduser; static BOOL tested_password_server = False; static BOOL bad_password_server = False; - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; BOOL locally_made_cli = False; /* @@ -233,7 +233,7 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context if(is_myname(user_info->domain.str)) { DEBUG(3,("check_smbserver_security: Requested domain was for this machine.\n")); - return NT_STATUS_LOGON_FAILURE; + return nt_status; } cli = my_private_data; diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 4e25d7fd34..ea46d27e9e 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -764,6 +764,7 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) { NTSTATUS nt_status; + struct passwd *pwd; if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) return nt_status; @@ -773,16 +774,35 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, if (!NT_STATUS_IS_OK(nt_status = sid_to_uid(pdb_get_user_sid(sampass), &((*server_info)->uid)))) return nt_status; - if (!NT_STATUS_IS_OK(nt_status = sid_to_gid(pdb_get_group_sid(sampass), &((*server_info)->gid)))) + if (!(pwd = getpwuid_alloc(((*server_info)->uid)))) { + fstring sid; + DEBUG(1, ("User %s in passdb (%s) maps to UID, but getpwuid(%u) fails!\n", + pdb_get_username(sampass), + sid_to_string(sid, pdb_get_user_sid(sampass)), + (unsigned)(*server_info)->uid)); + free_server_info(server_info); + return NT_STATUS_NO_SUCH_USER; + } + (*server_info)->unix_name = smb_xstrdup(pwd->pw_name); + passwd_free(&pwd); + + if (!NT_STATUS_IS_OK(nt_status = sid_to_gid(pdb_get_group_sid(sampass), + &((*server_info)->gid)))) { + free_server_info(server_info); return nt_status; + } if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, sampass, - (*server_info)->uid, (*server_info)->gid))) + (*server_info)->uid, + (*server_info)->gid))) { + free_server_info(server_info); return nt_status; + } (*server_info)->sam_fill_level = SAM_FILL_ALL; - DEBUG(5,("make_server_info_sam: made server info for user %s\n", - pdb_get_username((*server_info)->sam_account))); + DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n", + pdb_get_username(sampass), + (*server_info)->unix_name)); return nt_status; } @@ -809,6 +829,8 @@ NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, const struc return nt_status; } + (*server_info)->unix_name = smb_xstrdup(pwd->pw_name); + (*server_info)->sam_fill_level = SAM_FILL_ALL; (*server_info)->uid = pwd->pw_uid; (*server_info)->gid = pwd->pw_gid; @@ -852,8 +874,10 @@ NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info) Purely internal function for make_server_info_info3 Fill the sam account from getpwnam ***************************************************************************/ -static NTSTATUS fill_sam_account(const char *domain, +static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx, + const char *domain, const char *username, + char **found_username, uid_t *uid, gid_t *gid, SAM_ACCOUNT **sam_account) { @@ -878,6 +902,8 @@ static NTSTATUS fill_sam_account(const char *domain, *uid = passwd->pw_uid; *gid = passwd->pw_gid; + *found_username = talloc_strdup(mem_ctx, passwd->pw_name); + return pdb_init_sam_pw(sam_account, passwd); } @@ -893,7 +919,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *info3) { NTSTATUS nt_status = NT_STATUS_OK; - + char *found_username; const char *nt_domain; const char *nt_username; @@ -958,13 +984,15 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, gid = passwd->pw_gid; /* we should check this is the same name */ - + found_username = talloc_strdup(mem_ctx, passwd->pw_name); + passwd_free(&passwd); } else { /* User not from winbind - try and find them by getpwnam() */ - nt_status = fill_sam_account(nt_domain, + nt_status = fill_sam_account(mem_ctx, nt_domain, internal_username, + &found_username, &uid, &gid, &sam_account); @@ -972,8 +1000,9 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, DEBUG(3,("User %s does not exist, trying to add it\n", internal_username)); auth_add_user_script(nt_domain, internal_username); - nt_status = fill_sam_account(nt_domain, + nt_status = fill_sam_account(mem_ctx, nt_domain, internal_username, + &found_username, &uid, &gid, &sam_account); } @@ -984,17 +1013,12 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, return nt_status; } - if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) { + if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) { pdb_free_sam(&sam_account); - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_NO_MEMORY; } - if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) { - pdb_free_sam(&sam_account); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) { + if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) { pdb_free_sam(&sam_account); return NT_STATUS_NO_MEMORY; } @@ -1004,7 +1028,18 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - if (!pdb_set_fullname(sam_account, unistr2_static(&(info3->uni_full_name)), PDB_CHANGED)) { + if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) { + pdb_free_sam(&sam_account); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) { + pdb_free_sam(&sam_account); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!pdb_set_fullname(sam_account, unistr2_static(&(info3->uni_full_name)), + PDB_CHANGED)) { pdb_free_sam(&sam_account); return NT_STATUS_NO_MEMORY; } @@ -1040,6 +1075,8 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, (*server_info)->sam_account = sam_account; + (*server_info)->unix_name = smb_xstrdup(found_username); + /* Fill in the unix info we found on the way */ (*server_info)->sam_fill_level = SAM_FILL_ALL; @@ -1050,7 +1087,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, returned to the caller. */ if (!NT_STATUS_IS_OK(nt_status - = get_user_groups_from_local_sam(pdb_get_username(sam_account), + = get_user_groups_from_local_sam((*server_info)->unix_name, uid, gid, &n_lgroupSIDs, &lgroupSIDs, @@ -1070,6 +1107,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, if (!all_group_SIDs) { DEBUG(0, ("malloc() failed for DOM_SID list!\n")); SAFE_FREE(lgroupSIDs); + free_server_info(server_info); return NT_STATUS_NO_MEMORY; } @@ -1085,6 +1123,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, DEBUG(3,("could not append additional group rid 0x%x\n", info3->gids[i].g_rid)); SAFE_FREE(lgroupSIDs); + free_server_info(server_info); return nt_status; } } @@ -1110,6 +1149,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, all_group_SIDs, False, &token))) { DEBUG(4,("create_nt_user_token failed\n")); SAFE_FREE(all_group_SIDs); + free_server_info(server_info); return nt_status; } @@ -1161,6 +1201,7 @@ void free_server_info(auth_serversupplied_info **server_info) /* call pam_end here, unless we know we are keeping it */ delete_nt_token( &(*server_info)->ptok ); SAFE_FREE((*server_info)->groups); + SAFE_FREE((*server_info)->unix_name); ZERO_STRUCT(**server_info); } SAFE_FREE(*server_info); diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c index 6ae8685b11..856b8f5a82 100644 --- a/source3/auth/auth_winbind.c +++ b/source3/auth/auth_winbind.c @@ -72,9 +72,14 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, if (!auth_context) { DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", user_info->internal_username.str)); - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_INVALID_PARAMETER; } + if (strequal(user_info->domain.str, get_global_sam_name())) { + DEBUG(3,("check_winbind_security: Not using winbind, requested domain was for this SAM.\n")); + return NT_STATUS_NOT_IMPLEMENTED; + } + /* Send off request */ ZERO_STRUCT(request); @@ -100,8 +105,11 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, 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); - + + /* we are contacting the privileged pipe */ + become_root(); result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); + unbecome_root(); if ( result == NSS_STATUS_UNAVAIL ) { struct auth_methods *auth_method = my_private_data; @@ -129,7 +137,7 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, } } } else if (NT_STATUS_IS_OK(nt_status)) { - nt_status = NT_STATUS_UNSUCCESSFUL; + nt_status = NT_STATUS_NO_LOGON_SERVERS; } return nt_status; -- cgit