Make sure that we only propogate the INHERITED flag when we are allowed to.
[Samba.git] / source3 / lib / secdesc.c
blob7ff3a6af47db2cf9d33614b809b80a5f33ddaf25
1 /*
2 * Unix SMB/Netbios implementation.
3 * SEC_DESC handling functions
4 * Copyright (C) Andrew Tridgell 1992-1998,
5 * Copyright (C) Jeremy R. Allison 1995-2003.
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
7 * Copyright (C) Paul Ashton 1997-1998.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "../librpc/gen_ndr/ndr_security.h"
25 #include "../libcli/security/security.h"
27 #define ALL_SECURITY_INFORMATION (SECINFO_OWNER|SECINFO_GROUP|\
28 SECINFO_DACL|SECINFO_SACL|\
29 SECINFO_UNPROTECTED_SACL|\
30 SECINFO_UNPROTECTED_DACL|\
31 SECINFO_PROTECTED_SACL|\
32 SECINFO_PROTECTED_DACL)
34 /* Map generic permissions to file object specific permissions */
36 const struct generic_mapping file_generic_mapping = {
37 FILE_GENERIC_READ,
38 FILE_GENERIC_WRITE,
39 FILE_GENERIC_EXECUTE,
40 FILE_GENERIC_ALL
43 /*******************************************************************
44 Given a security_descriptor return the sec_info.
45 ********************************************************************/
47 uint32_t get_sec_info(const struct security_descriptor *sd)
49 uint32_t sec_info = ALL_SECURITY_INFORMATION;
51 SMB_ASSERT(sd);
53 if (sd->owner_sid == NULL) {
54 sec_info &= ~SECINFO_OWNER;
56 if (sd->group_sid == NULL) {
57 sec_info &= ~SECINFO_GROUP;
59 if (sd->sacl == NULL) {
60 sec_info &= ~SECINFO_SACL;
62 if (sd->dacl == NULL) {
63 sec_info &= ~SECINFO_DACL;
66 return sec_info;
70 /*******************************************************************
71 Merge part of security descriptor old_sec in to the empty sections of
72 security descriptor new_sec.
73 ********************************************************************/
75 struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
77 struct dom_sid *owner_sid, *group_sid;
78 struct sec_desc_buf *return_sdb;
79 struct security_acl *dacl, *sacl;
80 struct security_descriptor *psd = NULL;
81 uint16 secdesc_type;
82 size_t secdesc_size;
84 /* Copy over owner and group sids. There seems to be no flag for
85 this so just check the pointer values. */
87 owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
88 old_sdb->sd->owner_sid;
90 group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
91 old_sdb->sd->group_sid;
93 secdesc_type = new_sdb->sd->type;
95 /* Ignore changes to the system ACL. This has the effect of making
96 changes through the security tab audit button not sticking.
97 Perhaps in future Samba could implement these settings somehow. */
99 sacl = NULL;
100 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
102 /* Copy across discretionary ACL */
104 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
105 dacl = new_sdb->sd->dacl;
106 } else {
107 dacl = old_sdb->sd->dacl;
110 /* Create new security descriptor from bits */
112 psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
113 owner_sid, group_sid, sacl, dacl, &secdesc_size);
115 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
117 return(return_sdb);
120 struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
122 struct dom_sid *owner_sid, *group_sid;
123 struct security_acl *dacl, *sacl;
124 struct security_descriptor *psd = NULL;
125 uint16 secdesc_type;
126 size_t secdesc_size;
128 /* Copy over owner and group sids. There seems to be no flag for
129 this so just check the pointer values. */
131 owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
132 old_sdb->owner_sid;
134 group_sid = new_sdb->group_sid ? new_sdb->group_sid :
135 old_sdb->group_sid;
137 secdesc_type = new_sdb->type;
139 /* Ignore changes to the system ACL. This has the effect of making
140 changes through the security tab audit button not sticking.
141 Perhaps in future Samba could implement these settings somehow. */
143 sacl = NULL;
144 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
146 /* Copy across discretionary ACL */
148 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
149 dacl = new_sdb->dacl;
150 } else {
151 dacl = old_sdb->dacl;
154 /* Create new security descriptor from bits */
155 psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type,
156 owner_sid, group_sid, sacl, dacl, &secdesc_size);
158 return psd;
161 /*******************************************************************
162 Creates a struct security_descriptor structure
163 ********************************************************************/
165 #define SEC_DESC_HEADER_SIZE (2 * sizeof(uint16) + 4 * sizeof(uint32))
167 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
168 enum security_descriptor_revision revision,
169 uint16 type,
170 const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
171 struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
173 struct security_descriptor *dst;
174 uint32 offset = 0;
176 *sd_size = 0;
178 if(( dst = TALLOC_ZERO_P(ctx, struct security_descriptor)) == NULL)
179 return NULL;
181 dst->revision = revision;
182 dst->type = type;
184 if (sacl)
185 dst->type |= SEC_DESC_SACL_PRESENT;
186 if (dacl)
187 dst->type |= SEC_DESC_DACL_PRESENT;
189 dst->owner_sid = NULL;
190 dst->group_sid = NULL;
191 dst->sacl = NULL;
192 dst->dacl = NULL;
194 if(owner_sid && ((dst->owner_sid = dom_sid_dup(dst,owner_sid)) == NULL))
195 goto error_exit;
197 if(grp_sid && ((dst->group_sid = dom_sid_dup(dst,grp_sid)) == NULL))
198 goto error_exit;
200 if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
201 goto error_exit;
203 if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
204 goto error_exit;
206 offset = SEC_DESC_HEADER_SIZE;
209 * Work out the linearization sizes.
212 if (dst->sacl != NULL) {
213 offset += dst->sacl->size;
215 if (dst->dacl != NULL) {
216 offset += dst->dacl->size;
219 if (dst->owner_sid != NULL) {
220 offset += ndr_size_dom_sid(dst->owner_sid, 0);
223 if (dst->group_sid != NULL) {
224 offset += ndr_size_dom_sid(dst->group_sid, 0);
227 *sd_size = (size_t)offset;
228 return dst;
230 error_exit:
232 *sd_size = 0;
233 return NULL;
236 /*******************************************************************
237 Duplicate a struct security_descriptor structure.
238 ********************************************************************/
240 struct security_descriptor *dup_sec_desc(TALLOC_CTX *ctx, const struct security_descriptor *src)
242 size_t dummy;
244 if(src == NULL)
245 return NULL;
247 return make_sec_desc( ctx, src->revision, src->type,
248 src->owner_sid, src->group_sid, src->sacl,
249 src->dacl, &dummy);
252 /*******************************************************************
253 Convert a secdesc into a byte stream
254 ********************************************************************/
255 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
256 struct security_descriptor *secdesc,
257 uint8 **data, size_t *len)
259 DATA_BLOB blob;
260 enum ndr_err_code ndr_err;
262 ndr_err = ndr_push_struct_blob(
263 &blob, mem_ctx, secdesc,
264 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
266 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
267 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
268 ndr_errstr(ndr_err)));
269 return ndr_map_error2ntstatus(ndr_err);
272 *data = blob.data;
273 *len = blob.length;
274 return NT_STATUS_OK;
277 /*******************************************************************
278 Convert a secdesc_buf into a byte stream
279 ********************************************************************/
281 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
282 struct sec_desc_buf *secdesc_buf,
283 uint8_t **data, size_t *len)
285 DATA_BLOB blob;
286 enum ndr_err_code ndr_err;
288 ndr_err = ndr_push_struct_blob(
289 &blob, mem_ctx, secdesc_buf,
290 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
292 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
293 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
294 ndr_errstr(ndr_err)));
295 return ndr_map_error2ntstatus(ndr_err);
298 *data = blob.data;
299 *len = blob.length;
300 return NT_STATUS_OK;
303 /*******************************************************************
304 Parse a byte stream into a secdesc
305 ********************************************************************/
306 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
307 struct security_descriptor **psecdesc)
309 DATA_BLOB blob;
310 enum ndr_err_code ndr_err;
311 struct security_descriptor *result;
313 if ((data == NULL) || (len == 0)) {
314 return NT_STATUS_INVALID_PARAMETER;
317 result = TALLOC_ZERO_P(mem_ctx, struct security_descriptor);
318 if (result == NULL) {
319 return NT_STATUS_NO_MEMORY;
322 blob = data_blob_const(data, len);
324 ndr_err = ndr_pull_struct_blob(&blob, result, result,
325 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
327 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
328 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
329 ndr_errstr(ndr_err)));
330 TALLOC_FREE(result);
331 return ndr_map_error2ntstatus(ndr_err);
334 *psecdesc = result;
335 return NT_STATUS_OK;
338 /*******************************************************************
339 Parse a byte stream into a sec_desc_buf
340 ********************************************************************/
342 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
343 struct sec_desc_buf **psecdesc_buf)
345 DATA_BLOB blob;
346 enum ndr_err_code ndr_err;
347 struct sec_desc_buf *result;
349 if ((data == NULL) || (len == 0)) {
350 return NT_STATUS_INVALID_PARAMETER;
353 result = TALLOC_ZERO_P(mem_ctx, struct sec_desc_buf);
354 if (result == NULL) {
355 return NT_STATUS_NO_MEMORY;
358 blob = data_blob_const(data, len);
360 ndr_err = ndr_pull_struct_blob(&blob, result, result,
361 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
363 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
364 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
365 ndr_errstr(ndr_err)));
366 TALLOC_FREE(result);
367 return ndr_map_error2ntstatus(ndr_err);
370 *psecdesc_buf = result;
371 return NT_STATUS_OK;
374 /*******************************************************************
375 Creates a struct security_descriptor structure with typical defaults.
376 ********************************************************************/
378 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
379 struct security_acl *dacl, size_t *sd_size)
381 return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
382 SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
383 dacl, sd_size);
386 /*******************************************************************
387 Creates a struct sec_desc_buf structure.
388 ********************************************************************/
390 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
392 struct sec_desc_buf *dst;
394 if((dst = TALLOC_ZERO_P(ctx, struct sec_desc_buf)) == NULL)
395 return NULL;
397 /* max buffer size (allocated size) */
398 dst->sd_size = (uint32)len;
400 if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
401 return NULL;
404 return dst;
407 /*******************************************************************
408 Duplicates a struct sec_desc_buf structure.
409 ********************************************************************/
411 struct sec_desc_buf *dup_sec_desc_buf(TALLOC_CTX *ctx, struct sec_desc_buf *src)
413 if(src == NULL)
414 return NULL;
416 return make_sec_desc_buf( ctx, src->sd_size, src->sd);
419 /*******************************************************************
420 Add a new SID with its permissions to struct security_descriptor.
421 ********************************************************************/
423 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, const struct dom_sid *sid, uint32 mask, size_t *sd_size)
425 struct security_descriptor *sd = 0;
426 struct security_acl *dacl = 0;
427 struct security_ace *ace = 0;
428 NTSTATUS status;
430 if (!ctx || !psd || !sid || !sd_size)
431 return NT_STATUS_INVALID_PARAMETER;
433 *sd_size = 0;
435 status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
437 if (!NT_STATUS_IS_OK(status))
438 return status;
440 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
441 return NT_STATUS_UNSUCCESSFUL;
443 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
444 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
445 return NT_STATUS_UNSUCCESSFUL;
447 *psd = sd;
448 sd = 0;
449 return NT_STATUS_OK;
452 /*******************************************************************
453 Modify a SID's permissions in a struct security_descriptor.
454 ********************************************************************/
456 NTSTATUS sec_desc_mod_sid(struct security_descriptor *sd, struct dom_sid *sid, uint32 mask)
458 NTSTATUS status;
460 if (!sd || !sid)
461 return NT_STATUS_INVALID_PARAMETER;
463 status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
465 if (!NT_STATUS_IS_OK(status))
466 return status;
468 return NT_STATUS_OK;
471 /*******************************************************************
472 Delete a SID from a struct security_descriptor.
473 ********************************************************************/
475 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, size_t *sd_size)
477 struct security_descriptor *sd = 0;
478 struct security_acl *dacl = 0;
479 struct security_ace *ace = 0;
480 NTSTATUS status;
482 if (!ctx || !psd[0] || !sid || !sd_size)
483 return NT_STATUS_INVALID_PARAMETER;
485 *sd_size = 0;
487 status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
489 if (!NT_STATUS_IS_OK(status))
490 return status;
492 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
493 return NT_STATUS_UNSUCCESSFUL;
495 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
496 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
497 return NT_STATUS_UNSUCCESSFUL;
499 *psd = sd;
500 sd = 0;
501 return NT_STATUS_OK;
505 * Determine if an struct security_ace is inheritable
508 static bool is_inheritable_ace(const struct security_ace *ace,
509 bool container)
511 if (!container) {
512 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
515 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
516 return true;
519 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
520 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
521 return true;
524 return false;
528 * Does a security descriptor have any inheritable components for
529 * the newly created type ?
532 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
534 unsigned int i;
535 const struct security_acl *the_acl = parent_ctr->dacl;
537 if (the_acl == NULL) {
538 return false;
541 for (i = 0; i < the_acl->num_aces; i++) {
542 const struct security_ace *ace = &the_acl->aces[i];
544 if (is_inheritable_ace(ace, container)) {
545 return true;
548 return false;
551 /* Create a child security descriptor using another security descriptor as
552 the parent container. This child object can either be a container or
553 non-container object. */
555 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
556 struct security_descriptor **ppsd,
557 size_t *psize,
558 const struct security_descriptor *parent_ctr,
559 const struct dom_sid *owner_sid,
560 const struct dom_sid *group_sid,
561 bool container)
563 struct security_acl *new_dacl = NULL, *the_acl = NULL;
564 struct security_ace *new_ace_list = NULL;
565 unsigned int new_ace_list_ndx = 0, i;
566 bool set_inherited_flags = (parent_ctr->type & SEC_DESC_DACL_AUTO_INHERITED);
568 *ppsd = NULL;
569 *psize = 0;
571 /* Currently we only process the dacl when creating the child. The
572 sacl should also be processed but this is left out as sacls are
573 not implemented in Samba at the moment.*/
575 the_acl = parent_ctr->dacl;
577 if (the_acl->num_aces) {
578 if (2*the_acl->num_aces < the_acl->num_aces) {
579 return NT_STATUS_NO_MEMORY;
582 if (!(new_ace_list = TALLOC_ARRAY(ctx, struct security_ace,
583 2*the_acl->num_aces))) {
584 return NT_STATUS_NO_MEMORY;
586 } else {
587 new_ace_list = NULL;
590 for (i = 0; i < the_acl->num_aces; i++) {
591 const struct security_ace *ace = &the_acl->aces[i];
592 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
593 const struct dom_sid *ptrustee = &ace->trustee;
594 const struct dom_sid *creator = NULL;
595 uint8 new_flags = ace->flags;
597 if (!is_inheritable_ace(ace, container)) {
598 continue;
601 /* see the RAW-ACLS inheritance test for details on these rules */
602 if (!container) {
603 new_flags = 0;
604 } else {
605 new_flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY|
606 SEC_ACE_FLAG_INHERITED_ACE);
608 if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
609 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
611 if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
612 new_flags = 0;
616 /* The CREATOR sids are special when inherited */
617 if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
618 creator = &global_sid_Creator_Owner;
619 ptrustee = owner_sid;
620 } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
621 creator = &global_sid_Creator_Group;
622 ptrustee = group_sid;
625 if (creator && container &&
626 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
628 /* First add the regular ACE entry. */
629 init_sec_ace(new_ace, ptrustee, ace->type,
630 ace->access_mask,
631 set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0);
633 DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
634 " inherited as %s:%d/0x%02x/0x%08x\n",
635 sid_string_dbg(&ace->trustee),
636 ace->type, ace->flags, ace->access_mask,
637 sid_string_dbg(&new_ace->trustee),
638 new_ace->type, new_ace->flags,
639 new_ace->access_mask));
641 new_ace_list_ndx++;
643 /* Now add the extra creator ACE. */
644 new_ace = &new_ace_list[new_ace_list_ndx];
646 ptrustee = creator;
647 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
648 } else if (container &&
649 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
650 ptrustee = &ace->trustee;
653 init_sec_ace(new_ace, ptrustee, ace->type,
654 ace->access_mask, new_flags |
655 (set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0));
657 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
658 " inherited as %s:%d/0x%02x/0x%08x\n",
659 sid_string_dbg(&ace->trustee),
660 ace->type, ace->flags, ace->access_mask,
661 sid_string_dbg(&ace->trustee),
662 new_ace->type, new_ace->flags,
663 new_ace->access_mask));
665 new_ace_list_ndx++;
668 /* Create child security descriptor to return */
669 if (new_ace_list_ndx) {
670 new_dacl = make_sec_acl(ctx,
671 NT4_ACL_REVISION,
672 new_ace_list_ndx,
673 new_ace_list);
675 if (!new_dacl) {
676 return NT_STATUS_NO_MEMORY;
680 *ppsd = make_sec_desc(ctx,
681 SECURITY_DESCRIPTOR_REVISION_1,
682 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
683 (set_inherited_flags ? SEC_DESC_DACL_AUTO_INHERITED : 0),
684 owner_sid,
685 group_sid,
686 NULL,
687 new_dacl,
688 psize);
689 if (!*ppsd) {
690 return NT_STATUS_NO_MEMORY;
692 return NT_STATUS_OK;
695 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
696 struct sec_desc_buf **ppsdb,
697 const struct security_descriptor *parent_ctr,
698 bool container)
700 NTSTATUS status;
701 size_t size = 0;
702 struct security_descriptor *sd = NULL;
704 *ppsdb = NULL;
705 status = se_create_child_secdesc(ctx,
706 &sd,
707 &size,
708 parent_ctr,
709 parent_ctr->owner_sid,
710 parent_ctr->group_sid,
711 container);
712 if (!NT_STATUS_IS_OK(status)) {
713 return status;
716 *ppsdb = make_sec_desc_buf(ctx, size, sd);
717 if (!*ppsdb) {
718 return NT_STATUS_NO_MEMORY;
720 return NT_STATUS_OK;