diff options
Diffstat (limited to 'source4/librpc/ndr/ndr_sec.c')
-rw-r--r-- | source4/librpc/ndr/ndr_sec.c | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/source4/librpc/ndr/ndr_sec.c b/source4/librpc/ndr/ndr_sec.c new file mode 100644 index 0000000000..31cf823e0d --- /dev/null +++ b/source4/librpc/ndr/ndr_sec.c @@ -0,0 +1,309 @@ +/* + Unix SMB/CIFS implementation. + + routines for marshalling/unmarshalling security descriptors + and related structures + + Copyright (C) Andrew Tridgell 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "includes.h" + +/* + parse a security_ace +*/ +NTSTATUS ndr_pull_security_ace(struct ndr_pull *ndr, struct security_ace *ace) +{ + uint16 size; + struct ndr_pull_save save; + + ndr_pull_save(ndr, &save); + + NDR_CHECK(ndr_pull_uint8(ndr, &ace->type)); + NDR_CHECK(ndr_pull_uint8(ndr, &ace->flags)); + NDR_CHECK(ndr_pull_uint16(ndr, &size)); + NDR_CHECK(ndr_pull_limit_size(ndr, size, 4)); + + NDR_CHECK(ndr_pull_uint32(ndr, &ace->access_mask)); + + if (sec_ace_object(ace->type)) { + NDR_ALLOC(ndr, ace->obj); + NDR_CHECK(ndr_pull_uint32(ndr, &ace->obj->flags)); + if (ace->obj->flags & SEC_ACE_OBJECT_PRESENT) { + NDR_CHECK(ndr_pull_guid(ndr, &ace->obj->object_guid)); + } + if (ace->obj->flags & SEC_ACE_OBJECT_INHERITED_PRESENT) { + NDR_CHECK(ndr_pull_guid(ndr, &ace->obj->inherit_guid)); + } + } + + + NDR_CHECK(ndr_pull_dom_sid(ndr, &ace->trustee)); + + ndr_pull_restore(ndr, &save); + NDR_CHECK(ndr_pull_advance(ndr, size)); + + return NT_STATUS_OK; +} + +/* + parse a security_acl +*/ +NTSTATUS ndr_pull_security_acl(struct ndr_pull *ndr, struct security_acl *acl) +{ + int i; + uint16 size; + struct ndr_pull_save save; + + ndr_pull_save(ndr, &save); + + NDR_CHECK(ndr_pull_uint16(ndr, &acl->revision)); + NDR_CHECK(ndr_pull_uint16(ndr, &size)); + NDR_CHECK(ndr_pull_limit_size(ndr, size, 4)); + NDR_CHECK(ndr_pull_uint32(ndr, &acl->num_aces)); + + NDR_ALLOC_N(ndr, acl->aces, acl->num_aces); + + for (i=0;i<acl->num_aces;i++) { + NDR_CHECK(ndr_pull_security_ace(ndr, &acl->aces[i])); + } + + ndr_pull_restore(ndr, &save); + NDR_CHECK(ndr_pull_advance(ndr, size)); + + return NT_STATUS_OK; +} + +/* + parse a security_acl offset and structure +*/ +NTSTATUS ndr_pull_security_acl_ofs(struct ndr_pull *ndr, struct security_acl **acl) +{ + uint32 ofs; + struct ndr_pull_save save; + + NDR_CHECK(ndr_pull_uint32(ndr, &ofs)); + if (ofs == 0) { + /* it is valid for an acl ptr to be NULL */ + *acl = NULL; + return NT_STATUS_OK; + } + + ndr_pull_save(ndr, &save); + NDR_CHECK(ndr_pull_set_offset(ndr, ofs)); + NDR_ALLOC(ndr, *acl); + NDR_CHECK(ndr_pull_security_acl(ndr, *acl)); + ndr_pull_restore(ndr, &save); + + return NT_STATUS_OK; +} + + +/* + parse a dom_sid +*/ +NTSTATUS ndr_pull_dom_sid(struct ndr_pull *ndr, struct dom_sid *sid) +{ + int i; + + NDR_CHECK(ndr_pull_uint8(ndr, &sid->sid_rev_num)); + NDR_CHECK(ndr_pull_uint8(ndr, &sid->num_auths)); + for (i=0;i<6;i++) { + NDR_CHECK(ndr_pull_uint8(ndr, &sid->id_auth[i])); + } + + NDR_ALLOC_N(ndr, sid->sub_auths, sid->num_auths); + + for (i=0;i<sid->num_auths;i++) { + NDR_CHECK(ndr_pull_uint32(ndr, &sid->sub_auths[i])); + } + + return NT_STATUS_OK; +} + +/* + parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field +*/ +NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, struct dom_sid *sid) +{ + uint32 num_auths; + NDR_CHECK(ndr_pull_uint32(ndr, &num_auths)); + return ndr_pull_dom_sid(ndr, sid); +} + +/* + parse a dom_sid offset and structure +*/ +NTSTATUS ndr_pull_dom_sid_ofs(struct ndr_pull *ndr, struct dom_sid **sid) +{ + uint32 ofs; + struct ndr_pull_save save; + + NDR_CHECK(ndr_pull_uint32(ndr, &ofs)); + if (ofs == 0) { + /* it is valid for a dom_sid ptr to be NULL */ + *sid = NULL; + return NT_STATUS_OK; + } + + ndr_pull_save(ndr, &save); + NDR_CHECK(ndr_pull_set_offset(ndr, ofs)); + NDR_ALLOC(ndr, *sid); + NDR_CHECK(ndr_pull_dom_sid(ndr, *sid)); + ndr_pull_restore(ndr, &save); + + return NT_STATUS_OK; +} + +/* + parse a security descriptor +*/ +NTSTATUS ndr_pull_security_descriptor(struct ndr_pull *ndr, + struct security_descriptor **sd) +{ + NDR_ALLOC(ndr, *sd); + + NDR_CHECK(ndr_pull_uint8(ndr, &(*sd)->revision)); + NDR_CHECK(ndr_pull_uint16(ndr, &(*sd)->type)); + NDR_CHECK(ndr_pull_dom_sid_ofs(ndr, &(*sd)->owner_sid)); + NDR_CHECK(ndr_pull_dom_sid_ofs(ndr, &(*sd)->group_sid)); + NDR_CHECK(ndr_pull_security_acl_ofs(ndr, &(*sd)->sacl)); + NDR_CHECK(ndr_pull_security_acl_ofs(ndr, &(*sd)->dacl)); + + return NT_STATUS_OK; +} + + +/* + parse a security_ace +*/ +NTSTATUS ndr_push_security_ace(struct ndr_push *ndr, struct security_ace *ace) +{ + struct ndr_push_save save1, save2; + + NDR_CHECK(ndr_push_uint8(ndr, ace->type)); + NDR_CHECK(ndr_push_uint8(ndr, ace->flags)); + ndr_push_save(ndr, &save1); + NDR_CHECK(ndr_push_uint16(ndr, 0)); + NDR_CHECK(ndr_push_uint32(ndr, ace->access_mask)); + + if (sec_ace_object(ace->type)) { + NDR_CHECK(ndr_push_uint32(ndr, ace->obj->flags)); + if (ace->obj->flags & SEC_ACE_OBJECT_PRESENT) { + NDR_CHECK(ndr_push_guid(ndr, &ace->obj->object_guid)); + } + if (ace->obj->flags & SEC_ACE_OBJECT_INHERITED_PRESENT) { + NDR_CHECK(ndr_push_guid(ndr, &ace->obj->inherit_guid)); + } + } + + NDR_CHECK(ndr_push_dom_sid(ndr, &ace->trustee)); + + ndr_push_save(ndr, &save2); + ndr_push_restore(ndr, &save1); + NDR_CHECK(ndr_push_uint16(ndr, 2 + save2.offset - save1.offset)); + ndr_push_restore(ndr, &save2); + + return NT_STATUS_OK; +} + + +/* + push a security_acl +*/ +NTSTATUS ndr_push_security_acl(struct ndr_push *ndr, struct security_acl *acl) +{ + int i; + struct ndr_push_save save1, save2; + + NDR_CHECK(ndr_push_uint16(ndr, acl->revision)); + ndr_push_save(ndr, &save1); + NDR_CHECK(ndr_push_uint16(ndr, 0)); + NDR_CHECK(ndr_push_uint32(ndr, acl->num_aces)); + for (i=0;i<acl->num_aces;i++) { + NDR_CHECK(ndr_push_security_ace(ndr, &acl->aces[i])); + } + ndr_push_save(ndr, &save2); + ndr_push_restore(ndr, &save1); + NDR_CHECK(ndr_push_uint16(ndr, 2 + save2.offset - save1.offset)); + ndr_push_restore(ndr, &save2); + + return NT_STATUS_OK; +} + +/* + push a dom_sid +*/ +NTSTATUS ndr_push_dom_sid(struct ndr_push *ndr, struct dom_sid *sid) +{ + int i; + + NDR_CHECK(ndr_push_uint8(ndr, sid->sid_rev_num)); + NDR_CHECK(ndr_push_uint8(ndr, sid->num_auths)); + for (i=0;i<6;i++) { + NDR_CHECK(ndr_push_uint8(ndr, sid->id_auth[i])); + } + for (i=0;i<sid->num_auths;i++) { + NDR_CHECK(ndr_push_uint32(ndr, sid->sub_auths[i])); + } + + return NT_STATUS_OK; +} + + +/* + generate a ndr security descriptor +*/ +NTSTATUS ndr_push_security_descriptor(struct ndr_push *ndr, + struct security_descriptor *sd) +{ + struct ndr_push_save save; + struct ndr_push_save ofs1, ofs2, ofs3, ofs4; + + ndr_push_save(ndr, &save); + + NDR_CHECK(ndr_push_uint8(ndr, sd->revision)); + NDR_CHECK(ndr_push_uint16(ndr, sd->type)); + + NDR_CHECK(ndr_push_offset(ndr, &ofs1)); + NDR_CHECK(ndr_push_offset(ndr, &ofs2)); + NDR_CHECK(ndr_push_offset(ndr, &ofs3)); + NDR_CHECK(ndr_push_offset(ndr, &ofs4)); + + if (sd->owner_sid) { + NDR_CHECK(ndr_push_offset_ptr(ndr, &ofs1, &save)); + NDR_CHECK(ndr_push_dom_sid(ndr, sd->owner_sid)); + } + + if (sd->group_sid) { + NDR_CHECK(ndr_push_offset_ptr(ndr, &ofs2, &save)); + NDR_CHECK(ndr_push_dom_sid(ndr, sd->group_sid)); + } + + if (sd->sacl) { + NDR_CHECK(ndr_push_offset_ptr(ndr, &ofs3, &save)); + NDR_CHECK(ndr_push_security_acl(ndr, sd->sacl)); + } + + if (sd->dacl) { + NDR_CHECK(ndr_push_offset_ptr(ndr, &ofs4, &save)); + NDR_CHECK(ndr_push_security_acl(ndr, sd->dacl)); + } + + return NT_STATUS_OK; +} |