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 +++++-- source3/include/auth.h | 2 + source3/rpc_parse/parse_net.c | 19 +-------- source3/rpc_server/srv_netlog_nt.c | 2 - source3/rpc_server/srv_pipe.c | 2 +- 11 files changed, 97 insertions(+), 64 deletions(-) (limited to 'source3') 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; diff --git a/source3/include/auth.h b/source3/include/auth.h index eb80e3c5b4..6b42418be8 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -96,6 +96,8 @@ typedef struct auth_serversupplied_info SAM_ACCOUNT *sam_account; void *pam_handle; + + char *unix_name; } auth_serversupplied_info; diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c index 43bd8cd20e..f977549a07 100644 --- a/source3/rpc_parse/parse_net.c +++ b/source3/rpc_parse/parse_net.c @@ -1283,7 +1283,6 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, /* need to count the number of space-delimited sids */ unsigned int i; int num_other_sids = 0; - char *username; NTTIME logon_time, logoff_time, kickoff_time, pass_last_set_time, pass_can_change_time, @@ -1295,21 +1294,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, int len_logon_srv = strlen(logon_srv); int len_logon_dom = strlen(logon_dom); - - /* do some cleanup on the user name here to deal with users from a - trusted domain logging onto a client in our domain. If we are running - winbindd, the trusted users will be of the form DOMAIN\user so strip - out the domain portion. I noticed then when looking at an SMBsessionsetup&X. - The client was sending GLASS\Administrator as the username and GLASS as the - domain name -- jerry */ - - if ( (username = strchr( user_name, *lp_winbind_separator() )) != NULL ) - username++; - else - username = user_name; - - - len_user_name = strlen(username ); + len_user_name = strlen(user_name ); len_full_name = strlen(full_name ); len_home_dir = strlen(home_dir ); len_dir_drive = strlen(dir_drive ); @@ -1372,7 +1357,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, usr->num_other_sids = num_other_sids; usr->buffer_other_sids = (num_other_sids != 0) ? 1 : 0; - init_unistr2(&usr->uni_user_name, username, len_user_name); + init_unistr2(&usr->uni_user_name, user_name, len_user_name); init_unistr2(&usr->uni_full_name, full_name, len_full_name); init_unistr2(&usr->uni_logon_script, logon_script, len_logon_script); init_unistr2(&usr->uni_profile_path, profile_path, len_profile_path); diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 0dcdf39158..c4a87d2e26 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -650,10 +650,8 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * } /* end switch */ if ( NT_STATUS_IS_OK(status) ) { - become_root(); status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); - unbecome_root(); } (auth_context->free)(&auth_context); diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 6a9e591f64..f7663204b2 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -464,7 +464,7 @@ failed authentication on named pipe %s.\n", domain, user_name, wks, p->name )); } fstrcpy(p->user_name, user_name); - fstrcpy(p->pipe_user_name, pdb_get_username(server_info->sam_account)); + fstrcpy(p->pipe_user_name, server_info->unix_name); fstrcpy(p->domain, domain); fstrcpy(p->wks, wks); -- cgit