Fixes to make SCHANNEL work against a W2K DC. Still need to fix
authorJeremy Allison <jra@samba.org>
Wed, 16 Apr 2003 15:54:00 +0000 (15:54 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 16 Apr 2003 15:54:00 +0000 (15:54 +0000)
multi-PDU encode/decode with SCHANNEL. Also need to test against WNT DC.
Jeremy.

source/include/rpc_dce.h
source/rpc_client/cli_pipe.c
source/rpc_parse/parse_prs.c
source/rpc_parse/parse_rpc.c
source/rpc_server/srv_pipe.c

index 22dae7ce367b5a931cea144b7f776970f08545bc..b99639d68d8f440fb828f4117d6f810e9e8d5188 100644 (file)
@@ -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;
index 93c6b98bc362173f049b1f8a69564691c3ad1537..a0be3d9774f881d736ddbe1dbea6de3ae111c707 100644 (file)
@@ -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)) {
index a22ae1bacdaaa15631a7ec36f7a97b3e0854749f..696142905bb555e7fae6d2f69361e0a6f25eca3c 100644 (file)
@@ -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);
index 30909c69105fa9dc7206300bcaecc709ae7770d2..dd75ea1f557384efcfd45685a53bbc8b8a14b446 100644 (file)
@@ -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;
 }
index 43fbb4edaacec9a436e8d01706ff0afbeba57dda..df99c15777a2d1084be9815111f403ba5cd713c6 100644 (file)
@@ -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;
 }