From 60f0627afb167faad57385d44f0b587186a7ac2b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 31 Oct 2001 10:46:25 +0000 Subject: This is a farily large patch (3300 lines) and reworks most of the AuthRewrite code. In particular this assists tpot in some of his work, becouse it provides the connection between the authenticaion and the vuid generation. Major Changes: - Fully malloc'ed structures. - Massive rework of the code so that all structures are made and destroyed using malloc and free, rather than hanging around on the stack. - SAM_ACCOUNT unix uids and gids are now pointers to the same, to allow them to be declared 'invalid' without the chance that people might get ROOT by default. - kill off some of the "DOMAIN\user" lookups. These can be readded at a more appropriate place (probably domain_client_validate.c) in the future. They don't belong in session setups. - Massive introduction of DATA_BLOB structures, particularly for passwords. - Use NTLMSSP flags to tell the backend what its getting, rather than magic lenghths. - Fix winbind back up again, but tpot is redoing this soon anyway. - Abstract much of the work in srv_netlog_nt back into auth helper functions. This is a LARGE change, and any assistance is testing it is appriciated. Domain logons are still broken (as far as I can tell) but other functionality seems intact. Needs testing with a wide variety of MS clients. Andrew Bartlett (This used to be commit f70fb819b2f57bd57232b51808345e2319d52f6c) --- source3/rpc_server/srv_netlog_nt.c | 197 ++++++++++--------------------------- source3/rpc_server/srv_pipe.c | 76 +++++++------- source3/rpc_server/srv_srvsvc_nt.c | 12 +-- 3 files changed, 94 insertions(+), 191 deletions(-) (limited to 'source3/rpc_server') diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 0f2b672d38..26054117fb 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -484,123 +484,6 @@ NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOF return r_u->status; } -/************************************************************************* - _net_logon_any: Use the new authentications subsystem to log in. - *************************************************************************/ - -static NTSTATUS _net_logon_any(NET_ID_INFO_CTR *ctr, char *user, char *domain, char *workstation, char *sess_key) -{ - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - - auth_usersupplied_info user_info; - auth_serversupplied_info server_info; - AUTH_STR ourdomain, theirdomain, smb_username, wksta_name; - - DEBUG(5, ("_net_logon_any: entered with user %s and domain %s\n", user, domain)); - - ZERO_STRUCT(user_info); - ZERO_STRUCT(server_info); - ZERO_STRUCT(ourdomain); - ZERO_STRUCT(theirdomain); - ZERO_STRUCT(smb_username); - ZERO_STRUCT(wksta_name); - - ourdomain.str = lp_workgroup(); - ourdomain.len = strlen(ourdomain.str); - - theirdomain.str = domain; - theirdomain.len = strlen(theirdomain.str); - - user_info.requested_domain = theirdomain; - user_info.domain = ourdomain; - - smb_username.str = user; - smb_username.len = strlen(smb_username.str); - - user_info.unix_username = smb_username; /* For the time-being */ - user_info.smb_username = smb_username; - - user_info.wksta_name.str = workstation; - user_info.wksta_name.len = strlen(workstation); - - user_info.wksta_name = wksta_name; - - DEBUG(10,("_net_logon_any: Attempting validation level %d.\n", ctr->switch_value)); - switch (ctr->switch_value) { - case NET_LOGON_TYPE: - /* Standard challange/response authenticaion */ - - user_info.lm_resp.buffer = (uint8 *)ctr->auth.id2.lm_chal_resp.buffer; - user_info.lm_resp.len = ctr->auth.id2.lm_chal_resp.str_str_len; - user_info.nt_resp.buffer = (uint8 *)ctr->auth.id2.nt_chal_resp.buffer; - user_info.nt_resp.len = ctr->auth.id2.nt_chal_resp.str_str_len; - memcpy(user_info.chal, ctr->auth.id2.lm_chal, 8); - break; - case INTERACTIVE_LOGON_TYPE: - /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted - with the session key. We will convert this to challange/responce for the - auth subsystem to chew on */ - { - char nt_pwd[16]; - char lm_pwd[16]; - unsigned char key[16]; - - memset(key, 0, 16); - memcpy(key, sess_key, 8); - - memcpy(lm_pwd, ctr->auth.id1.lm_owf.data, 16); - memcpy(nt_pwd, ctr->auth.id1.nt_owf.data, 16); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("key:")); - dump_data(100, (char *)key, 16); - - DEBUG(100,("lm owf password:")); - dump_data(100, lm_pwd, 16); - - DEBUG(100,("nt owf password:")); - dump_data(100, nt_pwd, 16); -#endif - - SamOEMhash((uchar *)lm_pwd, key, 16); - SamOEMhash((uchar *)nt_pwd, key, 16); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("decrypt of lm owf password:")); - dump_data(100, lm_pwd, 16); - - DEBUG(100,("decrypt of nt owf password:")); - dump_data(100, nt_pwd, 16); -#endif - - generate_random_buffer(user_info.chal, 8, False); - SMBOWFencrypt((const unsigned char *)lm_pwd, user_info.chal, local_lm_response); - SMBOWFencrypt((const unsigned char *)nt_pwd, user_info.chal, local_nt_response); - user_info.lm_resp.buffer = (uint8 *)local_lm_response; - user_info.lm_resp.len = 24; - user_info.nt_resp.buffer = (uint8 *)local_nt_response; - user_info.nt_resp.len = 24; - break; - } - default: - DEBUG(2,("SAM Logon: unsupported switch value\n")); - return NT_STATUS_INVALID_INFO_CLASS; - } /* end switch */ - - nt_status = check_password(&user_info, &server_info); - - DEBUG(5, ("_net_logon_any: exited with status %s\n", - get_nt_error_msg(nt_status))); - - free_serversupplied_info(&server_info); /* No info needed */ - - return nt_status; -} - - /************************************************************************* _net_sam_logon @@ -610,15 +493,16 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * { NTSTATUS status = NT_STATUS_OK; NET_USER_INFO_3 *usr_info = NULL; + NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr; DOM_CRED srv_cred; SAM_ACCOUNT *sampass = NULL; UNISTR2 *uni_samlogon_user = NULL; UNISTR2 *uni_samlogon_domain = NULL; UNISTR2 *uni_samlogon_workstation = NULL; fstring nt_username, nt_domain, nt_workstation; - - BOOL ret; - + auth_usersupplied_info *user_info; + auth_serversupplied_info *server_info; + usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3)); if (!usr_info) return NT_STATUS_NO_MEMORY; @@ -647,16 +531,17 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * switch (q_u->sam_id.logon_level) { case INTERACTIVE_LOGON_TYPE: - uni_samlogon_user = &q_u->sam_id.ctr->auth.id1.uni_user_name; - uni_samlogon_domain = &q_u->sam_id.ctr->auth.id1.uni_domain_name; - uni_samlogon_workstation = &q_u->sam_id.ctr->auth.id1.uni_wksta_name; + uni_samlogon_user = &ctr->auth.id1.uni_user_name; + uni_samlogon_domain = &ctr->auth.id1.uni_domain_name; + + uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name; DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup())); break; case NET_LOGON_TYPE: - uni_samlogon_user = &q_u->sam_id.ctr->auth.id2.uni_user_name; - uni_samlogon_domain = &q_u->sam_id.ctr->auth.id2.uni_domain_name; - uni_samlogon_workstation = &q_u->sam_id.ctr->auth.id2.uni_wksta_name; + uni_samlogon_user = &ctr->auth.id2.uni_user_name; + uni_samlogon_domain = &ctr->auth.id2.uni_domain_name; + uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name; DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup())); break; @@ -678,29 +563,51 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * * Convert to a UNIX username. */ - map_username(nt_username); + DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username)); - DEBUG(10,("Attempting validation level %d for mapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username)); + switch (ctr->switch_value) { + case NET_LOGON_TYPE: + /* Standard challange/response authenticaion */ + make_user_info_netlogon_network(&user_info, + nt_username, nt_domain, + nt_workstation, ctr->auth.id2.lm_chal, + ctr->auth.id2.lm_chal_resp.buffer, + ctr->auth.id2.lm_chal_resp.str_str_len, + ctr->auth.id2.nt_chal_resp.buffer, + ctr->auth.id2.nt_chal_resp.str_str_len); + break; + case INTERACTIVE_LOGON_TYPE: + /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted + with the session key. We will convert this to challange/responce for the + auth subsystem to chew on */ + { + make_user_info_netlogon_interactive(&user_info, + nt_username, nt_domain, + nt_workstation, + ctr->auth.id1.lm_owf.data, 16, + ctr->auth.id1.lm_owf.data, 16, + p->dc.sess_key); + break; + } + default: + DEBUG(2,("SAM Logon: unsupported switch value\n")); + return NT_STATUS_INVALID_INFO_CLASS; + } /* end switch */ + + status = check_password(user_info, &server_info); - status = _net_logon_any(q_u->sam_id.ctr, nt_username, nt_domain, nt_workstation, (char *)p->dc.sess_key); + free_user_info(&user_info); + + DEBUG(5, ("_net_sam_logon: exiting with status %s\n", + get_nt_error_msg(status))); /* Check account and password */ - if (NT_STATUS_IS_ERR(status)) + if (NT_STATUS_IS_ERR(status)) { + free_server_info(&server_info); return status; - - pdb_init_sam(&sampass); - - /* get the account information */ - become_root(); - ret = pdb_getsampwnam(sampass, nt_username); - unbecome_root(); - - if (ret == False) { - pdb_free_sam(&sampass); - return NT_STATUS_NO_SUCH_USER; } - + /* This is the point at which, if the login was successful, that the SAM Local Security Authority should record that the user is logged in to the domain. */ @@ -748,12 +655,14 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * num_gids, /* uint32 num_groups */ gids , /* DOM_GID *gids */ 0x20 , /* uint32 user_flgs (?) */ - NULL, /* char sess_key[16] */ + NULL, /* uchar sess_key[16] */ my_name , /* char *logon_srv */ my_workgroup, /* char *logon_dom */ &global_sam_sid, /* DOM_SID *dom_sid */ NULL); /* char *other_sids */ } - pdb_free_sam(&sampass); + free_server_info(&server_info); return status; } + + diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 6f3c050519..21de4d3d2b 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -269,10 +269,16 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm fstring domain; fstring wks; BOOL guest_user = False; - SAM_ACCOUNT *sampass = NULL; uchar null_smb_passwd[16]; + const uchar *smb_passwd_ptr = NULL; + auth_usersupplied_info *user_info; + auth_serversupplied_info *server_info; + + uid_t *puid; + uid_t *pgid; + DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n")); memset(p->user_name, '\0', sizeof(p->user_name)); @@ -336,14 +342,6 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm } else { - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - fstrcpy(pipe_user_name, user_name); - (void)map_username(pipe_user_name); - /* * Do the length checking only if user is not NULL. */ @@ -362,41 +360,28 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm } if(!guest_user) { + NTSTATUS nt_status; - become_root(); - - p->ntlmssp_auth_validated = - NT_STATUS_IS_OK(pass_check_smb_with_chal(pipe_user_name, NULL, - domain, wks, - (uchar*)p->challenge, - lm_owf, lm_pw_len, - nt_owf, nt_pw_len)); - if (!p->ntlmssp_auth_validated) { - DEBUG(1,("api_pipe_ntlmssp_verify: User %s\\%s from machine %s \ -failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name )); - unbecome_root(); + if (!make_user_info_netlogon_network(&user_info, + user_name, domain, wks, (uchar*)p->challenge, + lm_owf, lm_pw_len, + nt_owf, nt_pw_len)) { + DEBUG(0,("make_user_info_netlogon_network failed! Failing authenticaion.\n")); return False; } - pdb_init_sam(&sampass); - - if(!pdb_getsampwnam(sampass, pipe_user_name)) { - DEBUG(1,("api_pipe_ntlmssp_verify: Cannot find user %s in smb passwd database.\n", - pipe_user_name)); - pdb_free_sam(&sampass); - unbecome_root(); - return False; - } + nt_status = check_password(user_info, &server_info); + + free_user_info(&user_info); - unbecome_root(); + p->ntlmssp_auth_validated = NT_STATUS_IS_OK(nt_status); - if(!pdb_get_nt_passwd(sampass)) { - DEBUG(1,("Account for user '%s' has no NT password hash.\n", pipe_user_name)); - pdb_free_sam(&sampass); + if (!p->ntlmssp_auth_validated) { + DEBUG(1,("api_pipe_ntlmssp_verify: User %s\\%s from machine %s \ +failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name )); + free_server_info(&server_info); return False; - } - - smb_passwd_ptr = pdb_get_lanman_passwd(sampass); + } } /* @@ -405,7 +390,7 @@ failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name { uchar p24[24]; - NTLMSSPOWFencrypt(smb_passwd_ptr, lm_owf, p24); + NTLMSSPOWFencrypt(server_info->first_8_lm_hash, lm_owf, p24); { unsigned char j = 0; int ind; @@ -447,8 +432,17 @@ failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name * Store the UNIX credential data (uid/gid pair) in the pipe structure. */ - p->pipe_user.uid = pdb_get_uid(sampass); - p->pipe_user.gid = pdb_get_gid(sampass); + puid = pdb_get_uid(server_info->sam_account); + pgid = pdb_get_gid(server_info->sam_account); + + if (!puid || !pgid) { + DEBUG(0,("Attempted authenticated pipe with invalid user. No uid/gid in SAM_ACCOUNT\n")); + free_server_info(&server_info); + return False; + } + + p->pipe_user.uid = *puid; + p->pipe_user.gid = *pgid; /* Set up pipe user group membership. */ initialise_groups(pipe_user_name, p->pipe_user.uid, p->pipe_user.gid); @@ -461,7 +455,7 @@ failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name p->ntlmssp_auth_validated = True; - pdb_free_sam(&sampass); + pdb_free_sam(&server_info->sam_account); return True; } diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 44e44cfa3a..7369c9d37d 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -1574,7 +1574,7 @@ NTSTATUS _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDE { SEC_DESC *psd = NULL; size_t sd_size; - fstring null_pw; + DATA_BLOB null_pw; pstring filename; pstring qualname; files_struct *fsp = NULL; @@ -1594,12 +1594,12 @@ NTSTATUS _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDE unistr2_to_ascii(qualname, &q_u->uni_qual_name, sizeof(qualname)); /* Null password is ok - we are already an authenticated user... */ - *null_pw = '\0'; + null_pw = data_blob(NULL, 0); get_current_user(&user, p); become_root(); - conn = make_connection(qualname, null_pw, 0, "A:", user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1678,7 +1678,7 @@ NTSTATUS _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC * SRV_R_NET_FILE_SET_SECDESC *r_u) { BOOL ret; - fstring null_pw; + DATA_BLOB null_pw; pstring filename; pstring qualname; files_struct *fsp = NULL; @@ -1698,12 +1698,12 @@ NTSTATUS _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC * unistr2_to_ascii(qualname, &q_u->uni_qual_name, sizeof(qualname)); /* Null password is ok - we are already an authenticated user... */ - *null_pw = '\0'; + null_pw = data_blob(NULL, 0); get_current_user(&user, p); become_root(); - conn = make_connection(qualname, null_pw, 0, "A:", user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { -- cgit