LCOV - code coverage report
Current view: top level - source3/libsmb - libsmb_xattr.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 289 1242 23.3 %
Date: 2024-05-31 13:13:24 Functions: 4 16 25.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/Netbios implementation.
       3             :    SMB client library implementation
       4             :    Copyright (C) Andrew Tridgell 1998
       5             :    Copyright (C) Richard Sharpe 2000, 2002
       6             :    Copyright (C) John Terpstra 2000
       7             :    Copyright (C) Tom Jansen (Ninja ISD) 2002
       8             :    Copyright (C) Derrell Lipman 2003-2008
       9             :    Copyright (C) Jeremy Allison 2007, 2008
      10             : 
      11             :    This program is free software; you can redistribute it and/or modify
      12             :    it under the terms of the GNU General Public License as published by
      13             :    the Free Software Foundation; either version 3 of the License, or
      14             :    (at your option) any later version.
      15             : 
      16             :    This program is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :    GNU General Public License for more details.
      20             : 
      21             :    You should have received a copy of the GNU General Public License
      22             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "includes.h"
      26             : #include "libsmb/libsmb.h"
      27             : #include "libsmbclient.h"
      28             : #include "libsmb_internal.h"
      29             : #include "../librpc/gen_ndr/ndr_lsa.h"
      30             : #include "rpc_client/rpc_client.h"
      31             : #include "rpc_client/cli_lsarpc.h"
      32             : #include "../libcli/security/security.h"
      33             : #include "lib/util/string_wrappers.h"
      34             : 
      35             : /*
      36             :  * Find an lsa pipe handle associated with a cli struct.
      37             :  */
      38             : static struct rpc_pipe_client *
      39          40 : find_lsa_pipe_hnd(struct cli_state *ipc_cli)
      40             : {
      41           0 :         struct rpc_pipe_client *pipe_hnd;
      42             : 
      43          40 :         for (pipe_hnd = ipc_cli->pipe_list;
      44          40 :              pipe_hnd;
      45           0 :              pipe_hnd = pipe_hnd->next) {
      46          40 :                 if (ndr_syntax_id_equal(&pipe_hnd->abstract_syntax,
      47             :                                         &ndr_table_lsarpc.syntax_id)) {
      48          40 :                         return pipe_hnd;
      49             :                 }
      50             :         }
      51           0 :         return NULL;
      52             : }
      53             : 
      54             : /*
      55             :  * Sort ACEs according to the documentation at
      56             :  * http://support.microsoft.com/kb/269175, at least as far as it defines the
      57             :  * order.
      58             :  */
      59             : 
      60             : static int
      61           0 : ace_compare(struct security_ace *ace1,
      62             :             struct security_ace *ace2)
      63             : {
      64           0 :         bool b1;
      65           0 :         bool b2;
      66             : 
      67             :         /* If the ACEs are equal, we have nothing more to do. */
      68           0 :         if (security_ace_equal(ace1, ace2)) {
      69           0 :                 return 0;
      70             :         }
      71             : 
      72             :         /* Inherited follow non-inherited */
      73           0 :         b1 = ((ace1->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0);
      74           0 :         b2 = ((ace2->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0);
      75           0 :         if (b1 != b2) {
      76           0 :                 return (b1 ? 1 : -1);
      77             :         }
      78             : 
      79             :         /*
      80             :          * What shall we do with AUDITs and ALARMs?  It's undefined.  We'll
      81             :          * sort them after DENY and ALLOW.
      82             :          */
      83           0 :         b1 = (ace1->type != SEC_ACE_TYPE_ACCESS_ALLOWED &&
      84           0 :               ace1->type != SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT &&
      85           0 :               ace1->type != SEC_ACE_TYPE_ACCESS_DENIED &&
      86           0 :               ace1->type != SEC_ACE_TYPE_ACCESS_DENIED_OBJECT);
      87           0 :         b2 = (ace2->type != SEC_ACE_TYPE_ACCESS_ALLOWED &&
      88           0 :               ace2->type != SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT &&
      89           0 :               ace2->type != SEC_ACE_TYPE_ACCESS_DENIED &&
      90           0 :               ace2->type != SEC_ACE_TYPE_ACCESS_DENIED_OBJECT);
      91           0 :         if (b1 != b2) {
      92           0 :                 return (b1 ? 1 : -1);
      93             :         }
      94             : 
      95             :         /* Allowed ACEs follow denied ACEs */
      96           0 :         b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED ||
      97           0 :               ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT);
      98           0 :         b2 = (ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED ||
      99           0 :               ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT);
     100           0 :         if (b1 != b2) {
     101           0 :                 return (b1 ? 1 : -1);
     102             :         }
     103             : 
     104             :         /*
     105             :          * ACEs applying to an entity's object follow those applying to the
     106             :          * entity itself
     107             :          */
     108           0 :         b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
     109           0 :               ace1->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT);
     110           0 :         b2 = (ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
     111           0 :               ace2->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT);
     112           0 :         if (b1 != b2) {
     113           0 :                 return (b1 ? 1 : -1);
     114             :         }
     115             : 
     116             :         /*
     117             :          * If we get this far, the ACEs are similar as far as the
     118             :          * characteristics we typically care about (those defined by the
     119             :          * referenced MS document).  We'll now sort by characteristics that
     120             :          * just seems reasonable.
     121             :          */
     122             : 
     123           0 :         if (ace1->type != ace2->type) {
     124             :                 /*
     125             :                  * ace2 and ace1 are reversed here, so that
     126             :                  * ACCESS_DENIED_ACE_TYPE (1) sorts before
     127             :                  * ACCESS_ALLOWED_ACE_TYPE (0), which is the order you
     128             :                  * usually want.
     129             :                  */
     130           0 :                 return NUMERIC_CMP(ace2->type, ace1->type);
     131             :         }
     132             : 
     133           0 :         if (dom_sid_compare(&ace1->trustee, &ace2->trustee)) {
     134           0 :                 return dom_sid_compare(&ace1->trustee, &ace2->trustee);
     135             :         }
     136             : 
     137           0 :         if (ace1->flags != ace2->flags) {
     138           0 :                 return NUMERIC_CMP(ace1->flags, ace2->flags);
     139             :         }
     140             : 
     141           0 :         if (ace1->access_mask != ace2->access_mask) {
     142           0 :                 return NUMERIC_CMP(ace1->access_mask, ace2->access_mask);
     143             :         }
     144             : 
     145           0 :         if (ace1->size != ace2->size) {
     146           0 :                 return NUMERIC_CMP(ace1->size, ace2->size);
     147             :         }
     148             : 
     149           0 :         return memcmp(ace1, ace2, sizeof(struct security_ace));
     150             : }
     151             : 
     152             : 
     153             : static void
     154           0 : sort_acl(struct security_acl *the_acl)
     155             : {
     156           0 :         uint32_t i;
     157           0 :         if (!the_acl) return;
     158             : 
     159           0 :         TYPESAFE_QSORT(the_acl->aces, the_acl->num_aces, ace_compare);
     160             : 
     161           0 :         for (i=1;i<the_acl->num_aces;) {
     162           0 :                 if (security_ace_equal(&the_acl->aces[i-1],
     163           0 :                                        &the_acl->aces[i])) {
     164           0 :                         ARRAY_DEL_ELEMENT(
     165           0 :                                 the_acl->aces, i, the_acl->num_aces);
     166           0 :                         the_acl->num_aces--;
     167             :                 } else {
     168           0 :                         i++;
     169             :                 }
     170             :         }
     171             : }
     172             : 
     173             : /* convert a SID to a string, either numeric or username/group */
     174             : static void
     175          40 : convert_sid_to_string(struct cli_state *ipc_cli,
     176             :                       struct policy_handle *pol,
     177             :                       fstring str,
     178             :                       bool numeric,
     179             :                       struct dom_sid *sid)
     180             : {
     181          40 :         char **domains = NULL;
     182          40 :         char **names = NULL;
     183          40 :         enum lsa_SidType *types = NULL;
     184          40 :         struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli);
     185           0 :         TALLOC_CTX *ctx;
     186             : 
     187          40 :         sid_to_fstring(str, sid);
     188             : 
     189          40 :         if (numeric) {
     190          40 :                 return;     /* no lookup desired */
     191             :         }
     192             : 
     193           0 :         if (!pipe_hnd) {
     194           0 :                 return;
     195             :         }
     196             : 
     197             :         /* Ask LSA to convert the sid to a name */
     198             : 
     199           0 :         ctx = talloc_stackframe();
     200             : 
     201           0 :         if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(pipe_hnd, ctx,
     202             :                                                     pol, 1, sid, &domains,
     203           0 :                                                     &names, &types)) ||
     204           0 :             !domains || !domains[0] || !names || !names[0]) {
     205           0 :                 TALLOC_FREE(ctx);
     206           0 :                 return;
     207             :         }
     208             : 
     209             :         /* Converted OK */
     210             : 
     211           0 :         fstr_sprintf(str, "%s%s%s",
     212             :                      domains[0], lp_winbind_separator(), names[0]);
     213             : 
     214           0 :         TALLOC_FREE(ctx);
     215             : }
     216             : 
     217             : /* convert a string to a SID, either numeric or username/group */
     218             : static bool
     219           0 : convert_string_to_sid(struct cli_state *ipc_cli,
     220             :                       struct policy_handle *pol,
     221             :                       bool numeric,
     222             :                       struct dom_sid *sid,
     223             :                       const char *str)
     224             : {
     225           0 :         enum lsa_SidType *types = NULL;
     226           0 :         struct dom_sid *sids = NULL;
     227           0 :         bool result = True;
     228           0 :         TALLOC_CTX *ctx = NULL;
     229           0 :         struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli);
     230             : 
     231           0 :         if (!pipe_hnd) {
     232           0 :                 return False;
     233             :         }
     234             : 
     235           0 :         if (numeric) {
     236           0 :                 if (strncmp(str, "S-", 2) == 0) {
     237           0 :                         return string_to_sid(sid, str);
     238             :                 }
     239             : 
     240           0 :                 result = False;
     241           0 :                 goto done;
     242             :         }
     243             : 
     244           0 :         ctx = talloc_stackframe();
     245           0 :         if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(pipe_hnd, ctx,
     246             :                                                      pol, 1, &str,
     247             :                                                      NULL, 1, &sids,
     248             :                                                      &types))) {
     249           0 :                 result = False;
     250           0 :                 goto done;
     251             :         }
     252             : 
     253           0 :         sid_copy(sid, &sids[0]);
     254           0 : done:
     255           0 :         TALLOC_FREE(ctx);
     256           0 :         return result;
     257             : }
     258             : 
     259             : 
     260             : /* parse an struct security_ace in the same format as print_ace() */
     261             : static bool
     262           0 : parse_ace(struct cli_state *ipc_cli,
     263             :           struct policy_handle *pol,
     264             :           struct security_ace *ace,
     265             :           bool numeric,
     266             :           char *str)
     267             : {
     268           0 :         char *p;
     269           0 :         const char *cp;
     270           0 :         char *tok;
     271           0 :         unsigned int atype;
     272           0 :         unsigned int aflags;
     273           0 :         unsigned int amask;
     274           0 :         struct dom_sid sid;
     275           0 :         uint32_t mask;
     276           0 :         struct perm_value {
     277             :                 const char perm[7];
     278             :                 uint32_t mask;
     279             :         };
     280           0 :         size_t i;
     281           0 :         TALLOC_CTX *frame = talloc_stackframe();
     282             : 
     283             :         /* These values discovered by inspection */
     284           0 :         static const struct perm_value special_values[] = {
     285             :                 { "R", 0x00120089 },
     286             :                 { "W", 0x00120116 },
     287             :                 { "X", 0x001200a0 },
     288             :                 { "D", 0x00010000 },
     289             :                 { "P", 0x00040000 },
     290             :                 { "O", 0x00080000 },
     291             :         };
     292             : 
     293           0 :         static const struct perm_value standard_values[] = {
     294             :                 { "READ",   0x001200a9 },
     295             :                 { "CHANGE", 0x001301bf },
     296             :                 { "FULL",   0x001f01ff },
     297             :         };
     298             : 
     299           0 :         ZERO_STRUCTP(ace);
     300           0 :         p = strchr_m(str,':');
     301           0 :         if (!p) {
     302           0 :                 TALLOC_FREE(frame);
     303           0 :                 return False;
     304             :         }
     305           0 :         *p = '\0';
     306           0 :         p++;
     307             :         /* Try to parse numeric form */
     308             : 
     309           0 :         if (sscanf(p, "%u/%u/%u", &atype, &aflags, &amask) == 3 &&
     310           0 :             convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) {
     311           0 :                 goto done;
     312             :         }
     313             : 
     314             :         /* Try to parse text form */
     315             : 
     316           0 :         if (!convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) {
     317           0 :                 TALLOC_FREE(frame);
     318           0 :                 return false;
     319             :         }
     320             : 
     321           0 :         cp = p;
     322           0 :         if (!next_token_talloc(frame, &cp, &tok, "/")) {
     323           0 :                 TALLOC_FREE(frame);
     324           0 :                 return false;
     325             :         }
     326             : 
     327           0 :         if (strncasecmp_m(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
     328           0 :                 atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
     329           0 :         } else if (strncasecmp_m(tok, "DENIED", strlen("DENIED")) == 0) {
     330           0 :                 atype = SEC_ACE_TYPE_ACCESS_DENIED;
     331             :         } else {
     332           0 :                 TALLOC_FREE(frame);
     333           0 :                 return false;
     334             :         }
     335             : 
     336             :         /* Only numeric form accepted for flags at present */
     337             : 
     338           0 :         if (!(next_token_talloc(frame, &cp, &tok, "/") &&
     339           0 :               sscanf(tok, "%u", &aflags))) {
     340           0 :                 TALLOC_FREE(frame);
     341           0 :                 return false;
     342             :         }
     343             : 
     344           0 :         if (!next_token_talloc(frame, &cp, &tok, "/")) {
     345           0 :                 TALLOC_FREE(frame);
     346           0 :                 return false;
     347             :         }
     348             : 
     349           0 :         if (strncmp(tok, "0x", 2) == 0) {
     350           0 :                 if (sscanf(tok, "%u", &amask) != 1) {
     351           0 :                         TALLOC_FREE(frame);
     352           0 :                         return false;
     353             :                 }
     354           0 :                 goto done;
     355             :         }
     356             : 
     357           0 :         for (i = 0; i < ARRAY_SIZE(standard_values); i++) {
     358           0 :                 const struct perm_value *v = &standard_values[i];
     359           0 :                 if (strcmp(tok, v->perm) == 0) {
     360           0 :                         amask = v->mask;
     361           0 :                         goto done;
     362             :                 }
     363             :         }
     364             : 
     365           0 :         p = tok;
     366             : 
     367           0 :         while(*p) {
     368           0 :                 bool found = False;
     369             : 
     370           0 :                 for (i = 0; i < ARRAY_SIZE(special_values); i++) {
     371           0 :                         const struct perm_value *v = &special_values[i];
     372           0 :                         if (v->perm[0] == *p) {
     373           0 :                                 amask |= v->mask;
     374           0 :                                 found = True;
     375             :                         }
     376             :                 }
     377             : 
     378           0 :                 if (!found) {
     379           0 :                         TALLOC_FREE(frame);
     380           0 :                         return false;
     381             :                 }
     382           0 :                 p++;
     383             :         }
     384             : 
     385           0 :         if (*p) {
     386           0 :                 TALLOC_FREE(frame);
     387           0 :                 return false;
     388             :         }
     389             : 
     390           0 : done:
     391           0 :         mask = amask;
     392           0 :         init_sec_ace(ace, &sid, atype, mask, aflags);
     393           0 :         TALLOC_FREE(frame);
     394           0 :         return true;
     395             : }
     396             : 
     397             : /* add an struct security_ace to a list of struct security_aces in a struct security_acl */
     398             : static bool
     399           0 : add_ace(struct security_acl **the_acl,
     400             :         const struct security_ace *ace,
     401             :         TALLOC_CTX *ctx)
     402             : {
     403           0 :         struct security_acl *acl = *the_acl;
     404             : 
     405           0 :         if (acl == NULL) {
     406           0 :                 acl = make_sec_acl(ctx, 3, 0, NULL);
     407           0 :                 if (acl == NULL) {
     408           0 :                         return false;
     409             :                 }
     410             :         }
     411             : 
     412           0 :         if (acl->num_aces == UINT32_MAX) {
     413           0 :                 return false;
     414             :         }
     415           0 :         ADD_TO_ARRAY(
     416             :                 acl, struct security_ace, *ace, &acl->aces, &acl->num_aces);
     417           0 :         *the_acl = acl;
     418           0 :         return True;
     419             : }
     420             : 
     421             : 
     422             : /* parse a ascii version of a security descriptor */
     423             : static struct security_descriptor *
     424           0 : sec_desc_parse(TALLOC_CTX *ctx,
     425             :                struct cli_state *ipc_cli,
     426             :                struct policy_handle *pol,
     427             :                bool numeric,
     428             :                const char *str)
     429             : {
     430           0 :         const char *p = str;
     431           0 :         char *tok;
     432           0 :         struct security_descriptor *ret = NULL;
     433           0 :         size_t sd_size;
     434           0 :         struct dom_sid owner_sid = { .num_auths = 0 };
     435           0 :         struct dom_sid group_sid = { .num_auths = 0 };
     436           0 :         bool have_owner = false, have_group = false;
     437           0 :         struct security_acl *dacl=NULL;
     438           0 :         int revision=1;
     439             : 
     440           0 :         while (next_token_talloc(ctx, &p, &tok, "\t,\r\n")) {
     441             : 
     442           0 :                 if (strncasecmp_m(tok,"REVISION:", 9) == 0) {
     443           0 :                         revision = strtol(tok+9, NULL, 16);
     444           0 :                         continue;
     445             :                 }
     446             : 
     447           0 :                 if (strncasecmp_m(tok,"OWNER:", 6) == 0) {
     448           0 :                         if (have_owner) {
     449           0 :                                 DEBUG(5,("OWNER specified more than once!\n"));
     450           0 :                                 goto done;
     451             :                         }
     452           0 :                         if (!convert_string_to_sid(ipc_cli, pol,
     453             :                                                    numeric,
     454           0 :                                                    &owner_sid, tok+6)) {
     455           0 :                                 DEBUG(5, ("Failed to parse owner sid\n"));
     456           0 :                                 goto done;
     457             :                         }
     458           0 :                         have_owner = true;
     459           0 :                         continue;
     460             :                 }
     461             : 
     462           0 :                 if (strncasecmp_m(tok,"OWNER+:", 7) == 0) {
     463           0 :                         if (have_owner) {
     464           0 :                                 DEBUG(5,("OWNER specified more than once!\n"));
     465           0 :                                 goto done;
     466             :                         }
     467           0 :                         if (!convert_string_to_sid(ipc_cli, pol,
     468             :                                                    False,
     469           0 :                                                    &owner_sid, tok+7)) {
     470           0 :                                 DEBUG(5, ("Failed to parse owner sid\n"));
     471           0 :                                 goto done;
     472             :                         }
     473           0 :                         have_owner = true;
     474           0 :                         continue;
     475             :                 }
     476             : 
     477           0 :                 if (strncasecmp_m(tok,"GROUP:", 6) == 0) {
     478           0 :                         if (have_group) {
     479           0 :                                 DEBUG(5,("GROUP specified more than once!\n"));
     480           0 :                                 goto done;
     481             :                         }
     482           0 :                         if (!convert_string_to_sid(ipc_cli, pol,
     483             :                                                    numeric,
     484           0 :                                                    &group_sid, tok+6)) {
     485           0 :                                 DEBUG(5, ("Failed to parse group sid\n"));
     486           0 :                                 goto done;
     487             :                         }
     488           0 :                         have_group = true;
     489           0 :                         continue;
     490             :                 }
     491             : 
     492           0 :                 if (strncasecmp_m(tok,"GROUP+:", 7) == 0) {
     493           0 :                         if (have_group) {
     494           0 :                                 DEBUG(5,("GROUP specified more than once!\n"));
     495           0 :                                 goto done;
     496             :                         }
     497           0 :                         if (!convert_string_to_sid(ipc_cli, pol,
     498             :                                                    False,
     499           0 :                                                    &group_sid, tok+6)) {
     500           0 :                                 DEBUG(5, ("Failed to parse group sid\n"));
     501           0 :                                 goto done;
     502             :                         }
     503           0 :                         have_group = true;
     504           0 :                         continue;
     505             :                 }
     506             : 
     507           0 :                 if (strncasecmp_m(tok,"ACL:", 4) == 0) {
     508           0 :                         struct security_ace ace;
     509           0 :                         if (!parse_ace(ipc_cli, pol, &ace, numeric, tok+4)) {
     510           0 :                                 DEBUG(5, ("Failed to parse ACL %s\n", tok));
     511           0 :                                 goto done;
     512             :                         }
     513           0 :                         if(!add_ace(&dacl, &ace, ctx)) {
     514           0 :                                 DEBUG(5, ("Failed to add ACL %s\n", tok));
     515           0 :                                 goto done;
     516             :                         }
     517           0 :                         continue;
     518             :                 }
     519             : 
     520           0 :                 if (strncasecmp_m(tok,"ACL+:", 5) == 0) {
     521           0 :                         struct security_ace ace;
     522           0 :                         if (!parse_ace(ipc_cli, pol, &ace, False, tok+5)) {
     523           0 :                                 DEBUG(5, ("Failed to parse ACL %s\n", tok));
     524           0 :                                 goto done;
     525             :                         }
     526           0 :                         if(!add_ace(&dacl, &ace, ctx)) {
     527           0 :                                 DEBUG(5, ("Failed to add ACL %s\n", tok));
     528           0 :                                 goto done;
     529             :                         }
     530           0 :                         continue;
     531             :                 }
     532             : 
     533           0 :                 DEBUG(5, ("Failed to parse security descriptor\n"));
     534           0 :                 goto done;
     535             :         }
     536             : 
     537           0 :         ret = make_sec_desc(
     538             :                 ctx,
     539             :                 revision,
     540             :                 SEC_DESC_SELF_RELATIVE,
     541             :                 have_owner ? &owner_sid : NULL,
     542             :                 have_group ? &group_sid : NULL,
     543             :                 NULL,
     544             :                 dacl,
     545             :                 &sd_size);
     546             : 
     547           0 : done:
     548           0 :         return ret;
     549             : }
     550             : 
     551             : 
     552             : /* Obtain the current dos attributes */
     553             : static struct DOS_ATTR_DESC *
     554           0 : dos_attr_query(SMBCCTX *context,
     555             :                TALLOC_CTX *ctx,
     556             :                const char *filename,
     557             :                SMBCSRV *srv)
     558             : {
     559           0 :         struct stat sb = {0};
     560           0 :         struct DOS_ATTR_DESC *ret = NULL;
     561           0 :         NTSTATUS status;
     562             : 
     563           0 :         ret = talloc(ctx, struct DOS_ATTR_DESC);
     564           0 :         if (!ret) {
     565           0 :                 errno = ENOMEM;
     566           0 :                 return NULL;
     567             :         }
     568             : 
     569             :         /* Obtain the DOS attributes */
     570           0 :         status = SMBC_getatr(context, srv, filename, &sb);
     571           0 :         if (!NT_STATUS_IS_OK(status)) {
     572           0 :                 DEBUG(5, ("dos_attr_query Failed to query old attributes\n"));
     573           0 :                 TALLOC_FREE(ret);
     574           0 :                 errno = cli_status_to_errno(status);
     575           0 :                 return NULL;
     576             :         }
     577             : 
     578           0 :         ret->mode = sb.st_mode;
     579           0 :         ret->size = sb.st_size;
     580           0 :         ret->create_time = sb.st_ctime;
     581           0 :         ret->access_time = sb.st_atime;
     582           0 :         ret->write_time = sb.st_mtime;
     583           0 :         ret->change_time = sb.st_mtime;
     584           0 :         ret->inode = sb.st_ino;
     585             : 
     586           0 :         return ret;
     587             : }
     588             : 
     589             : 
     590             : /* parse a ascii version of a security descriptor */
     591             : static void
     592           0 : dos_attr_parse(SMBCCTX *context,
     593             :                struct DOS_ATTR_DESC *dad,
     594             :                SMBCSRV *srv,
     595             :                char *str)
     596             : {
     597           0 :         int n;
     598           0 :         const char *p = str;
     599           0 :         char *tok = NULL;
     600           0 :         TALLOC_CTX *frame = NULL;
     601           0 :         struct {
     602             :                 const char * create_time_attr;
     603             :                 const char * access_time_attr;
     604             :                 const char * write_time_attr;
     605             :                 const char * change_time_attr;
     606             :         } attr_strings;
     607             : 
     608             :         /* Determine whether to use old-style or new-style attribute names */
     609           0 :         if (context->internal->full_time_names) {
     610             :                 /* new-style names */
     611           0 :                 attr_strings.create_time_attr = "CREATE_TIME";
     612           0 :                 attr_strings.access_time_attr = "ACCESS_TIME";
     613           0 :                 attr_strings.write_time_attr = "WRITE_TIME";
     614           0 :                 attr_strings.change_time_attr = "CHANGE_TIME";
     615             :         } else {
     616             :                 /* old-style names */
     617           0 :                 attr_strings.create_time_attr = NULL;
     618           0 :                 attr_strings.access_time_attr = "A_TIME";
     619           0 :                 attr_strings.write_time_attr = "M_TIME";
     620           0 :                 attr_strings.change_time_attr = "C_TIME";
     621             :         }
     622             : 
     623             :         /* if this is to set the entire ACL... */
     624           0 :         if (*str == '*') {
     625             :                 /* ... then increment past the first colon if there is one */
     626           0 :                 if ((p = strchr(str, ':')) != NULL) {
     627           0 :                         ++p;
     628             :                 } else {
     629           0 :                         p = str;
     630             :                 }
     631             :         }
     632             : 
     633           0 :         frame = talloc_stackframe();
     634           0 :         while (next_token_talloc(frame, &p, &tok, "\t,\r\n")) {
     635           0 :                 if (strncasecmp_m(tok, "MODE:", 5) == 0) {
     636           0 :                         long request = strtol(tok+5, NULL, 16);
     637           0 :                         if (request == 0) {
     638           0 :                                 dad->mode =
     639           0 :                                         (dad->mode & FILE_ATTRIBUTE_DIRECTORY)
     640             :                                                 ? FILE_ATTRIBUTE_DIRECTORY
     641             :                                                 : FILE_ATTRIBUTE_NORMAL;
     642             :                         } else {
     643           0 :                                 dad->mode = request;
     644             :                         }
     645           0 :                         continue;
     646             :                 }
     647             : 
     648           0 :                 if (strncasecmp_m(tok, "SIZE:", 5) == 0) {
     649           0 :                         dad->size = (off_t)atof(tok+5);
     650           0 :                         continue;
     651             :                 }
     652             : 
     653           0 :                 n = strlen(attr_strings.access_time_attr);
     654           0 :                 if (strncasecmp_m(tok, attr_strings.access_time_attr, n) == 0) {
     655           0 :                         dad->access_time = (time_t)strtol(tok+n+1, NULL, 10);
     656           0 :                         continue;
     657             :                 }
     658             : 
     659           0 :                 n = strlen(attr_strings.change_time_attr);
     660           0 :                 if (strncasecmp_m(tok, attr_strings.change_time_attr, n) == 0) {
     661           0 :                         dad->change_time = (time_t)strtol(tok+n+1, NULL, 10);
     662           0 :                         continue;
     663             :                 }
     664             : 
     665           0 :                 n = strlen(attr_strings.write_time_attr);
     666           0 :                 if (strncasecmp_m(tok, attr_strings.write_time_attr, n) == 0) {
     667           0 :                         dad->write_time = (time_t)strtol(tok+n+1, NULL, 10);
     668           0 :                         continue;
     669             :                 }
     670             : 
     671           0 :                 if (attr_strings.create_time_attr != NULL) {
     672           0 :                         n = strlen(attr_strings.create_time_attr);
     673           0 :                         if (strncasecmp_m(tok, attr_strings.create_time_attr,
     674             :                                         n) == 0) {
     675           0 :                                 dad->create_time = (time_t)strtol(tok+n+1,
     676             :                                                                   NULL, 10);
     677           0 :                                 continue;
     678             :                         }
     679             :                 }
     680             : 
     681           0 :                 if (strncasecmp_m(tok, "INODE:", 6) == 0) {
     682           0 :                         dad->inode = (SMB_INO_T)atof(tok+6);
     683           0 :                         continue;
     684             :                 }
     685             :         }
     686           0 :         TALLOC_FREE(frame);
     687           0 : }
     688             : 
     689             : /*****************************************************
     690             :  Retrieve the acls for a file.
     691             : *******************************************************/
     692             : 
     693             : static int
     694           8 : cacl_get(SMBCCTX *context,
     695             :          TALLOC_CTX *ctx,
     696             :          SMBCSRV *srv,
     697             :          struct cli_state *ipc_cli,
     698             :          struct policy_handle *pol,
     699             :          const char *filename,
     700             :          const char *attr_name,
     701             :          char *buf,
     702             :          int bufsize)
     703             : {
     704           0 :         uint32_t i;
     705           8 :         int n = 0;
     706           0 :         int n_used;
     707           0 :         bool all;
     708           0 :         bool all_nt;
     709           0 :         bool all_nt_acls;
     710           0 :         bool all_dos;
     711           0 :         bool some_nt;
     712           0 :         bool some_dos;
     713           8 :         bool exclude_nt_revision = False;
     714           8 :         bool exclude_nt_owner = False;
     715           8 :         bool exclude_nt_group = False;
     716           8 :         bool exclude_nt_acl = False;
     717           8 :         bool exclude_dos_mode = False;
     718           8 :         bool exclude_dos_size = False;
     719           8 :         bool exclude_dos_create_time = False;
     720           8 :         bool exclude_dos_access_time = False;
     721           8 :         bool exclude_dos_write_time = False;
     722           8 :         bool exclude_dos_change_time = False;
     723           8 :         bool exclude_dos_inode = False;
     724           8 :         bool numeric = True;
     725           8 :         bool determine_size = (bufsize == 0);
     726           0 :         uint16_t fnum;
     727           0 :         struct security_descriptor *sd;
     728           0 :         fstring sidstr;
     729           0 :         fstring name_sandbox;
     730           0 :         char *name;
     731           0 :         char *pExclude;
     732           0 :         char *p;
     733           8 :         struct cli_state *cli = srv->cli;
     734           0 :         struct {
     735             :                 const char * create_time_attr;
     736             :                 const char * access_time_attr;
     737             :                 const char * write_time_attr;
     738             :                 const char * change_time_attr;
     739             :         } attr_strings;
     740           0 :         struct {
     741             :                 const char * create_time_attr;
     742             :                 const char * access_time_attr;
     743             :                 const char * write_time_attr;
     744             :                 const char * change_time_attr;
     745             :         } excl_attr_strings;
     746             : 
     747             :         /* Determine whether to use old-style or new-style attribute names */
     748           8 :         if (context->internal->full_time_names) {
     749             :                 /* new-style names */
     750           0 :                 attr_strings.create_time_attr = "CREATE_TIME";
     751           0 :                 attr_strings.access_time_attr = "ACCESS_TIME";
     752           0 :                 attr_strings.write_time_attr = "WRITE_TIME";
     753           0 :                 attr_strings.change_time_attr = "CHANGE_TIME";
     754             : 
     755           0 :                 excl_attr_strings.create_time_attr = "CREATE_TIME";
     756           0 :                 excl_attr_strings.access_time_attr = "ACCESS_TIME";
     757           0 :                 excl_attr_strings.write_time_attr = "WRITE_TIME";
     758           0 :                 excl_attr_strings.change_time_attr = "CHANGE_TIME";
     759             :         } else {
     760             :                 /* old-style names */
     761           8 :                 attr_strings.create_time_attr = NULL;
     762           8 :                 attr_strings.access_time_attr = "A_TIME";
     763           8 :                 attr_strings.write_time_attr = "M_TIME";
     764           8 :                 attr_strings.change_time_attr = "C_TIME";
     765             : 
     766           8 :                 excl_attr_strings.create_time_attr = NULL;
     767           8 :                 excl_attr_strings.access_time_attr = "dos_attr.A_TIME";
     768           8 :                 excl_attr_strings.write_time_attr = "dos_attr.M_TIME";
     769           8 :                 excl_attr_strings.change_time_attr = "dos_attr.C_TIME";
     770             :         }
     771             : 
     772             :         /* Copy name so we can strip off exclusions (if any are specified) */
     773           8 :         fstrcpy(name_sandbox, attr_name);
     774             : 
     775             :         /* Ensure name is null terminated */
     776           8 :         name_sandbox[sizeof(name_sandbox) - 1] = '\0';
     777             : 
     778             :         /* Play in the sandbox */
     779           8 :         name = name_sandbox;
     780             : 
     781             :         /* If there are any exclusions, point to them and mask them from name */
     782           8 :         if ((pExclude = strchr(name, '!')) != NULL)
     783             :         {
     784           0 :                 *pExclude++ = '\0';
     785             :         }
     786             : 
     787           8 :         all = (strncasecmp_m(name, "system.*", 8) == 0);
     788           8 :         all_nt = (strncasecmp_m(name, "system.nt_sec_desc.*", 20) == 0);
     789           8 :         all_nt_acls = (strncasecmp_m(name, "system.nt_sec_desc.acl.*", 24) == 0);
     790           8 :         all_dos = (strncasecmp_m(name, "system.dos_attr.*", 17) == 0);
     791           8 :         some_nt = (strncasecmp_m(name, "system.nt_sec_desc.", 19) == 0);
     792           8 :         some_dos = (strncasecmp_m(name, "system.dos_attr.", 16) == 0);
     793           8 :         numeric = (* (name + strlen(name) - 1) != '+');
     794             : 
     795             :         /* Look for exclusions from "all" requests */
     796           8 :         if (all || all_nt || all_dos) {
     797             :                 /* Exclusions are delimited by '!' */
     798           8 :                 for (;
     799           8 :                      pExclude != NULL;
     800           0 :                      pExclude = (p == NULL ? NULL : p + 1)) {
     801             : 
     802             :                         /* Find end of this exclusion name */
     803           0 :                         if ((p = strchr(pExclude, '!')) != NULL)
     804             :                         {
     805           0 :                                 *p = '\0';
     806             :                         }
     807             : 
     808             :                         /* Which exclusion name is this? */
     809           0 :                         if (strcasecmp_m(pExclude,
     810             :                                        "nt_sec_desc.revision") == 0) {
     811           0 :                                 exclude_nt_revision = True;
     812             :                         }
     813           0 :                         else if (strcasecmp_m(pExclude,
     814             :                                             "nt_sec_desc.owner") == 0) {
     815           0 :                                 exclude_nt_owner = True;
     816             :                         }
     817           0 :                         else if (strcasecmp_m(pExclude,
     818             :                                             "nt_sec_desc.group") == 0) {
     819           0 :                                 exclude_nt_group = True;
     820             :                         }
     821           0 :                         else if (strcasecmp_m(pExclude,
     822             :                                             "nt_sec_desc.acl") == 0) {
     823           0 :                                 exclude_nt_acl = True;
     824             :                         }
     825           0 :                         else if (strcasecmp_m(pExclude,
     826             :                                             "dos_attr.mode") == 0) {
     827           0 :                                 exclude_dos_mode = True;
     828             :                         }
     829           0 :                         else if (strcasecmp_m(pExclude,
     830             :                                             "dos_attr.size") == 0) {
     831           0 :                                 exclude_dos_size = True;
     832             :                         }
     833           0 :                         else if (excl_attr_strings.create_time_attr != NULL &&
     834           0 :                                  strcasecmp_m(pExclude,
     835             :                                             excl_attr_strings.change_time_attr) == 0) {
     836           0 :                                 exclude_dos_create_time = True;
     837             :                         }
     838           0 :                         else if (strcasecmp_m(pExclude,
     839             :                                             excl_attr_strings.access_time_attr) == 0) {
     840           0 :                                 exclude_dos_access_time = True;
     841             :                         }
     842           0 :                         else if (strcasecmp_m(pExclude,
     843             :                                             excl_attr_strings.write_time_attr) == 0) {
     844           0 :                                 exclude_dos_write_time = True;
     845             :                         }
     846           0 :                         else if (strcasecmp_m(pExclude,
     847             :                                             excl_attr_strings.change_time_attr) == 0) {
     848           0 :                                 exclude_dos_change_time = True;
     849             :                         }
     850           0 :                         else if (strcasecmp_m(pExclude, "dos_attr.inode") == 0) {
     851           0 :                                 exclude_dos_inode = True;
     852             :                         }
     853             :                         else {
     854           0 :                                 DEBUG(5, ("cacl_get received unknown exclusion: %s\n",
     855             :                                           pExclude));
     856           0 :                                 errno = ENOATTR;
     857           0 :                                 return -1;
     858             :                         }
     859             :                 }
     860             :         }
     861             : 
     862           8 :         n_used = 0;
     863             : 
     864             :         /*
     865             :          * If we are (possibly) talking to an NT or new system and some NT
     866             :          * attributes have been requested...
     867             :          */
     868           8 :         if (ipc_cli && (all || some_nt || all_nt_acls)) {
     869           8 :                 char *targetpath = NULL;
     870           8 :                 struct cli_state *targetcli = NULL;
     871           8 :                 struct cli_credentials *creds = NULL;
     872           0 :                 NTSTATUS status;
     873             : 
     874             :                 /* Point to the portion after "system.nt_sec_desc." */
     875           8 :                 name += 19;     /* if (all) this will be invalid but unused */
     876             : 
     877           8 :                 creds = context->internal->creds;
     878             : 
     879           8 :                 status = cli_resolve_path(
     880             :                         ctx, "",
     881             :                         creds,
     882             :                         cli, filename, &targetcli, &targetpath);
     883           8 :                 if (!NT_STATUS_IS_OK(status)) {
     884           0 :                         DEBUG(5, ("cacl_get Could not resolve %s\n",
     885             :                                 filename));
     886           0 :                         errno = ENOENT;
     887           0 :                         return -1;
     888             :                 }
     889             : 
     890             :                 /* ... then obtain any NT attributes which were requested */
     891           8 :                 status = cli_ntcreate(
     892             :                         targetcli,              /* cli */
     893             :                         targetpath,             /* fname */
     894             :                         0,                      /* CreatFlags */
     895             :                         READ_CONTROL_ACCESS,    /* DesiredAccess */
     896             :                         0,                      /* FileAttributes */
     897             :                         FILE_SHARE_READ|
     898             :                         FILE_SHARE_WRITE,       /* ShareAccess */
     899             :                         FILE_OPEN,              /* CreateDisposition */
     900             :                         0x0,                    /* CreateOptions */
     901             :                         0x0,                    /* SecurityFlags */
     902             :                         &fnum,                      /* pfid */
     903             :                         NULL);                  /* cr */
     904           8 :                 if (!NT_STATUS_IS_OK(status)) {
     905           0 :                         DEBUG(5, ("cacl_get failed to open %s: %s\n",
     906             :                                   targetpath, nt_errstr(status)));
     907           0 :                         errno = cli_status_to_errno(status);
     908           0 :                         return -1;
     909             :                 }
     910             : 
     911           8 :                 status = cli_query_secdesc(targetcli, fnum, ctx, &sd);
     912           8 :                 if (!NT_STATUS_IS_OK(status)) {
     913           0 :                         DEBUG(5,("cacl_get Failed to query old descriptor "
     914             :                                  "of %s: %s\n",
     915             :                                   targetpath, nt_errstr(status)));
     916           0 :                         errno = cli_status_to_errno(status);
     917           0 :                         return -1;
     918             :                 }
     919             : 
     920           8 :                 cli_close(targetcli, fnum);
     921             : 
     922           8 :                 if (! exclude_nt_revision) {
     923           8 :                         if (all || all_nt) {
     924           8 :                                 if (determine_size) {
     925           4 :                                         p = talloc_asprintf(ctx,
     926             :                                                             "REVISION:%d",
     927           4 :                                                             sd->revision);
     928           4 :                                         if (!p) {
     929           0 :                                                 errno = ENOMEM;
     930           0 :                                                 return -1;
     931             :                                         }
     932           4 :                                         n = strlen(p);
     933             :                                 } else {
     934           4 :                                         n = snprintf(buf, bufsize,
     935             :                                                      "REVISION:%d",
     936           4 :                                                      sd->revision);
     937             :                                 }
     938           0 :                         } else if (strcasecmp_m(name, "revision") == 0) {
     939           0 :                                 if (determine_size) {
     940           0 :                                         p = talloc_asprintf(ctx, "%d",
     941           0 :                                                             sd->revision);
     942           0 :                                         if (!p) {
     943           0 :                                                 errno = ENOMEM;
     944           0 :                                                 return -1;
     945             :                                         }
     946           0 :                                         n = strlen(p);
     947             :                                 } else {
     948           0 :                                         n = snprintf(buf, bufsize, "%d",
     949           0 :                                                      sd->revision);
     950             :                                 }
     951             :                         }
     952             : 
     953           8 :                         if (!determine_size && n > bufsize) {
     954           0 :                                 errno = ERANGE;
     955           0 :                                 return -1;
     956             :                         }
     957           8 :                         buf += n;
     958           8 :                         n_used += n;
     959           8 :                         bufsize -= n;
     960           8 :                         n = 0;
     961             :                 }
     962             : 
     963           8 :                 if (! exclude_nt_owner) {
     964             :                         /* Get owner and group sid */
     965           8 :                         if (sd->owner_sid) {
     966           8 :                                 convert_sid_to_string(ipc_cli, pol,
     967             :                                                       sidstr,
     968             :                                                       numeric,
     969           8 :                                                       sd->owner_sid);
     970             :                         } else {
     971           0 :                                 fstrcpy(sidstr, "");
     972             :                         }
     973             : 
     974           8 :                         if (all || all_nt) {
     975           8 :                                 if (determine_size) {
     976           4 :                                         p = talloc_asprintf(ctx, ",OWNER:%s",
     977             :                                                             sidstr);
     978           4 :                                         if (!p) {
     979           0 :                                                 errno = ENOMEM;
     980           0 :                                                 return -1;
     981             :                                         }
     982           4 :                                         n = strlen(p);
     983           4 :                                 } else if (sidstr[0] != '\0') {
     984           4 :                                         n = snprintf(buf, bufsize,
     985             :                                                      ",OWNER:%s", sidstr);
     986             :                                 }
     987           0 :                         } else if (strncasecmp_m(name, "owner", 5) == 0) {
     988           0 :                                 if (determine_size) {
     989           0 :                                         p = talloc_asprintf(ctx, "%s", sidstr);
     990           0 :                                         if (!p) {
     991           0 :                                                 errno = ENOMEM;
     992           0 :                                                 return -1;
     993             :                                         }
     994           0 :                                         n = strlen(p);
     995             :                                 } else {
     996           0 :                                         n = snprintf(buf, bufsize, "%s",
     997             :                                                      sidstr);
     998             :                                 }
     999             :                         }
    1000             : 
    1001           8 :                         if (!determine_size && n > bufsize) {
    1002           0 :                                 errno = ERANGE;
    1003           0 :                                 return -1;
    1004             :                         }
    1005           8 :                         buf += n;
    1006           8 :                         n_used += n;
    1007           8 :                         bufsize -= n;
    1008           8 :                         n = 0;
    1009             :                 }
    1010             : 
    1011           8 :                 if (! exclude_nt_group) {
    1012           8 :                         if (sd->group_sid) {
    1013           8 :                                 convert_sid_to_string(ipc_cli, pol,
    1014             :                                                       sidstr, numeric,
    1015           8 :                                                       sd->group_sid);
    1016             :                         } else {
    1017           0 :                                 fstrcpy(sidstr, "");
    1018             :                         }
    1019             : 
    1020           8 :                         if (all || all_nt) {
    1021           8 :                                 if (determine_size) {
    1022           4 :                                         p = talloc_asprintf(ctx, ",GROUP:%s",
    1023             :                                                             sidstr);
    1024           4 :                                         if (!p) {
    1025           0 :                                                 errno = ENOMEM;
    1026           0 :                                                 return -1;
    1027             :                                         }
    1028           4 :                                         n = strlen(p);
    1029           4 :                                 } else if (sidstr[0] != '\0') {
    1030           4 :                                         n = snprintf(buf, bufsize,
    1031             :                                                      ",GROUP:%s", sidstr);
    1032             :                                 }
    1033           0 :                         } else if (strncasecmp_m(name, "group", 5) == 0) {
    1034           0 :                                 if (determine_size) {
    1035           0 :                                         p = talloc_asprintf(ctx, "%s", sidstr);
    1036           0 :                                         if (!p) {
    1037           0 :                                                 errno = ENOMEM;
    1038           0 :                                                 return -1;
    1039             :                                         }
    1040           0 :                                         n = strlen(p);
    1041             :                                 } else {
    1042           0 :                                         n = snprintf(buf, bufsize,
    1043             :                                                      "%s", sidstr);
    1044             :                                 }
    1045             :                         }
    1046             : 
    1047           8 :                         if (!determine_size && n > bufsize) {
    1048           0 :                                 errno = ERANGE;
    1049           0 :                                 return -1;
    1050             :                         }
    1051           8 :                         buf += n;
    1052           8 :                         n_used += n;
    1053           8 :                         bufsize -= n;
    1054           8 :                         n = 0;
    1055             :                 }
    1056             : 
    1057           8 :                 if (! exclude_nt_acl) {
    1058             :                         /* Add aces to value buffer  */
    1059          32 :                         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
    1060             : 
    1061          24 :                                 struct security_ace *ace = &sd->dacl->aces[i];
    1062          24 :                                 convert_sid_to_string(ipc_cli, pol,
    1063             :                                                       sidstr, numeric,
    1064             :                                                       &ace->trustee);
    1065             : 
    1066          24 :                                 if (all || all_nt) {
    1067          24 :                                         if (determine_size) {
    1068          12 :                                                 p = talloc_asprintf(
    1069             :                                                         ctx,
    1070             :                                                         ",ACL:"
    1071             :                                                         "%s:%d/%d/0x%08x",
    1072             :                                                         sidstr,
    1073          12 :                                                         ace->type,
    1074          12 :                                                         ace->flags,
    1075             :                                                         ace->access_mask);
    1076          12 :                                                 if (!p) {
    1077           0 :                                                         errno = ENOMEM;
    1078           0 :                                                         return -1;
    1079             :                                                 }
    1080          12 :                                                 n = strlen(p);
    1081             :                                         } else {
    1082          12 :                                                 n = snprintf(
    1083             :                                                         buf, bufsize,
    1084             :                                                         ",ACL:%s:%d/%d/0x%08x",
    1085             :                                                         sidstr,
    1086          12 :                                                         ace->type,
    1087          12 :                                                         ace->flags,
    1088             :                                                         ace->access_mask);
    1089             :                                         }
    1090           0 :                                 } else if ((strncasecmp_m(name, "acl", 3) == 0 &&
    1091           0 :                                             strcasecmp_m(name+3, sidstr) == 0) ||
    1092           0 :                                            (strncasecmp_m(name, "acl+", 4) == 0 &&
    1093           0 :                                             strcasecmp_m(name+4, sidstr) == 0)) {
    1094           0 :                                         if (determine_size) {
    1095           0 :                                                 p = talloc_asprintf(
    1096             :                                                         ctx,
    1097             :                                                         "%d/%d/0x%08x",
    1098           0 :                                                         ace->type,
    1099           0 :                                                         ace->flags,
    1100             :                                                         ace->access_mask);
    1101           0 :                                                 if (!p) {
    1102           0 :                                                         errno = ENOMEM;
    1103           0 :                                                         return -1;
    1104             :                                                 }
    1105           0 :                                                 n = strlen(p);
    1106             :                                         } else {
    1107           0 :                                                 n = snprintf(buf, bufsize,
    1108             :                                                              "%d/%d/0x%08x",
    1109           0 :                                                              ace->type,
    1110           0 :                                                              ace->flags,
    1111             :                                                              ace->access_mask);
    1112             :                                         }
    1113           0 :                                 } else if (all_nt_acls) {
    1114           0 :                                         if (determine_size) {
    1115           0 :                                                 p = talloc_asprintf(
    1116             :                                                         ctx,
    1117             :                                                         "%s%s:%d/%d/0x%08x",
    1118             :                                                         i ? "," : "",
    1119             :                                                         sidstr,
    1120           0 :                                                         ace->type,
    1121           0 :                                                         ace->flags,
    1122             :                                                         ace->access_mask);
    1123           0 :                                                 if (!p) {
    1124           0 :                                                         errno = ENOMEM;
    1125           0 :                                                         return -1;
    1126             :                                                 }
    1127           0 :                                                 n = strlen(p);
    1128             :                                         } else {
    1129           0 :                                                 n = snprintf(buf, bufsize,
    1130             :                                                              "%s%s:%d/%d/0x%08x",
    1131             :                                                              i ? "," : "",
    1132             :                                                              sidstr,
    1133           0 :                                                              ace->type,
    1134           0 :                                                              ace->flags,
    1135             :                                                              ace->access_mask);
    1136             :                                         }
    1137             :                                 }
    1138          24 :                                 if (!determine_size && n > bufsize) {
    1139           0 :                                         errno = ERANGE;
    1140           0 :                                         return -1;
    1141             :                                 }
    1142          24 :                                 buf += n;
    1143          24 :                                 n_used += n;
    1144          24 :                                 bufsize -= n;
    1145          24 :                                 n = 0;
    1146             :                         }
    1147             :                 }
    1148             : 
    1149             :                 /* Restore name pointer to its original value */
    1150           8 :                 name -= 19;
    1151             :         }
    1152             : 
    1153           8 :         if (all || some_dos) {
    1154           8 :                 struct stat sb = {0};
    1155           8 :                 time_t create_time = (time_t)0;
    1156           8 :                 time_t write_time = (time_t)0;
    1157           8 :                 time_t access_time = (time_t)0;
    1158           8 :                 time_t change_time = (time_t)0;
    1159           8 :                 off_t size = 0;
    1160           8 :                 uint16_t mode = 0;
    1161           8 :                 SMB_INO_T ino = 0;
    1162           0 :                 NTSTATUS status;
    1163             : 
    1164             :                 /* Point to the portion after "system.dos_attr." */
    1165           8 :                 name += 16;     /* if (all) this will be invalid but unused */
    1166             : 
    1167             :                 /* Obtain the DOS attributes */
    1168           8 :                 status = SMBC_getatr(context, srv, filename, &sb);
    1169           8 :                 if (!NT_STATUS_IS_OK(status)) {
    1170           0 :                         errno = cli_status_to_errno(status);
    1171           0 :                         return -1;
    1172             :                 }
    1173             : 
    1174           8 :                 create_time = sb.st_ctime;
    1175           8 :                 access_time = sb.st_atime;
    1176           8 :                 write_time  = sb.st_mtime;
    1177           8 :                 change_time = sb.st_mtime;
    1178           8 :                 size        = sb.st_size;
    1179           8 :                 mode        = sb.st_mode;
    1180           8 :                 ino         = sb.st_ino;
    1181             : 
    1182           8 :                 if (! exclude_dos_mode) {
    1183           8 :                         if (all || all_dos) {
    1184           8 :                                 if (determine_size) {
    1185           8 :                                         p = talloc_asprintf(ctx,
    1186             :                                                             "%sMODE:0x%x",
    1187           4 :                                                             (ipc_cli &&
    1188           0 :                                                              (all || some_nt)
    1189             :                                                              ? ","
    1190             :                                                              : ""),
    1191             :                                                             mode);
    1192           4 :                                         if (!p) {
    1193           0 :                                                 errno = ENOMEM;
    1194           0 :                                                 return -1;
    1195             :                                         }
    1196           4 :                                         n = strlen(p);
    1197             :                                 } else {
    1198           8 :                                         n = snprintf(buf, bufsize,
    1199             :                                                      "%sMODE:0x%x",
    1200           4 :                                                      (ipc_cli &&
    1201           0 :                                                       (all || some_nt)
    1202             :                                                       ? ","
    1203             :                                                       : ""),
    1204             :                                                      mode);
    1205             :                                 }
    1206           0 :                         } else if (strcasecmp_m(name, "mode") == 0) {
    1207           0 :                                 if (determine_size) {
    1208           0 :                                         p = talloc_asprintf(ctx, "0x%x", mode);
    1209           0 :                                         if (!p) {
    1210           0 :                                                 errno = ENOMEM;
    1211           0 :                                                 return -1;
    1212             :                                         }
    1213           0 :                                         n = strlen(p);
    1214             :                                 } else {
    1215           0 :                                         n = snprintf(buf, bufsize,
    1216             :                                                      "0x%x", mode);
    1217             :                                 }
    1218             :                         }
    1219             : 
    1220           8 :                         if (!determine_size && n > bufsize) {
    1221           0 :                                 errno = ERANGE;
    1222           0 :                                 return -1;
    1223             :                         }
    1224           8 :                         buf += n;
    1225           8 :                         n_used += n;
    1226           8 :                         bufsize -= n;
    1227           8 :                         n = 0;
    1228             :                 }
    1229             : 
    1230           8 :                 if (! exclude_dos_size) {
    1231           8 :                         if (all || all_dos) {
    1232           8 :                                 if (determine_size) {
    1233           4 :                                         p = talloc_asprintf(
    1234             :                                                 ctx,
    1235             :                                                 ",SIZE:%.0f",
    1236             :                                                 (double)size);
    1237           4 :                                         if (!p) {
    1238           0 :                                                 errno = ENOMEM;
    1239           0 :                                                 return -1;
    1240             :                                         }
    1241           4 :                                         n = strlen(p);
    1242             :                                 } else {
    1243           4 :                                         n = snprintf(buf, bufsize,
    1244             :                                                      ",SIZE:%.0f",
    1245             :                                                      (double)size);
    1246             :                                 }
    1247           0 :                         } else if (strcasecmp_m(name, "size") == 0) {
    1248           0 :                                 if (determine_size) {
    1249           0 :                                         p = talloc_asprintf(
    1250             :                                                 ctx,
    1251             :                                                 "%.0f",
    1252             :                                                 (double)size);
    1253           0 :                                         if (!p) {
    1254           0 :                                                 errno = ENOMEM;
    1255           0 :                                                 return -1;
    1256             :                                         }
    1257           0 :                                         n = strlen(p);
    1258             :                                 } else {
    1259           0 :                                         n = snprintf(buf, bufsize,
    1260             :                                                      "%.0f",
    1261             :                                                      (double)size);
    1262             :                                 }
    1263             :                         }
    1264             : 
    1265           8 :                         if (!determine_size && n > bufsize) {
    1266           0 :                                 errno = ERANGE;
    1267           0 :                                 return -1;
    1268             :                         }
    1269           8 :                         buf += n;
    1270           8 :                         n_used += n;
    1271           8 :                         bufsize -= n;
    1272           8 :                         n = 0;
    1273             :                 }
    1274             : 
    1275           8 :                 if (! exclude_dos_create_time &&
    1276           8 :                     attr_strings.create_time_attr != NULL) {
    1277           0 :                         if (all || all_dos) {
    1278           0 :                                 if (determine_size) {
    1279           0 :                                         p = talloc_asprintf(ctx,
    1280             :                                                             ",%s:%lu",
    1281             :                                                             attr_strings.create_time_attr,
    1282             :                                                             (unsigned long) create_time);
    1283           0 :                                         if (!p) {
    1284           0 :                                                 errno = ENOMEM;
    1285           0 :                                                 return -1;
    1286             :                                         }
    1287           0 :                                         n = strlen(p);
    1288             :                                 } else {
    1289           0 :                                         n = snprintf(buf, bufsize,
    1290             :                                                      ",%s:%lu",
    1291             :                                                      attr_strings.create_time_attr,
    1292             :                                                      (unsigned long) create_time);
    1293             :                                 }
    1294           0 :                         } else if (strcasecmp_m(name, attr_strings.create_time_attr) == 0) {
    1295           0 :                                 if (determine_size) {
    1296           0 :                                         p = talloc_asprintf(ctx, "%lu", (unsigned long) create_time);
    1297           0 :                                         if (!p) {
    1298           0 :                                                 errno = ENOMEM;
    1299           0 :                                                 return -1;
    1300             :                                         }
    1301           0 :                                         n = strlen(p);
    1302             :                                 } else {
    1303           0 :                                         n = snprintf(buf, bufsize,
    1304             :                                                      "%lu", (unsigned long) create_time);
    1305             :                                 }
    1306             :                         }
    1307             : 
    1308           0 :                         if (!determine_size && n > bufsize) {
    1309           0 :                                 errno = ERANGE;
    1310           0 :                                 return -1;
    1311             :                         }
    1312           0 :                         buf += n;
    1313           0 :                         n_used += n;
    1314           0 :                         bufsize -= n;
    1315           0 :                         n = 0;
    1316             :                 }
    1317             : 
    1318           8 :                 if (! exclude_dos_access_time) {
    1319           8 :                         if (all || all_dos) {
    1320           8 :                                 if (determine_size) {
    1321           4 :                                         p = talloc_asprintf(ctx,
    1322             :                                                             ",%s:%lu",
    1323             :                                                             attr_strings.access_time_attr,
    1324             :                                                             (unsigned long) access_time);
    1325           4 :                                         if (!p) {
    1326           0 :                                                 errno = ENOMEM;
    1327           0 :                                                 return -1;
    1328             :                                         }
    1329           4 :                                         n = strlen(p);
    1330             :                                 } else {
    1331           4 :                                         n = snprintf(buf, bufsize,
    1332             :                                                      ",%s:%lu",
    1333             :                                                      attr_strings.access_time_attr,
    1334             :                                                      (unsigned long) access_time);
    1335             :                                 }
    1336           0 :                         } else if (strcasecmp_m(name, attr_strings.access_time_attr) == 0) {
    1337           0 :                                 if (determine_size) {
    1338           0 :                                         p = talloc_asprintf(ctx, "%lu", (unsigned long) access_time);
    1339           0 :                                         if (!p) {
    1340           0 :                                                 errno = ENOMEM;
    1341           0 :                                                 return -1;
    1342             :                                         }
    1343           0 :                                         n = strlen(p);
    1344             :                                 } else {
    1345           0 :                                         n = snprintf(buf, bufsize,
    1346             :                                                      "%lu", (unsigned long) access_time);
    1347             :                                 }
    1348             :                         }
    1349             : 
    1350           8 :                         if (!determine_size && n > bufsize) {
    1351           0 :                                 errno = ERANGE;
    1352           0 :                                 return -1;
    1353             :                         }
    1354           8 :                         buf += n;
    1355           8 :                         n_used += n;
    1356           8 :                         bufsize -= n;
    1357           8 :                         n = 0;
    1358             :                 }
    1359             : 
    1360           8 :                 if (! exclude_dos_write_time) {
    1361           8 :                         if (all || all_dos) {
    1362           8 :                                 if (determine_size) {
    1363           4 :                                         p = talloc_asprintf(ctx,
    1364             :                                                             ",%s:%lu",
    1365             :                                                             attr_strings.write_time_attr,
    1366             :                                                             (unsigned long) write_time);
    1367           4 :                                         if (!p) {
    1368           0 :                                                 errno = ENOMEM;
    1369           0 :                                                 return -1;
    1370             :                                         }
    1371           4 :                                         n = strlen(p);
    1372             :                                 } else {
    1373           4 :                                         n = snprintf(buf, bufsize,
    1374             :                                                      ",%s:%lu",
    1375             :                                                      attr_strings.write_time_attr,
    1376             :                                                      (unsigned long) write_time);
    1377             :                                 }
    1378           0 :                         } else if (strcasecmp_m(name, attr_strings.write_time_attr) == 0) {
    1379           0 :                                 if (determine_size) {
    1380           0 :                                         p = talloc_asprintf(ctx, "%lu", (unsigned long) write_time);
    1381           0 :                                         if (!p) {
    1382           0 :                                                 errno = ENOMEM;
    1383           0 :                                                 return -1;
    1384             :                                         }
    1385           0 :                                         n = strlen(p);
    1386             :                                 } else {
    1387           0 :                                         n = snprintf(buf, bufsize,
    1388             :                                                      "%lu", (unsigned long) write_time);
    1389             :                                 }
    1390             :                         }
    1391             : 
    1392           8 :                         if (!determine_size && n > bufsize) {
    1393           0 :                                 errno = ERANGE;
    1394           0 :                                 return -1;
    1395             :                         }
    1396           8 :                         buf += n;
    1397           8 :                         n_used += n;
    1398           8 :                         bufsize -= n;
    1399           8 :                         n = 0;
    1400             :                 }
    1401             : 
    1402           8 :                 if (! exclude_dos_change_time) {
    1403           8 :                         if (all || all_dos) {
    1404           8 :                                 if (determine_size) {
    1405           4 :                                         p = talloc_asprintf(ctx,
    1406             :                                                             ",%s:%lu",
    1407             :                                                             attr_strings.change_time_attr,
    1408             :                                                             (unsigned long) change_time);
    1409           4 :                                         if (!p) {
    1410           0 :                                                 errno = ENOMEM;
    1411           0 :                                                 return -1;
    1412             :                                         }
    1413           4 :                                         n = strlen(p);
    1414             :                                 } else {
    1415           4 :                                         n = snprintf(buf, bufsize,
    1416             :                                                      ",%s:%lu",
    1417             :                                                      attr_strings.change_time_attr,
    1418             :                                                      (unsigned long) change_time);
    1419             :                                 }
    1420           0 :                         } else if (strcasecmp_m(name, attr_strings.change_time_attr) == 0) {
    1421           0 :                                 if (determine_size) {
    1422           0 :                                         p = talloc_asprintf(ctx, "%lu", (unsigned long) change_time);
    1423           0 :                                         if (!p) {
    1424           0 :                                                 errno = ENOMEM;
    1425           0 :                                                 return -1;
    1426             :                                         }
    1427           0 :                                         n = strlen(p);
    1428             :                                 } else {
    1429           0 :                                         n = snprintf(buf, bufsize,
    1430             :                                                      "%lu", (unsigned long) change_time);
    1431             :                                 }
    1432             :                         }
    1433             : 
    1434           8 :                         if (!determine_size && n > bufsize) {
    1435           0 :                                 errno = ERANGE;
    1436           0 :                                 return -1;
    1437             :                         }
    1438           8 :                         buf += n;
    1439           8 :                         n_used += n;
    1440           8 :                         bufsize -= n;
    1441           8 :                         n = 0;
    1442             :                 }
    1443             : 
    1444           8 :                 if (! exclude_dos_inode) {
    1445           8 :                         if (all || all_dos) {
    1446           8 :                                 if (determine_size) {
    1447           4 :                                         p = talloc_asprintf(
    1448             :                                                 ctx,
    1449             :                                                 ",INODE:%.0f",
    1450             :                                                 (double)ino);
    1451           4 :                                         if (!p) {
    1452           0 :                                                 errno = ENOMEM;
    1453           0 :                                                 return -1;
    1454             :                                         }
    1455           4 :                                         n = strlen(p);
    1456             :                                 } else {
    1457           4 :                                         n = snprintf(buf, bufsize,
    1458             :                                                      ",INODE:%.0f",
    1459             :                                                      (double) ino);
    1460             :                                 }
    1461           0 :                         } else if (strcasecmp_m(name, "inode") == 0) {
    1462           0 :                                 if (determine_size) {
    1463           0 :                                         p = talloc_asprintf(
    1464             :                                                 ctx,
    1465             :                                                 "%.0f",
    1466             :                                                 (double) ino);
    1467           0 :                                         if (!p) {
    1468           0 :                                                 errno = ENOMEM;
    1469           0 :                                                 return -1;
    1470             :                                         }
    1471           0 :                                         n = strlen(p);
    1472             :                                 } else {
    1473           0 :                                         n = snprintf(buf, bufsize,
    1474             :                                                      "%.0f",
    1475             :                                                      (double) ino);
    1476             :                                 }
    1477             :                         }
    1478             : 
    1479           8 :                         if (!determine_size && n > bufsize) {
    1480           0 :                                 errno = ERANGE;
    1481           0 :                                 return -1;
    1482             :                         }
    1483           8 :                         buf += n;
    1484           8 :                         n_used += n;
    1485           8 :                         bufsize -= n;
    1486           8 :                         n = 0;
    1487             :                 }
    1488             : 
    1489             :                 /* Restore name pointer to its original value */
    1490           8 :                 name -= 16;
    1491             :         }
    1492             : 
    1493           8 :         if (n_used == 0) {
    1494           0 :                 errno = ENOATTR;
    1495           0 :                 return -1;
    1496             :         }
    1497             : 
    1498           8 :         return n_used;
    1499             : }
    1500             : 
    1501             : /*****************************************************
    1502             : set the ACLs on a file given an ascii description
    1503             : *******************************************************/
    1504             : static int
    1505           0 : cacl_set(SMBCCTX *context,
    1506             :         TALLOC_CTX *ctx,
    1507             :         struct cli_state *cli,
    1508             :         struct cli_state *ipc_cli,
    1509             :         struct policy_handle *pol,
    1510             :         const char *filename,
    1511             :         char *the_acl,
    1512             :         int mode,
    1513             :         int flags)
    1514             : {
    1515           0 :         uint16_t fnum = (uint16_t)-1;
    1516           0 :         int err = 0;
    1517           0 :         struct security_descriptor *sd = NULL, *old;
    1518           0 :         struct security_acl *dacl = NULL;
    1519           0 :         struct dom_sid *owner_sid = NULL;
    1520           0 :         struct dom_sid *group_sid = NULL;
    1521           0 :         uint32_t i, j;
    1522           0 :         size_t sd_size;
    1523           0 :         int ret = 0;
    1524           0 :         char *p;
    1525           0 :         bool numeric = True;
    1526           0 :         char *targetpath = NULL;
    1527           0 :         struct cli_state *targetcli = NULL;
    1528           0 :         struct cli_credentials *creds = NULL;
    1529           0 :         NTSTATUS status;
    1530             : 
    1531             :         /* the_acl will be null for REMOVE_ALL operations */
    1532           0 :         if (the_acl) {
    1533           0 :                 numeric = ((p = strchr(the_acl, ':')) != NULL &&
    1534           0 :                            p > the_acl &&
    1535           0 :                            p[-1] != '+');
    1536             : 
    1537             :                 /* if this is to set the entire ACL... */
    1538           0 :                 if (*the_acl == '*') {
    1539             :                         /* ... then increment past the first colon */
    1540           0 :                         the_acl = p + 1;
    1541             :                 }
    1542             : 
    1543           0 :                 sd = sec_desc_parse(ctx, ipc_cli, pol, numeric, the_acl);
    1544           0 :                 if (!sd) {
    1545           0 :                         errno = EINVAL;
    1546           0 :                         return -1;
    1547             :                 }
    1548             :         }
    1549             : 
    1550             :         /* SMBC_XATTR_MODE_REMOVE_ALL is the only caller
    1551             :            that doesn't deref sd */
    1552             : 
    1553           0 :         if (!sd && (mode != SMBC_XATTR_MODE_REMOVE_ALL)) {
    1554           0 :                 errno = EINVAL;
    1555           0 :                 return -1;
    1556             :         }
    1557             : 
    1558           0 :         creds = context->internal->creds;
    1559             : 
    1560           0 :         status = cli_resolve_path(ctx, "",
    1561             :                                   creds,
    1562             :                                   cli, filename, &targetcli, &targetpath);
    1563           0 :         if (!NT_STATUS_IS_OK(status)) {
    1564           0 :                 DEBUG(5,("cacl_set: Could not resolve %s\n", filename));
    1565           0 :                 errno = ENOENT;
    1566           0 :                 return -1;
    1567             :         }
    1568             : 
    1569             :         /* The desired access below is the only one I could find that works
    1570             :            with NT4, W2KP and Samba */
    1571             : 
    1572           0 :         status = cli_ntcreate(
    1573             :                 targetcli,              /* cli */
    1574             :                 targetpath,             /* fname */
    1575             :                 0,                      /* CreatFlags */
    1576             :                 READ_CONTROL_ACCESS,    /* DesiredAccess */
    1577             :                 0,                      /* FileAttributes */
    1578             :                 FILE_SHARE_READ|
    1579             :                 FILE_SHARE_WRITE,       /* ShareAccess */
    1580             :                 FILE_OPEN,              /* CreateDisposition */
    1581             :                 0x0,                    /* CreateOptions */
    1582             :                 0x0,                    /* SecurityFlags */
    1583             :                 &fnum,                      /* pfid */
    1584             :                 NULL);                  /* cr */
    1585           0 :         if (!NT_STATUS_IS_OK(status)) {
    1586           0 :                 DEBUG(5, ("cacl_set failed to open %s: %s\n",
    1587             :                           targetpath, nt_errstr(status)));
    1588           0 :                 errno = 0;
    1589           0 :                 return -1;
    1590             :         }
    1591             : 
    1592           0 :         status = cli_query_secdesc(targetcli, fnum, ctx, &old);
    1593           0 :         if (!NT_STATUS_IS_OK(status)) {
    1594           0 :                 DEBUG(5,("cacl_set Failed to query old descriptor of %s: %s\n",
    1595             :                          targetpath, nt_errstr(status)));
    1596           0 :                 errno = 0;
    1597           0 :                 return -1;
    1598             :         }
    1599             : 
    1600           0 :         cli_close(targetcli, fnum);
    1601             : 
    1602           0 :         switch (mode) {
    1603           0 :         case SMBC_XATTR_MODE_REMOVE_ALL:
    1604           0 :                 old->dacl->num_aces = 0;
    1605           0 :                 dacl = old->dacl;
    1606           0 :                 break;
    1607             : 
    1608           0 :         case SMBC_XATTR_MODE_REMOVE:
    1609           0 :                 for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
    1610           0 :                         bool found = False;
    1611             : 
    1612           0 :                         for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
    1613           0 :                                 if (security_ace_equal(&sd->dacl->aces[i],
    1614           0 :                                                        &old->dacl->aces[j])) {
    1615             :                                         uint32_t k;
    1616           0 :                                         for (k=j; k<old->dacl->num_aces-1;k++) {
    1617           0 :                                                 old->dacl->aces[k] =
    1618           0 :                                                         old->dacl->aces[k+1];
    1619             :                                         }
    1620           0 :                                         old->dacl->num_aces--;
    1621           0 :                                         found = True;
    1622           0 :                                         dacl = old->dacl;
    1623           0 :                                         break;
    1624             :                                 }
    1625             :                         }
    1626             : 
    1627           0 :                         if (!found) {
    1628           0 :                                 err = ENOATTR;
    1629           0 :                                 ret = -1;
    1630           0 :                                 goto failed;
    1631             :                         }
    1632             :                 }
    1633           0 :                 break;
    1634             : 
    1635           0 :         case SMBC_XATTR_MODE_ADD:
    1636           0 :                 for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
    1637           0 :                         bool found = False;
    1638             : 
    1639           0 :                         for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
    1640           0 :                                 if (dom_sid_equal(&sd->dacl->aces[i].trustee,
    1641           0 :                                               &old->dacl->aces[j].trustee)) {
    1642           0 :                                         if (!(flags & SMBC_XATTR_FLAG_CREATE)) {
    1643           0 :                                                 err = EEXIST;
    1644           0 :                                                 ret = -1;
    1645           0 :                                                 goto failed;
    1646             :                                         }
    1647           0 :                                         old->dacl->aces[j] = sd->dacl->aces[i];
    1648           0 :                                         ret = -1;
    1649           0 :                                         found = True;
    1650             :                                 }
    1651             :                         }
    1652             : 
    1653           0 :                         if (!found && (flags & SMBC_XATTR_FLAG_REPLACE)) {
    1654           0 :                                 err = ENOATTR;
    1655           0 :                                 ret = -1;
    1656           0 :                                 goto failed;
    1657             :                         }
    1658             : 
    1659           0 :                         for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
    1660           0 :                                 add_ace(&old->dacl, &sd->dacl->aces[i], ctx);
    1661             :                         }
    1662             :                 }
    1663           0 :                 dacl = old->dacl;
    1664           0 :                 break;
    1665             : 
    1666           0 :         case SMBC_XATTR_MODE_SET:
    1667           0 :                 old = sd;
    1668           0 :                 owner_sid = old->owner_sid;
    1669           0 :                 group_sid = old->group_sid;
    1670           0 :                 dacl = old->dacl;
    1671           0 :                 break;
    1672             : 
    1673           0 :         case SMBC_XATTR_MODE_CHOWN:
    1674           0 :                 owner_sid = sd->owner_sid;
    1675           0 :                 break;
    1676             : 
    1677           0 :         case SMBC_XATTR_MODE_CHGRP:
    1678           0 :                 group_sid = sd->group_sid;
    1679           0 :                 break;
    1680             :         }
    1681             : 
    1682             :         /* Denied ACE entries must come before allowed ones */
    1683           0 :         sort_acl(old->dacl);
    1684             : 
    1685             :         /* Create new security descriptor and set it */
    1686           0 :         sd = make_sec_desc(ctx, old->revision, SEC_DESC_SELF_RELATIVE,
    1687             :                            owner_sid, group_sid, NULL, dacl, &sd_size);
    1688             : 
    1689           0 :         status = cli_ntcreate(targetcli, targetpath, 0,
    1690             :                               WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
    1691             :                               FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
    1692             :                               0x0, 0x0, &fnum, NULL);
    1693           0 :         if (!NT_STATUS_IS_OK(status)) {
    1694           0 :                 DEBUG(5, ("cacl_set failed to open %s: %s\n",
    1695             :                           targetpath, nt_errstr(status)));
    1696           0 :                 errno = 0;
    1697           0 :                 return -1;
    1698             :         }
    1699             : 
    1700           0 :         status = cli_set_secdesc(targetcli, fnum, sd);
    1701           0 :         if (!NT_STATUS_IS_OK(status)) {
    1702           0 :                 DEBUG(5, ("ERROR: secdesc set failed: %s\n",
    1703             :                           nt_errstr(status)));
    1704           0 :                 ret = -1;
    1705             :         }
    1706             : 
    1707             :         /* Clean up */
    1708             : 
    1709           0 : failed:
    1710           0 :         cli_close(targetcli, fnum);
    1711             : 
    1712           0 :         if (err != 0) {
    1713           0 :                 errno = err;
    1714             :         }
    1715             : 
    1716           0 :         return ret;
    1717             : }
    1718             : 
    1719             : 
    1720             : int
    1721           0 : SMBC_setxattr_ctx(SMBCCTX *context,
    1722             :                   const char *fname,
    1723             :                   const char *name,
    1724             :                   const void *value,
    1725             :                   size_t size,
    1726             :                   int flags)
    1727             : {
    1728           0 :         int ret;
    1729           0 :         int ret2;
    1730           0 :         SMBCSRV *srv = NULL;
    1731           0 :         SMBCSRV *ipc_srv = NULL;
    1732           0 :         char *server = NULL;
    1733           0 :         char *share = NULL;
    1734           0 :         char *user = NULL;
    1735           0 :         char *password = NULL;
    1736           0 :         char *workgroup = NULL;
    1737           0 :         char *path = NULL;
    1738           0 :         struct DOS_ATTR_DESC *dad = NULL;
    1739           0 :         struct {
    1740             :                 const char * create_time_attr;
    1741             :                 const char * access_time_attr;
    1742             :                 const char * write_time_attr;
    1743             :                 const char * change_time_attr;
    1744             :         } attr_strings;
    1745           0 :         uint16_t port = 0;
    1746           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1747             : 
    1748           0 :         if (!context || !context->internal->initialized) {
    1749           0 :                 errno = EINVAL;  /* Best I can think of ... */
    1750           0 :                 TALLOC_FREE(frame);
    1751           0 :                 return -1;
    1752             :         }
    1753             : 
    1754           0 :         if (!fname) {
    1755           0 :                 errno = EINVAL;
    1756           0 :                 TALLOC_FREE(frame);
    1757           0 :                 return -1;
    1758             :         }
    1759             : 
    1760           0 :         DEBUG(4, ("smbc_setxattr(%s, %s, %.*s)\n",
    1761             :                   fname, name, (int) size, (const char*)value));
    1762             : 
    1763           0 :         if (SMBC_parse_path(frame,
    1764             :                             context,
    1765             :                             fname,
    1766             :                             &workgroup,
    1767             :                             &server,
    1768             :                             &port,
    1769             :                             &share,
    1770             :                             &path,
    1771             :                             &user,
    1772             :                             &password,
    1773             :                             NULL)) {
    1774           0 :                 errno = EINVAL;
    1775           0 :                 TALLOC_FREE(frame);
    1776           0 :                 return -1;
    1777             :         }
    1778             : 
    1779           0 :         if (!user || user[0] == (char)0) {
    1780           0 :                 user = talloc_strdup(frame, smbc_getUser(context));
    1781           0 :                 if (!user) {
    1782           0 :                         errno = ENOMEM;
    1783           0 :                         TALLOC_FREE(frame);
    1784           0 :                         return -1;
    1785             :                 }
    1786             :         }
    1787             : 
    1788           0 :         srv = SMBC_server(frame, context, True,
    1789             :                           server, port, share, &workgroup, &user, &password);
    1790           0 :         if (!srv) {
    1791           0 :                 TALLOC_FREE(frame);
    1792           0 :                 return -1;  /* errno set by SMBC_server */
    1793             :         }
    1794             : 
    1795           0 :         if (! srv->no_nt_session) {
    1796           0 :                 ipc_srv = SMBC_attr_server(frame, context, server, port, share,
    1797             :                                            &workgroup, &user, &password);
    1798           0 :                 if (! ipc_srv) {
    1799           0 :                         srv->no_nt_session = True;
    1800             :                 }
    1801             :         } else {
    1802           0 :                 ipc_srv = NULL;
    1803             :         }
    1804             : 
    1805             :         /*
    1806             :          * Are they asking to set the entire set of known attributes?
    1807             :          */
    1808           0 :         if (strcasecmp_m(name, "system.*") == 0 ||
    1809           0 :             strcasecmp_m(name, "system.*+") == 0) {
    1810             :                 /* Yup. */
    1811           0 :                 char *namevalue =
    1812           0 :                         talloc_asprintf(talloc_tos(), "%s:%s",
    1813             :                                         name+7, (const char *) value);
    1814           0 :                 if (! namevalue) {
    1815           0 :                         errno = ENOMEM;
    1816           0 :                         ret = -1;
    1817           0 :                         TALLOC_FREE(frame);
    1818           0 :                         return -1;
    1819             :                 }
    1820             : 
    1821           0 :                 if (ipc_srv) {
    1822           0 :                         ret = cacl_set(context, talloc_tos(), srv->cli,
    1823             :                                        ipc_srv->cli, &ipc_srv->pol, path,
    1824             :                                        namevalue,
    1825           0 :                                        (*namevalue == '*'
    1826             :                                         ? SMBC_XATTR_MODE_SET
    1827             :                                         : SMBC_XATTR_MODE_ADD),
    1828             :                                        flags);
    1829             :                 } else {
    1830           0 :                         ret = 0;
    1831             :                 }
    1832             : 
    1833             :                 /* get a DOS Attribute Descriptor with current attributes */
    1834           0 :                 dad = dos_attr_query(context, talloc_tos(), path, srv);
    1835           0 :                 if (dad) {
    1836           0 :                         bool ok;
    1837             : 
    1838             :                         /* Overwrite old with new, using what was provided */
    1839           0 :                         dos_attr_parse(context, dad, srv, namevalue);
    1840             : 
    1841             :                         /* Set the new DOS attributes */
    1842           0 :                         ok = SMBC_setatr(
    1843             :                                 context,
    1844             :                                 srv,
    1845             :                                 path,
    1846           0 :                                 (struct timespec) {
    1847           0 :                                         .tv_sec = dad->create_time },
    1848           0 :                                 (struct timespec) {
    1849           0 :                                         .tv_sec = dad->access_time },
    1850           0 :                                 (struct timespec) {
    1851           0 :                                         .tv_sec = dad->write_time },
    1852           0 :                                 (struct timespec) {
    1853           0 :                                         .tv_sec = dad->change_time },
    1854           0 :                                 dad->mode);
    1855           0 :                         if (!ok) {
    1856             :                                 /* cause failure if NT failed too */
    1857           0 :                                 dad = NULL;
    1858             :                         }
    1859             :                 }
    1860             : 
    1861             :                 /* we only fail if both NT and DOS sets failed */
    1862           0 :                 if (ret < 0 && ! dad) {
    1863           0 :                         ret = -1; /* in case dad was null */
    1864             :                 }
    1865             :                 else {
    1866           0 :                         ret = 0;
    1867             :                 }
    1868             : 
    1869           0 :                 TALLOC_FREE(frame);
    1870           0 :                 return ret;
    1871             :         }
    1872             : 
    1873             :         /*
    1874             :          * Are they asking to set an access control element or to set
    1875             :          * the entire access control list?
    1876             :          */
    1877           0 :         if (strcasecmp_m(name, "system.nt_sec_desc.*") == 0 ||
    1878           0 :             strcasecmp_m(name, "system.nt_sec_desc.*+") == 0 ||
    1879           0 :             strcasecmp_m(name, "system.nt_sec_desc.revision") == 0 ||
    1880           0 :             strncasecmp_m(name, "system.nt_sec_desc.acl", 22) == 0 ||
    1881           0 :             strncasecmp_m(name, "system.nt_sec_desc.acl+", 23) == 0) {
    1882             : 
    1883             :                 /* Yup. */
    1884           0 :                 char *namevalue =
    1885           0 :                         talloc_asprintf(talloc_tos(), "%s:%s",
    1886             :                                         name+19, (const char *) value);
    1887             : 
    1888           0 :                 if (! ipc_srv) {
    1889           0 :                         ret = -1; /* errno set by SMBC_server() */
    1890             :                 }
    1891           0 :                 else if (! namevalue) {
    1892           0 :                         errno = ENOMEM;
    1893           0 :                         ret = -1;
    1894             :                 } else {
    1895           0 :                         ret = cacl_set(context, talloc_tos(), srv->cli,
    1896             :                                        ipc_srv->cli, &ipc_srv->pol, path,
    1897             :                                        namevalue,
    1898           0 :                                        (*namevalue == '*'
    1899             :                                         ? SMBC_XATTR_MODE_SET
    1900             :                                         : SMBC_XATTR_MODE_ADD),
    1901             :                                        flags);
    1902             :                 }
    1903           0 :                 TALLOC_FREE(frame);
    1904           0 :                 return ret;
    1905             :         }
    1906             : 
    1907             :         /*
    1908             :          * Are they asking to set the owner?
    1909             :          */
    1910           0 :         if (strcasecmp_m(name, "system.nt_sec_desc.owner") == 0 ||
    1911           0 :             strcasecmp_m(name, "system.nt_sec_desc.owner+") == 0) {
    1912             : 
    1913             :                 /* Yup. */
    1914           0 :                 char *namevalue =
    1915           0 :                         talloc_asprintf(talloc_tos(), "%s:%s",
    1916             :                                         name+19, (const char *) value);
    1917             : 
    1918           0 :                 if (! ipc_srv) {
    1919           0 :                         ret = -1; /* errno set by SMBC_server() */
    1920             :                 }
    1921           0 :                 else if (! namevalue) {
    1922           0 :                         errno = ENOMEM;
    1923           0 :                         ret = -1;
    1924             :                 } else {
    1925           0 :                         ret = cacl_set(context, talloc_tos(), srv->cli,
    1926             :                                        ipc_srv->cli, &ipc_srv->pol, path,
    1927             :                                        namevalue, SMBC_XATTR_MODE_CHOWN, 0);
    1928             :                 }
    1929           0 :                 TALLOC_FREE(frame);
    1930           0 :                 return ret;
    1931             :         }
    1932             : 
    1933             :         /*
    1934             :          * Are they asking to set the group?
    1935             :          */
    1936           0 :         if (strcasecmp_m(name, "system.nt_sec_desc.group") == 0 ||
    1937           0 :             strcasecmp_m(name, "system.nt_sec_desc.group+") == 0) {
    1938             : 
    1939             :                 /* Yup. */
    1940           0 :                 char *namevalue =
    1941           0 :                         talloc_asprintf(talloc_tos(), "%s:%s",
    1942             :                                         name+19, (const char *) value);
    1943             : 
    1944           0 :                 if (! ipc_srv) {
    1945             :                         /* errno set by SMBC_server() */
    1946           0 :                         ret = -1;
    1947             :                 }
    1948           0 :                 else if (! namevalue) {
    1949           0 :                         errno = ENOMEM;
    1950           0 :                         ret = -1;
    1951             :                 } else {
    1952           0 :                         ret = cacl_set(context, talloc_tos(), srv->cli,
    1953             :                                        ipc_srv->cli, &ipc_srv->pol, path,
    1954             :                                        namevalue, SMBC_XATTR_MODE_CHGRP, 0);
    1955             :                 }
    1956           0 :                 TALLOC_FREE(frame);
    1957           0 :                 return ret;
    1958             :         }
    1959             : 
    1960             :         /* Determine whether to use old-style or new-style attribute names */
    1961           0 :         if (context->internal->full_time_names) {
    1962             :                 /* new-style names */
    1963           0 :                 attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME";
    1964           0 :                 attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME";
    1965           0 :                 attr_strings.write_time_attr = "system.dos_attr.WRITE_TIME";
    1966           0 :                 attr_strings.change_time_attr = "system.dos_attr.CHANGE_TIME";
    1967             :         } else {
    1968             :                 /* old-style names */
    1969           0 :                 attr_strings.create_time_attr = NULL;
    1970           0 :                 attr_strings.access_time_attr = "system.dos_attr.A_TIME";
    1971           0 :                 attr_strings.write_time_attr = "system.dos_attr.M_TIME";
    1972           0 :                 attr_strings.change_time_attr = "system.dos_attr.C_TIME";
    1973             :         }
    1974             : 
    1975             :         /*
    1976             :          * Are they asking to set a DOS attribute?
    1977             :          */
    1978           0 :         if (strcasecmp_m(name, "system.dos_attr.*") == 0 ||
    1979           0 :             strcasecmp_m(name, "system.dos_attr.mode") == 0 ||
    1980           0 :             (attr_strings.create_time_attr != NULL &&
    1981           0 :              strcasecmp_m(name, attr_strings.create_time_attr) == 0) ||
    1982           0 :             strcasecmp_m(name, attr_strings.access_time_attr) == 0 ||
    1983           0 :             strcasecmp_m(name, attr_strings.write_time_attr) == 0 ||
    1984           0 :             strcasecmp_m(name, attr_strings.change_time_attr) == 0) {
    1985             : 
    1986             :                 /* get a DOS Attribute Descriptor with current attributes */
    1987           0 :                 dad = dos_attr_query(context, talloc_tos(), path, srv);
    1988           0 :                 if (dad) {
    1989           0 :                         char *namevalue =
    1990           0 :                                 talloc_asprintf(talloc_tos(), "%s:%s",
    1991             :                                                 name+16, (const char *) value);
    1992           0 :                         if (! namevalue) {
    1993           0 :                                 errno = ENOMEM;
    1994           0 :                                 ret = -1;
    1995             :                         } else {
    1996             :                                 /* Overwrite old with provided new params */
    1997           0 :                                 dos_attr_parse(context, dad, srv, namevalue);
    1998             : 
    1999             :                                 /* Set the new DOS attributes */
    2000           0 :                                 ret2 = SMBC_setatr(
    2001             :                                         context,
    2002             :                                         srv,
    2003             :                                         path,
    2004           0 :                                         (struct timespec) {
    2005           0 :                                                 .tv_sec = dad->create_time },
    2006           0 :                                         (struct timespec) {
    2007           0 :                                                 .tv_sec = dad->access_time },
    2008           0 :                                         (struct timespec) {
    2009           0 :                                                 .tv_sec = dad->write_time },
    2010           0 :                                         (struct timespec) {
    2011           0 :                                                 .tv_sec = dad->change_time },
    2012           0 :                                         dad->mode);
    2013             : 
    2014             :                                 /* ret2 has True (success) / False (failure) */
    2015           0 :                                 if (ret2) {
    2016           0 :                                         ret = 0;
    2017             :                                 } else {
    2018           0 :                                         ret = -1;
    2019             :                                 }
    2020             :                         }
    2021             :                 } else {
    2022           0 :                         ret = -1;
    2023             :                 }
    2024             : 
    2025           0 :                 TALLOC_FREE(frame);
    2026           0 :                 return ret;
    2027             :         }
    2028             : 
    2029             :         /* Unsupported attribute name */
    2030           0 :         errno = EINVAL;
    2031           0 :         TALLOC_FREE(frame);
    2032           0 :         return -1;
    2033             : }
    2034             : 
    2035             : int
    2036          12 : SMBC_getxattr_ctx(SMBCCTX *context,
    2037             :                   const char *fname,
    2038             :                   const char *name,
    2039             :                   const void *value,
    2040             :                   size_t size)
    2041             : {
    2042           0 :         int ret;
    2043          12 :         SMBCSRV *srv = NULL;
    2044          12 :         SMBCSRV *ipc_srv = NULL;
    2045          12 :         char *server = NULL;
    2046          12 :         char *share = NULL;
    2047          12 :         char *user = NULL;
    2048          12 :         char *password = NULL;
    2049          12 :         char *workgroup = NULL;
    2050          12 :         char *path = NULL;
    2051           0 :         struct {
    2052             :                 const char * create_time_attr;
    2053             :                 const char * access_time_attr;
    2054             :                 const char * write_time_attr;
    2055             :                 const char * change_time_attr;
    2056             :         } attr_strings;
    2057          12 :         uint16_t port = 0;
    2058          12 :         TALLOC_CTX *frame = talloc_stackframe();
    2059             : 
    2060          12 :         if (!context || !context->internal->initialized) {
    2061           0 :                 errno = EINVAL;  /* Best I can think of ... */
    2062           0 :                 TALLOC_FREE(frame);
    2063           0 :                 return -1;
    2064             :         }
    2065             : 
    2066          12 :         if (!fname) {
    2067           0 :                 errno = EINVAL;
    2068           0 :                 TALLOC_FREE(frame);
    2069           0 :                 return -1;
    2070             :         }
    2071             : 
    2072          12 :         DEBUG(4, ("smbc_getxattr(%s, %s)\n", fname, name));
    2073             : 
    2074          12 :         if (SMBC_parse_path(frame,
    2075             :                             context,
    2076             :                             fname,
    2077             :                             &workgroup,
    2078             :                             &server,
    2079             :                             &port,
    2080             :                             &share,
    2081             :                             &path,
    2082             :                             &user,
    2083             :                             &password,
    2084             :                             NULL)) {
    2085           0 :                 errno = EINVAL;
    2086           0 :                 TALLOC_FREE(frame);
    2087           0 :                 return -1;
    2088             :         }
    2089             : 
    2090          12 :         if (!user || user[0] == '\0') {
    2091           0 :                 user = talloc_strdup(frame, smbc_getUser(context));
    2092           0 :                 if (!user) {
    2093           0 :                         errno = ENOMEM;
    2094           0 :                         TALLOC_FREE(frame);
    2095           0 :                         return -1;
    2096             :                 }
    2097             :         }
    2098             : 
    2099          12 :         srv = SMBC_server(frame, context, True,
    2100             :                           server, port, share, &workgroup, &user, &password);
    2101          12 :         if (!srv) {
    2102           0 :                 TALLOC_FREE(frame);
    2103           0 :                 return -1;  /* errno set by SMBC_server */
    2104             :         }
    2105             : 
    2106          12 :         if (! srv->no_nt_session) {
    2107          12 :                 ipc_srv = SMBC_attr_server(frame, context, server, port, share,
    2108             :                                            &workgroup, &user, &password);
    2109             :                 /*
    2110             :                  * SMBC_attr_server() can cause the original
    2111             :                  * server to be removed from the cache.
    2112             :                  * If so we must error out here as the srv
    2113             :                  * pointer has been freed.
    2114             :                  */
    2115          12 :                 if (smbc_getFunctionGetCachedServer(context)(context,
    2116             :                                 server,
    2117             :                                 share,
    2118             :                                 workgroup,
    2119             :                                 user) != srv) {
    2120             : #if defined(ECONNRESET)
    2121           0 :                         errno = ECONNRESET;
    2122             : #else
    2123             :                         errno = ETIMEDOUT;
    2124             : #endif
    2125           0 :                         TALLOC_FREE(frame);
    2126           0 :                         return -1;
    2127             :                 }
    2128          12 :                 if (! ipc_srv) {
    2129           0 :                         srv->no_nt_session = True;
    2130             :                 }
    2131             :         } else {
    2132           0 :                 ipc_srv = NULL;
    2133             :         }
    2134             : 
    2135             :         /* Determine whether to use old-style or new-style attribute names */
    2136          12 :         if (context->internal->full_time_names) {
    2137             :                 /* new-style names */
    2138           0 :                 attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME";
    2139           0 :                 attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME";
    2140           0 :                 attr_strings.write_time_attr = "system.dos_attr.WRITE_TIME";
    2141           0 :                 attr_strings.change_time_attr = "system.dos_attr.CHANGE_TIME";
    2142             :         } else {
    2143             :                 /* old-style names */
    2144          12 :                 attr_strings.create_time_attr = NULL;
    2145          12 :                 attr_strings.access_time_attr = "system.dos_attr.A_TIME";
    2146          12 :                 attr_strings.write_time_attr = "system.dos_attr.M_TIME";
    2147          12 :                 attr_strings.change_time_attr = "system.dos_attr.C_TIME";
    2148             :         }
    2149             : 
    2150             :         /* Are they requesting a supported attribute? */
    2151          16 :         if (strcasecmp_m(name, "system.*") == 0 ||
    2152           8 :             strncasecmp_m(name, "system.*!", 9) == 0 ||
    2153           8 :             strcasecmp_m(name, "system.*+") == 0 ||
    2154           8 :             strncasecmp_m(name, "system.*+!", 10) == 0 ||
    2155           8 :             strcasecmp_m(name, "system.nt_sec_desc.*") == 0 ||
    2156           8 :             strncasecmp_m(name, "system.nt_sec_desc.*!", 21) == 0 ||
    2157           8 :             strcasecmp_m(name, "system.nt_sec_desc.*+") == 0 ||
    2158           8 :             strncasecmp_m(name, "system.nt_sec_desc.*+!", 22) == 0 ||
    2159           8 :             strcasecmp_m(name, "system.nt_sec_desc.revision") == 0 ||
    2160           8 :             strcasecmp_m(name, "system.nt_sec_desc.owner") == 0 ||
    2161           8 :             strcasecmp_m(name, "system.nt_sec_desc.owner+") == 0 ||
    2162           8 :             strcasecmp_m(name, "system.nt_sec_desc.group") == 0 ||
    2163           8 :             strcasecmp_m(name, "system.nt_sec_desc.group+") == 0 ||
    2164           8 :             strncasecmp_m(name, "system.nt_sec_desc.acl", 22) == 0 ||
    2165           8 :             strncasecmp_m(name, "system.nt_sec_desc.acl+", 23) == 0 ||
    2166           8 :             strcasecmp_m(name, "system.dos_attr.*") == 0 ||
    2167           8 :             strncasecmp_m(name, "system.dos_attr.*!", 18) == 0 ||
    2168           8 :             strcasecmp_m(name, "system.dos_attr.mode") == 0 ||
    2169           4 :             strcasecmp_m(name, "system.dos_attr.size") == 0 ||
    2170           4 :             (attr_strings.create_time_attr != NULL &&
    2171           4 :              strcasecmp_m(name, attr_strings.create_time_attr) == 0) ||
    2172           8 :             strcasecmp_m(name, attr_strings.access_time_attr) == 0 ||
    2173           8 :             strcasecmp_m(name, attr_strings.write_time_attr) == 0 ||
    2174           8 :             strcasecmp_m(name, attr_strings.change_time_attr) == 0 ||
    2175           4 :             strcasecmp_m(name, "system.dos_attr.inode") == 0) {
    2176             : 
    2177             :                 /* Yup. */
    2178           8 :                 const char *filename = name;
    2179           8 :                 ret = cacl_get(context, talloc_tos(), srv,
    2180             :                                ipc_srv == NULL ? NULL : ipc_srv->cli,
    2181             :                                &ipc_srv->pol, path,
    2182             :                                filename,
    2183             :                                discard_const_p(char, value),
    2184             :                                size);
    2185           8 :                 TALLOC_FREE(frame);
    2186             :                 /*
    2187             :                  * static function cacl_get returns a value greater than zero
    2188             :                  * which is needed buffer size needed when size_t is 0.
    2189             :                  */
    2190           8 :                 return ret;
    2191             :         }
    2192             : 
    2193             :         /* Unsupported attribute name */
    2194           4 :         errno = EINVAL;
    2195           4 :         TALLOC_FREE(frame);
    2196           4 :         return -1;
    2197             : }
    2198             : 
    2199             : 
    2200             : int
    2201           0 : SMBC_removexattr_ctx(SMBCCTX *context,
    2202             :                      const char *fname,
    2203             :                      const char *name)
    2204             : {
    2205           0 :         int ret;
    2206           0 :         SMBCSRV *srv = NULL;
    2207           0 :         SMBCSRV *ipc_srv = NULL;
    2208           0 :         char *server = NULL;
    2209           0 :         char *share = NULL;
    2210           0 :         char *user = NULL;
    2211           0 :         char *password = NULL;
    2212           0 :         char *workgroup = NULL;
    2213           0 :         char *path = NULL;
    2214           0 :         uint16_t port = 0;
    2215           0 :         TALLOC_CTX *frame = talloc_stackframe();
    2216             : 
    2217           0 :         if (!context || !context->internal->initialized) {
    2218           0 :                 errno = EINVAL;  /* Best I can think of ... */
    2219           0 :                 TALLOC_FREE(frame);
    2220           0 :                 return -1;
    2221             :         }
    2222             : 
    2223           0 :         if (!fname) {
    2224           0 :                 errno = EINVAL;
    2225           0 :                 TALLOC_FREE(frame);
    2226           0 :                 return -1;
    2227             :         }
    2228             : 
    2229           0 :         DEBUG(4, ("smbc_removexattr(%s, %s)\n", fname, name));
    2230             : 
    2231           0 :         if (SMBC_parse_path(frame,
    2232             :                             context,
    2233             :                             fname,
    2234             :                             &workgroup,
    2235             :                             &server,
    2236             :                             &port,
    2237             :                             &share,
    2238             :                             &path,
    2239             :                             &user,
    2240             :                             &password,
    2241             :                             NULL)) {
    2242           0 :                 errno = EINVAL;
    2243           0 :                 TALLOC_FREE(frame);
    2244           0 :                 return -1;
    2245             :         }
    2246             : 
    2247           0 :         if (!user || user[0] == (char)0) {
    2248           0 :                 user = talloc_strdup(frame, smbc_getUser(context));
    2249           0 :                 if (!user) {
    2250           0 :                         errno = ENOMEM;
    2251           0 :                         TALLOC_FREE(frame);
    2252           0 :                         return -1;
    2253             :                 }
    2254             :         }
    2255             : 
    2256           0 :         srv = SMBC_server(frame, context, True,
    2257             :                           server, port, share, &workgroup, &user, &password);
    2258           0 :         if (!srv) {
    2259           0 :                 TALLOC_FREE(frame);
    2260           0 :                 return -1;  /* errno set by SMBC_server */
    2261             :         }
    2262             : 
    2263           0 :         if (! srv->no_nt_session) {
    2264           0 :                 int saved_errno;
    2265           0 :                 ipc_srv = SMBC_attr_server(frame, context, server, port, share,
    2266             :                                            &workgroup, &user, &password);
    2267           0 :                 saved_errno = errno;
    2268             :                 /*
    2269             :                  * SMBC_attr_server() can cause the original
    2270             :                  * server to be removed from the cache.
    2271             :                  * If so we must error out here as the srv
    2272             :                  * pointer has been freed.
    2273             :                  */
    2274           0 :                 if (smbc_getFunctionGetCachedServer(context)(context,
    2275             :                                 server,
    2276             :                                 share,
    2277             :                                 workgroup,
    2278             :                                 user) != srv) {
    2279             : #if defined(ECONNRESET)
    2280           0 :                         errno = ECONNRESET;
    2281             : #else
    2282             :                         errno = ETIMEDOUT;
    2283             : #endif
    2284           0 :                         TALLOC_FREE(frame);
    2285           0 :                         return -1;
    2286             :                 }
    2287           0 :                 if (! ipc_srv) {
    2288           0 :                         errno = saved_errno;
    2289           0 :                         srv->no_nt_session = True;
    2290             :                 }
    2291             :         } else {
    2292           0 :                 ipc_srv = NULL;
    2293             :         }
    2294             : 
    2295           0 :         if (! ipc_srv) {
    2296           0 :                 TALLOC_FREE(frame);
    2297           0 :                 return -1; /* errno set by SMBC_attr_server */
    2298             :         }
    2299             : 
    2300             :         /* Are they asking to set the entire ACL? */
    2301           0 :         if (strcasecmp_m(name, "system.nt_sec_desc.*") == 0 ||
    2302           0 :             strcasecmp_m(name, "system.nt_sec_desc.*+") == 0) {
    2303             : 
    2304             :                 /* Yup. */
    2305           0 :                 ret = cacl_set(context, talloc_tos(), srv->cli,
    2306             :                                ipc_srv->cli, &ipc_srv->pol, path,
    2307             :                                NULL, SMBC_XATTR_MODE_REMOVE_ALL, 0);
    2308           0 :                 TALLOC_FREE(frame);
    2309           0 :                 return ret;
    2310             :         }
    2311             : 
    2312             :         /*
    2313             :          * Are they asking to remove one or more specific security descriptor
    2314             :          * attributes?
    2315             :          */
    2316           0 :         if (strcasecmp_m(name, "system.nt_sec_desc.revision") == 0 ||
    2317           0 :             strcasecmp_m(name, "system.nt_sec_desc.owner") == 0 ||
    2318           0 :             strcasecmp_m(name, "system.nt_sec_desc.owner+") == 0 ||
    2319           0 :             strcasecmp_m(name, "system.nt_sec_desc.group") == 0 ||
    2320           0 :             strcasecmp_m(name, "system.nt_sec_desc.group+") == 0 ||
    2321           0 :             strncasecmp_m(name, "system.nt_sec_desc.acl", 22) == 0 ||
    2322           0 :             strncasecmp_m(name, "system.nt_sec_desc.acl+", 23) == 0) {
    2323             : 
    2324             :                 /* Yup. */
    2325           0 :                 ret = cacl_set(context, talloc_tos(), srv->cli,
    2326             :                                ipc_srv->cli, &ipc_srv->pol, path,
    2327             :                                discard_const_p(char, name) + 19,
    2328             :                                SMBC_XATTR_MODE_REMOVE, 0);
    2329           0 :                 TALLOC_FREE(frame);
    2330           0 :                 return ret;
    2331             :         }
    2332             : 
    2333             :         /* Unsupported attribute name */
    2334           0 :         errno = EINVAL;
    2335           0 :         TALLOC_FREE(frame);
    2336           0 :         return -1;
    2337             : }
    2338             : 
    2339             : int
    2340           0 : SMBC_listxattr_ctx(SMBCCTX *context,
    2341             :                    const char *fname,
    2342             :                    char *list,
    2343             :                    size_t size)
    2344             : {
    2345             :         /*
    2346             :          * This isn't quite what listxattr() is supposed to do.  This returns
    2347             :          * the complete set of attribute names, always, rather than only those
    2348             :          * attribute names which actually exist for a file.  Hmmm...
    2349             :          */
    2350           0 :         size_t retsize;
    2351           0 :         static const char supported_old[] =
    2352             :                 "system.*\0"
    2353             :                 "system.*+\0"
    2354             :                 "system.nt_sec_desc.revision\0"
    2355             :                 "system.nt_sec_desc.owner\0"
    2356             :                 "system.nt_sec_desc.owner+\0"
    2357             :                 "system.nt_sec_desc.group\0"
    2358             :                 "system.nt_sec_desc.group+\0"
    2359             :                 "system.nt_sec_desc.acl.*\0"
    2360             :                 "system.nt_sec_desc.acl\0"
    2361             :                 "system.nt_sec_desc.acl+\0"
    2362             :                 "system.nt_sec_desc.*\0"
    2363             :                 "system.nt_sec_desc.*+\0"
    2364             :                 "system.dos_attr.*\0"
    2365             :                 "system.dos_attr.mode\0"
    2366             :                 "system.dos_attr.c_time\0"
    2367             :                 "system.dos_attr.a_time\0"
    2368             :                 "system.dos_attr.m_time\0"
    2369             :                 ;
    2370           0 :         static const char supported_new[] =
    2371             :                 "system.*\0"
    2372             :                 "system.*+\0"
    2373             :                 "system.nt_sec_desc.revision\0"
    2374             :                 "system.nt_sec_desc.owner\0"
    2375             :                 "system.nt_sec_desc.owner+\0"
    2376             :                 "system.nt_sec_desc.group\0"
    2377             :                 "system.nt_sec_desc.group+\0"
    2378             :                 "system.nt_sec_desc.acl.*\0"
    2379             :                 "system.nt_sec_desc.acl\0"
    2380             :                 "system.nt_sec_desc.acl+\0"
    2381             :                 "system.nt_sec_desc.*\0"
    2382             :                 "system.nt_sec_desc.*+\0"
    2383             :                 "system.dos_attr.*\0"
    2384             :                 "system.dos_attr.mode\0"
    2385             :                 "system.dos_attr.create_time\0"
    2386             :                 "system.dos_attr.access_time\0"
    2387             :                 "system.dos_attr.write_time\0"
    2388             :                 "system.dos_attr.change_time\0"
    2389             :                 ;
    2390           0 :         const char * supported;
    2391             : 
    2392           0 :         if (context->internal->full_time_names) {
    2393           0 :                 supported = supported_new;
    2394           0 :                 retsize = sizeof(supported_new);
    2395             :         } else {
    2396           0 :                 supported = supported_old;
    2397           0 :                 retsize = sizeof(supported_old);
    2398             :         }
    2399             : 
    2400           0 :         if (size == 0) {
    2401           0 :                 return retsize;
    2402             :         }
    2403             : 
    2404           0 :         if (retsize > size) {
    2405           0 :                 errno = ERANGE;
    2406           0 :                 return -1;
    2407             :         }
    2408             : 
    2409             :         /* this can't be strcpy() because there are embedded null characters */
    2410           0 :         memcpy(list, supported, retsize);
    2411           0 :         return retsize;
    2412             : }

Generated by: LCOV version 1.14