summaryrefslogtreecommitdiff
path: root/source3/rpc_parse
diff options
context:
space:
mode:
Diffstat (limited to 'source3/rpc_parse')
-rw-r--r--source3/rpc_parse/parse_misc.c142
-rw-r--r--source3/rpc_parse/parse_net.c35
-rw-r--r--source3/rpc_parse/parse_prs.c278
-rw-r--r--source3/rpc_parse/parse_rpc.c26
-rw-r--r--source3/rpc_parse/parse_samr.c64
-rw-r--r--source3/rpc_parse/parse_sec.c179
-rw-r--r--source3/rpc_parse/parse_spoolss.c9
-rw-r--r--source3/rpc_parse/parse_srv.c3
8 files changed, 410 insertions, 326 deletions
diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c
index a39e3391bb..17a96fff80 100644
--- a/source3/rpc_parse/parse_misc.c
+++ b/source3/rpc_parse/parse_misc.c
@@ -1122,78 +1122,6 @@ BOOL smb_io_unistr2_array(const char *desc, UNISTR2_ARRAY *array, prs_struct *ps
}
-/*
- initialise a SID_ARRAY from a list of sids
-*/
-BOOL init_sid_array(SID_ARRAY *array,
- uint32 count, DOM_SID *sids)
-{
- unsigned int i;
-
- array->count = count;
- array->ref_id = count?1:0;
- if (array->count == 0) {
- return True;
- }
-
- array->sids = (SID_ARRAY_EL *)talloc_zero(get_talloc_ctx(), count * sizeof(SID_ARRAY_EL));
- if (!array->sids) {
- return False;
- }
-
- for (i=0;i<count;i++) {
- array->sids[i].ref_id = 1;
- init_dom_sid2(&array->sids[i].sid, &sids[i]);
- }
-
- return True;
-}
-
-
-/*******************************************************************
- Reads or writes a SID_ARRAY structure.
-********************************************************************/
-BOOL smb_io_sid_array(const char *desc, SID_ARRAY *array, prs_struct *ps, int depth)
-{
- unsigned int i;
-
- prs_debug(ps, depth, desc, "smb_io_sid_array");
- depth++;
-
- if(!prs_uint32("ref_id", ps, depth, &array->ref_id))
- return False;
-
- if (! array->ref_id) {
- return True;
- }
-
- if(!prs_uint32("count", ps, depth, &array->count))
- return False;
-
- if (array->count == 0) {
- return True;
- }
-
- if (UNMARSHALLING(ps)) {
- array->sids = talloc_zero(get_talloc_ctx(), array->count * sizeof(array->sids[0]));
- }
- if (! array->sids) {
- return False;
- }
-
- for (i=0;i<array->count;i++) {
- if(!prs_uint32("ref_id", ps, depth, &array->sids[i].ref_id))
- return False;
- }
-
- for (i=0;i<array->count;i++) {
- if (!smb_io_dom_sid2("sid", &array->sids[i].sid, ps, depth))
- return False;
- }
-
- return True;
-}
-
/*******************************************************************
Inits a DOM_RID2 structure.
********************************************************************/
@@ -1289,22 +1217,22 @@ void init_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid)
Inits a DOM_CLNT_SRV structure.
********************************************************************/
-static void init_clnt_srv(DOM_CLNT_SRV *dlog, const char *logon_srv, const char *comp_name)
+static void init_clnt_srv(DOM_CLNT_SRV *logcln, const char *logon_srv, const char *comp_name)
{
DEBUG(5,("init_clnt_srv: %d\n", __LINE__));
if (logon_srv != NULL) {
- dlog->undoc_buffer = 1;
- init_unistr2(&dlog->uni_logon_srv, logon_srv, strlen(logon_srv)+1);
+ logcln->undoc_buffer = 1;
+ init_unistr2(&logcln->uni_logon_srv, logon_srv, strlen(logon_srv)+1);
} else {
- dlog->undoc_buffer = 0;
+ logcln->undoc_buffer = 0;
}
if (comp_name != NULL) {
- dlog->undoc_buffer2 = 1;
- init_unistr2(&dlog->uni_comp_name, comp_name, strlen(comp_name)+1);
+ logcln->undoc_buffer2 = 1;
+ init_unistr2(&logcln->uni_comp_name, comp_name, strlen(comp_name)+1);
} else {
- dlog->undoc_buffer2 = 0;
+ logcln->undoc_buffer2 = 0;
}
}
@@ -1312,9 +1240,9 @@ static void init_clnt_srv(DOM_CLNT_SRV *dlog, const char *logon_srv, const char
Inits or writes a DOM_CLNT_SRV structure.
********************************************************************/
-static BOOL smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *dlog, prs_struct *ps, int depth)
+static BOOL smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *logcln, prs_struct *ps, int depth)
{
- if (dlog == NULL)
+ if (logcln == NULL)
return False;
prs_debug(ps, depth, desc, "smb_io_clnt_srv");
@@ -1323,22 +1251,22 @@ static BOOL smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *dlog, prs_struct *ps
if(!prs_align(ps))
return False;
- if(!prs_uint32("undoc_buffer ", ps, depth, &dlog->undoc_buffer))
+ if(!prs_uint32("undoc_buffer ", ps, depth, &logcln->undoc_buffer))
return False;
- if (dlog->undoc_buffer != 0) {
- if(!smb_io_unistr2("unistr2", &dlog->uni_logon_srv, dlog->undoc_buffer, ps, depth))
+ if (logcln->undoc_buffer != 0) {
+ if(!smb_io_unistr2("unistr2", &logcln->uni_logon_srv, logcln->undoc_buffer, ps, depth))
return False;
}
if(!prs_align(ps))
return False;
- if(!prs_uint32("undoc_buffer2", ps, depth, &dlog->undoc_buffer2))
+ if(!prs_uint32("undoc_buffer2", ps, depth, &logcln->undoc_buffer2))
return False;
- if (dlog->undoc_buffer2 != 0) {
- if(!smb_io_unistr2("unistr2", &dlog->uni_comp_name, dlog->undoc_buffer2, ps, depth))
+ if (logcln->undoc_buffer2 != 0) {
+ if(!smb_io_unistr2("unistr2", &logcln->uni_comp_name, logcln->undoc_buffer2, ps, depth))
return False;
}
@@ -1349,28 +1277,28 @@ static BOOL smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *dlog, prs_struct *ps
Inits a DOM_LOG_INFO structure.
********************************************************************/
-void init_log_info(DOM_LOG_INFO *dlog, const char *logon_srv, const char *acct_name,
+void init_log_info(DOM_LOG_INFO *loginfo, const char *logon_srv, const char *acct_name,
uint16 sec_chan, const char *comp_name)
{
DEBUG(5,("make_log_info %d\n", __LINE__));
- dlog->undoc_buffer = 1;
+ loginfo->undoc_buffer = 1;
- init_unistr2(&dlog->uni_logon_srv, logon_srv, strlen(logon_srv)+1);
- init_unistr2(&dlog->uni_acct_name, acct_name, strlen(acct_name)+1);
+ init_unistr2(&loginfo->uni_logon_srv, logon_srv, strlen(logon_srv)+1);
+ init_unistr2(&loginfo->uni_acct_name, acct_name, strlen(acct_name)+1);
- dlog->sec_chan = sec_chan;
+ loginfo->sec_chan = sec_chan;
- init_unistr2(&dlog->uni_comp_name, comp_name, strlen(comp_name)+1);
+ init_unistr2(&loginfo->uni_comp_name, comp_name, strlen(comp_name)+1);
}
/*******************************************************************
Reads or writes a DOM_LOG_INFO structure.
********************************************************************/
-BOOL smb_io_log_info(const char *desc, DOM_LOG_INFO *dlog, prs_struct *ps, int depth)
+BOOL smb_io_log_info(const char *desc, DOM_LOG_INFO *loginfo, prs_struct *ps, int depth)
{
- if (dlog == NULL)
+ if (loginfo == NULL)
return False;
prs_debug(ps, depth, desc, "smb_io_log_info");
@@ -1379,18 +1307,18 @@ BOOL smb_io_log_info(const char *desc, DOM_LOG_INFO *dlog, prs_struct *ps, int d
if(!prs_align(ps))
return False;
- if(!prs_uint32("undoc_buffer", ps, depth, &dlog->undoc_buffer))
+ if(!prs_uint32("undoc_buffer", ps, depth, &loginfo->undoc_buffer))
return False;
- if(!smb_io_unistr2("unistr2", &dlog->uni_logon_srv, True, ps, depth))
+ if(!smb_io_unistr2("unistr2", &loginfo->uni_logon_srv, True, ps, depth))
return False;
- if(!smb_io_unistr2("unistr2", &dlog->uni_acct_name, True, ps, depth))
+ if(!smb_io_unistr2("unistr2", &loginfo->uni_acct_name, True, ps, depth))
return False;
- if(!prs_uint16("sec_chan", ps, depth, &dlog->sec_chan))
+ if(!prs_uint16("sec_chan", ps, depth, &loginfo->sec_chan))
return False;
- if(!smb_io_unistr2("unistr2", &dlog->uni_comp_name, True, ps, depth))
+ if(!smb_io_unistr2("unistr2", &loginfo->uni_comp_name, True, ps, depth))
return False;
return True;
@@ -1529,21 +1457,21 @@ BOOL smb_io_clnt_info(const char *desc, DOM_CLNT_INFO *clnt, prs_struct *ps, in
Inits a DOM_LOGON_ID structure.
********************************************************************/
-void init_logon_id(DOM_LOGON_ID *dlog, uint32 log_id_low, uint32 log_id_high)
+void init_logon_id(DOM_LOGON_ID *logonid, uint32 log_id_low, uint32 log_id_high)
{
DEBUG(5,("make_logon_id: %d\n", __LINE__));
- dlog->low = log_id_low;
- dlog->high = log_id_high;
+ logonid->low = log_id_low;
+ logonid->high = log_id_high;
}
/*******************************************************************
Reads or writes a DOM_LOGON_ID structure.
********************************************************************/
-BOOL smb_io_logon_id(const char *desc, DOM_LOGON_ID *dlog, prs_struct *ps, int depth)
+BOOL smb_io_logon_id(const char *desc, DOM_LOGON_ID *logonid, prs_struct *ps, int depth)
{
- if (dlog == NULL)
+ if (logonid == NULL)
return False;
prs_debug(ps, depth, desc, "smb_io_logon_id");
@@ -1552,9 +1480,9 @@ BOOL smb_io_logon_id(const char *desc, DOM_LOGON_ID *dlog, prs_struct *ps, int d
if(!prs_align(ps))
return False;
- if(!prs_uint32("low ", ps, depth, &dlog->low ))
+ if(!prs_uint32("low ", ps, depth, &logonid->low ))
return False;
- if(!prs_uint32("high", ps, depth, &dlog->high))
+ if(!prs_uint32("high", ps, depth, &logonid->high))
return False;
return True;
diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c
index 1a14915c9f..804da707de 100644
--- a/source3/rpc_parse/parse_net.c
+++ b/source3/rpc_parse/parse_net.c
@@ -446,7 +446,7 @@ void init_r_trust_dom(NET_R_TRUST_DOM_LIST *r_t,
for (i = 0; i < num_doms; i++) {
fstring domain_name;
fstrcpy(domain_name, dom_name);
- strupper(domain_name);
+ strupper_m(domain_name);
init_unistr2(&r_t->uni_trust_dom_name[i], domain_name, strlen(domain_name)+1);
/* the use of UNISTR2 here is non-standard. */
r_t->uni_trust_dom_name[i].undoc = 0x1;
@@ -1294,7 +1294,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
int len_logon_srv = strlen(logon_srv);
int len_logon_dom = strlen(logon_dom);
- len_user_name = strlen(user_name );
+ len_user_name = strlen(user_name );
len_full_name = strlen(full_name );
len_home_dir = strlen(home_dir );
len_dir_drive = strlen(dir_drive );
@@ -1306,6 +1306,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
usr->ptr_user_info = 1; /* yes, we're bothering to put USER_INFO data here */
+
/* Create NTTIME structs */
unix_to_nt_time (&logon_time, unix_logon_time);
@@ -1808,9 +1809,9 @@ static BOOL net_io_sam_domain_info(const char *desc, SAM_DOMAIN_INFO * info,
if (!smb_io_unihdr("hdr_unknown", &info->hdr_unknown, ps, depth))
return False;
- if (prs_offset(ps) + 40 > prs_data_size(ps))
+ if (ps->data_offset + 40 > ps->buffer_size)
return False;
- prs_set_offset(ps, prs_offset(ps) + 40);
+ ps->data_offset += 40;
if (!smb_io_unistr2("uni_dom_name", &info->uni_dom_name,
info->hdr_dom_name.buffer, ps, depth))
@@ -1847,9 +1848,9 @@ static BOOL net_io_sam_group_info(const char *desc, SAM_GROUP_INFO * info,
if (!smb_io_bufhdr2("hdr_sec_desc", &info->hdr_sec_desc, ps, depth))
return False;
- if (prs_offset(ps) + 48 > prs_data_size(ps))
+ if (ps->data_offset + 48 > ps->buffer_size)
return False;
- prs_set_offset(ps, prs_offset(ps) + 48);
+ ps->data_offset += 48;
if (!smb_io_unistr2("uni_grp_name", &info->uni_grp_name,
info->hdr_grp_name.buffer, ps, depth))
@@ -2128,13 +2129,13 @@ static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16],
uint32 len = 0x44;
if (!prs_uint32("pwd_len", ps, depth, &len))
return False;
- old_offset = prs_offset(ps);
+ old_offset = ps->data_offset;
if (len > 0)
{
if (ps->io)
{
/* reading */
- if (!prs_hash1(ps, prs_offset(ps), sess_key))
+ if (!prs_hash1(ps, ps->data_offset, sess_key, len))
return False;
}
if (!net_io_sam_passwd_info("pass", &info->pass,
@@ -2144,13 +2145,13 @@ static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16],
if (!ps->io)
{
/* writing */
- if (!prs_hash1(ps, old_offset, sess_key))
+ if (!prs_hash1(ps, old_offset, sess_key, len))
return False;
}
}
- if (old_offset + len > prs_data_size(ps))
+ if (old_offset + len > ps->buffer_size)
return False;
- prs_set_offset(ps, old_offset + len);
+ ps->data_offset = old_offset + len;
}
if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc,
info->hdr_sec_desc.buffer, ps, depth))
@@ -2185,9 +2186,9 @@ static BOOL net_io_sam_group_mem_info(const char *desc, SAM_GROUP_MEM_INFO * inf
if (!prs_uint32("num_members", ps, depth, &info->num_members))
return False;
- if (prs_offset(ps) + 16 > prs_data_size(ps))
+ if (ps->data_offset + 16 > ps->buffer_size)
return False;
- prs_set_offset(ps, prs_offset(ps) + 16);
+ ps->data_offset += 16;
if (info->ptr_rids != 0)
{
@@ -2267,9 +2268,9 @@ static BOOL net_io_sam_alias_info(const char *desc, SAM_ALIAS_INFO * info,
if (!smb_io_unihdr("hdr_als_desc", &info->hdr_als_desc, ps, depth))
return False;
- if (prs_offset(ps) + 40 > prs_data_size(ps))
+ if (ps->data_offset + 40 > ps->buffer_size)
return False;
- prs_set_offset(ps, prs_offset(ps) + 40);
+ ps->data_offset += 40;
if (!smb_io_unistr2("uni_als_name", &info->uni_als_name,
info->hdr_als_name.buffer, ps, depth))
@@ -2307,9 +2308,9 @@ static BOOL net_io_sam_alias_mem_info(const char *desc, SAM_ALIAS_MEM_INFO * inf
if (info->ptr_members != 0)
{
- if (prs_offset(ps) + 16 > prs_data_size(ps))
+ if (ps->data_offset + 16 > ps->buffer_size)
return False;
- prs_set_offset(ps, prs_offset(ps) + 16);
+ ps->data_offset += 16;
if (!prs_uint32("num_sids", ps, depth, &info->num_sids))
return False;
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c
index e0a75d7382..efd4914c66 100644
--- a/source3/rpc_parse/parse_prs.c
+++ b/source3/rpc_parse/parse_prs.c
@@ -1316,7 +1316,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])
+BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len)
{
char *q;
@@ -1326,12 +1326,12 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16])
#ifdef DEBUG_PASSWORD
DEBUG(100, ("prs_hash1\n"));
dump_data(100, sess_key, 16);
- dump_data(100, q, 68);
+ dump_data(100, q, len);
#endif
- SamOEMhash((uchar *) q, sess_key, 68);
+ SamOEMhash((uchar *) q, sess_key, len);
#ifdef DEBUG_PASSWORD
- dump_data(100, q, 68);
+ dump_data(100, q, len);
#endif
return True;
@@ -1378,141 +1378,221 @@ static void netsechash(uchar * key, uchar * data, int data_len)
}
}
-void dump_data_pw(const char *msg, const uchar * data, size_t len)
+
+/*******************************************************************
+ Create a digest over the entire packet (including the data), and
+ MD5 it with the session key.
+ ********************************************************************/
+static void netsec_digest(struct netsec_auth_struct *a,
+ int auth_flags,
+ RPC_AUTH_NETSEC_CHK * verf,
+ char *data, size_t data_len,
+ uchar digest_final[16])
{
-#ifdef DEBUG_PASSWORD
- DEBUG(11, ("%s", msg));
- if (data != NULL && len > 0)
- {
- dump_data(11, data, len);
+ uchar whole_packet_digest[16];
+ static uchar zeros[4];
+ struct MD5Context ctx3;
+
+ /* verfiy the signature on the packet by MD5 over various bits */
+ MD5Init(&ctx3);
+ /* use our sequence number, which ensures the packet is not
+ out of order */
+ 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));
}
-#endif
+ MD5Update(&ctx3, data, data_len);
+ MD5Final(whole_packet_digest, &ctx3);
+ dump_data_pw("whole_packet_digest:\n", whole_packet_digest, sizeof(whole_packet_digest));
+
+ /* MD5 this result and the session key, to prove that
+ only a valid client could had produced this */
+ hmac_md5(a->sess_key, whole_packet_digest, sizeof(whole_packet_digest), digest_final);
}
-void netsec_encode(struct netsec_auth_struct *a,
- RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len)
+/*******************************************************************
+ 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,
+ uchar sealing_key[16])
{
- uchar dataN[4];
- uchar digest1[16];
- struct MD5Context ctx3;
+ static uchar zeros[4];
+ uchar digest2[16];
uchar sess_kf0[16];
int i;
- SIVAL(dataN, 0, 0);
-
for (i = 0; i < sizeof(sess_kf0); i++) {
sess_kf0[i] = a->sess_key[i] ^ 0xf0;
}
+
+ dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0));
+
+ /* MD5 of sess_kf0 and the high bytes of the sequence number */
+ hmac_md5(sess_kf0, zeros, 0x4, digest2);
+ dump_data_pw("digest2:\n", digest2, sizeof(digest2));
+
+ /* MD5 of the above result, plus 8 bytes of sequence number */
+ hmac_md5(digest2, verf->seq_num, sizeof(verf->seq_num), sealing_key);
+ dump_data_pw("sealing_key:\n", sealing_key, 16);
+}
- 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));
+/*******************************************************************
+ 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 uchar zeros[4];
+ uchar sequence_key[16];
+ uchar digest1[16];
- MD5Init(&ctx3);
- MD5Update(&ctx3, dataN, 0x4);
- MD5Update(&ctx3, verf->sig, 8);
+ hmac_md5(a->sess_key, zeros, sizeof(zeros), digest1);
+ dump_data_pw("(sequence key) digest1:\n", digest1, sizeof(digest1));
- MD5Update(&ctx3, verf->data8, 8);
+ hmac_md5(digest1, verf->packet_digest, 8, sequence_key);
- dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8));
- dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0));
+ dump_data_pw("sequence_key:\n", sequence_key, sizeof(sequence_key));
- hmac_md5(sess_kf0, dataN, 0x4, digest1);
- dump_data_pw("digest1 (ebp-8):\n", digest1, sizeof(digest1));
- hmac_md5(digest1, verf->data3, 8, digest1);
- dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1));
- netsechash(digest1, verf->data8, 8);
+ dump_data_pw("seq_num (before):\n", verf->seq_num, sizeof(verf->seq_num));
+ netsechash(sequence_key, verf->seq_num, 8);
+ dump_data_pw("seq_num (after):\n", verf->seq_num, sizeof(verf->seq_num));
+}
- dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8));
- dump_data_pw("data :\n", data, data_len);
- MD5Update(&ctx3, data, data_len);
+/*******************************************************************
+ Encode a blob of data using the netsec (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, char *data, size_t data_len)
+{
+ uchar digest_final[16];
- {
- char digest_tmp[16];
- char digest2[16];
- MD5Final(digest_tmp, &ctx3);
- hmac_md5(a->sess_key, digest_tmp, 16, digest2);
- dump_data_pw("digest_tmp:\n", digest_tmp, sizeof(digest_tmp));
- dump_data_pw("digest:\n", digest2, sizeof(digest2));
- memcpy(verf->data1, digest2, sizeof(verf->data1));
+ 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));
+
+ RSIVAL(verf->seq_num, 0, a->seq_num);
+
+ switch (direction) {
+ case SENDER_IS_INITIATOR:
+ SIVAL(verf->seq_num, 4, 0x80);
+ break;
+ case SENDER_IS_ACCEPTOR:
+ SIVAL(verf->seq_num, 4, 0x0);
+ break;
}
- netsechash(digest1, data, data_len);
- dump_data_pw("data:\n", data, data_len);
+ dump_data_pw("verf->seq_num:\n", verf->seq_num, sizeof(verf->seq_num));
- hmac_md5(a->sess_key, dataN, 0x4, digest1);
- dump_data_pw("ctx:\n", digest1, sizeof(digest1));
+ /* 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));
- hmac_md5(digest1, verf->data1, 8, digest1);
+ if (auth_flags & AUTH_PIPE_SEAL) {
+ uchar sealing_key[16];
- dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1));
+ /* get the key to encode the data with */
+ netsec_get_sealing_key(a, verf, sealing_key);
- dump_data_pw("verf->data3:\n", verf->data3, sizeof(verf->data3));
- netsechash(digest1, verf->data3, 8);
- dump_data_pw("verf->data3:\n", verf->data3, sizeof(verf->data3));
+ /* 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->data8_enc:\n", verf->data8, sizeof(verf->data8));
+
+ /* encode the packet payload */
+ dump_data_pw("data:\n", data, data_len);
+ netsechash(sealing_key, data, data_len);
+ dump_data_pw("data_enc:\n", data, data_len);
+ }
+
+ /* 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);
return;
}
-BOOL netsec_decode(struct netsec_auth_struct *a,
+/*******************************************************************
+ Decode a blob of data using the netsec (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)
{
- uchar dataN[4];
- uchar digest1[16];
- struct MD5Context ctx3;
- uchar sess_kf0[16];
- int i;
-
- SIVAL(dataN, 0, 0);
-
- for (i = 0; i < sizeof(sess_kf0); i++) {
- sess_kf0[i] = a->sess_key[i] ^ 0xf0;
+ uchar digest_final[16];
+
+ /* Create the expected sequence number for comparison */
+ uchar seq_num[8];
+ RSIVAL(seq_num, 0, a->seq_num);
+
+ switch (direction) {
+ case SENDER_IS_INITIATOR:
+ SIVAL(seq_num, 4, 0x80);
+ break;
+ case SENDER_IS_ACCEPTOR:
+ SIVAL(seq_num, 4, 0x0);
+ break;
}
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);
- dump_data_pw("ctx:\n", digest1, sizeof(digest1));
-
- hmac_md5(digest1, verf->data1, 8, digest1);
-
- dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1));
- dump_data_pw("verf->data3:\n", verf->data3, sizeof(verf->data3));
- netsechash(digest1, verf->data3, 8);
- dump_data_pw("verf->data3_dec:\n", verf->data3, sizeof(verf->data3));
-
- MD5Init(&ctx3);
- MD5Update(&ctx3, dataN, 0x4);
- MD5Update(&ctx3, verf->sig, 8);
-
- dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0));
- hmac_md5(sess_kf0, dataN, 0x4, digest1);
- dump_data_pw("digest1 (ebp-8):\n", digest1, sizeof(digest1));
- hmac_md5(digest1, verf->data3, 8, digest1);
- dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1));
+ dump_data_pw("seq_num:\n", seq_num, sizeof(seq_num));
- dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8));
- netsechash(digest1, verf->data8, 8);
- dump_data_pw("verf->data8_dec:\n", verf->data8, sizeof(verf->data8));
- MD5Update(&ctx3, verf->data8, 8);
+ /* 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);
- dump_data_pw("data :\n", data, data_len);
- netsechash(digest1, data, data_len);
- dump_data_pw("datadec:\n", data, data_len);
+ if (memcmp(verf->seq_num, seq_num, sizeof(seq_num))) {
+ /* don't even bother with the below if the sequence number is out */
+ /* The sequence number is MD5'ed with a key based on the whole-packet
+ digest, as supplied by the client. We check that it's a valid
+ checksum after the decode, below
+ */
+ return False;
+ }
- MD5Update(&ctx3, data, data_len);
- {
- uchar digest_tmp[16];
- MD5Final(digest_tmp, &ctx3);
- hmac_md5(a->sess_key, digest_tmp, 16, digest1);
- dump_data_pw("digest_tmp:\n", digest_tmp, sizeof(digest_tmp));
+ if (auth_flags & AUTH_PIPE_SEAL) {
+ uchar sealing_key[16];
+
+ /* get the key to extract the data with */
+ 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->data8_dec:\n", verf->data8,
+ sizeof(verf->data8));
+
+ /* extract the packet payload */
+ dump_data_pw("data :\n", data, data_len);
+ netsechash(sealing_key, data, data_len);
+ dump_data_pw("datadec:\n", data, data_len);
}
- dump_data_pw("digest:\n", digest1, sizeof(digest1));
- dump_data_pw("verf->data1:\n", verf->data1, sizeof(verf->data1));
+ /* digest includes 'data' after unsealing */
+ netsec_digest(a, auth_flags, verf, data, data_len, digest_final);
- return memcmp(digest1, verf->data1, sizeof(verf->data1)) == 0;
+ dump_data_pw("Calculated digest:\n", digest_final,
+ sizeof(digest_final));
+ dump_data_pw("verf->packet_digest:\n", verf->packet_digest,
+ sizeof(verf->packet_digest));
+
+ /* compare - if the client got the same result as us, then
+ it must know the session key */
+ return (memcmp(digest_final, verf->packet_digest,
+ sizeof(verf->packet_digest)) == 0);
}
diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c
index be3a04e31c..34ba62caa9 100644
--- a/source3/rpc_parse/parse_rpc.c
+++ b/source3/rpc_parse/parse_rpc.c
@@ -603,15 +603,6 @@ BOOL smb_io_rpc_hdr_autha(const char *desc, RPC_HDR_AUTHA *rai, prs_struct *ps,
}
/*******************************************************************
- Checks an RPC_HDR_AUTH structure.
-********************************************************************/
-
-BOOL rpc_hdr_auth_chk(RPC_HDR_AUTH *rai)
-{
- return (rai->auth_type == NTLMSSP_AUTH_TYPE && rai->auth_level == NTLMSSP_AUTH_LEVEL);
-}
-
-/*******************************************************************
Inits an RPC_HDR_AUTH structure.
********************************************************************/
@@ -1088,9 +1079,10 @@ BOOL rpc_auth_ntlmssp_chk(RPC_AUTH_NTLMSSP_CHK *chk, uint32 crc32, uint32 seq_nu
chk->seq_num != seq_num)
{
DEBUG(5,("verify failed - crc %x ver %x seq %d\n",
- crc32, NTLMSSP_SIGN_VERSION, seq_num));
+ chk->crc32, chk->ver, chk->seq_num));
+
DEBUG(5,("verify expect - crc %x ver %x seq %d\n",
- chk->crc32, chk->ver, chk->seq_num));
+ crc32, NTLMSSP_SIGN_VERSION, seq_num));
return False;
}
return True;
@@ -1182,15 +1174,15 @@ creates an RPC_AUTH_NETSEC_CHK structure.
********************************************************************/
BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk,
const uchar sig[8],
- const uchar data1[8],
- const uchar data3[8], const uchar data8[8])
+ const uchar packet_digest[8],
+ const uchar seq_num[8], const uchar data8[8])
{
if (chk == NULL)
return False;
memcpy(chk->sig, sig, sizeof(chk->sig));
- memcpy(chk->data1, data1, sizeof(chk->data1));
- memcpy(chk->data3, data3, sizeof(chk->data3));
+ 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));
return True;
@@ -1209,8 +1201,8 @@ BOOL smb_io_rpc_auth_netsec_chk(const char *desc, RPC_AUTH_NETSEC_CHK * chk,
depth++;
prs_uint8s(False, "sig ", ps, depth, chk->sig, sizeof(chk->sig));
- prs_uint8s(False, "data3", ps, depth, chk->data3, sizeof(chk->data3));
- prs_uint8s(False, "data1", ps, depth, chk->data1, sizeof(chk->data1));
+ 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));
return True;
diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c
index ac1e9da61b..45c81deb89 100644
--- a/source3/rpc_parse/parse_samr.c
+++ b/source3/rpc_parse/parse_samr.c
@@ -1500,7 +1500,7 @@ inits a SAM_DISPINFO_1 structure.
********************************************************************/
NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_entries,
- uint32 start_idx, DISP_USER_INFO *disp_user_info,
+ uint32 start_idx, SAM_ACCOUNT *disp_user_info,
DOM_SID *domain_sid)
{
uint32 len_sam_name, len_sam_full, len_sam_desc;
@@ -1535,7 +1535,7 @@ NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_en
DEBUG(11, ("init_sam_dispinfo_1: entry: %d\n",i));
- pwd=disp_user_info[i+start_idx].sam;
+ pwd=&disp_user_info[i+start_idx];
username = pdb_get_username(pwd);
fullname = pdb_get_fullname(pwd);
@@ -1635,7 +1635,7 @@ inits a SAM_DISPINFO_2 structure.
********************************************************************/
NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 num_entries,
- uint32 start_idx, DISP_USER_INFO *disp_user_info,
+ uint32 start_idx, SAM_ACCOUNT *disp_user_info,
DOM_SID *domain_sid )
{
uint32 len_sam_name, len_sam_desc;
@@ -1666,7 +1666,7 @@ NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 num_en
fstring user_sid_string, domain_sid_string;
DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i));
- pwd=disp_user_info[i+start_idx].sam;
+ pwd=&disp_user_info[i+start_idx];
username = pdb_get_username(pwd);
acct_desc = pdb_get_acct_desc(pwd);
@@ -1754,7 +1754,7 @@ inits a SAM_DISPINFO_3 structure.
********************************************************************/
NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 num_entries,
- uint32 start_idx, DISP_GROUP_INFO *disp_group_info)
+ uint32 start_idx, DOMAIN_GRP *disp_group_info)
{
uint32 len_sam_name, len_sam_desc;
uint32 i;
@@ -1776,7 +1776,7 @@ NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 num_en
ZERO_STRUCTP(sam->str);
for (i = 0; i < num_entries; i++) {
- DOMAIN_GRP *grp = disp_group_info[i+start_idx].grp;
+ DOMAIN_GRP *grp = &disp_group_info[i+start_idx];
DEBUG(11, ("init_sam_dispinfo_3: entry: %d\n",i));
@@ -1848,7 +1848,7 @@ inits a SAM_DISPINFO_4 structure.
********************************************************************/
NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 *sam, uint32 num_entries,
- uint32 start_idx, DISP_USER_INFO *disp_user_info)
+ uint32 start_idx, SAM_ACCOUNT *disp_user_info)
{
uint32 len_sam_name;
uint32 i;
@@ -1872,7 +1872,7 @@ NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 *sam, uint32 num_en
for (i = 0; i < num_entries; i++) {
DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i));
- pwd=disp_user_info[i+start_idx].sam;
+ pwd=&disp_user_info[i+start_idx];
len_sam_name = strlen(pdb_get_username(pwd));
@@ -1939,7 +1939,7 @@ inits a SAM_DISPINFO_5 structure.
********************************************************************/
NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 *sam, uint32 num_entries,
- uint32 start_idx, DISP_GROUP_INFO *disp_group_info)
+ uint32 start_idx, DOMAIN_GRP *disp_group_info)
{
uint32 len_sam_name;
uint32 i;
@@ -1961,7 +1961,7 @@ NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 *sam, uint32 num_en
ZERO_STRUCTP(sam->str);
for (i = 0; i < num_entries; i++) {
- DOMAIN_GRP *grp = disp_group_info[i+start_idx].grp;
+ DOMAIN_GRP *grp = &disp_group_info[i+start_idx];
DEBUG(11, ("init_sam_dispinfo_5: entry: %d\n",i));
@@ -4598,7 +4598,6 @@ BOOL samr_io_r_query_aliasmem(const char *desc, SAMR_R_QUERY_ALIASMEM * r_u,
prs_struct *ps, int depth)
{
uint32 i;
- uint32 ptr_sid[MAX_LOOKUP_SIDS];
if (r_u == NULL)
return False;
@@ -4614,28 +4613,31 @@ BOOL samr_io_r_query_aliasmem(const char *desc, SAMR_R_QUERY_ALIASMEM * r_u,
if(!prs_uint32("ptr", ps, depth, &r_u->ptr))
return False;
- if (r_u->ptr != 0) {
- SMB_ASSERT_ARRAY(ptr_sid, r_u->num_sids);
-
- if (r_u->num_sids != 0) {
- if(!prs_uint32("num_sids1", ps, depth, &r_u->num_sids1))
- return False;
-
- for (i = 0; i < r_u->num_sids1; i++) {
- ptr_sid[i] = 1;
- if(!prs_uint32("ptr_sid", ps, depth, &ptr_sid[i]))
- return False;
- }
+ if (r_u->ptr != 0 && r_u->num_sids != 0) {
+ uint32 *ptr_sid = NULL;
- if (UNMARSHALLING(ps)) {
- r_u->sid = talloc(ps->mem_ctx, r_u->num_sids1 * sizeof(DOM_SID2));
- }
+ if(!prs_uint32("num_sids1", ps, depth, &r_u->num_sids1))
+ return False;
- for (i = 0; i < r_u->num_sids1; i++) {
- if (ptr_sid[i] != 0) {
- if(!smb_io_dom_sid2("sid", &r_u->sid[i], ps, depth))
- return False;
- }
+ ptr_sid = talloc(ps->mem_ctx, sizeof(uint32) * r_u->num_sids1);
+ if (!ptr_sid) {
+ return False;
+ }
+
+ for (i = 0; i < r_u->num_sids1; i++) {
+ ptr_sid[i] = 1;
+ if(!prs_uint32("ptr_sid", ps, depth, &ptr_sid[i]))
+ return False;
+ }
+
+ if (UNMARSHALLING(ps)) {
+ r_u->sid = talloc(ps->mem_ctx, r_u->num_sids1 * sizeof(DOM_SID2));
+ }
+
+ for (i = 0; i < r_u->num_sids1; i++) {
+ if (ptr_sid[i] != 0) {
+ if(!smb_io_dom_sid2("sid", &r_u->sid[i], ps, depth))
+ return False;
}
}
}
diff --git a/source3/rpc_parse/parse_sec.c b/source3/rpc_parse/parse_sec.c
index 081173cf8d..3848bd7051 100644
--- a/source3/rpc_parse/parse_sec.c
+++ b/source3/rpc_parse/parse_sec.c
@@ -3,7 +3,7 @@
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1998,
- * Copyright (C) Jeremy R. Allison 1995-1998
+ * Copyright (C) Jeremy R. Allison 1995-2003.
* Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
* Copyright (C) Paul Ashton 1997-1998.
*
@@ -48,7 +48,7 @@ BOOL sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
prs_debug(ps, depth, desc, "sec_io_access");
depth++;
- if(!prs_uint32("mask", ps, depth, &(t->mask)))
+ if(!prs_uint32("mask", ps, depth, &t->mask))
return False;
return True;
@@ -579,8 +579,6 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision,
{
SEC_DESC *dst;
uint32 offset = 0;
- uint32 offset_sid = SEC_DESC_HEADER_SIZE;
- uint32 offset_acl = 0;
*sd_size = 0;
@@ -610,58 +608,33 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision,
if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
goto error_exit;
- offset = 0;
+ offset = SEC_DESC_HEADER_SIZE;
/*
* Work out the linearization sizes.
*/
- if (dst->owner_sid != NULL) {
-
- if (offset == 0)
- offset = SEC_DESC_HEADER_SIZE;
-
- offset += sid_size(dst->owner_sid);
- }
-
- if (dst->grp_sid != NULL) {
-
- if (offset == 0)
- offset = SEC_DESC_HEADER_SIZE;
-
- offset += sid_size(dst->grp_sid);
- }
if (dst->sacl != NULL) {
-
- offset_acl = SEC_DESC_HEADER_SIZE;
-
- dst->off_sacl = offset_acl;
- offset_acl += dst->sacl->size;
- offset += dst->sacl->size;
- offset_sid += dst->sacl->size;
+ dst->off_sacl = offset;
+ offset += dst->sacl->size;
}
if (dst->dacl != NULL) {
-
- if (offset_acl == 0)
- offset_acl = SEC_DESC_HEADER_SIZE;
-
- dst->off_dacl = offset_acl;
- offset_acl += dst->dacl->size;
- offset += dst->dacl->size;
- offset_sid += dst->dacl->size;
+ dst->off_dacl = offset;
+ offset += dst->dacl->size;
}
- *sd_size = (size_t)((offset == 0) ? SEC_DESC_HEADER_SIZE : offset);
+ if (dst->owner_sid != NULL) {
+ dst->off_owner_sid = offset;
+ offset += sid_size(dst->owner_sid);
+ }
- if (dst->owner_sid != NULL)
- dst->off_owner_sid = offset_sid;
-
- /* sid_size() returns 0 if the sid is NULL so this is ok */
-
- if (dst->grp_sid != NULL)
- dst->off_grp_sid = offset_sid + sid_size(dst->owner_sid);
+ if (dst->grp_sid != NULL) {
+ dst->off_grp_sid = offset;
+ offset += sid_size(dst->grp_sid);
+ }
+ *sd_size = (size_t)offset;
return dst;
error_exit:
@@ -928,7 +901,7 @@ BOOL sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int
}
/*******************************************************************
- adds new SID with its permissions to SEC_DESC
+ Add a new SID with its permissions to SEC_DESC.
********************************************************************/
NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
@@ -940,7 +913,8 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32
*sd_size = 0;
- if (!ctx || !psd || !sid || !sd_size) return NT_STATUS_INVALID_PARAMETER;
+ if (!ctx || !psd || !sid || !sd_size)
+ return NT_STATUS_INVALID_PARAMETER;
status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask);
@@ -960,14 +934,15 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32
}
/*******************************************************************
- modify SID's permissions at SEC_DESC
+ Modify a SID's permissions in a SEC_DESC.
********************************************************************/
NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
{
NTSTATUS status;
- if (!sd || !sid) return NT_STATUS_INVALID_PARAMETER;
+ if (!sd || !sid)
+ return NT_STATUS_INVALID_PARAMETER;
status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask);
@@ -978,7 +953,7 @@ NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
}
/*******************************************************************
- delete SID from SEC_DESC
+ Delete a SID from a SEC_DESC.
********************************************************************/
NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
@@ -990,7 +965,8 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t
*sd_size = 0;
- if (!ctx || !psd[0] || !sid || !sd_size) return NT_STATUS_INVALID_PARAMETER;
+ if (!ctx || !psd[0] || !sid || !sd_size)
+ return NT_STATUS_INVALID_PARAMETER;
status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid);
@@ -1008,3 +984,108 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t
sd = 0;
return NT_STATUS_OK;
}
+
+/*******************************************************************
+ Comparison function to sort non-inherited first.
+*******************************************************************/
+
+static int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2)
+{
+ int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE;
+ int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE;
+
+ if (a1_inh == a2_inh)
+ return 0;
+
+ if (!a1_inh && a2_inh)
+ return -1;
+ return 1;
+}
+
+/*******************************************************************
+ Comparison function to apply the order explained below in a group.
+*******************************************************************/
+
+static int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2)
+{
+ if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
+ (a2->type != SEC_ACE_TYPE_ACCESS_DENIED))
+ return -1;
+
+ if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
+ (a1->type != SEC_ACE_TYPE_ACCESS_DENIED))
+ return 1;
+
+ /* Both access denied or access allowed. */
+
+ /* 1. ACEs that apply to the object itself */
+
+ if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
+ (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY))
+ return -1;
+ else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
+ (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY))
+ return 1;
+
+ /* 2. ACEs that apply to a subobject of the object, such as
+ * a property set or property. */
+
+ if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
+ !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
+ return -1;
+ else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
+ !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
+ return 1;
+
+ return 0;
+}
+
+/*******************************************************************
+ Functions to convert a SEC_DESC ACE DACL list into canonical order.
+ JRA.
+
+--- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp
+
+The following describes the preferred order:
+
+ To ensure that noninherited ACEs have precedence over inherited ACEs,
+ place all noninherited ACEs in a group before any inherited ACEs.
+ This ordering ensures, for example, that a noninherited access-denied ACE
+ is enforced regardless of any inherited ACE that allows access.
+
+ Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows:
+ 1. Access-denied ACEs that apply to the object itself
+ 2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property
+ 3. Access-allowed ACEs that apply to the object itself
+ 4. Access-allowed ACEs that apply to a subobject of the object"
+
+********************************************************************/
+
+void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces)
+{
+ unsigned int i;
+
+ if (!srclist || num_aces == 0)
+ return;
+
+ /* Sort so that non-inherited ACE's come first. */
+ qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp);
+
+ /* Find the boundary between non-inherited ACEs. */
+ for (i = 0; i < num_aces; i++ ) {
+ SEC_ACE *curr_ace = &srclist[i];
+
+ if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE)
+ break;
+ }
+
+ /* i now points at entry number of the first inherited ACE. */
+
+ /* Sort the non-inherited ACEs. */
+ if (i)
+ qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
+
+ /* Now sort the inherited ACEs. */
+ if (num_aces - i)
+ qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
+}
diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c
index a5d2087a3a..1a380c64d5 100644
--- a/source3/rpc_parse/parse_spoolss.c
+++ b/source3/rpc_parse/parse_spoolss.c
@@ -645,7 +645,7 @@ static BOOL spool_io_user_level(const char *desc, SPOOL_USER_CTR *q_u, prs_struc
BOOL spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE *devmode)
{
- uint32 available_space; /* size of the device mode left to parse */
+ int available_space; /* size of the device mode left to parse */
/* only important on unmarshalling */
int i = 0;
@@ -7296,15 +7296,14 @@ static BOOL spoolss_io_printer_enum_values_ctr(const char *desc, prs_struct *ps,
if (!prs_unistr("valuename", ps, depth, &ctr->values[i].valuename))
return False;
- if (UNMARSHALLING(ps)) {
+ if (UNMARSHALLING(ps) && ctr->values[i].data_len) {
ctr->values[i].data = (uint8 *)prs_alloc_mem(
ps, ctr->values[i].data_len);
if (!ctr->values[i].data)
return False;
+ if (!prs_uint8s(False, "data", ps, depth, ctr->values[i].data, ctr->values[i].data_len))
+ return False;
}
-
- if (!prs_uint8s(False, "data", ps, depth, ctr->values[i].data, ctr->values[i].data_len))
- return False;
if ( !prs_align_uint16(ps) )
return False;
diff --git a/source3/rpc_parse/parse_srv.c b/source3/rpc_parse/parse_srv.c
index 27763aa224..bbb5193ddc 100644
--- a/source3/rpc_parse/parse_srv.c
+++ b/source3/rpc_parse/parse_srv.c
@@ -623,7 +623,8 @@ static BOOL srv_io_share_info1005(const char* desc, SRV_SHARE_INFO_1005* sh1005,
if(!prs_align(ps))
return False;
- if(!prs_uint32("dfs_root_flag", ps, depth, &sh1005->dfs_root_flag))
+ if(!prs_uint32("share_info_flags", ps, depth,
+ &sh1005->share_info_flags))
return False;
return True;