lib/secdesc.c

説明を見る。
00001 /* 
00002  *  Unix SMB/Netbios implementation.
00003  *  SEC_DESC handling functions
00004  *  Copyright (C) Andrew Tridgell              1992-1998,
00005  *  Copyright (C) Jeremy R. Allison            1995-2003.
00006  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
00007  *  Copyright (C) Paul Ashton                  1997-1998.
00008  *  
00009  *  This program is free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *  
00014  *  This program is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *  
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with this program; if not, write to the Free Software
00021  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022  */
00023 
00024 #include "includes.h"
00025 
00026 /* Map generic permissions to file object specific permissions */
00027 
00028 struct generic_mapping file_generic_mapping = {
00029         FILE_GENERIC_READ,
00030         FILE_GENERIC_WRITE,
00031         FILE_GENERIC_EXECUTE,
00032         FILE_GENERIC_ALL
00033 };
00034 
00035 /*******************************************************************
00036  Works out the linearization size of a SEC_DESC.
00037 ********************************************************************/
00038 
00039 size_t sec_desc_size(SEC_DESC *psd)
00040 {
00041         size_t offset;
00042 
00043         if (!psd) return 0;
00044 
00045         offset = SEC_DESC_HEADER_SIZE;
00046 
00047         /* don't align */
00048 
00049         if (psd->owner_sid != NULL)
00050                 offset += sid_size(psd->owner_sid);
00051 
00052         if (psd->group_sid != NULL)
00053                 offset += sid_size(psd->group_sid);
00054 
00055         if (psd->sacl != NULL)
00056                 offset += psd->sacl->size;
00057 
00058         if (psd->dacl != NULL)
00059                 offset += psd->dacl->size;
00060 
00061         return offset;
00062 }
00063 
00064 /*******************************************************************
00065  Compares two SEC_DESC structures
00066 ********************************************************************/
00067 
00068 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
00069 {
00070         /* Trivial case */
00071 
00072         if (!s1 && !s2) {
00073                 goto done;
00074         }
00075 
00076         if (!s1 || !s2) {
00077                 return False;
00078         }
00079 
00080         /* Check top level stuff */
00081 
00082         if (s1->revision != s2->revision) {
00083                 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
00084                            s1->revision, s2->revision));
00085                 return False;
00086         }
00087 
00088         if (s1->type!= s2->type) {
00089                 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
00090                            s1->type, s2->type));
00091                 return False;
00092         }
00093 
00094         /* Check owner and group */
00095 
00096         if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
00097                 fstring str1, str2;
00098 
00099                 sid_to_string(str1, s1->owner_sid);
00100                 sid_to_string(str2, s2->owner_sid);
00101 
00102                 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
00103                            str1, str2));
00104                 return False;
00105         }
00106 
00107         if (!sid_equal(s1->group_sid, s2->group_sid)) {
00108                 fstring str1, str2;
00109 
00110                 sid_to_string(str1, s1->group_sid);
00111                 sid_to_string(str2, s2->group_sid);
00112 
00113                 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
00114                            str1, str2));
00115                 return False;
00116         }
00117 
00118         /* Check ACLs present in one but not the other */
00119 
00120         if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
00121             (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
00122                 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
00123                 return False;
00124         }
00125 
00126         /* Sigh - we have to do it the hard way by iterating over all
00127            the ACEs in the ACLs */
00128 
00129         if (!sec_acl_equal(s1->dacl, s2->dacl) ||
00130             !sec_acl_equal(s1->sacl, s2->sacl)) {
00131                 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
00132                 return False;
00133         }
00134 
00135  done:
00136         DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
00137         return True;
00138 }
00139 
00140 /*******************************************************************
00141  Merge part of security descriptor old_sec in to the empty sections of 
00142  security descriptor new_sec.
00143 ********************************************************************/
00144 
00145 SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
00146 {
00147         DOM_SID *owner_sid, *group_sid;
00148         SEC_DESC_BUF *return_sdb;
00149         SEC_ACL *dacl, *sacl;
00150         SEC_DESC *psd = NULL;
00151         uint16 secdesc_type;
00152         size_t secdesc_size;
00153 
00154         /* Copy over owner and group sids.  There seems to be no flag for
00155            this so just check the pointer values. */
00156 
00157         owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
00158                 old_sdb->sec->owner_sid;
00159 
00160         group_sid = new_sdb->sec->group_sid ? new_sdb->sec->group_sid :
00161                 old_sdb->sec->group_sid;
00162         
00163         secdesc_type = new_sdb->sec->type;
00164 
00165         /* Ignore changes to the system ACL.  This has the effect of making
00166            changes through the security tab audit button not sticking. 
00167            Perhaps in future Samba could implement these settings somehow. */
00168 
00169         sacl = NULL;
00170         secdesc_type &= ~SEC_DESC_SACL_PRESENT;
00171 
00172         /* Copy across discretionary ACL */
00173 
00174         if (secdesc_type & SEC_DESC_DACL_PRESENT) {
00175                 dacl = new_sdb->sec->dacl;
00176         } else {
00177                 dacl = old_sdb->sec->dacl;
00178         }
00179 
00180         /* Create new security descriptor from bits */
00181 
00182         psd = make_sec_desc(ctx, new_sdb->sec->revision, secdesc_type,
00183                             owner_sid, group_sid, sacl, dacl, &secdesc_size);
00184 
00185         return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
00186 
00187         return(return_sdb);
00188 }
00189 
00190 /*******************************************************************
00191  Creates a SEC_DESC structure
00192 ********************************************************************/
00193 
00194 SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type,
00195                         const DOM_SID *owner_sid, const DOM_SID *group_sid,
00196                         SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
00197 {
00198         SEC_DESC *dst;
00199         uint32 offset     = 0;
00200 
00201         *sd_size = 0;
00202 
00203         if(( dst = TALLOC_ZERO_P(ctx, SEC_DESC)) == NULL)
00204                 return NULL;
00205 
00206         dst->revision = revision;
00207         dst->type = type;
00208 
00209         if (sacl)
00210                 dst->type |= SEC_DESC_SACL_PRESENT;
00211         if (dacl)
00212                 dst->type |= SEC_DESC_DACL_PRESENT;
00213 
00214         dst->off_owner_sid = 0;
00215         dst->off_grp_sid   = 0;
00216         dst->off_sacl      = 0;
00217         dst->off_dacl      = 0;
00218 
00219         if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
00220                 goto error_exit;
00221 
00222         if(group_sid && ((dst->group_sid = sid_dup_talloc(ctx,group_sid)) == NULL))
00223                 goto error_exit;
00224 
00225         if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
00226                 goto error_exit;
00227 
00228         if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
00229                 goto error_exit;
00230 
00231         offset = SEC_DESC_HEADER_SIZE;
00232 
00233         /*
00234          * Work out the linearization sizes.
00235          */
00236 
00237         if (dst->sacl != NULL) {
00238                 dst->off_sacl = offset;
00239                 offset += dst->sacl->size;
00240         }
00241         if (dst->dacl != NULL) {
00242                 dst->off_dacl = offset;
00243                 offset += dst->dacl->size;
00244         }
00245 
00246         if (dst->owner_sid != NULL) {
00247                 dst->off_owner_sid = offset;
00248                 offset += sid_size(dst->owner_sid);
00249         }
00250 
00251         if (dst->group_sid != NULL) {
00252                 dst->off_grp_sid = offset;
00253                 offset += sid_size(dst->group_sid);
00254         }
00255 
00256         *sd_size = (size_t)offset;
00257         return dst;
00258 
00259 error_exit:
00260 
00261         *sd_size = 0;
00262         return NULL;
00263 }
00264 
00265 /*******************************************************************
00266  Duplicate a SEC_DESC structure.  
00267 ********************************************************************/
00268 
00269 SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src)
00270 {
00271         size_t dummy;
00272 
00273         if(src == NULL)
00274                 return NULL;
00275 
00276         return make_sec_desc( ctx, src->revision, src->type,
00277                                 src->owner_sid, src->group_sid, src->sacl,
00278                                 src->dacl, &dummy);
00279 }
00280 
00281 /*******************************************************************
00282  Creates a SEC_DESC structure with typical defaults.
00283 ********************************************************************/
00284 
00285 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *group_sid,
00286                                  SEC_ACL *dacl, size_t *sd_size)
00287 {
00288         return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
00289                              owner_sid, group_sid, NULL, dacl, sd_size);
00290 }
00291 
00292 /*******************************************************************
00293  Creates a SEC_DESC_BUF structure.
00294 ********************************************************************/
00295 
00296 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
00297 {
00298         SEC_DESC_BUF *dst;
00299 
00300         if((dst = TALLOC_ZERO_P(ctx, SEC_DESC_BUF)) == NULL)
00301                 return NULL;
00302 
00303         /* max buffer size (allocated size) */
00304         dst->max_len = (uint32)len;
00305         dst->len = (uint32)len;
00306         
00307         if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) {
00308                 return NULL;
00309         }
00310 
00311         dst->ptr = 0x1;
00312 
00313         return dst;
00314 }
00315 
00316 /*******************************************************************
00317  Duplicates a SEC_DESC_BUF structure.
00318 ********************************************************************/
00319 
00320 SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
00321 {
00322         if(src == NULL)
00323                 return NULL;
00324 
00325         return make_sec_desc_buf( ctx, src->len, src->sec);
00326 }
00327 
00328 /*******************************************************************
00329  Add a new SID with its permissions to SEC_DESC.
00330 ********************************************************************/
00331 
00332 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
00333 {
00334         SEC_DESC *sd   = 0;
00335         SEC_ACL  *dacl = 0;
00336         SEC_ACE  *ace  = 0;
00337         NTSTATUS  status;
00338 
00339         if (!ctx || !psd || !sid || !sd_size)
00340                 return NT_STATUS_INVALID_PARAMETER;
00341 
00342         *sd_size = 0;
00343 
00344         status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
00345         
00346         if (!NT_STATUS_IS_OK(status))
00347                 return status;
00348 
00349         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
00350                 return NT_STATUS_UNSUCCESSFUL;
00351         
00352         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
00353                 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
00354                 return NT_STATUS_UNSUCCESSFUL;
00355 
00356         *psd = sd;
00357          sd  = 0;
00358         return NT_STATUS_OK;
00359 }
00360 
00361 /*******************************************************************
00362  Modify a SID's permissions in a SEC_DESC.
00363 ********************************************************************/
00364 
00365 NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
00366 {
00367         NTSTATUS status;
00368 
00369         if (!sd || !sid)
00370                 return NT_STATUS_INVALID_PARAMETER;
00371 
00372         status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
00373 
00374         if (!NT_STATUS_IS_OK(status))
00375                 return status;
00376         
00377         return NT_STATUS_OK;
00378 }
00379 
00380 /*******************************************************************
00381  Delete a SID from a SEC_DESC.
00382 ********************************************************************/
00383 
00384 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
00385 {
00386         SEC_DESC *sd   = 0;
00387         SEC_ACL  *dacl = 0;
00388         SEC_ACE  *ace  = 0;
00389         NTSTATUS  status;
00390 
00391         if (!ctx || !psd[0] || !sid || !sd_size)
00392                 return NT_STATUS_INVALID_PARAMETER;
00393 
00394         *sd_size = 0;
00395         
00396         status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
00397 
00398         if (!NT_STATUS_IS_OK(status))
00399                 return status;
00400 
00401         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
00402                 return NT_STATUS_UNSUCCESSFUL;
00403         
00404         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
00405                 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
00406                 return NT_STATUS_UNSUCCESSFUL;
00407 
00408         *psd = sd;
00409          sd  = 0;
00410         return NT_STATUS_OK;
00411 }
00412 
00413 /* Create a child security descriptor using another security descriptor as
00414    the parent container.  This child object can either be a container or
00415    non-container object. */
00416 
00417 SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
00418                                       BOOL child_container)
00419 {
00420         SEC_DESC_BUF *sdb;
00421         SEC_DESC *sd;
00422         SEC_ACL *new_dacl, *the_acl;
00423         SEC_ACE *new_ace_list = NULL;
00424         unsigned int new_ace_list_ndx = 0, i;
00425         size_t size;
00426 
00427         /* Currently we only process the dacl when creating the child.  The
00428            sacl should also be processed but this is left out as sacls are
00429            not implemented in Samba at the moment.*/
00430 
00431         the_acl = parent_ctr->dacl;
00432 
00433         if (the_acl->num_aces) {
00434                 if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE, the_acl->num_aces))) 
00435                         return NULL;
00436         } else {
00437                 new_ace_list = NULL;
00438         }
00439 
00440         for (i = 0; i < the_acl->num_aces; i++) {
00441                 SEC_ACE *ace = &the_acl->aces[i];
00442                 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
00443                 uint8 new_flags = 0;
00444                 BOOL inherit = False;
00445                 fstring sid_str;
00446 
00447                 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
00448                    inherited by non-container children objects.  Container
00449                    children objects will inherit it as an INHERIT_ONLY
00450                    ACE. */
00451 
00452                 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
00453 
00454                         if (!child_container) {
00455                                 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
00456                         } else {
00457                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
00458                         }
00459 
00460                         inherit = True;
00461                 }
00462 
00463                 /* The CONAINER_INHERIT_ACE flag means all child container
00464                    objects will inherit and use the ACE. */
00465 
00466                 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
00467                         if (!child_container) {
00468                                 inherit = False;
00469                         } else {
00470                                 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
00471                         }
00472                 }
00473 
00474                 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
00475                    function for the parent container, but is inherited by
00476                    all child objects as a normal ACE. */
00477 
00478                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
00479                         /* Move along, nothing to see here */
00480                 }
00481 
00482                 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
00483                    is inherited by child objects but not grandchildren
00484                    objects.  We clear the object inherit and container
00485                    inherit flags in the inherited ACE. */
00486 
00487                 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
00488                         new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
00489                                        SEC_ACE_FLAG_CONTAINER_INHERIT);
00490                 }
00491 
00492                 /* Add ACE to ACE list */
00493 
00494                 if (!inherit)
00495                         continue;
00496 
00497                 init_sec_access(&new_ace->access_mask, ace->access_mask);
00498                 init_sec_ace(new_ace, &ace->trustee, ace->type,
00499                              new_ace->access_mask, new_flags);
00500 
00501                 sid_to_string(sid_str, &ace->trustee);
00502 
00503                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
00504                           " inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
00505                           ace->type, ace->flags, ace->access_mask,
00506                           sid_str, new_ace->type, new_ace->flags,
00507                           new_ace->access_mask));
00508 
00509                 new_ace_list_ndx++;
00510         }
00511 
00512         /* Create child security descriptor to return */
00513         
00514         new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
00515 
00516         /* Use the existing user and group sids.  I don't think this is
00517            correct.  Perhaps the user and group should be passed in as
00518            parameters by the caller? */
00519 
00520         sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
00521                            parent_ctr->owner_sid,
00522                            parent_ctr->group_sid,
00523                            parent_ctr->sacl,
00524                            new_dacl, &size);
00525 
00526         sdb = make_sec_desc_buf(ctx, size, sd);
00527 
00528         return sdb;
00529 }
00530 
00531 /*******************************************************************
00532  Sets up a SEC_ACCESS structure.
00533 ********************************************************************/
00534 
00535 void init_sec_access(SEC_ACCESS *t, uint32 mask)
00536 {
00537         *t = mask;
00538 }

Sambaに対してSat Aug 29 21:22:59 2009に生成されました。  doxygen 1.4.7