1/* 2 * Unix SMB/Netbios implementation. 3 * Version 1.9. 4 * RPC Pipe client / server routines 5 * Copyright (C) Andrew Tridgell 1992-1998, 6 * Copyright (C) Jeremy R. Allison 1995-2005. 7 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, 8 * Copyright (C) Paul Ashton 1997-1998. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 */ 24 25#include "includes.h" 26 27#undef DBGC_CLASS 28#define DBGC_CLASS DBGC_RPC_PARSE 29 30/******************************************************************* 31 Reads or writes a SEC_ACE structure. 32********************************************************************/ 33 34BOOL sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth) 35{ 36 uint32 old_offset; 37 uint32 offset_ace_size; 38 39 if (psa == NULL) 40 return False; 41 42 prs_debug(ps, depth, desc, "sec_io_ace"); 43 depth++; 44 45 old_offset = prs_offset(ps); 46 47 if(!prs_uint8("type ", ps, depth, &psa->type)) 48 return False; 49 50 if(!prs_uint8("flags", ps, depth, &psa->flags)) 51 return False; 52 53 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size)) 54 return False; 55 56 if (!prs_uint32("access_mask", ps, depth, &psa->access_mask)) 57 return False; 58 59 /* check whether object access is present */ 60 if (!sec_ace_object(psa->type)) { 61 if (!smb_io_dom_sid("trustee ", &psa->trustee , ps, depth)) 62 return False; 63 } else { 64 if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags)) 65 return False; 66 67 if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT) 68 if (!smb_io_uuid("obj_guid", &psa->obj_guid, ps,depth)) 69 return False; 70 71 if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT) 72 if (!smb_io_uuid("inh_guid", &psa->inh_guid, ps,depth)) 73 return False; 74 75 if(!smb_io_dom_sid("trustee ", &psa->trustee , ps, depth)) 76 return False; 77 } 78 79 /* Theorectically an ACE can have a size greater than the 80 sum of its components. When marshalling, pad with extra null bytes up to the 81 correct size. */ 82 83 if (MARSHALLING(ps) && (psa->size > prs_offset(ps) - old_offset)) { 84 uint32 extra_len = psa->size - (prs_offset(ps) - old_offset); 85 uint32 i; 86 uint8 c = 0; 87 88 for (i = 0; i < extra_len; i++) { 89 if (!prs_uint8("ace extra space", ps, depth, &c)) 90 return False; 91 } 92 } 93 94 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset)) 95 return False; 96 97 return True; 98} 99 100/******************************************************************* 101 Reads or writes a SEC_ACL structure. 102 103 First of the xx_io_xx functions that allocates its data structures 104 for you as it reads them. 105********************************************************************/ 106 107BOOL sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth) 108{ 109 unsigned int i; 110 uint32 old_offset; 111 uint32 offset_acl_size; 112 SEC_ACL *psa; 113 114 /* 115 * Note that the size is always a multiple of 4 bytes due to the 116 * nature of the data structure. Therefore the prs_align() calls 117 * have been removed as they through us off when doing two-layer 118 * marshalling such as in the printing code (RPC_BUFFER). --jerry 119 */ 120 121 if (ppsa == NULL) 122 return False; 123 124 psa = *ppsa; 125 126 if(UNMARSHALLING(ps) && psa == NULL) { 127 /* 128 * This is a read and we must allocate the stuct to read into. 129 */ 130 if((psa = PRS_ALLOC_MEM(ps, SEC_ACL, 1)) == NULL) 131 return False; 132 *ppsa = psa; 133 } 134 135 prs_debug(ps, depth, desc, "sec_io_acl"); 136 depth++; 137 138 old_offset = prs_offset(ps); 139 140 if(!prs_uint16("revision", ps, depth, &psa->revision)) 141 return False; 142 143 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_acl_size)) 144 return False; 145 146 if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces)) 147 return False; 148 149 if (UNMARSHALLING(ps)) { 150 if (psa->num_aces) { 151 if((psa->aces = PRS_ALLOC_MEM(ps, SEC_ACE, psa->num_aces)) == NULL) 152 return False; 153 } else { 154 psa->aces = NULL; 155 } 156 } 157 158 for (i = 0; i < psa->num_aces; i++) { 159 fstring tmp; 160 slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i); 161 if(!sec_io_ace(tmp, &psa->aces[i], ps, depth)) 162 return False; 163 } 164 165 /* Theorectically an ACL can have a size greater than the 166 sum of its components. When marshalling, pad with extra null bytes up to the 167 correct size. */ 168 169 if (MARSHALLING(ps) && (psa->size > prs_offset(ps) - old_offset)) { 170 uint32 extra_len = psa->size - (prs_offset(ps) - old_offset); 171 uint8 c = 0; 172 173 for (i = 0; i < extra_len; i++) { 174 if (!prs_uint8("acl extra space", ps, depth, &c)) 175 return False; 176 } 177 } 178 179 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_acl_size, old_offset)) 180 return False; 181 182 return True; 183} 184 185/******************************************************************* 186 Reads or writes a SEC_DESC structure. 187 If reading and the *ppsd = NULL, allocates the structure. 188********************************************************************/ 189 190BOOL sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth) 191{ 192 uint32 old_offset; 193 uint32 max_offset = 0; /* after we're done, move offset to end */ 194 uint32 tmp_offset = 0; 195 196 SEC_DESC *psd; 197 198 if (ppsd == NULL) 199 return False; 200 201 psd = *ppsd; 202 203 if (psd == NULL) { 204 if(UNMARSHALLING(ps)) { 205 if((psd = PRS_ALLOC_MEM(ps,SEC_DESC,1)) == NULL) 206 return False; 207 *ppsd = psd; 208 } else { 209 /* Marshalling - just ignore. */ 210 return True; 211 } 212 } 213 214 prs_debug(ps, depth, desc, "sec_io_desc"); 215 depth++; 216 217 /* start of security descriptor stored for back-calc offset purposes */ 218 old_offset = prs_offset(ps); 219 220 if(!prs_uint16("revision ", ps, depth, &psd->revision)) 221 return False; 222 223 if(!prs_uint16("type ", ps, depth, &psd->type)) 224 return False; 225 226 if (MARSHALLING(ps)) { 227 uint32 offset = SEC_DESC_HEADER_SIZE; 228 229 /* 230 * Work out the offsets here, as we write it out. 231 */ 232 233 if (psd->sacl != NULL) { 234 psd->off_sacl = offset; 235 offset += psd->sacl->size; 236 } else { 237 psd->off_sacl = 0; 238 } 239 240 if (psd->dacl != NULL) { 241 psd->off_dacl = offset; 242 offset += psd->dacl->size; 243 } else { 244 psd->off_dacl = 0; 245 } 246 247 if (psd->owner_sid != NULL) { 248 psd->off_owner_sid = offset; 249 offset += sid_size(psd->owner_sid); 250 } else { 251 psd->off_owner_sid = 0; 252 } 253 254 if (psd->group_sid != NULL) { 255 psd->off_grp_sid = offset; 256 offset += sid_size(psd->group_sid); 257 } else { 258 psd->off_grp_sid = 0; 259 } 260 } 261 262 if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid)) 263 return False; 264 265 if(!prs_uint32("off_grp_sid ", ps, depth, &psd->off_grp_sid)) 266 return False; 267 268 if(!prs_uint32("off_sacl ", ps, depth, &psd->off_sacl)) 269 return False; 270 271 if(!prs_uint32("off_dacl ", ps, depth, &psd->off_dacl)) 272 return False; 273 274 max_offset = MAX(max_offset, prs_offset(ps)); 275 276 if (psd->off_owner_sid != 0) { 277 278 tmp_offset = prs_offset(ps); 279 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid)) 280 return False; 281 282 if (UNMARSHALLING(ps)) { 283 /* reading */ 284 if((psd->owner_sid = PRS_ALLOC_MEM(ps,DOM_SID,1)) == NULL) 285 return False; 286 } 287 288 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth)) 289 return False; 290 291 max_offset = MAX(max_offset, prs_offset(ps)); 292 293 if (!prs_set_offset(ps,tmp_offset)) 294 return False; 295 } 296 297 if (psd->off_grp_sid != 0) { 298 299 tmp_offset = prs_offset(ps); 300 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid)) 301 return False; 302 303 if (UNMARSHALLING(ps)) { 304 /* reading */ 305 if((psd->group_sid = PRS_ALLOC_MEM(ps,DOM_SID,1)) == NULL) 306 return False; 307 } 308 309 if(!smb_io_dom_sid("group_sid", psd->group_sid, ps, depth)) 310 return False; 311 312 max_offset = MAX(max_offset, prs_offset(ps)); 313 314 if (!prs_set_offset(ps,tmp_offset)) 315 return False; 316 } 317 318 if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) { 319 tmp_offset = prs_offset(ps); 320 if(!prs_set_offset(ps, old_offset + psd->off_sacl)) 321 return False; 322 if(!sec_io_acl("sacl", &psd->sacl, ps, depth)) 323 return False; 324 max_offset = MAX(max_offset, prs_offset(ps)); 325 if (!prs_set_offset(ps,tmp_offset)) 326 return False; 327 } 328 329 if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) { 330 tmp_offset = prs_offset(ps); 331 if(!prs_set_offset(ps, old_offset + psd->off_dacl)) 332 return False; 333 if(!sec_io_acl("dacl", &psd->dacl, ps, depth)) 334 return False; 335 max_offset = MAX(max_offset, prs_offset(ps)); 336 if (!prs_set_offset(ps,tmp_offset)) 337 return False; 338 } 339 340 if(!prs_set_offset(ps, max_offset)) 341 return False; 342 343 return True; 344} 345 346/******************************************************************* 347 Reads or writes a SEC_DESC_BUF structure. 348********************************************************************/ 349 350BOOL sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth) 351{ 352 uint32 off_len; 353 uint32 off_max_len; 354 uint32 old_offset; 355 uint32 size; 356 SEC_DESC_BUF *psdb; 357 358 if (ppsdb == NULL) 359 return False; 360 361 psdb = *ppsdb; 362 363 if (UNMARSHALLING(ps) && psdb == NULL) { 364 if((psdb = PRS_ALLOC_MEM(ps,SEC_DESC_BUF,1)) == NULL) 365 return False; 366 *ppsdb = psdb; 367 } 368 369 prs_debug(ps, depth, desc, "sec_io_desc_buf"); 370 depth++; 371 372 if(!prs_align(ps)) 373 return False; 374 375 if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len)) 376 return False; 377 378 if(!prs_uint32 ("ptr ", ps, depth, &psdb->ptr)) 379 return False; 380 381 if(!prs_uint32_pre("len ", ps, depth, &psdb->len, &off_len)) 382 return False; 383 384 old_offset = prs_offset(ps); 385 386 /* reading, length is non-zero; writing, descriptor is non-NULL */ 387 if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) { 388 if(!sec_io_desc("sec ", &psdb->sec, ps, depth)) 389 return False; 390 } 391 392 if(!prs_align(ps)) 393 return False; 394 395 size = prs_offset(ps) - old_offset; 396 if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size)) 397 return False; 398 399 if(!prs_uint32_post("len ", ps, depth, &psdb->len, off_len, size)) 400 return False; 401 402 return True; 403} 404