pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


idmapper prototype rework 2023-11-27
Posted by Anonymous on Mon 27th Nov 2023 19:07
raw | new post

  1. diff --git a/build.vc19/nfsd/nfsd.vcxproj b/build.vc19/nfsd/nfsd.vcxproj
  2. index 047f02d..77df470 100644
  3. --- a/build.vc19/nfsd/nfsd.vcxproj
  4. +++ b/build.vc19/nfsd/nfsd.vcxproj
  5. @@ -153,11 +153,13 @@
  6.      <ClCompile Include="..\..\daemon\acl.c" />
  7.      <ClCompile Include="..\..\daemon\callback_server.c" />
  8.      <ClCompile Include="..\..\daemon\callback_xdr.c" />
  9. +    <ClCompile Include="..\..\daemon\cpvparser1.c" />
  10.      <ClCompile Include="..\..\daemon\daemon_debug.c" />
  11.      <ClCompile Include="..\..\daemon\delegation.c" />
  12.      <ClCompile Include="..\..\daemon\ea.c" />
  13.      <ClCompile Include="..\..\daemon\getattr.c" />
  14.      <ClCompile Include="..\..\daemon\idmap.c" />
  15. +    <ClCompile Include="..\..\daemon\idmap_cygwin.c" />
  16.      <ClCompile Include="..\..\daemon\lock.c" />
  17.      <ClCompile Include="..\..\daemon\lookup.c" />
  18.      <ClCompile Include="..\..\daemon\mount.c" />
  19. @@ -188,6 +190,7 @@
  20.      <ClCompile Include="..\..\daemon\volume.c" />
  21.    </ItemGroup>
  22.    <ItemGroup>
  23. +    <ClInclude Include="..\..\daemon\cpvparser1.h" />
  24.      <ClInclude Include="..\..\daemon\daemon_debug.h" />
  25.      <ClInclude Include="..\..\daemon\delegation.h" />
  26.      <ClInclude Include="..\..\daemon\from_kernel.h" />
  27. diff --git a/build.vc19/nfsd/nfsd.vcxproj.filters b/build.vc19/nfsd/nfsd.vcxproj.filters
  28. index d0ebad9..cc1ee27 100644
  29. --- a/build.vc19/nfsd/nfsd.vcxproj.filters
  30. +++ b/build.vc19/nfsd/nfsd.vcxproj.filters
  31. @@ -24,6 +24,9 @@
  32.      <ClCompile Include="..\..\daemon\callback_xdr.c">
  33.        <Filter>Source Files</Filter>
  34.      </ClCompile>
  35. +    <ClCompile Include="..\..\daemon\cpvparser1.c">
  36. +      <Filter>Source Files</Filter>
  37. +    </ClCompile>
  38.      <ClCompile Include="..\..\daemon\daemon_debug.c">
  39.        <Filter>Source Files</Filter>
  40.      </ClCompile>
  41. @@ -39,6 +42,9 @@
  42.      <ClCompile Include="..\..\daemon\idmap.c">
  43.        <Filter>Source Files</Filter>
  44.      </ClCompile>
  45. +    <ClCompile Include="..\..\daemon\idmap_cygwin.c">
  46. +      <Filter>Source Files</Filter>
  47. +    </ClCompile>
  48.      <ClCompile Include="..\..\daemon\lock.c">
  49.        <Filter>Source Files</Filter>
  50.      </ClCompile>
  51. @@ -125,6 +131,9 @@
  52.      </ClCompile>
  53.    </ItemGroup>
  54.    <ItemGroup>
  55. +    <ClInclude Include="..\..\daemon\cpvparser1.h">
  56. +      <Filter>Header Files</Filter>
  57. +    </ClInclude>
  58.      <ClInclude Include="..\..\daemon\daemon_debug.h">
  59.        <Filter>Header Files</Filter>
  60.      </ClInclude>
  61. diff --git a/cygwin_idmapper.ksh b/cygwin_idmapper.ksh
  62. new file mode 100644
  63. index 0000000..4b96ecf
  64. --- /dev/null
  65. +++ b/cygwin_idmapper.ksh
  66. @@ -0,0 +1,124 @@
  67. +#!/bin/ksh93
  68. +
  69. +set -o nounset
  70. +typeset IFS=''
  71. +
  72. +#
  73. +# global variables
  74. +# (stored in compound variable so we
  75. +# can do a $ print -u2 -v c # for debugging)
  76. +#
  77. +compound c=(
  78. +        mode="$1"
  79. +        name="$2"
  80. +)
  81. +
  82. +compound -A localusers=(
  83. +       ["roland_mainz"]=(
  84. +               localaccoutname='roland_mainz'
  85. +               localuid=197608
  86. +               localgid=197121
  87. +       )
  88. +       ["siegfried_wulsch"]=(
  89. +               localaccoutname='siegfried_wulsch'
  90. +               localuid=197609
  91. +               localgid=197121
  92. +       )
  93. +       ["SYSTEM"]=(
  94. +               localaccoutname='SYSTEM'
  95. +               localuid=18
  96. +               localgid=18
  97. +       )
  98. +       ["rmainz"]=(
  99. +               localaccoutname='rmainz'
  100. +               localuid=1616
  101. +               localgid=1616
  102. +       )
  103. +       ["swulsch"]=(
  104. +               localaccoutname='swulsch'
  105. +               localuid=1818
  106. +               localgid=1818
  107. +       )
  108. +       ["root"]=(
  109. +               localaccoutname='root'
  110. +               localuid=0
  111. +               localgid=0
  112. +       )
  113. +       ["nobody"]=(
  114. +               localaccoutname='nobody'
  115. +               localuid=65534
  116. +               localgid=65534
  117. +       )
  118. +)
  119. +
  120. +compound -A localgroups=(
  121. +       ["Kein"]=(
  122. +               localaccoutname='Kein'
  123. +               localgid=197121
  124. +       )
  125. +       ["rmainz"]=(
  126. +               localaccoutname='rmainz'
  127. +               localuid=1616
  128. +               localgid=1616
  129. +       )
  130. +       ["swulsch"]=(
  131. +               localaccoutname='swulsch'
  132. +               localuid=1818
  133. +               localgid=1818
  134. +       )
  135. +       ["root"]=(
  136. +               localaccoutname='root'
  137. +               localuid=0
  138. +               localgid=0
  139. +       )
  140. +       ["nogroup"]=(
  141. +               localaccoutname='nogroup'
  142. +               localuid=65534
  143. +               localgid=65534
  144. +       )
  145. +)
  146. +
  147. +case "${c.mode}" in
  148. +       'nfsserveruser2localaccount')
  149. +               if [[ "${c.name}" == ~(Elr)[[:digit:]]+ ]] ; then
  150. +                       for s in "${!localusers[@]}" ; do
  151. +                               if (( localusers[$s].localuid == c.name )) ; then
  152. +                                       print -v localusers[$s]
  153. +                                       exit 0
  154. +                               fi
  155. +                       done
  156. +               fi
  157. +
  158. +               if [[ -v localusers["${c.name}"] ]] ; then
  159. +                       print -v localusers["${c.name}"]
  160. +                       exit 0
  161. +               else
  162. +                       print -u2 -f "cygwin_idmapper.ksh: Account '%s' not found.\n" "${c.name}"
  163. +                       exit 1
  164. +               fi
  165. +               ;;
  166. +       'nfsserveruser2localgroup')
  167. +               if [[ "${c.name}" == ~(Elr)[[:digit:]]+ ]] ; then
  168. +                       for s in "${!localgroups[@]}" ; do
  169. +                               if (( localgroups[$s].localgid == c.name )) ; then
  170. +                                       print -v localgroups[$s]
  171. +                                       exit 0
  172. +                               fi
  173. +                       done
  174. +               fi
  175. +
  176. +               if [[ -v localgroups["${c.name}"] ]] ; then
  177. +                       print -v localgroups["${c.name}"]
  178. +                       exit 0
  179. +               else
  180. +                       print -u2 -f "cygwin_idmapper.ksh: Account '%s' not found.\n" "${c.name}"
  181. +                       exit 1
  182. +               fi
  183. +               ;;
  184. +       *)
  185. +               print -u2 "cygwin_idmapper.ksh: Unknown mode"
  186. +               exit 1
  187. +               ;;
  188. +esac
  189. +
  190. +# EOF.
  191. diff --git a/daemon/acl.c b/daemon/acl.c
  192. index 1d1eac4..86e0d5a 100644
  193. --- a/daemon/acl.c
  194. +++ b/daemon/acl.c
  195. @@ -21,6 +21,7 @@
  196.  
  197.  #include <Windows.h>
  198.  #include <stdio.h>
  199. +#include <time.h>
  200.  #include <strsafe.h>
  201.  #include <sddl.h>
  202.  
  203. @@ -198,10 +199,138 @@ BOOL allocate_unixgroup_sid(unsigned long gid, PSID *pSid)
  204.  }
  205.  #endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
  206.  
  207. -static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_len, PSID *sid, LPCSTR name)
  208. +
  209. +/* fixme: should be in sys/nfs41_build_features.h */
  210. +#define USE_SID_CACHE 1
  211. +
  212. +
  213. +#ifdef USE_SID_CACHE
  214. +#define SID_CACHE_SIZE 20
  215. +#define SID_CACHE_TTL 600
  216. +
  217. +typedef struct _sid_cache_entry
  218. +{
  219. +    char    name[256]; /* fixme: size correct ? */
  220. +    PSID    sid;
  221. +    DWORD   sid_len;
  222. +    time_t  timestamp;
  223. +} sid_cache_entry;
  224. +
  225. +typedef struct _sid_cache
  226. +{
  227. +    CRITICAL_SECTION    lock;
  228. +    sid_cache_entry     entries[SID_CACHE_SIZE];
  229. +    ssize_t             cacheIndex;
  230. +} sid_cache;
  231. +
  232. +/* fixme: need function to deallocate this */
  233. +sid_cache user_sid_cache = { 0 };
  234. +
  235. +static volatile int cache_once = 0;
  236. +
  237. +/* copy SID |value| into cache */
  238. +void sid_addcache(sid_cache *cache, const char* name, PSID *value)
  239. +{
  240. +    int i;
  241. +    int oldestEntryIndex;
  242. +    time_t currentTimestamp;
  243. +
  244. +    /* fixme: this is not really threadsafe!! */
  245. +    if (cache_once++ == 0) {
  246. +        InitializeCriticalSection(&cache->lock);
  247. +        dprintf(0, "SID cache init\n");
  248. +    }
  249. +
  250. +    EnterCriticalSection(&cache->lock);
  251. +    currentTimestamp = time(NULL);
  252. +
  253. +    /* Find the oldest valid cache entry */
  254. +    oldestEntryIndex = -1;
  255. +    for (i = 0; i < SID_CACHE_SIZE; i++) {
  256. +        if ((cache->entries[i].sid == NULL) || (cache->entries[i].timestamp < (currentTimestamp - SID_CACHE_TTL))) {
  257. +            oldestEntryIndex = i;
  258. +            break;
  259. +        }
  260. +    }
  261. +
  262. +    /* If no valid entry was found, overwrite the oldest entry */
  263. +    if (oldestEntryIndex == -1) {
  264. +        oldestEntryIndex = cache->cacheIndex;
  265. +    }
  266. +
  267. +    /* Replace the cache entry */
  268. +    DWORD sid_len = GetLengthSid(value);
  269. +    PSID malloced_sid = malloc(sid_len);
  270. +    if (!malloced_sid)
  271. +        goto done;
  272. +    if (!CopySid(sid_len, malloced_sid, value)) {
  273. +        free(malloced_sid);
  274. +        goto done;
  275. +    }
  276. +
  277. +    sid_cache_entry *e = &cache->entries[oldestEntryIndex];
  278. +
  279. +    e->sid_len = sid_len;
  280. +    if (e->sid)
  281. +        free(e->sid);
  282. +    e->sid = malloced_sid;
  283. +    (void)strcpy(e->name, name);
  284. +    e->timestamp = currentTimestamp;
  285. +
  286. +    cache->cacheIndex = (cache->cacheIndex + 1) % SID_CACHE_SIZE;
  287. +
  288. +done:
  289. +    LeaveCriticalSection(&cache->lock);
  290. +}
  291. +
  292. +/* return |malloc()|'ed copy of SID from cache entry */
  293. +PSID *sid_getfromcache(sid_cache *cache, const char *name)
  294.  {
  295. +    int i;
  296. +    time_t currentTimestamp;
  297. +    PSID *ret_sid = NULL;
  298. +
  299. +    /* fixme: this is not really threadsafe!! */
  300. +    if (cache_once++ == 0) {
  301. +        InitializeCriticalSection(&cache->lock);
  302. +        dprintf(0, "SID cache init\n");
  303. +    }
  304. +
  305. +    EnterCriticalSection(&cache->lock);
  306. +    currentTimestamp = time(NULL);
  307. +
  308. +    for (i = 0; i < SID_CACHE_SIZE; i++) {
  309. +        sid_cache_entry *e = &cache->entries[i];
  310. +
  311. +        if ((!strcmp(e->name, name)) && (e->timestamp >= (currentTimestamp - SID_CACHE_TTL))) {
  312. +            PSID malloced_sid = malloc(e->sid_len);
  313. +
  314. +            if (!malloced_sid)
  315. +                goto done;
  316. +
  317. +            if (!CopySid(e->sid_len, malloced_sid, e->sid)) {
  318. +                free(malloced_sid);
  319. +                goto done;
  320. +            }
  321. +
  322. +            ret_sid = malloced_sid;
  323. +            goto done;
  324. +        }
  325. +    }
  326. +
  327. +done:
  328. +    LeaveCriticalSection(&cache->lock);
  329. +    return ret_sid;
  330. +}
  331. +#endif
  332. +
  333. +static int map_nfs4servername_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_len, PSID *sid, LPCSTR name)
  334. +{
  335. +    const char *orig_name = name;
  336. +
  337.      int status = ERROR_INTERNAL_ERROR;
  338.      SID_NAME_USE sid_type;
  339. +    char name_buff[256+2];
  340.      LPSTR tmp_buf = NULL;
  341.      DWORD tmp = 0;
  342.  #ifdef NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID
  343. @@ -210,24 +339,38 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
  344.  #endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
  345.  
  346.  #ifdef NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID
  347. +    /* use our own idmapper script to map nfsv4 owner string to local Windows account */
  348.      if (query & OWNER_SECURITY_INFORMATION) {
  349. -        if (!strcmp(name, "rmainz")) {
  350. -            name = "roland_mainz";
  351. -            dprintf(ACLLVL, "map_name_2_sid: remap rmainz --> roland_mainz\n");
  352. -        }
  353. -        else if (!strcmp(name, "197608")) {
  354. -            name = "roland_mainz";
  355. -            dprintf(ACLLVL, "map_name_2_sid: remap 197608 --> roland_mainz\n");
  356. +        uid_t udummy = -1;
  357. +        gid_t gdummy = -1;
  358. +
  359. +int cygwin_getent_passwd(const char *name, char *res_loginname, uid_t *res_uid, gid_t *res_gid);
  360. +
  361. +#ifdef USE_SID_CACHE
  362. +        if (*sid = sid_getfromcache(&user_sid_cache, name)) {
  363. +            *sid_len = GetLengthSid(*sid);
  364. +//            dprintf(0, "map_nfs4servername_2_sid: returning cached sid for '%s'\n", name);
  365. +            return 0;
  366. +        }
  367. +#endif /* USE_SID_CACHE */
  368. +
  369. +#ifndef USE_SID_CACHE
  370. +        /* gisburn: fixme: We must cache this, or the performance impact will be devastating!! */
  371. +#endif /* !USE_SID_CACHE */
  372. +        if (!cygwin_getent_passwd(name, name_buff, &udummy, &gdummy)) {
  373. +            if (strcmp(name, name_buff)) {
  374. +                dprintf(0,
  375. +                    "map_nfs4servername_2_sid: remap '%s' --> '%s'\n",
  376. +                    name,
  377. +                    name_buff);
  378. +                name = name_buff;
  379.              }
  380. -        else if (!strcmp(name, "1616")) {
  381. -            name = "roland_mainz";
  382. -            dprintf(ACLLVL, "map_name_2_sid: remap 1616 --> roland_mainz\n");
  383.          }
  384.      }
  385.  #endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
  386.  
  387.      status = LookupAccountName(NULL, name, NULL, sid_len, NULL, &tmp, &sid_type);
  388. -    dprintf(ACLLVL, "map_name_2_sid(query=%x,name='%s'): LookupAccountName returned %d "
  389. +    dprintf(ACLLVL, "map_nfs4servername_2_sid(query=%x,name='%s'): LookupAccountName returned %d "
  390.              "GetLastError %d name len %d domain len %d\n",
  391.              query, name, status, GetLastError(), *sid_len, tmp);
  392.      if (status)
  393. @@ -248,7 +391,7 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
  394.                                      &tmp, &sid_type);
  395.          free(tmp_buf);
  396.          if (!status) {
  397. -            eprintf("map_name_2_sid(query=%x,name='%s'): LookupAccountName failed "
  398. +            eprintf("map_nfs4servername_2_sid(query=%x,name='%s'): LookupAccountName failed "
  399.                      "with %d\n", query, name, GetLastError());
  400.              goto out_free_sid;
  401.          } else {
  402. @@ -256,13 +399,13 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
  403.              LPSTR ssid = NULL;
  404.              if (IsValidSid(*sid))
  405.                  if (ConvertSidToStringSidA(*sid, &ssid))
  406. -                    dprintf(1, "map_name_2_sid: sid_type = %d SID %s\n",
  407. +                    dprintf(1, "map_nfs4servername_2_sid: sid_type = %d SID %s\n",
  408.                              sid_type, ssid);
  409.                  else
  410. -                    dprintf(1, "map_name_2_sid: ConvertSidToStringSidA failed "
  411. +                    dprintf(1, "map_nfs4servername_2_sid: ConvertSidToStringSidA failed "
  412.                              "with %d\n", GetLastError());
  413.              else
  414. -                dprintf(1, "map_name_2_sid: Invalid Sid ?\n");
  415. +                dprintf(1, "map_nfs4servername_2_sid: Invalid Sid ?\n");
  416.              if (ssid) LocalFree(ssid);
  417.  #endif
  418.          }
  419. @@ -270,7 +413,7 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
  420.          break;
  421.      case ERROR_NONE_MAPPED:
  422.  #ifdef NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID
  423. -        dprintf(1, "map_name_2_sid(query=%x,name='%s'): none mapped, "
  424. +        dprintf(1, "map_nfs4servername_2_sid(query=%x,name='%s'): none mapped, "
  425.              "trying Unix_User+/Unix_Group+ mapping\n",
  426.              query, name);
  427.  
  428. @@ -286,7 +429,7 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
  429.                  user_uid = map_uid;
  430.              }
  431.              else {
  432. -                dprintf(1, "map_name_2_sid(query=%x,name='%s'): nfs41_idmap_name_to_ids() failed\n",
  433. +                dprintf(1, "map_nfs4servername_2_sid(query=%x,name='%s'): nfs41_idmap_name_to_ids() failed\n",
  434.                      query, name);
  435.                  /* fixme: try harder here, "1234" should to to |atol()| */
  436.              }
  437. @@ -302,7 +445,7 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
  438.                  group_gid = map_gid;
  439.              }
  440.              else {
  441. -                dprintf(1, "map_name_2_sid(query=%x,name='%s'): nfs41_idmap_group_to_gid() failed\n",
  442. +                dprintf(1, "map_nfs4servername_2_sid(query=%x,name='%s'): nfs41_idmap_group_to_gid() failed\n",
  443.                      query, name);
  444.                  /* fixme: try harder here, "1234" should to to |atol()| */
  445.              }
  446. @@ -310,14 +453,15 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
  447.  
  448.          if (user_uid != -1) {
  449.              if (allocate_unixuser_sid(user_uid, sid)) {
  450. -                dprintf(ACLLVL, "map_name_2_sid(query=%x,name='%s'): "
  451. +                dprintf(ACLLVL, "map_nfs4servername_2_sid(query=%x,name='%s'): "
  452.                      "allocate_unixuser_sid(uid=%ld) success\n",
  453.                      query, name, user_uid);
  454. -                return ERROR_SUCCESS;
  455. +                status = ERROR_SUCCESS;
  456. +                goto out;
  457.              }
  458.  
  459.              status = GetLastError();
  460. -            dprintf(ACLLVL, "map_name_2_sid(query=%x,name='%s'): "
  461. +            dprintf(ACLLVL, "map_nfs4servername_2_sid(query=%x,name='%s'): "
  462.                  "allocate_unixuser_sid(uid=%ld) failed, error=%d\n",
  463.                  query, name, user_uid, status);
  464.              return status;
  465. @@ -325,21 +469,22 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
  466.  
  467.          if (group_gid != -1) {
  468.              if (allocate_unixgroup_sid(group_gid, sid)) {
  469. -                dprintf(ACLLVL, "map_name_2_sid(query=%x,name='%s'): "
  470. +                dprintf(ACLLVL, "map_nfs4servername_2_sid(query=%x,name='%s'): "
  471.                      "allocate_unixgroup_sid(gid=%ld) success\n",
  472.                      query, name, group_gid);
  473. -                return ERROR_SUCCESS;
  474. +                status = ERROR_SUCCESS;
  475. +                goto out;
  476.              }
  477.  
  478.              status = GetLastError();
  479. -            dprintf(ACLLVL, "map_name_2_sid(query=%x,name='%s'): "
  480. +            dprintf(ACLLVL, "map_nfs4servername_2_sid(query=%x,name='%s'): "
  481.                  "allocate_unixgroup_sid(gid=%ld) failed, error=%d\n",
  482.                  query, name, group_gid, status);
  483.              return status;
  484.          }
  485.  #endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
  486.  
  487. -        dprintf(1, "map_name_2_sid(query=%x,name='%s'): none mapped, "
  488. +        dprintf(1, "map_nfs4servername_2_sid(query=%x,name='%s'): none mapped, "
  489.              "using WinNullSid mapping\n",
  490.              query, name);
  491.  
  492. @@ -348,11 +493,20 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
  493.              goto out_free_sid;
  494.          break;
  495.      default:
  496. -        dprintf(1, "map_name_2_sid(query=%x,name='%s'): error %d not handled\n",
  497. +        dprintf(1, "map_nfs4servername_2_sid(query=%x,name='%s'): error %d not handled\n",
  498.              query, name, GetLastError());
  499.          break;
  500.      }
  501.  out:
  502. +#ifdef USE_SID_CACHE
  503. +    if (*sid) {
  504. +        /* fixme: No other flags in |query| must be set!! */
  505. +        if (query & OWNER_SECURITY_INFORMATION) {
  506. +            sid_addcache(&user_sid_cache, orig_name, *sid);
  507. +        }
  508. +    }
  509. +#endif /* USE_SID_CACHE */
  510. +
  511.      return status;
  512.  out_free_sid:
  513.      status = GetLastError();
  514. @@ -417,7 +571,7 @@ static int convert_nfs4acl_2_dacl(nfs41_daemon_globals *nfs41dg,
  515.              goto out;
  516.          }
  517.          if (!flag) {
  518. -            status = map_name_2_sid(nfs41dg,
  519. +            status = map_nfs4servername_2_sid(nfs41dg,
  520.                  0xFFFF /* fixme: Unknown whether user or group */,
  521.                  &sid_len, &sids[i], acl->aces[i].who);
  522.              if (status) {
  523. @@ -534,7 +688,7 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
  524.          dprintf(ACLLVL, "handle_getacl: OWNER_SECURITY_INFORMATION: for user=%s "
  525.                  "domain=%s\n", info.owner, domain?domain:"<null>");
  526.          sid_len = 0;
  527. -        status = map_name_2_sid(nfs41dg,
  528. +        status = map_nfs4servername_2_sid(nfs41dg,
  529.              OWNER_SECURITY_INFORMATION, &sid_len, &osid, info.owner);
  530.          if (status)
  531.              goto out;
  532. @@ -552,7 +706,7 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
  533.          dprintf(ACLLVL, "handle_getacl: GROUP_SECURITY_INFORMATION: for %s "
  534.                  "domain=%s\n", info.owner_group, domain?domain:"<null>");
  535.          sid_len = 0;
  536. -        status = map_name_2_sid(nfs41dg,
  537. +        status = map_nfs4servername_2_sid(nfs41dg,
  538.              GROUP_SECURITY_INFORMATION, &sid_len, &gsid, info.owner_group);
  539.          if (status)
  540.              goto out;
  541. diff --git a/daemon/cpvparser1.c b/daemon/cpvparser1.c
  542. new file mode 100644
  543. index 0000000..285fc76
  544. --- /dev/null
  545. +++ b/daemon/cpvparser1.c
  546. @@ -0,0 +1,361 @@
  547. +
  548. +/*
  549. + * MIT License
  550. + *
  551. + * Copyright (c) 2023 Roland Mainz <roland.mainz@nrubsig.org>
  552. + *
  553. + * Permission is hereby granted, free of charge, to any person obtaining a copy
  554. + * of this software and associated documentation files (the "Software"), to deal
  555. + * in the Software without restriction, including without limitation the rights
  556. + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  557. + * copies of the Software, and to permit persons to whom the Software is
  558. + * furnished to do so, subject to the following conditions:
  559. + *
  560. + * The above copyright notice and this permission notice shall be included in all
  561. + * copies or substantial portions of the Software.
  562. + *
  563. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  564. + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  565. + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  566. + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FORalloca ANY CLAIM, DAMAGES OR OTHER
  567. + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  568. + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  569. + * SOFTWARE.
  570. + */
  571. +
  572. +/*
  573. + * cpvparser1.c - simple ksh93 compound variable parsing
  574. + *
  575. + * It basically reads the output of $ print -v ... # like this:
  576. + * ---- snip ----
  577. + * $ ksh93 -c 'compound c=( va=1 vb=hello ) ; print -v c'
  578. + * (
  579. + *        va=1
  580. + *        vb=hello
  581. + * )
  582. + * ---- snip ----
  583. + *
  584. + * ToDo:
  585. + * - arrays (indexed, sparse indexed and associative)
  586. + * - multibyte characters
  587. + *
  588. + * Written by Roland Mainz <roland.mainz@nrubsig.org>
  589. + */
  590. +
  591. +#include <stdlib.h>
  592. +#include <stdbool.h>
  593. +#include <string.h>
  594. +#include <stdio.h>
  595. +#include <ctype.h>
  596. +
  597. +#include "cpvparser1.h"
  598. +
  599. +#ifdef _WIN32
  600. +#define strdup(s) _strdup(s)
  601. +#endif
  602. +
  603. +/* private data! */
  604. +typedef struct cpv_parse_context {
  605. +       const char *start_string;
  606. +       const char *curr_string;
  607. +       size_t max_name_val_size;
  608. +       unsigned long flags;
  609. +} cpv_parse_context;
  610. +
  611. +
  612. +void *cpv_create_parser(const char *s, unsigned long flags, ...)
  613. +{
  614. +       cpv_parse_context *cpc;
  615. +
  616. +       cpc = calloc(1, sizeof(cpv_parse_context));
  617. +       if (!cpc)
  618. +               goto fail;
  619. +
  620. +       cpc->start_string = strdup(s);
  621. +       if (!cpc->start_string)
  622. +               goto fail;
  623. +
  624. +       cpc->curr_string = cpc->start_string;
  625. +       cpc->max_name_val_size = strlen(cpc->start_string);
  626. +       cpc->flags = flags;
  627. +
  628. +       return (cpc);
  629. +
  630. +fail:
  631. +       if (cpc) {
  632. +               free((void *)cpc->start_string);
  633. +               free(cpc);
  634. +       }
  635. +
  636. +       return NULL;
  637. +}
  638. +
  639. +void cpv_free_parser(void *v_cpc)
  640. +{
  641. +       cpv_parse_context *cpc = (cpv_parse_context *)v_cpc;
  642. +       if (cpc) {
  643. +               free((void *)cpc->start_string);
  644. +               free(cpc);
  645. +       }
  646. +}
  647. +
  648. +int cpv_read_cpv_header(void *v_cpc)
  649. +{
  650. +       cpv_parse_context *cpc = (cpv_parse_context *)v_cpc;
  651. +       const char *s = cpc->curr_string;
  652. +
  653. +skipspaces:
  654. +       while((*s != '\0') && isspace(*s))
  655. +               s++;
  656. +
  657. +       /*
  658. +        * skip POSIX-style '#' comments
  659. +        * (allowed since this is based on POSIX sh(1) syntax)
  660. +        */
  661. +       if (*s == '#') {
  662. +               s++;
  663. +               /* ignore everything until the end-of-line */
  664. +               while((*s != '\0') && (*s != '\n'))
  665. +                       s++;
  666. +               goto skipspaces;
  667. +       }
  668. +
  669. +       if (*s == '(') {
  670. +               cpc->curr_string=++s;
  671. +               if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
  672. +                       (void)fprintf(stderr, "cpv_read_cpv_header: begin-of-cpv\n");
  673. +               }
  674. +               return 0;
  675. +       }
  676. +
  677. +       if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
  678. +               (void)fprintf(stderr, "cpv_read_cpv_header: end-of-string, should not happen\n");
  679. +       }
  680. +       return 1;
  681. +}
  682. +
  683. +int cpv_parse_name_val(void *v_cpc, cpv_name_val *cpv_nv)
  684. +{
  685. +       cpv_parse_context *cpc = (cpv_parse_context *)v_cpc;
  686. +#ifdef _WIN32
  687. +       char *namebuff = _alloca(cpc->max_name_val_size+1);
  688. +       char *valbuff  = _alloca(cpc->max_name_val_size+1);
  689. +#else
  690. +       char namebuff[cpc->max_name_val_size+1];
  691. +       char valbuff[cpc->max_name_val_size+1];
  692. +#endif
  693. +
  694. +       const char *s = cpc->curr_string;
  695. +
  696. +       char *n; /* pointer in |namebuff| */
  697. +       char *v; /* pointer in |valbuff| */
  698. +
  699. +skipspaces:
  700. +       while((*s != '\0') && isspace(*s))
  701. +               s++;
  702. +
  703. +       /*
  704. +        * skip POSIX-style '#' comments
  705. +        * (allowed since this is based on POSIX sh(1) syntax)
  706. +        */
  707. +       if (*s == '#') {
  708. +               s++;
  709. +               /* ignore everything until the end-of-line */
  710. +               while((*s != '\0') && (*s != '\n'))
  711. +                       s++;
  712. +               goto skipspaces;
  713. +       }
  714. +
  715. +       if (*s == '\0') {
  716. +               if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
  717. +                       (void)fprintf(stderr, "cpv_parse_name_val: "
  718. +                               "error: end-of-string, should not happen\n");
  719. +               }
  720. +               return 1;
  721. +       }
  722. +
  723. +       /* cpv == "( foo=bar blabla=text )"*/
  724. +       if (*s == ')') {
  725. +               if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
  726. +                       (void)fprintf(stderr, "cpv_parse_name_val: end-of-cpv (OK)\n");
  727. +               }
  728. +               return 1;
  729. +       }
  730. +
  731. +parse_varname:
  732. +       /*
  733. +        * start parsing variable name
  734. +        */
  735. +
  736. +       /* variable names MUST start with a letter! */
  737. +       if (!isalpha(*s)) {
  738. +               if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
  739. +                       (void)fprintf(stderr,
  740. +                               "cpv_parse_name_val: parser error, first char "
  741. +                               "in variable name not isalpha(c=%c)\n",
  742. +                               *s);
  743. +               }
  744. +               return 1;
  745. +       }
  746. +
  747. +       n = namebuff;
  748. +       while((*s != '\0') && isalnum(*s))
  749. +               *n++ = *s++;
  750. +       *n = '\0';
  751. +
  752. +       /*
  753. +        * skip typed member varables
  754. +        * (e.g. "typeset ", "typeset -i ", "typeset -l -i2" etc.)
  755. +        */
  756. +       if (isspace(*s)) {
  757. +               if ((!strcmp(namebuff, "typeset")) ||
  758. +                       (!strcmp(namebuff, "integer")) ||
  759. +                       (!strcmp(namebuff, "float")) ||
  760. +                       (!strcmp(namebuff, "compound"))) {
  761. +skip_typeset_options:
  762. +                       while(isspace(*s))
  763. +                               s++;
  764. +                       if (*s == '-') {
  765. +                               s++;
  766. +                               while(isalnum(*s))
  767. +                                       s++;
  768. +                               goto skip_typeset_options;
  769. +                       }
  770. +
  771. +                       goto parse_varname;
  772. +               }
  773. +       }
  774. +
  775. +       /* handle '=' */
  776. +       if (*s != '=') {
  777. +               if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
  778. +                       (void)fprintf(stderr, "cpv_parse_name_val: "
  779. +                               "parser error, expected '=', got '%c'.\n",
  780. +                               *s);
  781. +               }
  782. +               return 1;
  783. +       }
  784. +
  785. +       s++; /* skip '=' */
  786. +
  787. +       /*
  788. +        * start parsing variable value
  789. +        */
  790. +       bool in_doublequotes=false;
  791. +       bool in_singlequotes=false;
  792. +       v = valbuff;
  793. +val_quotes:
  794. +       if (in_singlequotes) {
  795. +               while(*s != '\0') {
  796. +                       if (*s == '\'') {
  797. +                               in_singlequotes = false;
  798. +                               s++;
  799. +                               goto val_quotes;
  800. +                       }
  801. +
  802. +                       if ((*s == '\\') && (*(s+1) != '\0')) {
  803. +                               /*
  804. +                                * fixme: should support \ooo octals,
  805. +                                * \u[hex] unicode and \w[hex] wchar
  806. +                                */
  807. +                               s++;
  808. +                       }
  809. +                       *v++ = *s++;
  810. +               }
  811. +       }
  812. +       else if (in_doublequotes) {
  813. +               while(*s != '\0') {
  814. +                       if (*s == '"') {
  815. +                               in_doublequotes = false;
  816. +                               s++;
  817. +                               goto val_quotes;
  818. +                       }
  819. +
  820. +                       if ((*s == '\\') && (*(s+1) != '\0')) {
  821. +                               /*
  822. +                                * fixme: should support \ooo octals,
  823. +                                * \u[hex] unicode and \w[hex] wchar
  824. +                                */
  825. +                               s++;
  826. +                       }
  827. +
  828. +                       *v++ = *s++;
  829. +               }
  830. +       }
  831. +       else
  832. +       {
  833. +               while((*s != '\0') && (!isspace(*s))) {
  834. +                       if (*s == '"') {
  835. +                               in_doublequotes = true;
  836. +                               s++;
  837. +                               goto val_quotes;
  838. +                       }
  839. +
  840. +                       if (*s == '\'') {
  841. +                               in_singlequotes = true;
  842. +                               s++;
  843. +                               goto val_quotes;
  844. +                       }
  845. +
  846. +                       if ((*s == '\\') && (*(s+1) != '\0')) {
  847. +                               /*
  848. +                                * fixme: should support \ooo octals,
  849. +                                * \u[hex] unicode and \w[hex] wchar
  850. +                                */
  851. +                               s++;
  852. +                       }
  853. +                       *v++ = *s++;
  854. +               }
  855. +       }
  856. +
  857. +       if (in_singlequotes) {
  858. +               if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
  859. +                       (void)fprintf(stderr, "cpv_parse_name_val: "
  860. +                               "parsererror, still in single quotes "
  861. +                               "at the end\n");
  862. +               }
  863. +               return 1;
  864. +       }
  865. +       if (in_doublequotes) {
  866. +               if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
  867. +                       (void)fprintf(stderr, "cpv_parse_name_val: "
  868. +                               "parser error, still in double quotes "
  869. +                               "at the end\n");
  870. +               }
  871. +               return 1;
  872. +       }
  873. +
  874. +       *v = '\0';
  875. +
  876. +#if 0
  877. +       (void)printf("cpv_parse_name_val: name='%s', value='%s'\n",
  878. +               namebuff, valbuff);
  879. +#endif
  880. +
  881. +       cpv_nv->cpv_name   = strdup(namebuff);
  882. +       cpv_nv->cpv_value  = strdup(valbuff);
  883. +
  884. +       if ((cpv_nv->cpv_name == NULL) || (cpv_nv->cpv_value == NULL)) {
  885. +               cpv_free_name_val_data(cpv_nv);
  886. +               if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
  887. +                       (void)fprintf(stderr, "cpv_parse_name_val: "
  888. +                               "parser error, out of memory\n");
  889. +               }
  890. +               return 2;
  891. +       }
  892. +
  893. +       cpc->curr_string = s;
  894. +
  895. +       return 0;
  896. +}
  897. +
  898. +void cpv_free_name_val_data(cpv_name_val *cnv)
  899. +{
  900. +       if (!cnv)
  901. +               return;
  902. +
  903. +       free((void *)cnv->cpv_name);
  904. +       free((void *)cnv->cpv_value);
  905. +       cnv->cpv_name = NULL;
  906. +       cnv->cpv_value = NULL;
  907. +}
  908. diff --git a/daemon/cpvparser1.h b/daemon/cpvparser1.h
  909. new file mode 100644
  910. index 0000000..a6ed609
  911. --- /dev/null
  912. +++ b/daemon/cpvparser1.h
  913. @@ -0,0 +1,64 @@
  914. +
  915. +/*
  916. + * MIT License
  917. + *
  918. + * Copyright (c) 2023 Roland Mainz <roland.mainz@nrubsig.org>
  919. + *
  920. + * Permission is hereby granted, free of charge, to any person obtaining a copy
  921. + * of this software and associated documentation files (the "Software"), to deal
  922. + * in the Software without restriction, including without limitation the rights
  923. + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  924. + * copies of the Software, and to permit persons to whom the Software is
  925. + * furnished to do so, subject to the following conditions:
  926. + *
  927. + * The above copyright notice and this permission notice shall be included in all
  928. + * copies or substantial portions of the Software.
  929. + *
  930. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  931. + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  932. + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  933. + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  934. + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  935. + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  936. + * SOFTWARE.
  937. + */
  938. +
  939. +/*
  940. + * cpvparser1.h - simple ksh93 compound variable parsing
  941. + *
  942. + * It basically reads the output of $ print -v ... # like this:
  943. + * ---- snip ----
  944. + * $ ksh93 -c 'compound c=( va=1 vb=hello ) ; print -v c'
  945. + * (
  946. + *        va=1
  947. + *        vb=hello
  948. + * )
  949. + * ---- snip ----
  950. + *
  951. + * ToDo:
  952. + * - arrays (indexed, sparse indexed and associative)
  953. + * - multibyte characters
  954. + *
  955. + * Written by Roland Mainz <roland.mainz@nrubsig.org>
  956. + */
  957. +
  958. +#ifndef CPV_PARSER_H
  959. +#define CPV_PARSER_H 1
  960. +
  961. +typedef struct cpv_name_val
  962. +{
  963. +       const char *cpv_name;
  964. +       const char *cpv_value;
  965. +} cpv_name_val;
  966. +
  967. +/* Flags for |cpv_create_parser()| */
  968. +#define CPVFLAG_DEBUG_OUTPUT (0x00000008L)
  969. +
  970. +/* prototypes */
  971. +void *cpv_create_parser(const char *s, unsigned long flags, ...);
  972. +void cpv_free_parser(void *);
  973. +int cpv_read_cpv_header(void *);
  974. +void cpv_free_name_val_data(cpv_name_val *);
  975. +int cpv_parse_name_val(void *, cpv_name_val *);
  976. +
  977. +#endif /* !CPV_PARSER_H */
  978. diff --git a/daemon/idmap.c b/daemon/idmap.c
  979. index 00af1fe..0672a85 100644
  980. --- a/daemon/idmap.c
  981. +++ b/daemon/idmap.c
  982. @@ -3,6 +3,7 @@
  983.   *
  984.   * Olga Kornievskaia <aglo@umich.edu>
  985.   * Casey Bodley <cbodley@umich.edu>
  986. + * Roland Mainz <roland.mainz@nrubsig.org>
  987.   *
  988.   * This library is free software; you can redistribute it and/or modify it
  989.   * under the terms of the GNU Lesser General Public License as published by
  990. @@ -33,7 +34,7 @@
  991.  #include "daemon_debug.h"
  992.  
  993.  #define IDLVL 2         /* dprintf level for idmap logging */
  994. -#define CYGWINIDLVL 2   /* dprintf level for idmap logging */
  995. +#define CYGWINIDLVL 0   /* dprintf level for idmap logging */
  996.  
  997.  #define FILTER_LEN 1024
  998.  #define NAME_LEN 32
  999. @@ -133,7 +134,7 @@ static const struct config_option g_options[] = {
  1000.      OPT_ATTR("ldap_attr_gidNumber", "gidNumber", ATTR_GID),
  1001.  
  1002.      /* caching configuration */
  1003. -    OPT_INT("cache_ttl", "60", cache_ttl),
  1004. +    OPT_INT("cache_ttl", "6000", cache_ttl),
  1005.  };
  1006.  
  1007.  
  1008. @@ -376,246 +377,6 @@ out:
  1009.      return status;
  1010.  }
  1011.  
  1012. -#ifdef NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN
  1013. -int cygwin_getent_passwd(const char *name, char *res_loginname, uid_t *res_uid, gid_t *res_gid)
  1014. -{
  1015. -    char cmdbuff[1024];
  1016. -    char passwd_line[1024];
  1017. -    FILE* getent_pipe = NULL;
  1018. -    int res = 1;
  1019. -    unsigned long uid = -1;
  1020. -    unsigned long gid = -1;
  1021. -    struct _cypwent {
  1022. -        char* loginname;
  1023. -        char* passwd;
  1024. -        char* uidstr;
  1025. -        char* gidstr;
  1026. -        char* comment;
  1027. -        char* homedir;
  1028. -        char* shell;
  1029. -    } pwent = { 0 };
  1030. -#define PWENT_ENTRY(var, prevvar) \
  1031. -    (((var) = strchr((prevvar), ':'))?(*(var)++ = '\0',(var)):(NULL))
  1032. -
  1033. -    dprintf(CYGWINIDLVL, "--> cygwin_getent_passwd('%s')\n", name);
  1034. -
  1035. -#if 1
  1036. -    /* hack for testing, map "roland_mainz" to rmainz account */
  1037. -    if ((!strcmp(name, "rmainz")) || (!strcmp(name, "1616"))) {
  1038. -        uid = 1616;
  1039. -        gid = 1616;
  1040. -        pwent.loginname = "rmainz";
  1041. -        goto found;
  1042. -    }
  1043. -    if ((!strcmp(name, "nobody")) || (!strcmp(name, "no+body")) ||
  1044. -        (!strcmp(name, "65534"))) {
  1045. -        uid = 65534;
  1046. -        gid = 65534;
  1047. -        pwent.loginname = "no+body"; /* Cygwin-specific */
  1048. -        goto found;
  1049. -    }
  1050. -    if ((!strcmp(name, "root")) || (!strcmp(name, "0"))) {
  1051. -        uid = 0;
  1052. -        gid = 0;
  1053. -        pwent.loginname = "root";
  1054. -        goto found;
  1055. -    }
  1056. -    if ((!strcmp(name, "iam")) || (!strcmp(name, "2010"))) {
  1057. -        uid = 2010;
  1058. -        gid = 2010;
  1059. -        pwent.loginname = "iam";
  1060. -        goto found;
  1061. -    }
  1062. -    if ((!strcmp(name, "swulsch")) || (!strcmp(name, "1818"))) {
  1063. -        uid = 1818;
  1064. -        gid = 1818;
  1065. -        pwent.loginname = "swulsch";
  1066. -        goto found;
  1067. -    }
  1068. -    if ((!strcmp(name, "mwenzel")) || (!strcmp(name, "8239"))) {
  1069. -        uid = 8239;
  1070. -        gid = 8239;
  1071. -        pwent.loginname = "mwenzel";
  1072. -        goto found;
  1073. -    }
  1074. -#endif
  1075. -
  1076. -    /* fixme: better quoting for |name| needed */
  1077. -    (void)snprintf(cmdbuff, sizeof(cmdbuff), "%s passwd \"%s\"",
  1078. -        "C:\\cygwin64\\bin\\getent.exe",
  1079. -        name);
  1080. -    if ((getent_pipe = _popen(cmdbuff, "rt")) == NULL) {
  1081. -        dprintf(CYGWINIDLVL, "cygwin_getent_passwd: /usr/bin/getent failed, errno='%s'\n",
  1082. -            strerror(errno));
  1083. -        goto fail;
  1084. -    }
  1085. -
  1086. -    if (fgets(passwd_line, sizeof(passwd_line), getent_pipe)) {
  1087. -        pwent.loginname = passwd_line;
  1088. -        if (!PWENT_ENTRY(pwent.passwd, pwent.loginname)) goto fail;
  1089. -        if (!PWENT_ENTRY(pwent.uidstr, pwent.passwd)) goto fail;
  1090. -        if (!PWENT_ENTRY(pwent.gidstr, pwent.uidstr)) goto fail;
  1091. -        if (!PWENT_ENTRY(pwent.comment, pwent.gidstr)) goto fail;
  1092. -        if (!PWENT_ENTRY(pwent.homedir, pwent.comment)) goto fail;
  1093. -        PWENT_ENTRY(pwent.shell, pwent.homedir);
  1094. -
  1095. -        errno = 0;
  1096. -        uid = strtol(pwent.uidstr, NULL, 10);
  1097. -        if (errno != 0)
  1098. -            goto fail;
  1099. -
  1100. -        errno = 0;
  1101. -        gid = strtol(pwent.gidstr, NULL, 10);
  1102. -        if (errno != 0)
  1103. -            goto fail;
  1104. -
  1105. -#if 0
  1106. -        dprintf(CYGWINIDLVL, "cygwin_getent_passwd(): name='%s'\n", name);
  1107. -        dprintf(CYGWINIDLVL, "loginname\t='%s'\n", pwent.loginname);
  1108. -        dprintf(CYGWINIDLVL, "passwd\t='%s'\n", pwent.passwd);
  1109. -        dprintf(CYGWINIDLVL, "uidstr\t='%s' (%lu)\n", pwent.uidstr, (unsigned long)uid);
  1110. -        dprintf(CYGWINIDLVL, "gidstr\t='%s' (%lu)\n", pwent.gidstr, (unsigned long)gid);
  1111. -        dprintf(CYGWINIDLVL, "comment\t='%s'\n", pwent.comment);
  1112. -        dprintf(CYGWINIDLVL, "homedir\t='%s'\n", pwent.homedir);
  1113. -        dprintf(CYGWINIDLVL, "shell\t='%s'\n", pwent.shell);
  1114. -#endif
  1115. -
  1116. -found:
  1117. -        if (res_loginname)
  1118. -            (void)strcpy_s(res_loginname, VAL_LEN, pwent.loginname);
  1119. -        *res_uid = uid;
  1120. -        *res_gid = gid;
  1121. -        res = 0;
  1122. -    }
  1123. -
  1124. -fail:
  1125. -    if (getent_pipe)
  1126. -        (void)_pclose(getent_pipe);
  1127. -
  1128. -    if (res == 0) {
  1129. -        dprintf(CYGWINIDLVL, "<-- cygwin_getent_passwd('%s'): "
  1130. -            "returning res_uid=%lu, res_gid=%lu, res_loginname='%s'\n",
  1131. -            name,
  1132. -            (unsigned long)(*res_uid),
  1133. -            (unsigned long)(*res_gid),
  1134. -            res_loginname?res_loginname:"<NULL>");
  1135. -    }
  1136. -    else {
  1137. -        dprintf(CYGWINIDLVL, "<-- cygwin_getent_passwd('%s'): no match found\n",
  1138. -            name);
  1139. -    }
  1140. -
  1141. -    return res;
  1142. -}
  1143. -
  1144. -int cygwin_getent_group(const char* name, char* res_group_name, gid_t* res_gid)
  1145. -{
  1146. -    char cmdbuff[1024];
  1147. -    char group_line[1024];
  1148. -    FILE* getent_pipe = NULL;
  1149. -    int res = 1;
  1150. -    unsigned long gid = -1;
  1151. -    struct _cygrent
  1152. -    {
  1153. -        char* group_name;
  1154. -        char* passwd;
  1155. -        char* gidstr;
  1156. -        char* userlist;
  1157. -    } grent = { 0 };
  1158. -
  1159. -    dprintf(CYGWINIDLVL, "--> cygwin_getent_group('%s')\n", name);
  1160. -
  1161. -#if 1
  1162. -    if ((!strcmp(name, "rmainz")) || (!strcmp(name, "1616"))) {
  1163. -        gid = 1616;
  1164. -        grent.group_name = "rmainz";
  1165. -        goto found;
  1166. -    }
  1167. -    if ((!strcmp(name, "nogroup")) || (!strcmp(name, "no+body")) ||
  1168. -        (!strcmp(name, "65534"))) {
  1169. -        gid = 65534;
  1170. -        grent.group_name = "no+body"; /* Cygwin-specific */
  1171. -        goto found;
  1172. -    }
  1173. -    if ((!strcmp(name, "root")) || (!strcmp(name, "0"))) {
  1174. -        gid = 0;
  1175. -        grent.group_name = "root";
  1176. -        goto found;
  1177. -    }
  1178. -    if ((!strcmp(name, "iam")) || (!strcmp(name, "2010"))) {
  1179. -        gid = 2010;
  1180. -        grent.group_name = "iam";
  1181. -        goto found;
  1182. -    }
  1183. -    if ((!strcmp(name, "swulsch")) || (!strcmp(name, "1818"))) {
  1184. -        gid = 1818;
  1185. -        grent.group_name = "swulsch";
  1186. -        goto found;
  1187. -    }
  1188. -    if ((!strcmp(name, "mwenzel")) || (!strcmp(name, "8239"))) {
  1189. -        gid = 8239;
  1190. -        grent.group_name = "mwenzel";
  1191. -        goto found;
  1192. -    }
  1193. -#endif
  1194. -
  1195. -    /* fixme: better quoting for |name| needed */
  1196. -    (void)snprintf(cmdbuff, sizeof(cmdbuff), "%s group \"%s\"",
  1197. -        "C:\\cygwin64\\bin\\getent.exe",
  1198. -        name);
  1199. -    if ((getent_pipe = _popen(cmdbuff, "rt")) == NULL) {
  1200. -        dprintf(CYGWINIDLVL,
  1201. -            "cygwin_getent_group: /usr/bin/getent failed, errno='%s'\n",
  1202. -            strerror(errno));
  1203. -        goto fail;
  1204. -    }
  1205. -
  1206. -    if (fgets(group_line, sizeof(group_line), getent_pipe))
  1207. -    {
  1208. -        grent.group_name = group_line;
  1209. -        if (!PWENT_ENTRY(grent.passwd, grent.group_name)) goto fail;
  1210. -        if (!PWENT_ENTRY(grent.gidstr, grent.passwd)) goto fail;
  1211. -        PWENT_ENTRY(grent.userlist, grent.gidstr);
  1212. -
  1213. -        errno = 0;
  1214. -        gid = strtol(grent.gidstr, NULL, 10);
  1215. -        if (errno != 0)
  1216. -            goto fail;
  1217. -
  1218. -#if 0
  1219. -        dprintf(CYGWINIDLVL, "cygwin_getent_group(): name='%s'\n", name);
  1220. -        dprintf(CYGWINIDLVL, "group_name\t='%s'\n", grent.group_name);
  1221. -        dprintf(CYGWINIDLVL, "passwd\t='%s'\n", grent.passwd);
  1222. -        dprintf(CYGWINIDLVL, "gidstr\t='%s' (%lu)\n", grent.gidstr, (unsigned long)gid);
  1223. -        dprintf(CYGWINIDLVL, "userlist\t='%s'\n", grent.userlist);
  1224. -#endif
  1225. -
  1226. -found:
  1227. -        if (res_group_name)
  1228. -            (void)strcpy_s(res_group_name, VAL_LEN, grent.group_name);
  1229. -        *res_gid = gid;
  1230. -        res = 0;
  1231. -    }
  1232. -
  1233. -fail:
  1234. -    if (getent_pipe)
  1235. -        (void)_pclose(getent_pipe);
  1236. -
  1237. -    if (res == 0) {
  1238. -        dprintf(CYGWINIDLVL, "<-- cygwin_getent_group('%s'): "
  1239. -            "returning res_gid=%lu, res_group_name='%s'\n",
  1240. -            name, (unsigned long)(*res_gid),
  1241. -            res_group_name?res_group_name:"<NULL>");
  1242. -    }
  1243. -    else {
  1244. -        dprintf(CYGWINIDLVL,
  1245. -            "<-- cygwin_getent_group('%s'): no match found\n",
  1246. -            name);
  1247. -    }
  1248. -
  1249. -    return res;
  1250. -}
  1251. -#endif /* NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN */
  1252.  
  1253.  /* generic cache */
  1254.  typedef struct list_entry* (*entry_alloc_fn)();
  1255. @@ -906,7 +667,7 @@ static int idmap_lookup_user(
  1256.      if (status == NO_ERROR) {
  1257.          /* don't return expired entries; query new attributes
  1258.           * and overwrite the entry with cache_insert() */
  1259. -        if ((time(NULL) - user->last_updated) < context->config.cache_ttl)
  1260. +        if (difftime(time(NULL), user->last_updated) < (double)context->config.cache_ttl)
  1261.              goto out;
  1262.      }
  1263.  #ifndef NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN
  1264. @@ -1060,7 +821,7 @@ static int idmap_lookup_group(
  1265.      if (status == NO_ERROR) {
  1266.          /* don't return expired entries; query new attributes
  1267.           * and overwrite the entry with cache_insert() */
  1268. -        if ((time(NULL) - group->last_updated) < context->config.cache_ttl)
  1269. +        if (difftime(time(NULL), group->last_updated) < (double)context->config.cache_ttl)
  1270.              goto out;
  1271.      }
  1272.  #ifndef NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN
  1273. diff --git a/daemon/idmap_cygwin.c b/daemon/idmap_cygwin.c
  1274. new file mode 100644
  1275. index 0000000..8d62f2f
  1276. --- /dev/null
  1277. +++ b/daemon/idmap_cygwin.c
  1278. @@ -0,0 +1,243 @@
  1279. +/* NFSv4.1 client for Windows
  1280. + * Copyright  2023 Roland Mainz <roland.mainz@nrubsig.org>
  1281. + *
  1282. + * Roland Mainz <roland.mainz@nrubsig.org>
  1283. + *
  1284. + * This library is free software; you can redistribute it and/or modify it
  1285. + * under the terms of the GNU Lesser General Public License as published by
  1286. + * the Free Software Foundation; either version 2.1 of the License, or (at
  1287. + * your option) any later version.
  1288. + *
  1289. + * This library is distributed in the hope that it will be useful, but
  1290. + * without any warranty; without even the implied warranty of merchantability
  1291. + * or fitness for a particular purpose.  See the GNU Lesser General Public
  1292. + * License for more details.
  1293. + *
  1294. + * You should have received a copy of the GNU Lesser General Public License
  1295. + * along with this library; if not, write to the Free Software Foundation,
  1296. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  1297. + */
  1298. +
  1299. +#include <Windows.h>
  1300. +#include <strsafe.h>
  1301. +#include <Winldap.h>
  1302. +#include <stdlib.h> /* for strtoul() */
  1303. +#include <errno.h>
  1304. +#include <time.h>
  1305. +
  1306. +#include "nfs41_build_features.h"
  1307. +#include "idmap.h"
  1308. +#include "nfs41_const.h"
  1309. +#include "list.h"
  1310. +#include "daemon_debug.h"
  1311. +#ifdef NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN
  1312. +#include "cpvparser1.h"
  1313. +#endif /* NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN */
  1314. +
  1315. +#define CYGWINIDLVL 0   /* dprintf level for idmap logging */
  1316. +
  1317. +#define VAL_LEN 257
  1318. +
  1319. +#define CYGWIN_IDMAPPER_SCRIPT \
  1320. +    ("C:\\cygwin64\\bin\\ksh93.exe " \
  1321. +    "/home/roland_mainz/work/msnfs41_uidmapping/ms-nfs41-client/cygwin_idmapper.ksh")
  1322. +
  1323. +
  1324. +#ifdef NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN
  1325. +int cygwin_getent_passwd(const char *name, char *res_loginname, uid_t *res_uid, gid_t *res_gid)
  1326. +{
  1327. +    char cmdbuff[1024];
  1328. +    char buff[2048];
  1329. +    size_t num_buff_read;
  1330. +    FILE* script_pipe = NULL;
  1331. +    int res = 1;
  1332. +    unsigned long uid = -1;
  1333. +    unsigned long gid = -1;
  1334. +    void *cpvp = NULL;
  1335. +    int numcnv = 0;
  1336. +    int i = 0;
  1337. +    cpv_name_val cnv[256] = { 0 };
  1338. +    cpv_name_val *cnv_cur = NULL;
  1339. +    const char *localaccoutname = NULL;
  1340. +
  1341. +    dprintf(CYGWINIDLVL, "--> cygwin_getent_passwd('%s')\n", name);
  1342. +
  1343. +    /* fixme: better quoting for |name| needed */
  1344. +    (void)snprintf(cmdbuff, sizeof(cmdbuff), "%s nfsserveruser2localaccount \"%s\"",
  1345. +        CYGWIN_IDMAPPER_SCRIPT,
  1346. +        name);
  1347. +    if ((script_pipe = _popen(cmdbuff, "rt")) == NULL) {
  1348. +        dprintf(0, "cygwin_getent_passwd: '%s' failed, errno='%s'\n",
  1349. +            cmdbuff,
  1350. +            strerror(errno));
  1351. +        goto fail;
  1352. +    }
  1353. +
  1354. +    num_buff_read = fread(buff, 1, sizeof(buff), script_pipe);
  1355. +    if (num_buff_read < 10) {
  1356. +        dprintf(0, "cygwin_getent_passwd: Could not read enough data, returned %d\n", (int)num_buff_read);
  1357. +        goto fail;
  1358. +    }
  1359. +
  1360. +    buff[num_buff_read] = '\0';
  1361. +
  1362. +    cpvp = cpv_create_parser(buff, 0/*CPVFLAG_DEBUG_OUTPUT*/);
  1363. +    if (!cpvp) {
  1364. +        dprintf(0, "cygwin_getent_passwd: Could not create parser\n");
  1365. +        goto fail;
  1366. +    }
  1367. +
  1368. +    if (cpv_read_cpv_header(cpvp)) {
  1369. +        dprintf(0, "cygwin_getent_passwd: cpv_read_cpv_header failed\n");
  1370. +        goto fail;
  1371. +    }
  1372. +
  1373. +    for (numcnv=0 ; cpv_parse_name_val(cpvp, &cnv[numcnv]) == 0 ; numcnv++) {
  1374. +    }
  1375. +
  1376. +    for (i=0 ; i < numcnv ; i++) {
  1377. +        cnv_cur = &cnv[i];
  1378. +        if (!strcmp("localaccoutname", cnv_cur->cpv_name)) {
  1379. +            localaccoutname = cnv_cur->cpv_value;
  1380. +        }
  1381. +        else if (!strcmp("localuid", cnv_cur->cpv_name)) {
  1382. +            errno = 0;
  1383. +            uid = strtol(cnv_cur->cpv_value, NULL, 10);
  1384. +            if (errno != 0)
  1385. +                goto fail;
  1386. +        }
  1387. +        else if (!strcmp("localgid", cnv_cur->cpv_name)) {
  1388. +            errno = 0;
  1389. +            gid = strtol(cnv_cur->cpv_value, NULL, 10);
  1390. +            if (errno != 0)
  1391. +                goto fail;
  1392. +        }
  1393. +    }
  1394. +
  1395. +    if (res_loginname)
  1396. +        (void)strcpy_s(res_loginname, VAL_LEN, localaccoutname);
  1397. +    *res_uid = uid;
  1398. +    *res_gid = gid;
  1399. +    res = 0;
  1400. +
  1401. +fail:
  1402. +    if (script_pipe)
  1403. +        (void)_pclose(script_pipe);
  1404. +
  1405. +    for (i=0 ; i < numcnv ; i++) {
  1406. +        cpv_free_name_val_data(&cnv[i]);
  1407. +    }
  1408. +
  1409. +    cpv_free_parser(cpvp);
  1410. +
  1411. +    if (res == 0) {
  1412. +        dprintf(CYGWINIDLVL, "<-- cygwin_getent_passwd('%s'): "
  1413. +            "returning res_uid=%lu, res_gid=%lu, res_loginname='%s'\n",
  1414. +            name,
  1415. +            (unsigned long)(*res_uid),
  1416. +            (unsigned long)(*res_gid),
  1417. +            res_loginname?res_loginname:"<NULL>");
  1418. +    }
  1419. +    else {
  1420. +        dprintf(CYGWINIDLVL, "<-- cygwin_getent_passwd('%s'): no match found\n",
  1421. +            name);
  1422. +    }
  1423. +
  1424. +    return res;
  1425. +}
  1426. +
  1427. +int cygwin_getent_group(const char* name, char* res_group_name, gid_t* res_gid)
  1428. +{
  1429. +    char cmdbuff[1024];
  1430. +    char buff[2048];
  1431. +    size_t num_buff_read;
  1432. +    FILE* script_pipe = NULL;
  1433. +    int res = 1;
  1434. +    unsigned long gid = -1;
  1435. +    void *cpvp = NULL;
  1436. +    int numcnv = 0;
  1437. +    int i = 0;
  1438. +    cpv_name_val cnv[256] = { 0 };
  1439. +    cpv_name_val *cnv_cur = NULL;
  1440. +
  1441. +    const char *localgroupname = NULL;
  1442. +
  1443. +    dprintf(CYGWINIDLVL, "--> cygwin_getent_group('%s')\n", name);
  1444. +
  1445. +    /* fixme: better quoting for |name| needed */
  1446. +    (void)snprintf(cmdbuff, sizeof(cmdbuff), "%s nfsserveruser2localgroup \"%s\"",
  1447. +        CYGWIN_IDMAPPER_SCRIPT,
  1448. +        name);
  1449. +    if ((script_pipe = _popen(cmdbuff, "rt")) == NULL) {
  1450. +        dprintf(0, "cygwin_getent_group: '%s' failed, errno='%s'\n",
  1451. +            cmdbuff,
  1452. +            strerror(errno));
  1453. +        goto fail;
  1454. +    }
  1455. +
  1456. +    num_buff_read = fread(buff, 1, sizeof(buff), script_pipe);
  1457. +    if (num_buff_read < 10) {
  1458. +        dprintf(0, "cygwin_getent_group: Could not read enough data, returned %d\n", (int)num_buff_read);
  1459. +        goto fail;
  1460. +    }
  1461. +
  1462. +    buff[num_buff_read] = '\0';
  1463. +
  1464. +    cpvp = cpv_create_parser(buff, 0/*CPVFLAG_DEBUG_OUTPUT*/);
  1465. +    if (!cpvp) {
  1466. +        dprintf(0, "cygwin_getent_group: Could not create parser\n");
  1467. +        goto fail;
  1468. +    }
  1469. +
  1470. +    if (cpv_read_cpv_header(cpvp)) {
  1471. +        dprintf(0, "cygwin_getent_group: cpv_read_cpv_header failed\n");
  1472. +        goto fail;
  1473. +    }
  1474. +
  1475. +    for (numcnv=0 ; cpv_parse_name_val(cpvp, &cnv[numcnv]) == 0 ; numcnv++) {
  1476. +    }
  1477. +
  1478. +    for (i=0 ; i < numcnv ; i++) {
  1479. +        cnv_cur = &cnv[i];
  1480. +        if (!strcmp("localgroupname", cnv_cur->cpv_name)) {
  1481. +            localgroupname = cnv_cur->cpv_value;
  1482. +        }
  1483. +        else if (!strcmp("localgid", cnv_cur->cpv_name)) {
  1484. +            errno = 0;
  1485. +            gid = strtol(cnv_cur->cpv_value, NULL, 10);
  1486. +            if (errno != 0)
  1487. +                goto fail;
  1488. +        }
  1489. +    }
  1490. +
  1491. +    if (res_group_name)
  1492. +        (void)strcpy_s(res_group_name, VAL_LEN, localgroupname);
  1493. +    *res_gid = gid;
  1494. +    res = 0;
  1495. +
  1496. +fail:
  1497. +    if (script_pipe)
  1498. +        (void)_pclose(script_pipe);
  1499. +
  1500. +    for (i=0 ; i < numcnv ; i++) {
  1501. +        cpv_free_name_val_data(&cnv[i]);
  1502. +    }
  1503. +
  1504. +    cpv_free_parser(cpvp);
  1505. +
  1506. +    if (res == 0) {
  1507. +        dprintf(CYGWINIDLVL, "<-- cygwin_getent_group('%s'): "
  1508. +            "returning res_gid=%lu, res_group_name='%s'\n",
  1509. +            name,
  1510. +            (unsigned long)(*res_gid),
  1511. +            res_group_name?res_group_name:"<NULL>");
  1512. +    }
  1513. +    else {
  1514. +        dprintf(CYGWINIDLVL, "<-- cygwin_getent_group('%s'): no match found\n",
  1515. +            name);
  1516. +    }
  1517. +
  1518. +    return res;
  1519. +}
  1520. +#endif /* NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN */
  1521. +

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