1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

This patch (donated by Marc Jacobsen of HP) should make Sun and HP very happy :-).

Probably Veritas too... :-).
It allows Samba as a domain member to authenticate against an AS/U server such
as the older HP PDC product or PD Netlink. It does this by trying a netlogon
with info level 3 and then falling back to info level 2 if the PDC returns
invalid info level.
Jeremy.
(This used to be commit bda1d6d4a4)
This commit is contained in:
Jeremy Allison 2001-02-24 00:42:41 +00:00
parent a1425244fa
commit 3699948e97
3 changed files with 176 additions and 77 deletions

View File

@ -39,32 +39,63 @@
#define SEC_CHAN_DOMAIN 4
#if 0
/* JRATEST.... */
/* I think this is correct - it's what gets parsed on the wire. JRA. */
/* NET_USER_INFO_2 */
typedef struct net_user_info_2
{
uint32 ptr_user_info;
uint32 ptr_user_info;
NTTIME logon_time; /* logon time */
NTTIME logoff_time; /* logoff time */
NTTIME kickoff_time; /* kickoff time */
NTTIME pass_last_set_time; /* password last set time */
NTTIME pass_can_change_time; /* password can change time */
NTTIME pass_must_change_time; /* password must change time */
NTTIME logon_time; /* logon time */
NTTIME logoff_time; /* logoff time */
NTTIME kickoff_time; /* kickoff time */
NTTIME pass_last_set_time; /* password last set time */
NTTIME pass_can_change_time; /* password can change time */
NTTIME pass_must_change_time; /* password must change time */
UNIHDR hdr_user_name; /* username unicode string header */
UNIHDR hdr_full_name; /* user's full name unicode string header */
UNIHDR hdr_logon_script; /* logon script unicode string header */
UNIHDR hdr_profile_path; /* profile path unicode string header */
UNIHDR hdr_home_dir; /* home directory unicode string header */
UNIHDR hdr_dir_drive; /* home directory drive unicode string header */
uint16 logon_count; /* logon count */
uint16 bad_pw_count; /* bad password count */
....
uint32 user_id; /* User ID */
uint32 group_id; /* Group ID */
....
uint32 num_groups; /* num groups */
uint32 buffer_groups; /* undocumented buffer pointer to groups. */
uint32 user_flgs; /* user flags */
uint8 user_sess_key[16]; /* unused user session key */
UNIHDR hdr_logon_srv; /* logon server unicode string header */
UNIHDR hdr_logon_dom; /* logon domain unicode string header */
uint32 buffer_dom_id; /* undocumented logon domain id pointer */
uint8 padding[40]; /* unused padding bytes. expansion room */
UNISTR2 uni_user_name; /* username unicode string */
UNISTR2 uni_full_name; /* user's full name unicode string */
UNISTR2 uni_logon_script; /* logon script unicode string */
UNISTR2 uni_profile_path; /* profile path unicode string */
UNISTR2 uni_home_dir; /* home directory unicode string */
UNISTR2 uni_dir_drive; /* home directory drive unicode string */
uint32 num_groups2; /* num groups */
DOM_GID *gids; /* group info */
UNIHDR hdr_logon_srv; /* logon server unicode string header */
UNISTR2 uni_logon_srv; /* logon server unicode string */
UNISTR2 uni_logon_dom; /* logon domain unicode string */
DOM_SID2 dom_sid;
DOM_SID2 dom_sid; /* domain SID */
uint32 num_other_groups; /* other groups */
DOM_GID *other_gids; /* group info */
DOM_SID2 *other_sids; /* undocumented - domain SIDs */
} NET_USER_INFO_2;
/* ! JRATEST.... */
#endif
/* NET_USER_INFO_3 */

View File

@ -337,90 +337,144 @@ password ?).\n", cli->desthost ));
}
/***************************************************************************
LSA SAM Logon - interactive or network.
LSA SAM Logon internal - interactive or network. Does level 2 or 3 but always
returns level 3.
****************************************************************************/
BOOL cli_net_sam_logon(struct cli_state *cli, NET_ID_INFO_CTR *ctr,
NET_USER_INFO_3 *user_info3)
static uint32 cli_net_sam_logon_internal(struct cli_state *cli, NET_ID_INFO_CTR *ctr,
NET_USER_INFO_3 *user_info3, uint16 validation_level)
{
DOM_CRED new_clnt_cred;
DOM_CRED dummy_rtn_creds;
prs_struct rbuf;
prs_struct buf;
uint16 validation_level = 3;
NET_Q_SAM_LOGON q_s;
BOOL ok = False;
DOM_CRED new_clnt_cred;
DOM_CRED dummy_rtn_creds;
prs_struct rbuf;
prs_struct buf;
NET_Q_SAM_LOGON q_s;
NET_R_SAM_LOGON r_s;
uint32 retval;
gen_next_creds( cli, &new_clnt_cred);
gen_next_creds( cli, &new_clnt_cred);
prs_init(&buf , 1024, 4, cli->mem_ctx, False);
prs_init(&rbuf, 0, 4, cli->mem_ctx, True );
prs_init(&buf , 1024, 4, cli->mem_ctx, False);
prs_init(&rbuf, 0, 4, cli->mem_ctx, True );
/* create and send a MSRPC command with api NET_SAMLOGON */
/* create and send a MSRPC command with api NET_SAMLOGON */
DEBUG(4,("cli_net_sam_logon: srv:%s mc:%s clnt %s %x ll: %d\n",
DEBUG(4,("cli_net_sam_logon_internal: srv:%s mc:%s clnt %s %x ll: %d\n",
cli->srv_name_slash, global_myname,
credstr(new_clnt_cred.challenge.data), cli->clnt_cred.timestamp.time,
ctr->switch_value));
memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds));
memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds));
dummy_rtn_creds.timestamp.time = time(NULL);
/* store the parameters */
q_s.validation_level = validation_level;
init_sam_info(&q_s.sam_id, unix_to_dos(cli->srv_name_slash,False),
/* store the parameters */
q_s.validation_level = validation_level;
init_sam_info(&q_s.sam_id, unix_to_dos(cli->srv_name_slash,False),
global_myname, &new_clnt_cred, &dummy_rtn_creds,
ctr->switch_value, ctr);
/* turn parameters into data stream */
if(!net_io_q_sam_logon("", &q_s, &buf, 0)) {
DEBUG(0,("cli_net_sam_logon: Error : failed to marshall NET_Q_SAM_LOGON struct.\n"));
prs_mem_free(&buf);
prs_mem_free(&rbuf);
return False;
}
/* turn parameters into data stream */
if(!net_io_q_sam_logon("", &q_s, &buf, 0)) {
DEBUG(0,("cli_net_sam_logon_internal: Error : failed to marshall NET_Q_SAM_LOGON struct.\n"));
retval = NT_STATUS_NO_MEMORY;
goto out;
}
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, NET_SAMLOGON, &buf, &rbuf))
{
NET_R_SAM_LOGON r_s;
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, NET_SAMLOGON, &buf, &rbuf)) {
DEBUG(0,("cli_net_sam_logon_internal: Erro rpc_api_pipe_req failed.\n"));
retval = cli->nt_error;
goto out;
}
r_s.user = user_info3;
r_s.user = user_info3;
ok = net_io_r_sam_logon("", &r_s, &rbuf, 0);
if(!net_io_r_sam_logon("", &r_s, &rbuf, 0)) {
DEBUG(0,("cli_net_sam_logon_internal: Error : failed to unmarshal NET_R_SAM_LOGON struct.\n"));
retval = NT_STATUS_NO_MEMORY;
goto out;
}
if (ok && r_s.status != 0)
{
/* report error code */
DEBUG(0,("cli_net_sam_logon: %s\n", get_nt_error_msg(r_s.status)));
cli->nt_error = r_s.status;
ok = False;
retval = r_s.status;
/*
* Don't treat NT_STATUS_INVALID_INFO_CLASS as an error - we will re-issue
* the call.
*/
if (retval == NT_STATUS_INVALID_INFO_CLASS) {
goto out;
}
if (retval != 0) {
/* report error code */
DEBUG(0,("cli_net_sam_logon_internal: %s\n", get_nt_error_msg(r_s.status)));
cli->nt_error = r_s.status;
goto out;
}
/* Update the credentials. */
if (ok && !clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_creds)))
{
/*
* Server replied with bad credential. Fail.
*/
DEBUG(0,("cli_net_sam_logon: server %s replied with bad credential (bad machine \
if (!clnt_deal_with_creds(cli->sess_key, &cli->clnt_cred, &r_s.srv_creds)) {
/*
* Server replied with bad credential. Fail.
*/
DEBUG(0,("cli_net_sam_logon_internal: server %s replied with bad credential (bad machine \
password ?).\n", cli->desthost ));
ok = False;
retval = NT_STATUS_WRONG_PASSWORD;
}
if (ok && r_s.switch_value != 3)
{
/* report different switch_value */
DEBUG(0,("cli_net_sam_logon: switch_value of 3 expected %x\n",
r_s.switch_value));
ok = False;
if (r_s.switch_value != validation_level) {
/* report different switch_value */
DEBUG(0,("cli_net_sam_logon: switch_value of %u expected %x\n", r_s.switch_value));
retval = NT_STATUS_INVALID_PARAMETER;
}
}
prs_mem_free(&buf);
prs_mem_free(&rbuf);
out:
return ok;
prs_mem_free(&buf);
prs_mem_free(&rbuf);
return retval;
}
/***************************************************************************
LSA SAM Logon - interactive or network.
****************************************************************************/
BOOL cli_net_sam_logon(struct cli_state *cli, NET_ID_INFO_CTR *ctr, NET_USER_INFO_3 *user_info3)
{
BOOL ok = True;
#if 0 /* JRATEST */
uint16 validation_level=2;
#else
uint16 validation_level=3;
#endif
uint32 ret_err_code;
ret_err_code = cli_net_sam_logon_internal(cli, ctr, user_info3, validation_level);
if(ret_err_code == NT_STATUS_NOPROBLEMO) {
DEBUG(10,("cli_net_sam_logon: Success \n"));
ok = True;
} else if (ret_err_code == NT_STATUS_INVALID_INFO_CLASS) {
DEBUG(10,("cli_net_sam_logon: STATUS INVALID INFO CLASS \n"));
validation_level=2;
/*
* Since this is the second time we call this function, don't care
* for the error. If its error, return False.
*/
if(cli_net_sam_logon_internal(cli, ctr, user_info3, validation_level) != 0)
ok = False;
} else {
DEBUG(10,("cli_net_sam_logon: Error\n"));
ok = False;
}
return ok;
}
/***************************************************************************

View File

@ -1130,10 +1130,14 @@ void free_user_info3(NET_USER_INFO_3 *usr)
}
/*******************************************************************
Reads or writes a structure.
This code has been modified to cope with a NET_USER_INFO_2 - which is
exactly the same as a NET_USER_INFO_3, minus the other sids parameters.
We use validation level to determine if we're marshalling a info 2 or
INFO_3 - be we always return an INFO_3. Based on code donated by Marc
Jacobsen at HP. JRA.
********************************************************************/
static BOOL net_io_user_info3(char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, int depth)
static BOOL net_io_user_info3(char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, int depth, uint16 validation_level)
{
int i;
@ -1143,6 +1147,9 @@ static BOOL net_io_user_info3(char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
prs_debug(ps, depth, desc, "lsa_io_lsa_user_info");
depth++;
if (UNMARSHALLING(ps))
ZERO_STRUCTP(usr);
if(!prs_align(ps))
return False;
@ -1207,10 +1214,17 @@ static BOOL net_io_user_info3(char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
if(!prs_uint8s (False, "padding ", ps, depth, usr->padding, 40)) /* unused padding bytes? */
return False;
if(!prs_uint32("num_other_sids", ps, depth, &usr->num_other_sids)) /* 0 - num_sids */
return False;
if(!prs_uint32("buffer_other_sids", ps, depth, &usr->buffer_other_sids)) /* NULL - undocumented pointer to SIDs. */
return False;
if (validation_level == 3) {
if(!prs_uint32("num_other_sids", ps, depth, &usr->num_other_sids)) /* 0 - num_sids */
return False;
if(!prs_uint32("buffer_other_sids", ps, depth, &usr->buffer_other_sids)) /* NULL - undocumented pointer to SIDs. */
return False;
} else {
if (UNMARSHALLING(ps)) {
usr->num_other_sids = 0;
usr->buffer_other_sids = 0;
}
}
if(!smb_io_unistr2("unistr2", &usr->uni_user_name, usr->hdr_user_name.buffer, ps, depth)) /* username unicode string */
return False;
@ -1260,7 +1274,7 @@ static BOOL net_io_user_info3(char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
if(!prs_uint32("num_other_groups", ps, depth, &usr->num_other_groups))
return False;
if (UNMARSHALLING(ps)) {
if (UNMARSHALLING(ps) && usr->num_other_groups > 0) {
usr->other_gids = (DOM_GID *)prs_alloc_mem(ps, sizeof(DOM_GID)*usr->num_other_groups);
if (usr->other_gids == NULL)
return False;
@ -1326,7 +1340,7 @@ BOOL net_io_r_sam_logon(char *desc, NET_R_SAM_LOGON *r_l, prs_struct *ps, int de
return False;
if (r_l->switch_value != 0) {
if(!net_io_user_info3("", r_l->user, ps, depth))
if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value))
return False;
}