From 09a50497d1360659eb8bd1b9f4be510680267bd2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Apr 2003 15:39:57 +0000 Subject: Fixes to make SCHANNEL work in 3.0 against a W2K DC. Still need to fix multi-PDU encode/decode with SCHANNEL. Also need to test against WNT DC. Jeremy. (This used to be commit ff66d4097088409205b6bad5124a78ef9946010d) --- source3/include/rpc_dce.h | 4 ++-- source3/rpc_client/cli_pipe.c | 37 ++++++++++++++++++++++++------------- source3/rpc_parse/parse_prs.c | 14 ++++++-------- source3/rpc_parse/parse_rpc.c | 14 +++++++------- source3/rpc_server/srv_pipe.c | 12 ++++++++++-- source3/utils/net_rpc.c | 2 ++ 6 files changed, 51 insertions(+), 32 deletions(-) diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index 22dae7ce36..b99639d68d 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -211,8 +211,8 @@ typedef struct rpc_hdr_auth_info /* RPC_AUTH_NETSEC_NEG */ typedef struct rpc_auth_netsec_neg_info { - uint32 unknown1; - uint32 unknown2; + uint32 type1; /* Always zero ? */ + uint32 type2; /* Types 0x3 and 0x13 seen. Check AcquireSecurityContext() docs.... */ fstring domain; /* calling workstations's domain */ fstring myname; /* calling workstation's name */ } RPC_AUTH_NETSEC_NEG; diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 93c6b98bc3..a0be3d9774 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -193,8 +193,8 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, int len, int BOOL auth_seal = ((cli->ntlmssp_srv_flgs & NTLMSSP_NEGOTIATE_SEAL) != 0); BOOL auth_schannel = (cli->saved_netlogon_pipe_fnum != 0); - DEBUG(5,("rpc_auth_pipe: len: %d auth_len: %d verify %s seal %s\n", - len, auth_len, BOOLSTR(auth_verify), BOOLSTR(auth_seal))); + DEBUG(5,("rpc_auth_pipe: len: %d auth_len: %d verify %s seal %s schannel %s\n", + len, auth_len, BOOLSTR(auth_verify), BOOLSTR(auth_seal), BOOLSTR(auth_schannel))); /* * Unseal any sealed data in the PDU, not including the @@ -302,16 +302,16 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, int len, int prs_struct auth_verf; if (auth_len != RPC_AUTH_NETSEC_CHK_LEN) { - DEBUG(0,("rpc_auth_pipe: wrong auth len %d\n", auth_len)); + DEBUG(0,("rpc_auth_pipe: wrong schannel auth len %d\n", auth_len)); return False; } if (dp - prs_data_p(rdata) > prs_data_size(rdata)) { - DEBUG(0,("rpc_auth_pipe: auth data > data size !\n")); + DEBUG(0,("rpc_auth_pipe: schannel auth data > data size !\n")); return False; } - DEBUG(10,("rpc_auth_pipe: verify netsec\n")); + DEBUG(10,("rpc_auth_pipe: schannel verify netsec\n")); dump_data(100, dp, auth_len); memcpy(data, dp, sizeof(data)); @@ -324,17 +324,18 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, int len, int prs_give_memory(&auth_verf, data, RPC_AUTH_NETSEC_CHK_LEN, False); - if (!smb_io_rpc_auth_netsec_chk("auth_sign", &chk, &auth_verf, 0)) { - DEBUG(0, ("rpc_auth_pipe: unmarshalling " + if (!smb_io_rpc_auth_netsec_chk("schannel_auth_sign", &chk, &auth_verf, 0)) { + DEBUG(0, ("rpc_auth_pipe: schannel unmarshalling " "RPC_AUTH_NETSECK_CHK failed\n")); return False; } + cli->auth_info.seq_num++; + if (!netsec_decode(&cli->auth_info, &chk, reply_data, data_len)) { DEBUG(0, ("rpc_auth_pipe: Could not decode schannel\n")); return False; } - cli->auth_info.seq_num++; } return True; } @@ -360,7 +361,7 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, int len, int +------------+-----------------+-------------+---------------+-------------+ Where the presence of the AUTH_HDR and AUTH are dependent on the - signing & sealing being neogitated. + signing & sealing being negotiated. ****************************************************************************/ @@ -649,7 +650,7 @@ static BOOL create_rpc_bind_req(prs_struct *rpc_out, BOOL do_auth, BOOL do_netse init_rpc_hdr_auth(&hdr_auth, NETSEC_AUTH_TYPE, NETSEC_AUTH_LEVEL, 0x00, 1); - init_rpc_auth_netsec_neg(&netsec_neg, my_name, domain); + init_rpc_auth_netsec_neg(&netsec_neg, domain, my_name); /* * Use the 4k buffer to store the auth info. @@ -1018,8 +1019,15 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num, uchar sign[8]; prs_struct netsec_blob; - memset(sign, 0, sizeof(sign)); - sign[4] = 0x80; + if ((cli->auth_info.seq_num & 1) != 0) { + DEBUG(0,("SCHANNEL ERROR: seq_num must be even in client (seq_num=%d)\n", + cli->auth_info.seq_num)); + } + + DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num)); + + RSIVAL(sign, 0, cli->auth_info.seq_num); + SIVAL(sign, 4, 0x80); if (!prs_init(&netsec_blob, send_size+auth_padding, cli->mem_ctx, MARSHALL)) { @@ -1047,12 +1055,15 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num, init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, sign, nullbytes); - netsec_encode(&(cli->auth_info), &verf, + netsec_encode(&cli->auth_info, &verf, prs_data_p(&netsec_blob), prs_data_size(&netsec_blob)); prs_append_prs_data(&outgoing_packet, &netsec_blob); prs_mem_free(&netsec_blob); + + cli->auth_info.seq_num++; + } else { if(!prs_append_some_prs_data(&outgoing_packet, data, data_sent, send_size)) { diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index a22ae1bacd..696142905b 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -1392,14 +1392,13 @@ void netsec_encode(struct netsec_auth_struct *a, uchar sess_kf0[16]; int i; - /* store the sequence number */ - SIVAL(dataN, 0, a->seq_num); + SIVAL(dataN, 0, 0); - for (i = 0; i < sizeof(sess_kf0); i++) - { + for (i = 0; i < sizeof(sess_kf0); i++) { sess_kf0[i] = a->sess_key[i] ^ 0xf0; } + DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%d\n", a->seq_num, data_len)); dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); dump_data_pw("a->seq_num :\n", dataN, sizeof(dataN)); @@ -1459,14 +1458,13 @@ BOOL netsec_decode(struct netsec_auth_struct *a, uchar sess_kf0[16]; int i; - /* store the sequence number */ - SIVAL(dataN, 0, a->seq_num); + SIVAL(dataN, 0, 0); - for (i = 0; i < sizeof(sess_kf0); i++) - { + for (i = 0; i < sizeof(sess_kf0); i++) { sess_kf0[i] = a->sess_key[i] ^ 0xf0; } + DEBUG(10,("SCHANNEL: netsec_decode seq_num=%d data_len=%d\n", a->seq_num, data_len)); dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); dump_data_pw("a->seq_num :\n", dataN, sizeof(dataN)); hmac_md5(a->sess_key, dataN, 0x4, digest1); diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index 30909c6910..dd75ea1f55 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -1144,8 +1144,8 @@ creates an RPC_AUTH_NETSEC_NEG structure. void init_rpc_auth_netsec_neg(RPC_AUTH_NETSEC_NEG *neg, const char *domain, const char *myname) { - neg->unknown1 = 0; - neg->unknown2 = 0x13; + neg->type1 = 0; + neg->type2 = 0x3; fstrcpy(neg->domain, domain); fstrcpy(neg->myname, myname); } @@ -1166,16 +1166,16 @@ BOOL smb_io_rpc_auth_netsec_neg(const char *desc, RPC_AUTH_NETSEC_NEG *neg, if(!prs_align(ps)) return False; - if(!prs_uint32("unknown1", ps, depth, &neg->unknown1)) + if(!prs_uint32("type1", ps, depth, &neg->type1)) return False; - if(!prs_uint32("unknown2", ps, depth, &neg->unknown2)) - return False; - if(!prs_string("myname ", ps, depth, neg->myname, - strlen(neg->myname), sizeof(neg->myname))) + if(!prs_uint32("type2", ps, depth, &neg->type2)) return False; if(!prs_string("domain ", ps, depth, neg->domain, strlen(neg->domain), sizeof(neg->domain))) return False; + if(!prs_string("myname ", ps, depth, neg->myname, + strlen(neg->myname), sizeof(neg->myname))) + return False; return True; } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 43fbb4edaa..df99c15777 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -279,8 +279,13 @@ BOOL create_next_pdu(pipes_struct *p) prs_init(&rverf, 0, p->mem_ctx, MARSHALL); prs_init(&rauth, 0, p->mem_ctx, MARSHALL); - memset(sign, 0, sizeof(sign)); - sign[3] = 0x01; + if ((p->netsec_auth.seq_num & 1) == 0) { + DEBUG(0,("SCHANNEL ERROR: seq_num must be odd in server! (seq_num=%d)\n", + p->netsec_auth.seq_num)); + } + + RSIVAL(sign, 0, p->netsec_auth.seq_num); + SIVAL(sign, 4, 0); init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, sign, nullbytes); @@ -1340,6 +1345,9 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in) return False; } + /* The sequence number gets incremented on both send and receive. */ + p->netsec_auth.seq_num++; + return True; } diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index a35cdd0b5b..fcd8a54118 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -317,6 +317,8 @@ int net_rpc_join(int argc, const char **argv) }; if (argc == 0) { + if (opt_user_specified) + return net_rpc_join_newstyle(argc, argv); if ((net_rpc_join_oldstyle(argc, argv) == 0)) return 0; -- cgit