00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "includes.h"
00023
00024 extern struct current_user current_user;
00025 extern struct generic_mapping file_generic_mapping;
00026
00027 #undef DBGC_CLASS
00028 #define DBGC_CLASS DBGC_ACLS
00029
00030
00031
00032
00033
00034 enum ace_owner {UID_ACE, GID_ACE, WORLD_ACE};
00035 enum ace_attribute {ALLOW_ACE, DENY_ACE};
00036
00037 typedef union posix_id {
00038 uid_t uid;
00039 gid_t gid;
00040 int world;
00041 } posix_id;
00042
00043 typedef struct canon_ace {
00044 struct canon_ace *next, *prev;
00045 SMB_ACL_TAG_T type;
00046 mode_t perms;
00047 DOM_SID trustee;
00048 enum ace_owner owner_type;
00049 enum ace_attribute attr;
00050 posix_id unix_ug;
00051 BOOL inherited;
00052 } canon_ace;
00053
00054 #define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR)
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #define PAI_VERSION_OFFSET 0
00067 #define PAI_FLAG_OFFSET 1
00068 #define PAI_NUM_ENTRIES_OFFSET 2
00069 #define PAI_NUM_DEFAULT_ENTRIES_OFFSET 4
00070 #define PAI_ENTRIES_BASE 6
00071
00072 #define PAI_VERSION 1
00073 #define PAI_ACL_FLAG_PROTECTED 0x1
00074 #define PAI_ENTRY_LENGTH 5
00075
00076
00077
00078
00079
00080 struct pai_entry {
00081 struct pai_entry *next, *prev;
00082 enum ace_owner owner_type;
00083 posix_id unix_ug;
00084 };
00085
00086 struct pai_val {
00087 BOOL pai_protected;
00088 unsigned int num_entries;
00089 struct pai_entry *entry_list;
00090 unsigned int num_def_entries;
00091 struct pai_entry *def_entry_list;
00092 };
00093
00094
00095
00096
00097
00098 static uint32 get_pai_entry_val(struct pai_entry *paie)
00099 {
00100 switch (paie->owner_type) {
00101 case UID_ACE:
00102 DEBUG(10,("get_pai_entry_val: uid = %u\n", (unsigned int)paie->unix_ug.uid ));
00103 return (uint32)paie->unix_ug.uid;
00104 case GID_ACE:
00105 DEBUG(10,("get_pai_entry_val: gid = %u\n", (unsigned int)paie->unix_ug.gid ));
00106 return (uint32)paie->unix_ug.gid;
00107 case WORLD_ACE:
00108 default:
00109 DEBUG(10,("get_pai_entry_val: world ace\n"));
00110 return (uint32)-1;
00111 }
00112 }
00113
00114
00115
00116
00117
00118 static uint32 get_entry_val(canon_ace *ace_entry)
00119 {
00120 switch (ace_entry->owner_type) {
00121 case UID_ACE:
00122 DEBUG(10,("get_entry_val: uid = %u\n", (unsigned int)ace_entry->unix_ug.uid ));
00123 return (uint32)ace_entry->unix_ug.uid;
00124 case GID_ACE:
00125 DEBUG(10,("get_entry_val: gid = %u\n", (unsigned int)ace_entry->unix_ug.gid ));
00126 return (uint32)ace_entry->unix_ug.gid;
00127 case WORLD_ACE:
00128 default:
00129 DEBUG(10,("get_entry_val: world ace\n"));
00130 return (uint32)-1;
00131 }
00132 }
00133
00134
00135
00136
00137
00138 static unsigned int num_inherited_entries(canon_ace *ace_list)
00139 {
00140 unsigned int num_entries = 0;
00141
00142 for (; ace_list; ace_list = ace_list->next)
00143 if (ace_list->inherited)
00144 num_entries++;
00145 return num_entries;
00146 }
00147
00148
00149
00150
00151
00152 static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, BOOL pai_protected, size_t *store_size)
00153 {
00154 char *pai_buf = NULL;
00155 canon_ace *ace_list = NULL;
00156 char *entry_offset = NULL;
00157 unsigned int num_entries = 0;
00158 unsigned int num_def_entries = 0;
00159
00160 for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next)
00161 if (ace_list->inherited)
00162 num_entries++;
00163
00164 for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next)
00165 if (ace_list->inherited)
00166 num_def_entries++;
00167
00168 DEBUG(10,("create_pai_buf: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries ));
00169
00170 *store_size = PAI_ENTRIES_BASE + ((num_entries + num_def_entries)*PAI_ENTRY_LENGTH);
00171
00172 pai_buf = (char *)SMB_MALLOC(*store_size);
00173 if (!pai_buf) {
00174 return NULL;
00175 }
00176
00177
00178 memset(pai_buf, '\0', PAI_ENTRIES_BASE);
00179 SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_VERSION);
00180 SCVAL(pai_buf,PAI_FLAG_OFFSET,(pai_protected ? PAI_ACL_FLAG_PROTECTED : 0));
00181 SSVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET,num_entries);
00182 SSVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries);
00183
00184 entry_offset = pai_buf + PAI_ENTRIES_BASE;
00185
00186 for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {
00187 if (ace_list->inherited) {
00188 uint8 type_val = (unsigned char)ace_list->owner_type;
00189 uint32 entry_val = get_entry_val(ace_list);
00190
00191 SCVAL(entry_offset,0,type_val);
00192 SIVAL(entry_offset,1,entry_val);
00193 entry_offset += PAI_ENTRY_LENGTH;
00194 }
00195 }
00196
00197 for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {
00198 if (ace_list->inherited) {
00199 uint8 type_val = (unsigned char)ace_list->owner_type;
00200 uint32 entry_val = get_entry_val(ace_list);
00201
00202 SCVAL(entry_offset,0,type_val);
00203 SIVAL(entry_offset,1,entry_val);
00204 entry_offset += PAI_ENTRY_LENGTH;
00205 }
00206 }
00207
00208 return pai_buf;
00209 }
00210
00211
00212
00213
00214
00215 static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_list,
00216 canon_ace *dir_ace_list, BOOL pai_protected)
00217 {
00218 int ret;
00219 size_t store_size;
00220 char *pai_buf;
00221
00222 if (!lp_map_acl_inherit(SNUM(fsp->conn)))
00223 return;
00224
00225
00226
00227
00228
00229
00230 if (!pai_protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) {
00231
00232 if (fsp->fh->fd != -1)
00233 SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME);
00234 else
00235 SMB_VFS_REMOVEXATTR(fsp->conn, fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
00236 return;
00237 }
00238
00239 pai_buf = create_pai_buf(file_ace_list, dir_ace_list, pai_protected, &store_size);
00240
00241 if (fsp->fh->fd != -1)
00242 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME,
00243 pai_buf, store_size, 0);
00244 else
00245 ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME,
00246 pai_buf, store_size, 0);
00247
00248 SAFE_FREE(pai_buf);
00249
00250 DEBUG(10,("store_inheritance_attribute:%s for file %s\n", pai_protected ? " (protected)" : "", fsp->fsp_name));
00251 if (ret == -1 && !no_acl_syscall_error(errno))
00252 DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) ));
00253 }
00254
00255
00256
00257
00258
00259 static void free_inherited_info(struct pai_val *pal)
00260 {
00261 if (pal) {
00262 struct pai_entry *paie, *paie_next;
00263 for (paie = pal->entry_list; paie; paie = paie_next) {
00264 paie_next = paie->next;
00265 SAFE_FREE(paie);
00266 }
00267 for (paie = pal->def_entry_list; paie; paie = paie_next) {
00268 paie_next = paie->next;
00269 SAFE_FREE(paie);
00270 }
00271 SAFE_FREE(pal);
00272 }
00273 }
00274
00275
00276
00277
00278
00279 static BOOL get_protected_flag(struct pai_val *pal)
00280 {
00281 if (!pal)
00282 return False;
00283 return pal->pai_protected;
00284 }
00285
00286
00287
00288
00289
00290 static BOOL get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, BOOL default_ace)
00291 {
00292 struct pai_entry *paie;
00293
00294 if (!pal)
00295 return False;
00296
00297
00298 for (paie = (default_ace ? pal->def_entry_list : pal->entry_list); paie; paie = paie->next) {
00299 if (ace_entry->owner_type == paie->owner_type &&
00300 get_entry_val(ace_entry) == get_pai_entry_val(paie))
00301 return True;
00302 }
00303 return False;
00304 }
00305
00306
00307
00308
00309
00310 static BOOL check_pai_ok(char *pai_buf, size_t pai_buf_data_size)
00311 {
00312 uint16 num_entries;
00313 uint16 num_def_entries;
00314
00315 if (pai_buf_data_size < PAI_ENTRIES_BASE) {
00316
00317 return False;
00318 }
00319
00320 if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_VERSION)
00321 return False;
00322
00323 num_entries = SVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET);
00324 num_def_entries = SVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET);
00325
00326
00327
00328
00329 if (((num_entries + num_def_entries)*PAI_ENTRY_LENGTH) + PAI_ENTRIES_BASE != pai_buf_data_size)
00330 return False;
00331
00332 return True;
00333 }
00334
00335
00336
00337
00338
00339
00340 static struct pai_val *create_pai_val(char *buf, size_t size)
00341 {
00342 char *entry_offset;
00343 struct pai_val *paiv = NULL;
00344 int i;
00345
00346 if (!check_pai_ok(buf, size))
00347 return NULL;
00348
00349 paiv = SMB_MALLOC_P(struct pai_val);
00350 if (!paiv)
00351 return NULL;
00352
00353 memset(paiv, '\0', sizeof(struct pai_val));
00354
00355 paiv->pai_protected = (CVAL(buf,PAI_FLAG_OFFSET) == PAI_ACL_FLAG_PROTECTED);
00356
00357 paiv->num_entries = SVAL(buf,PAI_NUM_ENTRIES_OFFSET);
00358 paiv->num_def_entries = SVAL(buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET);
00359
00360 entry_offset = buf + PAI_ENTRIES_BASE;
00361
00362 DEBUG(10,("create_pai_val:%s num_entries = %u, num_def_entries = %u\n",
00363 paiv->pai_protected ? " (pai_protected)" : "", paiv->num_entries, paiv->num_def_entries ));
00364
00365 for (i = 0; i < paiv->num_entries; i++) {
00366 struct pai_entry *paie;
00367
00368 paie = SMB_MALLOC_P(struct pai_entry);
00369 if (!paie) {
00370 free_inherited_info(paiv);
00371 return NULL;
00372 }
00373
00374 paie->owner_type = (enum ace_owner)CVAL(entry_offset,0);
00375 switch( paie->owner_type) {
00376 case UID_ACE:
00377 paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1);
00378 DEBUG(10,("create_pai_val: uid = %u\n", (unsigned int)paie->unix_ug.uid ));
00379 break;
00380 case GID_ACE:
00381 paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1);
00382 DEBUG(10,("create_pai_val: gid = %u\n", (unsigned int)paie->unix_ug.gid ));
00383 break;
00384 case WORLD_ACE:
00385 paie->unix_ug.world = -1;
00386 DEBUG(10,("create_pai_val: world ace\n"));
00387 break;
00388 default:
00389 free_inherited_info(paiv);
00390 return NULL;
00391 }
00392 entry_offset += PAI_ENTRY_LENGTH;
00393 DLIST_ADD(paiv->entry_list, paie);
00394 }
00395
00396 for (i = 0; i < paiv->num_def_entries; i++) {
00397 struct pai_entry *paie;
00398
00399 paie = SMB_MALLOC_P(struct pai_entry);
00400 if (!paie) {
00401 free_inherited_info(paiv);
00402 return NULL;
00403 }
00404
00405 paie->owner_type = (enum ace_owner)CVAL(entry_offset,0);
00406 switch( paie->owner_type) {
00407 case UID_ACE:
00408 paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1);
00409 DEBUG(10,("create_pai_val: (def) uid = %u\n", (unsigned int)paie->unix_ug.uid ));
00410 break;
00411 case GID_ACE:
00412 paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1);
00413 DEBUG(10,("create_pai_val: (def) gid = %u\n", (unsigned int)paie->unix_ug.gid ));
00414 break;
00415 case WORLD_ACE:
00416 paie->unix_ug.world = -1;
00417 DEBUG(10,("create_pai_val: (def) world ace\n"));
00418 break;
00419 default:
00420 free_inherited_info(paiv);
00421 return NULL;
00422 }
00423 entry_offset += PAI_ENTRY_LENGTH;
00424 DLIST_ADD(paiv->def_entry_list, paie);
00425 }
00426
00427 return paiv;
00428 }
00429
00430
00431
00432
00433
00434 static struct pai_val *load_inherited_info(files_struct *fsp)
00435 {
00436 char *pai_buf;
00437 size_t pai_buf_size = 1024;
00438 struct pai_val *paiv = NULL;
00439 ssize_t ret;
00440
00441 if (!lp_map_acl_inherit(SNUM(fsp->conn)))
00442 return NULL;
00443
00444 if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL)
00445 return NULL;
00446
00447 do {
00448 if (fsp->fh->fd != -1)
00449 ret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME,
00450 pai_buf, pai_buf_size);
00451 else
00452 ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME,
00453 pai_buf, pai_buf_size);
00454
00455 if (ret == -1) {
00456 if (errno != ERANGE) {
00457 break;
00458 }
00459
00460 pai_buf_size *= 2;
00461 SAFE_FREE(pai_buf);
00462 if (pai_buf_size > 1024*1024) {
00463 return NULL;
00464 }
00465 if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL)
00466 return NULL;
00467 }
00468 } while (ret == -1);
00469
00470 DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fsp->fsp_name));
00471
00472 if (ret == -1) {
00473
00474 #if defined(ENOATTR)
00475 if (errno != ENOATTR)
00476 DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
00477 #else
00478 if (errno != ENOSYS)
00479 DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
00480 #endif
00481 SAFE_FREE(pai_buf);
00482 return NULL;
00483 }
00484
00485 paiv = create_pai_val(pai_buf, ret);
00486
00487 if (paiv && paiv->pai_protected)
00488 DEBUG(10,("load_inherited_info: ACL is protected for file %s\n", fsp->fsp_name));
00489
00490 SAFE_FREE(pai_buf);
00491 return paiv;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 static size_t count_canon_ace_list( canon_ace *list_head )
00503 {
00504 size_t count = 0;
00505 canon_ace *ace;
00506
00507 for (ace = list_head; ace; ace = ace->next)
00508 count++;
00509
00510 return count;
00511 }
00512
00513
00514
00515
00516
00517 static void free_canon_ace_list( canon_ace *list_head )
00518 {
00519 canon_ace *list, *next;
00520
00521 for (list = list_head; list; list = next) {
00522 next = list->next;
00523 DLIST_REMOVE(list_head, list);
00524 SAFE_FREE(list);
00525 }
00526 }
00527
00528
00529
00530
00531
00532 static canon_ace *dup_canon_ace( canon_ace *src_ace)
00533 {
00534 canon_ace *dst_ace = SMB_MALLOC_P(canon_ace);
00535
00536 if (dst_ace == NULL)
00537 return NULL;
00538
00539 *dst_ace = *src_ace;
00540 dst_ace->prev = dst_ace->next = NULL;
00541 return dst_ace;
00542 }
00543
00544
00545
00546
00547
00548 static void print_canon_ace(canon_ace *pace, int num)
00549 {
00550 fstring str;
00551
00552 dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
00553 dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee));
00554 if (pace->owner_type == UID_ACE) {
00555 const char *u_name = uidtoname(pace->unix_ug.uid);
00556 dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name );
00557 } else if (pace->owner_type == GID_ACE) {
00558 char *g_name = gidtoname(pace->unix_ug.gid);
00559 dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name );
00560 } else
00561 dbgtext( "other ");
00562 switch (pace->type) {
00563 case SMB_ACL_USER:
00564 dbgtext( "SMB_ACL_USER ");
00565 break;
00566 case SMB_ACL_USER_OBJ:
00567 dbgtext( "SMB_ACL_USER_OBJ ");
00568 break;
00569 case SMB_ACL_GROUP:
00570 dbgtext( "SMB_ACL_GROUP ");
00571 break;
00572 case SMB_ACL_GROUP_OBJ:
00573 dbgtext( "SMB_ACL_GROUP_OBJ ");
00574 break;
00575 case SMB_ACL_OTHER:
00576 dbgtext( "SMB_ACL_OTHER ");
00577 break;
00578 default:
00579 dbgtext( "MASK " );
00580 break;
00581 }
00582 if (pace->inherited)
00583 dbgtext( "(inherited) ");
00584 dbgtext( "perms ");
00585 dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-');
00586 dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-');
00587 dbgtext( "%c\n", pace->perms & S_IXUSR ? 'x' : '-');
00588 }
00589
00590
00591
00592
00593
00594 static void print_canon_ace_list(const char *name, canon_ace *ace_list)
00595 {
00596 int count = 0;
00597
00598 if( DEBUGLVL( 10 )) {
00599 dbgtext( "print_canon_ace_list: %s\n", name );
00600 for (;ace_list; ace_list = ace_list->next, count++)
00601 print_canon_ace(ace_list, count );
00602 }
00603 }
00604
00605
00606
00607
00608
00609 static mode_t convert_permset_to_mode_t(connection_struct *conn, SMB_ACL_PERMSET_T permset)
00610 {
00611 mode_t ret = 0;
00612
00613 ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0);
00614 ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0);
00615 ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0);
00616
00617 return ret;
00618 }
00619
00620
00621
00622
00623
00624 static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask)
00625 {
00626 mode_t ret = 0;
00627
00628 if (mode & r_mask)
00629 ret |= S_IRUSR;
00630 if (mode & w_mask)
00631 ret |= S_IWUSR;
00632 if (mode & x_mask)
00633 ret |= S_IXUSR;
00634
00635 return ret;
00636 }
00637
00638
00639
00640
00641
00642
00643 static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset)
00644 {
00645 if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) == -1)
00646 return -1;
00647 if (mode & S_IRUSR) {
00648 if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1)
00649 return -1;
00650 }
00651 if (mode & S_IWUSR) {
00652 if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1)
00653 return -1;
00654 }
00655 if (mode & S_IXUSR) {
00656 if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1)
00657 return -1;
00658 }
00659 return 0;
00660 }
00661
00662
00663
00664
00665
00666 static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid)
00667 {
00668 uid_to_sid( powner_sid, psbuf->st_uid );
00669 gid_to_sid( pgroup_sid, psbuf->st_gid );
00670 }
00671
00672
00673
00674
00675
00676 static BOOL identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2)
00677 {
00678 if (sid_equal(&ace1->trustee, &ace2->trustee)) {
00679 return True;
00680 }
00681 if (ace1->owner_type == ace2->owner_type) {
00682 if (ace1->owner_type == UID_ACE &&
00683 ace1->unix_ug.uid == ace2->unix_ug.uid) {
00684 return True;
00685 } else if (ace1->owner_type == GID_ACE &&
00686 ace1->unix_ug.gid == ace2->unix_ug.gid) {
00687 return True;
00688 }
00689 }
00690 return False;
00691 }
00692
00693
00694
00695
00696
00697
00698
00699 static void merge_aces( canon_ace **pp_list_head )
00700 {
00701 canon_ace *list_head = *pp_list_head;
00702 canon_ace *curr_ace_outer;
00703 canon_ace *curr_ace_outer_next;
00704
00705
00706
00707
00708
00709
00710 for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
00711 canon_ace *curr_ace;
00712 canon_ace *curr_ace_next;
00713
00714 curr_ace_outer_next = curr_ace_outer->next;
00715
00716 for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
00717
00718 curr_ace_next = curr_ace->next;
00719
00720 if (identity_in_ace_equal(curr_ace, curr_ace_outer) &&
00721 (curr_ace->attr == curr_ace_outer->attr)) {
00722
00723 if( DEBUGLVL( 10 )) {
00724 dbgtext("merge_aces: Merging ACE's\n");
00725 print_canon_ace( curr_ace_outer, 0);
00726 print_canon_ace( curr_ace, 0);
00727 }
00728
00729
00730
00731 curr_ace_outer->perms |= curr_ace->perms;
00732 DLIST_REMOVE(list_head, curr_ace);
00733 SAFE_FREE(curr_ace);
00734 curr_ace_outer_next = curr_ace_outer->next;
00735 }
00736 }
00737 }
00738
00739
00740
00741
00742
00743
00744
00745 for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
00746 canon_ace *curr_ace;
00747 canon_ace *curr_ace_next;
00748
00749 curr_ace_outer_next = curr_ace_outer->next;
00750
00751 for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
00752
00753 curr_ace_next = curr_ace->next;
00754
00755
00756
00757
00758
00759
00760 if (identity_in_ace_equal(curr_ace, curr_ace_outer) &&
00761 (curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {
00762
00763 if( DEBUGLVL( 10 )) {
00764 dbgtext("merge_aces: Masking ACE's\n");
00765 print_canon_ace( curr_ace_outer, 0);
00766 print_canon_ace( curr_ace, 0);
00767 }
00768
00769 curr_ace->perms &= ~curr_ace_outer->perms;
00770
00771 if (curr_ace->perms == 0) {
00772
00773
00774
00775
00776
00777 DLIST_REMOVE(list_head, curr_ace);
00778 SAFE_FREE(curr_ace);
00779 curr_ace_outer_next = curr_ace_outer->next;
00780
00781 } else {
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 DLIST_REMOVE(list_head, curr_ace_outer);
00794 SAFE_FREE(curr_ace_outer);
00795 break;
00796 }
00797 }
00798
00799 }
00800 }
00801
00802
00803
00804 *pp_list_head = list_head;
00805 }
00806
00807
00808
00809
00810
00811 static BOOL nt4_compatible_acls(void)
00812 {
00813 int compat = lp_acl_compatibility();
00814
00815 if (compat == ACL_COMPAT_AUTO) {
00816 enum remote_arch_types ra_type = get_remote_arch();
00817
00818
00819 return (ra_type <= RA_WINNT);
00820 } else
00821 return (compat == ACL_COMPAT_WINNT);
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831 static SEC_ACCESS map_canon_ace_perms(int snum,
00832 int *pacl_type,
00833 mode_t perms,
00834 BOOL directory_ace)
00835 {
00836 SEC_ACCESS sa;
00837 uint32 nt_mask = 0;
00838
00839 *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED;
00840
00841 if (lp_acl_map_full_control(snum) && ((perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) {
00842 if (directory_ace) {
00843 nt_mask = UNIX_DIRECTORY_ACCESS_RWX;
00844 } else {
00845 nt_mask = UNIX_ACCESS_RWX;
00846 }
00847 } else if ((perms & ALL_ACE_PERMS) == (mode_t)0) {
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857 if (nt4_compatible_acls())
00858 nt_mask = UNIX_ACCESS_NONE;
00859 else
00860 nt_mask = 0;
00861 } else {
00862 if (directory_ace) {
00863 nt_mask |= ((perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 );
00864 nt_mask |= ((perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 );
00865 nt_mask |= ((perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 );
00866 } else {
00867 nt_mask |= ((perms & S_IRUSR) ? UNIX_ACCESS_R : 0 );
00868 nt_mask |= ((perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );
00869 nt_mask |= ((perms & S_IXUSR) ? UNIX_ACCESS_X : 0 );
00870 }
00871 }
00872
00873 DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n",
00874 (unsigned int)perms, (unsigned int)nt_mask ));
00875
00876 init_sec_access(&sa,nt_mask);
00877 return sa;
00878 }
00879
00880
00881
00882
00883
00884 #define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES)
00885 #define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES)
00886 #define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)
00887
00888 static mode_t map_nt_perms( uint32 *mask, int type)
00889 {
00890 mode_t mode = 0;
00891
00892 switch(type) {
00893 case S_IRUSR:
00894 if((*mask) & GENERIC_ALL_ACCESS)
00895 mode = S_IRUSR|S_IWUSR|S_IXUSR;
00896 else {
00897 mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0;
00898 mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0;
00899 mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0;
00900 }
00901 break;
00902 case S_IRGRP:
00903 if((*mask) & GENERIC_ALL_ACCESS)
00904 mode = S_IRGRP|S_IWGRP|S_IXGRP;
00905 else {
00906 mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0;
00907 mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0;
00908 mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0;
00909 }
00910 break;
00911 case S_IROTH:
00912 if((*mask) & GENERIC_ALL_ACCESS)
00913 mode = S_IROTH|S_IWOTH|S_IXOTH;
00914 else {
00915 mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0;
00916 mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0;
00917 mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0;
00918 }
00919 break;
00920 }
00921
00922 return mode;
00923 }
00924
00925
00926
00927
00928
00929 BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
00930 {
00931 DOM_SID owner_sid;
00932 DOM_SID grp_sid;
00933
00934 *puser = (uid_t)-1;
00935 *pgrp = (gid_t)-1;
00936
00937 if(security_info_sent == 0) {
00938 DEBUG(0,("unpack_nt_owners: no security info sent !\n"));
00939 return True;
00940 }
00941
00942
00943
00944
00945
00946 memset(&owner_sid, '\0', sizeof(owner_sid));
00947 memset(&grp_sid, '\0', sizeof(grp_sid));
00948
00949 DEBUG(5,("unpack_nt_owners: validating owner_sids.\n"));
00950
00951
00952
00953
00954
00955
00956 if (security_info_sent & OWNER_SECURITY_INFORMATION) {
00957 sid_copy(&owner_sid, psd->owner_sid);
00958 if (!sid_to_uid(&owner_sid, puser)) {
00959 if (lp_force_unknown_acl_user(snum)) {
00960
00961
00962 *puser = current_user.ut.uid;
00963 } else {
00964 DEBUG(3,("unpack_nt_owners: unable to validate"
00965 " owner sid for %s\n",
00966 sid_string_static(&owner_sid)));
00967 return False;
00968 }
00969 }
00970 }
00971
00972
00973
00974
00975
00976
00977 if (security_info_sent & GROUP_SECURITY_INFORMATION) {
00978 sid_copy(&grp_sid, psd->group_sid);
00979 if (!sid_to_gid( &grp_sid, pgrp)) {
00980 if (lp_force_unknown_acl_user(snum)) {
00981
00982
00983 *pgrp = current_user.ut.gid;
00984 } else {
00985 DEBUG(3,("unpack_nt_owners: unable to validate"
00986 " group sid.\n"));
00987 return False;
00988 }
00989 }
00990 }
00991
00992 DEBUG(5,("unpack_nt_owners: owner_sids validated.\n"));
00993
00994 return True;
00995 }
00996
00997
00998
00999
01000
01001 static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
01002 {
01003 int snum = SNUM(fsp->conn);
01004 mode_t and_bits = (mode_t)0;
01005 mode_t or_bits = (mode_t)0;
01006
01007
01008
01009 if (fsp->is_directory) {
01010 and_bits = lp_dir_security_mask(snum);
01011 or_bits = lp_force_dir_security_mode(snum);
01012 } else {
01013 and_bits = lp_security_mask(snum);
01014 or_bits = lp_force_security_mode(snum);
01015 }
01016
01017
01018 switch(type) {
01019 case S_IRUSR:
01020
01021 pace->perms |= S_IRUSR;
01022 if (fsp->is_directory)
01023 pace->perms |= (S_IWUSR|S_IXUSR);
01024 and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR);
01025 or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR);
01026 break;
01027 case S_IRGRP:
01028 and_bits = unix_perms_to_acl_perms(and_bits, S_IRGRP, S_IWGRP, S_IXGRP);
01029 or_bits = unix_perms_to_acl_perms(or_bits, S_IRGRP, S_IWGRP, S_IXGRP);
01030 break;
01031 case S_IROTH:
01032 and_bits = unix_perms_to_acl_perms(and_bits, S_IROTH, S_IWOTH, S_IXOTH);
01033 or_bits = unix_perms_to_acl_perms(or_bits, S_IROTH, S_IWOTH, S_IXOTH);
01034 break;
01035 }
01036
01037 pace->perms = ((pace->perms & and_bits)|or_bits);
01038 }
01039
01040
01041
01042
01043
01044
01045 static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
01046 {
01047 fstring u_name;
01048
01049
01050
01051 if (sid_equal(&group_ace->trustee, &global_sid_World))
01052 return True;
01053
01054
01055
01056 if (uid_ace->unix_ug.uid == current_user.ut.uid && group_ace->unix_ug.gid == current_user.ut.gid)
01057 return True;
01058
01059 fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
01060 return user_in_group_sid(u_name, &group_ace->trustee);
01061 }
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
01074 files_struct *fsp,
01075 const DOM_SID *pfile_owner_sid,
01076 const DOM_SID *pfile_grp_sid,
01077 SMB_STRUCT_STAT *pst,
01078 BOOL setting_acl)
01079 {
01080 canon_ace *pace;
01081 BOOL got_user = False;
01082 BOOL got_grp = False;
01083 BOOL got_other = False;
01084 canon_ace *pace_other = NULL;
01085
01086 for (pace = *pp_ace; pace; pace = pace->next) {
01087 if (pace->type == SMB_ACL_USER_OBJ) {
01088
01089 if (setting_acl)
01090 apply_default_perms(fsp, pace, S_IRUSR);
01091 got_user = True;
01092
01093 } else if (pace->type == SMB_ACL_GROUP_OBJ) {
01094
01095
01096
01097
01098
01099 if (setting_acl)
01100 apply_default_perms(fsp, pace, S_IRGRP);
01101 got_grp = True;
01102
01103 } else if (pace->type == SMB_ACL_OTHER) {
01104
01105
01106
01107
01108
01109 if (setting_acl)
01110 apply_default_perms(fsp, pace, S_IROTH);
01111 got_other = True;
01112 pace_other = pace;
01113 }
01114 }
01115
01116 if (!got_user) {
01117 if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
01118 DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
01119 return False;
01120 }
01121
01122 ZERO_STRUCTP(pace);
01123 pace->type = SMB_ACL_USER_OBJ;
01124 pace->owner_type = UID_ACE;
01125 pace->unix_ug.uid = pst->st_uid;
01126 pace->trustee = *pfile_owner_sid;
01127 pace->attr = ALLOW_ACE;
01128
01129 if (setting_acl) {
01130
01131
01132
01133 BOOL group_matched = False;
01134 canon_ace *pace_iter;
01135
01136 for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) {
01137 if (pace_iter->type == SMB_ACL_GROUP_OBJ || pace_iter->type == SMB_ACL_GROUP) {
01138 if (uid_entry_in_group(pace, pace_iter)) {
01139 pace->perms |= pace_iter->perms;
01140 group_matched = True;
01141 }
01142 }
01143 }
01144
01145
01146 if (!group_matched) {
01147 if (got_other)
01148 pace->perms = pace_other->perms;
01149 else
01150 pace->perms = 0;
01151 }
01152
01153 apply_default_perms(fsp, pace, S_IRUSR);
01154 } else {
01155 pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
01156 }
01157
01158 DLIST_ADD(*pp_ace, pace);
01159 }
01160
01161 if (!got_grp) {
01162 if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
01163 DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
01164 return False;
01165 }
01166
01167 ZERO_STRUCTP(pace);
01168 pace->type = SMB_ACL_GROUP_OBJ;
01169 pace->owner_type = GID_ACE;
01170 pace->unix_ug.uid = pst->st_gid;
01171 pace->trustee = *pfile_grp_sid;
01172 pace->attr = ALLOW_ACE;
01173 if (setting_acl) {
01174
01175 if (got_other)
01176 pace->perms = pace_other->perms;
01177 else
01178 pace->perms = 0;
01179 apply_default_perms(fsp, pace, S_IRGRP);
01180 } else {
01181 pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
01182 }
01183
01184 DLIST_ADD(*pp_ace, pace);
01185 }
01186
01187 if (!got_other) {
01188 if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
01189 DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
01190 return False;
01191 }
01192
01193 ZERO_STRUCTP(pace);
01194 pace->type = SMB_ACL_OTHER;
01195 pace->owner_type = WORLD_ACE;
01196 pace->unix_ug.world = -1;
01197 pace->trustee = global_sid_World;
01198 pace->attr = ALLOW_ACE;
01199 if (setting_acl) {
01200 pace->perms = 0;
01201 apply_default_perms(fsp, pace, S_IROTH);
01202 } else
01203 pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH);
01204
01205 DLIST_ADD(*pp_ace, pace);
01206 }
01207
01208 return True;
01209 }
01210
01211
01212
01213
01214
01215
01216
01217 static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid)
01218 {
01219 BOOL got_user_obj, got_group_obj;
01220 canon_ace *current_ace;
01221 int i, entries;
01222
01223 entries = count_canon_ace_list(ace);
01224 got_user_obj = False;
01225 got_group_obj = False;
01226
01227 for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
01228 if (current_ace->type == SMB_ACL_USER_OBJ)
01229 got_user_obj = True;
01230 else if (current_ace->type == SMB_ACL_GROUP_OBJ)
01231 got_group_obj = True;
01232 }
01233 if (got_user_obj && got_group_obj) {
01234 DEBUG(10,("check_owning_objs: ACL had owning user/group entries.\n"));
01235 return;
01236 }
01237
01238 for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
01239 if (!got_user_obj && current_ace->owner_type == UID_ACE &&
01240 sid_equal(¤t_ace->trustee, pfile_owner_sid)) {
01241 current_ace->type = SMB_ACL_USER_OBJ;
01242 got_user_obj = True;
01243 }
01244 if (!got_group_obj && current_ace->owner_type == GID_ACE &&
01245 sid_equal(¤t_ace->trustee, pfile_grp_sid)) {
01246 current_ace->type = SMB_ACL_GROUP_OBJ;
01247 got_group_obj = True;
01248 }
01249 }
01250 if (!got_user_obj)
01251 DEBUG(10,("check_owning_objs: ACL is missing an owner entry.\n"));
01252 if (!got_group_obj)
01253 DEBUG(10,("check_owning_objs: ACL is missing an owning group entry.\n"));
01254 }
01255
01256
01257
01258
01259
01260 static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
01261 DOM_SID *pfile_owner_sid,
01262 DOM_SID *pfile_grp_sid,
01263 canon_ace **ppfile_ace, canon_ace **ppdir_ace,
01264 SEC_ACL *dacl)
01265 {
01266 BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False);
01267 canon_ace *file_ace = NULL;
01268 canon_ace *dir_ace = NULL;
01269 canon_ace *current_ace = NULL;
01270 BOOL got_dir_allow = False;
01271 BOOL got_file_allow = False;
01272 int i, j;
01273
01274 *ppfile_ace = NULL;
01275 *ppdir_ace = NULL;
01276
01277
01278
01279
01280
01281 for(i = 0; i < dacl->num_aces; i++) {
01282 SEC_ACE *psa = &dacl->aces[i];
01283
01284 if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) {
01285 DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n"));
01286 return False;
01287 }
01288
01289 if (nt4_compatible_acls()) {
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301 se_map_generic(&psa->access_mask, &file_generic_mapping);
01302
01303 psa->access_mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS);
01304
01305 if(psa->access_mask != UNIX_ACCESS_NONE)
01306 psa->access_mask &= ~UNIX_ACCESS_NONE;
01307 }
01308 }
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318 for(i = 0; i < dacl->num_aces; i++) {
01319 SEC_ACE *psa1 = &dacl->aces[i];
01320
01321 for (j = i + 1; j < dacl->num_aces; j++) {
01322 SEC_ACE *psa2 = &dacl->aces[j];
01323
01324 if (psa1->access_mask != psa2->access_mask)
01325 continue;
01326
01327 if (!sid_equal(&psa1->trustee, &psa2->trustee))
01328 continue;
01329
01330
01331
01332
01333
01334
01335 if (psa1->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
01336
01337 psa1->flags |= (psa2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT));
01338 psa2->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT);
01339
01340 } else if (psa2->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
01341
01342 psa2->flags |= (psa1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT));
01343 psa1->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT);
01344
01345 }
01346 }
01347 }
01348
01349 for(i = 0; i < dacl->num_aces; i++) {
01350 SEC_ACE *psa = &dacl->aces[i];
01351
01352
01353
01354
01355
01356 if ((current_ace = SMB_MALLOC_P(canon_ace)) == NULL) {
01357 free_canon_ace_list(file_ace);
01358 free_canon_ace_list(dir_ace);
01359 DEBUG(0,("create_canon_ace_lists: malloc fail.\n"));
01360 return False;
01361 }
01362
01363 ZERO_STRUCTP(current_ace);
01364
01365 sid_copy(¤t_ace->trustee, &psa->trustee);
01366
01367
01368
01369
01370
01371
01372
01373 if( sid_equal(¤t_ace->trustee, &global_sid_World)) {
01374 current_ace->owner_type = WORLD_ACE;
01375 current_ace->unix_ug.world = -1;
01376 current_ace->type = SMB_ACL_OTHER;
01377 } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Owner)) {
01378 current_ace->owner_type = UID_ACE;
01379 current_ace->unix_ug.uid = pst->st_uid;
01380 current_ace->type = SMB_ACL_USER_OBJ;
01381
01382
01383
01384
01385
01386
01387
01388 if (nt4_compatible_acls())
01389 psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
01390 } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Group)) {
01391 current_ace->owner_type = GID_ACE;
01392 current_ace->unix_ug.gid = pst->st_gid;
01393 current_ace->type = SMB_ACL_GROUP_OBJ;
01394
01395
01396
01397
01398
01399
01400 if (nt4_compatible_acls())
01401 psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
01402
01403 } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid)) {
01404 current_ace->owner_type = UID_ACE;
01405
01406
01407 if (current_ace->unix_ug.uid == pst->st_uid) {
01408 current_ace->type = SMB_ACL_USER_OBJ;
01409 } else {
01410 current_ace->type = SMB_ACL_USER;
01411 }
01412 } else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid)) {
01413 current_ace->owner_type = GID_ACE;
01414
01415
01416 if (current_ace->unix_ug.gid == pst->st_gid) {
01417 current_ace->type = SMB_ACL_GROUP_OBJ;
01418 } else {
01419 current_ace->type = SMB_ACL_GROUP;
01420 }
01421 } else {
01422 fstring str;
01423
01424
01425
01426
01427
01428 if (non_mappable_sid(&psa->trustee)) {
01429 DEBUG(10,("create_canon_ace_lists: ignoring non-mappable SID %s\n",
01430 sid_to_string(str, &psa->trustee) ));
01431 SAFE_FREE(current_ace);
01432 continue;
01433 }
01434
01435 free_canon_ace_list(file_ace);
01436 free_canon_ace_list(dir_ace);
01437 DEBUG(0,("create_canon_ace_lists: unable to map SID %s to uid or gid.\n",
01438 sid_to_string(str, ¤t_ace->trustee) ));
01439 SAFE_FREE(current_ace);
01440 return False;
01441 }
01442
01443
01444
01445
01446
01447
01448 current_ace->perms |= map_nt_perms( &psa->access_mask, S_IRUSR);
01449 current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE;
01450 current_ace->inherited = ((psa->flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False);
01451
01452
01453
01454
01455
01456
01457
01458 if (fsp->is_directory) {
01459
01460
01461
01462
01463
01464
01465 if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) ==
01466 (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) {
01467
01468 DLIST_ADD_END(dir_ace, current_ace, canon_ace *);
01469
01470
01471
01472
01473
01474
01475 if (current_ace->attr == ALLOW_ACE)
01476 got_dir_allow = True;
01477
01478 if ((current_ace->attr == DENY_ACE) && got_dir_allow) {
01479 DEBUG(0,("create_canon_ace_lists: malformed ACL in inheritable ACL ! \
01480 Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
01481 free_canon_ace_list(file_ace);
01482 free_canon_ace_list(dir_ace);
01483 return False;
01484 }
01485
01486 if( DEBUGLVL( 10 )) {
01487 dbgtext("create_canon_ace_lists: adding dir ACL:\n");
01488 print_canon_ace( current_ace, 0);
01489 }
01490
01491
01492
01493
01494
01495
01496 if (!(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
01497 canon_ace *dup_ace = dup_canon_ace(current_ace);
01498
01499 if (!dup_ace) {
01500 DEBUG(0,("create_canon_ace_lists: malloc fail !\n"));
01501 free_canon_ace_list(file_ace);
01502 free_canon_ace_list(dir_ace);
01503 return False;
01504 }
01505
01506
01507
01508
01509
01510 current_ace = dup_ace;
01511 } else {
01512
01513
01514
01515
01516 current_ace = NULL;
01517 }
01518 }
01519 }
01520
01521
01522
01523
01524
01525 if (current_ace && !(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
01526 DLIST_ADD_END(file_ace, current_ace, canon_ace *);
01527
01528
01529
01530
01531
01532
01533 if (current_ace->attr == ALLOW_ACE)
01534 got_file_allow = True;
01535
01536 if ((current_ace->attr == DENY_ACE) && got_file_allow) {
01537 DEBUG(0,("create_canon_ace_lists: malformed ACL in file ACL ! \
01538 Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
01539 free_canon_ace_list(file_ace);
01540 free_canon_ace_list(dir_ace);
01541 return False;
01542 }
01543
01544 if( DEBUGLVL( 10 )) {
01545 dbgtext("create_canon_ace_lists: adding file ACL:\n");
01546 print_canon_ace( current_ace, 0);
01547 }
01548 all_aces_are_inherit_only = False;
01549
01550
01551
01552
01553 current_ace = NULL;
01554 }
01555
01556
01557
01558
01559
01560 SAFE_FREE(current_ace);
01561 }
01562
01563 if (fsp->is_directory && all_aces_are_inherit_only) {
01564
01565
01566
01567
01568
01569
01570 DEBUG(10,("create_canon_ace_lists: Win2k inherit acl traverse. Ignoring DACL.\n"));
01571 free_canon_ace_list(file_ace);
01572 free_canon_ace_list(dir_ace);
01573 file_ace = NULL;
01574 dir_ace = NULL;
01575 } else {
01576
01577
01578
01579
01580
01581
01582 if (file_ace) {
01583 check_owning_objs(file_ace, pfile_owner_sid, pfile_grp_sid);
01584 }
01585 if (dir_ace) {
01586 check_owning_objs(dir_ace, pfile_owner_sid, pfile_grp_sid);
01587 }
01588 }
01589
01590 *ppfile_ace = file_ace;
01591 *ppdir_ace = dir_ace;
01592
01593 return True;
01594 }
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700 static void process_deny_list( canon_ace **pp_ace_list )
01701 {
01702 canon_ace *ace_list = *pp_ace_list;
01703 canon_ace *curr_ace = NULL;
01704 canon_ace *curr_ace_next = NULL;
01705
01706
01707
01708 for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
01709 canon_ace *allow_ace_p;
01710
01711 curr_ace_next = curr_ace->next;
01712
01713 if (curr_ace->attr != DENY_ACE)
01714 continue;
01715
01716 if (curr_ace->perms == (mode_t)0) {
01717
01718
01719
01720 DLIST_REMOVE(ace_list, curr_ace);
01721 continue;
01722 }
01723
01724 if (!sid_equal(&curr_ace->trustee, &global_sid_World))
01725 continue;
01726
01727
01728 SMB_ASSERT(curr_ace->owner_type == WORLD_ACE);
01729
01730 if (curr_ace->perms == ALL_ACE_PERMS) {
01731
01732
01733
01734
01735
01736
01737 canon_ace *prev_entry = curr_ace->prev;
01738
01739 free_canon_ace_list( curr_ace );
01740 if (prev_entry)
01741 prev_entry->next = NULL;
01742 else {
01743
01744 ace_list = NULL;
01745 }
01746 break;
01747 }
01748
01749 for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
01750
01751
01752
01753
01754
01755 if (allow_ace_p->attr != ALLOW_ACE)
01756 continue;
01757
01758 allow_ace_p->perms &= ~curr_ace->perms;
01759 }
01760
01761
01762
01763
01764
01765 DLIST_REMOVE(ace_list, curr_ace);
01766 }
01767
01768
01769
01770 for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
01771 mode_t new_perms = (mode_t)0;
01772 canon_ace *allow_ace_p;
01773
01774 curr_ace_next = curr_ace->next;
01775
01776 if (curr_ace->attr != DENY_ACE)
01777 continue;
01778
01779 if (curr_ace->owner_type != UID_ACE)
01780 continue;
01781
01782 if (curr_ace->perms == ALL_ACE_PERMS) {
01783
01784
01785
01786
01787
01788
01789 curr_ace->attr = ALLOW_ACE;
01790 curr_ace->perms = (mode_t)0;
01791 DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
01792 continue;
01793 }
01794
01795 for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
01796
01797 if (allow_ace_p->attr != ALLOW_ACE)
01798 continue;
01799
01800
01801
01802 if (allow_ace_p->owner_type == UID_ACE)
01803 continue;
01804
01805 if (uid_entry_in_group( curr_ace, allow_ace_p))
01806 new_perms |= allow_ace_p->perms;
01807 }
01808
01809
01810
01811
01812
01813
01814 curr_ace->attr = ALLOW_ACE;
01815 curr_ace->perms = (new_perms & ~curr_ace->perms);
01816 DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
01817 }
01818
01819
01820
01821 for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
01822 canon_ace *allow_ace_p;
01823 canon_ace *allow_everyone_p = NULL;
01824
01825 curr_ace_next = curr_ace->next;
01826
01827 if (curr_ace->attr != DENY_ACE)
01828 continue;
01829
01830 if (curr_ace->owner_type != GID_ACE)
01831 continue;
01832
01833 for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
01834
01835 if (allow_ace_p->attr != ALLOW_ACE)
01836 continue;
01837
01838
01839 if (allow_ace_p->owner_type == WORLD_ACE)
01840 allow_everyone_p = allow_ace_p;
01841
01842
01843
01844 if (allow_ace_p->owner_type != UID_ACE)
01845 continue;
01846
01847
01848
01849 if (uid_entry_in_group( allow_ace_p, curr_ace))
01850 allow_ace_p->perms &= ~curr_ace->perms;
01851 }
01852
01853
01854
01855
01856
01857
01858 curr_ace->attr = ALLOW_ACE;
01859 if (allow_everyone_p)
01860 curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms;
01861 else
01862 curr_ace->perms = (mode_t)0;
01863 DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
01864 }
01865
01866
01867
01868
01869
01870
01871
01872
01873 #if 0
01874
01875
01876 for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
01877 canon_ace *allow_ace_p;
01878
01879 curr_ace_next = curr_ace->next;
01880
01881 if (curr_ace->attr != ALLOW_ACE)
01882 continue;
01883
01884 if (curr_ace->owner_type != UID_ACE)
01885 continue;
01886
01887 for (allow_ace_p = ace_list; allow_ace_p; allow_ace_p = allow_ace_p->next) {
01888
01889 if (allow_ace_p->attr != ALLOW_ACE)
01890 continue;
01891
01892
01893
01894 if (allow_ace_p->owner_type != GID_ACE)
01895 continue;
01896
01897
01898
01899 if (uid_entry_in_group( curr_ace, allow_ace_p))
01900 curr_ace->perms |= allow_ace_p->perms;
01901 }
01902 }
01903 #endif
01904
01905 *pp_ace_list = ace_list;
01906 }
01907
01908
01909
01910
01911
01912
01913 static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode)
01914 {
01915 int snum = SNUM(fsp->conn);
01916 mode_t and_bits = (mode_t)0;
01917 mode_t or_bits = (mode_t)0;
01918 mode_t mode = interitable_mode
01919 ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name,
01920 NULL )
01921 : S_IRUSR;
01922
01923 if (fsp->is_directory)
01924 mode |= (S_IWUSR|S_IXUSR);
01925
01926
01927
01928
01929
01930
01931 if (fsp->is_directory) {
01932 and_bits = lp_dir_security_mask(snum);
01933 or_bits = lp_force_dir_security_mode(snum);
01934 } else {
01935 and_bits = lp_security_mask(snum);
01936 or_bits = lp_force_security_mode(snum);
01937 }
01938
01939 return ((mode & and_bits)|or_bits);
01940 }
01941
01942
01943
01944
01945
01946
01947 static BOOL unpack_canon_ace(files_struct *fsp,
01948 SMB_STRUCT_STAT *pst,
01949 DOM_SID *pfile_owner_sid,
01950 DOM_SID *pfile_grp_sid,
01951 canon_ace **ppfile_ace, canon_ace **ppdir_ace,
01952 uint32 security_info_sent, SEC_DESC *psd)
01953 {
01954 canon_ace *file_ace = NULL;
01955 canon_ace *dir_ace = NULL;
01956
01957 *ppfile_ace = NULL;
01958 *ppdir_ace = NULL;
01959
01960 if(security_info_sent == 0) {
01961 DEBUG(0,("unpack_canon_ace: no security info sent !\n"));
01962 return False;
01963 }
01964
01965
01966
01967
01968
01969 if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !psd->dacl)
01970 return True;
01971
01972
01973
01974
01975
01976 if (!create_canon_ace_lists( fsp, pst, pfile_owner_sid, pfile_grp_sid,
01977 &file_ace, &dir_ace, psd->dacl))
01978 return False;
01979
01980 if ((file_ace == NULL) && (dir_ace == NULL)) {
01981
01982 return True;
01983 }
01984
01985
01986
01987
01988
01989
01990
01991
01992 print_canon_ace_list( "file ace - before merge", file_ace);
01993 merge_aces( &file_ace );
01994
01995 print_canon_ace_list( "dir ace - before merge", dir_ace);
01996 merge_aces( &dir_ace );
01997
01998
01999
02000
02001
02002
02003 print_canon_ace_list( "file ace - before deny", file_ace);
02004 process_deny_list( &file_ace);
02005
02006 print_canon_ace_list( "dir ace - before deny", dir_ace);
02007 process_deny_list( &dir_ace);
02008
02009
02010
02011
02012
02013
02014
02015 print_canon_ace_list( "file ace - before valid", file_ace);
02016
02017
02018
02019
02020
02021
02022 pst->st_mode = create_default_mode(fsp, False);
02023
02024 if (!ensure_canon_entry_valid(&file_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) {
02025 free_canon_ace_list(file_ace);
02026 free_canon_ace_list(dir_ace);
02027 return False;
02028 }
02029
02030 print_canon_ace_list( "dir ace - before valid", dir_ace);
02031
02032
02033
02034
02035
02036
02037
02038 pst->st_mode = create_default_mode(fsp, True);
02039
02040 if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) {
02041 free_canon_ace_list(file_ace);
02042 free_canon_ace_list(dir_ace);
02043 return False;
02044 }
02045
02046 print_canon_ace_list( "file ace - return", file_ace);
02047 print_canon_ace_list( "dir ace - return", dir_ace);
02048
02049 *ppfile_ace = file_ace;
02050 *ppdir_ace = dir_ace;
02051 return True;
02052
02053 }
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074 static void arrange_posix_perms( char *filename, canon_ace **pp_list_head)
02075 {
02076 canon_ace *list_head = *pp_list_head;
02077 canon_ace *owner_ace = NULL;
02078 canon_ace *other_ace = NULL;
02079 canon_ace *ace = NULL;
02080
02081 for (ace = list_head; ace; ace = ace->next) {
02082 if (ace->type == SMB_ACL_USER_OBJ)
02083 owner_ace = ace;
02084 else if (ace->type == SMB_ACL_OTHER) {
02085
02086 other_ace = ace;
02087 }
02088 }
02089
02090 if (!owner_ace || !other_ace) {
02091 DEBUG(0,("arrange_posix_perms: Invalid POSIX permissions for file %s, missing owner or other.\n",
02092 filename ));
02093 return;
02094 }
02095
02096
02097
02098
02099
02100
02101 if (owner_ace) {
02102 DLIST_PROMOTE(list_head, owner_ace);
02103 }
02104
02105 if (other_ace) {
02106 DLIST_DEMOTE(list_head, other_ace, canon_ace *);
02107 }
02108
02109
02110
02111 *pp_list_head = list_head;
02112 }
02113
02114
02115
02116
02117
02118 static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf,
02119 const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
02120 {
02121 connection_struct *conn = fsp->conn;
02122 mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR);
02123 canon_ace *list_head = NULL;
02124 canon_ace *ace = NULL;
02125 canon_ace *next_ace = NULL;
02126 int entry_id = SMB_ACL_FIRST_ENTRY;
02127 SMB_ACL_ENTRY_T entry;
02128 size_t ace_count;
02129
02130 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
02131 SMB_ACL_TAG_T tagtype;
02132 SMB_ACL_PERMSET_T permset;
02133 DOM_SID sid;
02134 posix_id unix_ug;
02135 enum ace_owner owner_type;
02136
02137
02138 if (entry_id == SMB_ACL_FIRST_ENTRY)
02139 entry_id = SMB_ACL_NEXT_ENTRY;
02140
02141
02142 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
02143 continue;
02144
02145 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1)
02146 continue;
02147
02148
02149 switch(tagtype) {
02150 case SMB_ACL_USER_OBJ:
02151
02152 sid_copy(&sid, powner);
02153 unix_ug.uid = psbuf->st_uid;
02154 owner_type = UID_ACE;
02155 break;
02156 case SMB_ACL_USER:
02157 {
02158 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
02159 if (puid == NULL) {
02160 DEBUG(0,("canonicalise_acl: Failed to get uid.\n"));
02161 continue;
02162 }
02163
02164
02165
02166
02167
02168
02169
02170 if (the_acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) {
02171 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
02172 continue;
02173 }
02174 uid_to_sid( &sid, *puid);
02175 unix_ug.uid = *puid;
02176 owner_type = UID_ACE;
02177 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
02178 break;
02179 }
02180 case SMB_ACL_GROUP_OBJ:
02181
02182 sid_copy(&sid, pgroup);
02183 unix_ug.gid = psbuf->st_gid;
02184 owner_type = GID_ACE;
02185 break;
02186 case SMB_ACL_GROUP:
02187 {
02188 gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
02189 if (pgid == NULL) {
02190 DEBUG(0,("canonicalise_acl: Failed to get gid.\n"));
02191 continue;
02192 }
02193 gid_to_sid( &sid, *pgid);
02194 unix_ug.gid = *pgid;
02195 owner_type = GID_ACE;
02196 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
02197 break;
02198 }
02199 case SMB_ACL_MASK:
02200 acl_mask = convert_permset_to_mode_t(conn, permset);
02201 continue;
02202 case SMB_ACL_OTHER:
02203
02204 sid = global_sid_World;
02205 unix_ug.world = -1;
02206 owner_type = WORLD_ACE;
02207 break;
02208 default:
02209 DEBUG(0,("canonicalise_acl: Unknown tagtype %u\n", (unsigned int)tagtype));
02210 continue;
02211 }
02212
02213
02214
02215
02216
02217 if ((ace = SMB_MALLOC_P(canon_ace)) == NULL)
02218 goto fail;
02219
02220 ZERO_STRUCTP(ace);
02221 ace->type = tagtype;
02222 ace->perms = convert_permset_to_mode_t(conn, permset);
02223 ace->attr = ALLOW_ACE;
02224 ace->trustee = sid;
02225 ace->unix_ug = unix_ug;
02226 ace->owner_type = owner_type;
02227 ace->inherited = get_inherited_flag(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT));
02228
02229 DLIST_ADD(list_head, ace);
02230 }
02231
02232
02233
02234
02235
02236 if (!ensure_canon_entry_valid(&list_head, fsp, powner, pgroup, psbuf, False))
02237 goto fail;
02238
02239
02240
02241
02242
02243
02244 DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", the_acl_type == SMB_ACL_TYPE_ACCESS ? "Access" : "Default" ));
02245
02246 for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) {
02247 next_ace = ace->next;
02248
02249
02250 if (ace->type != SMB_ACL_OTHER && ace->type != SMB_ACL_USER_OBJ)
02251 ace->perms &= acl_mask;
02252
02253 if (ace->perms == 0) {
02254 DLIST_PROMOTE(list_head, ace);
02255 }
02256
02257 if( DEBUGLVL( 10 ) ) {
02258 print_canon_ace(ace, ace_count);
02259 }
02260 }
02261
02262 arrange_posix_perms(fsp->fsp_name,&list_head );
02263
02264 print_canon_ace_list( "canonicalise_acl: ace entries after arrange", list_head );
02265
02266 return list_head;
02267
02268 fail:
02269
02270 free_canon_ace_list(list_head);
02271 return NULL;
02272 }
02273
02274
02275
02276
02277
02278 static BOOL current_user_in_group(gid_t gid)
02279 {
02280 int i;
02281
02282 for (i = 0; i < current_user.ut.ngroups; i++) {
02283 if (current_user.ut.groups[i] == gid) {
02284 return True;
02285 }
02286 }
02287
02288 return False;
02289 }
02290
02291
02292
02293
02294
02295 static BOOL acl_group_override(connection_struct *conn, gid_t prim_gid, const char *fname)
02296 {
02297 SMB_STRUCT_STAT sbuf;
02298
02299 if ((errno != EPERM) && (errno != EACCES)) {
02300 return False;
02301 }
02302
02303
02304 if (lp_acl_group_control(SNUM(conn)) && current_user_in_group(prim_gid)) {
02305 return True;
02306 }
02307
02308
02309 if (lp_dos_filemode(SNUM(conn)) && can_write_to_file(conn, fname, &sbuf)) {
02310 return True;
02311 }
02312
02313 return False;
02314 }
02315
02316
02317
02318
02319
02320 static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace, gid_t prim_gid, BOOL *pacl_set_support)
02321 {
02322 connection_struct *conn = fsp->conn;
02323 BOOL ret = False;
02324 SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1);
02325 canon_ace *p_ace;
02326 int i;
02327 SMB_ACL_ENTRY_T mask_entry;
02328 BOOL got_mask_entry = False;
02329 SMB_ACL_PERMSET_T mask_permset;
02330 SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS);
02331 BOOL needs_mask = False;
02332 mode_t mask_perms = 0;
02333
02334 #if defined(POSIX_ACL_NEEDS_MASK)
02335
02336 needs_mask = True;
02337 #endif
02338
02339 if (the_acl == NULL) {
02340
02341 if (!no_acl_syscall_error(errno)) {
02342
02343
02344
02345
02346 DEBUG(0,("set_canon_ace_list: Unable to init %s ACL. (%s)\n",
02347 default_ace ? "default" : "file", strerror(errno) ));
02348 }
02349 *pacl_set_support = False;
02350 return False;
02351 }
02352
02353 if( DEBUGLVL( 10 )) {
02354 dbgtext("set_canon_ace_list: setting ACL:\n");
02355 for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) {
02356 print_canon_ace( p_ace, i);
02357 }
02358 }
02359
02360 for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) {
02361 SMB_ACL_ENTRY_T the_entry;
02362 SMB_ACL_PERMSET_T the_permset;
02363
02364
02365
02366
02367
02368
02369
02370
02371 if (p_ace->type == SMB_ACL_USER || p_ace->type == SMB_ACL_GROUP) {
02372 needs_mask = True;
02373 mask_perms |= p_ace->perms;
02374 } else if (p_ace->type == SMB_ACL_GROUP_OBJ) {
02375 mask_perms |= p_ace->perms;
02376 }
02377
02378
02379
02380
02381
02382 if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) {
02383 DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n",
02384 i, strerror(errno) ));
02385 goto fail;
02386 }
02387
02388 if (p_ace->type == SMB_ACL_MASK) {
02389 mask_entry = the_entry;
02390 got_mask_entry = True;
02391 }
02392
02393
02394
02395
02396
02397
02398 *pacl_set_support = True;
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408 if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, p_ace->type) == -1) {
02409 DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n",
02410 i, strerror(errno) ));
02411 goto fail;
02412 }
02413
02414
02415
02416
02417
02418
02419 if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) {
02420 if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) {
02421 DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n",
02422 i, strerror(errno) ));
02423 goto fail;
02424 }
02425 }
02426
02427
02428
02429
02430
02431 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) {
02432 DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n",
02433 i, strerror(errno) ));
02434 goto fail;
02435 }
02436
02437 if (map_acl_perms_to_permset(conn, p_ace->perms, &the_permset) == -1) {
02438 DEBUG(0,("set_canon_ace_list: Failed to create permset for mode (%u) on entry %d. (%s)\n",
02439 (unsigned int)p_ace->perms, i, strerror(errno) ));
02440 goto fail;
02441 }
02442
02443
02444
02445
02446
02447 if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) {
02448 DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n",
02449 i, strerror(errno) ));
02450 goto fail;
02451 }
02452
02453 if( DEBUGLVL( 10 ))
02454 print_canon_ace( p_ace, i);
02455
02456 }
02457
02458 if (needs_mask && !got_mask_entry) {
02459 if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &mask_entry) == -1) {
02460 DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) ));
02461 goto fail;
02462 }
02463
02464 if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, mask_entry, SMB_ACL_MASK) == -1) {
02465 DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) ));
02466 goto fail;
02467 }
02468
02469 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, mask_entry, &mask_permset) == -1) {
02470 DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) ));
02471 goto fail;
02472 }
02473
02474 if (map_acl_perms_to_permset(conn, S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) {
02475 DEBUG(0,("set_canon_ace_list: Failed to create mask permset. (%s)\n", strerror(errno) ));
02476 goto fail;
02477 }
02478
02479 if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, mask_entry, mask_permset) == -1) {
02480 DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) ));
02481 goto fail;
02482 }
02483 }
02484
02485
02486
02487
02488
02489 if(default_ace || fsp->is_directory || fsp->fh->fd == -1) {
02490 if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) {
02491
02492
02493
02494
02495 if (no_acl_syscall_error(errno)) {
02496 *pacl_set_support = False;
02497 }
02498
02499 if (acl_group_override(conn, prim_gid, fsp->fsp_name)) {
02500 int sret;
02501
02502 DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
02503 fsp->fsp_name ));
02504
02505 become_root();
02506 sret = SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl);
02507 unbecome_root();
02508 if (sret == 0) {
02509 ret = True;
02510 }
02511 }
02512
02513 if (ret == False) {
02514 DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n",
02515 the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file",
02516 fsp->fsp_name, strerror(errno) ));
02517 goto fail;
02518 }
02519 }
02520 } else {
02521 if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl) == -1) {
02522
02523
02524
02525
02526 if (no_acl_syscall_error(errno)) {
02527 *pacl_set_support = False;
02528 }
02529
02530 if (acl_group_override(conn, prim_gid, fsp->fsp_name)) {
02531 int sret;
02532
02533 DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
02534 fsp->fsp_name ));
02535
02536 become_root();
02537 sret = SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl);
02538 unbecome_root();
02539 if (sret == 0) {
02540 ret = True;
02541 }
02542 }
02543
02544 if (ret == False) {
02545 DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n",
02546 fsp->fsp_name, strerror(errno) ));
02547 goto fail;
02548 }
02549 }
02550 }
02551
02552 ret = True;
02553
02554 fail:
02555
02556 if (the_acl != NULL) {
02557 SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
02558 }
02559
02560 return ret;
02561 }
02562
02563
02564
02565
02566
02567 static struct canon_ace *canon_ace_entry_for(struct canon_ace *list, SMB_ACL_TAG_T type, posix_id *id)
02568 {
02569 while (list) {
02570 if (list->type == type && ((type != SMB_ACL_USER && type != SMB_ACL_GROUP) ||
02571 (type == SMB_ACL_USER && id && id->uid == list->unix_ug.uid) ||
02572 (type == SMB_ACL_GROUP && id && id->gid == list->unix_ug.gid)))
02573 break;
02574 list = list->next;
02575 }
02576 return list;
02577 }
02578
02579
02580
02581
02582
02583 SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl)
02584 {
02585 SMB_ACL_ENTRY_T entry;
02586
02587 if (!the_acl)
02588 return NULL;
02589 if (SMB_VFS_SYS_ACL_GET_ENTRY(conn, the_acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) {
02590 SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
02591 return NULL;
02592 }
02593 return the_acl;
02594 }
02595
02596
02597
02598
02599
02600 #define MAP_PERM(p,mask,result) (((p) & (mask)) ? (result) : 0 )
02601
02602 static BOOL convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms)
02603 {
02604 int snum = SNUM(fsp->conn);
02605 size_t ace_count = count_canon_ace_list(file_ace_list);
02606 canon_ace *ace_p;
02607 canon_ace *owner_ace = NULL;
02608 canon_ace *group_ace = NULL;
02609 canon_ace *other_ace = NULL;
02610 mode_t and_bits;
02611 mode_t or_bits;
02612
02613 if (ace_count != 3) {
02614 DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE entries for file %s to convert to \
02615 posix perms.\n", fsp->fsp_name ));
02616 return False;
02617 }
02618
02619 for (ace_p = file_ace_list; ace_p; ace_p = ace_p->next) {
02620 if (ace_p->owner_type == UID_ACE)
02621 owner_ace = ace_p;
02622 else if (ace_p->owner_type == GID_ACE)
02623 group_ace = ace_p;
02624 else if (ace_p->owner_type == WORLD_ACE)
02625 other_ace = ace_p;
02626 }
02627
02628 if (!owner_ace || !group_ace || !other_ace) {
02629 DEBUG(3,("convert_canon_ace_to_posix_perms: Can't get standard entries for file %s.\n",
02630 fsp->fsp_name ));
02631 return False;
02632 }
02633
02634 *posix_perms = (mode_t)0;
02635
02636 *posix_perms |= owner_ace->perms;
02637 *posix_perms |= MAP_PERM(group_ace->perms, S_IRUSR, S_IRGRP);
02638 *posix_perms |= MAP_PERM(group_ace->perms, S_IWUSR, S_IWGRP);
02639 *posix_perms |= MAP_PERM(group_ace->perms, S_IXUSR, S_IXGRP);
02640 *posix_perms |= MAP_PERM(other_ace->perms, S_IRUSR, S_IROTH);
02641 *posix_perms |= MAP_PERM(other_ace->perms, S_IWUSR, S_IWOTH);
02642 *posix_perms |= MAP_PERM(other_ace->perms, S_IXUSR, S_IXOTH);
02643
02644
02645
02646 *posix_perms |= S_IRUSR;
02647 if (fsp->is_directory)
02648 *posix_perms |= (S_IWUSR|S_IXUSR);
02649
02650
02651
02652
02653
02654 if (fsp->is_directory) {
02655 and_bits = lp_dir_security_mask(snum);
02656 or_bits = lp_force_dir_security_mode(snum);
02657 } else {
02658 and_bits = lp_security_mask(snum);
02659 or_bits = lp_force_security_mode(snum);
02660 }
02661
02662 *posix_perms = (((*posix_perms) & and_bits)|or_bits);
02663
02664 DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o to perm=0%o for file %s.\n",
02665 (int)owner_ace->perms, (int)group_ace->perms, (int)other_ace->perms, (int)*posix_perms,
02666 fsp->fsp_name ));
02667
02668 return True;
02669 }
02670
02671
02672
02673
02674
02675
02676
02677
02678 static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces)
02679 {
02680 size_t i, j;
02681
02682 for (i = 0; i < num_aces; i++) {
02683 for (j = i+1; j < num_aces; j++) {
02684 uint32 i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
02685 uint32 j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
02686 BOOL i_inh = (nt_ace_list[i].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
02687 BOOL j_inh = (nt_ace_list[j].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
02688
02689
02690 if ((nt_ace_list[i].type == nt_ace_list[j].type) &&
02691 (nt_ace_list[i].size == nt_ace_list[j].size) &&
02692 (nt_ace_list[i].access_mask == nt_ace_list[j].access_mask) &&
02693 sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) &&
02694 (i_inh == j_inh) &&
02695 (i_flags_ni == 0) &&
02696 (j_flags_ni == (SEC_ACE_FLAG_OBJECT_INHERIT|
02697 SEC_ACE_FLAG_CONTAINER_INHERIT|
02698 SEC_ACE_FLAG_INHERIT_ONLY))) {
02699
02700
02701
02702
02703
02704
02705 if (nt_ace_list[i].access_mask == 0) {
02706 nt_ace_list[j].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
02707 (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0);
02708 if (num_aces - i - 1 > 0)
02709 memmove(&nt_ace_list[i], &nt_ace_list[i+1], (num_aces-i-1) *
02710 sizeof(SEC_ACE));
02711
02712 DEBUG(10,("merge_default_aces: Merging zero access ACE %u onto ACE %u.\n",
02713 (unsigned int)i, (unsigned int)j ));
02714 } else {
02715
02716
02717
02718
02719
02720 nt_ace_list[i].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
02721 (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0);
02722 if (num_aces - j - 1 > 0)
02723 memmove(&nt_ace_list[j], &nt_ace_list[j+1], (num_aces-j-1) *
02724 sizeof(SEC_ACE));
02725
02726 DEBUG(10,("merge_default_aces: Merging ACE %u onto ACE %u.\n",
02727 (unsigned int)j, (unsigned int)i ));
02728 }
02729 num_aces--;
02730 break;
02731 }
02732 }
02733 }
02734
02735 return num_aces;
02736 }
02737
02738
02739
02740
02741
02742
02743
02744 size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc)
02745 {
02746 connection_struct *conn = fsp->conn;
02747 SMB_STRUCT_STAT sbuf;
02748 SEC_ACE *nt_ace_list = NULL;
02749 DOM_SID owner_sid;
02750 DOM_SID group_sid;
02751 size_t sd_size = 0;
02752 SEC_ACL *psa = NULL;
02753 size_t num_acls = 0;
02754 size_t num_def_acls = 0;
02755 size_t num_aces = 0;
02756 SMB_ACL_T posix_acl = NULL;
02757 SMB_ACL_T def_acl = NULL;
02758 canon_ace *file_ace = NULL;
02759 canon_ace *dir_ace = NULL;
02760 size_t num_profile_acls = 0;
02761 struct pai_val *pal = NULL;
02762 SEC_DESC *psd = NULL;
02763
02764 *ppdesc = NULL;
02765
02766 DEBUG(10,("get_nt_acl: called for file %s\n", fsp->fsp_name ));
02767
02768 if(fsp->is_directory || fsp->fh->fd == -1) {
02769
02770
02771 if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) {
02772 return 0;
02773 }
02774
02775
02776
02777
02778 posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
02779
02780
02781
02782
02783
02784 if(fsp->is_directory) {
02785 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
02786 def_acl = free_empty_sys_acl(conn, def_acl);
02787 }
02788
02789 } else {
02790
02791
02792 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
02793 return 0;
02794 }
02795
02796
02797
02798 posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
02799 }
02800
02801 DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n",
02802 posix_acl ? "present" : "absent",
02803 def_acl ? "present" : "absent" ));
02804
02805 pal = load_inherited_info(fsp);
02806
02807
02808
02809
02810
02811 if (lp_profile_acls(SNUM(conn))) {
02812
02813 sid_copy(&owner_sid, &global_sid_Builtin_Administrators);
02814 sid_copy(&group_sid, &global_sid_Builtin_Users);
02815 num_profile_acls = 2;
02816 } else {
02817 create_file_sids(&sbuf, &owner_sid, &group_sid);
02818 }
02819
02820 if ((security_info & DACL_SECURITY_INFORMATION) && !(security_info & PROTECTED_DACL_SECURITY_INFORMATION)) {
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832 file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, pal, SMB_ACL_TYPE_ACCESS );
02833
02834
02835
02836 if (count_canon_ace_list(file_ace) == 0) {
02837 DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name ));
02838 goto done;
02839 }
02840
02841 if (fsp->is_directory && def_acl) {
02842 dir_ace = canonicalise_acl(fsp, def_acl, &sbuf,
02843 &global_sid_Creator_Owner,
02844 &global_sid_Creator_Group, pal, SMB_ACL_TYPE_DEFAULT );
02845 }
02846
02847
02848
02849
02850
02851 {
02852 canon_ace *ace;
02853 int nt_acl_type;
02854 int i;
02855
02856 if (nt4_compatible_acls() && dir_ace) {
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869 ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL);
02870 if (ace && !ace->perms) {
02871 DLIST_REMOVE(dir_ace, ace);
02872 SAFE_FREE(ace);
02873
02874 ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL);
02875 if (ace && !ace->perms) {
02876 DLIST_REMOVE(file_ace, ace);
02877 SAFE_FREE(ace);
02878 }
02879 }
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890 #if 0
02891 ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL);
02892 if (ace && !ace->perms) {
02893 DLIST_REMOVE(dir_ace, ace);
02894 SAFE_FREE(ace);
02895 }
02896 #endif
02897
02898 ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL);
02899 if (ace && !ace->perms) {
02900 DLIST_REMOVE(file_ace, ace);
02901 SAFE_FREE(ace);
02902 }
02903 }
02904
02905 num_acls = count_canon_ace_list(file_ace);
02906 num_def_acls = count_canon_ace_list(dir_ace);
02907
02908
02909 if ((nt_ace_list = SMB_MALLOC_ARRAY(SEC_ACE,num_acls + num_profile_acls + num_def_acls)) == NULL) {
02910 DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n"));
02911 goto done;
02912 }
02913
02914 memset(nt_ace_list, '\0', (num_acls + num_def_acls) * sizeof(SEC_ACE) );
02915
02916
02917
02918
02919
02920 ace = file_ace;
02921
02922 for (i = 0; i < num_acls; i++, ace = ace->next) {
02923 SEC_ACCESS acc;
02924
02925 acc = map_canon_ace_perms(SNUM(conn),
02926 &nt_acl_type,
02927 ace->perms,
02928 fsp->is_directory);
02929 init_sec_ace(&nt_ace_list[num_aces++],
02930 &ace->trustee,
02931 nt_acl_type,
02932 acc,
02933 ace->inherited ?
02934 SEC_ACE_FLAG_INHERITED_ACE : 0);
02935 }
02936
02937
02938
02939 if (lp_profile_acls(SNUM(conn))) {
02940 SEC_ACCESS acc;
02941
02942 init_sec_access(&acc,FILE_GENERIC_ALL);
02943 init_sec_ace(&nt_ace_list[num_aces++],
02944 &global_sid_Builtin_Users,
02945 SEC_ACE_TYPE_ACCESS_ALLOWED,
02946 acc, 0);
02947 }
02948
02949 ace = dir_ace;
02950
02951 for (i = 0; i < num_def_acls; i++, ace = ace->next) {
02952 SEC_ACCESS acc;
02953
02954 acc = map_canon_ace_perms(SNUM(conn),
02955 &nt_acl_type,
02956 ace->perms,
02957 fsp->is_directory);
02958 init_sec_ace(&nt_ace_list[num_aces++],
02959 &ace->trustee,
02960 nt_acl_type,
02961 acc,
02962 SEC_ACE_FLAG_OBJECT_INHERIT|
02963 SEC_ACE_FLAG_CONTAINER_INHERIT|
02964 SEC_ACE_FLAG_INHERIT_ONLY|
02965 (ace->inherited ?
02966 SEC_ACE_FLAG_INHERITED_ACE : 0));
02967 }
02968
02969
02970
02971 if (lp_profile_acls(SNUM(conn))) {
02972 SEC_ACCESS acc;
02973
02974 init_sec_access(&acc,FILE_GENERIC_ALL);
02975 init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc,
02976 SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
02977 SEC_ACE_FLAG_INHERIT_ONLY|0);
02978 }
02979
02980
02981
02982
02983
02984
02985
02986 num_aces = merge_default_aces(nt_ace_list, num_aces);
02987
02988 }
02989
02990 if (num_aces) {
02991 if((psa = make_sec_acl( main_loop_talloc_get(), NT4_ACL_REVISION, num_aces, nt_ace_list)) == NULL) {
02992 DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n"));
02993 goto done;
02994 }
02995 }
02996 }
02997
02998 psd = make_standard_sec_desc( main_loop_talloc_get(),
02999 (security_info & OWNER_SECURITY_INFORMATION) ? &owner_sid : NULL,
03000 (security_info & GROUP_SECURITY_INFORMATION) ? &group_sid : NULL,
03001 psa,
03002 &sd_size);
03003
03004 if(!psd) {
03005 DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n"));
03006 sd_size = 0;
03007 goto done;
03008 }
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020 if (get_protected_flag(pal) || !lp_map_acl_inherit(SNUM(conn))) {
03021 psd->type |= SE_DESC_DACL_PROTECTED;
03022 }
03023
03024 if (psd->dacl) {
03025 dacl_sort_into_canonical_order(psd->dacl->aces, (unsigned int)psd->dacl->num_aces);
03026 }
03027
03028 *ppdesc = psd;
03029
03030 done:
03031
03032 if (posix_acl) {
03033 SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
03034 }
03035 if (def_acl) {
03036 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
03037 }
03038 free_canon_ace_list(file_ace);
03039 free_canon_ace_list(dir_ace);
03040 free_inherited_info(pal);
03041 SAFE_FREE(nt_ace_list);
03042
03043 return sd_size;
03044 }
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056 int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
03057 {
03058 int ret;
03059 files_struct *fsp;
03060 SMB_STRUCT_STAT st;
03061
03062 if(!CAN_WRITE(conn)) {
03063 return -1;
03064 }
03065
03066
03067
03068 ret = SMB_VFS_CHOWN(conn, fname, uid, gid);
03069 if (ret == 0)
03070 return 0;
03071
03072
03073 if (lp_enable_privileges()) {
03074
03075 BOOL has_take_ownership_priv = user_has_privileges(current_user.nt_user_token,
03076 &se_take_ownership);
03077 BOOL has_restore_priv = user_has_privileges(current_user.nt_user_token,
03078 &se_restore);
03079
03080
03081 if ( ( has_take_ownership_priv && ( uid == current_user.ut.uid ) ) ||
03082
03083 ( has_restore_priv ) ) {
03084
03085 become_root();
03086
03087 ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1);
03088 unbecome_root();
03089 return ret;
03090 }
03091 }
03092
03093
03094 if (!lp_dos_filemode(SNUM(conn))) {
03095 return -1;
03096 }
03097
03098
03099
03100
03101
03102 if (uid != current_user.ut.uid) {
03103 errno = EPERM;
03104 return -1;
03105 }
03106
03107 if (SMB_VFS_STAT(conn,fname,&st)) {
03108 return -1;
03109 }
03110
03111 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,&st,&fsp))) {
03112 return -1;
03113 }
03114
03115 become_root();
03116
03117 ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, uid, (gid_t)-1);
03118 unbecome_root();
03119
03120 close_file_fchmod(fsp);
03121
03122 return ret;
03123 }
03124
03125 #if 0
03126
03127
03128
03129
03130
03131
03132 static NTSTATUS append_parent_acl(files_struct *fsp,
03133 SMB_STRUCT_STAT *psbuf,
03134 SEC_DESC *psd,
03135 SEC_DESC **pp_new_sd)
03136 {
03137 SEC_DESC *parent_sd = NULL;
03138 files_struct *parent_fsp = NULL;
03139 TALLOC_CTX *mem_ctx = talloc_parent(psd);
03140 char *parent_name = NULL;
03141 SEC_ACE *new_ace = NULL;
03142 unsigned int num_aces = psd->dacl->num_aces;
03143 SMB_STRUCT_STAT sbuf;
03144 NTSTATUS status;
03145 int info;
03146 size_t sd_size;
03147 unsigned int i, j;
03148 BOOL is_dacl_protected = (psd->type & SE_DESC_DACL_PROTECTED);
03149
03150 ZERO_STRUCT(sbuf);
03151
03152 if (mem_ctx == NULL) {
03153 return NT_STATUS_NO_MEMORY;
03154 }
03155
03156 if (!parent_dirname_talloc(mem_ctx,
03157 fsp->fsp_name,
03158 &parent_name,
03159 NULL)) {
03160 return NT_STATUS_NO_MEMORY;
03161 }
03162
03163 status = open_directory(fsp->conn,
03164 parent_name,
03165 &sbuf,
03166 FILE_READ_ATTRIBUTES,
03167 FILE_SHARE_NONE,
03168 FILE_OPEN,
03169 0,
03170 0,
03171 &info,
03172 &parent_fsp);
03173
03174 if (!NT_STATUS_IS_OK(status)) {
03175 return status;
03176 }
03177
03178 sd_size = SMB_VFS_GET_NT_ACL(parent_fsp, parent_fsp->fsp_name,
03179 DACL_SECURITY_INFORMATION, &parent_sd );
03180
03181 close_file(parent_fsp, NORMAL_CLOSE);
03182
03183 if (!sd_size) {
03184 return NT_STATUS_ACCESS_DENIED;
03185 }
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197
03198
03199 num_aces += parent_sd->dacl->num_aces;
03200
03201 if((new_ace = TALLOC_ZERO_ARRAY(mem_ctx, SEC_ACE,
03202 num_aces)) == NULL) {
03203 return NT_STATUS_NO_MEMORY;
03204 }
03205
03206
03207 for (i = 0; i < psd->dacl->num_aces; i++) {
03208 sec_ace_copy(&new_ace[i], &psd->dacl->aces[i]);
03209 }
03210
03211
03212
03213
03214
03215
03216
03217 for (j = 0; j < parent_sd->dacl->num_aces; j++) {
03218 SEC_ACE *se = &parent_sd->dacl->aces[j];
03219
03220 if (fsp->is_directory) {
03221 if (!(se->flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
03222
03223 DEBUG(10,("append_parent_acl: directory %s "
03224 "ignoring non container "
03225 "inherit flags %u on ACE with sid %s "
03226 "from parent %s\n",
03227 fsp->fsp_name,
03228 (unsigned int)se->flags,
03229 sid_string_static(&se->trustee),
03230 parent_name));
03231 continue;
03232 }
03233 } else {
03234 if (!(se->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
03235
03236 DEBUG(10,("append_parent_acl: file %s "
03237 "ignoring non object "
03238 "inherit flags %u on ACE with sid %s "
03239 "from parent %s\n",
03240 fsp->fsp_name,
03241 (unsigned int)se->flags,
03242 sid_string_static(&se->trustee),
03243 parent_name));
03244 continue;
03245 }
03246 }
03247
03248 if (is_dacl_protected) {
03249
03250
03251
03252 unsigned int k;
03253 for (k = 0; k < psd->dacl->num_aces; k++) {
03254 if (sid_equal(&psd->dacl->aces[k].trustee,
03255 &se->trustee)) {
03256 break;
03257 }
03258 }
03259 if (k < psd->dacl->num_aces) {
03260
03261 DEBUG(10,("append_parent_acl: path %s "
03262 "ignoring ACE with protected sid %s "
03263 "from parent %s\n",
03264 fsp->fsp_name,
03265 sid_string_static(&se->trustee),
03266 parent_name));
03267 continue;
03268 }
03269 }
03270
03271 sec_ace_copy(&new_ace[i], se);
03272 if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
03273 new_ace[i].flags &= ~(SEC_ACE_FLAG_VALID_INHERIT);
03274 }
03275 new_ace[i].flags |= SEC_ACE_FLAG_INHERITED_ACE;
03276
03277 if (fsp->is_directory) {
03278
03279
03280
03281 new_ace[i].flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY);
03282 if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
03283
03284 new_ace[i].flags &=
03285 ~(SEC_ACE_FLAG_CONTAINER_INHERIT|
03286 SEC_ACE_FLAG_OBJECT_INHERIT);
03287 }
03288 } else {
03289
03290
03291
03292
03293 new_ace[i].flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|
03294 SEC_ACE_FLAG_INHERIT_ONLY|
03295 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT);
03296 }
03297
03298 i++;
03299
03300 DEBUG(10,("append_parent_acl: path %s "
03301 "inheriting ACE with sid %s "
03302 "from parent %s\n",
03303 fsp->fsp_name,
03304 sid_string_static(&se->trustee),
03305 parent_name));
03306
03307 }
03308
03309 parent_sd->dacl->aces = new_ace;
03310 parent_sd->dacl->num_aces = i;
03311
03312 *pp_new_sd = parent_sd;
03313 return status;
03314 }
03315
03316 #endif
03317
03318
03319
03320
03321
03322
03323
03324 BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
03325 {
03326 connection_struct *conn = fsp->conn;
03327 uid_t user = (uid_t)-1;
03328 gid_t grp = (gid_t)-1;
03329 SMB_STRUCT_STAT sbuf;
03330 DOM_SID file_owner_sid;
03331 DOM_SID file_grp_sid;
03332 canon_ace *file_ace_list = NULL;
03333 canon_ace *dir_ace_list = NULL;
03334 BOOL acl_perms = False;
03335 mode_t orig_mode = (mode_t)0;
03336 BOOL set_acl_as_root = False;
03337 BOOL acl_set_support = False;
03338 BOOL ret = False;
03339
03340 DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
03341
03342 if (!CAN_WRITE(conn)) {
03343 DEBUG(10,("set acl rejected on read-only share\n"));
03344 return False;
03345 }
03346
03347
03348
03349
03350
03351 if(fsp->is_directory || fsp->fh->fd == -1) {
03352 if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0)
03353 return False;
03354 } else {
03355 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0)
03356 return False;
03357 }
03358
03359
03360 orig_mode = sbuf.st_mode;
03361
03362
03363
03364
03365
03366 if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) {
03367 return False;
03368 }
03369
03370
03371
03372
03373
03374 if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) {
03375
03376 DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
03377 fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
03378
03379 if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
03380 DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
03381 fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
03382 return False;
03383 }
03384
03385
03386
03387
03388
03389
03390 if(fsp->is_directory) {
03391 if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) {
03392 return False;
03393 }
03394 } else {
03395
03396 int sret;
03397
03398 if(fsp->fh->fd == -1)
03399 sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
03400 else
03401 sret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf);
03402
03403 if(sret != 0)
03404 return False;
03405 }
03406
03407
03408 orig_mode = sbuf.st_mode;
03409
03410
03411
03412
03413 set_acl_as_root = True;
03414 }
03415
03416 create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
03417
03418 acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid,
03419 &file_ace_list, &dir_ace_list, security_info_sent, psd);
03420
03421
03422 if (!file_ace_list && !dir_ace_list) {
03423 return True;
03424 }
03425
03426 if (!acl_perms) {
03427 DEBUG(3,("set_nt_acl: cannot set permissions\n"));
03428 free_canon_ace_list(file_ace_list);
03429 free_canon_ace_list(dir_ace_list);
03430 return False;
03431 }
03432
03433
03434
03435
03436
03437 if(!(security_info_sent & DACL_SECURITY_INFORMATION) || (psd->dacl == NULL)) {
03438 free_canon_ace_list(file_ace_list);
03439 free_canon_ace_list(dir_ace_list);
03440 return True;
03441 }
03442
03443
03444
03445
03446
03447
03448 if (acl_perms && file_ace_list) {
03449 if (set_acl_as_root) {
03450 become_root();
03451 }
03452 ret = set_canon_ace_list(fsp, file_ace_list, False, sbuf.st_gid, &acl_set_support);
03453 if (set_acl_as_root) {
03454 unbecome_root();
03455 }
03456 if (acl_set_support && ret == false) {
03457 DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) ));
03458 free_canon_ace_list(file_ace_list);
03459 free_canon_ace_list(dir_ace_list);
03460 return ret;
03461 }
03462 }
03463
03464 if (acl_perms && acl_set_support && fsp->is_directory) {
03465 if (dir_ace_list) {
03466 if (set_acl_as_root) {
03467 become_root();
03468 }
03469 ret = set_canon_ace_list(fsp, dir_ace_list, True, sbuf.st_gid, &acl_set_support);
03470 if (set_acl_as_root) {
03471 unbecome_root();
03472 }
03473 if (ret == False) {
03474 DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) ));
03475 free_canon_ace_list(file_ace_list);
03476 free_canon_ace_list(dir_ace_list);
03477 return ret;
03478 }
03479 } else {
03480 int sret = -1;
03481
03482
03483
03484
03485
03486 if (set_acl_as_root) {
03487 become_root();
03488 }
03489 sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
03490 if (set_acl_as_root) {
03491 unbecome_root();
03492 }
03493 if (sret == -1) {
03494 if (acl_group_override(conn, sbuf.st_gid, fsp->fsp_name)) {
03495 DEBUG(5,("set_nt_acl: acl group control on and "
03496 "current user in file %s primary group. Override delete_def_acl\n",
03497 fsp->fsp_name ));
03498
03499 become_root();
03500 sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
03501 unbecome_root();
03502 }
03503
03504 if (sret == -1) {
03505 DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno)));
03506 free_canon_ace_list(file_ace_list);
03507 free_canon_ace_list(dir_ace_list);
03508 return False;
03509 }
03510 }
03511 }
03512 }
03513
03514 if (acl_set_support) {
03515 if (set_acl_as_root) {
03516 become_root();
03517 }
03518 store_inheritance_attributes(fsp, file_ace_list, dir_ace_list,
03519 (psd->type & SE_DESC_DACL_PROTECTED) ? True : False);
03520 if (set_acl_as_root) {
03521 unbecome_root();
03522 }
03523 }
03524
03525
03526
03527
03528
03529 if(!acl_set_support && acl_perms) {
03530 mode_t posix_perms;
03531
03532 if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) {
03533 free_canon_ace_list(file_ace_list);
03534 free_canon_ace_list(dir_ace_list);
03535 DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n",
03536 fsp->fsp_name ));
03537 return False;
03538 }
03539
03540 if (orig_mode != posix_perms) {
03541 int sret = -1;
03542
03543 DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n",
03544 fsp->fsp_name, (unsigned int)posix_perms ));
03545
03546 if (set_acl_as_root) {
03547 become_root();
03548 }
03549 sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
03550 if (set_acl_as_root) {
03551 unbecome_root();
03552 }
03553 if(sret == -1) {
03554 if (acl_group_override(conn, sbuf.st_gid, fsp->fsp_name)) {
03555 DEBUG(5,("set_nt_acl: acl group control on and "
03556 "current user in file %s primary group. Override chmod\n",
03557 fsp->fsp_name ));
03558
03559 become_root();
03560 sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
03561 unbecome_root();
03562 }
03563
03564 if (sret == -1) {
03565 DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n",
03566 fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) ));
03567 free_canon_ace_list(file_ace_list);
03568 free_canon_ace_list(dir_ace_list);
03569 return False;
03570 }
03571 }
03572 }
03573 }
03574
03575 free_canon_ace_list(file_ace_list);
03576 free_canon_ace_list(dir_ace_list);
03577 return True;
03578 }
03579
03580
03581
03582
03583
03584
03585
03586 int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode )
03587 {
03588 int entry_id = SMB_ACL_FIRST_ENTRY;
03589 SMB_ACL_ENTRY_T entry;
03590 SMB_ACL_T posix_acl;
03591 int result = -1;
03592
03593 posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
03594 if (posix_acl == (SMB_ACL_T)NULL)
03595 return -1;
03596
03597 while (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
03598 SMB_ACL_TAG_T tagtype;
03599 SMB_ACL_PERMSET_T permset;
03600
03601
03602 if (entry_id == SMB_ACL_FIRST_ENTRY)
03603 entry_id = SMB_ACL_NEXT_ENTRY;
03604
03605 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) ==-1)
03606 break;
03607
03608 if (tagtype == SMB_ACL_GROUP_OBJ) {
03609 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
03610 break;
03611 } else {
03612 *mode &= ~(S_IRGRP|S_IWGRP|S_IXGRP);
03613 *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRGRP : 0);
03614 *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWGRP : 0);
03615 *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXGRP : 0);
03616 result = 0;
03617 break;
03618 }
03619 }
03620 }
03621 SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
03622 return result;
03623 }
03624
03625
03626
03627
03628
03629
03630 static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mode_t mode)
03631 {
03632 int entry_id = SMB_ACL_FIRST_ENTRY;
03633 SMB_ACL_ENTRY_T entry;
03634 int num_entries = 0;
03635
03636 while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
03637 SMB_ACL_TAG_T tagtype;
03638 SMB_ACL_PERMSET_T permset;
03639 mode_t perms;
03640
03641
03642 if (entry_id == SMB_ACL_FIRST_ENTRY)
03643 entry_id = SMB_ACL_NEXT_ENTRY;
03644
03645 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
03646 return -1;
03647
03648 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1)
03649 return -1;
03650
03651 num_entries++;
03652
03653 switch(tagtype) {
03654 case SMB_ACL_USER_OBJ:
03655 perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR);
03656 break;
03657 case SMB_ACL_GROUP_OBJ:
03658 perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP);
03659 break;
03660 case SMB_ACL_MASK:
03661
03662
03663
03664
03665
03666
03667 perms = S_IRUSR|S_IWUSR|S_IXUSR;
03668 break;
03669 case SMB_ACL_OTHER:
03670 perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH);
03671 break;
03672 default:
03673 continue;
03674 }
03675
03676 if (map_acl_perms_to_permset(conn, perms, &permset) == -1)
03677 return -1;
03678
03679 if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) == -1)
03680 return -1;
03681 }
03682
03683
03684
03685
03686
03687
03688 if ((num_entries == 3) || (num_entries == 0))
03689 return -1;
03690
03691 return 0;
03692 }
03693
03694
03695
03696
03697
03698
03699
03700 static int copy_access_acl(connection_struct *conn, const char *from, const char *to, mode_t mode)
03701 {
03702 SMB_ACL_T posix_acl = NULL;
03703 int ret = -1;
03704
03705 if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL)
03706 return -1;
03707
03708 if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1)
03709 goto done;
03710
03711 ret = SMB_VFS_SYS_ACL_SET_FILE(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl);
03712
03713 done:
03714
03715 SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
03716 return ret;
03717 }
03718
03719
03720
03721
03722
03723
03724
03725 int chmod_acl(connection_struct *conn, const char *name, mode_t mode)
03726 {
03727 return copy_access_acl(conn, name, name, mode);
03728 }
03729
03730
03731
03732
03733
03734
03735 int inherit_access_acl(connection_struct *conn, const char *inherit_from_dir,
03736 const char *name, mode_t mode)
03737 {
03738 if (directory_has_default_acl(conn, inherit_from_dir))
03739 return 0;
03740
03741 return copy_access_acl(conn, inherit_from_dir, name, mode);
03742 }
03743
03744
03745
03746
03747
03748
03749 int fchmod_acl(files_struct *fsp, int fd, mode_t mode)
03750 {
03751 connection_struct *conn = fsp->conn;
03752 SMB_ACL_T posix_acl = NULL;
03753 int ret = -1;
03754
03755 if ((posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fd)) == NULL)
03756 return -1;
03757
03758 if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1)
03759 goto done;
03760
03761 ret = SMB_VFS_SYS_ACL_SET_FD(fsp, fd, posix_acl);
03762
03763 done:
03764
03765 SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
03766 return ret;
03767 }
03768
03769
03770
03771
03772
03773 BOOL directory_has_default_acl(connection_struct *conn, const char *fname)
03774 {
03775 SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT);
03776 BOOL has_acl = False;
03777 SMB_ACL_ENTRY_T entry;
03778
03779 if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) {
03780 has_acl = True;
03781 }
03782
03783 if (def_acl) {
03784 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
03785 }
03786 return has_acl;
03787 }
03788
03789
03790
03791
03792
03793 static BOOL unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_perm, SMB_ACL_PERMSET_T *p_permset)
03794 {
03795 if (wire_perm & ~(SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE)) {
03796 return False;
03797 }
03798
03799 if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) == -1) {
03800 return False;
03801 }
03802
03803 if (wire_perm & SMB_POSIX_ACL_READ) {
03804 if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1) {
03805 return False;
03806 }
03807 }
03808 if (wire_perm & SMB_POSIX_ACL_WRITE) {
03809 if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1) {
03810 return False;
03811 }
03812 }
03813 if (wire_perm & SMB_POSIX_ACL_EXECUTE) {
03814 if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1) {
03815 return False;
03816 }
03817 }
03818 return True;
03819 }
03820
03821
03822
03823
03824
03825 static BOOL unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt)
03826 {
03827 switch (wire_tt) {
03828 case SMB_POSIX_ACL_USER_OBJ:
03829 *p_tt = SMB_ACL_USER_OBJ;
03830 break;
03831 case SMB_POSIX_ACL_USER:
03832 *p_tt = SMB_ACL_USER;
03833 break;
03834 case SMB_POSIX_ACL_GROUP_OBJ:
03835 *p_tt = SMB_ACL_GROUP_OBJ;
03836 break;
03837 case SMB_POSIX_ACL_GROUP:
03838 *p_tt = SMB_ACL_GROUP;
03839 break;
03840 case SMB_POSIX_ACL_MASK:
03841 *p_tt = SMB_ACL_MASK;
03842 break;
03843 case SMB_POSIX_ACL_OTHER:
03844 *p_tt = SMB_ACL_OTHER;
03845 break;
03846 default:
03847 return False;
03848 }
03849 return True;
03850 }
03851
03852
03853
03854
03855
03856
03857 static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_acls, const char *pdata)
03858 {
03859 unsigned int i;
03860 SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, num_acls);
03861
03862 if (the_acl == NULL) {
03863 return NULL;
03864 }
03865
03866 for (i = 0; i < num_acls; i++) {
03867 SMB_ACL_ENTRY_T the_entry;
03868 SMB_ACL_PERMSET_T the_permset;
03869 SMB_ACL_TAG_T tag_type;
03870
03871 if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) {
03872 DEBUG(0,("create_posix_acl_from_wire: Failed to create entry %u. (%s)\n",
03873 i, strerror(errno) ));
03874 goto fail;
03875 }
03876
03877 if (!unix_ex_wire_to_tagtype(CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)), &tag_type)) {
03878 DEBUG(0,("create_posix_acl_from_wire: invalid wire tagtype %u on entry %u.\n",
03879 CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)), i ));
03880 goto fail;
03881 }
03882
03883 if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, tag_type) == -1) {
03884 DEBUG(0,("create_posix_acl_from_wire: Failed to set tagtype on entry %u. (%s)\n",
03885 i, strerror(errno) ));
03886 goto fail;
03887 }
03888
03889
03890 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) {
03891 DEBUG(0,("create_posix_acl_from_wire: Failed to get permset on entry %u. (%s)\n",
03892 i, strerror(errno) ));
03893 goto fail;
03894 }
03895
03896
03897 if (!unix_ex_wire_to_permset(conn, CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+1), &the_permset)) {
03898 DEBUG(0,("create_posix_acl_from_wire: invalid permset %u on entry %u.\n",
03899 CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE) + 1), i ));
03900 goto fail;
03901 }
03902
03903
03904 if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) {
03905 DEBUG(0,("create_posix_acl_from_wire: Failed to add permset on entry %u. (%s)\n",
03906 i, strerror(errno) ));
03907 goto fail;
03908 }
03909
03910 if (tag_type == SMB_ACL_USER) {
03911 uint32 uidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
03912 uid_t uid = (uid_t)uidval;
03913 if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&uid) == -1) {
03914 DEBUG(0,("create_posix_acl_from_wire: Failed to set uid %u on entry %u. (%s)\n",
03915 (unsigned int)uid, i, strerror(errno) ));
03916 goto fail;
03917 }
03918 }
03919
03920 if (tag_type == SMB_ACL_GROUP) {
03921 uint32 gidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
03922 gid_t gid = (uid_t)gidval;
03923 if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&gid) == -1) {
03924 DEBUG(0,("create_posix_acl_from_wire: Failed to set gid %u on entry %u. (%s)\n",
03925 (unsigned int)gid, i, strerror(errno) ));
03926 goto fail;
03927 }
03928 }
03929 }
03930
03931 return the_acl;
03932
03933 fail:
03934
03935 if (the_acl != NULL) {
03936 SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
03937 }
03938 return NULL;
03939 }
03940
03941
03942
03943
03944
03945
03946
03947
03948 BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf,
03949 uint16 num_def_acls, const char *pdata)
03950 {
03951 SMB_ACL_T def_acl = NULL;
03952
03953 if (num_def_acls && !S_ISDIR(psbuf->st_mode)) {
03954 DEBUG(5,("set_unix_posix_default_acl: Can't set default ACL on non-directory file %s\n", fname ));
03955 errno = EISDIR;
03956 return False;
03957 }
03958
03959 if (!num_def_acls) {
03960
03961 if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fname) == -1) {
03962 DEBUG(5,("set_unix_posix_default_acl: acl_delete_def_file failed on directory %s (%s)\n",
03963 fname, strerror(errno) ));
03964 return False;
03965 }
03966 return True;
03967 }
03968
03969 if ((def_acl = create_posix_acl_from_wire(conn, num_def_acls, pdata)) == NULL) {
03970 return False;
03971 }
03972
03973 if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, def_acl) == -1) {
03974 DEBUG(5,("set_unix_posix_default_acl: acl_set_file failed on directory %s (%s)\n",
03975 fname, strerror(errno) ));
03976 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
03977 return False;
03978 }
03979
03980 DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n", fname ));
03981 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
03982 return True;
03983 }
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993 static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname)
03994 {
03995 SMB_ACL_T file_acl = NULL;
03996 int entry_id = SMB_ACL_FIRST_ENTRY;
03997 SMB_ACL_ENTRY_T entry;
03998 BOOL ret = False;
03999
04000 SMB_ACL_T new_file_acl = SMB_VFS_SYS_ACL_INIT(conn, 3);
04001 SMB_ACL_ENTRY_T user_ent = NULL;
04002 SMB_ACL_ENTRY_T group_ent = NULL;
04003 SMB_ACL_ENTRY_T other_ent = NULL;
04004
04005 if (new_file_acl == NULL) {
04006 DEBUG(5,("remove_posix_acl: failed to init new ACL with 3 entries for file %s.\n", fname));
04007 return False;
04008 }
04009
04010
04011 if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &user_ent) == -1) {
04012 DEBUG(5,("remove_posix_acl: Failed to create user entry for file %s. (%s)\n",
04013 fname, strerror(errno) ));
04014 goto done;
04015 }
04016 if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, user_ent, SMB_ACL_USER_OBJ) == -1) {
04017 DEBUG(5,("remove_posix_acl: Failed to set user entry for file %s. (%s)\n",
04018 fname, strerror(errno) ));
04019 goto done;
04020 }
04021
04022 if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &group_ent) == -1) {
04023 DEBUG(5,("remove_posix_acl: Failed to create group entry for file %s. (%s)\n",
04024 fname, strerror(errno) ));
04025 goto done;
04026 }
04027 if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, group_ent, SMB_ACL_GROUP_OBJ) == -1) {
04028 DEBUG(5,("remove_posix_acl: Failed to set group entry for file %s. (%s)\n",
04029 fname, strerror(errno) ));
04030 goto done;
04031 }
04032
04033 if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &other_ent) == -1) {
04034 DEBUG(5,("remove_posix_acl: Failed to create other entry for file %s. (%s)\n",
04035 fname, strerror(errno) ));
04036 goto done;
04037 }
04038 if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, other_ent, SMB_ACL_OTHER) == -1) {
04039 DEBUG(5,("remove_posix_acl: Failed to set other entry for file %s. (%s)\n",
04040 fname, strerror(errno) ));
04041 goto done;
04042 }
04043
04044
04045 if (fsp && fsp->fh->fd != -1) {
04046 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
04047 } else {
04048 file_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_ACCESS);
04049 }
04050
04051 if (file_acl == NULL) {
04052
04053
04054 DEBUG(5,("remove_posix_acl: failed to get ACL from file %s (%s).\n",
04055 fname, strerror(errno) ));
04056 goto done;
04057 }
04058
04059 while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, file_acl, entry_id, &entry) == 1) {
04060 SMB_ACL_TAG_T tagtype;
04061 SMB_ACL_PERMSET_T permset;
04062
04063
04064 if (entry_id == SMB_ACL_FIRST_ENTRY)
04065 entry_id = SMB_ACL_NEXT_ENTRY;
04066
04067 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
04068 DEBUG(5,("remove_posix_acl: failed to get tagtype from ACL on file %s (%s).\n",
04069 fname, strerror(errno) ));
04070 goto done;
04071 }
04072
04073 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
04074 DEBUG(5,("remove_posix_acl: failed to get permset from ACL on file %s (%s).\n",
04075 fname, strerror(errno) ));
04076 goto done;
04077 }
04078
04079 if (tagtype == SMB_ACL_USER_OBJ) {
04080 if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, user_ent, permset) == -1) {
04081 DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
04082 fname, strerror(errno) ));
04083 }
04084 } else if (tagtype == SMB_ACL_GROUP_OBJ) {
04085 if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, group_ent, permset) == -1) {
04086 DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
04087 fname, strerror(errno) ));
04088 }
04089 } else if (tagtype == SMB_ACL_OTHER) {
04090 if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, other_ent, permset) == -1) {
04091 DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
04092 fname, strerror(errno) ));
04093 }
04094 }
04095 }
04096
04097
04098 if (fsp && fsp->fh->fd != -1) {
04099 if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, new_file_acl) == -1) {
04100 DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n",
04101 fname, strerror(errno) ));
04102 goto done;
04103 }
04104 } else {
04105 if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, new_file_acl) == -1) {
04106 DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n",
04107 fname, strerror(errno) ));
04108 goto done;
04109 }
04110 }
04111
04112 ret = True;
04113
04114 done:
04115
04116 if (file_acl) {
04117 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
04118 }
04119 if (new_file_acl) {
04120 SMB_VFS_SYS_ACL_FREE_ACL(conn, new_file_acl);
04121 }
04122 return ret;
04123 }
04124
04125
04126
04127
04128
04129
04130
04131 BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname, uint16 num_acls, const char *pdata)
04132 {
04133 SMB_ACL_T file_acl = NULL;
04134
04135 if (!num_acls) {
04136
04137 return remove_posix_acl(conn, fsp, fname);
04138 }
04139
04140 if ((file_acl = create_posix_acl_from_wire(conn, num_acls, pdata)) == NULL) {
04141 return False;
04142 }
04143
04144 if (fsp && fsp->fh->fd != -1) {
04145
04146 if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, file_acl) == -1) {
04147 DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n",
04148 fname, strerror(errno) ));
04149 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
04150 return False;
04151 }
04152 } else {
04153 if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, file_acl) == -1) {
04154 DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n",
04155 fname, strerror(errno) ));
04156 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
04157 return False;
04158 }
04159 }
04160
04161 DEBUG(10,("set_unix_posix_acl: set acl for file %s\n", fname ));
04162 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
04163 return True;
04164 }
04165
04166
04167
04168
04169
04170
04171
04172
04173 static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx,
04174 struct connection_struct *conn,
04175 const char *fname,
04176 SMB_STRUCT_STAT *psbuf,
04177 struct security_descriptor_info **psd)
04178 {
04179 NTSTATUS status;
04180 struct files_struct *fsp = NULL;
04181 struct security_descriptor_info *secdesc = NULL;
04182 size_t secdesc_size;
04183
04184 if (!VALID_STAT(*psbuf)) {
04185 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
04186 return map_nt_error_from_unix(errno);
04187 }
04188 }
04189
04190
04191
04192 if (S_ISDIR(psbuf->st_mode)) {
04193 status = open_directory(conn, fname, psbuf,
04194 READ_CONTROL_ACCESS,
04195 FILE_SHARE_READ|FILE_SHARE_WRITE,
04196 FILE_OPEN,
04197 0,
04198 FILE_ATTRIBUTE_DIRECTORY,
04199 NULL, &fsp);
04200 }
04201 else {
04202 status = open_file_stat(conn, fname, psbuf, &fsp);
04203 }
04204
04205 if (!NT_STATUS_IS_OK(status)) {
04206 DEBUG(3, ("Unable to open file %s: %s\n", fname,
04207 nt_errstr(status)));
04208 return status;
04209 }
04210
04211 secdesc_size = SMB_VFS_GET_NT_ACL(fsp, fname,
04212 (OWNER_SECURITY_INFORMATION |
04213 GROUP_SECURITY_INFORMATION |
04214 DACL_SECURITY_INFORMATION),
04215 &secdesc);
04216 if (secdesc_size == 0) {
04217 DEBUG(5, ("Unable to get NT ACL for file %s\n", fname));
04218 status = NT_STATUS_ACCESS_DENIED;
04219 goto done;
04220 }
04221
04222 *psd = talloc_move(mem_ctx, &secdesc);
04223 status = NT_STATUS_OK;
04224
04225 done:
04226 close_file(fsp, NORMAL_CLOSE);
04227 return status;
04228 }
04229
04230 static BOOL can_access_file_acl(struct connection_struct *conn,
04231 const char * fname, SMB_STRUCT_STAT *psbuf,
04232 uint32_t access_mask)
04233 {
04234 BOOL result;
04235 NTSTATUS status;
04236 uint32_t access_granted;
04237 struct security_descriptor_info *secdesc = NULL;
04238
04239 status = conn_get_nt_acl(tmp_talloc_ctx(), conn, fname, psbuf, &secdesc);
04240 if (!NT_STATUS_IS_OK(status)) {
04241 DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status)));
04242 return False;
04243 }
04244
04245 result = se_access_check(secdesc, current_user.nt_user_token,
04246 access_mask, &access_granted, &status);
04247 TALLOC_FREE(secdesc);
04248 return result;
04249 }
04250
04251
04252
04253
04254
04255
04256 BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
04257 {
04258 SMB_STRUCT_STAT sbuf;
04259 pstring dname;
04260
04261 if (!CAN_WRITE(conn)) {
04262 return False;
04263 }
04264
04265
04266 pstrcpy(dname, parent_dirname(fname));
04267 if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
04268 return False;
04269 }
04270
04271
04272
04273 if (!S_ISDIR(sbuf.st_mode)) {
04274 return False;
04275 }
04276 if (current_user.ut.uid == 0 || conn->admin_user) {
04277
04278 return True;
04279 }
04280
04281
04282 if (current_user.ut.uid == sbuf.st_uid) {
04283 return (sbuf.st_mode & S_IWUSR) ? True : False;
04284 }
04285
04286 #ifdef S_ISVTX
04287
04288 if (sbuf.st_mode & S_ISVTX) {
04289 SMB_STRUCT_STAT sbuf_file;
04290 if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
04291 if (errno == ENOENT) {
04292
04293
04294 return True;
04295 }
04296 return False;
04297 }
04298
04299
04300
04301
04302
04303 if (current_user.ut.uid != sbuf_file.st_uid) {
04304 return False;
04305 }
04306 }
04307 #endif
04308
04309
04310
04311 return can_access_file_acl(conn, dname, &sbuf, FILE_WRITE_DATA);
04312 }
04313
04314
04315
04316
04317
04318
04319
04320 BOOL can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask)
04321 {
04322 if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) {
04323 return False;
04324 }
04325 access_mask &= (FILE_READ_DATA|FILE_WRITE_DATA);
04326
04327
04328
04329 DEBUG(10,("can_access_file: requesting 0x%x on file %s\n",
04330 (unsigned int)access_mask, fname ));
04331
04332 if (current_user.ut.uid == 0 || conn->admin_user) {
04333
04334 return True;
04335 }
04336
04337 if (!VALID_STAT(*psbuf)) {
04338
04339 if(SMB_VFS_STAT(conn, fname, psbuf) != 0) {
04340 return False;
04341 }
04342 }
04343
04344
04345 if (current_user.ut.uid == psbuf->st_uid) {
04346 switch (access_mask) {
04347 case FILE_READ_DATA:
04348 return (psbuf->st_mode & S_IRUSR) ? True : False;
04349
04350 case FILE_WRITE_DATA:
04351 return (psbuf->st_mode & S_IWUSR) ? True : False;
04352
04353 default:
04354
04355 if ((psbuf->st_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) {
04356 return True;
04357 } else {
04358 return False;
04359 }
04360 }
04361 }
04362
04363
04364
04365 return can_access_file_acl(conn, fname, psbuf, access_mask);
04366 }
04367
04368
04369
04370
04371
04372
04373 BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
04374 {
04375 return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA);
04376 }
04377
04378
04379
04380
04381
04382
04383
04384
04385
04386
04387
04388 SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
04389 {
04390 SEC_DESC *psd, *ret_sd;
04391 connection_struct conn;
04392 files_struct finfo;
04393 struct fd_handle fh;
04394 pstring path;
04395 pstring filename;
04396
04397 ZERO_STRUCT( conn );
04398
04399 if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) {
04400 DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
04401 return NULL;
04402 }
04403
04404 if (!(conn.params = TALLOC_P(conn.mem_ctx, struct share_params))) {
04405 DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
04406 TALLOC_FREE(conn.mem_ctx);
04407 return NULL;
04408 }
04409
04410 conn.params->service = -1;
04411
04412 pstrcpy( path, "/" );
04413 set_conn_connectpath(&conn, path);
04414
04415 if (!smbd_vfs_init(&conn)) {
04416 DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
04417 conn_free_internal( &conn );
04418 return NULL;
04419 }
04420
04421 ZERO_STRUCT( finfo );
04422 ZERO_STRUCT( fh );
04423
04424 finfo.fnum = -1;
04425 finfo.conn = &conn;
04426 finfo.fh = &fh;
04427 finfo.fh->fd = -1;
04428 pstrcpy( filename, fname );
04429 finfo.fsp_name = filename;
04430
04431 if (get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd ) == 0) {
04432 DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
04433 conn_free_internal( &conn );
04434 return NULL;
04435 }
04436
04437 ret_sd = dup_sec_desc( ctx, psd );
04438
04439 conn_free_internal( &conn );
04440
04441 return ret_sd;
04442 }