pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: Patches to move ACL code, warning cleanup+misc, 2025-11-15
Posted by Anonymous on Sat 15th Nov 2025 15:57
raw | new post

  1. From 14c0ecf4fd59d2ca2044f951419ad4eecad8b54a Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Sat, 15 Nov 2025 15:18:13 +0100
  4. Subject: [PATCH 1/5] build.vc19,daemon: Move Windows ACL from/to NFSv4 ACL
  5.  conversion functions into aclutil.[ch]
  6.  
  7. Move Windows ACL from/to NFSv4 ACL conversion functions from acl.c
  8. into aclutil.[ch].
  9.  
  10. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  11. ---
  12. build.vc19/nfsd/nfsd.vcxproj         |    2 +
  13.  build.vc19/nfsd/nfsd.vcxproj.filters |    6 +
  14.  daemon/acl.c                         | 1159 +------------------------
  15.  daemon/aclutil.c                     | 1187 ++++++++++++++++++++++++++
  16.  daemon/aclutil.h                     |   46 +
  17.  daemon/open.c                        |    7 +-
  18.  6 files changed, 1243 insertions(+), 1164 deletions(-)
  19.  create mode 100644 daemon/aclutil.c
  20.  create mode 100644 daemon/aclutil.h
  21.  
  22. diff --git a/build.vc19/nfsd/nfsd.vcxproj b/build.vc19/nfsd/nfsd.vcxproj
  23. index 846dfbb..8589a2a 100644
  24. --- a/build.vc19/nfsd/nfsd.vcxproj
  25. +++ b/build.vc19/nfsd/nfsd.vcxproj
  26. @@ -288,6 +288,7 @@
  27.    <ItemGroup>
  28.      <ClCompile Include="..\..\daemon\accesstoken.c" />
  29.      <ClCompile Include="..\..\daemon\acl.c" />
  30. +    <ClCompile Include="..\..\daemon\aclutil.c" />
  31.      <ClCompile Include="..\..\daemon\callback_server.c" />
  32.      <ClCompile Include="..\..\daemon\callback_xdr.c" />
  33.      <ClCompile Include="..\..\daemon\cpvparser1.c" />
  34. @@ -333,6 +334,7 @@
  35.    </ItemGroup>
  36.    <ItemGroup>
  37.      <ClInclude Include="..\..\daemon\accesstoken.h" />
  38. +    <ClInclude Include="..\..\daemon\aclutil.h" />
  39.      <ClInclude Include="..\..\daemon\cpvparser1.h" />
  40.      <ClInclude Include="..\..\daemon\daemon_debug.h" />
  41.      <ClInclude Include="..\..\daemon\delegation.h" />
  42. diff --git a/build.vc19/nfsd/nfsd.vcxproj.filters b/build.vc19/nfsd/nfsd.vcxproj.filters
  43. index 135a635..8e833c1 100644
  44. --- a/build.vc19/nfsd/nfsd.vcxproj.filters
  45. +++ b/build.vc19/nfsd/nfsd.vcxproj.filters
  46. @@ -18,6 +18,9 @@
  47.      <ClCompile Include="..\..\daemon\acl.c">
  48.        <Filter>Source Files</Filter>
  49.      </ClCompile>
  50. +    <ClCompile Include="..\..\daemon\aclutil.c">
  51. +      <Filter>Source Files</Filter>
  52. +    </ClCompile>
  53.      <ClCompile Include="..\..\daemon\callback_server.c">
  54.        <Filter>Source Files</Filter>
  55.      </ClCompile>
  56. @@ -149,6 +152,9 @@
  57.      </ClCompile>
  58.    </ItemGroup>
  59.    <ItemGroup>
  60. +    <ClInclude Include="..\..\daemon\aclutil.h">
  61. +      <Filter>Header Files</Filter>
  62. +    </ClInclude>
  63.      <ClInclude Include="..\..\daemon\cpvparser1.h">
  64.        <Filter>Header Files</Filter>
  65.      </ClInclude>
  66. diff --git a/daemon/acl.c b/daemon/acl.c
  67. index d53281e..bd02f56 100644
  68. --- a/daemon/acl.c
  69. +++ b/daemon/acl.c
  70. @@ -28,6 +28,7 @@
  71.  
  72.  #include "nfs41_ops.h"
  73.  #include "nfs41_build_features.h"
  74. +#include "aclutil.h"
  75.  #include "nfs41_daemon.h"
  76.  #include "delegation.h"
  77.  #include "daemon_debug.h"
  78. @@ -36,25 +37,6 @@
  79.  #include "nfs41_xdr.h"
  80.  #include "sid.h"
  81.  
  82. -#define MAP_WIN32GENERIC2ACE4GENERIC 1
  83. -#define WORKAROUND_FOR_LINUX_NFSD_NOT_SETTING_ACE4_WRITE_ATTRIBUTES 1
  84. -
  85. -/* |DPRINTF()| levels for acl logging */
  86. -#define ACLLVL1 1
  87. -#define ACLLVL2 2
  88. -#define ACLLVL3 3
  89. -
  90. -#define ACE4_RW_NAMED_ATTRS \
  91. -    (ACE4_READ_NAMED_ATTRS|ACE4_WRITE_NAMED_ATTRS)
  92. -
  93. -/* Local prototypes */
  94. -static void map_winace2nfs4aceflags(BYTE win_aceflags, uint32_t *nfs4_aceflags);
  95. -static void map_nfs4aceflags2winaceflags(uint32_t nfs4_aceflags, DWORD *win_aceflags);
  96. -static void map_winaccessmask2nfs4acemask(ACCESS_MASK win_mask,
  97. -    int file_type, bool named_attr_support, uint32_t *nfs4_mask);
  98. -static void map_nfs4acemask2winaccessmask(uint32_t nfs4_mask,
  99. -    int file_type, bool named_attr_support, ACCESS_MASK *win_mask);
  100. -
  101.  static int parse_getacl(
  102.      const unsigned char *restrict buffer,
  103.      uint32_t length,
  104. @@ -73,267 +55,6 @@ out:
  105.      return status;
  106.  }
  107.  
  108. -static void convert_nfs4name_2_user_domain(LPSTR nfs4name,
  109. -                                           LPSTR *domain)
  110. -{
  111. -    LPSTR p = nfs4name;
  112. -    for(; p[0] != '\0'; p++) {
  113. -        if (p[0] == '@') {
  114. -            p[0] = '\0';
  115. -
  116. -            *domain = &p[1];
  117. -            break;
  118. -        }
  119. -    }
  120. -}
  121. -
  122. -static void free_sids(PSID *sids, int count)
  123. -{
  124. -    int i;
  125. -    for(i = 0; i < count; i++)
  126. -        free(sids[i]);
  127. -    free(sids);
  128. -}
  129. -
  130. -static int check_4_special_identifiers(const char *restrict who,
  131. -    PSID *sid,
  132. -    DWORD *sid_len,
  133. -    BOOLEAN *flag)
  134. -{
  135. -    int status = ERROR_SUCCESS;
  136. -    WELL_KNOWN_SID_TYPE type = 0;
  137. -    *flag = TRUE;
  138. -
  139. -    /*
  140. -     * Compare |who| against known constant strings, excluding the '@'
  141. -     * symbol. Note that |ACE4_NOBODY| and |ACE4_WIN_NULL_SID| do not
  142. -     * have a '@
  143. -     */
  144. -    if (!strncmp(who, ACE4_OWNER, ACE4_OWNER_LEN-1))
  145. -        type = WinCreatorOwnerSid;
  146. -#ifdef NFS41_DRIVER_WS2022_HACKS
  147. -    else if (!strncmp(who, ACE4_WIN_CREATOR_OWNER, ACE4_WIN_CREATOR_OWNER_LEN-1))
  148. -        type = WinCreatorOwnerSid;
  149. -#endif /* NFS41_DRIVER_WS2022_HACKS */
  150. -    else if (!strncmp(who, ACE4_GROUP, ACE4_GROUP_LEN-1))
  151. -        type = WinCreatorGroupSid;
  152. -#ifdef NFS41_DRIVER_WS2022_HACKS
  153. -    else if (!strncmp(who, ACE4_WIN_CREATOR_GROUP, ACE4_WIN_CREATOR_GROUP_LEN-1))
  154. -        type = WinCreatorGroupSid;
  155. -#endif /* NFS41_DRIVER_WS2022_HACKS */
  156. -    else if (!strncmp(who, ACE4_EVERYONE, ACE4_EVERYONE_LEN-1))
  157. -        type = WinWorldSid;
  158. -#ifdef NFS41_DRIVER_WS2022_HACKS
  159. -    else if (!strncmp(who, ACE4_WIN_EVERYONE, ACE4_WIN_EVERYONE_LEN-1))
  160. -        type = WinWorldSid;
  161. -#endif /* NFS41_DRIVER_WS2022_HACKS */
  162. -    else if (!strncmp(who, ACE4_NOBODY, ACE4_NOBODY_LEN))
  163. -        type = WinNullSid;
  164. -#ifdef NFS41_DRIVER_WS2022_HACKS
  165. -    else if (!strncmp(who, ACE4_WIN_NULL_SID, ACE4_WIN_NULL_SID_LEN))
  166. -        type = WinNullSid;
  167. -#endif /* NFS41_DRIVER_WS2022_HACKS */
  168. -    else
  169. -        *flag = FALSE;
  170. -    if (*flag)
  171. -        status = create_unknownsid(type, sid, sid_len);
  172. -    return status;
  173. -}
  174. -
  175. -static int convert_nfs4acl_2_dacl(nfs41_daemon_globals *nfs41dg,
  176. -    nfsacl41 *acl, int file_type, PACL *dacl_out, PSID **sids_out,
  177. -    bool named_attr_support)
  178. -{
  179. -    int status = ERROR_NOT_SUPPORTED, size = 0;
  180. -    uint32_t nfs_i = 0, win_i = 0;
  181. -    DWORD sid_len;
  182. -    PSID *sids;
  183. -    PACL dacl;
  184. -    LPSTR domain = NULL;
  185. -    BOOLEAN flag;
  186. -
  187. -    DPRINTF(ACLLVL2, ("--> convert_nfs4acl_2_dacl(acl=0x%p,"
  188. -        "file_type='%s'(=%d), named_attr_support=%d)\n",
  189. -        acl, map_nfs_ftype2str(file_type), file_type,
  190. -        (int)named_attr_support));
  191. -
  192. -    bool *skip_aces = _alloca(acl->count * sizeof(bool));
  193. -
  194. -    /*
  195. -     * We use |calloc()| here to get |NULL| pointer for unallocated
  196. -     * slots in case of error codepaths below...
  197. -     */
  198. -    sids = calloc(acl->count, sizeof(PSID));
  199. -    if (sids == NULL) {
  200. -        status = GetLastError();
  201. -        goto out;
  202. -    }
  203. -    for (nfs_i = win_i = 0; nfs_i < acl->count; nfs_i++) {
  204. -        nfsace4 *curr_nfsace = &acl->aces[nfs_i];
  205. -
  206. -        skip_aces[nfs_i] = false;
  207. -
  208. -        convert_nfs4name_2_user_domain(curr_nfsace->who, &domain);
  209. -        DPRINTF(ACLLVL2, ("convert_nfs4acl_2_dacl: for user='%s' domain='%s'\n",
  210. -                curr_nfsace->who, domain?domain:"<null>"));
  211. -
  212. -        EASSERT_MSG(!isdigit(curr_nfsace->who[0]),
  213. -            ("convert_nfs4acl_2_dacl: aces[%d]->who='%s' uses numeric id\n",
  214. -            (int)nfs_i, curr_nfsace->who));
  215. -
  216. -#ifdef NFS41_DRIVER_ACLS_SETACL_SKIP_WINNULLSID_ACES
  217. -        /*
  218. -         * Skip "nobody" ACEs - Cygwin uses |WinNullSid| ACEs (mapped
  219. -         * to NFS user "nobody") to store special data.
  220. -         * We skip these here, because we cannot use them, as Linux nfsd
  221. -         * only supports POSIX ACLs translated to NFSv4 ACLs, which
  222. -         * corrupts the Cygwin data.
  223. -         */
  224. -        if (!strcmp(curr_nfsace->who, ACE4_NOBODY)) {
  225. -            DPRINTF(ACLLVL3, ("Skipping 'nobody' ACE, "
  226. -                "win_i=%d nfs_i=%d\n", (int)win_i, (int)nfs_i));
  227. -            skip_aces[nfs_i] = true;
  228. -            continue;
  229. -        }
  230. -#endif /* NFS41_DRIVER_ACLS_SETACL_SKIP_WINNULLSID_ACES */
  231. -
  232. -        status = check_4_special_identifiers(curr_nfsace->who, &sids[win_i],
  233. -                                             &sid_len, &flag);
  234. -        if (status) {
  235. -            free_sids(sids, win_i);
  236. -            goto out;
  237. -        }
  238. -        if (!flag) {
  239. -            bool isgroupacl = (curr_nfsace->aceflag & ACE4_IDENTIFIER_GROUP)?true:false;
  240. -
  241. -
  242. -#ifdef NFS41_DRIVER_WS2022_HACKS
  243. -            if ((isgroupacl == false) && domain &&
  244. -                (!strcmp(domain, "BUILTIN"))) {
  245. -                if ((!strcmp(curr_nfsace->who, "Users")) ||
  246. -                    (!strcmp(curr_nfsace->who, "Administrators"))) {
  247. -                    DPRINTF(1, ("convert_nfs4acl_2_dacl: "
  248. -                        "force isgroupacl=true for for user='%s'\n",
  249. -                        curr_nfsace->who));
  250. -                    isgroupacl = true;
  251. -                }
  252. -            }
  253. -#endif /* NFS41_DRIVER_WS2022_HACKS */
  254. -            if (isgroupacl) {
  255. -                DPRINTF(ACLLVL2,
  256. -                    ("convert_nfs4acl_2_dacl: aces[%d].who='%s': "
  257. -                    "Setting group flag\n",
  258. -                    nfs_i, curr_nfsace->who));
  259. -            }
  260. -
  261. -            status = map_nfs4servername_2_sid(nfs41dg,
  262. -                (isgroupacl?GROUP_SECURITY_INFORMATION:OWNER_SECURITY_INFORMATION),
  263. -                &sid_len, &sids[win_i], curr_nfsace->who);
  264. -            if (status) {
  265. -                free_sids(sids, win_i);
  266. -                goto out;
  267. -            }
  268. -        }
  269. -        size += sid_len - sizeof(DWORD);
  270. -
  271. -        win_i++;
  272. -    }
  273. -    size += sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE)*win_i);
  274. -    size = align8(size); // align size on |DWORD| boundry
  275. -    dacl = malloc(size);
  276. -    if (dacl == NULL)
  277. -        goto out_free_sids;
  278. -
  279. -    if (InitializeAcl(dacl, size, ACL_REVISION)) {
  280. -        ACCESS_MASK mask;
  281. -        DWORD win_aceflags;
  282. -
  283. -        for (nfs_i = win_i = 0; nfs_i < acl->count; nfs_i++) {
  284. -            nfsace4 *curr_nfsace = &acl->aces[nfs_i];
  285. -
  286. -            if (skip_aces[nfs_i])
  287. -                continue;
  288. -
  289. -            map_nfs4aceflags2winaceflags(curr_nfsace->aceflag,
  290. -                &win_aceflags);
  291. -            map_nfs4acemask2winaccessmask(curr_nfsace->acemask,
  292. -                file_type, named_attr_support, &mask);
  293. -
  294. -            if (DPRINTF_LEVEL_ENABLED(ACLLVL1)) {
  295. -                dprintf_out("nfs2win: acl->aces[%d].who='%s': "
  296. -                    "acetype='%s', "
  297. -                    "nfs_acemask=0x%lx, win_mask=0x%lx, "
  298. -                    "win_aceflags=0x%lx\n",
  299. -                    nfs_i, curr_nfsace->who,
  300. -                    map_nfs_acetype2str(curr_nfsace->acetype),
  301. -                    (long)curr_nfsace->acemask,
  302. -                    (long)mask,
  303. -                    (long)win_aceflags);
  304. -
  305. -                print_nfs_access_mask(curr_nfsace->who,
  306. -                    curr_nfsace->acemask);
  307. -                print_windows_access_mask(curr_nfsace->who, mask);
  308. -            }
  309. -
  310. -            if (curr_nfsace->acetype == ACE4_ACCESS_ALLOWED_ACE_TYPE) {
  311. -                status = AddAccessAllowedAceEx(dacl, ACL_REVISION,
  312. -                    win_aceflags, mask, sids[win_i]);
  313. -                if (!status) {
  314. -                    eprintf("convert_nfs4acl_2_dacl: "
  315. -                        "AddAccessAllowedAceEx"
  316. -                        "(dacl=0x%p,win_aceflags=0x%x,mask=0x%x,who='%s') "
  317. -                        "failed with lasterr=%d\n",
  318. -                        dacl, (int)win_aceflags, (int)mask,
  319. -                        curr_nfsace->who, (int)GetLastError());
  320. -                    status = ERROR_INTERNAL_ERROR;
  321. -                    goto out_free_dacl;
  322. -                }
  323. -                status = ERROR_SUCCESS;
  324. -            } else if (curr_nfsace->acetype == ACE4_ACCESS_DENIED_ACE_TYPE) {
  325. -                status = AddAccessDeniedAceEx(dacl, ACL_REVISION,
  326. -                    win_aceflags, mask, sids[win_i]);
  327. -                if (!status) {
  328. -                    eprintf("convert_nfs4acl_2_dacl: "
  329. -                        "AddAccessDeniedAceEx"
  330. -                        "(dacl=0x%p,win_aceflags=0x%x,mask=0x%x,who='%s') "
  331. -                        "failed with lasterr=%d\n",
  332. -                        dacl, (int)win_aceflags, (int)mask,
  333. -                        curr_nfsace->who, (int)GetLastError());
  334. -                    status = ERROR_INTERNAL_ERROR;
  335. -                    goto out_free_dacl;
  336. -                }
  337. -                status = ERROR_SUCCESS;
  338. -            } else {
  339. -                eprintf("convert_nfs4acl_2_dacl: unknown acetype %d\n",
  340. -                        curr_nfsace->acetype);
  341. -                status = ERROR_INTERNAL_ERROR;
  342. -                free(dacl);
  343. -                free_sids(sids, win_i);
  344. -                goto out;
  345. -            }
  346. -
  347. -            win_i++;
  348. -        }
  349. -    } else {
  350. -        eprintf("convert_nfs4acl_2_dacl: InitializeAcl failed with %d\n", status);
  351. -        goto out_free_dacl;
  352. -    }
  353. -    status = ERROR_SUCCESS;
  354. -    *sids_out = sids;
  355. -    *dacl_out = dacl;
  356. -out:
  357. -    DPRINTF(ACLLVL2, ("<-- convert_nfs4acl_2_dacl("
  358. -        "acl=0x%p,file_type='%s'(=%d)) returning %d\n",
  359. -        acl, map_nfs_ftype2str(file_type), file_type, status));
  360. -    return status;
  361. -out_free_dacl:
  362. -    free(dacl);
  363. -out_free_sids:
  364. -    free_sids(sids, win_i);
  365. -    status = GetLastError();
  366. -    goto out;
  367. -}
  368. -
  369.  static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
  370.  {
  371.      int status = ERROR_NOT_SUPPORTED;
  372. @@ -553,884 +274,6 @@ out:
  373.      return status;
  374.  }
  375.  
  376. -static int is_well_known_sid(PSID sid, char *who, SID_NAME_USE *snu_out)
  377. -{
  378. -    const WELL_KNOWN_SID_TYPE test_types[] = {
  379. -        WinCreatorOwnerSid,
  380. -        WinCreatorGroupSid,
  381. -        WinBuiltinUsersSid,
  382. -        WinNullSid,
  383. -        WinAnonymousSid,
  384. -        WinWorldSid,
  385. -        WinAuthenticatedUserSid,
  386. -        WinDialupSid,
  387. -        WinNetworkSid,
  388. -        WinBatchSid,
  389. -        WinInteractiveSid,
  390. -        WinNetworkServiceSid,
  391. -        WinLocalServiceSid,
  392. -        WinServiceSid
  393. -    };
  394. -    const size_t test_types_count = ARRAYSIZE(test_types);
  395. -
  396. -    BOOL ismatch;
  397. -    size_t i;
  398. -
  399. -#ifdef _DEBUG
  400. -    static bool once = true;
  401. -
  402. -    if (once) {
  403. -        once = false;
  404. -        EASSERT(test_types_count == 14);
  405. -        /* Safeguards if someone tampers with the #defines for this */
  406. -        EASSERT(strlen(ACE4_OWNER) == ACE4_OWNER_LEN);
  407. -        EASSERT(strlen(ACE4_GROUP) == ACE4_GROUP_LEN);
  408. -        EASSERT(strlen(ACE4_NOBODY) == ACE4_NOBODY_LEN);
  409. -        EASSERT(strlen(ACE4_ANONYMOUS) == ACE4_ANONYMOUS_LEN);
  410. -        EASSERT(strlen(ACE4_EVERYONE) == ACE4_EVERYONE_LEN);
  411. -    }
  412. -#endif /* _DEBUG */
  413. -
  414. -    for (i = 0; i < test_types_count ; i++) {
  415. -        WELL_KNOWN_SID_TYPE tt = test_types[i];
  416. -
  417. -        ismatch = IsWellKnownSid(sid, tt);
  418. -        if (!ismatch) {
  419. -            continue;
  420. -        }
  421. -
  422. -        DPRINTF(ACLLVL3, ("WELL_KNOWN_SID_TYPE=%d\n", (int)tt));
  423. -        switch(tt) {
  424. -            case WinCreatorOwnerSid:
  425. -                (void)memcpy(who, ACE4_OWNER, ACE4_OWNER_LEN+1);
  426. -                *snu_out = SidTypeUser;
  427. -                return TRUE;
  428. -            case WinCreatorGroupSid:
  429. -            case WinBuiltinUsersSid:
  430. -                (void)memcpy(who, ACE4_GROUP, ACE4_GROUP_LEN+1);
  431. -                *snu_out = SidTypeGroup;
  432. -                return TRUE;
  433. -            case WinNullSid:
  434. -                (void)memcpy(who, ACE4_NOBODY, ACE4_NOBODY_LEN+1);
  435. -                *snu_out = SidTypeUser;
  436. -                return TRUE;
  437. -            case WinAnonymousSid:
  438. -                (void)memcpy(who, ACE4_ANONYMOUS, ACE4_ANONYMOUS_LEN+1);
  439. -                return TRUE;
  440. -            case WinWorldSid:
  441. -                (void)memcpy(who, ACE4_EVERYONE, ACE4_EVERYONE_LEN+1);
  442. -                *snu_out = SidTypeGroup;
  443. -                return TRUE;
  444. -            case WinAuthenticatedUserSid:
  445. -                (void)memcpy(who, ACE4_AUTHENTICATED, ACE4_AUTHENTICATED_LEN+1);
  446. -                return TRUE;
  447. -            case WinDialupSid:
  448. -                (void)memcpy(who, ACE4_DIALUP, ACE4_DIALUP_LEN+1);
  449. -                return TRUE;
  450. -            case WinNetworkSid:
  451. -                (void)memcpy(who, ACE4_NETWORK, ACE4_NETWORK_LEN+1);
  452. -                return TRUE;
  453. -            case WinBatchSid:
  454. -                (void)memcpy(who, ACE4_BATCH, ACE4_BATCH_LEN+1);
  455. -                return TRUE;
  456. -            case WinInteractiveSid:
  457. -                (void)memcpy(who, ACE4_INTERACTIVE, ACE4_INTERACTIVE_LEN+1);
  458. -                return TRUE;
  459. -            case WinNetworkServiceSid:
  460. -            case WinLocalServiceSid:
  461. -            case WinServiceSid:
  462. -                (void)memcpy(who, ACE4_SERVICE, ACE4_SERVICE_LEN+1);
  463. -                return TRUE;
  464. -            default:
  465. -                eprintf("is_well_known_sid: unknown tt=%d\n", (int)tt);
  466. -                return FALSE;
  467. -        }
  468. -    }
  469. -    return FALSE;
  470. -}
  471. -
  472. -static void map_winace2nfs4aceflags(BYTE win_aceflags, uint32_t *nfs4_aceflags)
  473. -{
  474. -    *nfs4_aceflags = 0;
  475. -
  476. -    if (win_aceflags & OBJECT_INHERIT_ACE)
  477. -        *nfs4_aceflags |= ACE4_FILE_INHERIT_ACE;
  478. -    if (win_aceflags & CONTAINER_INHERIT_ACE)
  479. -        *nfs4_aceflags |= ACE4_DIRECTORY_INHERIT_ACE;
  480. -    if (win_aceflags & NO_PROPAGATE_INHERIT_ACE)
  481. -        *nfs4_aceflags |= ACE4_NO_PROPAGATE_INHERIT_ACE;
  482. -    if (win_aceflags & INHERIT_ONLY_ACE)
  483. -        *nfs4_aceflags |= ACE4_INHERIT_ONLY_ACE;
  484. -    if (win_aceflags & INHERITED_ACE)
  485. -        *nfs4_aceflags |= ACE4_INHERITED_ACE;
  486. -    DPRINTF(ACLLVL3,
  487. -        ("map_winace2nfs4aceflags: win_aceflags=0x%x nfs4_aceflags=0x%x\n",
  488. -        (int)win_aceflags, (int)*nfs4_aceflags));
  489. -}
  490. -
  491. -static void map_nfs4aceflags2winaceflags(uint32_t nfs4_aceflags, DWORD *win_aceflags)
  492. -{
  493. -    *win_aceflags = 0;
  494. -
  495. -    if (nfs4_aceflags & ACE4_FILE_INHERIT_ACE)
  496. -        *win_aceflags |= OBJECT_INHERIT_ACE;
  497. -    if (nfs4_aceflags & ACE4_DIRECTORY_INHERIT_ACE)
  498. -        *win_aceflags |= CONTAINER_INHERIT_ACE;
  499. -    if (nfs4_aceflags & ACE4_NO_PROPAGATE_INHERIT_ACE)
  500. -        *win_aceflags |= NO_PROPAGATE_INHERIT_ACE;
  501. -    if (nfs4_aceflags & ACE4_INHERIT_ONLY_ACE)
  502. -        *win_aceflags |= INHERIT_ONLY_ACE;
  503. -    if (nfs4_aceflags & ACE4_INHERITED_ACE)
  504. -        *win_aceflags |= INHERITED_ACE;
  505. -    DPRINTF(ACLLVL3,
  506. -        ("map_nfs4aceflags2winace: nfs4_aceflags=0x%x win_aceflags=0x%x\n",
  507. -        (int)nfs4_aceflags, (int)*win_aceflags));
  508. -}
  509. -
  510. -static
  511. -void map_winaccessmask2nfs4acemask(ACCESS_MASK win_mask,
  512. -    int file_type, bool named_attr_support, uint32_t *nfs4_mask)
  513. -{
  514. -    *nfs4_mask = 0;
  515. -
  516. -    /* check if any GENERIC bits set */
  517. -    if (win_mask & 0xf000000) {
  518. -        /* Filtered |ACE4_GENERIC_*| masks */
  519. -        uint32_t ace4_generic_read_filt = ACE4_GENERIC_READ;
  520. -        uint32_t ace4_generic_write_filt =  ACE4_GENERIC_WRITE;
  521. -        uint32_t ace4_generic_execute_filt = ACE4_GENERIC_EXECUTE;
  522. -        uint32_t ace4_all_file_filt = ACE4_ALL_FILE;
  523. -        uint32_t ace4_all_dir_filt = ACE4_ALL_DIR;
  524. -
  525. -#ifdef MAP_WIN32GENERIC2ACE4GENERIC
  526. -        if (!named_attr_support) {
  527. -            /*
  528. -             * Filter out unsupported features for
  529. -             * |GENERIC_*| --> |ACE_*ATTR| conversion.
  530. -             * Do not filter out explicit individual flags below!
  531. -             */
  532. -            ace4_generic_read_filt &= ~ACE4_RW_NAMED_ATTRS;
  533. -            ace4_generic_write_filt &= ~ACE4_RW_NAMED_ATTRS;
  534. -            ace4_generic_execute_filt &= ~ACE4_RW_NAMED_ATTRS;
  535. -            ace4_all_file_filt &= ~ACE4_RW_NAMED_ATTRS;
  536. -            ace4_all_dir_filt &= ~ACE4_RW_NAMED_ATTRS;
  537. -        }
  538. -#endif /* MAP_WIN32GENERIC2ACE4GENERIC */
  539. -
  540. -        if (win_mask & GENERIC_ALL) {
  541. -            if (file_type == NF4DIR)
  542. -                *nfs4_mask |= ace4_all_dir_filt;
  543. -            else
  544. -                *nfs4_mask |= ace4_all_file_filt;
  545. -        } else {
  546. -            if (win_mask & GENERIC_READ)
  547. -                *nfs4_mask |= ace4_generic_read_filt;
  548. -            if (win_mask & GENERIC_WRITE)
  549. -                *nfs4_mask |= ace4_generic_write_filt;
  550. -            if (win_mask & GENERIC_EXECUTE)
  551. -                *nfs4_mask |= ace4_generic_execute_filt;
  552. -        }
  553. -    }
  554. -
  555. -    /* Individual flags */
  556. -    if (file_type == NF4DIR) {
  557. -        if (win_mask & FILE_LIST_DIRECTORY) {
  558. -            *nfs4_mask |= ACE4_LIST_DIRECTORY;
  559. -        }
  560. -        if (win_mask & FILE_ADD_FILE) {
  561. -            *nfs4_mask |= ACE4_ADD_FILE;
  562. -        }
  563. -        if (win_mask & FILE_ADD_SUBDIRECTORY) {
  564. -            *nfs4_mask |= ACE4_ADD_SUBDIRECTORY;
  565. -        }
  566. -        if (win_mask & FILE_DELETE_CHILD) {
  567. -            *nfs4_mask |= ACE4_DELETE_CHILD;
  568. -        }
  569. -        if (win_mask & FILE_TRAVERSE) {
  570. -            *nfs4_mask |= ACE4_EXECUTE;
  571. -        }
  572. -    }
  573. -    else {
  574. -        if (win_mask & FILE_READ_DATA) {
  575. -            *nfs4_mask |= ACE4_READ_DATA;
  576. -        }
  577. -        if (win_mask & FILE_WRITE_DATA) {
  578. -            *nfs4_mask |= ACE4_WRITE_DATA;
  579. -        }
  580. -        if (win_mask & FILE_APPEND_DATA) {
  581. -            *nfs4_mask |= ACE4_APPEND_DATA;
  582. -        }
  583. -        if (win_mask & FILE_EXECUTE) {
  584. -            *nfs4_mask |= ACE4_EXECUTE;
  585. -        }
  586. -        /*
  587. -         * gisburn: Why does Win10 set |FILE_DELETE_CHILD| for
  588. -         * plain files ?
  589. -         */
  590. -        if (win_mask & FILE_DELETE_CHILD) {
  591. -            *nfs4_mask |= ACE4_DELETE_CHILD;
  592. -        }
  593. -    }
  594. -
  595. -    if (win_mask & FILE_READ_EA) {
  596. -        *nfs4_mask |= ACE4_READ_NAMED_ATTRS;
  597. -    }
  598. -    if (win_mask & FILE_WRITE_EA) {
  599. -        *nfs4_mask |= ACE4_WRITE_NAMED_ATTRS;
  600. -    }
  601. -    if (win_mask & FILE_READ_ATTRIBUTES) {
  602. -        *nfs4_mask |= ACE4_READ_ATTRIBUTES;
  603. -    }
  604. -    if (win_mask & FILE_WRITE_ATTRIBUTES) {
  605. -        *nfs4_mask |= ACE4_WRITE_ATTRIBUTES;
  606. -    }
  607. -    if (win_mask & READ_CONTROL) {
  608. -        *nfs4_mask |= ACE4_READ_ACL;
  609. -    }
  610. -    if (win_mask & WRITE_DAC) {
  611. -        *nfs4_mask |= ACE4_WRITE_ACL;
  612. -    }
  613. -    if (win_mask & WRITE_OWNER) {
  614. -        *nfs4_mask |= ACE4_WRITE_OWNER;
  615. -    }
  616. -    if (win_mask & SYNCHRONIZE) {
  617. -        *nfs4_mask |= ACE4_SYNCHRONIZE;
  618. -    }
  619. -    if (win_mask & DELETE) {
  620. -        *nfs4_mask |= ACE4_DELETE;
  621. -    }
  622. -
  623. -#if 1
  624. -    /* DEBUG: Compare old and new code */
  625. -    DASSERT_MSG(0,
  626. -        ((long)*nfs4_mask == (long)(win_mask & 0x00ffffff)),
  627. -        ("map_winaccessmask2nfs4acemask: "
  628. -        "new code nfs4_mask=0x%lx, "
  629. -        "old code nfs4_mask=0x%lx\n",
  630. -        (long)*nfs4_mask, (long)(win_mask & 0x00ffffff)));
  631. -#endif
  632. -}
  633. -
  634. -static
  635. -void map_nfs4acemask2winaccessmask(uint32_t nfs4_mask,
  636. -    int file_type, bool named_attr_support, ACCESS_MASK *win_mask)
  637. -{
  638. -    *win_mask = 0;
  639. -
  640. -#ifdef MAP_WIN32GENERIC2ACE4GENERIC
  641. -    bool is_generic = false;
  642. -
  643. -    /* Filtered |ACE4_GENERIC_*| masks */
  644. -    uint32_t ace4_generic_read_filt = ACE4_GENERIC_READ;
  645. -    uint32_t ace4_generic_write_filt =  ACE4_GENERIC_WRITE;
  646. -    uint32_t ace4_generic_execute_filt = ACE4_GENERIC_EXECUTE;
  647. -    uint32_t ace4_all_file_filt = ACE4_ALL_FILE;
  648. -    uint32_t ace4_all_dir_filt = ACE4_ALL_DIR;
  649. -
  650. -    if (!named_attr_support) {
  651. -        /*
  652. -         * Filter out unsupported features for
  653. -         * |ACE_*ATTR| --> |GENERIC_*| conversion.
  654. -         * Do not filter out explicit individual flags below!
  655. -         */
  656. -        ace4_generic_read_filt &= ~ACE4_RW_NAMED_ATTRS;
  657. -        ace4_generic_write_filt &= ~ACE4_RW_NAMED_ATTRS;
  658. -        ace4_generic_execute_filt &= ~ACE4_RW_NAMED_ATTRS;
  659. -        ace4_all_file_filt &= ~ACE4_RW_NAMED_ATTRS;
  660. -        ace4_all_dir_filt &= ~ACE4_RW_NAMED_ATTRS;
  661. -
  662. -#ifdef WORKAROUND_FOR_LINUX_NFSD_NOT_SETTING_ACE4_WRITE_ATTRIBUTES
  663. -        /*
  664. -         * BUG(?): Linux 6.6.32-RT32 does not return
  665. -         * |ACE4_WRITE_ATTRIBUTES| even when the attributes are
  666. -         * writeable.
  667. -         *
  668. -         * Since |ACE4_GENERIC_WRITE| includes the
  669. -         * |ACE4_WRITE_ATTRIBUTES| bit an attempt to set
  670. -         * |GENERIC_WRITE| will succeed, but we can never get all
  671. -         * the |ACE4_*| bits in |ACE4_GENERIC_WRITE| back when
  672. -         * reading the ACL, so without this workaround we could
  673. -         * never match |GENERIC_WRITE| when constructing the Win32
  674. -         * ACLs.
  675. -         *
  676. -         * Testcase:
  677. -         * ---- snip ----
  678. -         * $ ksh93 -c 'rm -f test1.txt
  679. -         * touch test1.txt
  680. -         * icacls test1.txt /grant "siegfried_wulsch:(GW)"
  681. -         * icacls test1.txt'
  682. -         * ---- snip ----
  683. -         * Second icacls should return "GW" for user "siegfried_wulsch".
  684. -         */
  685. -        ace4_generic_read_filt &= ~ACE4_WRITE_ATTRIBUTES;
  686. -        ace4_generic_write_filt &= ~ACE4_WRITE_ATTRIBUTES;
  687. -        ace4_generic_execute_filt &= ~ACE4_WRITE_ATTRIBUTES;
  688. -        ace4_all_file_filt &= ~ACE4_WRITE_ATTRIBUTES;
  689. -        ace4_all_dir_filt &= ~ACE4_WRITE_ATTRIBUTES;
  690. -#endif /* WORKAROUND_FOR_LINUX_NFSD_NOT_SETTING_ACE4_WRITE_ATTRIBUTES */
  691. -    }
  692. -
  693. -    /*
  694. -     * Generic masks
  695. -     * (|ACE4_GENERIC_*| contain multiple bits)
  696. -     */
  697. -#define ACEMASK_TEST_MASK(value, mask) (((value)&(mask)) == (mask))
  698. -    if (file_type == NF4DIR) {
  699. -        if (ACEMASK_TEST_MASK(nfs4_mask, ace4_all_dir_filt)) {
  700. -            *win_mask |= GENERIC_ALL;
  701. -            is_generic = true;
  702. -        }
  703. -    }
  704. -    else {
  705. -        if (ACEMASK_TEST_MASK(nfs4_mask, ace4_all_file_filt)) {
  706. -            *win_mask |= GENERIC_ALL;
  707. -            is_generic = true;
  708. -        }
  709. -    }
  710. -
  711. -    if (!(*win_mask & GENERIC_ALL)) {
  712. -        if (ACEMASK_TEST_MASK(nfs4_mask, ace4_generic_read_filt)) {
  713. -            *win_mask |= GENERIC_READ;
  714. -            is_generic = true;
  715. -        }
  716. -        if (ACEMASK_TEST_MASK(nfs4_mask, ace4_generic_write_filt)) {
  717. -            *win_mask |= GENERIC_WRITE;
  718. -            is_generic = true;
  719. -        }
  720. -        if (ACEMASK_TEST_MASK(nfs4_mask, ace4_generic_execute_filt)) {
  721. -            *win_mask |= GENERIC_EXECUTE;
  722. -            is_generic = true;
  723. -        }
  724. -    }
  725. -#endif /* MAP_WIN32GENERIC2ACE4GENERIC */
  726. -
  727. -    /* Individual flags */
  728. -    if (file_type == NF4DIR) {
  729. -        if (nfs4_mask & ACE4_LIST_DIRECTORY) {
  730. -            *win_mask |= FILE_LIST_DIRECTORY;
  731. -        }
  732. -        if (nfs4_mask & ACE4_ADD_FILE) {
  733. -            *win_mask |= FILE_ADD_FILE;
  734. -        }
  735. -        if (nfs4_mask & ACE4_ADD_SUBDIRECTORY) {
  736. -            *win_mask |= FILE_ADD_SUBDIRECTORY;
  737. -        }
  738. -        if (nfs4_mask & ACE4_DELETE_CHILD) {
  739. -            *win_mask |= FILE_DELETE_CHILD;
  740. -        }
  741. -        if (nfs4_mask & ACE4_EXECUTE) {
  742. -            *win_mask |= FILE_TRAVERSE;
  743. -        }
  744. -    }
  745. -    else {
  746. -        if (nfs4_mask & ACE4_READ_DATA) {
  747. -            *win_mask |= FILE_READ_DATA;
  748. -        }
  749. -        if (nfs4_mask & ACE4_WRITE_DATA) {
  750. -            *win_mask |= FILE_WRITE_DATA;
  751. -        }
  752. -        if (nfs4_mask & ACE4_APPEND_DATA) {
  753. -            *win_mask |= FILE_APPEND_DATA;
  754. -        }
  755. -        if (nfs4_mask & ACE4_EXECUTE) {
  756. -            *win_mask |= FILE_EXECUTE;
  757. -        }
  758. -    }
  759. -
  760. -    if (nfs4_mask & ACE4_READ_NAMED_ATTRS) {
  761. -        *win_mask |= FILE_READ_EA;
  762. -    }
  763. -    if (nfs4_mask & ACE4_WRITE_NAMED_ATTRS) {
  764. -        *win_mask |= FILE_WRITE_EA;
  765. -    }
  766. -    if (nfs4_mask & ACE4_READ_ATTRIBUTES) {
  767. -        *win_mask |= FILE_READ_ATTRIBUTES;
  768. -    }
  769. -    if (nfs4_mask & ACE4_WRITE_ATTRIBUTES) {
  770. -        *win_mask |= FILE_WRITE_ATTRIBUTES;
  771. -    }
  772. -    if (nfs4_mask & ACE4_READ_ACL) {
  773. -        *win_mask |= READ_CONTROL;
  774. -    }
  775. -    if (nfs4_mask & ACE4_WRITE_ACL) {
  776. -        *win_mask |= WRITE_DAC;
  777. -    }
  778. -    if (nfs4_mask & ACE4_WRITE_OWNER) {
  779. -        *win_mask |= WRITE_OWNER;
  780. -    }
  781. -    if (nfs4_mask & ACE4_SYNCHRONIZE) {
  782. -        *win_mask |= SYNCHRONIZE;
  783. -    }
  784. -    if (nfs4_mask & ACE4_DELETE) {
  785. -        *win_mask |= DELETE;
  786. -    }
  787. -
  788. -#if 1
  789. -    /* DEBUG: Compare old and new code */
  790. -#ifdef MAP_WIN32GENERIC2ACE4GENERIC
  791. -    if (!is_generic)
  792. -#endif /* MAP_WIN32GENERIC2ACE4GENERIC */
  793. -    {
  794. -        DASSERT_MSG(0,
  795. -            ((long)*win_mask == (long)(nfs4_mask /*& 0x00ffffff*/)),
  796. -            ("#### map_nfs4acemask2winaccessmask: "
  797. -            "new code win_mask=0x%lx, "
  798. -            "old code win_mask=0x%lx\n",
  799. -            (long)*win_mask, (long)(nfs4_mask /*& 0x00ffffff*/)));
  800. -    }
  801. -#endif
  802. -}
  803. -
  804. -static
  805. -int map_sid2nfs4ace_who(PSID sid, PSID owner_sid, PSID group_sid,
  806. -    char *who_out, char *domain, SID_NAME_USE *sid_type_out)
  807. -{
  808. -    int status, lasterr;
  809. -    SID_NAME_USE sid_type = 0;
  810. -    /* |(UTF8_UNLEN+sizeof('\0'))*2| so we have space for user+domain */
  811. -    char who_buf[(UTF8_UNLEN+1)*2];
  812. -    char domain_buf[UTF8_UNLEN+1];
  813. -    DWORD who_size = sizeof(who_buf), domain_size = sizeof(domain_buf);
  814. -    LPSTR sidstr = NULL;
  815. -
  816. -    DPRINTF(ACLLVL2, ("--> map_sid2nfs4ace_who("
  817. -        "sid=0x%p,owner_sid=0x%p, group_sid=0x%p)\n",
  818. -        sid, owner_sid, group_sid));
  819. -
  820. -    if (DPRINTF_LEVEL_ENABLED(ACLLVL2)) {
  821. -        print_sid("sid", sid);
  822. -        print_sid("owner_sid", owner_sid);
  823. -        print_sid("group_sid", group_sid);
  824. -    }
  825. -
  826. -    /* for ace mapping, we want to map owner's sid into "owner@"
  827. -     * but for set_owner attribute we want to map owner into a user name
  828. -     * same applies to group
  829. -     */
  830. -    status = 0;
  831. -    if (owner_sid) {
  832. -        if (EqualSid(sid, owner_sid)) {
  833. -            DPRINTF(ACLLVL2, ("this is owner's sid\n"));
  834. -            (void)memcpy(who_out, ACE4_OWNER, ACE4_OWNER_LEN+1);
  835. -            sid_type = SidTypeUser;
  836. -            status = ERROR_SUCCESS;
  837. -            goto out;
  838. -        }
  839. -    }
  840. -    if (group_sid) {
  841. -        if (EqualSid(sid, group_sid)) {
  842. -            DPRINTF(ACLLVL2, ("this is group's sid\n"));
  843. -            memcpy(who_out, ACE4_GROUP, ACE4_GROUP_LEN+1);
  844. -            sid_type = SidTypeGroup;
  845. -            status = ERROR_SUCCESS;
  846. -            goto out;
  847. -        }
  848. -    }
  849. -    status = is_well_known_sid(sid, who_out, &sid_type);
  850. -    if (status) {
  851. -        if (!strncmp(who_out, ACE4_NOBODY, ACE4_NOBODY_LEN)) {
  852. -            who_size = (DWORD)ACE4_NOBODY_LEN;
  853. -            goto add_domain;
  854. -        }
  855. -
  856. -        /* fixme: What about |sid_type| ? */
  857. -        status = ERROR_SUCCESS;
  858. -        goto out;
  859. -    }
  860. -
  861. -    if (!ConvertSidToStringSidA(sid, &sidstr)) {
  862. -        status = GetLastError();
  863. -        eprintf("map_sid2nfs4ace_who: ConvertSidToStringSidA() "
  864. -            "failed, error=%d\n", status);
  865. -        goto out;
  866. -    }
  867. -
  868. -    status = lookupaccountsidutf8(NULL, sid, who_buf, &who_size, domain_buf,
  869. -        &domain_size, &sid_type);
  870. -    lasterr = GetLastError();
  871. -
  872. -    if (status) {
  873. -        DPRINTF(ACLLVL2, ("map_sid2nfs4ace_who: "
  874. -            "LookupAccountSid(sidtostr(sid)='%s', who_buf='%s', "
  875. -            "who_size=%d, domain='%s', domain_size=%d) "
  876. -            "returned success, status=%d, GetLastError=%d\n",
  877. -            sidstr, who_buf, who_size,
  878. -            domain_buf, domain_size, status, lasterr));
  879. -    }
  880. -    else {
  881. -        DPRINTF(ACLLVL2, ("map_sid2nfs4ace_who: "
  882. -            "LookupAccountSid(sidtostr(sid)='%s', who_size=%d, "
  883. -            "domain_size=%d) returned failure, status=%d, "
  884. -            "GetLastError=%d\n",
  885. -            sidstr, who_size, domain_size, status, lasterr));
  886. -
  887. -        /*
  888. -         * No SID to local account mapping. Can happen for some system
  889. -         * SIDs, and Unix_User+<uid> or Unix_Group+<gid> SIDs
  890. -         */
  891. -        switch (lasterr) {
  892. -            /*
  893. -             * This happens for Unix_User+<uid> or Unix_Group+<gid>
  894. -             * SIDs
  895. -             */
  896. -            case ERROR_NONE_MAPPED:
  897. -                /*
  898. -                 * This can happen for two reasons:
  899. -                 * 1. Someone copied a file from a NFS(v3) filesystem,
  900. -                 * and Cygwin generated an Unix_User+<uid> or
  901. -                 * Unix_Group+<gid> SID for the source file, which
  902. -                 * tools like Cygwin cp(1) just copy.
  903. -                 * 2. We have an uid/gid for which we do not have
  904. -                 * a user-/group-name mapped.
  905. -                 */
  906. -#ifdef NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID
  907. -                /* fixme: This should be a function argument */
  908. -                extern nfs41_daemon_globals nfs41_dg;
  909. -
  910. -                uid_t unixuser_uid = ~0U;
  911. -                gid_t unixgroup_gid = ~0U;
  912. -
  913. -                if (unixuser_sid2uid(sid, &unixuser_uid)) {
  914. -                    if (!nfs41_idmap_uid_to_name(nfs41_dg.idmapper,
  915. -                        unixuser_uid, who_out, UTF8_UNLEN)) {
  916. -                        who_size = (DWORD)strlen(who_out);
  917. -                        sid_type = SidTypeUser;
  918. -                        status = ERROR_SUCCESS;
  919. -
  920. -                        DPRINTF(ACLLVL1, ("map_sid2nfs4ace_who: "
  921. -                            "Unix_User+%d SID "
  922. -                            "mapped to user '%s'\n",
  923. -                            unixuser_uid, who_out));
  924. -                        goto add_domain;
  925. -                    }
  926. -
  927. -                    eprintf("map_sid2nfs4ace_who: "
  928. -                        "unixuser_sid2uid(sid='%s',unixuser_uid=%d) "
  929. -                        "returned no mapping.\n",
  930. -                        sidstr, (int)unixuser_uid);
  931. -                    goto err_none_mapped;
  932. -                }
  933. -
  934. -                if (unixgroup_sid2gid(sid, &unixgroup_gid)) {
  935. -                    if (!nfs41_idmap_gid_to_group(nfs41_dg.idmapper,
  936. -                        unixgroup_gid, who_out, UTF8_GNLEN)) {
  937. -                        who_size = (DWORD)strlen(who_out);
  938. -                        sid_type = SidTypeGroup;
  939. -                        status = ERROR_SUCCESS;
  940. -
  941. -                        DPRINTF(ACLLVL1, ("map_sid2nfs4ace_who: "
  942. -                            "Unix_Group+%d SID "
  943. -                            "mapped to group '%s'\n",
  944. -                            unixgroup_gid, who_out));
  945. -                        goto add_domain;
  946. -                    }
  947. -
  948. -                    eprintf("map_sid2nfs4ace_who: "
  949. -                        "unixgroup_sid2gid(sid='%s',unixgroup_gid=%d) "
  950. -                        "returned no mapping.\n",
  951. -                        sidstr, (int)unixgroup_gid);
  952. -                    goto err_none_mapped;
  953. -                }
  954. -
  955. -                eprintf("map_sid2nfs4ace_who: lookupaccountsidutf8() "
  956. -                    "returned ERROR_NONE_MAPPED+no "
  957. -                    "Unix_@(User|Group)+ mapping for sidstr='%s'\n",
  958. -                    sidstr);
  959. -err_none_mapped:
  960. -                status = ERROR_NONE_MAPPED;
  961. -#else
  962. -                DPRINTF(ACLLVL2,
  963. -                    ("map_sid2nfs4ace_who: lookupaccountsidutf8() "
  964. -                    "returned ERROR_NONE_MAPPED for sidstr='%s'\n",
  965. -                    sidstr));
  966. -                status = lasterr;
  967. -                goto out;
  968. -#endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
  969. -
  970. -            /* Catch other cases */
  971. -            case ERROR_NO_SUCH_USER:
  972. -            case ERROR_NO_SUCH_GROUP:
  973. -                eprintf("map_sid2nfs4ace_who: lookupaccountsidutf8() "
  974. -                    "returned ERROR_NO_SUCH_@(USER|GROUP) for "
  975. -                    "sidstr='%s'\n",
  976. -                    sidstr);
  977. -                status = lasterr;
  978. -                goto out;
  979. -            default:
  980. -                eprintf("map_sid2nfs4ace_who: Internal error, "
  981. -                    "lookupaccountsidutf8() returned unexpected ERROR_%d "
  982. -                    "for sidstr='%s'\n",
  983. -                    status, sidstr);
  984. -                status = ERROR_INTERNAL_ERROR;
  985. -                goto out;
  986. -        }
  987. -    }
  988. -
  989. -    (void)memcpy(who_out, who_buf, who_size);
  990. -add_domain:
  991. -    /*
  992. -     * Complain if we attempt to add a domain suffix to an UID/GID
  993. -     * value
  994. -     */
  995. -    EASSERT(!isdigit(who_out[0]));
  996. -
  997. -    char *wp;
  998. -
  999. -    wp = mempcpy(who_out+who_size, "@", sizeof(char));
  1000. -
  1001. -#ifdef NFS41_DRIVER_WS2022_HACKS
  1002. -    /* Fixup |domain| for Windows Sever 2022 NFSv4.1 server */
  1003. -    if ((!strncmp(who_out, "Users@", (size_t)who_size+1)) ||
  1004. -        (!strncmp(who_out, "Administrators@", (size_t)who_size+1))) {
  1005. -        domain = "BUILTIN";
  1006. -        DPRINTF(1,
  1007. -            ("map_sid2nfs4ace_who: Fixup '%.*s' domain='%s'\n",
  1008. -            (int)who_size+1, who_out, domain));
  1009. -    }
  1010. -    else if (!strncmp(who_out, "SYSTEM@", (size_t)who_size+1)) {
  1011. -        domain = "NT AUTHORITY";
  1012. -        DPRINTF(1,
  1013. -            ("map_sid2nfs4ace_who: Fixup '%.*s' domain='%s'\n",
  1014. -            (int)who_size+1, who_out, domain));
  1015. -    }
  1016. -#endif /* NFS41_DRIVER_WS2022_HACKS */
  1017. -    (void)memcpy(wp, domain, strlen(domain)+1);
  1018. -
  1019. -/* no_add_domain: */
  1020. -    status = ERROR_SUCCESS;
  1021. -out:
  1022. -    if (status) {
  1023. -        DPRINTF(ACLLVL2,
  1024. -            ("<-- map_sid2nfs4ace_who() returns %d\n", status));
  1025. -    }
  1026. -    else {
  1027. -        DPRINTF(ACLLVL2,
  1028. -            ("<-- map_sid2nfs4ace_who(who_out='%s', sid_type='%s'/%d) "
  1029. -            "returns %d\n",
  1030. -            who_out,
  1031. -            map_SID_NAME_USE2str(sid_type), sid_type,
  1032. -            status));
  1033. -        if (sid_type_out) {
  1034. -            *sid_type_out = sid_type;
  1035. -        }
  1036. -    }
  1037. -    if (sidstr)
  1038. -        LocalFree(sidstr);
  1039. -    return status;
  1040. -}
  1041. -
  1042. -/* FIXME: Move this into aclutils.c */
  1043. -int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
  1044. -    int file_type, bool named_attr_support, char *domain)
  1045. -{
  1046. -    int status;
  1047. -    if (acl == NULL) {
  1048. -        DPRINTF(ACLLVL2, ("this is a NULL dacl: all access to an object\n"));
  1049. -        nfs4_acl->count = 1;
  1050. -        nfs4_acl->aces = calloc(1, sizeof(nfsace4));
  1051. -        if (nfs4_acl->aces == NULL) {
  1052. -            status = GetLastError();
  1053. -            goto out;
  1054. -        }
  1055. -        nfs4_acl->flag = 0;
  1056. -        (void)memcpy(nfs4_acl->aces->who, ACE4_EVERYONE, ACE4_EVERYONE_LEN+1);
  1057. -        nfs4_acl->aces->acetype = ACE4_ACCESS_ALLOWED_ACE_TYPE;
  1058. -
  1059. -        if (file_type == NF4DIR) {
  1060. -            uint32_t ace4_all_dir_filt = ACE4_ALL_DIR;
  1061. -#ifdef MAP_WIN32GENERIC2ACE4GENERIC
  1062. -            /* Filter out unsupported features */
  1063. -            if (!named_attr_support)
  1064. -                ace4_all_dir_filt &= ~ACE4_RW_NAMED_ATTRS;
  1065. -#endif /* MAP_WIN32GENERIC2ACE4GENERIC */
  1066. -            nfs4_acl->aces->acemask = ace4_all_dir_filt;
  1067. -        }
  1068. -        else {
  1069. -            uint32_t ace4_all_file_filt = ACE4_ALL_FILE;
  1070. -#ifdef MAP_WIN32GENERIC2ACE4GENERIC
  1071. -            /* Filter out unsupported features */
  1072. -            if (!named_attr_support)
  1073. -                ace4_all_file_filt &= ~ACE4_RW_NAMED_ATTRS;
  1074. -#endif /* MAP_WIN32GENERIC2ACE4GENERIC */
  1075. -            nfs4_acl->aces->acemask = ace4_all_file_filt;
  1076. -        }
  1077. -        nfs4_acl->aces->aceflag = 0;
  1078. -    } else {
  1079. -        int win_i, nfs_i;
  1080. -        PACE_HEADER ace;
  1081. -        PBYTE tmp_pointer;
  1082. -        SID_NAME_USE who_sid_type = 0;
  1083. -        ACCESS_MASK win_mask;
  1084. -
  1085. -        DPRINTF(ACLLVL2, ("NON-NULL dacl with %d ACEs\n", acl->AceCount));
  1086. -        if (DPRINTF_LEVEL_ENABLED(ACLLVL3)) {
  1087. -            print_hexbuf_no_asci("ACL\n",
  1088. -                (const unsigned char *)acl, acl->AclSize);
  1089. -        }
  1090. -
  1091. -        nfs4_acl->aces = calloc(acl->AceCount, sizeof(nfsace4));
  1092. -        if (nfs4_acl->aces == NULL) {
  1093. -            status = GetLastError();
  1094. -            goto out;
  1095. -        }
  1096. -        nfs4_acl->flag = 0;
  1097. -        for (win_i = nfs_i = 0; win_i < acl->AceCount; win_i++) {
  1098. -            nfsace4 *curr_nfsace = &nfs4_acl->aces[nfs_i];
  1099. -            PSID ace_sid;
  1100. -
  1101. -            status = GetAce(acl, win_i, (LPVOID *)&ace);
  1102. -            if (!status) {
  1103. -                status = GetLastError();
  1104. -                eprintf("map_dacl_2_nfs4acl: GetAce failed with %d\n", status);
  1105. -                goto out_free;
  1106. -            }
  1107. -            tmp_pointer = (PBYTE)ace;
  1108. -            if (DPRINTF_LEVEL_ENABLED(ACLLVL3)) {
  1109. -                print_hexbuf_no_asci("ACE\n",
  1110. -                    (const unsigned char *)ace, ace->AceSize);
  1111. -            }
  1112. -            DPRINTF(ACLLVL3, ("ACE TYPE: 0x%x\n", ace->AceType));
  1113. -            if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
  1114. -                curr_nfsace->acetype = ACE4_ACCESS_ALLOWED_ACE_TYPE;
  1115. -            else if (ace->AceType == ACCESS_DENIED_ACE_TYPE)
  1116. -                curr_nfsace->acetype = ACE4_ACCESS_DENIED_ACE_TYPE;
  1117. -            else {
  1118. -                eprintf("map_dacl_2_nfs4acl: unsupported ACE type %d\n",
  1119. -                    ace->AceType);
  1120. -                status = ERROR_NOT_SUPPORTED;
  1121. -                goto out_free;
  1122. -            }
  1123. -
  1124. -            tmp_pointer += sizeof(ACCESS_MASK) + sizeof(ACE_HEADER);
  1125. -            ace_sid = tmp_pointer;
  1126. -
  1127. -#ifdef NFS41_DRIVER_ACLS_SETACL_SKIP_WINNULLSID_ACES
  1128. -            if (IsWellKnownSid(ace_sid, WinNullSid)) {
  1129. -                /*
  1130. -                 * Skip ACEs with SID==|WinNullSid|
  1131. -                 *
  1132. -                 * Cygwin generates artificial ACEs with SID user
  1133. -                 * |WinNullSid| to encode permission information
  1134. -                 * (see |CYG_ACE_ISBITS_TO_POSIX()| in
  1135. -                 * Cygwin newlib-cygwin/winsup/cygwin/sec/acl.cc
  1136. -                 *
  1137. -                 * This assumes that the filesystem which stores
  1138. -                 * the ACL data leaves them 1:1 intact - which is
  1139. -                 * not the case for the Linux NFSv4.1 server
  1140. -                 * (tested with Linux 6.6.32), which transforms the
  1141. -                 * NFSv4.1 ACLs into POSIX ACLs at setacl time,
  1142. -                 * and the POSIX ACLs back to NFSv4 ACLs at getacl
  1143. -                 * time.
  1144. -                 * And this lossy transformation screws-up Cygwin
  1145. -                 * completly.
  1146. -                 * The best we can do for now is to skip such
  1147. -                 * ACEs, as we have no way to detect whether
  1148. -                 * the NFS server supports full NFSv4 ACLs, or
  1149. -                 * only POSIX ACLs disguised as NFSv4 ACLs.
  1150. -                 */
  1151. -                DPRINTF(ACLLVL3, ("Skipping WinNullSid ACE, "
  1152. -                    "win_i=%d nfs_i=%d\n", (int)win_i, (int)nfs_i));
  1153. -                continue;
  1154. -            }
  1155. -#endif /* NFS41_DRIVER_ACLS_SETACL_SKIP_WINNULLSID_ACES */
  1156. -
  1157. -            status = map_sid2nfs4ace_who(ace_sid, sid, gsid,
  1158. -                curr_nfsace->who, domain, &who_sid_type);
  1159. -            if (status)
  1160. -                goto out_free;
  1161. -
  1162. -            win_mask = *(PACCESS_MASK)(ace + 1);
  1163. -
  1164. -            map_winace2nfs4aceflags(ace->AceFlags,
  1165. -                &curr_nfsace->aceflag);
  1166. -            map_winaccessmask2nfs4acemask(win_mask,
  1167. -                file_type, named_attr_support,
  1168. -                &curr_nfsace->acemask);
  1169. -
  1170. -            /*
  1171. -             * Clear |ACE4_INHERITED_ACE|
  1172. -             *
  1173. -             * (See RFC 8884 Section-6.2.1.4.1:
  1174. -             * ACE4_INHERITED_ACE
  1175. -             * Indicates that this ACE is inherited from a parent
  1176. -             * directory. A server that supports automatic inheritance
  1177. -             * will place this flag on any ACEs inherited from the
  1178. -             * parent directory when creating a new object.
  1179. -             * Client applications will use this to perform automatic
  1180. -             * inheritance. Clients and servers MUST clear this bit in
  1181. -             * the acl attribute; it may only be used in the dacl and
  1182. -             * sacl attributes.
  1183. -             * ---- snip ----
  1184. -             * )
  1185. -             *
  1186. -             * If we do not clear this bit Linux 6.6.32-RT32 nfsd
  1187. -             * will reject setting ACLs |NFS4ERR_ATTRNOTSUPP| via
  1188. -             * icacls(1win) if the parent directory has inheritance
  1189. -             * ACLs.
  1190. -             */
  1191. -            if (curr_nfsace->aceflag & ACE4_INHERITED_ACE) {
  1192. -                curr_nfsace->aceflag &= ~ACE4_INHERITED_ACE;
  1193. -                DPRINTF(ACLLVL3, ("clearning ACE4_INHERITED_ACE\n"));
  1194. -            }
  1195. -
  1196. -            /*
  1197. -             * Treat |SidTypeAlias| as (local) group
  1198. -             *
  1199. -             * It seems that |LookupAccount*A()| will always return
  1200. -             * |SidTypeAlias| for local groups created with
  1201. -             * $ net localgroup cygwingrp1 /add #
  1202. -             *
  1203. -             * References:
  1204. -             * - https://stackoverflow.com/questions/39373188/lookupaccountnamew-returns-sidtypealias-but-expected-sidtypegroup
  1205. -             */
  1206. -            if ((who_sid_type == SidTypeGroup) ||
  1207. -                (who_sid_type == SidTypeAlias)) {
  1208. -                DPRINTF(ACLLVL3, ("map_dacl_2_nfs4acl: who_sid_type='%s': "
  1209. -                    "aces[%d].who='%s': "
  1210. -                    "setting group flag\n",
  1211. -                    map_SID_NAME_USE2str(who_sid_type),
  1212. -                    nfs_i, curr_nfsace->who));
  1213. -                curr_nfsace->aceflag |= ACE4_IDENTIFIER_GROUP;
  1214. -            }
  1215. -
  1216. -            if (DPRINTF_LEVEL_ENABLED(ACLLVL1)) {
  1217. -                dprintf_out("win2nfs: nfs4_acl->aces[%d]=(who='%s', "
  1218. -                    "acetype='%s', "
  1219. -                    "aceflag='%s'/0x%lx, "
  1220. -                    "acemask='%s'/0x%lx(=win_mask=0x%lx)), "
  1221. -                    "who_sid_type='%s', "
  1222. -                    "win_i=%d\n",
  1223. -                    nfs_i,
  1224. -                    curr_nfsace->who,
  1225. -                    map_nfs_acetype2str(curr_nfsace->acetype),
  1226. -                    nfs_aceflag2shortname(curr_nfsace->aceflag),
  1227. -                    curr_nfsace->aceflag,
  1228. -                    nfs_mask2shortname(curr_nfsace->acemask),
  1229. -                    (long)curr_nfsace->acemask,
  1230. -                    (long)win_mask,
  1231. -                    map_SID_NAME_USE2str(who_sid_type),
  1232. -                    (int)win_i);
  1233. -                if (DPRINTF_LEVEL_ENABLED(ACLLVL2)) {
  1234. -                    print_windows_access_mask(curr_nfsace->who,
  1235. -                        win_mask);
  1236. -                    print_nfs_access_mask(curr_nfsace->who,
  1237. -                        curr_nfsace->acemask);
  1238. -                }
  1239. -            }
  1240. -
  1241. -            nfs_i++;
  1242. -        }
  1243. -
  1244. -        nfs4_acl->count = nfs_i;
  1245. -    }
  1246. -    status = ERROR_SUCCESS;
  1247. -out:
  1248. -    return status;
  1249. -out_free:
  1250. -    free(nfs4_acl->aces);
  1251. -    goto out;
  1252. -}
  1253. -
  1254.  static int handle_setacl(void *daemon_context, nfs41_upcall *upcall)
  1255.  {
  1256.      int status = ERROR_NOT_SUPPORTED;
  1257. diff --git a/daemon/aclutil.c b/daemon/aclutil.c
  1258. new file mode 100644
  1259. index 0000000..57c1111
  1260. --- /dev/null
  1261. +++ b/daemon/aclutil.c
  1262. @@ -0,0 +1,1187 @@
  1263. +/* NFSv4.1 client for Windows
  1264. + * Copyright (C) 2012 The Regents of the University of Michigan
  1265. + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
  1266. + *
  1267. + * Olga Kornievskaia <aglo@umich.edu>
  1268. + * Casey Bodley <cbodley@umich.edu>
  1269. + * Roland Mainz <roland.mainz@nrubsig.org>
  1270. + *
  1271. + * This library is free software; you can redistribute it and/or modify it
  1272. + * under the terms of the GNU Lesser General Public License as published by
  1273. + * the Free Software Foundation; either version 2.1 of the License, or (at
  1274. + * your option) any later version.
  1275. + *
  1276. + * This library is distributed in the hope that it will be useful, but
  1277. + * without any warranty; without even the implied warranty of merchantability
  1278. + * or fitness for a particular purpose.  See the GNU Lesser General Public
  1279. + * License for more details.
  1280. + *
  1281. + * You should have received a copy of the GNU Lesser General Public License
  1282. + * along with this library; if not, write to the Free Software Foundation,
  1283. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  1284. + */
  1285. +
  1286. +#include <Windows.h>
  1287. +#include <stdio.h>
  1288. +#include <strsafe.h>
  1289. +#include <sddl.h>
  1290. +
  1291. +#include "nfs41_build_features.h"
  1292. +#include "aclutil.h"
  1293. +#include "nfs41_daemon.h"
  1294. +#include "daemon_debug.h"
  1295. +#include "util.h"
  1296. +#include "sid.h"
  1297. +
  1298. +#define MAP_WIN32GENERIC2ACE4GENERIC 1
  1299. +#define WORKAROUND_FOR_LINUX_NFSD_NOT_SETTING_ACE4_WRITE_ATTRIBUTES 1
  1300. +
  1301. +#define ACE4_RW_NAMED_ATTRS \
  1302. +    (ACE4_READ_NAMED_ATTRS|ACE4_WRITE_NAMED_ATTRS)
  1303. +
  1304. +/* Local prototypes */
  1305. +static void map_winace2nfs4aceflags(BYTE win_aceflags, uint32_t *nfs4_aceflags);
  1306. +static void map_nfs4aceflags2winaceflags(uint32_t nfs4_aceflags, DWORD *win_aceflags);
  1307. +static void map_winaccessmask2nfs4acemask(ACCESS_MASK win_mask,
  1308. +    int file_type, bool named_attr_support, uint32_t *nfs4_mask);
  1309. +static void map_nfs4acemask2winaccessmask(uint32_t nfs4_mask,
  1310. +    int file_type, bool named_attr_support, ACCESS_MASK *win_mask);
  1311. +
  1312. + void convert_nfs4name_2_user_domain(LPSTR nfs4name,
  1313. +    LPSTR *domain)
  1314. +{
  1315. +    LPSTR p = nfs4name;
  1316. +    for(; p[0] != '\0'; p++) {
  1317. +        if (p[0] == '@') {
  1318. +            p[0] = '\0';
  1319. +
  1320. +            *domain = &p[1];
  1321. +            break;
  1322. +        }
  1323. +    }
  1324. +}
  1325. +
  1326. +void free_sids(PSID *sids, int count)
  1327. +{
  1328. +    int i;
  1329. +    for(i = 0; i < count; i++)
  1330. +        free(sids[i]);
  1331. +    free(sids);
  1332. +}
  1333. +
  1334. +static int check_4_special_identifiers(const char *restrict who,
  1335. +    PSID *sid,
  1336. +    DWORD *sid_len,
  1337. +    BOOLEAN *flag)
  1338. +{
  1339. +    int status = ERROR_SUCCESS;
  1340. +    WELL_KNOWN_SID_TYPE type = 0;
  1341. +    *flag = TRUE;
  1342. +
  1343. +    /*
  1344. +     * Compare |who| against known constant strings, excluding the '@'
  1345. +     * symbol. Note that |ACE4_NOBODY| and |ACE4_WIN_NULL_SID| do not
  1346. +     * have a '@
  1347. +     */
  1348. +    if (!strncmp(who, ACE4_OWNER, ACE4_OWNER_LEN-1))
  1349. +        type = WinCreatorOwnerSid;
  1350. +#ifdef NFS41_DRIVER_WS2022_HACKS
  1351. +    else if (!strncmp(who, ACE4_WIN_CREATOR_OWNER, ACE4_WIN_CREATOR_OWNER_LEN-1))
  1352. +        type = WinCreatorOwnerSid;
  1353. +#endif /* NFS41_DRIVER_WS2022_HACKS */
  1354. +    else if (!strncmp(who, ACE4_GROUP, ACE4_GROUP_LEN-1))
  1355. +        type = WinCreatorGroupSid;
  1356. +#ifdef NFS41_DRIVER_WS2022_HACKS
  1357. +    else if (!strncmp(who, ACE4_WIN_CREATOR_GROUP, ACE4_WIN_CREATOR_GROUP_LEN-1))
  1358. +        type = WinCreatorGroupSid;
  1359. +#endif /* NFS41_DRIVER_WS2022_HACKS */
  1360. +    else if (!strncmp(who, ACE4_EVERYONE, ACE4_EVERYONE_LEN-1))
  1361. +        type = WinWorldSid;
  1362. +#ifdef NFS41_DRIVER_WS2022_HACKS
  1363. +    else if (!strncmp(who, ACE4_WIN_EVERYONE, ACE4_WIN_EVERYONE_LEN-1))
  1364. +        type = WinWorldSid;
  1365. +#endif /* NFS41_DRIVER_WS2022_HACKS */
  1366. +    else if (!strncmp(who, ACE4_NOBODY, ACE4_NOBODY_LEN))
  1367. +        type = WinNullSid;
  1368. +#ifdef NFS41_DRIVER_WS2022_HACKS
  1369. +    else if (!strncmp(who, ACE4_WIN_NULL_SID, ACE4_WIN_NULL_SID_LEN))
  1370. +        type = WinNullSid;
  1371. +#endif /* NFS41_DRIVER_WS2022_HACKS */
  1372. +    else
  1373. +        *flag = FALSE;
  1374. +    if (*flag)
  1375. +        status = create_unknownsid(type, sid, sid_len);
  1376. +    return status;
  1377. +}
  1378. +
  1379. +int convert_nfs4acl_2_dacl(nfs41_daemon_globals *nfs41dg,
  1380. +    nfsacl41 *acl, int file_type, PACL *dacl_out, PSID **sids_out,
  1381. +    bool named_attr_support)
  1382. +{
  1383. +    int status = ERROR_NOT_SUPPORTED, size = 0;
  1384. +    uint32_t nfs_i = 0, win_i = 0;
  1385. +    DWORD sid_len;
  1386. +    PSID *sids;
  1387. +    PACL dacl;
  1388. +    LPSTR domain = NULL;
  1389. +    BOOLEAN flag;
  1390. +
  1391. +    DPRINTF(ACLLVL2, ("--> convert_nfs4acl_2_dacl(acl=0x%p,"
  1392. +        "file_type='%s'(=%d), named_attr_support=%d)\n",
  1393. +        acl, map_nfs_ftype2str(file_type), file_type,
  1394. +        (int)named_attr_support));
  1395. +
  1396. +    bool *skip_aces = _alloca(acl->count * sizeof(bool));
  1397. +
  1398. +    /*
  1399. +     * We use |calloc()| here to get |NULL| pointer for unallocated
  1400. +     * slots in case of error codepaths below...
  1401. +     */
  1402. +    sids = calloc(acl->count, sizeof(PSID));
  1403. +    if (sids == NULL) {
  1404. +        status = GetLastError();
  1405. +        goto out;
  1406. +    }
  1407. +    for (nfs_i = win_i = 0; nfs_i < acl->count; nfs_i++) {
  1408. +        nfsace4 *curr_nfsace = &acl->aces[nfs_i];
  1409. +
  1410. +        skip_aces[nfs_i] = false;
  1411. +
  1412. +        convert_nfs4name_2_user_domain(curr_nfsace->who, &domain);
  1413. +        DPRINTF(ACLLVL2, ("convert_nfs4acl_2_dacl: for user='%s' domain='%s'\n",
  1414. +                curr_nfsace->who, domain?domain:"<null>"));
  1415. +
  1416. +        EASSERT_MSG(!isdigit(curr_nfsace->who[0]),
  1417. +            ("convert_nfs4acl_2_dacl: aces[%d]->who='%s' uses numeric id\n",
  1418. +            (int)nfs_i, curr_nfsace->who));
  1419. +
  1420. +#ifdef NFS41_DRIVER_ACLS_SETACL_SKIP_WINNULLSID_ACES
  1421. +        /*
  1422. +         * Skip "nobody" ACEs - Cygwin uses |WinNullSid| ACEs (mapped
  1423. +         * to NFS user "nobody") to store special data.
  1424. +         * We skip these here, because we cannot use them, as Linux nfsd
  1425. +         * only supports POSIX ACLs translated to NFSv4 ACLs, which
  1426. +         * corrupts the Cygwin data.
  1427. +         */
  1428. +        if (!strcmp(curr_nfsace->who, ACE4_NOBODY)) {
  1429. +            DPRINTF(ACLLVL3, ("Skipping 'nobody' ACE, "
  1430. +                "win_i=%d nfs_i=%d\n", (int)win_i, (int)nfs_i));
  1431. +            skip_aces[nfs_i] = true;
  1432. +            continue;
  1433. +        }
  1434. +#endif /* NFS41_DRIVER_ACLS_SETACL_SKIP_WINNULLSID_ACES */
  1435. +
  1436. +        status = check_4_special_identifiers(curr_nfsace->who, &sids[win_i],
  1437. +                                             &sid_len, &flag);
  1438. +        if (status) {
  1439. +            free_sids(sids, win_i);
  1440. +            goto out;
  1441. +        }
  1442. +        if (!flag) {
  1443. +            bool isgroupacl = (curr_nfsace->aceflag & ACE4_IDENTIFIER_GROUP)?true:false;
  1444. +
  1445. +
  1446. +#ifdef NFS41_DRIVER_WS2022_HACKS
  1447. +            if ((isgroupacl == false) && domain &&
  1448. +                (!strcmp(domain, "BUILTIN"))) {
  1449. +                if ((!strcmp(curr_nfsace->who, "Users")) ||
  1450. +                    (!strcmp(curr_nfsace->who, "Administrators"))) {
  1451. +                    DPRINTF(1, ("convert_nfs4acl_2_dacl: "
  1452. +                        "force isgroupacl=true for for user='%s'\n",
  1453. +                        curr_nfsace->who));
  1454. +                    isgroupacl = true;
  1455. +                }
  1456. +            }
  1457. +#endif /* NFS41_DRIVER_WS2022_HACKS */
  1458. +            if (isgroupacl) {
  1459. +                DPRINTF(ACLLVL2,
  1460. +                    ("convert_nfs4acl_2_dacl: aces[%d].who='%s': "
  1461. +                    "Setting group flag\n",
  1462. +                    nfs_i, curr_nfsace->who));
  1463. +            }
  1464. +
  1465. +            status = map_nfs4servername_2_sid(nfs41dg,
  1466. +                (isgroupacl?GROUP_SECURITY_INFORMATION:OWNER_SECURITY_INFORMATION),
  1467. +                &sid_len, &sids[win_i], curr_nfsace->who);
  1468. +            if (status) {
  1469. +                free_sids(sids, win_i);
  1470. +                goto out;
  1471. +            }
  1472. +        }
  1473. +        size += sid_len - sizeof(DWORD);
  1474. +
  1475. +        win_i++;
  1476. +    }
  1477. +    size += sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE)*win_i);
  1478. +    size = align8(size); /* align size on |DWORD| boundry */
  1479. +    dacl = malloc(size);
  1480. +    if (dacl == NULL)
  1481. +        goto out_free_sids;
  1482. +
  1483. +    if (InitializeAcl(dacl, size, ACL_REVISION)) {
  1484. +        ACCESS_MASK mask;
  1485. +        DWORD win_aceflags;
  1486. +
  1487. +        for (nfs_i = win_i = 0; nfs_i < acl->count; nfs_i++) {
  1488. +            nfsace4 *curr_nfsace = &acl->aces[nfs_i];
  1489. +
  1490. +            if (skip_aces[nfs_i])
  1491. +                continue;
  1492. +
  1493. +            map_nfs4aceflags2winaceflags(curr_nfsace->aceflag,
  1494. +                &win_aceflags);
  1495. +            map_nfs4acemask2winaccessmask(curr_nfsace->acemask,
  1496. +                file_type, named_attr_support, &mask);
  1497. +
  1498. +            if (DPRINTF_LEVEL_ENABLED(ACLLVL1)) {
  1499. +                dprintf_out("nfs2win: acl->aces[%d].who='%s': "
  1500. +                    "acetype='%s', "
  1501. +                    "nfs_acemask=0x%lx, win_mask=0x%lx, "
  1502. +                    "win_aceflags=0x%lx\n",
  1503. +                    nfs_i, curr_nfsace->who,
  1504. +                    map_nfs_acetype2str(curr_nfsace->acetype),
  1505. +                    (long)curr_nfsace->acemask,
  1506. +                    (long)mask,
  1507. +                    (long)win_aceflags);
  1508. +
  1509. +                print_nfs_access_mask(curr_nfsace->who,
  1510. +                    curr_nfsace->acemask);
  1511. +                print_windows_access_mask(curr_nfsace->who, mask);
  1512. +            }
  1513. +
  1514. +            if (curr_nfsace->acetype == ACE4_ACCESS_ALLOWED_ACE_TYPE) {
  1515. +                status = AddAccessAllowedAceEx(dacl, ACL_REVISION,
  1516. +                    win_aceflags, mask, sids[win_i]);
  1517. +                if (!status) {
  1518. +                    eprintf("convert_nfs4acl_2_dacl: "
  1519. +                        "AddAccessAllowedAceEx"
  1520. +                        "(dacl=0x%p,win_aceflags=0x%x,mask=0x%x,who='%s') "
  1521. +                        "failed with lasterr=%d\n",
  1522. +                        dacl, (int)win_aceflags, (int)mask,
  1523. +                        curr_nfsace->who, (int)GetLastError());
  1524. +                    status = ERROR_INTERNAL_ERROR;
  1525. +                    goto out_free_dacl;
  1526. +                }
  1527. +                status = ERROR_SUCCESS;
  1528. +            } else if (curr_nfsace->acetype == ACE4_ACCESS_DENIED_ACE_TYPE) {
  1529. +                status = AddAccessDeniedAceEx(dacl, ACL_REVISION,
  1530. +                    win_aceflags, mask, sids[win_i]);
  1531. +                if (!status) {
  1532. +                    eprintf("convert_nfs4acl_2_dacl: "
  1533. +                        "AddAccessDeniedAceEx"
  1534. +                        "(dacl=0x%p,win_aceflags=0x%x,mask=0x%x,who='%s') "
  1535. +                        "failed with lasterr=%d\n",
  1536. +                        dacl, (int)win_aceflags, (int)mask,
  1537. +                        curr_nfsace->who, (int)GetLastError());
  1538. +                    status = ERROR_INTERNAL_ERROR;
  1539. +                    goto out_free_dacl;
  1540. +                }
  1541. +                status = ERROR_SUCCESS;
  1542. +            } else {
  1543. +                eprintf("convert_nfs4acl_2_dacl: unknown acetype %d\n",
  1544. +                        curr_nfsace->acetype);
  1545. +                status = ERROR_INTERNAL_ERROR;
  1546. +                free(dacl);
  1547. +                free_sids(sids, win_i);
  1548. +                goto out;
  1549. +            }
  1550. +
  1551. +            win_i++;
  1552. +        }
  1553. +    } else {
  1554. +        eprintf("convert_nfs4acl_2_dacl: InitializeAcl failed with %d\n", status);
  1555. +        goto out_free_dacl;
  1556. +    }
  1557. +    status = ERROR_SUCCESS;
  1558. +    *sids_out = sids;
  1559. +    *dacl_out = dacl;
  1560. +out:
  1561. +    DPRINTF(ACLLVL2, ("<-- convert_nfs4acl_2_dacl("
  1562. +        "acl=0x%p,file_type='%s'(=%d)) returning %d\n",
  1563. +        acl, map_nfs_ftype2str(file_type), file_type, status));
  1564. +    return status;
  1565. +out_free_dacl:
  1566. +    free(dacl);
  1567. +out_free_sids:
  1568. +    free_sids(sids, win_i);
  1569. +    status = GetLastError();
  1570. +    goto out;
  1571. +}
  1572. +
  1573. +static int is_well_known_sid(PSID sid, char *who, SID_NAME_USE *snu_out)
  1574. +{
  1575. +    const WELL_KNOWN_SID_TYPE test_types[] = {
  1576. +        WinCreatorOwnerSid,
  1577. +        WinCreatorGroupSid,
  1578. +        WinBuiltinUsersSid,
  1579. +        WinNullSid,
  1580. +        WinAnonymousSid,
  1581. +        WinWorldSid,
  1582. +        WinAuthenticatedUserSid,
  1583. +        WinDialupSid,
  1584. +        WinNetworkSid,
  1585. +        WinBatchSid,
  1586. +        WinInteractiveSid,
  1587. +        WinNetworkServiceSid,
  1588. +        WinLocalServiceSid,
  1589. +        WinServiceSid
  1590. +    };
  1591. +    const size_t test_types_count = ARRAYSIZE(test_types);
  1592. +
  1593. +    BOOL ismatch;
  1594. +    size_t i;
  1595. +
  1596. +#ifdef _DEBUG
  1597. +    static bool once = true;
  1598. +
  1599. +    if (once) {
  1600. +        once = false;
  1601. +        EASSERT(test_types_count == 14);
  1602. +        /* Safeguards if someone tampers with the #defines for this */
  1603. +        EASSERT(strlen(ACE4_OWNER) == ACE4_OWNER_LEN);
  1604. +        EASSERT(strlen(ACE4_GROUP) == ACE4_GROUP_LEN);
  1605. +        EASSERT(strlen(ACE4_NOBODY) == ACE4_NOBODY_LEN);
  1606. +        EASSERT(strlen(ACE4_ANONYMOUS) == ACE4_ANONYMOUS_LEN);
  1607. +        EASSERT(strlen(ACE4_EVERYONE) == ACE4_EVERYONE_LEN);
  1608. +    }
  1609. +#endif /* _DEBUG */
  1610. +
  1611. +    for (i = 0; i < test_types_count ; i++) {
  1612. +        WELL_KNOWN_SID_TYPE tt = test_types[i];
  1613. +
  1614. +        ismatch = IsWellKnownSid(sid, tt);
  1615. +        if (!ismatch) {
  1616. +            continue;
  1617. +        }
  1618. +
  1619. +        DPRINTF(ACLLVL3, ("WELL_KNOWN_SID_TYPE=%d\n", (int)tt));
  1620. +        switch(tt) {
  1621. +            case WinCreatorOwnerSid:
  1622. +                (void)memcpy(who, ACE4_OWNER, ACE4_OWNER_LEN+1);
  1623. +                *snu_out = SidTypeUser;
  1624. +                return TRUE;
  1625. +            case WinCreatorGroupSid:
  1626. +            case WinBuiltinUsersSid:
  1627. +                (void)memcpy(who, ACE4_GROUP, ACE4_GROUP_LEN+1);
  1628. +                *snu_out = SidTypeGroup;
  1629. +                return TRUE;
  1630. +            case WinNullSid:
  1631. +                (void)memcpy(who, ACE4_NOBODY, ACE4_NOBODY_LEN+1);
  1632. +                *snu_out = SidTypeUser;
  1633. +                return TRUE;
  1634. +            case WinAnonymousSid:
  1635. +                (void)memcpy(who, ACE4_ANONYMOUS, ACE4_ANONYMOUS_LEN+1);
  1636. +                return TRUE;
  1637. +            case WinWorldSid:
  1638. +                (void)memcpy(who, ACE4_EVERYONE, ACE4_EVERYONE_LEN+1);
  1639. +                *snu_out = SidTypeGroup;
  1640. +                return TRUE;
  1641. +            case WinAuthenticatedUserSid:
  1642. +                (void)memcpy(who, ACE4_AUTHENTICATED, ACE4_AUTHENTICATED_LEN+1);
  1643. +                return TRUE;
  1644. +            case WinDialupSid:
  1645. +                (void)memcpy(who, ACE4_DIALUP, ACE4_DIALUP_LEN+1);
  1646. +                return TRUE;
  1647. +            case WinNetworkSid:
  1648. +                (void)memcpy(who, ACE4_NETWORK, ACE4_NETWORK_LEN+1);
  1649. +                return TRUE;
  1650. +            case WinBatchSid:
  1651. +                (void)memcpy(who, ACE4_BATCH, ACE4_BATCH_LEN+1);
  1652. +                return TRUE;
  1653. +            case WinInteractiveSid:
  1654. +                (void)memcpy(who, ACE4_INTERACTIVE, ACE4_INTERACTIVE_LEN+1);
  1655. +                return TRUE;
  1656. +            case WinNetworkServiceSid:
  1657. +            case WinLocalServiceSid:
  1658. +            case WinServiceSid:
  1659. +                (void)memcpy(who, ACE4_SERVICE, ACE4_SERVICE_LEN+1);
  1660. +                return TRUE;
  1661. +            default:
  1662. +                eprintf("is_well_known_sid: unknown tt=%d\n", (int)tt);
  1663. +                return FALSE;
  1664. +        }
  1665. +    }
  1666. +    return FALSE;
  1667. +}
  1668. +
  1669. +static void map_winace2nfs4aceflags(BYTE win_aceflags, uint32_t *nfs4_aceflags)
  1670. +{
  1671. +    *nfs4_aceflags = 0;
  1672. +
  1673. +    if (win_aceflags & OBJECT_INHERIT_ACE)
  1674. +        *nfs4_aceflags |= ACE4_FILE_INHERIT_ACE;
  1675. +    if (win_aceflags & CONTAINER_INHERIT_ACE)
  1676. +        *nfs4_aceflags |= ACE4_DIRECTORY_INHERIT_ACE;
  1677. +    if (win_aceflags & NO_PROPAGATE_INHERIT_ACE)
  1678. +        *nfs4_aceflags |= ACE4_NO_PROPAGATE_INHERIT_ACE;
  1679. +    if (win_aceflags & INHERIT_ONLY_ACE)
  1680. +        *nfs4_aceflags |= ACE4_INHERIT_ONLY_ACE;
  1681. +    if (win_aceflags & INHERITED_ACE)
  1682. +        *nfs4_aceflags |= ACE4_INHERITED_ACE;
  1683. +    DPRINTF(ACLLVL3,
  1684. +        ("map_winace2nfs4aceflags: win_aceflags=0x%x nfs4_aceflags=0x%x\n",
  1685. +        (int)win_aceflags, (int)*nfs4_aceflags));
  1686. +}
  1687. +
  1688. +static void map_nfs4aceflags2winaceflags(uint32_t nfs4_aceflags, DWORD *win_aceflags)
  1689. +{
  1690. +    *win_aceflags = 0;
  1691. +
  1692. +    if (nfs4_aceflags & ACE4_FILE_INHERIT_ACE)
  1693. +        *win_aceflags |= OBJECT_INHERIT_ACE;
  1694. +    if (nfs4_aceflags & ACE4_DIRECTORY_INHERIT_ACE)
  1695. +        *win_aceflags |= CONTAINER_INHERIT_ACE;
  1696. +    if (nfs4_aceflags & ACE4_NO_PROPAGATE_INHERIT_ACE)
  1697. +        *win_aceflags |= NO_PROPAGATE_INHERIT_ACE;
  1698. +    if (nfs4_aceflags & ACE4_INHERIT_ONLY_ACE)
  1699. +        *win_aceflags |= INHERIT_ONLY_ACE;
  1700. +    if (nfs4_aceflags & ACE4_INHERITED_ACE)
  1701. +        *win_aceflags |= INHERITED_ACE;
  1702. +    DPRINTF(ACLLVL3,
  1703. +        ("map_nfs4aceflags2winace: nfs4_aceflags=0x%x win_aceflags=0x%x\n",
  1704. +        (int)nfs4_aceflags, (int)*win_aceflags));
  1705. +}
  1706. +
  1707. +static
  1708. +void map_winaccessmask2nfs4acemask(ACCESS_MASK win_mask,
  1709. +    int file_type, bool named_attr_support, uint32_t *nfs4_mask)
  1710. +{
  1711. +    *nfs4_mask = 0;
  1712. +
  1713. +    /* check if any GENERIC bits set */
  1714. +    if (win_mask & 0xf000000) {
  1715. +        /* Filtered |ACE4_GENERIC_*| masks */
  1716. +        uint32_t ace4_generic_read_filt = ACE4_GENERIC_READ;
  1717. +        uint32_t ace4_generic_write_filt =  ACE4_GENERIC_WRITE;
  1718. +        uint32_t ace4_generic_execute_filt = ACE4_GENERIC_EXECUTE;
  1719. +        uint32_t ace4_all_file_filt = ACE4_ALL_FILE;
  1720. +        uint32_t ace4_all_dir_filt = ACE4_ALL_DIR;
  1721. +
  1722. +#ifdef MAP_WIN32GENERIC2ACE4GENERIC
  1723. +        if (!named_attr_support) {
  1724. +            /*
  1725. +             * Filter out unsupported features for
  1726. +             * |GENERIC_*| --> |ACE_*ATTR| conversion.
  1727. +             * Do not filter out explicit individual flags below!
  1728. +             */
  1729. +            ace4_generic_read_filt &= ~ACE4_RW_NAMED_ATTRS;
  1730. +            ace4_generic_write_filt &= ~ACE4_RW_NAMED_ATTRS;
  1731. +            ace4_generic_execute_filt &= ~ACE4_RW_NAMED_ATTRS;
  1732. +            ace4_all_file_filt &= ~ACE4_RW_NAMED_ATTRS;
  1733. +            ace4_all_dir_filt &= ~ACE4_RW_NAMED_ATTRS;
  1734. +        }
  1735. +#endif /* MAP_WIN32GENERIC2ACE4GENERIC */
  1736. +
  1737. +        if (win_mask & GENERIC_ALL) {
  1738. +            if (file_type == NF4DIR)
  1739. +                *nfs4_mask |= ace4_all_dir_filt;
  1740. +            else
  1741. +                *nfs4_mask |= ace4_all_file_filt;
  1742. +        } else {
  1743. +            if (win_mask & GENERIC_READ)
  1744. +                *nfs4_mask |= ace4_generic_read_filt;
  1745. +            if (win_mask & GENERIC_WRITE)
  1746. +                *nfs4_mask |= ace4_generic_write_filt;
  1747. +            if (win_mask & GENERIC_EXECUTE)
  1748. +                *nfs4_mask |= ace4_generic_execute_filt;
  1749. +        }
  1750. +    }
  1751. +
  1752. +    /* Individual flags */
  1753. +    if (file_type == NF4DIR) {
  1754. +        if (win_mask & FILE_LIST_DIRECTORY) {
  1755. +            *nfs4_mask |= ACE4_LIST_DIRECTORY;
  1756. +        }
  1757. +        if (win_mask & FILE_ADD_FILE) {
  1758. +            *nfs4_mask |= ACE4_ADD_FILE;
  1759. +        }
  1760. +        if (win_mask & FILE_ADD_SUBDIRECTORY) {
  1761. +            *nfs4_mask |= ACE4_ADD_SUBDIRECTORY;
  1762. +        }
  1763. +        if (win_mask & FILE_DELETE_CHILD) {
  1764. +            *nfs4_mask |= ACE4_DELETE_CHILD;
  1765. +        }
  1766. +        if (win_mask & FILE_TRAVERSE) {
  1767. +            *nfs4_mask |= ACE4_EXECUTE;
  1768. +        }
  1769. +    }
  1770. +    else {
  1771. +        if (win_mask & FILE_READ_DATA) {
  1772. +            *nfs4_mask |= ACE4_READ_DATA;
  1773. +        }
  1774. +        if (win_mask & FILE_WRITE_DATA) {
  1775. +            *nfs4_mask |= ACE4_WRITE_DATA;
  1776. +        }
  1777. +        if (win_mask & FILE_APPEND_DATA) {
  1778. +            *nfs4_mask |= ACE4_APPEND_DATA;
  1779. +        }
  1780. +        if (win_mask & FILE_EXECUTE) {
  1781. +            *nfs4_mask |= ACE4_EXECUTE;
  1782. +        }
  1783. +        /*
  1784. +         * gisburn: Why does Win10 set |FILE_DELETE_CHILD| for
  1785. +         * plain files ?
  1786. +         */
  1787. +        if (win_mask & FILE_DELETE_CHILD) {
  1788. +            *nfs4_mask |= ACE4_DELETE_CHILD;
  1789. +        }
  1790. +    }
  1791. +
  1792. +    if (win_mask & FILE_READ_EA) {
  1793. +        *nfs4_mask |= ACE4_READ_NAMED_ATTRS;
  1794. +    }
  1795. +    if (win_mask & FILE_WRITE_EA) {
  1796. +        *nfs4_mask |= ACE4_WRITE_NAMED_ATTRS;
  1797. +    }
  1798. +    if (win_mask & FILE_READ_ATTRIBUTES) {
  1799. +        *nfs4_mask |= ACE4_READ_ATTRIBUTES;
  1800. +    }
  1801. +    if (win_mask & FILE_WRITE_ATTRIBUTES) {
  1802. +        *nfs4_mask |= ACE4_WRITE_ATTRIBUTES;
  1803. +    }
  1804. +    if (win_mask & READ_CONTROL) {
  1805. +        *nfs4_mask |= ACE4_READ_ACL;
  1806. +    }
  1807. +    if (win_mask & WRITE_DAC) {
  1808. +        *nfs4_mask |= ACE4_WRITE_ACL;
  1809. +    }
  1810. +    if (win_mask & WRITE_OWNER) {
  1811. +        *nfs4_mask |= ACE4_WRITE_OWNER;
  1812. +    }
  1813. +    if (win_mask & SYNCHRONIZE) {
  1814. +        *nfs4_mask |= ACE4_SYNCHRONIZE;
  1815. +    }
  1816. +    if (win_mask & DELETE) {
  1817. +        *nfs4_mask |= ACE4_DELETE;
  1818. +    }
  1819. +
  1820. +#if 1
  1821. +    /* DEBUG: Compare old and new code */
  1822. +    DASSERT_MSG(0,
  1823. +        ((long)*nfs4_mask == (long)(win_mask & 0x00ffffff)),
  1824. +        ("map_winaccessmask2nfs4acemask: "
  1825. +        "new code nfs4_mask=0x%lx, "
  1826. +        "old code nfs4_mask=0x%lx\n",
  1827. +        (long)*nfs4_mask, (long)(win_mask & 0x00ffffff)));
  1828. +#endif
  1829. +}
  1830. +
  1831. +static
  1832. +void map_nfs4acemask2winaccessmask(uint32_t nfs4_mask,
  1833. +    int file_type, bool named_attr_support, ACCESS_MASK *win_mask)
  1834. +{
  1835. +    *win_mask = 0;
  1836. +
  1837. +#ifdef MAP_WIN32GENERIC2ACE4GENERIC
  1838. +    bool is_generic = false;
  1839. +
  1840. +    /* Filtered |ACE4_GENERIC_*| masks */
  1841. +    uint32_t ace4_generic_read_filt = ACE4_GENERIC_READ;
  1842. +    uint32_t ace4_generic_write_filt =  ACE4_GENERIC_WRITE;
  1843. +    uint32_t ace4_generic_execute_filt = ACE4_GENERIC_EXECUTE;
  1844. +    uint32_t ace4_all_file_filt = ACE4_ALL_FILE;
  1845. +    uint32_t ace4_all_dir_filt = ACE4_ALL_DIR;
  1846. +
  1847. +    if (!named_attr_support) {
  1848. +        /*
  1849. +         * Filter out unsupported features for
  1850. +         * |ACE_*ATTR| --> |GENERIC_*| conversion.
  1851. +         * Do not filter out explicit individual flags below!
  1852. +         */
  1853. +        ace4_generic_read_filt &= ~ACE4_RW_NAMED_ATTRS;
  1854. +        ace4_generic_write_filt &= ~ACE4_RW_NAMED_ATTRS;
  1855. +        ace4_generic_execute_filt &= ~ACE4_RW_NAMED_ATTRS;
  1856. +        ace4_all_file_filt &= ~ACE4_RW_NAMED_ATTRS;
  1857. +        ace4_all_dir_filt &= ~ACE4_RW_NAMED_ATTRS;
  1858. +
  1859. +#ifdef WORKAROUND_FOR_LINUX_NFSD_NOT_SETTING_ACE4_WRITE_ATTRIBUTES
  1860. +        /*
  1861. +         * BUG(?): Linux 6.6.32-RT32 does not return
  1862. +         * |ACE4_WRITE_ATTRIBUTES| even when the attributes are
  1863. +         * writeable.
  1864. +         *
  1865. +         * Since |ACE4_GENERIC_WRITE| includes the
  1866. +         * |ACE4_WRITE_ATTRIBUTES| bit an attempt to set
  1867. +         * |GENERIC_WRITE| will succeed, but we can never get all
  1868. +         * the |ACE4_*| bits in |ACE4_GENERIC_WRITE| back when
  1869. +         * reading the ACL, so without this workaround we could
  1870. +         * never match |GENERIC_WRITE| when constructing the Win32
  1871. +         * ACLs.
  1872. +         *
  1873. +         * Testcase:
  1874. +         * ---- snip ----
  1875. +         * $ ksh93 -c 'rm -f test1.txt
  1876. +         * touch test1.txt
  1877. +         * icacls test1.txt /grant "siegfried_wulsch:(GW)"
  1878. +         * icacls test1.txt'
  1879. +         * ---- snip ----
  1880. +         * Second icacls should return "GW" for user "siegfried_wulsch".
  1881. +         */
  1882. +        ace4_generic_read_filt &= ~ACE4_WRITE_ATTRIBUTES;
  1883. +        ace4_generic_write_filt &= ~ACE4_WRITE_ATTRIBUTES;
  1884. +        ace4_generic_execute_filt &= ~ACE4_WRITE_ATTRIBUTES;
  1885. +        ace4_all_file_filt &= ~ACE4_WRITE_ATTRIBUTES;
  1886. +        ace4_all_dir_filt &= ~ACE4_WRITE_ATTRIBUTES;
  1887. +#endif /* WORKAROUND_FOR_LINUX_NFSD_NOT_SETTING_ACE4_WRITE_ATTRIBUTES */
  1888. +    }
  1889. +
  1890. +    /*
  1891. +     * Generic masks
  1892. +     * (|ACE4_GENERIC_*| contain multiple bits)
  1893. +     */
  1894. +#define ACEMASK_TEST_MASK(value, mask) (((value)&(mask)) == (mask))
  1895. +    if (file_type == NF4DIR) {
  1896. +        if (ACEMASK_TEST_MASK(nfs4_mask, ace4_all_dir_filt)) {
  1897. +            *win_mask |= GENERIC_ALL;
  1898. +            is_generic = true;
  1899. +        }
  1900. +    }
  1901. +    else {
  1902. +        if (ACEMASK_TEST_MASK(nfs4_mask, ace4_all_file_filt)) {
  1903. +            *win_mask |= GENERIC_ALL;
  1904. +            is_generic = true;
  1905. +        }
  1906. +    }
  1907. +
  1908. +    if (!(*win_mask & GENERIC_ALL)) {
  1909. +        if (ACEMASK_TEST_MASK(nfs4_mask, ace4_generic_read_filt)) {
  1910. +            *win_mask |= GENERIC_READ;
  1911. +            is_generic = true;
  1912. +        }
  1913. +        if (ACEMASK_TEST_MASK(nfs4_mask, ace4_generic_write_filt)) {
  1914. +            *win_mask |= GENERIC_WRITE;
  1915. +            is_generic = true;
  1916. +        }
  1917. +        if (ACEMASK_TEST_MASK(nfs4_mask, ace4_generic_execute_filt)) {
  1918. +            *win_mask |= GENERIC_EXECUTE;
  1919. +            is_generic = true;
  1920. +        }
  1921. +    }
  1922. +#endif /* MAP_WIN32GENERIC2ACE4GENERIC */
  1923. +
  1924. +    /* Individual flags */
  1925. +    if (file_type == NF4DIR) {
  1926. +        if (nfs4_mask & ACE4_LIST_DIRECTORY) {
  1927. +            *win_mask |= FILE_LIST_DIRECTORY;
  1928. +        }
  1929. +        if (nfs4_mask & ACE4_ADD_FILE) {
  1930. +            *win_mask |= FILE_ADD_FILE;
  1931. +        }
  1932. +        if (nfs4_mask & ACE4_ADD_SUBDIRECTORY) {
  1933. +            *win_mask |= FILE_ADD_SUBDIRECTORY;
  1934. +        }
  1935. +        if (nfs4_mask & ACE4_DELETE_CHILD) {
  1936. +            *win_mask |= FILE_DELETE_CHILD;
  1937. +        }
  1938. +        if (nfs4_mask & ACE4_EXECUTE) {
  1939. +            *win_mask |= FILE_TRAVERSE;
  1940. +        }
  1941. +    }
  1942. +    else {
  1943. +        if (nfs4_mask & ACE4_READ_DATA) {
  1944. +            *win_mask |= FILE_READ_DATA;
  1945. +        }
  1946. +        if (nfs4_mask & ACE4_WRITE_DATA) {
  1947. +            *win_mask |= FILE_WRITE_DATA;
  1948. +        }
  1949. +        if (nfs4_mask & ACE4_APPEND_DATA) {
  1950. +            *win_mask |= FILE_APPEND_DATA;
  1951. +        }
  1952. +        if (nfs4_mask & ACE4_EXECUTE) {
  1953. +            *win_mask |= FILE_EXECUTE;
  1954. +        }
  1955. +    }
  1956. +
  1957. +    if (nfs4_mask & ACE4_READ_NAMED_ATTRS) {
  1958. +        *win_mask |= FILE_READ_EA;
  1959. +    }
  1960. +    if (nfs4_mask & ACE4_WRITE_NAMED_ATTRS) {
  1961. +        *win_mask |= FILE_WRITE_EA;
  1962. +    }
  1963. +    if (nfs4_mask & ACE4_READ_ATTRIBUTES) {
  1964. +        *win_mask |= FILE_READ_ATTRIBUTES;
  1965. +    }
  1966. +    if (nfs4_mask & ACE4_WRITE_ATTRIBUTES) {
  1967. +        *win_mask |= FILE_WRITE_ATTRIBUTES;
  1968. +    }
  1969. +    if (nfs4_mask & ACE4_READ_ACL) {
  1970. +        *win_mask |= READ_CONTROL;
  1971. +    }
  1972. +    if (nfs4_mask & ACE4_WRITE_ACL) {
  1973. +        *win_mask |= WRITE_DAC;
  1974. +    }
  1975. +    if (nfs4_mask & ACE4_WRITE_OWNER) {
  1976. +        *win_mask |= WRITE_OWNER;
  1977. +    }
  1978. +    if (nfs4_mask & ACE4_SYNCHRONIZE) {
  1979. +        *win_mask |= SYNCHRONIZE;
  1980. +    }
  1981. +    if (nfs4_mask & ACE4_DELETE) {
  1982. +        *win_mask |= DELETE;
  1983. +    }
  1984. +
  1985. +#if 1
  1986. +    /* DEBUG: Compare old and new code */
  1987. +#ifdef MAP_WIN32GENERIC2ACE4GENERIC
  1988. +    if (!is_generic)
  1989. +#endif /* MAP_WIN32GENERIC2ACE4GENERIC */
  1990. +    {
  1991. +        DASSERT_MSG(0,
  1992. +            ((long)*win_mask == (long)(nfs4_mask /*& 0x00ffffff*/)),
  1993. +            ("#### map_nfs4acemask2winaccessmask: "
  1994. +            "new code win_mask=0x%lx, "
  1995. +            "old code win_mask=0x%lx\n",
  1996. +            (long)*win_mask, (long)(nfs4_mask /*& 0x00ffffff*/)));
  1997. +    }
  1998. +#endif
  1999. +}
  2000. +
  2001. +int map_sid2nfs4ace_who(PSID sid, PSID owner_sid, PSID group_sid,
  2002. +    char *who_out, char *domain, SID_NAME_USE *sid_type_out)
  2003. +{
  2004. +    int status, lasterr;
  2005. +    SID_NAME_USE sid_type = 0;
  2006. +    /* |(UTF8_UNLEN+sizeof('\0'))*2| so we have space for user+domain */
  2007. +    char who_buf[(UTF8_UNLEN+1)*2];
  2008. +    char domain_buf[UTF8_UNLEN+1];
  2009. +    DWORD who_size = sizeof(who_buf), domain_size = sizeof(domain_buf);
  2010. +    LPSTR sidstr = NULL;
  2011. +
  2012. +    DPRINTF(ACLLVL2, ("--> map_sid2nfs4ace_who("
  2013. +        "sid=0x%p,owner_sid=0x%p, group_sid=0x%p)\n",
  2014. +        sid, owner_sid, group_sid));
  2015. +
  2016. +    if (DPRINTF_LEVEL_ENABLED(ACLLVL2)) {
  2017. +        print_sid("sid", sid);
  2018. +        print_sid("owner_sid", owner_sid);
  2019. +        print_sid("group_sid", group_sid);
  2020. +    }
  2021. +
  2022. +    /* for ace mapping, we want to map owner's sid into "owner@"
  2023. +     * but for set_owner attribute we want to map owner into a user name
  2024. +     * same applies to group
  2025. +     */
  2026. +    status = 0;
  2027. +    if (owner_sid) {
  2028. +        if (EqualSid(sid, owner_sid)) {
  2029. +            DPRINTF(ACLLVL2, ("this is owner's sid\n"));
  2030. +            (void)memcpy(who_out, ACE4_OWNER, ACE4_OWNER_LEN+1);
  2031. +            sid_type = SidTypeUser;
  2032. +            status = ERROR_SUCCESS;
  2033. +            goto out;
  2034. +        }
  2035. +    }
  2036. +    if (group_sid) {
  2037. +        if (EqualSid(sid, group_sid)) {
  2038. +            DPRINTF(ACLLVL2, ("this is group's sid\n"));
  2039. +            memcpy(who_out, ACE4_GROUP, ACE4_GROUP_LEN+1);
  2040. +            sid_type = SidTypeGroup;
  2041. +            status = ERROR_SUCCESS;
  2042. +            goto out;
  2043. +        }
  2044. +    }
  2045. +    status = is_well_known_sid(sid, who_out, &sid_type);
  2046. +    if (status) {
  2047. +        if (!strncmp(who_out, ACE4_NOBODY, ACE4_NOBODY_LEN)) {
  2048. +            who_size = (DWORD)ACE4_NOBODY_LEN;
  2049. +            goto add_domain;
  2050. +        }
  2051. +
  2052. +        /* fixme: What about |sid_type| ? */
  2053. +        status = ERROR_SUCCESS;
  2054. +        goto out;
  2055. +    }
  2056. +
  2057. +    if (!ConvertSidToStringSidA(sid, &sidstr)) {
  2058. +        status = GetLastError();
  2059. +        eprintf("map_sid2nfs4ace_who: ConvertSidToStringSidA() "
  2060. +            "failed, error=%d\n", status);
  2061. +        goto out;
  2062. +    }
  2063. +
  2064. +    status = lookupaccountsidutf8(NULL, sid, who_buf, &who_size, domain_buf,
  2065. +        &domain_size, &sid_type);
  2066. +    lasterr = GetLastError();
  2067. +
  2068. +    if (status) {
  2069. +        DPRINTF(ACLLVL2, ("map_sid2nfs4ace_who: "
  2070. +            "LookupAccountSid(sidtostr(sid)='%s', who_buf='%s', "
  2071. +            "who_size=%d, domain='%s', domain_size=%d) "
  2072. +            "returned success, status=%d, GetLastError=%d\n",
  2073. +            sidstr, who_buf, who_size,
  2074. +            domain_buf, domain_size, status, lasterr));
  2075. +    }
  2076. +    else {
  2077. +        DPRINTF(ACLLVL2, ("map_sid2nfs4ace_who: "
  2078. +            "LookupAccountSid(sidtostr(sid)='%s', who_size=%d, "
  2079. +            "domain_size=%d) returned failure, status=%d, "
  2080. +            "GetLastError=%d\n",
  2081. +            sidstr, who_size, domain_size, status, lasterr));
  2082. +
  2083. +        /*
  2084. +         * No SID to local account mapping. Can happen for some system
  2085. +         * SIDs, and Unix_User+<uid> or Unix_Group+<gid> SIDs
  2086. +         */
  2087. +        switch (lasterr) {
  2088. +            /*
  2089. +             * This happens for Unix_User+<uid> or Unix_Group+<gid>
  2090. +             * SIDs
  2091. +             */
  2092. +            case ERROR_NONE_MAPPED:
  2093. +                /*
  2094. +                 * This can happen for two reasons:
  2095. +                 * 1. Someone copied a file from a NFS(v3) filesystem,
  2096. +                 * and Cygwin generated an Unix_User+<uid> or
  2097. +                 * Unix_Group+<gid> SID for the source file, which
  2098. +                 * tools like Cygwin cp(1) just copy.
  2099. +                 * 2. We have an uid/gid for which we do not have
  2100. +                 * a user-/group-name mapped.
  2101. +                 */
  2102. +#ifdef NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID
  2103. +                /* fixme: This should be a function argument */
  2104. +                extern nfs41_daemon_globals nfs41_dg;
  2105. +
  2106. +                uid_t unixuser_uid = ~0U;
  2107. +                gid_t unixgroup_gid = ~0U;
  2108. +
  2109. +                if (unixuser_sid2uid(sid, &unixuser_uid)) {
  2110. +                    if (!nfs41_idmap_uid_to_name(nfs41_dg.idmapper,
  2111. +                        unixuser_uid, who_out, UTF8_UNLEN)) {
  2112. +                        who_size = (DWORD)strlen(who_out);
  2113. +                        sid_type = SidTypeUser;
  2114. +                        status = ERROR_SUCCESS;
  2115. +
  2116. +                        DPRINTF(ACLLVL1, ("map_sid2nfs4ace_who: "
  2117. +                            "Unix_User+%d SID "
  2118. +                            "mapped to user '%s'\n",
  2119. +                            unixuser_uid, who_out));
  2120. +                        goto add_domain;
  2121. +                    }
  2122. +
  2123. +                    eprintf("map_sid2nfs4ace_who: "
  2124. +                        "unixuser_sid2uid(sid='%s',unixuser_uid=%d) "
  2125. +                        "returned no mapping.\n",
  2126. +                        sidstr, (int)unixuser_uid);
  2127. +                    goto err_none_mapped;
  2128. +                }
  2129. +
  2130. +                if (unixgroup_sid2gid(sid, &unixgroup_gid)) {
  2131. +                    if (!nfs41_idmap_gid_to_group(nfs41_dg.idmapper,
  2132. +                        unixgroup_gid, who_out, UTF8_GNLEN)) {
  2133. +                        who_size = (DWORD)strlen(who_out);
  2134. +                        sid_type = SidTypeGroup;
  2135. +                        status = ERROR_SUCCESS;
  2136. +
  2137. +                        DPRINTF(ACLLVL1, ("map_sid2nfs4ace_who: "
  2138. +                            "Unix_Group+%d SID "
  2139. +                            "mapped to group '%s'\n",
  2140. +                            unixgroup_gid, who_out));
  2141. +                        goto add_domain;
  2142. +                    }
  2143. +
  2144. +                    eprintf("map_sid2nfs4ace_who: "
  2145. +                        "unixgroup_sid2gid(sid='%s',unixgroup_gid=%d) "
  2146. +                        "returned no mapping.\n",
  2147. +                        sidstr, (int)unixgroup_gid);
  2148. +                    goto err_none_mapped;
  2149. +                }
  2150. +
  2151. +                eprintf("map_sid2nfs4ace_who: lookupaccountsidutf8() "
  2152. +                    "returned ERROR_NONE_MAPPED+no "
  2153. +                    "Unix_@(User|Group)+ mapping for sidstr='%s'\n",
  2154. +                    sidstr);
  2155. +err_none_mapped:
  2156. +                status = ERROR_NONE_MAPPED;
  2157. +#else
  2158. +                DPRINTF(ACLLVL2,
  2159. +                    ("map_sid2nfs4ace_who: lookupaccountsidutf8() "
  2160. +                    "returned ERROR_NONE_MAPPED for sidstr='%s'\n",
  2161. +                    sidstr));
  2162. +                status = lasterr;
  2163. +                goto out;
  2164. +#endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
  2165. +
  2166. +            /* Catch other cases */
  2167. +            case ERROR_NO_SUCH_USER:
  2168. +            case ERROR_NO_SUCH_GROUP:
  2169. +                eprintf("map_sid2nfs4ace_who: lookupaccountsidutf8() "
  2170. +                    "returned ERROR_NO_SUCH_@(USER|GROUP) for "
  2171. +                    "sidstr='%s'\n",
  2172. +                    sidstr);
  2173. +                status = lasterr;
  2174. +                goto out;
  2175. +            default:
  2176. +                eprintf("map_sid2nfs4ace_who: Internal error, "
  2177. +                    "lookupaccountsidutf8() returned unexpected ERROR_%d "
  2178. +                    "for sidstr='%s'\n",
  2179. +                    status, sidstr);
  2180. +                status = ERROR_INTERNAL_ERROR;
  2181. +                goto out;
  2182. +        }
  2183. +    }
  2184. +
  2185. +    (void)memcpy(who_out, who_buf, who_size);
  2186. +add_domain:
  2187. +    /*
  2188. +     * Complain if we attempt to add a domain suffix to an UID/GID
  2189. +     * value
  2190. +     */
  2191. +    EASSERT(!isdigit(who_out[0]));
  2192. +
  2193. +    char *wp;
  2194. +
  2195. +    wp = mempcpy(who_out+who_size, "@", sizeof(char));
  2196. +
  2197. +#ifdef NFS41_DRIVER_WS2022_HACKS
  2198. +    /* Fixup |domain| for Windows Sever 2022 NFSv4.1 server */
  2199. +    if ((!strncmp(who_out, "Users@", (size_t)who_size+1)) ||
  2200. +        (!strncmp(who_out, "Administrators@", (size_t)who_size+1))) {
  2201. +        domain = "BUILTIN";
  2202. +        DPRINTF(1,
  2203. +            ("map_sid2nfs4ace_who: Fixup '%.*s' domain='%s'\n",
  2204. +            (int)who_size+1, who_out, domain));
  2205. +    }
  2206. +    else if (!strncmp(who_out, "SYSTEM@", (size_t)who_size+1)) {
  2207. +        domain = "NT AUTHORITY";
  2208. +        DPRINTF(1,
  2209. +            ("map_sid2nfs4ace_who: Fixup '%.*s' domain='%s'\n",
  2210. +            (int)who_size+1, who_out, domain));
  2211. +    }
  2212. +#endif /* NFS41_DRIVER_WS2022_HACKS */
  2213. +    (void)memcpy(wp, domain, strlen(domain)+1);
  2214. +
  2215. +/* no_add_domain: */
  2216. +    status = ERROR_SUCCESS;
  2217. +out:
  2218. +    if (status) {
  2219. +        DPRINTF(ACLLVL2,
  2220. +            ("<-- map_sid2nfs4ace_who() returns %d\n", status));
  2221. +    }
  2222. +    else {
  2223. +        DPRINTF(ACLLVL2,
  2224. +            ("<-- map_sid2nfs4ace_who(who_out='%s', sid_type='%s'/%d) "
  2225. +            "returns %d\n",
  2226. +            who_out,
  2227. +            map_SID_NAME_USE2str(sid_type), sid_type,
  2228. +            status));
  2229. +        if (sid_type_out) {
  2230. +            *sid_type_out = sid_type;
  2231. +        }
  2232. +    }
  2233. +    if (sidstr)
  2234. +        LocalFree(sidstr);
  2235. +    return status;
  2236. +}
  2237. +
  2238. +int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
  2239. +    int file_type, bool named_attr_support, char *domain)
  2240. +{
  2241. +    int status;
  2242. +    if (acl == NULL) {
  2243. +        DPRINTF(ACLLVL2, ("this is a NULL dacl: all access to an object\n"));
  2244. +        nfs4_acl->count = 1;
  2245. +        nfs4_acl->aces = calloc(1, sizeof(nfsace4));
  2246. +        if (nfs4_acl->aces == NULL) {
  2247. +            status = GetLastError();
  2248. +            goto out;
  2249. +        }
  2250. +        nfs4_acl->flag = 0;
  2251. +        (void)memcpy(nfs4_acl->aces->who, ACE4_EVERYONE, ACE4_EVERYONE_LEN+1);
  2252. +        nfs4_acl->aces->acetype = ACE4_ACCESS_ALLOWED_ACE_TYPE;
  2253. +
  2254. +        if (file_type == NF4DIR) {
  2255. +            uint32_t ace4_all_dir_filt = ACE4_ALL_DIR;
  2256. +#ifdef MAP_WIN32GENERIC2ACE4GENERIC
  2257. +            /* Filter out unsupported features */
  2258. +            if (!named_attr_support) {
  2259. +                ace4_all_dir_filt &= ~ACE4_RW_NAMED_ATTRS;
  2260. +            }
  2261. +#endif /* MAP_WIN32GENERIC2ACE4GENERIC */
  2262. +            nfs4_acl->aces->acemask = ace4_all_dir_filt;
  2263. +        }
  2264. +        else {
  2265. +            uint32_t ace4_all_file_filt = ACE4_ALL_FILE;
  2266. +#ifdef MAP_WIN32GENERIC2ACE4GENERIC
  2267. +            /* Filter out unsupported features */
  2268. +            if (!named_attr_support) {
  2269. +                ace4_all_file_filt &= ~ACE4_RW_NAMED_ATTRS;
  2270. +            }
  2271. +#endif /* MAP_WIN32GENERIC2ACE4GENERIC */
  2272. +            nfs4_acl->aces->acemask = ace4_all_file_filt;
  2273. +        }
  2274. +        nfs4_acl->aces->aceflag = 0;
  2275. +    } else {
  2276. +        int win_i, nfs_i;
  2277. +        PACE_HEADER ace;
  2278. +        PBYTE tmp_pointer;
  2279. +        SID_NAME_USE who_sid_type = 0;
  2280. +        ACCESS_MASK win_mask;
  2281. +
  2282. +        DPRINTF(ACLLVL2, ("NON-NULL dacl with %d ACEs\n", acl->AceCount));
  2283. +        if (DPRINTF_LEVEL_ENABLED(ACLLVL3)) {
  2284. +            print_hexbuf_no_asci("ACL\n",
  2285. +                (const unsigned char *)acl, acl->AclSize);
  2286. +        }
  2287. +
  2288. +        nfs4_acl->aces = calloc(acl->AceCount, sizeof(nfsace4));
  2289. +        if (nfs4_acl->aces == NULL) {
  2290. +            status = GetLastError();
  2291. +            goto out;
  2292. +        }
  2293. +        nfs4_acl->flag = 0;
  2294. +        for (win_i = nfs_i = 0; win_i < acl->AceCount; win_i++) {
  2295. +            nfsace4 *curr_nfsace = &nfs4_acl->aces[nfs_i];
  2296. +            PSID ace_sid;
  2297. +
  2298. +            status = GetAce(acl, win_i, (LPVOID *)&ace);
  2299. +            if (!status) {
  2300. +                status = GetLastError();
  2301. +                eprintf("map_dacl_2_nfs4acl: GetAce failed with %d\n", status);
  2302. +                goto out_free;
  2303. +            }
  2304. +            tmp_pointer = (PBYTE)ace;
  2305. +            if (DPRINTF_LEVEL_ENABLED(ACLLVL3)) {
  2306. +                print_hexbuf_no_asci("ACE\n",
  2307. +                    (const unsigned char *)ace, ace->AceSize);
  2308. +            }
  2309. +            DPRINTF(ACLLVL3, ("ACE TYPE: 0x%x\n", ace->AceType));
  2310. +            if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
  2311. +                curr_nfsace->acetype = ACE4_ACCESS_ALLOWED_ACE_TYPE;
  2312. +            else if (ace->AceType == ACCESS_DENIED_ACE_TYPE)
  2313. +                curr_nfsace->acetype = ACE4_ACCESS_DENIED_ACE_TYPE;
  2314. +            else {
  2315. +                eprintf("map_dacl_2_nfs4acl: unsupported ACE type %d\n",
  2316. +                    ace->AceType);
  2317. +                status = ERROR_NOT_SUPPORTED;
  2318. +                goto out_free;
  2319. +            }
  2320. +
  2321. +            tmp_pointer += sizeof(ACCESS_MASK) + sizeof(ACE_HEADER);
  2322. +            ace_sid = tmp_pointer;
  2323. +
  2324. +#ifdef NFS41_DRIVER_ACLS_SETACL_SKIP_WINNULLSID_ACES
  2325. +            if (IsWellKnownSid(ace_sid, WinNullSid)) {
  2326. +                /*
  2327. +                 * Skip ACEs with SID==|WinNullSid|
  2328. +                 *
  2329. +                 * Cygwin generates artificial ACEs with SID user
  2330. +                 * |WinNullSid| to encode permission information
  2331. +                 * (see |CYG_ACE_ISBITS_TO_POSIX()| in
  2332. +                 * Cygwin newlib-cygwin/winsup/cygwin/sec/acl.cc
  2333. +                 *
  2334. +                 * This assumes that the filesystem which stores
  2335. +                 * the ACL data leaves them 1:1 intact - which is
  2336. +                 * not the case for the Linux NFSv4.1 server
  2337. +                 * (tested with Linux 6.6.32), which transforms the
  2338. +                 * NFSv4.1 ACLs into POSIX ACLs at setacl time,
  2339. +                 * and the POSIX ACLs back to NFSv4 ACLs at getacl
  2340. +                 * time.
  2341. +                 * And this lossy transformation screws-up Cygwin
  2342. +                 * completly.
  2343. +                 * The best we can do for now is to skip such
  2344. +                 * ACEs, as we have no way to detect whether
  2345. +                 * the NFS server supports full NFSv4 ACLs, or
  2346. +                 * only POSIX ACLs disguised as NFSv4 ACLs.
  2347. +                 */
  2348. +                DPRINTF(ACLLVL3, ("Skipping WinNullSid ACE, "
  2349. +                    "win_i=%d nfs_i=%d\n", (int)win_i, (int)nfs_i));
  2350. +                continue;
  2351. +            }
  2352. +#endif /* NFS41_DRIVER_ACLS_SETACL_SKIP_WINNULLSID_ACES */
  2353. +
  2354. +            status = map_sid2nfs4ace_who(ace_sid, sid, gsid,
  2355. +                curr_nfsace->who, domain, &who_sid_type);
  2356. +            if (status)
  2357. +                goto out_free;
  2358. +
  2359. +            win_mask = *(PACCESS_MASK)(ace + 1);
  2360. +
  2361. +            map_winace2nfs4aceflags(ace->AceFlags,
  2362. +                &curr_nfsace->aceflag);
  2363. +            map_winaccessmask2nfs4acemask(win_mask,
  2364. +                file_type, named_attr_support,
  2365. +                &curr_nfsace->acemask);
  2366. +
  2367. +            /*
  2368. +             * Clear |ACE4_INHERITED_ACE|
  2369. +             *
  2370. +             * (See RFC 8884 Section-6.2.1.4.1:
  2371. +             * ACE4_INHERITED_ACE
  2372. +             * Indicates that this ACE is inherited from a parent
  2373. +             * directory. A server that supports automatic inheritance
  2374. +             * will place this flag on any ACEs inherited from the
  2375. +             * parent directory when creating a new object.
  2376. +             * Client applications will use this to perform automatic
  2377. +             * inheritance. Clients and servers MUST clear this bit in
  2378. +             * the acl attribute; it may only be used in the dacl and
  2379. +             * sacl attributes.
  2380. +             * ---- snip ----
  2381. +             * )
  2382. +             *
  2383. +             * If we do not clear this bit Linux 6.6.32-RT32 nfsd
  2384. +             * will reject setting ACLs |NFS4ERR_ATTRNOTSUPP| via
  2385. +             * icacls(1win) if the parent directory has inheritance
  2386. +             * ACLs.
  2387. +             */
  2388. +            if (curr_nfsace->aceflag & ACE4_INHERITED_ACE) {
  2389. +                curr_nfsace->aceflag &= ~ACE4_INHERITED_ACE;
  2390. +                DPRINTF(ACLLVL3, ("clearning ACE4_INHERITED_ACE\n"));
  2391. +            }
  2392. +
  2393. +            /*
  2394. +             * Treat |SidTypeAlias| as (local) group
  2395. +             *
  2396. +             * It seems that |LookupAccount*A()| will always return
  2397. +             * |SidTypeAlias| for local groups created with
  2398. +             * $ net localgroup cygwingrp1 /add #
  2399. +             *
  2400. +             * References:
  2401. +             * - https://stackoverflow.com/questions/39373188/lookupaccountnamew-returns-sidtypealias-but-expected-sidtypegroup
  2402. +             */
  2403. +            if ((who_sid_type == SidTypeGroup) ||
  2404. +                (who_sid_type == SidTypeAlias)) {
  2405. +                DPRINTF(ACLLVL3, ("map_dacl_2_nfs4acl: who_sid_type='%s': "
  2406. +                    "aces[%d].who='%s': "
  2407. +                    "setting group flag\n",
  2408. +                    map_SID_NAME_USE2str(who_sid_type),
  2409. +                    nfs_i, curr_nfsace->who));
  2410. +                curr_nfsace->aceflag |= ACE4_IDENTIFIER_GROUP;
  2411. +            }
  2412. +
  2413. +            if (DPRINTF_LEVEL_ENABLED(ACLLVL1)) {
  2414. +                dprintf_out("win2nfs: nfs4_acl->aces[%d]=(who='%s', "
  2415. +                    "acetype='%s', "
  2416. +                    "aceflag='%s'/0x%lx, "
  2417. +                    "acemask='%s'/0x%lx(=win_mask=0x%lx)), "
  2418. +                    "who_sid_type='%s', "
  2419. +                    "win_i=%d\n",
  2420. +                    nfs_i,
  2421. +                    curr_nfsace->who,
  2422. +                    map_nfs_acetype2str(curr_nfsace->acetype),
  2423. +                    nfs_aceflag2shortname(curr_nfsace->aceflag),
  2424. +                    curr_nfsace->aceflag,
  2425. +                    nfs_mask2shortname(curr_nfsace->acemask),
  2426. +                    (long)curr_nfsace->acemask,
  2427. +                    (long)win_mask,
  2428. +                    map_SID_NAME_USE2str(who_sid_type),
  2429. +                    (int)win_i);
  2430. +                if (DPRINTF_LEVEL_ENABLED(ACLLVL2)) {
  2431. +                    print_windows_access_mask(curr_nfsace->who,
  2432. +                        win_mask);
  2433. +                    print_nfs_access_mask(curr_nfsace->who,
  2434. +                        curr_nfsace->acemask);
  2435. +                }
  2436. +            }
  2437. +
  2438. +            nfs_i++;
  2439. +        }
  2440. +
  2441. +        nfs4_acl->count = nfs_i;
  2442. +    }
  2443. +    status = ERROR_SUCCESS;
  2444. +out:
  2445. +    return status;
  2446. +out_free:
  2447. +    free(nfs4_acl->aces);
  2448. +    goto out;
  2449. +}
  2450. diff --git a/daemon/aclutil.h b/daemon/aclutil.h
  2451. new file mode 100644
  2452. index 0000000..66b4f24
  2453. --- /dev/null
  2454. +++ b/daemon/aclutil.h
  2455. @@ -0,0 +1,46 @@
  2456. +/* NFSv4.1 client for Windows
  2457. + * Copyright (C) 2012 The Regents of the University of Michigan
  2458. + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
  2459. + *
  2460. + * Olga Kornievskaia <aglo@umich.edu>
  2461. + * Casey Bodley <cbodley@umich.edu>
  2462. + * Roland Mainz <roland.mainz@nrubsig.org>
  2463. + *
  2464. + * This library is free software; you can redistribute it and/or modify it
  2465. + * under the terms of the GNU Lesser General Public License as published by
  2466. + * the Free Software Foundation; either version 2.1 of the License, or (at
  2467. + * your option) any later version.
  2468. + *
  2469. + * This library is distributed in the hope that it will be useful, but
  2470. + * without any warranty; without even the implied warranty of merchantability
  2471. + * or fitness for a particular purpose.  See the GNU Lesser General Public
  2472. + * License for more details.
  2473. + *
  2474. + * You should have received a copy of the GNU Lesser General Public License
  2475. + * along with this library; if not, write to the Free Software Foundation,
  2476. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  2477. + */
  2478. +
  2479. +#ifndef __NFS41_DAEMON_ACLUTIL_H__
  2480. +#define __NFS41_DAEMON_ACLUTIL_H__ 1
  2481. +
  2482. +#include "nfs41_build_features.h"
  2483. +#include "nfs41_daemon.h"
  2484. +
  2485. +/* |DPRINTF()| levels for acl logging */
  2486. +#define ACLLVL1 1
  2487. +#define ACLLVL2 2
  2488. +#define ACLLVL3 3
  2489. +
  2490. +void free_sids(PSID *sids, int count);
  2491. +int map_sid2nfs4ace_who(PSID sid, PSID owner_sid, PSID group_sid,
  2492. +    char *who_out, char *domain, SID_NAME_USE *sid_type_out);
  2493. +void convert_nfs4name_2_user_domain(LPSTR nfs4name,
  2494. +    LPSTR *domain);
  2495. +int convert_nfs4acl_2_dacl(nfs41_daemon_globals *nfs41dg,
  2496. +    nfsacl41 *acl, int file_type, PACL *dacl_out, PSID **sids_out,
  2497. +    bool named_attr_support);
  2498. +int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
  2499. +    int file_type, bool named_attr_support, char *domain);
  2500. +
  2501. +#endif /* !__NFS41_DAEMON_ACLUTIL_H__ */
  2502. diff --git a/daemon/open.c b/daemon/open.c
  2503. index e010c55..9cfc28b 100644
  2504. --- a/daemon/open.c
  2505. +++ b/daemon/open.c
  2506. @@ -27,6 +27,7 @@
  2507.  #include <strsafe.h>
  2508.  
  2509.  #include "nfs41_build_features.h"
  2510. +#include "aclutil.h"
  2511.  #include "nfs41_ops.h"
  2512.  #include "nfs41_daemon.h"
  2513.  #include "delegation.h"
  2514. @@ -807,12 +808,6 @@ out:
  2515.  }
  2516.  #endif /* NFS41_DRIVER_FEATURE_LOCAL_UIDGID_IN_NFSV3ATTRIBUTES */
  2517.  
  2518. -#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  2519. -/* FIXME: Move this into aclutils.h */
  2520. -int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
  2521. -    int file_type, bool named_attr_support, char *domain);
  2522. -#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  2523. -
  2524.  static int handle_open(void *daemon_context, nfs41_upcall *upcall)
  2525.  {
  2526.      int status = 0;
  2527. --
  2528. 2.51.0
  2529.  
  2530. From 9600b8f7f1c7c7ec9220b7d6e0bbc89cf52a639b Mon Sep 17 00:00:00 2001
  2531. From: Dan Shelton <dan.f.shelton@gmail.com>
  2532. Date: Sat, 15 Nov 2025 15:25:57 +0100
  2533. Subject: [PATCH 2/5] daemon: Fix arithmetic overflow
  2534.  
  2535. Fix arithmetic overflow.
  2536.  
  2537. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  2538. ---
  2539. daemon/lock.c | 2 +-
  2540.  1 file changed, 1 insertion(+), 1 deletion(-)
  2541.  
  2542. diff --git a/daemon/lock.c b/daemon/lock.c
  2543. index 9bafb66..7265fd4 100644
  2544. --- a/daemon/lock.c
  2545. +++ b/daemon/lock.c
  2546. @@ -305,7 +305,7 @@ retry_lock:
  2547.          DPRINTF(1,
  2548.              ("handle_lock(state->path.path='%s'): retry in %ldms\n",
  2549.              state->path.path, (long)poll_delay));
  2550. -        (void)delayxid(upcall->xid, 30+(poll_delay/1000));
  2551. +        (void)delayxid(upcall->xid, 30LL+((long long)poll_delay/1000LL));
  2552.          Sleep(poll_delay);
  2553.  
  2554.          goto retry_lock;
  2555. --
  2556. 2.51.0
  2557.  
  2558. From 54e251b2b53b109dbb843d5f608dc6baa8e90e5f Mon Sep 17 00:00:00 2001
  2559. From: Dan Shelton <dan.f.shelton@gmail.com>
  2560. Date: Sat, 15 Nov 2025 15:49:19 +0100
  2561. Subject: [PATCH 3/5] daemon: Fix printf()-style&co format argument warnings
  2562.  
  2563. Fix printf()-style&co format argument warnings.
  2564.  
  2565. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  2566. ---
  2567. daemon/idmap.c      | 8 ++++----
  2568.  daemon/name_cache.c | 6 +++---
  2569.  2 files changed, 7 insertions(+), 7 deletions(-)
  2570.  
  2571. diff --git a/daemon/idmap.c b/daemon/idmap.c
  2572. index 61fa576..031a840 100644
  2573. --- a/daemon/idmap.c
  2574. +++ b/daemon/idmap.c
  2575. @@ -1156,8 +1156,8 @@ int nfs41_idmap_uid_to_name(
  2576.  
  2577.      if (FAILED(StringCchCopyA(name, len, user.username))) {
  2578.          status = ERROR_BUFFER_OVERFLOW;
  2579. -        eprintf("username buffer overflow: '%s' > %u\n",
  2580. -            user.username, len);
  2581. +        eprintf("username buffer overflow: '%s' > %lu\n",
  2582. +            user.username, (unsigned long)len);
  2583.          goto out;
  2584.      }
  2585.  
  2586. @@ -1294,8 +1294,8 @@ int nfs41_idmap_gid_to_group(
  2587.  
  2588.      if (FAILED(StringCchCopyA(name, len, group.name))) {
  2589.          status = ERROR_BUFFER_OVERFLOW;
  2590. -        eprintf("group name buffer overflow: '%s' > %u\n",
  2591. -            group.name, len);
  2592. +        eprintf("group name buffer overflow: '%s' > %lu\n",
  2593. +            group.name, (unsigned long)len);
  2594.          goto out;
  2595.      }
  2596.  
  2597. diff --git a/daemon/name_cache.c b/daemon/name_cache.c
  2598. index 14afb14..3f301ef 100644
  2599. --- a/daemon/name_cache.c
  2600. +++ b/daemon/name_cache.c
  2601. @@ -564,7 +564,7 @@ int icu_strcmpcoll(UCollator *coll, const char *str1, const char *str2, int32_t
  2602.      if (U_FAILURE(status)) {
  2603.          eprintf("icu_strcmpcoll: "
  2604.              "ucol_strcollUTF8(str1='%s',str2='%s') returned status='%s'\n",
  2605. -            u_errorName(status));
  2606. +            str1, str2, u_errorName(status));
  2607.          return -1;
  2608.      }
  2609.  
  2610. @@ -579,7 +579,7 @@ int icu_strcmpcoll(UCollator *coll, const char *str1, const char *str2, int32_t
  2611.  
  2612.      eprintf("icu_strcmpcoll: "
  2613.          "ucol_strcollUTF8(str1='%s',str2='%s') returned unexpected result=0x%lx\n",
  2614. -        (long)result);
  2615. +        str1, str2, (long)result);
  2616.      return -1;
  2617.  }
  2618.  
  2619. @@ -1240,7 +1240,7 @@ int nfs41_name_cache_insert(
  2620.      int status;
  2621.  
  2622.      DPRINTF(NCLVL1, ("--> nfs41_name_cache_insert('%.*s')\n",
  2623. -        name->name + name->len - path, path));
  2624. +        (unsigned int)(name->name + name->len - path), path));
  2625.  
  2626.      NC_SET_NAMECMP(caseinsensitivesearch);
  2627.  
  2628. --
  2629. 2.51.0
  2630.  
  2631. From 641822e3866a872d522b422095bbb228d99cf794 Mon Sep 17 00:00:00 2001
  2632. From: Dan Shelton <dan.f.shelton@gmail.com>
  2633. Date: Sat, 15 Nov 2025 16:29:48 +0100
  2634. Subject: [PATCH 4/5] sys: Remove unused _updowncall_entry.cattrs variable
  2635.  
  2636. Remove unused _updowncall_entry.cattrs variable.
  2637.  
  2638. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  2639. ---
  2640. sys/nfs41sys_driver.h | 1 -
  2641.  1 file changed, 1 deletion(-)
  2642.  
  2643. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  2644. index bf5ebc0..1c327ab 100644
  2645. --- a/sys/nfs41sys_driver.h
  2646. +++ b/sys/nfs41sys_driver.h
  2647. @@ -240,7 +240,6 @@ typedef struct _updowncall_entry {
  2648.              PSECURITY_DESCRIPTOR SdBuffer;
  2649.  #endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  2650.              ULONG disp;
  2651. -            ULONG cattrs;
  2652.              LONG open_owner_id;
  2653.              DWORD mode;
  2654.  #ifdef NFS41_DRIVER_FEATURE_LOCAL_UIDGID_IN_NFSV3ATTRIBUTES
  2655. --
  2656. 2.51.0
  2657.  
  2658. From 4dff4fadf58e935432b50bbebfe0a3723799233b Mon Sep 17 00:00:00 2001
  2659. From: Roland Mainz <roland.mainz@nrubsig.org>
  2660. Date: Sat, 15 Nov 2025 16:46:13 +0100
  2661. Subject: [PATCH 5/5] daemon: Fix ACL data alignment in
  2662.  |convert_nfs4acl_2_dacl()|
  2663.  
  2664. Fix ACL data alignment in |convert_nfs4acl_2_dacl()|, data should
  2665. be |DWORD|-aligned per Windows spec, but |sizeof(DWORD)| == 4|,
  2666. and not |8|.
  2667.  
  2668. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  2669. ---
  2670. daemon/aclutil.c | 2 +-
  2671.  1 file changed, 1 insertion(+), 1 deletion(-)
  2672.  
  2673. diff --git a/daemon/aclutil.c b/daemon/aclutil.c
  2674. index 57c1111..6724543 100644
  2675. --- a/daemon/aclutil.c
  2676. +++ b/daemon/aclutil.c
  2677. @@ -213,7 +213,7 @@ int convert_nfs4acl_2_dacl(nfs41_daemon_globals *nfs41dg,
  2678.          win_i++;
  2679.      }
  2680.      size += sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE)*win_i);
  2681. -    size = align8(size); /* align size on |DWORD| boundry */
  2682. +    size = align4(size); /* align size on |DWORD| boundry */
  2683.      dacl = malloc(size);
  2684.      if (dacl == NULL)
  2685.          goto out_free_sids;
  2686. --
  2687. 2.51.0

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at