pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: Patch to remove hardcoded domain, Win32AuthentificationId in NFSv4.1 client id hash, VC19 installer config+misc, 2024-06-11
Posted by Anonymous on Tue 11th Jun 2024 17:21
raw | new post

  1. From c83dd8f0c5e40274985eb1c74b4ebcf710c8fb8a Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Tue, 11 Jun 2024 14:06:51 +0200
  4. Subject: [PATCH 1/5] daemon,cygwin: Do not hardcode and/or overwrite
  5.  domainname
  6.  
  7. Do not hardcode the domain name to "GLOBAL.LOC", nor overwrite
  8. a domain name which has been previously set.
  9.  
  10. msnfs41client.bash will still set the system's domain name
  11. to "GLOBAL.LOC" if there is no domain name.
  12.  
  13. Reported-by: Dan Shelton <dan.f.shelton@gmail.com>
  14. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  15. ---
  16. cygwin/devel/msnfs41client.bash | 16 ++++++++++++----
  17.  daemon/idmap.c                  | 20 ++++++++++++++++----
  18.  daemon/idmap.h                  |  2 +-
  19.  daemon/nfs41_daemon.c           |  5 ++++-
  20.  4 files changed, 33 insertions(+), 10 deletions(-)
  21.  
  22. diff --git a/cygwin/devel/msnfs41client.bash b/cygwin/devel/msnfs41client.bash
  23. index ffce9be..2b66485 100644
  24. --- a/cygwin/devel/msnfs41client.bash
  25. +++ b/cygwin/devel/msnfs41client.bash
  26. @@ -143,7 +143,13 @@ function nfsclient_install
  27.         bcdedit /dbgsettings local
  28.  
  29.         # set domain name
  30. +       typeset win_domainname=''
  31. +       if [[ -f '/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters/Domain' ]] ; then
  32. +               win_domainname="$( strings '/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters/Domain' )"
  33. +       fi
  34. +       if [[ "${win_domainname}" == '' ]] ; then
  35.         regtool -s set '/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters/Domain' 'GLOBAL.LOC'
  36. +       fi
  37.  
  38.         # disable DFS
  39.         sc query Dfsc
  40. @@ -204,10 +210,11 @@ function nfsclient_rundeamon
  41.  {
  42.         set -o nounset
  43.  
  44. -       printf '# user='%s' uname='%s' isadmin=%d\n' \
  45. +       printf '# user="%s" uname="%s" isadmin=%d domainname="%s"\n' \
  46.                 "$(id -u -n)" \
  47.                 "$(uname -a)" \
  48. -               "$(is_windows_admin_account ; printf "%d\n" $((${?}?0:1)))"
  49. +               "$(is_windows_admin_account ; printf "%d\n" $((${?}?0:1)))" \
  50. +               "$(domainname)"
  51.  
  52.         # sync before starting nfs41 client daemon, to limit the damage
  53.         # if the kernel module generates a crash on startup
  54. @@ -301,10 +308,11 @@ function nfsclient_system_rundeamon
  55.  {
  56.         set -o nounset
  57.  
  58. -       printf '# user='%s' uname='%s' isadmin=%d\n' \
  59. +       printf '# user="%s" uname="%s" isadmin=%d domainname="%s"\n' \
  60.                 "$(id -u -n)" \
  61.                 "$(uname -a)" \
  62. -               "$(is_windows_admin_account ; printf "%d\n" $((${?}?0:1)))"
  63. +               "$(is_windows_admin_account ; printf "%d\n" $((${?}?0:1)))" \
  64. +               "$(domainname)"
  65.  
  66.         # sync before starting nfs41 client daemon, to limit the damage
  67.         # if the kernel module generates a crash on startup
  68. diff --git a/daemon/idmap.c b/daemon/idmap.c
  69. index 8fe4fd4..82d058f 100644
  70. --- a/daemon/idmap.c
  71. +++ b/daemon/idmap.c
  72. @@ -84,6 +84,7 @@ static const char CONFIG_FILENAME[] = "C:\\etc\\ms-nfs41-idmap.conf";
  73.  struct idmap_config {
  74.      /* ldap server information */
  75.      char hostname[NFS41_HOSTNAME_LEN+1];
  76. +    char localdomain_name[NFS41_HOSTNAME_LEN+1];
  77.      UINT port;
  78.      UINT version;
  79.      UINT timeout;
  80. @@ -728,7 +729,8 @@ static int idmap_lookup_user(
  81.                  ("# ATTR_USER_NAME: cygwin_getent_passwd: returned '%s', uid=%u, gid=%u\n",
  82.                  lookup->value, (unsigned int)cy_uid, (unsigned int)cy_gid));
  83.              (void)snprintf(principal_name, sizeof(principal_name),
  84. -                "%s@%s", (const char *)lookup->value, "GLOBAL.LOC");
  85. +                "%s@%s", (const char *)lookup->value,
  86. +                context->config.localdomain_name);
  87.              StringCchCopyA(user->username, VAL_LEN, lookup->value);
  88.              StringCchCopyA(user->principal, VAL_LEN, principal_name);
  89.              user->uid = cy_uid;
  90. @@ -758,7 +760,8 @@ static int idmap_lookup_user(
  91.                  ("# ATTR_PRINCIPAL: cygwin_getent_passwd: returned '%s', uid=%u, gid=%u\n",
  92.                  lookup->value, (unsigned int)cy_uid, (unsigned int)cy_gid));
  93.              (void)snprintf(principal_name, sizeof(principal_name),
  94. -                "%s@%s", (const char *)lookup->value, "GLOBAL.LOC");
  95. +                "%s@%s", (const char *)lookup->value,
  96. +                context->config.localdomain_name);
  97.  
  98.              if (!strcmp(principal_name, lookup->value)) {
  99.                  StringCchCopyA(user->username, VAL_LEN, search_name);
  100. @@ -785,7 +788,8 @@ static int idmap_lookup_user(
  101.              DPRINTF(CYGWINIDLVL,
  102.                  ("# ATTR_UID: cygwin_getent_passwd: returned '%s', uid=%u, gid=%u\n",
  103.                  res_username, (unsigned int)cy_uid, (unsigned int)cy_gid));
  104. -            (void)snprintf(principal_name, sizeof(principal_name), "%s@%s", res_username, "GLOBAL.LOC");
  105. +            (void)snprintf(principal_name, sizeof(principal_name),
  106. +                "%s@%s", res_username, context->config.localdomain_name);
  107.  
  108.              StringCchCopyA(user->username, VAL_LEN, res_username);
  109.              StringCchCopyA(user->principal, VAL_LEN, principal_name);
  110. @@ -929,7 +933,7 @@ out:
  111.  
  112.  /* public idmap interface */
  113.  int nfs41_idmap_create(
  114. -    struct idmap_context **context_out)
  115. +    struct idmap_context **context_out, const char *localdomain_name)
  116.  {
  117.      struct idmap_context *context;
  118.      int status = NO_ERROR;
  119. @@ -940,6 +944,14 @@ int nfs41_idmap_create(
  120.          goto out;
  121.      }
  122.  
  123. +    (void)strcpy_s(context->config.localdomain_name,
  124. +        sizeof(context->config.localdomain_name),
  125. +        localdomain_name);
  126. +    if (context == NULL) {
  127. +        status = GetLastError();
  128. +        goto out;
  129. +    }
  130. +
  131.      /* initialize the caches */
  132.      cache_init(&context->users, &user_cache_ops);
  133.      cache_init(&context->groups, &group_cache_ops);
  134. diff --git a/daemon/idmap.h b/daemon/idmap.h
  135. index 82b5867..6a74458 100644
  136. --- a/daemon/idmap.h
  137. +++ b/daemon/idmap.h
  138. @@ -30,7 +30,7 @@
  139.  typedef struct idmap_context nfs41_idmapper;
  140.  
  141.  int nfs41_idmap_create(
  142. -    nfs41_idmapper **context_out);
  143. +    nfs41_idmapper **context_out, const char *localdomain_name);
  144.  
  145.  void nfs41_idmap_free(
  146.      nfs41_idmapper *context);
  147. diff --git a/daemon/nfs41_daemon.c b/daemon/nfs41_daemon.c
  148. index febca0d..4797b00 100644
  149. --- a/daemon/nfs41_daemon.c
  150. +++ b/daemon/nfs41_daemon.c
  151. @@ -762,7 +762,10 @@ VOID ServiceStart(DWORD argc, LPTSTR *argv)
  152.      nfs41_server_list_init();
  153.  
  154.      if (cmd_args.ldap_enable) {
  155. -        status = nfs41_idmap_create(&(nfs41_dg.idmapper));
  156. +        EASSERT(nfs41_dg.localdomain_name[0] != '\0');
  157. +
  158. +        status = nfs41_idmap_create(&(nfs41_dg.idmapper),
  159. +            nfs41_dg.localdomain_name);
  160.          if (status) {
  161.              eprintf("id mapping initialization failed with %d\n", status);
  162.              goto out_logs;
  163. --
  164. 2.45.1
  165.  
  166. From a34d4989fea0ec44920d93d3e504920e170bb099 Mon Sep 17 00:00:00 2001
  167. From: Roland Mainz <roland.mainz@nrubsig.org>
  168. Date: Tue, 11 Jun 2024 15:04:26 +0200
  169. Subject: [PATCH 2/5] libtirpc: Add debug code to hunt for callback deadlocks
  170.  
  171. Add debug code to hunt for callback deadlocks
  172.  
  173. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  174. ---
  175. libtirpc/src/clnt_vc.c | 59 +++++++++++++++++++++++++++++++++++++++---
  176.  1 file changed, 55 insertions(+), 4 deletions(-)
  177.  
  178. diff --git a/libtirpc/src/clnt_vc.c b/libtirpc/src/clnt_vc.c
  179. index f15eb38..7b3962f 100644
  180. --- a/libtirpc/src/clnt_vc.c
  181. +++ b/libtirpc/src/clnt_vc.c
  182. @@ -93,6 +93,9 @@
  183.  #include <rpc/rpc.h>
  184.  #include "rpc_com.h"
  185.  
  186. +#define DEBUG_TIRPC_CB_DEADLOCKS 1
  187. +
  188. +
  189.  #define MCALL_MSG_SIZE 24
  190.  
  191.  #define CMGROUP_MAX    16
  192. @@ -175,6 +178,7 @@ static cond_t   *vc_cv;
  193.  /* XXX Need Windows signal/event stuff XXX */
  194.  #define release_fd_lock(fd, mask) {    \
  195.         mutex_lock(&clnt_fd_lock);      \
  196. +       assert(vc_fd_locks[(fd)] != 0); \
  197.         vc_fd_locks[(fd)] = 0;          \
  198.         \
  199.         cond_broadcast(&vc_cv[(fd)]);   \
  200. @@ -195,6 +199,20 @@ static const char clnt_vc_str[] = "clnt_vc_create";
  201.  static const char clnt_read_vc_str[] = "read_vc";
  202.  static const char __no_mem_str[] = "out of memory";
  203.  
  204. +#ifdef DEBUG_TIRPC_CB_DEADLOCKS
  205. +#define TIRPCDbgEnter() __try {
  206. +#define TIRPCDbgLeave() ; } \
  207. +       __except(EXCEPTION_EXECUTE_HANDLER) { \
  208. +               (void)fprintf(stderr, \
  209. +                       "#### FATAL: exception in " \
  210. +                       "thr=%04lx'%s'/%ld ####\n", \
  211. +                       (long)GetCurrentThreadId(), \
  212. +                       __FILE__, (long)__LINE__); }
  213. +#else
  214. +#define TIRPCDbgEnter()
  215. +#define TIRPCDbgLeave()
  216. +#endif /* DEBUG_TIRPC_CB_DEADLOCKS */
  217. +
  218.  /* callback thread */
  219.  #define CALLBACK_TIMEOUT 5000
  220.  #define        RQCRED_SIZE     400     /* this size is excessive */
  221. @@ -211,19 +229,44 @@ static unsigned int WINAPI clnt_cb_thread(void *args)
  222.  
  223.      (void)fprintf(stderr/*stdout*/,
  224.          "%04lx: cb: Callback thread running\n", (long)GetCurrentThreadId());
  225. +
  226. +#ifdef DEBUG_TIRPC_CB_DEADLOCKS
  227. +    int cond_wait_timed_fails;
  228. +    DWORD lasterr;
  229. +
  230. +loop_restart:
  231. +#endif /* DEBUG_TIRPC_CB_DEADLOCKS */
  232.      while(1) {
  233.          cb_req header;
  234.          void *res = NULL;
  235. +
  236. +#ifdef DEBUG_TIRPC_CB_DEADLOCKS
  237. +        TIRPCDbgEnter();
  238. +#endif /* DEBUG_TIRPC_CB_DEADLOCKS */
  239.          mutex_lock(&clnt_fd_lock);
  240. +#ifdef DEBUG_TIRPC_CB_DEADLOCKS
  241. +        cond_wait_timed_fails = 0;
  242. +#endif /* DEBUG_TIRPC_CB_DEADLOCKS */
  243.             while (vc_fd_locks[ct->ct_fd] ||
  244.                  !ct->use_stored_reply_msg ||
  245.                  (ct->use_stored_reply_msg && ct->reply_msg.rm_direction != CALL)) {
  246.              if (cl->shutdown)
  247.                  break;
  248. -                   if (!cond_wait_timed(&vc_cv[ct->ct_fd], &clnt_fd_lock,
  249. -                CALLBACK_TIMEOUT))
  250. +           if (!cond_wait_timed(&vc_cv[ct->ct_fd], &clnt_fd_lock,
  251. +                CALLBACK_TIMEOUT)) {
  252. +#ifdef DEBUG_TIRPC_CB_DEADLOCKS
  253. +                lasterr = GetLastError();
  254. +                if (cond_wait_timed_fails++ > 2) {
  255. +                    mutex_unlock(&clnt_fd_lock);
  256. +                    (void)fprintf(stdout,
  257. +                        "%04lx: cb: possible deadlockm, lasterr=%d\n",
  258. +                        (long)GetCurrentThreadId(), (int)lasterr);
  259. +                    goto loop_restart;
  260. +                }
  261. +#endif /* DEBUG_TIRPC_CB_DEADLOCKS */
  262.                  if (!vc_fd_locks[ct->ct_fd])
  263.                      break;
  264. +           }
  265.         }
  266.         vc_fd_locks[ct->ct_fd] = 1;
  267.         mutex_unlock(&clnt_fd_lock);
  268. @@ -316,6 +359,9 @@ skip_setlastfrag:
  269.          ct->ct_wait.tv_sec = saved_timeout_sec;
  270.          ct->ct_wait.tv_usec = saved_timeout_usec;
  271.          release_fd_lock(ct->ct_fd, mask);
  272. +#ifdef DEBUG_TIRPC_CB_DEADLOCKS
  273. +        TIRPCDbgLeave();
  274. +#endif /* DEBUG_TIRPC_CB_DEADLOCKS */
  275.      }
  276.  out:
  277.      return status;
  278. @@ -541,7 +587,9 @@ clnt_vc_call(cl, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
  279.  #else
  280.         /* XXX Need Windows signal/event stuff XXX */
  281.  #endif
  282. -    enum clnt_stat status;
  283. +    enum clnt_stat status = RPC_SYSTEMERROR;
  284. +
  285. +       TIRPCDbgEnter();
  286.  
  287.         assert(cl != NULL);
  288.  
  289. @@ -586,7 +634,8 @@ call_again:
  290.         }
  291.         if (! shipnow) {
  292.                 release_fd_lock(ct->ct_fd, mask);
  293. -               return (RPC_SUCCESS);
  294. +               status = RPC_SUCCESS;
  295. +               goto out_status;
  296.         }
  297.  
  298.  #ifdef NO_CB_4_KRB5P
  299. @@ -711,6 +760,8 @@ call_again:
  300.  out:
  301.      status = ct->ct_error.re_status;
  302.         release_fd_lock(ct->ct_fd, mask);
  303. +out_status:
  304. +       TIRPCDbgLeave();
  305.         return status;
  306.  }
  307.  
  308. --
  309. 2.45.1
  310.  
  311. From 9b5619ff7dcb589d910574ce724b114d5effc613 Mon Sep 17 00:00:00 2001
  312. From: Roland Mainz <roland.mainz@nrubsig.org>
  313. Date: Tue, 11 Jun 2024 16:13:58 +0200
  314. Subject: [PATCH 3/5] daemon: Logging same user with different
  315.  AuthenticationIds causes session issues
  316.  
  317. Logging same user with different AuthenticationIds (same user, one
  318. time as normal login, and one time with Adminstrator priviledges)
  319. causes NFSv4.1 session issues.
  320. Issue is that each AuthenticationId LUID requires a seperate nfs_mount,
  321. but |nfs41_client_owner()| does not generate a different hash.
  322.  
  323. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  324. ---
  325. daemon/nfs41_client.c | 26 ++++++++++++++++++++++++++
  326.  daemon/util.c         | 21 +++++++++++++++++++++
  327.  daemon/util.h         |  1 +
  328.  3 files changed, 48 insertions(+)
  329.  
  330. diff --git a/daemon/nfs41_client.c b/daemon/nfs41_client.c
  331. index 361794d..8b16cf4 100644
  332. --- a/daemon/nfs41_client.c
  333. +++ b/daemon/nfs41_client.c
  334. @@ -369,6 +369,7 @@ int nfs41_client_owner(
  335.      const ULONGLONG time_created = GetTickCount64();
  336.      int status;
  337.      char username[UNLEN+1];
  338. +    LUID authenticationid;
  339.  
  340.      /*
  341.       * gisburn: What about primary group (for /usr/bin/newgrp
  342. @@ -381,6 +382,19 @@ int nfs41_client_owner(
  343.          goto out;
  344.      }
  345.  
  346. +    if (!get_token_authenticationid(GetCurrentThreadEffectiveToken(),
  347. +        &authenticationid)) {
  348. +        status = GetLastError();
  349. +        eprintf("get_token_authenticationid() failed with %d\n", status);
  350. +        goto out;
  351. +    }
  352. +
  353. +    DPRINTF(0, ("nfs41_client_owner: "
  354. +        "username='%s' authenticationid=(0x%x/0x%lx)\n",
  355. +        username,
  356. +        (int)authenticationid.LowPart,
  357. +        (long)authenticationid.HighPart));
  358. +
  359.      /* owner.verifier = "time created" */
  360.      memcpy(owner->co_verifier, &time_created, sizeof(time_created));
  361.  
  362. @@ -415,6 +429,18 @@ int nfs41_client_owner(
  363.          goto out_hash;
  364.      }
  365.  
  366. +    if (!CryptHashData(hash, (const BYTE*)&authenticationid.LowPart, (DWORD)sizeof(DWORD), 0)) {
  367. +        status = GetLastError();
  368. +        eprintf("CryptHashData() failed with %d\n", status);
  369. +        goto out_hash;
  370. +    }
  371. +
  372. +    if (!CryptHashData(hash, (const BYTE*)&authenticationid.HighPart, (DWORD)sizeof(LONG), 0)) {
  373. +        status = GetLastError();
  374. +        eprintf("CryptHashData() failed with %d\n", status);
  375. +        goto out_hash;
  376. +    }
  377. +
  378.      if (!CryptHashData(hash, (const BYTE*)&port, (DWORD)sizeof(port), 0)) {
  379.          status = GetLastError();
  380.          eprintf("CryptHashData() failed with %d\n", status);
  381. diff --git a/daemon/util.c b/daemon/util.c
  382. index 79a2312..c4e0dd7 100644
  383. --- a/daemon/util.c
  384. +++ b/daemon/util.c
  385. @@ -842,6 +842,27 @@ bool get_token_primarygroup_name(HANDLE tok, char *out_buffer)
  386.      return true;
  387.  }
  388.  
  389. +bool get_token_authenticationid(HANDLE tok, LUID *out_authenticationid)
  390. +{
  391. +    DWORD tokdatalen;
  392. +    PTOKEN_GROUPS_AND_PRIVILEGES ptgp;
  393. +
  394. +    tokdatalen = sizeof(TOKEN_GROUPS_AND_PRIVILEGES)+GETTOKINFO_EXTRA_BUFFER;
  395. +    ptgp = _alloca(tokdatalen);
  396. +    if (!GetTokenInformation(tok, TokenGroupsAndPrivileges, ptgp,
  397. +        tokdatalen, &tokdatalen)) {
  398. +        eprintf("get_token_authenticationid: "
  399. +            "GetTokenInformation(tok=0x%p, TokenGroupsAndPrivileges) failed, "
  400. +            "status=%d\n",
  401. +            (void *)tok, (int)GetLastError());
  402. +        return false;
  403. +    }
  404. +
  405. +    *out_authenticationid = ptgp->AuthenticationId;
  406. +
  407. +    return true;
  408. +}
  409. +
  410.  bool set_token_privilege(HANDLE tok, const char *seprivname, bool enable_priv)
  411.  {
  412.      TOKEN_PRIVILEGES tp;
  413. diff --git a/daemon/util.h b/daemon/util.h
  414. index e350cf8..20922a3 100644
  415. --- a/daemon/util.h
  416. +++ b/daemon/util.h
  417. @@ -306,6 +306,7 @@ bool getwinntversionnnumbers(DWORD *MajorVersionPtr, DWORD *MinorVersionPtr, DWO
  418.  
  419.  bool get_token_user_name(HANDLE tok, char *out_buffer);
  420.  bool get_token_primarygroup_name(HANDLE tok, char *out_buffer);
  421. +bool get_token_authenticationid(HANDLE tok, LUID *out_authenticationid);
  422.  bool set_token_privilege(HANDLE tok, const char *seprivname, bool enable_priv);
  423.  
  424.  
  425. --
  426. 2.45.1
  427.  
  428. From a7d4c6742a29a6212d0f6d717a905b32647e5f21 Mon Sep 17 00:00:00 2001
  429. From: Roland Mainz <roland.mainz@nrubsig.org>
  430. Date: Tue, 11 Jun 2024 16:50:13 +0200
  431. Subject: [PATCH 4/5] build.vc19,daemon: Factor out access token code to its
  432.  own source file
  433.  
  434. Factor out access token code to its own source file
  435.  
  436. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  437. ---
  438. build.vc19/nfsd/nfsd.vcxproj |   2 +
  439.  daemon/accesstoken.c         | 185 +++++++++++++++++++++++++++++++++++
  440.  daemon/accesstoken.h         |  33 +++++++
  441.  daemon/daemon_debug.c        |   1 +
  442.  daemon/nfs41_client.c        |   1 +
  443.  daemon/nfs41_daemon.c        |   1 +
  444.  daemon/open.c                |   1 +
  445.  daemon/util.c                | 162 ------------------------------
  446.  daemon/util.h                |   6 --
  447.  9 files changed, 224 insertions(+), 168 deletions(-)
  448.  create mode 100644 daemon/accesstoken.c
  449.  create mode 100644 daemon/accesstoken.h
  450.  
  451. diff --git a/build.vc19/nfsd/nfsd.vcxproj b/build.vc19/nfsd/nfsd.vcxproj
  452. index 4b1ec49..cc98f3c 100644
  453. --- a/build.vc19/nfsd/nfsd.vcxproj
  454. +++ b/build.vc19/nfsd/nfsd.vcxproj
  455. @@ -172,6 +172,7 @@
  456.      </Link>
  457.    </ItemDefinitionGroup>
  458.    <ItemGroup>
  459. +    <ClCompile Include="..\..\daemon\accesstoken.c" />
  460.      <ClCompile Include="..\..\daemon\acl.c" />
  461.      <ClCompile Include="..\..\daemon\callback_server.c" />
  462.      <ClCompile Include="..\..\daemon\callback_xdr.c" />
  463. @@ -213,6 +214,7 @@
  464.      <ClCompile Include="..\..\daemon\volume.c" />
  465.    </ItemGroup>
  466.    <ItemGroup>
  467. +    <ClInclude Include="..\..\daemon\accesstoken.h" />
  468.      <ClInclude Include="..\..\daemon\cpvparser1.h" />
  469.      <ClInclude Include="..\..\daemon\daemon_debug.h" />
  470.      <ClInclude Include="..\..\daemon\delegation.h" />
  471. diff --git a/daemon/accesstoken.c b/daemon/accesstoken.c
  472. new file mode 100644
  473. index 0000000..a164b4e
  474. --- /dev/null
  475. +++ b/daemon/accesstoken.c
  476. @@ -0,0 +1,185 @@
  477. +/*
  478. + * NFSv4.1 client for Windows
  479. + * Copyright (C) 2024 Roland Mainz <roland.mainz@nrubsig.org>
  480. + *
  481. + * Roland Mainz <roland.mainz@nrubsig.org>
  482. + *
  483. + * This library is free software; you can redistribute it and/or modify it
  484. + * under the terms of the GNU Lesser General Public License as published by
  485. + * the Free Software Foundation; either version 2.1 of the License, or (at
  486. + * your option) any later version.
  487. + *
  488. + * This library is distributed in the hope that it will be useful, but
  489. + * without any warranty; without even the implied warranty of merchantability
  490. + * or fitness for a particular purpose.  See the GNU Lesser General Public
  491. + * License for more details.
  492. + *
  493. + * You should have received a copy of the GNU Lesser General Public License
  494. + * along with this library; if not, write to the Free Software Foundation,
  495. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  496. + */
  497. +
  498. +#include "accesstoken.h"
  499. +#include "daemon_debug.h"
  500. +#include <Lmcons.h>
  501. +
  502. +/*
  503. + * Performance hack:
  504. + * GETTOKINFO_EXTRA_BUFFER - extra space for more data
  505. + * |GetTokenInformation()| for |TOKEN_USER| and |TOKEN_PRIMARY_GROUP|
  506. + * always fails in Win10 with |ERROR_INSUFFICIENT_BUFFER| if you
  507. + * just pass the |sizeof(TOKEN_*)| value. Instead of calling
  508. + * |GetTokenInformation()| with |NULL| arg to obtain the size to
  509. + * allocate we just provide 2048 bytes of extra space after the
  510. + * |TOKEN_*| size, and pray it is enough
  511. + */
  512. +#define GETTOKINFO_EXTRA_BUFFER (2048)
  513. +
  514. +bool get_token_user_name(HANDLE tok, char *out_buffer)
  515. +{
  516. +    DWORD tokdatalen;
  517. +    PTOKEN_USER ptuser;
  518. +    PSID pusid;
  519. +    DWORD namesize = UNLEN+1;
  520. +    char domainbuffer[UNLEN+1];
  521. +    DWORD domainbuffer_size = sizeof(domainbuffer);
  522. +    SID_NAME_USE name_use;
  523. +
  524. +    tokdatalen = sizeof(TOKEN_USER)+GETTOKINFO_EXTRA_BUFFER;
  525. +    ptuser = _alloca(tokdatalen);
  526. +    if (!GetTokenInformation(tok, TokenUser, ptuser,
  527. +        tokdatalen, &tokdatalen)) {
  528. +        eprintf("get_token_username: "
  529. +            "GetTokenInformation(tok=0x%p, TokenUser) failed, "
  530. +            "status=%d\n",
  531. +            (void *)tok, (int)GetLastError());
  532. +        return false;
  533. +    }
  534. +
  535. +    pusid = ptuser->User.Sid;
  536. +
  537. +#ifdef NFS41_DRIVER_SID_CACHE
  538. +    if (sidcache_getcached_bysid(&user_sidcache, pusid, out_buffer)) {
  539. +        return true;
  540. +    }
  541. +#endif /* NFS41_DRIVER_SID_CACHE */
  542. +
  543. +    if (!LookupAccountSidA(NULL, pusid, out_buffer, &namesize,
  544. +        domainbuffer, &domainbuffer_size, &name_use)) {
  545. +        eprintf("get_token_user_name: "
  546. +            "LookupAccountSidA() failed, status=%d\n",
  547. +            (int)GetLastError());
  548. +        return false;
  549. +    }
  550. +
  551. +#ifdef NFS41_DRIVER_SID_CACHE
  552. +    sidcache_add(&user_sidcache, out_buffer, pusid);
  553. +#endif /* NFS41_DRIVER_SID_CACHE */
  554. +
  555. +    return true;
  556. +}
  557. +
  558. +bool get_token_primarygroup_name(HANDLE tok, char *out_buffer)
  559. +{
  560. +    DWORD tokdatalen;
  561. +    PTOKEN_PRIMARY_GROUP ptpgroup;
  562. +    PSID pgsid;
  563. +    DWORD namesize = GNLEN+1;
  564. +    char domainbuffer[UNLEN+1];
  565. +    DWORD domainbuffer_size = sizeof(domainbuffer);
  566. +    SID_NAME_USE name_use;
  567. +
  568. +    tokdatalen = sizeof(TOKEN_PRIMARY_GROUP)+GETTOKINFO_EXTRA_BUFFER;
  569. +    ptpgroup = _alloca(tokdatalen);
  570. +    if (!GetTokenInformation(tok, TokenPrimaryGroup, ptpgroup,
  571. +        tokdatalen, &tokdatalen)) {
  572. +        eprintf("get_token_primarygroup_name: "
  573. +            "GetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
  574. +            "status=%d\n",
  575. +            (void *)tok, (int)GetLastError());
  576. +        return false;
  577. +    }
  578. +
  579. +    pgsid = ptpgroup->PrimaryGroup;
  580. +
  581. +#ifdef NFS41_DRIVER_SID_CACHE
  582. +    if (sidcache_getcached_bysid(&group_sidcache, pgsid, out_buffer)) {
  583. +        return true;
  584. +    }
  585. +#endif /* NFS41_DRIVER_SID_CACHE */
  586. +
  587. +    if (!LookupAccountSidA(NULL, pgsid, out_buffer, &namesize,
  588. +        domainbuffer, &domainbuffer_size, &name_use)) {
  589. +        eprintf("get_token_primarygroup_name: "
  590. +            "LookupAccountSidA() failed, status=%d\n",
  591. +            (int)GetLastError());
  592. +        return false;
  593. +    }
  594. +
  595. +#ifdef NFS41_DRIVER_SID_CACHE
  596. +    sidcache_add(&group_sidcache, out_buffer, pgsid);
  597. +#endif /* NFS41_DRIVER_SID_CACHE */
  598. +
  599. +    return true;
  600. +}
  601. +
  602. +bool get_token_authenticationid(HANDLE tok, LUID *out_authenticationid)
  603. +{
  604. +    DWORD tokdatalen;
  605. +    PTOKEN_GROUPS_AND_PRIVILEGES ptgp;
  606. +
  607. +    tokdatalen = sizeof(TOKEN_GROUPS_AND_PRIVILEGES)+GETTOKINFO_EXTRA_BUFFER;
  608. +    ptgp = _alloca(tokdatalen);
  609. +    if (!GetTokenInformation(tok, TokenGroupsAndPrivileges, ptgp,
  610. +        tokdatalen, &tokdatalen)) {
  611. +        eprintf("get_token_authenticationid: "
  612. +            "GetTokenInformation(tok=0x%p, TokenGroupsAndPrivileges) failed, "
  613. +            "status=%d\n",
  614. +            (void *)tok, (int)GetLastError());
  615. +        return false;
  616. +    }
  617. +
  618. +    *out_authenticationid = ptgp->AuthenticationId;
  619. +
  620. +    return true;
  621. +}
  622. +
  623. +bool set_token_privilege(HANDLE tok, const char *seprivname, bool enable_priv)
  624. +{
  625. +    TOKEN_PRIVILEGES tp;
  626. +    LUID luid;
  627. +    bool res;
  628. +
  629. +    if(!LookupPrivilegeValueA(NULL, seprivname, &luid)) {
  630. +        DPRINTF(1, ("set_token_privilege: "
  631. +            "LookupPrivilegeValue(seprivname='%s') failed, "
  632. +            "status=%d\n",
  633. +            seprivname,
  634. +            (int)GetLastError()));
  635. +        res = false;
  636. +        goto out;
  637. +    }
  638. +
  639. +    tp.PrivilegeCount = 1;
  640. +    tp.Privileges[0].Luid = luid;
  641. +    tp.Privileges[0].Attributes = enable_priv?(SE_PRIVILEGE_ENABLED):0;
  642. +
  643. +    if(!AdjustTokenPrivileges(tok,
  644. +        FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
  645. +        NULL, NULL)) {
  646. +        DPRINTF(1, ("set_token_privilege: "
  647. +            "AdjustTokenPrivileges() for '%s' failed, status=%d\n",
  648. +            seprivname,
  649. +            (int)GetLastError()));
  650. +        res = false;
  651. +        goto out;
  652. +    }
  653. +
  654. +    res = true;
  655. +out:
  656. +    DPRINTF(0,
  657. +        ("set_token_privilege(seprivname='%s',enable_priv=%d), res=%d\n",
  658. +        seprivname, (int)enable_priv, (int)res));
  659. +
  660. +    return res;
  661. +}
  662. diff --git a/daemon/accesstoken.h b/daemon/accesstoken.h
  663. new file mode 100644
  664. index 0000000..67f49cd
  665. --- /dev/null
  666. +++ b/daemon/accesstoken.h
  667. @@ -0,0 +1,33 @@
  668. +/*
  669. + * NFSv4.1 client for Windows
  670. + * Copyright (C) 2024 Roland Mainz <roland.mainz@nrubsig.org>
  671. + *
  672. + * Roland Mainz <roland.mainz@nrubsig.org>
  673. + *
  674. + * This library is free software; you can redistribute it and/or modify it
  675. + * under the terms of the GNU Lesser General Public License as published by
  676. + * the Free Software Foundation; either version 2.1 of the License, or (at
  677. + * your option) any later version.
  678. + *
  679. + * This library is distributed in the hope that it will be useful, but
  680. + * without any warranty; without even the implied warranty of merchantability
  681. + * or fitness for a particular purpose.  See the GNU Lesser General Public
  682. + * License for more details.
  683. + *
  684. + * You should have received a copy of the GNU Lesser General Public License
  685. + * along with this library; if not, write to the Free Software Foundation,
  686. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  687. + */
  688. +
  689. +#ifndef __NFS41_DAEMON_ACCESSTOKEN_H__
  690. +#define __NFS41_DAEMON_ACCESSTOKEN_H__ 1
  691. +
  692. +#include <Windows.h>
  693. +#include <stdbool.h>
  694. +
  695. +bool get_token_user_name(HANDLE tok, char *out_buffer);
  696. +bool get_token_primarygroup_name(HANDLE tok, char *out_buffer);
  697. +bool get_token_authenticationid(HANDLE tok, LUID *out_authenticationid);
  698. +bool set_token_privilege(HANDLE tok, const char *seprivname, bool enable_priv);
  699. +
  700. +#endif /* !__NFS41_DAEMON_ACCESSTOKEN_H__ */
  701. diff --git a/daemon/daemon_debug.c b/daemon/daemon_debug.c
  702. index df9620a..05e0c0a 100644
  703. --- a/daemon/daemon_debug.c
  704. +++ b/daemon/daemon_debug.c
  705. @@ -32,6 +32,7 @@
  706.  #include "service.h"
  707.  #include "rpc/rpc.h"
  708.  #include "rpc/auth_sspi.h"
  709. +#include "accesstoken.h"
  710.  
  711.  extern int g_debug_level = DEFAULT_DEBUG_LEVEL;
  712.  
  713. diff --git a/daemon/nfs41_client.c b/daemon/nfs41_client.c
  714. index 8b16cf4..8df4390 100644
  715. --- a/daemon/nfs41_client.c
  716. +++ b/daemon/nfs41_client.c
  717. @@ -31,6 +31,7 @@
  718.  #include "delegation.h"
  719.  #include "daemon_debug.h"
  720.  #include "nfs41_ops.h"
  721. +#include "accesstoken.h"
  722.  
  723.  
  724.  uint32_t nfs41_exchange_id_flags(
  725. diff --git a/daemon/nfs41_daemon.c b/daemon/nfs41_daemon.c
  726. index 4797b00..3456c08 100644
  727. --- a/daemon/nfs41_daemon.c
  728. +++ b/daemon/nfs41_daemon.c
  729. @@ -40,6 +40,7 @@
  730.  #include "daemon_debug.h"
  731.  #include "upcall.h"
  732.  #include "sid.h"
  733. +#include "accesstoken.h"
  734.  #include "util.h"
  735.  
  736.  /* nfs41_dg.num_worker_threads sets the actual number of worker threads */
  737. diff --git a/daemon/open.c b/daemon/open.c
  738. index ccfda2f..dfaf17f 100644
  739. --- a/daemon/open.c
  740. +++ b/daemon/open.c
  741. @@ -34,6 +34,7 @@
  742.  #include "upcall.h"
  743.  #include "util.h"
  744.  #include "idmap.h"
  745. +#include "accesstoken.h"
  746.  
  747.  static int create_open_state(
  748.      IN const char *path,
  749. diff --git a/daemon/util.c b/daemon/util.c
  750. index c4e0dd7..c764303 100644
  751. --- a/daemon/util.c
  752. +++ b/daemon/util.c
  753. @@ -25,7 +25,6 @@
  754.  #include <stdio.h>
  755.  #include <stdlib.h>
  756.  #include <wincrypt.h> /* for Crypt*() functions */
  757. -#include <Lmcons.h>
  758.  
  759.  #include "daemon_debug.h"
  760.  #include "util.h"
  761. @@ -741,164 +740,3 @@ bool getwinntversionnnumbers(
  762.      return false;
  763.  #endif /* _WIN64 */
  764.  }
  765. -
  766. -/*
  767. - * Performance hack:
  768. - * GETTOKINFO_EXTRA_BUFFER - extra space for more data
  769. - * |GetTokenInformation()| for |TOKEN_USER| and |TOKEN_PRIMARY_GROUP|
  770. - * always fails in Win10 with |ERROR_INSUFFICIENT_BUFFER| if you
  771. - * just pass the |sizeof(TOKEN_*)| value. Instead of calling
  772. - * |GetTokenInformation()| with |NULL| arg to obtain the size to
  773. - * allocate we just provide 2048 bytes of extra space after the
  774. - * |TOKEN_*| size, and pray it is enough
  775. - */
  776. -#define GETTOKINFO_EXTRA_BUFFER (2048)
  777. -
  778. -bool get_token_user_name(HANDLE tok, char *out_buffer)
  779. -{
  780. -    DWORD tokdatalen;
  781. -    PTOKEN_USER ptuser;
  782. -    PSID pusid;
  783. -    DWORD namesize = UNLEN+1;
  784. -    char domainbuffer[UNLEN+1];
  785. -    DWORD domainbuffer_size = sizeof(domainbuffer);
  786. -    SID_NAME_USE name_use;
  787. -
  788. -    tokdatalen = sizeof(TOKEN_USER)+GETTOKINFO_EXTRA_BUFFER;
  789. -    ptuser = _alloca(tokdatalen);
  790. -    if (!GetTokenInformation(tok, TokenUser, ptuser,
  791. -        tokdatalen, &tokdatalen)) {
  792. -        eprintf("get_token_username: "
  793. -            "GetTokenInformation(tok=0x%p, TokenUser) failed, "
  794. -            "status=%d\n",
  795. -            (void *)tok, (int)GetLastError());
  796. -        return false;
  797. -    }
  798. -
  799. -    pusid = ptuser->User.Sid;
  800. -
  801. -#ifdef NFS41_DRIVER_SID_CACHE
  802. -    if (sidcache_getcached_bysid(&user_sidcache, pusid, out_buffer)) {
  803. -        return true;
  804. -    }
  805. -#endif /* NFS41_DRIVER_SID_CACHE */
  806. -
  807. -    if (!LookupAccountSidA(NULL, pusid, out_buffer, &namesize,
  808. -        domainbuffer, &domainbuffer_size, &name_use)) {
  809. -        eprintf("get_token_user_name: "
  810. -            "LookupAccountSidA() failed, status=%d\n",
  811. -            (int)GetLastError());
  812. -        return false;
  813. -    }
  814. -
  815. -#ifdef NFS41_DRIVER_SID_CACHE
  816. -    sidcache_add(&user_sidcache, out_buffer, pusid);
  817. -#endif /* NFS41_DRIVER_SID_CACHE */
  818. -
  819. -    return true;
  820. -}
  821. -
  822. -bool get_token_primarygroup_name(HANDLE tok, char *out_buffer)
  823. -{
  824. -    DWORD tokdatalen;
  825. -    PTOKEN_PRIMARY_GROUP ptpgroup;
  826. -    PSID pgsid;
  827. -    DWORD namesize = GNLEN+1;
  828. -    char domainbuffer[UNLEN+1];
  829. -    DWORD domainbuffer_size = sizeof(domainbuffer);
  830. -    SID_NAME_USE name_use;
  831. -
  832. -    tokdatalen = sizeof(TOKEN_PRIMARY_GROUP)+GETTOKINFO_EXTRA_BUFFER;
  833. -    ptpgroup = _alloca(tokdatalen);
  834. -    if (!GetTokenInformation(tok, TokenPrimaryGroup, ptpgroup,
  835. -        tokdatalen, &tokdatalen)) {
  836. -        eprintf("get_token_primarygroup_name: "
  837. -            "GetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
  838. -            "status=%d\n",
  839. -            (void *)tok, (int)GetLastError());
  840. -        return false;
  841. -    }
  842. -
  843. -    pgsid = ptpgroup->PrimaryGroup;
  844. -
  845. -#ifdef NFS41_DRIVER_SID_CACHE
  846. -    if (sidcache_getcached_bysid(&group_sidcache, pgsid, out_buffer)) {
  847. -        return true;
  848. -    }
  849. -#endif /* NFS41_DRIVER_SID_CACHE */
  850. -
  851. -    if (!LookupAccountSidA(NULL, pgsid, out_buffer, &namesize,
  852. -        domainbuffer, &domainbuffer_size, &name_use)) {
  853. -        eprintf("get_token_primarygroup_name: "
  854. -            "LookupAccountSidA() failed, status=%d\n",
  855. -            (int)GetLastError());
  856. -        return false;
  857. -    }
  858. -
  859. -#ifdef NFS41_DRIVER_SID_CACHE
  860. -    sidcache_add(&group_sidcache, out_buffer, pgsid);
  861. -#endif /* NFS41_DRIVER_SID_CACHE */
  862. -
  863. -    return true;
  864. -}
  865. -
  866. -bool get_token_authenticationid(HANDLE tok, LUID *out_authenticationid)
  867. -{
  868. -    DWORD tokdatalen;
  869. -    PTOKEN_GROUPS_AND_PRIVILEGES ptgp;
  870. -
  871. -    tokdatalen = sizeof(TOKEN_GROUPS_AND_PRIVILEGES)+GETTOKINFO_EXTRA_BUFFER;
  872. -    ptgp = _alloca(tokdatalen);
  873. -    if (!GetTokenInformation(tok, TokenGroupsAndPrivileges, ptgp,
  874. -        tokdatalen, &tokdatalen)) {
  875. -        eprintf("get_token_authenticationid: "
  876. -            "GetTokenInformation(tok=0x%p, TokenGroupsAndPrivileges) failed, "
  877. -            "status=%d\n",
  878. -            (void *)tok, (int)GetLastError());
  879. -        return false;
  880. -    }
  881. -
  882. -    *out_authenticationid = ptgp->AuthenticationId;
  883. -
  884. -    return true;
  885. -}
  886. -
  887. -bool set_token_privilege(HANDLE tok, const char *seprivname, bool enable_priv)
  888. -{
  889. -    TOKEN_PRIVILEGES tp;
  890. -    LUID luid;
  891. -    bool res;
  892. -
  893. -    if(!LookupPrivilegeValueA(NULL, seprivname, &luid)) {
  894. -        DPRINTF(1, ("set_token_privilege: "
  895. -            "LookupPrivilegeValue(seprivname='%s') failed, "
  896. -            "status=%d\n",
  897. -            seprivname,
  898. -            (int)GetLastError()));
  899. -        res = false;
  900. -        goto out;
  901. -    }
  902. -
  903. -    tp.PrivilegeCount = 1;
  904. -    tp.Privileges[0].Luid = luid;
  905. -    tp.Privileges[0].Attributes = enable_priv?(SE_PRIVILEGE_ENABLED):0;
  906. -
  907. -    if(!AdjustTokenPrivileges(tok,
  908. -        FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
  909. -        NULL, NULL)) {
  910. -        DPRINTF(1, ("set_token_privilege: "
  911. -            "AdjustTokenPrivileges() for '%s' failed, status=%d\n",
  912. -            seprivname,
  913. -            (int)GetLastError()));
  914. -        res = false;
  915. -        goto out;
  916. -    }
  917. -
  918. -    res = true;
  919. -out:
  920. -    DPRINTF(0,
  921. -        ("set_token_privilege(seprivname='%s',enable_priv=%d), res=%d\n",
  922. -        seprivname, (int)enable_priv, (int)res));
  923. -
  924. -    return res;
  925. -}
  926. diff --git a/daemon/util.h b/daemon/util.h
  927. index 20922a3..7f7d585 100644
  928. --- a/daemon/util.h
  929. +++ b/daemon/util.h
  930. @@ -304,10 +304,4 @@ bool_t waitcriticalsection(LPCRITICAL_SECTION cs);
  931.  
  932.  bool getwinntversionnnumbers(DWORD *MajorVersionPtr, DWORD *MinorVersionPtr, DWORD *BuildNumberPtr);
  933.  
  934. -bool get_token_user_name(HANDLE tok, char *out_buffer);
  935. -bool get_token_primarygroup_name(HANDLE tok, char *out_buffer);
  936. -bool get_token_authenticationid(HANDLE tok, LUID *out_authenticationid);
  937. -bool set_token_privilege(HANDLE tok, const char *seprivname, bool enable_priv);
  938. -
  939. -
  940.  #endif /* !__NFS41_DAEMON_UTIL_H__ */
  941. --
  942. 2.45.1
  943.  
  944. From c8a9b25ed433e8947dc938bbf6a48d6f949fe127 Mon Sep 17 00:00:00 2001
  945. From: Roland Mainz <roland.mainz@nrubsig.org>
  946. Date: Tue, 11 Jun 2024 17:46:50 +0200
  947. Subject: [PATCH 5/5] build.vc19: Add Visual Studio 19 Installer install
  948.  configuration
  949.  
  950. Add Visual Studio 19 Installer install configuration, so users
  951. can replicate the exact build configuration.
  952.  
  953. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  954. ---
  955. build.vc19/ms-nfs41-client.vsconfig | 57 +++++++++++++++++++++++++++++
  956.  1 file changed, 57 insertions(+)
  957.  create mode 100755 build.vc19/ms-nfs41-client.vsconfig
  958.  
  959. diff --git a/build.vc19/ms-nfs41-client.vsconfig b/build.vc19/ms-nfs41-client.vsconfig
  960. new file mode 100755
  961. index 0000000..f11cd52
  962. --- /dev/null
  963. +++ b/build.vc19/ms-nfs41-client.vsconfig
  964. @@ -0,0 +1,57 @@
  965. +{
  966. +  "version": "1.0",
  967. +  "components": [
  968. +    "Microsoft.VisualStudio.Component.CoreEditor",
  969. +    "Microsoft.VisualStudio.Workload.CoreEditor",
  970. +    "Microsoft.VisualStudio.Component.NuGet",
  971. +    "Microsoft.Net.Component.4.6.1.TargetingPack",
  972. +    "Microsoft.VisualStudio.Component.Roslyn.Compiler",
  973. +    "Microsoft.VisualStudio.Component.Roslyn.LanguageServices",
  974. +    "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions",
  975. +    "Microsoft.Net.Component.4.8.SDK",
  976. +    "Microsoft.VisualStudio.Component.TypeScript.4.3",
  977. +    "Microsoft.VisualStudio.Component.JavaScript.TypeScript",
  978. +    "Microsoft.Component.MSBuild",
  979. +    "Microsoft.VisualStudio.Component.TextTemplating",
  980. +    "Microsoft.VisualStudio.Component.Debugger.JustInTime",
  981. +    "Component.Microsoft.VisualStudio.LiveShare",
  982. +    "Microsoft.VisualStudio.Component.IntelliCode",
  983. +    "Microsoft.VisualStudio.Component.VC.CoreIde",
  984. +    "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
  985. +    "Microsoft.VisualStudio.Component.Graphics.Tools",
  986. +    "Microsoft.VisualStudio.Component.VC.DiagnosticTools",
  987. +    "Microsoft.VisualStudio.Component.Windows10SDK.19041",
  988. +    "Microsoft.VisualStudio.Component.VC.Redist.14.Latest",
  989. +    "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
  990. +    "Microsoft.VisualStudio.Component.VC.Tools.ARM64",
  991. +    "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.CMake",
  992. +    "Microsoft.VisualStudio.Component.VC.CMake.Project",
  993. +    "Microsoft.VisualStudio.Component.VC.ATL",
  994. +    "Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest",
  995. +    "Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest",
  996. +    "Microsoft.VisualStudio.Component.VC.ATLMFC",
  997. +    "Microsoft.VisualStudio.Component.VC.CLI.Support",
  998. +    "Microsoft.VisualStudio.Component.VC.ASAN",
  999. +    "Microsoft.VisualStudio.Component.VC.Modules.x86.x64",
  1000. +    "Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset",
  1001. +    "Microsoft.VisualStudio.Component.VC.Llvm.Clang",
  1002. +    "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Llvm.Clang",
  1003. +    "Microsoft.VisualStudio.Component.Windows10SDK.18362",
  1004. +    "Microsoft.Component.VC.Runtime.UCRTSDK",
  1005. +    "Microsoft.VisualStudio.Workload.NativeDesktop",
  1006. +    "Microsoft.VisualStudio.Component.VC.Tools.ARM64EC",
  1007. +    "Microsoft.VisualStudio.Component.VC.Tools.ARM",
  1008. +    "Microsoft.VisualStudio.Component.Git",
  1009. +    "Microsoft.VisualStudio.Component.VC.Runtimes.ARM.Spectre",
  1010. +    "Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre",
  1011. +    "Microsoft.VisualStudio.Component.VC.Runtimes.ARM64EC.Spectre",
  1012. +    "Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre",
  1013. +    "Microsoft.VisualStudio.Component.VC.ATL.ARM",
  1014. +    "Microsoft.VisualStudio.Component.VC.ATL.ARM64",
  1015. +    "Microsoft.VisualStudio.Component.VC.ATL.ARM64EC",
  1016. +    "Microsoft.VisualStudio.Component.VC.MFC.ARM",
  1017. +    "Microsoft.VisualStudio.Component.VC.MFC.ARM64",
  1018. +    "Microsoft.VisualStudio.Component.VC.MFC.ARM64EC",
  1019. +    "Microsoft.VisualStudio.Component.Windows10SDK.20348"
  1020. +  ]
  1021. +}
  1022. \ No newline at end of file
  1023. --
  1024. 2.45.1

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