commit sign only patch from Andrew; bug 167; tested using 2k & XP clientspreviously...
authorGerald Carter <jerry@samba.org>
Wed, 1 Oct 2003 22:00:19 +0000 (22:00 +0000)
committerGerald Carter <jerry@samba.org>
Wed, 1 Oct 2003 22:00:19 +0000 (22:00 +0000)
(This used to be commit 9d2e585e5e6f9066c6901aa8d8308734f8667296)

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

index 2e4a418bb7d186b7510a3f412877d5b273619610..52fe08d8753b15bb6903dc14b5929bf3efdb5797 100644 (file)
@@ -61,8 +61,14 @@ enum RPC_PKT_TYPE
 
 /* Netlogon schannel auth type and level */
 #define NETSEC_AUTH_TYPE 0x44
-#define NETSEC_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 }
+#define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }
+#define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 }
 #define RPC_AUTH_NETSEC_CHK_LEN 0x20
+
+/* The 7 here seems to be required to get Win2k not to downgrade us
+   to NT4.  Actually, anything other than 1ff would seem to do... */
+#define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff
 #define NETLOGON_NEG_SCHANNEL    0x40000000
 
 enum netsec_direction
@@ -239,13 +245,14 @@ typedef struct rpc_auth_netsec_chk_info
        uint8 sig  [8]; /* 77 00 7a 00 ff ff 00 00 */
        uint8 packet_digest[8]; /* checksum over the packet, MD5'ed with session key */
        uint8 seq_num[8]; /* verifier, seq num */
-       uint8 data8[8]; /* random 8-byte nonce */
+       uint8 confounder[8]; /* random 8-byte nonce */
 } RPC_AUTH_NETSEC_CHK;
 
 struct netsec_auth_struct
 {
        uchar sess_key[16];
        uint32 seq_num;
+       int auth_flags;
 };
 
 /* RPC_BIND_REQ - ms req bind */
index dedbf017a93a04caae8bc4f9055e36cea4fc5f5b..9ce10202dbe456cb471cb8588bbb3829ede671e6 100644 (file)
@@ -29,7 +29,9 @@
 
 extern struct pipe_id_info pipe_names[];
 
-static void get_auth_type_level(int pipe_auth_flags, int *auth_type, int *auth_level) 
+/* convert pipe auth flags into the RPC auth type and level */
+
+void get_auth_type_level(int pipe_auth_flags, int *auth_type, int *auth_level) 
 {
        *auth_type = 0;
        *auth_level = 0;
@@ -938,7 +940,6 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num,
                uint32 data_len, send_size;
                uint8 flags = 0;
                uint32 auth_padding = 0;
-               RPC_AUTH_NETSEC_CHK verf;
                DATA_BLOB sign_blob;
 
                /*
@@ -1022,14 +1023,10 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num,
 
                        }
                        else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {     
-                               static const uchar netsec_sig[8] = NETSEC_SIGNATURE;
-                               static const uchar nullbytes[8] = { 0,0,0,0,0,0,0,0 };
                                size_t parse_offset_marker;
+                               RPC_AUTH_NETSEC_CHK verf;
                                DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num));
                                
-                               init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes,
-                                                        nullbytes, nullbytes);
-                               
                                netsec_encode(&cli->auth_info, 
                                              cli->pipe_auth_flags,
                                              SENDER_IS_INITIATOR,
@@ -1277,8 +1274,10 @@ static BOOL rpc_send_auth_reply(struct cli_state *cli, prs_struct *rdata, uint32
        prs_init(&rpc_out, RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN, /* need at least this much */ 
                 cli->mem_ctx, MARSHALL);
 
-       create_rpc_bind_resp(cli, rpc_call_id,
-                            &rpc_out);
+       if (!NT_STATUS_IS_OK(create_rpc_bind_resp(cli, rpc_call_id,
+                                                 &rpc_out))) {
+               return False;
+       }
 
        if ((ret = cli_write(cli, cli->nt_pipe_fnum, 0x8, prs_data_p(&rpc_out), 
                        0, (size_t)prs_offset(&rpc_out))) != (ssize_t)prs_offset(&rpc_out)) {
@@ -1493,9 +1492,7 @@ NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan,
                                   const uchar trust_password[16])
 {
        NTSTATUS result;        
-       /* The 7 here seems to be required to get Win2k not to downgrade us
-          to NT4.  Actually, anything other than 1ff would seem to do... */
-       uint32 neg_flags = 0x000701ff;
+       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
        int fnum;
 
        cli_nt_netlogon_netsec_session_close(cli);
@@ -1584,13 +1581,11 @@ NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan,
 }
 
 
-NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan,
+NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan, int auth_flags,
                             const uchar trust_password[16])
 {
        NTSTATUS result;        
-       /* The 7 here seems to be required to get Win2k not to downgrade us
-          to NT4.  Actually, anything other than 1ff would seem to do... */
-       uint32 neg_flags = 0x000701ff;
+       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
        cli->pipe_auth_flags = 0;
 
        if (lp_client_schannel() == False) {
@@ -1632,7 +1627,7 @@ NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan,
        cli->nt_pipe_fnum = 0;
 
        /* doing schannel, not per-user auth */
-       cli->pipe_auth_flags = AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL;
+       cli->pipe_auth_flags = auth_flags;
 
        return NT_STATUS_OK;
 }
index 81a95730778595da0226ce2416ae3a5038683ccc..b30c41c0903152bd07d05dc355e39e118a147505 100644 (file)
@@ -3,7 +3,8 @@
    Samba memory buffer functions
    Copyright (C) Andrew Tridgell              1992-1997
    Copyright (C) Luke Kenneth Casson Leighton 1996-1997
-   Copyright (C) Jeremy Allison 1999.
+   Copyright (C) Jeremy Allison               1999
+   Copyright (C) Andrew Bartlett              2003.
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -1337,47 +1338,6 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len)
        return True;
 }
 
-static void netsechash(uchar * key, uchar * data, int data_len)
-{
-       uchar hash[256];
-       uchar index_i = 0;
-       uchar index_j = 0;
-       uchar j = 0;
-       int ind;
-
-       for (ind = 0; ind < 256; ind++)
-       {
-               hash[ind] = (uchar) ind;
-       }
-
-       for (ind = 0; ind < 256; ind++)
-       {
-               uchar tc;
-
-               j += (hash[ind] + key[ind % 16]);
-
-               tc = hash[ind];
-               hash[ind] = hash[j];
-               hash[j] = tc;
-       }
-
-       for (ind = 0; ind < data_len; ind++)
-       {
-               uchar tc;
-               uchar t;
-
-               index_i++;
-               index_j += hash[index_i];
-
-               tc = hash[index_i];
-               hash[index_i] = hash[index_j];
-               hash[index_j] = tc;
-
-               t = hash[index_i] + hash[index_j];
-               data[ind] ^= hash[t];
-       }
-}
-
 
 /*******************************************************************
  Create a digest over the entire packet (including the data), and 
@@ -1400,7 +1360,7 @@ static void netsec_digest(struct netsec_auth_struct *a,
        MD5Update(&ctx3, zeros, sizeof(zeros));
        MD5Update(&ctx3, verf->sig, sizeof(verf->sig));
        if (auth_flags & AUTH_PIPE_SEAL) {
-               MD5Update(&ctx3, verf->data8, sizeof(verf->data8));
+               MD5Update(&ctx3, verf->confounder, sizeof(verf->confounder));
        }
        MD5Update(&ctx3, (const unsigned char *)data, data_len);
        MD5Final(whole_packet_digest, &ctx3);
@@ -1456,10 +1416,29 @@ static void netsec_deal_with_seq_num(struct netsec_auth_struct *a,
        dump_data_pw("sequence_key:\n", sequence_key, sizeof(sequence_key));
 
        dump_data_pw("seq_num (before):\n", verf->seq_num, sizeof(verf->seq_num));
-       netsechash(sequence_key, verf->seq_num, 8);
+       SamOEMhash(verf->seq_num, sequence_key, 8);
        dump_data_pw("seq_num (after):\n", verf->seq_num, sizeof(verf->seq_num));
 }
 
+/*******************************************************************
+creates an RPC_AUTH_NETSEC_CHK structure.
+********************************************************************/
+static BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk,
+                             const uchar sig[8],
+                             const uchar packet_digest[8],
+                             const uchar seq_num[8], const uchar confounder[8])
+{
+       if (chk == NULL)
+               return False;
+
+       memcpy(chk->sig, sig, sizeof(chk->sig));
+       memcpy(chk->packet_digest, packet_digest, sizeof(chk->packet_digest));
+       memcpy(chk->seq_num, seq_num, sizeof(chk->seq_num));
+       memcpy(chk->confounder, confounder, sizeof(chk->confounder));
+
+       return True;
+}
+
 
 /*******************************************************************
  Encode a blob of data using the netsec (schannel) alogrithm, also produceing
@@ -1469,26 +1448,47 @@ static void netsec_deal_with_seq_num(struct netsec_auth_struct *a,
  ********************************************************************/
 void netsec_encode(struct netsec_auth_struct *a, int auth_flags, 
                   enum netsec_direction direction,
-                  RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len)
+                  RPC_AUTH_NETSEC_CHK * verf,
+                  char *data, size_t data_len)
 {
        uchar digest_final[16];
+       uchar confounder[8];
+       uchar seq_num[8];
+       static const uchar nullbytes[8];
+
+       static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE;
+       static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE;
+       const uchar *netsec_sig;
 
        DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
+       
+       if (auth_flags & AUTH_PIPE_SEAL) {
+               netsec_sig = netsec_seal_sig;
+       } else if (auth_flags & AUTH_PIPE_SIGN) {
+               netsec_sig = netsec_sign_sig;
+       }
+
+       /* fill the 'confounder' with random data */
+       generate_random_buffer(confounder, sizeof(confounder), False);
+
        dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key));
 
-       RSIVAL(verf->seq_num, 0, a->seq_num);
+       RSIVAL(seq_num, 0, a->seq_num);
 
        switch (direction) {
        case SENDER_IS_INITIATOR:
-               SIVAL(verf->seq_num, 4, 0x80);
+               SIVAL(seq_num, 4, 0x80);
                break;
        case SENDER_IS_ACCEPTOR:
-               SIVAL(verf->seq_num, 4, 0x0);
+               SIVAL(seq_num, 4, 0x0);
                break;
        }
 
-       dump_data_pw("verf->seq_num:\n", verf->seq_num, sizeof(verf->seq_num));
+       dump_data_pw("verf->seq_num:\n", seq_num, sizeof(verf->seq_num));
 
+       init_rpc_auth_netsec_chk(verf, netsec_sig, nullbytes,
+                                seq_num, confounder);
+                               
        /* produce a digest of the packet to prove it's legit (before we seal it) */
        netsec_digest(a, auth_flags, verf, data, data_len, digest_final);
        memcpy(verf->packet_digest, digest_final, sizeof(verf->packet_digest));
@@ -1500,14 +1500,14 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags,
                netsec_get_sealing_key(a, verf, sealing_key);
 
                /* encode the verification data */
-               dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8));
-               netsechash(sealing_key, verf->data8, 8);
+               dump_data_pw("verf->confounder:\n", verf->confounder, sizeof(verf->confounder));
+               SamOEMhash(verf->confounder, sealing_key, 8);
 
-               dump_data_pw("verf->data8_enc:\n", verf->data8, sizeof(verf->data8));
+               dump_data_pw("verf->confounder_enc:\n", verf->confounder, sizeof(verf->confounder));
                
                /* encode the packet payload */
                dump_data_pw("data:\n", (const unsigned char *)data, data_len);
-               netsechash(sealing_key, (unsigned char *)data, data_len);
+               SamOEMhash((unsigned char *)data, sealing_key, data_len);
                dump_data_pw("data_enc:\n", (const unsigned char *)data, data_len);
        }
 
@@ -1531,8 +1531,21 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
 {
        uchar digest_final[16];
 
-       /* Create the expected sequence number for comparison */
+       static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE;
+       static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE;
+       const uchar *netsec_sig;
+
        uchar seq_num[8];
+
+       DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
+       
+       if (auth_flags & AUTH_PIPE_SEAL) {
+               netsec_sig = netsec_seal_sig;
+       } else if (auth_flags & AUTH_PIPE_SIGN) {
+               netsec_sig = netsec_sign_sig;
+       }
+
+       /* Create the expected sequence number for comparison */
        RSIVAL(seq_num, 0, a->seq_num);
 
        switch (direction) {
@@ -1560,6 +1573,20 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
                   digest, as supplied by the client.  We check that it's a valid 
                   checksum after the decode, below
                */
+               DEBUG(2, ("netsec_decode: FAILED: packet sequence number:\n"));
+               dump_data(2, verf->seq_num, sizeof(verf->seq_num));
+               DEBUG(2, ("should be:\n"));
+               dump_data(2, seq_num, sizeof(seq_num));
+
+               return False;
+       }
+
+       if (memcmp(verf->sig, netsec_sig, sizeof(verf->sig))) {
+               /* Validate that the other end sent the expected header */
+               DEBUG(2, ("netsec_decode: FAILED: packet header:\n"));
+               dump_data(2, verf->sig, sizeof(verf->sig));
+               DEBUG(2, ("should be:\n"));
+               dump_data(2, netsec_sig, sizeof(netsec_sig));
                return False;
        }
 
@@ -1570,16 +1597,16 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
                netsec_get_sealing_key(a, verf, sealing_key);
 
                /* extract the verification data */
-               dump_data_pw("verf->data8:\n", verf->data8
-                            sizeof(verf->data8));
-               netsechash(sealing_key, verf->data8, 8);
+               dump_data_pw("verf->confounder:\n", verf->confounder
+                            sizeof(verf->confounder));
+               SamOEMhash(verf->confounder, sealing_key, 8);
 
-               dump_data_pw("verf->data8_dec:\n", verf->data8
-                            sizeof(verf->data8));
+               dump_data_pw("verf->confounder_dec:\n", verf->confounder
+                            sizeof(verf->confounder));
                
                /* extract the packet payload */
                dump_data_pw("data   :\n", (const unsigned char *)data, data_len);
-               netsechash(sealing_key, (unsigned char *)data, data_len);
+               SamOEMhash((unsigned char *)data, sealing_key, data_len);
                dump_data_pw("datadec:\n", (const unsigned char *)data, data_len);      
        }
 
index 34ba62caa92d8241fbf46d42749bde4f76327048..558378548a5841edc8ea39f95dcf814fedc84d41 100644 (file)
@@ -1175,7 +1175,7 @@ creates an RPC_AUTH_NETSEC_CHK structure.
 BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk,
                              const uchar sig[8],
                              const uchar packet_digest[8],
-                             const uchar seq_num[8], const uchar data8[8])
+                             const uchar seq_num[8], const uchar confounder[8])
 {
        if (chk == NULL)
                return False;
@@ -1183,7 +1183,7 @@ BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk,
        memcpy(chk->sig, sig, sizeof(chk->sig));
        memcpy(chk->packet_digest, packet_digest, sizeof(chk->packet_digest));
        memcpy(chk->seq_num, seq_num, sizeof(chk->seq_num));
-       memcpy(chk->data8, data8, sizeof(chk->data8));
+       memcpy(chk->confounder, confounder, sizeof(chk->confounder));
 
        return True;
 }
@@ -1203,7 +1203,7 @@ BOOL smb_io_rpc_auth_netsec_chk(const char *desc, RPC_AUTH_NETSEC_CHK * chk,
        prs_uint8s(False, "sig  ", ps, depth, chk->sig, sizeof(chk->sig));
        prs_uint8s(False, "seq_num", ps, depth, chk->seq_num, sizeof(chk->seq_num));
        prs_uint8s(False, "packet_digest", ps, depth, chk->packet_digest, sizeof(chk->packet_digest));
-       prs_uint8s(False, "data8", ps, depth, chk->data8, sizeof(chk->data8));
+       prs_uint8s(False, "data8", ps, depth, chk->confounder, sizeof(chk->confounder));
 
        return True;
 }
index d1fb587d748a4368067a37ae5ff3ff28e92f977b..96261c665f7455bf24d8ff2e5c4a375fcbd4645d 100644 (file)
@@ -254,18 +254,19 @@ BOOL create_next_pdu(pipes_struct *p)
        }
 
        if (p->netsec_auth_validated) {
+               int auth_type, auth_level;
                char *data;
                RPC_HDR_AUTH auth_info;
-               static const uchar netsec_sig[8] = NETSEC_SIGNATURE;
-               static const uchar nullbytes[8] = { 0,0,0,0,0,0,0,0 };
 
                RPC_AUTH_NETSEC_CHK verf;
                prs_struct rverf;
                prs_struct rauth;
 
                data = prs_data_p(&outgoing_pdu) + data_pos;
+               /* Check it's the type of reply we were expecting to decode */
 
-               init_rpc_hdr_auth(&auth_info, NETSEC_AUTH_TYPE, RPC_PIPE_AUTH_SEAL_LEVEL, 
+               get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level);
+               init_rpc_hdr_auth(&auth_info, auth_type, auth_level, 
                                  RPC_HDR_AUTH_LEN, 1);
 
                if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
@@ -277,10 +278,8 @@ BOOL create_next_pdu(pipes_struct *p)
                prs_init(&rverf, 0, p->mem_ctx, MARSHALL);
                prs_init(&rauth, 0, p->mem_ctx, MARSHALL);
 
-               init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, nullbytes, nullbytes);
-
                netsec_encode(&p->netsec_auth, 
-                             AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL, 
+                             p->netsec_auth.auth_flags,
                              SENDER_IS_ACCEPTOR,
                              &verf, data, data_len);
 
@@ -1337,10 +1336,19 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in)
                return False;
        }
 
-       if ((auth_info.auth_type != NETSEC_AUTH_TYPE) ||
-           (auth_info.auth_level != RPC_PIPE_AUTH_SEAL_LEVEL)) {
-               DEBUG(0,("Invalid auth info %d or level %d on schannel\n",
-                        auth_info.auth_type, auth_info.auth_level));
+       if (auth_info.auth_type != NETSEC_AUTH_TYPE) {
+               DEBUG(0,("Invalid auth info %d on schannel\n",
+                        auth_info.auth_type));
+               return False;
+       }
+
+       if (auth_info.auth_level == RPC_PIPE_AUTH_SEAL_LEVEL) {
+               p->netsec_auth.auth_flags = AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL;
+       } else if (auth_info.auth_level == RPC_PIPE_AUTH_SIGN_LEVEL) {
+               p->netsec_auth.auth_flags = AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN;
+       } else {
+               DEBUG(0,("Invalid auth level %d on schannel\n",
+                        auth_info.auth_level));
                return False;
        }
 
@@ -1350,7 +1358,7 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in)
        }
 
        if (!netsec_decode(&p->netsec_auth,
-                          AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL, 
+                          p->netsec_auth.auth_flags,
                           SENDER_IS_INITIATOR,
                           &netsec_chk,
                           prs_data_p(rpc_in)+old_offset, data_len)) {
index 515489292bc2b0c6a9ff704454830166e52d218e..773441a27cc10f87b080ea9f6db46ff15d59f6c5 100644 (file)
@@ -352,38 +352,33 @@ static NTSTATUS cmd_none(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK; 
 }
 
-static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                            int argc, const char **argv)
+static NTSTATUS setup_schannel(struct cli_state *cli, int pipe_auth_flags,
+                              int argc, const char **argv)
 {
        NTSTATUS ret;
+       static uchar zeros[16];
        uchar trust_password[16];
        uint32 sec_channel_type;
-       static uchar zeros[16];
-
        if (argc == 2) {
                strhex_to_str((char *)cli->auth_info.sess_key,
                              strlen(argv[1]), 
                              argv[1]);
                memcpy(cli->sess_key, cli->auth_info.sess_key, sizeof(cli->sess_key));
 
-               cli->pipe_auth_flags = AUTH_PIPE_NETSEC;
-               cli->pipe_auth_flags |= AUTH_PIPE_SIGN;
-               cli->pipe_auth_flags |= AUTH_PIPE_SEAL;
-
+               cli->pipe_auth_flags = pipe_auth_flags;
                return NT_STATUS_OK;
        }
 
        /* Cleanup */
 
        if ((memcmp(cli->auth_info.sess_key, zeros, sizeof(cli->auth_info.sess_key)) != 0)) {
-               if (cli->pipe_auth_flags == (AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL)) {
+               if (cli->pipe_auth_flags == pipe_auth_flags) {
                        /* already in this mode nothing to do */
                        return NT_STATUS_OK;
                } else {
-                       /* schannel is setup, just need to use it again */
-                       cli->pipe_auth_flags = AUTH_PIPE_NETSEC;
-                       cli->pipe_auth_flags |= AUTH_PIPE_SIGN;
-                       cli->pipe_auth_flags |= AUTH_PIPE_SEAL;
+                       /* schannel is setup, just need to use it again with new flags */
+                       cli->pipe_auth_flags = pipe_auth_flags;
+
                        if (cli->nt_pipe_fnum != 0)
                                cli_nt_session_close(cli);
                        return NT_STATUS_OK;
@@ -393,17 +388,13 @@ static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        if (cli->nt_pipe_fnum != 0)
                cli_nt_session_close(cli);
 
-       cli->pipe_auth_flags = AUTH_PIPE_NETSEC;
-       cli->pipe_auth_flags |= AUTH_PIPE_SIGN;
-       cli->pipe_auth_flags |= AUTH_PIPE_SEAL;
-
        if (!secrets_fetch_trust_account_password(lp_workgroup(),
                                                  trust_password,
                                                  NULL, &sec_channel_type)) {
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       ret = cli_nt_setup_netsec(cli, sec_channel_type, trust_password);
+       ret = cli_nt_setup_netsec(cli, sec_channel_type, pipe_auth_flags, trust_password);
        if (NT_STATUS_IS_OK(ret)) {
                char *hex_session_key;
                hex_encode(cli->auth_info.sess_key,
@@ -415,6 +406,24 @@ static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
+
+static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                            int argc, const char **argv)
+{
+       d_printf("Setting schannel - sign and seal\n");
+       return setup_schannel(cli, AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL, 
+                             argc, argv);
+}
+
+static NTSTATUS cmd_schannel_sign(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                            int argc, const char **argv)
+{
+       d_printf("Setting schannel - sign only\n");
+       return setup_schannel(cli, AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN, 
+                             argc, argv);
+}
+
+
 /* Built in rpcclient commands */
 
 static struct cmd_set rpcclient_commands[] = {
@@ -430,6 +439,7 @@ static struct cmd_set rpcclient_commands[] = {
        { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL,     -1,   "Force RPC pipe connections to be signed", "" },
        { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL,     -1,   "Force RPC pipe connections to be sealed", "" },
        { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL,     -1,   "Force RPC pipe connections to be sealed with 'schannel' (NETSEC).  Assumes valid machine account to this domain controller.", "" },
+       { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL,    -1,   "Force RPC pipe connections to be signed (not sealed) with 'schannel' (NETSEC).  Assumes valid machine account to this domain controller.", "" },
        { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL,     -1,   "Force RPC pipe connections to have no special properties", "" },
 
        { NULL }
@@ -522,9 +532,7 @@ static NTSTATUS do_cmd(struct cli_state *cli,
        /* some of the DsXXX commands use the netlogon pipe */
 
        if (lp_client_schannel() && (cmd_entry->pipe_idx == PI_NETLOGON) && !(cli->pipe_auth_flags & AUTH_PIPE_NETSEC)) {
-               /* The 7 here seems to be required to get Win2k not to downgrade us
-                  to NT4.  Actually, anything other than 1ff would seem to do... */
-               uint32 neg_flags = 0x000001ff;
+               uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
                uint32 sec_channel_type;
        
                if (!secrets_fetch_trust_account_password(lp_workgroup(),