r10656: BIG merge from trunk. Features not copied over
[nivanova/samba-autobuild/.git] / source3 / rpc_parse / parse_prs.c
index 709a5d39af6c3f78178c45baebd0a5727adfe662..d174bad444d7714e181088ecd3e29aae812880bf 100644 (file)
@@ -34,7 +34,6 @@ void prs_dump(char *name, int v, prs_struct *ps)
        prs_dump_region(name, v, ps, ps->data_offset, ps->buffer_size);
 }
 
-
 /**
  * Dump from the start of the prs to the current location.
  **/
@@ -43,7 +42,6 @@ void prs_dump_before(char *name, int v, prs_struct *ps)
        prs_dump_region(name, v, ps, 0, ps->data_offset);
 }
 
-
 /**
  * Dump everything from the start of the prs up to the current location.
  **/
@@ -52,6 +50,7 @@ void prs_dump_region(char *name, int v, prs_struct *ps,
 {
        int fd, i;
        pstring fname;
+       ssize_t sz;
        if (DEBUGLEVEL < 50) return;
        for (i=1;i<100;i++) {
                if (v != -1) {
@@ -63,26 +62,28 @@ void prs_dump_region(char *name, int v, prs_struct *ps,
                if (fd != -1 || errno != EEXIST) break;
        }
        if (fd != -1) {
-               write(fd, ps->data_p + from_off, to_off - from_off);
-               close(fd);
-               DEBUG(0,("created %s\n", fname));
+               sz = write(fd, ps->data_p + from_off, to_off - from_off);
+               i = close(fd);
+               if ( (sz != to_off-from_off) || (i != 0) ) {
+                       DEBUG(0,("Error writing/closing %s: %ld!=%ld %d\n", fname, (unsigned long)sz, (unsigned long)to_off-from_off, i ));
+               } else {
+                       DEBUG(0,("created %s\n", fname));
+               }
        }
 }
 
-
-
 /*******************************************************************
- debug output for parsing info.
+ Debug output for parsing info
 
- XXXX side-effect of this function is to increase the debug depth XXXX
+ XXXX side-effect of this function is to increase the debug depth XXXX.
+
+********************************************************************/
 
- ********************************************************************/
 void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name)
 {
        DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->data_offset, fn_name, desc));
 }
 
-
 /**
  * Initialise an expandable parse structure.
  *
@@ -91,6 +92,7 @@ void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name)
  *
  * @return False if allocation fails, otherwise True.
  **/
+
 BOOL prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, BOOL io)
 {
        ZERO_STRUCTP(ps);
@@ -111,6 +113,9 @@ BOOL prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, BOOL io)
                }
                memset(ps->data_p, '\0', (size_t)size);
                ps->is_dynamic = True; /* We own this memory. */
+       } else if (MARSHALLING(ps)) {
+               /* If size is zero and we're marshalling we should allocate memory on demand. */
+               ps->is_dynamic = True;
        }
 
        return True;
@@ -254,7 +259,7 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space)
                 * is greater.
                 */
 
-               new_size = MAX(MAX_PDU_FRAG_LEN,extra_space);
+               new_size = MAX(RPC_MAX_PDU_FRAG_LEN,extra_space);
 
                if((new_data = SMB_MALLOC(new_size)) == NULL) {
                        DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size));
@@ -398,7 +403,7 @@ BOOL prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uin
  Append the data from a buffer into a parse_struct.
  ********************************************************************/
 
-BOOL prs_copy_data_in(prs_struct *dst, char *src, uint32 len)
+BOOL prs_copy_data_in(prs_struct *dst, const char *src, uint32 len)
 {
        if (len == 0)
                return True;
@@ -564,6 +569,15 @@ void prs_force_dynamic(prs_struct *ps)
        ps->is_dynamic=True;
 }
 
+/*******************************************************************
+ Associate a session key with a parse struct.
+ ********************************************************************/
+
+void prs_set_session_key(prs_struct *ps, const char sess_key[16])
+{
+       ps->sess_key = sess_key;
+}
+
 /*******************************************************************
  Stream a uint8.
  ********************************************************************/
@@ -596,9 +610,9 @@ BOOL prs_pointer( const char *name, prs_struct *ps, int depth,
 {
        uint32 data_p;
 
-       /* caputure the pointer value to stream */
+       /* output f000baaa to stream if the pointer is non-zero. */
 
-       data_p = (uint32) *data;
+       data_p = *data ? 0xf000baaa : 0;
 
        if ( !prs_uint32("ptr", ps, depth, &data_p ))
                return False;
@@ -1387,7 +1401,7 @@ int tdb_prs_fetch(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps, TALLOC_CTX *me
  hash a stream.
  ********************************************************************/
 
-BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len)
+BOOL prs_hash1(prs_struct *ps, uint32 offset, int len)
 {
        char *q;
 
@@ -1396,10 +1410,10 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len)
 
 #ifdef DEBUG_PASSWORD
        DEBUG(100, ("prs_hash1\n"));
-       dump_data(100, sess_key, 16);
+       dump_data(100, ps->sess_key, 16);
        dump_data(100, q, len);
 #endif
-       SamOEMhash((uchar *) q, sess_key, len);
+       SamOEMhash((uchar *) q, ps->sess_key, len);
 
 #ifdef DEBUG_PASSWORD
        dump_data(100, q, len);
@@ -1413,9 +1427,9 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len)
  MD5 it with the session key.
  ********************************************************************/
 
-static void netsec_digest(struct netsec_auth_struct *a,
-                         int auth_flags,
-                         RPC_AUTH_NETSEC_CHK * verf,
+static void schannel_digest(struct schannel_auth_struct *a,
+                         enum pipe_auth_level auth_level,
+                         RPC_AUTH_SCHANNEL_CHK * verf,
                          char *data, size_t data_len,
                          uchar digest_final[16]) 
 {
@@ -1429,7 +1443,7 @@ static void netsec_digest(struct netsec_auth_struct *a,
           out of order */
        MD5Update(&ctx3, zeros, sizeof(zeros));
        MD5Update(&ctx3, verf->sig, sizeof(verf->sig));
-       if (auth_flags & AUTH_PIPE_SEAL) {
+       if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
                MD5Update(&ctx3, verf->confounder, sizeof(verf->confounder));
        }
        MD5Update(&ctx3, (const unsigned char *)data, data_len);
@@ -1445,8 +1459,8 @@ static void netsec_digest(struct netsec_auth_struct *a,
  Calculate the key with which to encode the data payload 
  ********************************************************************/
 
-static void netsec_get_sealing_key(struct netsec_auth_struct *a,
-                                  RPC_AUTH_NETSEC_CHK *verf,
+static void schannel_get_sealing_key(struct schannel_auth_struct *a,
+                                  RPC_AUTH_SCHANNEL_CHK *verf,
                                   uchar sealing_key[16]) 
 {
        static uchar zeros[4];
@@ -1473,8 +1487,8 @@ static void netsec_get_sealing_key(struct netsec_auth_struct *a,
  Encode or Decode the sequence number (which is symmetric)
  ********************************************************************/
 
-static void netsec_deal_with_seq_num(struct netsec_auth_struct *a,
-                                    RPC_AUTH_NETSEC_CHK *verf)
+static void schannel_deal_with_seq_num(struct schannel_auth_struct *a,
+                                    RPC_AUTH_SCHANNEL_CHK *verf)
 {
        static uchar zeros[4];
        uchar sequence_key[16];
@@ -1493,10 +1507,10 @@ static void netsec_deal_with_seq_num(struct netsec_auth_struct *a,
 }
 
 /*******************************************************************
-creates an RPC_AUTH_NETSEC_CHK structure.
+creates an RPC_AUTH_SCHANNEL_CHK structure.
 ********************************************************************/
 
-static BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk,
+static BOOL init_rpc_auth_schannel_chk(RPC_AUTH_SCHANNEL_CHK * chk,
                              const uchar sig[8],
                              const uchar packet_digest[8],
                              const uchar seq_num[8], const uchar confounder[8])
@@ -1513,15 +1527,15 @@ static BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk,
 }
 
 /*******************************************************************
- Encode a blob of data using the netsec (schannel) alogrithm, also produceing
+ Encode a blob of data using the schannel alogrithm, also produceing
  a checksum over the original data.  We currently only support
  signing and sealing togeather - the signing-only code is close, but not
  quite compatible with what MS does.
  ********************************************************************/
 
-void netsec_encode(struct netsec_auth_struct *a, int auth_flags, 
-                  enum netsec_direction direction,
-                  RPC_AUTH_NETSEC_CHK * verf,
+void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level,
+                  enum schannel_direction direction,
+                  RPC_AUTH_SCHANNEL_CHK * verf,
                   char *data, size_t data_len)
 {
        uchar digest_final[16];
@@ -1529,16 +1543,16 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags,
        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 = NULL;
+       static const uchar schannel_seal_sig[8] = SCHANNEL_SEAL_SIGNATURE;
+       static const uchar schannel_sign_sig[8] = SCHANNEL_SIGN_SIGNATURE;
+       const uchar *schannel_sig = NULL;
 
-       DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
+       DEBUG(10,("SCHANNEL: schannel_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;
+       if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
+               schannel_sig = schannel_seal_sig;
+       } else {
+               schannel_sig = schannel_sign_sig;
        }
 
        /* fill the 'confounder' with random data */
@@ -1559,18 +1573,18 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags,
 
        dump_data_pw("verf->seq_num:\n", seq_num, sizeof(verf->seq_num));
 
-       init_rpc_auth_netsec_chk(verf, netsec_sig, nullbytes,
+       init_rpc_auth_schannel_chk(verf, schannel_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);
+       schannel_digest(a, auth_level, verf, data, data_len, digest_final);
        memcpy(verf->packet_digest, digest_final, sizeof(verf->packet_digest));
 
-       if (auth_flags & AUTH_PIPE_SEAL) {
+       if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
                uchar sealing_key[16];
 
                /* get the key to encode the data with */
-               netsec_get_sealing_key(a, verf, sealing_key);
+               schannel_get_sealing_key(a, verf, sealing_key);
 
                /* encode the verification data */
                dump_data_pw("verf->confounder:\n", verf->confounder, sizeof(verf->confounder));
@@ -1587,35 +1601,35 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags,
        /* encode the sequence number (key based on packet digest) */
        /* needs to be done after the sealing, as the original version 
           is used in the sealing stuff... */
-       netsec_deal_with_seq_num(a, verf);
+       schannel_deal_with_seq_num(a, verf);
 
        return;
 }
 
 /*******************************************************************
- Decode a blob of data using the netsec (schannel) alogrithm, also verifiying
+ Decode a blob of data using the schannel alogrithm, also verifiying
  a checksum over the original data.  We currently can verify signed messages,
  as well as decode sealed messages
  ********************************************************************/
 
-BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
-                  enum netsec_direction direction, 
-                  RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len)
+BOOL schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level,
+                  enum schannel_direction direction, 
+                  RPC_AUTH_SCHANNEL_CHK * verf, char *data, size_t data_len)
 {
        uchar digest_final[16];
 
-       static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE;
-       static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE;
-       const uchar *netsec_sig = NULL;
+       static const uchar schannel_seal_sig[8] = SCHANNEL_SEAL_SIGNATURE;
+       static const uchar schannel_sign_sig[8] = SCHANNEL_SIGN_SIGNATURE;
+       const uchar *schannel_sig = NULL;
 
        uchar seq_num[8];
 
-       DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
+       DEBUG(10,("SCHANNEL: schannel_decode 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;
+       if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
+               schannel_sig = schannel_seal_sig;
+       } else {
+               schannel_sig = schannel_sign_sig;
        }
 
        /* Create the expected sequence number for comparison */
@@ -1630,7 +1644,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
                break;
        }
 
-       DEBUG(10,("SCHANNEL: netsec_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
+       DEBUG(10,("SCHANNEL: schannel_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
        dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key));
 
        dump_data_pw("seq_num:\n", seq_num, sizeof(seq_num));
@@ -1638,7 +1652,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
        /* extract the sequence number (key based on supplied packet digest) */
        /* needs to be done before the sealing, as the original version 
           is used in the sealing stuff... */
-       netsec_deal_with_seq_num(a, verf);
+       schannel_deal_with_seq_num(a, verf);
 
        if (memcmp(verf->seq_num, seq_num, sizeof(seq_num))) {
                /* don't even bother with the below if the sequence number is out */
@@ -1646,7 +1660,7 @@ 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"));
+               DEBUG(2, ("schannel_decode: FAILED: packet sequence number:\n"));
                dump_data(2, (const char*)verf->seq_num, sizeof(verf->seq_num));
                DEBUG(2, ("should be:\n"));
                dump_data(2, (const char*)seq_num, sizeof(seq_num));
@@ -1654,20 +1668,20 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
                return False;
        }
 
-       if (memcmp(verf->sig, netsec_sig, sizeof(verf->sig))) {
+       if (memcmp(verf->sig, schannel_sig, sizeof(verf->sig))) {
                /* Validate that the other end sent the expected header */
-               DEBUG(2, ("netsec_decode: FAILED: packet header:\n"));
+               DEBUG(2, ("schannel_decode: FAILED: packet header:\n"));
                dump_data(2, (const char*)verf->sig, sizeof(verf->sig));
                DEBUG(2, ("should be:\n"));
-               dump_data(2, (const char*)netsec_sig, sizeof(netsec_sig));
+               dump_data(2, (const char*)schannel_sig, sizeof(schannel_sig));
                return False;
        }
 
-       if (auth_flags & AUTH_PIPE_SEAL) {
+       if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
                uchar sealing_key[16];
                
                /* get the key to extract the data with */
-               netsec_get_sealing_key(a, verf, sealing_key);
+               schannel_get_sealing_key(a, verf, sealing_key);
 
                /* extract the verification data */
                dump_data_pw("verf->confounder:\n", verf->confounder, 
@@ -1684,7 +1698,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
        }
 
        /* digest includes 'data' after unsealing */
-       netsec_digest(a, auth_flags, verf, data, data_len, digest_final);
+       schannel_digest(a, auth_level, verf, data, data_len, digest_final);
 
        dump_data_pw("Calculated digest:\n", digest_final, 
                     sizeof(digest_final));