X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Fauth%2Fauth_util.c;h=c81432d277d67235a446d2ef78acfa8bb259e0de;hb=7f47cec2343ca7658460cc14fa613fdd2611677a;hp=71fec767584ee422885d43250c134a7b76c2162c;hpb=8ecee11790c68948a12bdc46f07a05586c8afaf6;p=vlendec%2Fsamba-autobuild%2F.git diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 71fec767584..c81432d277d 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -23,6 +23,7 @@ #include "includes.h" #include "auth.h" +#include "lib/util_unixsids.h" #include "../libcli/auth/libcli_auth.h" #include "../lib/crypto/arcfour.h" #include "rpc_client/init_lsa.h" @@ -33,6 +34,9 @@ #include "../librpc/gen_ndr/ndr_auth.h" #include "../auth/auth_sam_reply.h" #include "../librpc/gen_ndr/idmap.h" +#include "lib/param/loadparm.h" +#include "../lib/tsocket/tsocket.h" +#include "rpc_client/util_netlogon.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -47,7 +51,7 @@ static int _smb_create_user(const char *domain, const char *unix_username, const char *add_script; int ret; - add_script = talloc_strdup(ctx, lp_adduser_script()); + add_script = lp_add_user_script(ctx); if (!add_script || !*add_script) { return -1; } @@ -76,7 +80,7 @@ static int _smb_create_user(const char *domain, const char *unix_username, const return -1; } } - ret = smbrun(add_script,NULL); + ret = smbrun(add_script, NULL, NULL); flush_pwnam_cache(); DEBUG(ret ? 0 : 3, ("smb_create_user: Running the command `%s' gave %d\n", @@ -88,11 +92,14 @@ static int _smb_create_user(const char *domain, const char *unix_username, const Create an auth_usersupplied_data structure after appropriate mapping. ****************************************************************************/ -NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info, +NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx, + struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *workstation_name, const struct tsocket_address *remote_address, + const struct tsocket_address *local_address, + const char *service_description, const DATA_BLOB *lm_pwd, const DATA_BLOB *nt_pwd, const struct samr_Password *lm_interactive_pwd, @@ -113,37 +120,18 @@ NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info, DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n", client_domain, smb_name, workstation_name)); + /* + * We let the auth stack canonicalize, username + * and domain. + */ domain = client_domain; - /* If you connect to a Windows domain member using a bogus domain name, - * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if - * the Windows box is a DC the name will become DOMAIN\user and be - * authenticated against AD, if the Windows box is a member server but - * not a DC the name will become WORKSTATION\user. A standalone - * non-domain member box will also map to WORKSTATION\user. - * This also deals with the client passing in a "" domain */ - - if (!is_trusted_domain(domain) && - !strequal(domain, my_sam_name())) - { - if (lp_map_untrusted_to_domain()) - domain = my_sam_name(); - else - domain = get_global_sam_name(); - DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from " - "workstation [%s]\n", - client_domain, domain, smb_name, workstation_name)); - } - - /* We know that the given domain is trusted (and we are allowing them), - * it is our global SAM name, or for legacy behavior it is our - * primary domain name */ - - result = make_user_info(user_info, smb_name, internal_username, - client_domain, domain, workstation_name, - remote_address, lm_pwd, nt_pwd, - lm_interactive_pwd, nt_interactive_pwd, - plaintext, password_state); + result = make_user_info(mem_ctx, user_info, smb_name, internal_username, + client_domain, domain, workstation_name, + remote_address, local_address, + service_description, lm_pwd, nt_pwd, + lm_interactive_pwd, nt_interactive_pwd, + plaintext, password_state); if (NT_STATUS_IS_OK(result)) { /* We have tried mapping */ (*user_info)->mapped_state = true; @@ -158,12 +146,14 @@ NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info, Decrypt and encrypt the passwords. ****************************************************************************/ -bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info, +bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx, + struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *workstation_name, const struct tsocket_address *remote_address, - uint32 logon_parameters, + const struct tsocket_address *local_address, + uint32_t logon_parameters, const uchar *lm_network_pwd, int lm_pwd_len, const uchar *nt_network_pwd, @@ -174,10 +164,12 @@ bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info, DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); - status = make_user_info_map(user_info, + status = make_user_info_map(mem_ctx, user_info, smb_name, client_domain, workstation_name, remote_address, + local_address, + "SamLogon", lm_pwd_len ? &lm_blob : NULL, nt_pwd_len ? &nt_blob : NULL, NULL, NULL, NULL, @@ -198,24 +190,22 @@ bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info, Decrypt and encrypt the passwords. ****************************************************************************/ -bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info, +bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx, + struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *workstation_name, const struct tsocket_address *remote_address, - uint32 logon_parameters, + const struct tsocket_address *local_address, + uint32_t logon_parameters, const uchar chal[8], const uchar lm_interactive_pwd[16], - const uchar nt_interactive_pwd[16], - const uchar *dc_sess_key) + const uchar nt_interactive_pwd[16]) { struct samr_Password lm_pwd; struct samr_Password nt_pwd; unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; - unsigned char key[16]; - - memcpy(key, dc_sess_key, 16); if (lm_interactive_pwd) memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash)); @@ -223,31 +213,6 @@ bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_in if (nt_interactive_pwd) memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash)); -#ifdef DEBUG_PASSWORD - DEBUG(100,("key:")); - dump_data(100, key, sizeof(key)); - - DEBUG(100,("lm owf password:")); - dump_data(100, lm_pwd.hash, sizeof(lm_pwd.hash)); - - DEBUG(100,("nt owf password:")); - dump_data(100, nt_pwd.hash, sizeof(nt_pwd.hash)); -#endif - - if (lm_interactive_pwd) - arcfour_crypt(lm_pwd.hash, key, sizeof(lm_pwd.hash)); - - if (nt_interactive_pwd) - arcfour_crypt(nt_pwd.hash, key, sizeof(nt_pwd.hash)); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("decrypt of lm owf password:")); - dump_data(100, lm_pwd.hash, sizeof(lm_pwd)); - - DEBUG(100,("decrypt of nt owf password:")); - dump_data(100, nt_pwd.hash, sizeof(nt_pwd)); -#endif - if (lm_interactive_pwd) SMBOWFencrypt(lm_pwd.hash, chal, local_lm_response); @@ -256,14 +221,11 @@ bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_in SMBOWFencrypt(nt_pwd.hash, chal, local_nt_response); - /* Password info paranoia */ - ZERO_STRUCT(key); - { bool ret; NTSTATUS nt_status; - DATA_BLOB local_lm_blob; - DATA_BLOB local_nt_blob; + DATA_BLOB local_lm_blob = data_blob_null; + DATA_BLOB local_nt_blob = data_blob_null; if (lm_interactive_pwd) { local_lm_blob = data_blob(local_lm_response, @@ -276,9 +238,12 @@ bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_in } nt_status = make_user_info_map( + mem_ctx, user_info, smb_name, client_domain, workstation_name, remote_address, + local_address, + "SamLogon", lm_interactive_pwd ? &local_lm_blob : NULL, nt_interactive_pwd ? &local_nt_blob : NULL, lm_interactive_pwd ? &lm_pwd : NULL, @@ -301,11 +266,14 @@ bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_in Create an auth_usersupplied_data structure ****************************************************************************/ -bool make_user_info_for_reply(struct auth_usersupplied_info **user_info, +bool make_user_info_for_reply(TALLOC_CTX *mem_ctx, + struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const struct tsocket_address *remote_address, - const uint8 chal[8], + const struct tsocket_address *local_address, + const char *service_description, + const uint8_t chal[8], DATA_BLOB plaintext_password) { @@ -348,10 +316,12 @@ bool make_user_info_for_reply(struct auth_usersupplied_info **user_info, return false; } - ret = make_user_info( + ret = make_user_info(mem_ctx, user_info, smb_name, smb_name, client_domain, client_domain, get_remote_machine_name(), remote_address, + local_address, + service_description, local_lm_blob.data ? &local_lm_blob : NULL, local_nt_blob.data ? &local_nt_blob : NULL, NULL, NULL, @@ -371,16 +341,36 @@ bool make_user_info_for_reply(struct auth_usersupplied_info **user_info, Create an auth_usersupplied_data structure ****************************************************************************/ -NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info, +NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx, + struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const struct tsocket_address *remote_address, - DATA_BLOB lm_resp, DATA_BLOB nt_resp) + const struct tsocket_address *local_address, + const char *service_description, + DATA_BLOB lm_resp, DATA_BLOB nt_resp) { - return make_user_info(user_info, smb_name, smb_name, - client_domain, client_domain, + bool allow_raw = lp_raw_ntlmv2_auth(); + + if (!allow_raw && nt_resp.length >= 48) { + /* + * NTLMv2_RESPONSE has at least 48 bytes + * and should only be supported via NTLMSSP. + */ + DEBUG(2,("Rejecting raw NTLMv2 authentication with " + "user [%s\\%s] from[%s]\n", + client_domain, smb_name, + tsocket_address_string(remote_address, mem_ctx))); + return NT_STATUS_INVALID_PARAMETER; + } + + return make_user_info(mem_ctx, + user_info, smb_name, smb_name, + client_domain, client_domain, get_remote_machine_name(), remote_address, + local_address, + service_description, lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL, nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL, NULL, NULL, NULL, @@ -391,16 +381,22 @@ NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info, Create a guest user_info blob, for anonymous authentication. ****************************************************************************/ -bool make_user_info_guest(const struct tsocket_address *remote_address, +bool make_user_info_guest(TALLOC_CTX *mem_ctx, + const struct tsocket_address *remote_address, + const struct tsocket_address *local_address, + const char *service_description, struct auth_usersupplied_info **user_info) { NTSTATUS nt_status; - nt_status = make_user_info(user_info, + nt_status = make_user_info(mem_ctx, + user_info, "","", "","", "", remote_address, + local_address, + service_description, NULL, NULL, NULL, NULL, NULL, @@ -416,8 +412,8 @@ static NTSTATUS log_nt_token(struct security_token *token) char *group_sidstr; size_t i; - if ((lp_log_nt_token_command() == NULL) || - (strlen(lp_log_nt_token_command()) == 0)) { + if ((lp_log_nt_token_command(frame) == NULL) || + (strlen(lp_log_nt_token_command(frame)) == 0)) { TALLOC_FREE(frame); return NT_STATUS_OK; } @@ -430,7 +426,7 @@ static NTSTATUS log_nt_token(struct security_token *token) } command = talloc_string_sub( - frame, lp_log_nt_token_command(), + frame, lp_log_nt_token_command(frame), "%s", sid_string_talloc(frame, &token->sids[0])); command = talloc_string_sub(frame, command, "%t", group_sidstr); @@ -440,7 +436,7 @@ static NTSTATUS log_nt_token(struct security_token *token) } DEBUG(8, ("running command: [%s]\n", command)); - if (smbrun(command, NULL) != 0) { + if (smbrun(command, NULL, NULL) != 0) { DEBUG(0, ("Could not log NT token\n")); TALLOC_FREE(frame); return NT_STATUS_ACCESS_DENIED; @@ -531,9 +527,8 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, if (server_info->security_token) { /* Just copy the token, it has already been finalised - * (nasty hack to support a cached guest session_info, - * and a possible strategy for auth_samba4 to pass in - * a finalised session) */ + * (nasty hack to support a cached guest/system session_info + */ session_info->security_token = dup_nt_token(session_info, server_info->security_token); if (!session_info->security_token) { @@ -616,7 +611,8 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, sid_string_dbg(&t->sids[i]))); continue; } - if (!add_gid_to_array_unique(session_info, ids[i].id, + if (!add_gid_to_array_unique(session_info->unix_token, + ids[i].id, &session_info->unix_token->groups, &session_info->unix_token->ngroups)) { return NT_STATUS_NO_MEMORY; @@ -670,143 +666,71 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, to a struct samu ***************************************************************************/ -NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info, - char *unix_username, - struct passwd *pwd) +NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx, + const char *unix_username, + const struct passwd *pwd, + struct auth_serversupplied_info **server_info) { NTSTATUS status; - struct samu *sampass = NULL; - char *qualified_name = NULL; - TALLOC_CTX *mem_ctx = NULL; - struct dom_sid u_sid; - enum lsa_SidType type; + TALLOC_CTX *tmp_ctx = NULL; struct auth_serversupplied_info *result; - /* - * The SID returned in server_info->sam_account is based - * on our SAM sid even though for a pure UNIX account this should - * not be the case as it doesn't really exist in the SAM db. - * This causes lookups on "[in]valid users" to fail as they - * will lookup this name as a "Unix User" SID to check against - * the user token. Fix this by adding the "Unix User"\unix_username - * SID to the sid array. The correct fix should probably be - * changing the server_info->sam_account user SID to be a - * S-1-22 Unix SID, but this might break old configs where - * plaintext passwords were used with no SAM backend. - */ - - mem_ctx = talloc_init("make_server_info_pw_tmp"); - if (!mem_ctx) { - return NT_STATUS_NO_MEMORY; - } - - qualified_name = talloc_asprintf(mem_ctx, "%s\\%s", - unix_users_domain_name(), - unix_username ); - if (!qualified_name) { - TALLOC_FREE(mem_ctx); - return NT_STATUS_NO_MEMORY; - } - - if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL, - NULL, NULL, - &u_sid, &type)) { - TALLOC_FREE(mem_ctx); - return NT_STATUS_NO_SUCH_USER; - } - - TALLOC_FREE(mem_ctx); - - if (type != SID_NAME_USER) { - return NT_STATUS_NO_SUCH_USER; - } - - if ( !(sampass = samu_new( NULL )) ) { + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } - status = samu_set_unix( sampass, pwd ); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* In pathological cases the above call can set the account - * name to the DOMAIN\username form. Reset the account name - * using unix_username */ - pdb_set_username(sampass, unix_username, PDB_SET); - - /* set the user sid to be the calculated u_sid */ - pdb_set_user_sid(sampass, &u_sid, PDB_SET); - - result = make_server_info(NULL); + result = make_server_info(tmp_ctx); if (result == NULL) { - TALLOC_FREE(sampass); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto done; } - status = samu_to_SamInfo3(result, sampass, lp_netbios_name(), - &result->info3, &result->extra); - TALLOC_FREE(sampass); + status = passwd_to_SamInfo3(result, + unix_username, + pwd, + &result->info3, + &result->extra); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("Failed to convert samu to info3: %s\n", - nt_errstr(status))); - TALLOC_FREE(result); - return status; + goto done; } result->unix_name = talloc_strdup(result, unix_username); - if (result->unix_name == NULL) { - TALLOC_FREE(result); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto done; } result->utok.uid = pwd->pw_uid; result->utok.gid = pwd->pw_gid; - *server_info = result; + *server_info = talloc_steal(mem_ctx, result); + status = NT_STATUS_OK; +done: + talloc_free(tmp_ctx); - return NT_STATUS_OK; + return status; } static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx, - struct passwd *pwd, struct netr_SamInfo3 *info3) { NTSTATUS status; - struct dom_sid *system_sid; - const char *tmp; /* Set account name */ - tmp = talloc_strdup(mem_ctx, pwd->pw_name); - if (tmp == NULL) { - return NT_STATUS_NO_MEMORY; - } - init_lsa_String(&info3->base.account_name, tmp); + init_lsa_String(&info3->base.account_name, "SYSTEM"); /* Set domain name */ - tmp = talloc_strdup(mem_ctx, get_global_sam_name()); - if (tmp == NULL) { - return NT_STATUS_NO_MEMORY; - } - init_lsa_StringLarge(&info3->base.logon_domain, tmp); + init_lsa_StringLarge(&info3->base.logon_domain, "NT AUTHORITY"); - /* The SID set here will be overwirtten anyway, but try and make it SID_NT_SYSTEM anyway */ - /* Domain sid is NT_AUTHORITY */ - - system_sid = dom_sid_parse_talloc(mem_ctx, SID_NT_SYSTEM); - if (system_sid == NULL) { - return NT_STATUS_NO_MEMORY; - } - - status = dom_sid_split_rid(mem_ctx, system_sid, &info3->base.domain_sid, + status = dom_sid_split_rid(mem_ctx, &global_sid_System, + &info3->base.domain_sid, &info3->base.rid); - TALLOC_FREE(system_sid); if (!NT_STATUS_IS_OK(status)) { return status; } - + /* Primary gid is the same */ info3->base.primary_gid = info3->base.rid; @@ -816,7 +740,7 @@ static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx, static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx, struct netr_SamInfo3 *info3) { - const char *guest_account = lp_guestaccount(); + const char *guest_account = lp_guest_account(); struct dom_sid domain_sid; struct passwd *pwd; const char *tmp; @@ -854,7 +778,7 @@ static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx, info3->base.rid = DOMAIN_RID_GUEST; /* Primary gid */ - info3->base.primary_gid = BUILTIN_RID_GUESTS; + info3->base.primary_gid = DOMAIN_RID_GUESTS; /* Set as guest */ info3->base.user_flags = NETLOGON_GUEST; @@ -874,10 +798,13 @@ static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx, left as-is for now. ***************************************************************************/ -static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_info, struct auth_serversupplied_info **server_info) +static NTSTATUS make_new_session_info_guest(TALLOC_CTX *mem_ctx, + struct auth_session_info **_session_info, + struct auth_serversupplied_info **_server_info) { - static const char zeros[16] = {0}; - const char *guest_account = lp_guestaccount(); + struct auth_session_info *session_info = NULL; + struct auth_serversupplied_info *server_info = NULL; + const char *guest_account = lp_guest_account(); const char *domain = lp_netbios_name(); struct netr_SamInfo3 info3; TALLOC_CTX *tmp_ctx; @@ -900,7 +827,7 @@ static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_i status = make_server_info_info3(tmp_ctx, guest_account, domain, - server_info, + &server_info, &info3); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("make_server_info_info3 failed with %s\n", @@ -908,25 +835,26 @@ static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_i goto done; } - (*server_info)->guest = true; + server_info->guest = true; /* This should not be done here (we should produce a server * info, and later construct a session info from it), but for * now this does not change the previous behavior */ - status = create_local_token(tmp_ctx, *server_info, NULL, - (*server_info)->info3->base.account_name.string, - session_info); + status = create_local_token(tmp_ctx, server_info, NULL, + server_info->info3->base.account_name.string, + &session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("create_local_token failed: %s\n", nt_errstr(status))); goto done; } - talloc_steal(NULL, *session_info); - talloc_steal(NULL, *server_info); /* annoying, but the Guest really does have a session key, and it is all zeros! */ - (*session_info)->session_key = data_blob(zeros, sizeof(zeros)); + session_info->session_key = data_blob_talloc_zero(session_info, 16); + + *_session_info = talloc_move(mem_ctx, &session_info); + *_server_info = talloc_move(mem_ctx, &server_info); status = NT_STATUS_OK; done: @@ -942,12 +870,8 @@ done: static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx, struct auth_session_info **session_info) { - struct passwd *pwd; NTSTATUS status; - struct auth_serversupplied_info *server_info; - const char *domain = lp_netbios_name(); - struct netr_SamInfo3 info3; TALLOC_CTX *tmp_ctx; tmp_ctx = talloc_stackframe(); @@ -955,36 +879,59 @@ static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - pwd = getpwuid_alloc(tmp_ctx, sec_initial_uid()); - if (pwd == NULL) { - status = NT_STATUS_NO_SUCH_USER; + server_info = make_server_info(tmp_ctx); + if (!server_info) { + status = NT_STATUS_NO_MEMORY; + DEBUG(0, ("failed making server_info\n")); goto done; } - ZERO_STRUCT(info3); + server_info->info3 = talloc_zero(server_info, struct netr_SamInfo3); + if (!server_info->info3) { + status = NT_STATUS_NO_MEMORY; + DEBUG(0, ("talloc failed setting info3\n")); + goto done; + } - status = get_system_info3(tmp_ctx, pwd, &info3); + status = get_system_info3(server_info, server_info->info3); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed creating system info3 with %s\n", nt_errstr(status))); goto done; } - status = make_server_info_info3(tmp_ctx, - pwd->pw_name, - domain, - &server_info, - &info3); + server_info->utok.uid = sec_initial_uid(); + server_info->utok.gid = sec_initial_gid(); + server_info->unix_name = talloc_asprintf(server_info, + "NT AUTHORITY%cSYSTEM", + *lp_winbind_separator()); + + if (!server_info->unix_name) { + status = NT_STATUS_NO_MEMORY; + DEBUG(0, ("talloc_asprintf failed setting unix_name\n")); + goto done; + } + + server_info->security_token = talloc_zero(server_info, struct security_token); + if (!server_info->security_token) { + status = NT_STATUS_NO_MEMORY; + DEBUG(0, ("talloc failed setting security token\n")); + goto done; + } + + status = add_sid_to_array_unique(server_info->security_token->sids, + &global_sid_System, + &server_info->security_token->sids, + &server_info->security_token->num_sids); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("make_server_info_info3 failed with %s\n", - nt_errstr(status))); goto done; } - server_info->nss_token = true; + /* SYSTEM has all privilages */ + server_info->security_token->privilege_mask = ~0; /* Now turn the server_info into a session_info with the full token etc */ - status = create_local_token(mem_ctx, server_info, NULL, pwd->pw_name, session_info); + status = create_local_token(mem_ctx, server_info, NULL, "SYSTEM", session_info); talloc_free(server_info); if (!NT_STATUS_IS_OK(status)) { @@ -993,20 +940,6 @@ static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx, goto done; } - TALLOC_FREE((*session_info)->security_token->sids); - (*session_info)->security_token->num_sids = 0; - - status = add_sid_to_array_unique((*session_info)->security_token->sids, - &global_sid_System, - &(*session_info)->security_token->sids, - &(*session_info)->security_token->num_sids); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - /* SYSTEM has all privilages */ - (*session_info)->security_token->privilege_mask = ~0; - talloc_steal(mem_ctx, *session_info); done: @@ -1028,25 +961,36 @@ NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx, struct passwd *pwd; NTSTATUS status; struct auth_serversupplied_info *result; + TALLOC_CTX *tmp_ctx; - pwd = Get_Pwnam_alloc(talloc_tos(), username); - if (pwd == NULL) { - return NT_STATUS_NO_SUCH_USER; + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NT_STATUS_NO_MEMORY; } - status = make_server_info_pw(&result, pwd->pw_name, pwd); + pwd = Get_Pwnam_alloc(tmp_ctx, username); + if (pwd == NULL) { + status = NT_STATUS_NO_SUCH_USER; + goto done; + } + status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result); if (!NT_STATUS_IS_OK(status)) { - return status; + goto done; } result->nss_token = true; result->guest = is_guest; /* Now turn the server_info into a session_info with the full token etc */ - status = create_local_token(mem_ctx, result, NULL, pwd->pw_name, session_info); - TALLOC_FREE(result); - TALLOC_FREE(pwd); + status = create_local_token(mem_ctx, + result, + NULL, + pwd->pw_name, + session_info); + +done: + talloc_free(tmp_ctx); return status; } @@ -1069,6 +1013,7 @@ static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLO struct auth_serversupplied_info *server_info) { struct auth_serversupplied_info *dst; + NTSTATUS status; dst = make_server_info(mem_ctx); if (dst == NULL) { @@ -1116,8 +1061,10 @@ static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLO dst->lm_session_key = data_blob_talloc(dst, src->session_key.data, src->session_key.length); - dst->info3 = copy_netr_SamInfo3(dst, server_info->info3); - if (!dst->info3) { + status = copy_netr_SamInfo3(dst, + server_info->info3, + &dst->info3); + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(dst); return NULL; } @@ -1189,12 +1136,17 @@ static struct auth_session_info *guest_info = NULL; static struct auth_serversupplied_info *guest_server_info = NULL; -bool init_guest_info(void) +bool init_guest_session_info(TALLOC_CTX *mem_ctx) { + NTSTATUS status; + if (guest_info != NULL) return true; - return NT_STATUS_IS_OK(make_new_session_info_guest(&guest_info, &guest_server_info)); + status = make_new_session_info_guest(mem_ctx, + &guest_info, + &guest_server_info); + return NT_STATUS_IS_OK(status); } NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx, @@ -1257,7 +1209,9 @@ static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain, if (!lower_username) { return NT_STATUS_NO_MEMORY; } - strlower_m( lower_username ); + if (!strlower_m( lower_username )) { + return NT_STATUS_INVALID_PARAMETER; + } orig_dom_user = talloc_asprintf(mem_ctx, "%s%c%s", @@ -1334,7 +1288,8 @@ struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser, /* make sure we get the case of the username correct */ /* work around 'winbind use default domain = yes' */ - if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) { + if ( lp_winbind_use_default_domain() && + !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) { char *domain; /* split the domain and username into 2 strings */ @@ -1402,19 +1357,18 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, const char *sent_nt_username, const char *domain, struct auth_serversupplied_info **server_info, - struct netr_SamInfo3 *info3) + const struct netr_SamInfo3 *info3) { - static const char zeros[16] = {0, }; - NTSTATUS nt_status = NT_STATUS_OK; char *found_username = NULL; const char *nt_domain; const char *nt_username; + struct dom_sid user_sid; + struct dom_sid group_sid; bool username_was_mapped; struct passwd *pwd; struct auth_serversupplied_info *result; - struct dom_sid *group_sid; - struct netr_SamInfo3 *i3; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); /* Here is where we should check the list of @@ -1422,7 +1376,18 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, matches. */ - nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string); + if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) { + nt_status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + + if (!sid_compose(&group_sid, info3->base.domain_sid, + info3->base.primary_gid)) { + nt_status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + + nt_username = talloc_strdup(tmp_ctx, info3->base.account_name.string); if (!nt_username) { /* If the server didn't give us one, just use the one we sent * them */ @@ -1449,63 +1414,53 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, /* this call will try to create the user if necessary */ - nt_status = check_account(mem_ctx, nt_domain, sent_nt_username, - &found_username, &pwd, - &username_was_mapped); + nt_status = check_account(tmp_ctx, + nt_domain, + nt_username, + &found_username, + &pwd, + &username_was_mapped); if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; + /* Handle 'map to guest = Bad Uid */ + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) && + (lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) && + lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) { + DBG_NOTICE("Try to map %s to guest account", + nt_username); + nt_status = make_server_info_guest(tmp_ctx, &result); + if (NT_STATUS_IS_OK(nt_status)) { + *server_info = talloc_move(mem_ctx, &result); + } + } + goto out; } - result = make_server_info(NULL); + result = make_server_info(tmp_ctx); if (result == NULL) { DEBUG(4, ("make_server_info failed!\n")); - return NT_STATUS_NO_MEMORY; + nt_status = NT_STATUS_NO_MEMORY; + goto out; } result->unix_name = talloc_strdup(result, found_username); /* copy in the info3 */ - result->info3 = i3 = copy_netr_SamInfo3(result, info3); - if (result->info3 == NULL) { - TALLOC_FREE(result); - return NT_STATUS_NO_MEMORY; + nt_status = copy_netr_SamInfo3(result, + info3, + &result->info3); + if (!NT_STATUS_IS_OK(nt_status)) { + goto out; } /* Fill in the unix info we found on the way */ + result->utok.uid = pwd->pw_uid; result->utok.gid = pwd->pw_gid; - /* We can't just trust that the primary group sid sent us is something - * we can really use. Obtain the usable sid, and store the original - * one as an additional group if it had to be replaced */ - nt_status = get_primary_group_sid(mem_ctx, found_username, - &pwd, &group_sid); - if (!NT_STATUS_IS_OK(nt_status)) { - TALLOC_FREE(result); - return nt_status; - } - - /* store and check if it is the same we got originally */ - sid_peek_rid(group_sid, &i3->base.primary_gid); - if (i3->base.primary_gid != info3->base.primary_gid) { - uint32_t n = i3->base.groups.count; - /* not the same, store the original as an additional group */ - i3->base.groups.rids = - talloc_realloc(i3, i3->base.groups.rids, - struct samr_RidWithAttribute, n + 1); - if (i3->base.groups.rids == NULL) { - TALLOC_FREE(result); - return NT_STATUS_NO_MEMORY; - } - i3->base.groups.rids[n].rid = info3->base.primary_gid; - i3->base.groups.rids[n].attributes = SE_GROUP_ENABLED; - i3->base.groups.count = n + 1; - } - /* ensure we are never given NULL session keys */ - if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) { + if (all_zero(info3->base.key.key, sizeof(info3->base.key.key))) { result->session_key = data_blob_null; } else { result->session_key = data_blob_talloc( @@ -1513,7 +1468,8 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, sizeof(info3->base.key.key)); } - if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) { + if (all_zero(info3->base.LMSessKey.key, + sizeof(info3->base.LMSessKey.key))) { result->lm_session_key = data_blob_null; } else { result->lm_session_key = data_blob_talloc( @@ -1525,9 +1481,13 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, result->guest = (info3->base.user_flags & NETLOGON_GUEST); - *server_info = result; + *server_info = talloc_move(mem_ctx, &result); - return NT_STATUS_OK; + nt_status = NT_STATUS_OK; +out: + talloc_free(tmp_ctx); + + return nt_status; } /***************************************************************************** @@ -1540,21 +1500,28 @@ NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx, const struct wbcAuthUserInfo *info, struct auth_serversupplied_info **server_info) { - struct netr_SamInfo3 *info3; + struct netr_SamInfo3 info3; + struct netr_SamInfo6 *info6; - info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info); - if (!info3) { + info6 = wbcAuthUserInfo_to_netr_SamInfo6(mem_ctx, info); + if (!info6) { return NT_STATUS_NO_MEMORY; } + info3.base = info6->base; + info3.sidcount = info6->sidcount; + info3.sids = info6->sids; + return make_server_info_info3(mem_ctx, sent_nt_username, domain, - server_info, info3); + server_info, &info3); } /** * Verify whether or not given domain is trusted. * + * This should only be used on a DC. + * * @param domain_name name of the domain to be verified * @return true if domain is one of the trusted ones or * false if otherwise @@ -1562,13 +1529,11 @@ NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx, bool is_trusted_domain(const char* dom_name) { - struct dom_sid trustdom_sid; bool ret; - /* no trusted domains for a standalone server */ - - if ( lp_server_role() == ROLE_STANDALONE ) + if (!IS_DC) { return false; + } if (dom_name == NULL || dom_name[0] == '\0') { return false; @@ -1578,49 +1543,13 @@ bool is_trusted_domain(const char* dom_name) return false; } - /* if we are a DC, then check for a direct trust relationships */ - - if ( IS_DC ) { - become_root(); - DEBUG (5,("is_trusted_domain: Checking for domain trust with " - "[%s]\n", dom_name )); - ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL); - unbecome_root(); - if (ret) - return true; - } - else { - wbcErr result; - - /* If winbind is around, ask it */ - - result = wb_is_trusted_domain(dom_name); - - if (result == WBC_ERR_SUCCESS) { - return true; - } + become_root(); + DEBUG (5,("is_trusted_domain: Checking for domain trust with " + "[%s]\n", dom_name )); + ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL); + unbecome_root(); - if (result == WBC_ERR_DOMAIN_NOT_FOUND) { - /* winbind could not find the domain */ - return false; - } - - /* The only other possible result is that winbind is not up - and running. We need to update the trustdom_cache - ourselves */ - - update_trustdom_cache(); - } - - /* now the trustdom cache should be available a DC could still - * have a transitive trust so fall back to the cache of trusted - * domains (like a domain member would use */ - - if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) { - return true; - } - - return false; + return ret; } @@ -1629,9 +1558,11 @@ bool is_trusted_domain(const char* dom_name) on a logon error possibly map the error to success if "map to guest" is set approriately */ -NTSTATUS do_map_to_guest_server_info(NTSTATUS status, - struct auth_serversupplied_info **server_info, - const char *user, const char *domain) +NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx, + NTSTATUS status, + const char *user, + const char *domain, + struct auth_serversupplied_info **server_info) { user = user ? user : ""; domain = domain ? domain : ""; @@ -1641,13 +1572,13 @@ NTSTATUS do_map_to_guest_server_info(NTSTATUS status, (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { DEBUG(3,("No such user %s [%s] - using guest account\n", user, domain)); - return make_server_info_guest(NULL, server_info); + return make_server_info_guest(mem_ctx, server_info); } } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) { if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { DEBUG(3,("Registered username %s for guest access\n", user)); - return make_server_info_guest(NULL, server_info); + return make_server_info_guest(mem_ctx, server_info); } }