- diff --git a/build.vc19/nfsd/nfsd.vcxproj b/build.vc19/nfsd/nfsd.vcxproj
- index 047f02d..77df470 100644
- --- a/build.vc19/nfsd/nfsd.vcxproj
- +++ b/build.vc19/nfsd/nfsd.vcxproj
- @@ -153,11 +153,13 @@
- <ClCompile Include="..\..\daemon\acl.c" />
- <ClCompile Include="..\..\daemon\callback_server.c" />
- <ClCompile Include="..\..\daemon\callback_xdr.c" />
- + <ClCompile Include="..\..\daemon\cpvparser1.c" />
- <ClCompile Include="..\..\daemon\daemon_debug.c" />
- <ClCompile Include="..\..\daemon\delegation.c" />
- <ClCompile Include="..\..\daemon\ea.c" />
- <ClCompile Include="..\..\daemon\getattr.c" />
- <ClCompile Include="..\..\daemon\idmap.c" />
- + <ClCompile Include="..\..\daemon\idmap_cygwin.c" />
- <ClCompile Include="..\..\daemon\lock.c" />
- <ClCompile Include="..\..\daemon\lookup.c" />
- <ClCompile Include="..\..\daemon\mount.c" />
- @@ -188,6 +190,7 @@
- <ClCompile Include="..\..\daemon\volume.c" />
- </ItemGroup>
- <ItemGroup>
- + <ClInclude Include="..\..\daemon\cpvparser1.h" />
- <ClInclude Include="..\..\daemon\daemon_debug.h" />
- <ClInclude Include="..\..\daemon\delegation.h" />
- <ClInclude Include="..\..\daemon\from_kernel.h" />
- diff --git a/build.vc19/nfsd/nfsd.vcxproj.filters b/build.vc19/nfsd/nfsd.vcxproj.filters
- index d0ebad9..cc1ee27 100644
- --- a/build.vc19/nfsd/nfsd.vcxproj.filters
- +++ b/build.vc19/nfsd/nfsd.vcxproj.filters
- @@ -24,6 +24,9 @@
- <ClCompile Include="..\..\daemon\callback_xdr.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- + <ClCompile Include="..\..\daemon\cpvparser1.c">
- + <Filter>Source Files</Filter>
- + </ClCompile>
- <ClCompile Include="..\..\daemon\daemon_debug.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- @@ -39,6 +42,9 @@
- <ClCompile Include="..\..\daemon\idmap.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- + <ClCompile Include="..\..\daemon\idmap_cygwin.c">
- + <Filter>Source Files</Filter>
- + </ClCompile>
- <ClCompile Include="..\..\daemon\lock.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- @@ -125,6 +131,9 @@
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- + <ClInclude Include="..\..\daemon\cpvparser1.h">
- + <Filter>Header Files</Filter>
- + </ClInclude>
- <ClInclude Include="..\..\daemon\daemon_debug.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- diff --git a/cygwin_idmapper.ksh b/cygwin_idmapper.ksh
- new file mode 100644
- index 0000000..4b96ecf
- --- /dev/null
- +++ b/cygwin_idmapper.ksh
- @@ -0,0 +1,124 @@
- +#!/bin/ksh93
- +
- +set -o nounset
- +typeset IFS=''
- +
- +#
- +# global variables
- +# (stored in compound variable so we
- +# can do a $ print -u2 -v c # for debugging)
- +#
- +compound c=(
- + mode="$1"
- + name="$2"
- +)
- +
- +compound -A localusers=(
- + ["roland_mainz"]=(
- + localaccoutname='roland_mainz'
- + localuid=197608
- + localgid=197121
- + )
- + ["siegfried_wulsch"]=(
- + localaccoutname='siegfried_wulsch'
- + localuid=197609
- + localgid=197121
- + )
- + ["SYSTEM"]=(
- + localaccoutname='SYSTEM'
- + localuid=18
- + localgid=18
- + )
- + ["rmainz"]=(
- + localaccoutname='rmainz'
- + localuid=1616
- + localgid=1616
- + )
- + ["swulsch"]=(
- + localaccoutname='swulsch'
- + localuid=1818
- + localgid=1818
- + )
- + ["root"]=(
- + localaccoutname='root'
- + localuid=0
- + localgid=0
- + )
- + ["nobody"]=(
- + localaccoutname='nobody'
- + localuid=65534
- + localgid=65534
- + )
- +)
- +
- +compound -A localgroups=(
- + ["Kein"]=(
- + localaccoutname='Kein'
- + localgid=197121
- + )
- + ["rmainz"]=(
- + localaccoutname='rmainz'
- + localuid=1616
- + localgid=1616
- + )
- + ["swulsch"]=(
- + localaccoutname='swulsch'
- + localuid=1818
- + localgid=1818
- + )
- + ["root"]=(
- + localaccoutname='root'
- + localuid=0
- + localgid=0
- + )
- + ["nogroup"]=(
- + localaccoutname='nogroup'
- + localuid=65534
- + localgid=65534
- + )
- +)
- +
- +case "${c.mode}" in
- + 'nfsserveruser2localaccount')
- + if [[ "${c.name}" == ~(Elr)[[:digit:]]+ ]] ; then
- + for s in "${!localusers[@]}" ; do
- + if (( localusers[$s].localuid == c.name )) ; then
- + print -v localusers[$s]
- + exit 0
- + fi
- + done
- + fi
- +
- + if [[ -v localusers["${c.name}"] ]] ; then
- + print -v localusers["${c.name}"]
- + exit 0
- + else
- + print -u2 -f "cygwin_idmapper.ksh: Account '%s' not found.\n" "${c.name}"
- + exit 1
- + fi
- + ;;
- + 'nfsserveruser2localgroup')
- + if [[ "${c.name}" == ~(Elr)[[:digit:]]+ ]] ; then
- + for s in "${!localgroups[@]}" ; do
- + if (( localgroups[$s].localgid == c.name )) ; then
- + print -v localgroups[$s]
- + exit 0
- + fi
- + done
- + fi
- +
- + if [[ -v localgroups["${c.name}"] ]] ; then
- + print -v localgroups["${c.name}"]
- + exit 0
- + else
- + print -u2 -f "cygwin_idmapper.ksh: Account '%s' not found.\n" "${c.name}"
- + exit 1
- + fi
- + ;;
- + *)
- + print -u2 "cygwin_idmapper.ksh: Unknown mode"
- + exit 1
- + ;;
- +esac
- +
- +# EOF.
- diff --git a/daemon/acl.c b/daemon/acl.c
- index 1d1eac4..86e0d5a 100644
- --- a/daemon/acl.c
- +++ b/daemon/acl.c
- @@ -21,6 +21,7 @@
- #include <Windows.h>
- #include <stdio.h>
- +#include <time.h>
- #include <strsafe.h>
- #include <sddl.h>
- @@ -198,10 +199,138 @@ BOOL allocate_unixgroup_sid(unsigned long gid, PSID *pSid)
- }
- #endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
- -static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_len, PSID *sid, LPCSTR name)
- +
- +/* fixme: should be in sys/nfs41_build_features.h */
- +#define USE_SID_CACHE 1
- +
- +
- +#ifdef USE_SID_CACHE
- +#define SID_CACHE_SIZE 20
- +#define SID_CACHE_TTL 600
- +
- +typedef struct _sid_cache_entry
- +{
- + char name[256]; /* fixme: size correct ? */
- + PSID sid;
- + DWORD sid_len;
- + time_t timestamp;
- +} sid_cache_entry;
- +
- +typedef struct _sid_cache
- +{
- + CRITICAL_SECTION lock;
- + sid_cache_entry entries[SID_CACHE_SIZE];
- + ssize_t cacheIndex;
- +} sid_cache;
- +
- +/* fixme: need function to deallocate this */
- +sid_cache user_sid_cache = { 0 };
- +
- +static volatile int cache_once = 0;
- +
- +/* copy SID |value| into cache */
- +void sid_addcache(sid_cache *cache, const char* name, PSID *value)
- +{
- + int i;
- + int oldestEntryIndex;
- + time_t currentTimestamp;
- +
- + /* fixme: this is not really threadsafe!! */
- + if (cache_once++ == 0) {
- + InitializeCriticalSection(&cache->lock);
- + dprintf(0, "SID cache init\n");
- + }
- +
- + EnterCriticalSection(&cache->lock);
- + currentTimestamp = time(NULL);
- +
- + /* Find the oldest valid cache entry */
- + oldestEntryIndex = -1;
- + for (i = 0; i < SID_CACHE_SIZE; i++) {
- + if ((cache->entries[i].sid == NULL) || (cache->entries[i].timestamp < (currentTimestamp - SID_CACHE_TTL))) {
- + oldestEntryIndex = i;
- + break;
- + }
- + }
- +
- + /* If no valid entry was found, overwrite the oldest entry */
- + if (oldestEntryIndex == -1) {
- + oldestEntryIndex = cache->cacheIndex;
- + }
- +
- + /* Replace the cache entry */
- + DWORD sid_len = GetLengthSid(value);
- + PSID malloced_sid = malloc(sid_len);
- + if (!malloced_sid)
- + goto done;
- + if (!CopySid(sid_len, malloced_sid, value)) {
- + free(malloced_sid);
- + goto done;
- + }
- +
- + sid_cache_entry *e = &cache->entries[oldestEntryIndex];
- +
- + e->sid_len = sid_len;
- + if (e->sid)
- + free(e->sid);
- + e->sid = malloced_sid;
- + (void)strcpy(e->name, name);
- + e->timestamp = currentTimestamp;
- +
- + cache->cacheIndex = (cache->cacheIndex + 1) % SID_CACHE_SIZE;
- +
- +done:
- + LeaveCriticalSection(&cache->lock);
- +}
- +
- +/* return |malloc()|'ed copy of SID from cache entry */
- +PSID *sid_getfromcache(sid_cache *cache, const char *name)
- {
- + int i;
- + time_t currentTimestamp;
- + PSID *ret_sid = NULL;
- +
- + /* fixme: this is not really threadsafe!! */
- + if (cache_once++ == 0) {
- + InitializeCriticalSection(&cache->lock);
- + dprintf(0, "SID cache init\n");
- + }
- +
- + EnterCriticalSection(&cache->lock);
- + currentTimestamp = time(NULL);
- +
- + for (i = 0; i < SID_CACHE_SIZE; i++) {
- + sid_cache_entry *e = &cache->entries[i];
- +
- + if ((!strcmp(e->name, name)) && (e->timestamp >= (currentTimestamp - SID_CACHE_TTL))) {
- + PSID malloced_sid = malloc(e->sid_len);
- +
- + if (!malloced_sid)
- + goto done;
- +
- + if (!CopySid(e->sid_len, malloced_sid, e->sid)) {
- + free(malloced_sid);
- + goto done;
- + }
- +
- + ret_sid = malloced_sid;
- + goto done;
- + }
- + }
- +
- +done:
- + LeaveCriticalSection(&cache->lock);
- + return ret_sid;
- +}
- +#endif
- +
- +static int map_nfs4servername_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_len, PSID *sid, LPCSTR name)
- +{
- + const char *orig_name = name;
- +
- int status = ERROR_INTERNAL_ERROR;
- SID_NAME_USE sid_type;
- + char name_buff[256+2];
- LPSTR tmp_buf = NULL;
- DWORD tmp = 0;
- #ifdef NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID
- @@ -210,24 +339,38 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
- #endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
- #ifdef NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID
- + /* use our own idmapper script to map nfsv4 owner string to local Windows account */
- if (query & OWNER_SECURITY_INFORMATION) {
- - if (!strcmp(name, "rmainz")) {
- - name = "roland_mainz";
- - dprintf(ACLLVL, "map_name_2_sid: remap rmainz --> roland_mainz\n");
- - }
- - else if (!strcmp(name, "197608")) {
- - name = "roland_mainz";
- - dprintf(ACLLVL, "map_name_2_sid: remap 197608 --> roland_mainz\n");
- + uid_t udummy = -1;
- + gid_t gdummy = -1;
- +
- +int cygwin_getent_passwd(const char *name, char *res_loginname, uid_t *res_uid, gid_t *res_gid);
- +
- +#ifdef USE_SID_CACHE
- + if (*sid = sid_getfromcache(&user_sid_cache, name)) {
- + *sid_len = GetLengthSid(*sid);
- +// dprintf(0, "map_nfs4servername_2_sid: returning cached sid for '%s'\n", name);
- + return 0;
- + }
- +#endif /* USE_SID_CACHE */
- +
- +#ifndef USE_SID_CACHE
- + /* gisburn: fixme: We must cache this, or the performance impact will be devastating!! */
- +#endif /* !USE_SID_CACHE */
- + if (!cygwin_getent_passwd(name, name_buff, &udummy, &gdummy)) {
- + if (strcmp(name, name_buff)) {
- + dprintf(0,
- + "map_nfs4servername_2_sid: remap '%s' --> '%s'\n",
- + name,
- + name_buff);
- + name = name_buff;
- }
- - else if (!strcmp(name, "1616")) {
- - name = "roland_mainz";
- - dprintf(ACLLVL, "map_name_2_sid: remap 1616 --> roland_mainz\n");
- }
- }
- #endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
- status = LookupAccountName(NULL, name, NULL, sid_len, NULL, &tmp, &sid_type);
- - dprintf(ACLLVL, "map_name_2_sid(query=%x,name='%s'): LookupAccountName returned %d "
- + dprintf(ACLLVL, "map_nfs4servername_2_sid(query=%x,name='%s'): LookupAccountName returned %d "
- "GetLastError %d name len %d domain len %d\n",
- query, name, status, GetLastError(), *sid_len, tmp);
- if (status)
- @@ -248,7 +391,7 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
- &tmp, &sid_type);
- free(tmp_buf);
- if (!status) {
- - eprintf("map_name_2_sid(query=%x,name='%s'): LookupAccountName failed "
- + eprintf("map_nfs4servername_2_sid(query=%x,name='%s'): LookupAccountName failed "
- "with %d\n", query, name, GetLastError());
- goto out_free_sid;
- } else {
- @@ -256,13 +399,13 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
- LPSTR ssid = NULL;
- if (IsValidSid(*sid))
- if (ConvertSidToStringSidA(*sid, &ssid))
- - dprintf(1, "map_name_2_sid: sid_type = %d SID %s\n",
- + dprintf(1, "map_nfs4servername_2_sid: sid_type = %d SID %s\n",
- sid_type, ssid);
- else
- - dprintf(1, "map_name_2_sid: ConvertSidToStringSidA failed "
- + dprintf(1, "map_nfs4servername_2_sid: ConvertSidToStringSidA failed "
- "with %d\n", GetLastError());
- else
- - dprintf(1, "map_name_2_sid: Invalid Sid ?\n");
- + dprintf(1, "map_nfs4servername_2_sid: Invalid Sid ?\n");
- if (ssid) LocalFree(ssid);
- #endif
- }
- @@ -270,7 +413,7 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
- break;
- case ERROR_NONE_MAPPED:
- #ifdef NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID
- - dprintf(1, "map_name_2_sid(query=%x,name='%s'): none mapped, "
- + dprintf(1, "map_nfs4servername_2_sid(query=%x,name='%s'): none mapped, "
- "trying Unix_User+/Unix_Group+ mapping\n",
- query, name);
- @@ -286,7 +429,7 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
- user_uid = map_uid;
- }
- else {
- - dprintf(1, "map_name_2_sid(query=%x,name='%s'): nfs41_idmap_name_to_ids() failed\n",
- + dprintf(1, "map_nfs4servername_2_sid(query=%x,name='%s'): nfs41_idmap_name_to_ids() failed\n",
- query, name);
- /* fixme: try harder here, "1234" should to to |atol()| */
- }
- @@ -302,7 +445,7 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
- group_gid = map_gid;
- }
- else {
- - dprintf(1, "map_name_2_sid(query=%x,name='%s'): nfs41_idmap_group_to_gid() failed\n",
- + dprintf(1, "map_nfs4servername_2_sid(query=%x,name='%s'): nfs41_idmap_group_to_gid() failed\n",
- query, name);
- /* fixme: try harder here, "1234" should to to |atol()| */
- }
- @@ -310,14 +453,15 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
- if (user_uid != -1) {
- if (allocate_unixuser_sid(user_uid, sid)) {
- - dprintf(ACLLVL, "map_name_2_sid(query=%x,name='%s'): "
- + dprintf(ACLLVL, "map_nfs4servername_2_sid(query=%x,name='%s'): "
- "allocate_unixuser_sid(uid=%ld) success\n",
- query, name, user_uid);
- - return ERROR_SUCCESS;
- + status = ERROR_SUCCESS;
- + goto out;
- }
- status = GetLastError();
- - dprintf(ACLLVL, "map_name_2_sid(query=%x,name='%s'): "
- + dprintf(ACLLVL, "map_nfs4servername_2_sid(query=%x,name='%s'): "
- "allocate_unixuser_sid(uid=%ld) failed, error=%d\n",
- query, name, user_uid, status);
- return status;
- @@ -325,21 +469,22 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
- if (group_gid != -1) {
- if (allocate_unixgroup_sid(group_gid, sid)) {
- - dprintf(ACLLVL, "map_name_2_sid(query=%x,name='%s'): "
- + dprintf(ACLLVL, "map_nfs4servername_2_sid(query=%x,name='%s'): "
- "allocate_unixgroup_sid(gid=%ld) success\n",
- query, name, group_gid);
- - return ERROR_SUCCESS;
- + status = ERROR_SUCCESS;
- + goto out;
- }
- status = GetLastError();
- - dprintf(ACLLVL, "map_name_2_sid(query=%x,name='%s'): "
- + dprintf(ACLLVL, "map_nfs4servername_2_sid(query=%x,name='%s'): "
- "allocate_unixgroup_sid(gid=%ld) failed, error=%d\n",
- query, name, group_gid, status);
- return status;
- }
- #endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
- - dprintf(1, "map_name_2_sid(query=%x,name='%s'): none mapped, "
- + dprintf(1, "map_nfs4servername_2_sid(query=%x,name='%s'): none mapped, "
- "using WinNullSid mapping\n",
- query, name);
- @@ -348,11 +493,20 @@ static int map_name_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_l
- goto out_free_sid;
- break;
- default:
- - dprintf(1, "map_name_2_sid(query=%x,name='%s'): error %d not handled\n",
- + dprintf(1, "map_nfs4servername_2_sid(query=%x,name='%s'): error %d not handled\n",
- query, name, GetLastError());
- break;
- }
- out:
- +#ifdef USE_SID_CACHE
- + if (*sid) {
- + /* fixme: No other flags in |query| must be set!! */
- + if (query & OWNER_SECURITY_INFORMATION) {
- + sid_addcache(&user_sid_cache, orig_name, *sid);
- + }
- + }
- +#endif /* USE_SID_CACHE */
- +
- return status;
- out_free_sid:
- status = GetLastError();
- @@ -417,7 +571,7 @@ static int convert_nfs4acl_2_dacl(nfs41_daemon_globals *nfs41dg,
- goto out;
- }
- if (!flag) {
- - status = map_name_2_sid(nfs41dg,
- + status = map_nfs4servername_2_sid(nfs41dg,
- 0xFFFF /* fixme: Unknown whether user or group */,
- &sid_len, &sids[i], acl->aces[i].who);
- if (status) {
- @@ -534,7 +688,7 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
- dprintf(ACLLVL, "handle_getacl: OWNER_SECURITY_INFORMATION: for user=%s "
- "domain=%s\n", info.owner, domain?domain:"<null>");
- sid_len = 0;
- - status = map_name_2_sid(nfs41dg,
- + status = map_nfs4servername_2_sid(nfs41dg,
- OWNER_SECURITY_INFORMATION, &sid_len, &osid, info.owner);
- if (status)
- goto out;
- @@ -552,7 +706,7 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
- dprintf(ACLLVL, "handle_getacl: GROUP_SECURITY_INFORMATION: for %s "
- "domain=%s\n", info.owner_group, domain?domain:"<null>");
- sid_len = 0;
- - status = map_name_2_sid(nfs41dg,
- + status = map_nfs4servername_2_sid(nfs41dg,
- GROUP_SECURITY_INFORMATION, &sid_len, &gsid, info.owner_group);
- if (status)
- goto out;
- diff --git a/daemon/cpvparser1.c b/daemon/cpvparser1.c
- new file mode 100644
- index 0000000..285fc76
- --- /dev/null
- +++ b/daemon/cpvparser1.c
- @@ -0,0 +1,361 @@
- +
- +/*
- + * MIT License
- + *
- + * Copyright (c) 2023 Roland Mainz <roland.mainz@nrubsig.org>
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a copy
- + * of this software and associated documentation files (the "Software"), to deal
- + * in the Software without restriction, including without limitation the rights
- + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- + * copies of the Software, and to permit persons to whom the Software is
- + * furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included in all
- + * copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FORalloca ANY CLAIM, DAMAGES OR OTHER
- + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- + * SOFTWARE.
- + */
- +
- +/*
- + * cpvparser1.c - simple ksh93 compound variable parsing
- + *
- + * It basically reads the output of $ print -v ... # like this:
- + * ---- snip ----
- + * $ ksh93 -c 'compound c=( va=1 vb=hello ) ; print -v c'
- + * (
- + * va=1
- + * vb=hello
- + * )
- + * ---- snip ----
- + *
- + * ToDo:
- + * - arrays (indexed, sparse indexed and associative)
- + * - multibyte characters
- + *
- + * Written by Roland Mainz <roland.mainz@nrubsig.org>
- + */
- +
- +#include <stdlib.h>
- +#include <stdbool.h>
- +#include <string.h>
- +#include <stdio.h>
- +#include <ctype.h>
- +
- +#include "cpvparser1.h"
- +
- +#ifdef _WIN32
- +#define strdup(s) _strdup(s)
- +#endif
- +
- +/* private data! */
- +typedef struct cpv_parse_context {
- + const char *start_string;
- + const char *curr_string;
- + size_t max_name_val_size;
- + unsigned long flags;
- +} cpv_parse_context;
- +
- +
- +void *cpv_create_parser(const char *s, unsigned long flags, ...)
- +{
- + cpv_parse_context *cpc;
- +
- + cpc = calloc(1, sizeof(cpv_parse_context));
- + if (!cpc)
- + goto fail;
- +
- + cpc->start_string = strdup(s);
- + if (!cpc->start_string)
- + goto fail;
- +
- + cpc->curr_string = cpc->start_string;
- + cpc->max_name_val_size = strlen(cpc->start_string);
- + cpc->flags = flags;
- +
- + return (cpc);
- +
- +fail:
- + if (cpc) {
- + free((void *)cpc->start_string);
- + free(cpc);
- + }
- +
- + return NULL;
- +}
- +
- +void cpv_free_parser(void *v_cpc)
- +{
- + cpv_parse_context *cpc = (cpv_parse_context *)v_cpc;
- + if (cpc) {
- + free((void *)cpc->start_string);
- + free(cpc);
- + }
- +}
- +
- +int cpv_read_cpv_header(void *v_cpc)
- +{
- + cpv_parse_context *cpc = (cpv_parse_context *)v_cpc;
- + const char *s = cpc->curr_string;
- +
- +skipspaces:
- + while((*s != '\0') && isspace(*s))
- + s++;
- +
- + /*
- + * skip POSIX-style '#' comments
- + * (allowed since this is based on POSIX sh(1) syntax)
- + */
- + if (*s == '#') {
- + s++;
- + /* ignore everything until the end-of-line */
- + while((*s != '\0') && (*s != '\n'))
- + s++;
- + goto skipspaces;
- + }
- +
- + if (*s == '(') {
- + cpc->curr_string=++s;
- + if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
- + (void)fprintf(stderr, "cpv_read_cpv_header: begin-of-cpv\n");
- + }
- + return 0;
- + }
- +
- + if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
- + (void)fprintf(stderr, "cpv_read_cpv_header: end-of-string, should not happen\n");
- + }
- + return 1;
- +}
- +
- +int cpv_parse_name_val(void *v_cpc, cpv_name_val *cpv_nv)
- +{
- + cpv_parse_context *cpc = (cpv_parse_context *)v_cpc;
- +#ifdef _WIN32
- + char *namebuff = _alloca(cpc->max_name_val_size+1);
- + char *valbuff = _alloca(cpc->max_name_val_size+1);
- +#else
- + char namebuff[cpc->max_name_val_size+1];
- + char valbuff[cpc->max_name_val_size+1];
- +#endif
- +
- + const char *s = cpc->curr_string;
- +
- + char *n; /* pointer in |namebuff| */
- + char *v; /* pointer in |valbuff| */
- +
- +skipspaces:
- + while((*s != '\0') && isspace(*s))
- + s++;
- +
- + /*
- + * skip POSIX-style '#' comments
- + * (allowed since this is based on POSIX sh(1) syntax)
- + */
- + if (*s == '#') {
- + s++;
- + /* ignore everything until the end-of-line */
- + while((*s != '\0') && (*s != '\n'))
- + s++;
- + goto skipspaces;
- + }
- +
- + if (*s == '\0') {
- + if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
- + (void)fprintf(stderr, "cpv_parse_name_val: "
- + "error: end-of-string, should not happen\n");
- + }
- + return 1;
- + }
- +
- + /* cpv == "( foo=bar blabla=text )"*/
- + if (*s == ')') {
- + if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
- + (void)fprintf(stderr, "cpv_parse_name_val: end-of-cpv (OK)\n");
- + }
- + return 1;
- + }
- +
- +parse_varname:
- + /*
- + * start parsing variable name
- + */
- +
- + /* variable names MUST start with a letter! */
- + if (!isalpha(*s)) {
- + if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
- + (void)fprintf(stderr,
- + "cpv_parse_name_val: parser error, first char "
- + "in variable name not isalpha(c=%c)\n",
- + *s);
- + }
- + return 1;
- + }
- +
- + n = namebuff;
- + while((*s != '\0') && isalnum(*s))
- + *n++ = *s++;
- + *n = '\0';
- +
- + /*
- + * skip typed member varables
- + * (e.g. "typeset ", "typeset -i ", "typeset -l -i2" etc.)
- + */
- + if (isspace(*s)) {
- + if ((!strcmp(namebuff, "typeset")) ||
- + (!strcmp(namebuff, "integer")) ||
- + (!strcmp(namebuff, "float")) ||
- + (!strcmp(namebuff, "compound"))) {
- +skip_typeset_options:
- + while(isspace(*s))
- + s++;
- + if (*s == '-') {
- + s++;
- + while(isalnum(*s))
- + s++;
- + goto skip_typeset_options;
- + }
- +
- + goto parse_varname;
- + }
- + }
- +
- + /* handle '=' */
- + if (*s != '=') {
- + if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
- + (void)fprintf(stderr, "cpv_parse_name_val: "
- + "parser error, expected '=', got '%c'.\n",
- + *s);
- + }
- + return 1;
- + }
- +
- + s++; /* skip '=' */
- +
- + /*
- + * start parsing variable value
- + */
- + bool in_doublequotes=false;
- + bool in_singlequotes=false;
- + v = valbuff;
- +val_quotes:
- + if (in_singlequotes) {
- + while(*s != '\0') {
- + if (*s == '\'') {
- + in_singlequotes = false;
- + s++;
- + goto val_quotes;
- + }
- +
- + if ((*s == '\\') && (*(s+1) != '\0')) {
- + /*
- + * fixme: should support \ooo octals,
- + * \u[hex] unicode and \w[hex] wchar
- + */
- + s++;
- + }
- + *v++ = *s++;
- + }
- + }
- + else if (in_doublequotes) {
- + while(*s != '\0') {
- + if (*s == '"') {
- + in_doublequotes = false;
- + s++;
- + goto val_quotes;
- + }
- +
- + if ((*s == '\\') && (*(s+1) != '\0')) {
- + /*
- + * fixme: should support \ooo octals,
- + * \u[hex] unicode and \w[hex] wchar
- + */
- + s++;
- + }
- +
- + *v++ = *s++;
- + }
- + }
- + else
- + {
- + while((*s != '\0') && (!isspace(*s))) {
- + if (*s == '"') {
- + in_doublequotes = true;
- + s++;
- + goto val_quotes;
- + }
- +
- + if (*s == '\'') {
- + in_singlequotes = true;
- + s++;
- + goto val_quotes;
- + }
- +
- + if ((*s == '\\') && (*(s+1) != '\0')) {
- + /*
- + * fixme: should support \ooo octals,
- + * \u[hex] unicode and \w[hex] wchar
- + */
- + s++;
- + }
- + *v++ = *s++;
- + }
- + }
- +
- + if (in_singlequotes) {
- + if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
- + (void)fprintf(stderr, "cpv_parse_name_val: "
- + "parsererror, still in single quotes "
- + "at the end\n");
- + }
- + return 1;
- + }
- + if (in_doublequotes) {
- + if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
- + (void)fprintf(stderr, "cpv_parse_name_val: "
- + "parser error, still in double quotes "
- + "at the end\n");
- + }
- + return 1;
- + }
- +
- + *v = '\0';
- +
- +#if 0
- + (void)printf("cpv_parse_name_val: name='%s', value='%s'\n",
- + namebuff, valbuff);
- +#endif
- +
- + cpv_nv->cpv_name = strdup(namebuff);
- + cpv_nv->cpv_value = strdup(valbuff);
- +
- + if ((cpv_nv->cpv_name == NULL) || (cpv_nv->cpv_value == NULL)) {
- + cpv_free_name_val_data(cpv_nv);
- + if (cpc->flags & CPVFLAG_DEBUG_OUTPUT) {
- + (void)fprintf(stderr, "cpv_parse_name_val: "
- + "parser error, out of memory\n");
- + }
- + return 2;
- + }
- +
- + cpc->curr_string = s;
- +
- + return 0;
- +}
- +
- +void cpv_free_name_val_data(cpv_name_val *cnv)
- +{
- + if (!cnv)
- + return;
- +
- + free((void *)cnv->cpv_name);
- + free((void *)cnv->cpv_value);
- + cnv->cpv_name = NULL;
- + cnv->cpv_value = NULL;
- +}
- diff --git a/daemon/cpvparser1.h b/daemon/cpvparser1.h
- new file mode 100644
- index 0000000..a6ed609
- --- /dev/null
- +++ b/daemon/cpvparser1.h
- @@ -0,0 +1,64 @@
- +
- +/*
- + * MIT License
- + *
- + * Copyright (c) 2023 Roland Mainz <roland.mainz@nrubsig.org>
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a copy
- + * of this software and associated documentation files (the "Software"), to deal
- + * in the Software without restriction, including without limitation the rights
- + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- + * copies of the Software, and to permit persons to whom the Software is
- + * furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included in all
- + * copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- + * SOFTWARE.
- + */
- +
- +/*
- + * cpvparser1.h - simple ksh93 compound variable parsing
- + *
- + * It basically reads the output of $ print -v ... # like this:
- + * ---- snip ----
- + * $ ksh93 -c 'compound c=( va=1 vb=hello ) ; print -v c'
- + * (
- + * va=1
- + * vb=hello
- + * )
- + * ---- snip ----
- + *
- + * ToDo:
- + * - arrays (indexed, sparse indexed and associative)
- + * - multibyte characters
- + *
- + * Written by Roland Mainz <roland.mainz@nrubsig.org>
- + */
- +
- +#ifndef CPV_PARSER_H
- +#define CPV_PARSER_H 1
- +
- +typedef struct cpv_name_val
- +{
- + const char *cpv_name;
- + const char *cpv_value;
- +} cpv_name_val;
- +
- +/* Flags for |cpv_create_parser()| */
- +#define CPVFLAG_DEBUG_OUTPUT (0x00000008L)
- +
- +/* prototypes */
- +void *cpv_create_parser(const char *s, unsigned long flags, ...);
- +void cpv_free_parser(void *);
- +int cpv_read_cpv_header(void *);
- +void cpv_free_name_val_data(cpv_name_val *);
- +int cpv_parse_name_val(void *, cpv_name_val *);
- +
- +#endif /* !CPV_PARSER_H */
- diff --git a/daemon/idmap.c b/daemon/idmap.c
- index 00af1fe..0672a85 100644
- --- a/daemon/idmap.c
- +++ b/daemon/idmap.c
- @@ -3,6 +3,7 @@
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- + * Roland Mainz <roland.mainz@nrubsig.org>
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- @@ -33,7 +34,7 @@
- #include "daemon_debug.h"
- #define IDLVL 2 /* dprintf level for idmap logging */
- -#define CYGWINIDLVL 2 /* dprintf level for idmap logging */
- +#define CYGWINIDLVL 0 /* dprintf level for idmap logging */
- #define FILTER_LEN 1024
- #define NAME_LEN 32
- @@ -133,7 +134,7 @@ static const struct config_option g_options[] = {
- OPT_ATTR("ldap_attr_gidNumber", "gidNumber", ATTR_GID),
- /* caching configuration */
- - OPT_INT("cache_ttl", "60", cache_ttl),
- + OPT_INT("cache_ttl", "6000", cache_ttl),
- };
- @@ -376,246 +377,6 @@ out:
- return status;
- }
- -#ifdef NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN
- -int cygwin_getent_passwd(const char *name, char *res_loginname, uid_t *res_uid, gid_t *res_gid)
- -{
- - char cmdbuff[1024];
- - char passwd_line[1024];
- - FILE* getent_pipe = NULL;
- - int res = 1;
- - unsigned long uid = -1;
- - unsigned long gid = -1;
- - struct _cypwent {
- - char* loginname;
- - char* passwd;
- - char* uidstr;
- - char* gidstr;
- - char* comment;
- - char* homedir;
- - char* shell;
- - } pwent = { 0 };
- -#define PWENT_ENTRY(var, prevvar) \
- - (((var) = strchr((prevvar), ':'))?(*(var)++ = '\0',(var)):(NULL))
- -
- - dprintf(CYGWINIDLVL, "--> cygwin_getent_passwd('%s')\n", name);
- -
- -#if 1
- - /* hack for testing, map "roland_mainz" to rmainz account */
- - if ((!strcmp(name, "rmainz")) || (!strcmp(name, "1616"))) {
- - uid = 1616;
- - gid = 1616;
- - pwent.loginname = "rmainz";
- - goto found;
- - }
- - if ((!strcmp(name, "nobody")) || (!strcmp(name, "no+body")) ||
- - (!strcmp(name, "65534"))) {
- - uid = 65534;
- - gid = 65534;
- - pwent.loginname = "no+body"; /* Cygwin-specific */
- - goto found;
- - }
- - if ((!strcmp(name, "root")) || (!strcmp(name, "0"))) {
- - uid = 0;
- - gid = 0;
- - pwent.loginname = "root";
- - goto found;
- - }
- - if ((!strcmp(name, "iam")) || (!strcmp(name, "2010"))) {
- - uid = 2010;
- - gid = 2010;
- - pwent.loginname = "iam";
- - goto found;
- - }
- - if ((!strcmp(name, "swulsch")) || (!strcmp(name, "1818"))) {
- - uid = 1818;
- - gid = 1818;
- - pwent.loginname = "swulsch";
- - goto found;
- - }
- - if ((!strcmp(name, "mwenzel")) || (!strcmp(name, "8239"))) {
- - uid = 8239;
- - gid = 8239;
- - pwent.loginname = "mwenzel";
- - goto found;
- - }
- -#endif
- -
- - /* fixme: better quoting for |name| needed */
- - (void)snprintf(cmdbuff, sizeof(cmdbuff), "%s passwd \"%s\"",
- - "C:\\cygwin64\\bin\\getent.exe",
- - name);
- - if ((getent_pipe = _popen(cmdbuff, "rt")) == NULL) {
- - dprintf(CYGWINIDLVL, "cygwin_getent_passwd: /usr/bin/getent failed, errno='%s'\n",
- - strerror(errno));
- - goto fail;
- - }
- -
- - if (fgets(passwd_line, sizeof(passwd_line), getent_pipe)) {
- - pwent.loginname = passwd_line;
- - if (!PWENT_ENTRY(pwent.passwd, pwent.loginname)) goto fail;
- - if (!PWENT_ENTRY(pwent.uidstr, pwent.passwd)) goto fail;
- - if (!PWENT_ENTRY(pwent.gidstr, pwent.uidstr)) goto fail;
- - if (!PWENT_ENTRY(pwent.comment, pwent.gidstr)) goto fail;
- - if (!PWENT_ENTRY(pwent.homedir, pwent.comment)) goto fail;
- - PWENT_ENTRY(pwent.shell, pwent.homedir);
- -
- - errno = 0;
- - uid = strtol(pwent.uidstr, NULL, 10);
- - if (errno != 0)
- - goto fail;
- -
- - errno = 0;
- - gid = strtol(pwent.gidstr, NULL, 10);
- - if (errno != 0)
- - goto fail;
- -
- -#if 0
- - dprintf(CYGWINIDLVL, "cygwin_getent_passwd(): name='%s'\n", name);
- - dprintf(CYGWINIDLVL, "loginname\t='%s'\n", pwent.loginname);
- - dprintf(CYGWINIDLVL, "passwd\t='%s'\n", pwent.passwd);
- - dprintf(CYGWINIDLVL, "uidstr\t='%s' (%lu)\n", pwent.uidstr, (unsigned long)uid);
- - dprintf(CYGWINIDLVL, "gidstr\t='%s' (%lu)\n", pwent.gidstr, (unsigned long)gid);
- - dprintf(CYGWINIDLVL, "comment\t='%s'\n", pwent.comment);
- - dprintf(CYGWINIDLVL, "homedir\t='%s'\n", pwent.homedir);
- - dprintf(CYGWINIDLVL, "shell\t='%s'\n", pwent.shell);
- -#endif
- -
- -found:
- - if (res_loginname)
- - (void)strcpy_s(res_loginname, VAL_LEN, pwent.loginname);
- - *res_uid = uid;
- - *res_gid = gid;
- - res = 0;
- - }
- -
- -fail:
- - if (getent_pipe)
- - (void)_pclose(getent_pipe);
- -
- - if (res == 0) {
- - dprintf(CYGWINIDLVL, "<-- cygwin_getent_passwd('%s'): "
- - "returning res_uid=%lu, res_gid=%lu, res_loginname='%s'\n",
- - name,
- - (unsigned long)(*res_uid),
- - (unsigned long)(*res_gid),
- - res_loginname?res_loginname:"<NULL>");
- - }
- - else {
- - dprintf(CYGWINIDLVL, "<-- cygwin_getent_passwd('%s'): no match found\n",
- - name);
- - }
- -
- - return res;
- -}
- -
- -int cygwin_getent_group(const char* name, char* res_group_name, gid_t* res_gid)
- -{
- - char cmdbuff[1024];
- - char group_line[1024];
- - FILE* getent_pipe = NULL;
- - int res = 1;
- - unsigned long gid = -1;
- - struct _cygrent
- - {
- - char* group_name;
- - char* passwd;
- - char* gidstr;
- - char* userlist;
- - } grent = { 0 };
- -
- - dprintf(CYGWINIDLVL, "--> cygwin_getent_group('%s')\n", name);
- -
- -#if 1
- - if ((!strcmp(name, "rmainz")) || (!strcmp(name, "1616"))) {
- - gid = 1616;
- - grent.group_name = "rmainz";
- - goto found;
- - }
- - if ((!strcmp(name, "nogroup")) || (!strcmp(name, "no+body")) ||
- - (!strcmp(name, "65534"))) {
- - gid = 65534;
- - grent.group_name = "no+body"; /* Cygwin-specific */
- - goto found;
- - }
- - if ((!strcmp(name, "root")) || (!strcmp(name, "0"))) {
- - gid = 0;
- - grent.group_name = "root";
- - goto found;
- - }
- - if ((!strcmp(name, "iam")) || (!strcmp(name, "2010"))) {
- - gid = 2010;
- - grent.group_name = "iam";
- - goto found;
- - }
- - if ((!strcmp(name, "swulsch")) || (!strcmp(name, "1818"))) {
- - gid = 1818;
- - grent.group_name = "swulsch";
- - goto found;
- - }
- - if ((!strcmp(name, "mwenzel")) || (!strcmp(name, "8239"))) {
- - gid = 8239;
- - grent.group_name = "mwenzel";
- - goto found;
- - }
- -#endif
- -
- - /* fixme: better quoting for |name| needed */
- - (void)snprintf(cmdbuff, sizeof(cmdbuff), "%s group \"%s\"",
- - "C:\\cygwin64\\bin\\getent.exe",
- - name);
- - if ((getent_pipe = _popen(cmdbuff, "rt")) == NULL) {
- - dprintf(CYGWINIDLVL,
- - "cygwin_getent_group: /usr/bin/getent failed, errno='%s'\n",
- - strerror(errno));
- - goto fail;
- - }
- -
- - if (fgets(group_line, sizeof(group_line), getent_pipe))
- - {
- - grent.group_name = group_line;
- - if (!PWENT_ENTRY(grent.passwd, grent.group_name)) goto fail;
- - if (!PWENT_ENTRY(grent.gidstr, grent.passwd)) goto fail;
- - PWENT_ENTRY(grent.userlist, grent.gidstr);
- -
- - errno = 0;
- - gid = strtol(grent.gidstr, NULL, 10);
- - if (errno != 0)
- - goto fail;
- -
- -#if 0
- - dprintf(CYGWINIDLVL, "cygwin_getent_group(): name='%s'\n", name);
- - dprintf(CYGWINIDLVL, "group_name\t='%s'\n", grent.group_name);
- - dprintf(CYGWINIDLVL, "passwd\t='%s'\n", grent.passwd);
- - dprintf(CYGWINIDLVL, "gidstr\t='%s' (%lu)\n", grent.gidstr, (unsigned long)gid);
- - dprintf(CYGWINIDLVL, "userlist\t='%s'\n", grent.userlist);
- -#endif
- -
- -found:
- - if (res_group_name)
- - (void)strcpy_s(res_group_name, VAL_LEN, grent.group_name);
- - *res_gid = gid;
- - res = 0;
- - }
- -
- -fail:
- - if (getent_pipe)
- - (void)_pclose(getent_pipe);
- -
- - if (res == 0) {
- - dprintf(CYGWINIDLVL, "<-- cygwin_getent_group('%s'): "
- - "returning res_gid=%lu, res_group_name='%s'\n",
- - name, (unsigned long)(*res_gid),
- - res_group_name?res_group_name:"<NULL>");
- - }
- - else {
- - dprintf(CYGWINIDLVL,
- - "<-- cygwin_getent_group('%s'): no match found\n",
- - name);
- - }
- -
- - return res;
- -}
- -#endif /* NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN */
- /* generic cache */
- typedef struct list_entry* (*entry_alloc_fn)();
- @@ -906,7 +667,7 @@ static int idmap_lookup_user(
- if (status == NO_ERROR) {
- /* don't return expired entries; query new attributes
- * and overwrite the entry with cache_insert() */
- - if ((time(NULL) - user->last_updated) < context->config.cache_ttl)
- + if (difftime(time(NULL), user->last_updated) < (double)context->config.cache_ttl)
- goto out;
- }
- #ifndef NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN
- @@ -1060,7 +821,7 @@ static int idmap_lookup_group(
- if (status == NO_ERROR) {
- /* don't return expired entries; query new attributes
- * and overwrite the entry with cache_insert() */
- - if ((time(NULL) - group->last_updated) < context->config.cache_ttl)
- + if (difftime(time(NULL), group->last_updated) < (double)context->config.cache_ttl)
- goto out;
- }
- #ifndef NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN
- diff --git a/daemon/idmap_cygwin.c b/daemon/idmap_cygwin.c
- new file mode 100644
- index 0000000..8d62f2f
- --- /dev/null
- +++ b/daemon/idmap_cygwin.c
- @@ -0,0 +1,243 @@
- +/* NFSv4.1 client for Windows
- + * Copyright 2023 Roland Mainz <roland.mainz@nrubsig.org>
- + *
- + * Roland Mainz <roland.mainz@nrubsig.org>
- + *
- + * This library is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU Lesser General Public License as published by
- + * the Free Software Foundation; either version 2.1 of the License, or (at
- + * your option) any later version.
- + *
- + * This library is distributed in the hope that it will be useful, but
- + * without any warranty; without even the implied warranty of merchantability
- + * or fitness for a particular purpose. See the GNU Lesser General Public
- + * License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public License
- + * along with this library; if not, write to the Free Software Foundation,
- + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- + */
- +
- +#include <Windows.h>
- +#include <strsafe.h>
- +#include <Winldap.h>
- +#include <stdlib.h> /* for strtoul() */
- +#include <errno.h>
- +#include <time.h>
- +
- +#include "nfs41_build_features.h"
- +#include "idmap.h"
- +#include "nfs41_const.h"
- +#include "list.h"
- +#include "daemon_debug.h"
- +#ifdef NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN
- +#include "cpvparser1.h"
- +#endif /* NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN */
- +
- +#define CYGWINIDLVL 0 /* dprintf level for idmap logging */
- +
- +#define VAL_LEN 257
- +
- +#define CYGWIN_IDMAPPER_SCRIPT \
- + ("C:\\cygwin64\\bin\\ksh93.exe " \
- + "/home/roland_mainz/work/msnfs41_uidmapping/ms-nfs41-client/cygwin_idmapper.ksh")
- +
- +
- +#ifdef NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN
- +int cygwin_getent_passwd(const char *name, char *res_loginname, uid_t *res_uid, gid_t *res_gid)
- +{
- + char cmdbuff[1024];
- + char buff[2048];
- + size_t num_buff_read;
- + FILE* script_pipe = NULL;
- + int res = 1;
- + unsigned long uid = -1;
- + unsigned long gid = -1;
- + void *cpvp = NULL;
- + int numcnv = 0;
- + int i = 0;
- + cpv_name_val cnv[256] = { 0 };
- + cpv_name_val *cnv_cur = NULL;
- + const char *localaccoutname = NULL;
- +
- + dprintf(CYGWINIDLVL, "--> cygwin_getent_passwd('%s')\n", name);
- +
- + /* fixme: better quoting for |name| needed */
- + (void)snprintf(cmdbuff, sizeof(cmdbuff), "%s nfsserveruser2localaccount \"%s\"",
- + CYGWIN_IDMAPPER_SCRIPT,
- + name);
- + if ((script_pipe = _popen(cmdbuff, "rt")) == NULL) {
- + dprintf(0, "cygwin_getent_passwd: '%s' failed, errno='%s'\n",
- + cmdbuff,
- + strerror(errno));
- + goto fail;
- + }
- +
- + num_buff_read = fread(buff, 1, sizeof(buff), script_pipe);
- + if (num_buff_read < 10) {
- + dprintf(0, "cygwin_getent_passwd: Could not read enough data, returned %d\n", (int)num_buff_read);
- + goto fail;
- + }
- +
- + buff[num_buff_read] = '\0';
- +
- + cpvp = cpv_create_parser(buff, 0/*CPVFLAG_DEBUG_OUTPUT*/);
- + if (!cpvp) {
- + dprintf(0, "cygwin_getent_passwd: Could not create parser\n");
- + goto fail;
- + }
- +
- + if (cpv_read_cpv_header(cpvp)) {
- + dprintf(0, "cygwin_getent_passwd: cpv_read_cpv_header failed\n");
- + goto fail;
- + }
- +
- + for (numcnv=0 ; cpv_parse_name_val(cpvp, &cnv[numcnv]) == 0 ; numcnv++) {
- + }
- +
- + for (i=0 ; i < numcnv ; i++) {
- + cnv_cur = &cnv[i];
- + if (!strcmp("localaccoutname", cnv_cur->cpv_name)) {
- + localaccoutname = cnv_cur->cpv_value;
- + }
- + else if (!strcmp("localuid", cnv_cur->cpv_name)) {
- + errno = 0;
- + uid = strtol(cnv_cur->cpv_value, NULL, 10);
- + if (errno != 0)
- + goto fail;
- + }
- + else if (!strcmp("localgid", cnv_cur->cpv_name)) {
- + errno = 0;
- + gid = strtol(cnv_cur->cpv_value, NULL, 10);
- + if (errno != 0)
- + goto fail;
- + }
- + }
- +
- + if (res_loginname)
- + (void)strcpy_s(res_loginname, VAL_LEN, localaccoutname);
- + *res_uid = uid;
- + *res_gid = gid;
- + res = 0;
- +
- +fail:
- + if (script_pipe)
- + (void)_pclose(script_pipe);
- +
- + for (i=0 ; i < numcnv ; i++) {
- + cpv_free_name_val_data(&cnv[i]);
- + }
- +
- + cpv_free_parser(cpvp);
- +
- + if (res == 0) {
- + dprintf(CYGWINIDLVL, "<-- cygwin_getent_passwd('%s'): "
- + "returning res_uid=%lu, res_gid=%lu, res_loginname='%s'\n",
- + name,
- + (unsigned long)(*res_uid),
- + (unsigned long)(*res_gid),
- + res_loginname?res_loginname:"<NULL>");
- + }
- + else {
- + dprintf(CYGWINIDLVL, "<-- cygwin_getent_passwd('%s'): no match found\n",
- + name);
- + }
- +
- + return res;
- +}
- +
- +int cygwin_getent_group(const char* name, char* res_group_name, gid_t* res_gid)
- +{
- + char cmdbuff[1024];
- + char buff[2048];
- + size_t num_buff_read;
- + FILE* script_pipe = NULL;
- + int res = 1;
- + unsigned long gid = -1;
- + void *cpvp = NULL;
- + int numcnv = 0;
- + int i = 0;
- + cpv_name_val cnv[256] = { 0 };
- + cpv_name_val *cnv_cur = NULL;
- +
- + const char *localgroupname = NULL;
- +
- + dprintf(CYGWINIDLVL, "--> cygwin_getent_group('%s')\n", name);
- +
- + /* fixme: better quoting for |name| needed */
- + (void)snprintf(cmdbuff, sizeof(cmdbuff), "%s nfsserveruser2localgroup \"%s\"",
- + CYGWIN_IDMAPPER_SCRIPT,
- + name);
- + if ((script_pipe = _popen(cmdbuff, "rt")) == NULL) {
- + dprintf(0, "cygwin_getent_group: '%s' failed, errno='%s'\n",
- + cmdbuff,
- + strerror(errno));
- + goto fail;
- + }
- +
- + num_buff_read = fread(buff, 1, sizeof(buff), script_pipe);
- + if (num_buff_read < 10) {
- + dprintf(0, "cygwin_getent_group: Could not read enough data, returned %d\n", (int)num_buff_read);
- + goto fail;
- + }
- +
- + buff[num_buff_read] = '\0';
- +
- + cpvp = cpv_create_parser(buff, 0/*CPVFLAG_DEBUG_OUTPUT*/);
- + if (!cpvp) {
- + dprintf(0, "cygwin_getent_group: Could not create parser\n");
- + goto fail;
- + }
- +
- + if (cpv_read_cpv_header(cpvp)) {
- + dprintf(0, "cygwin_getent_group: cpv_read_cpv_header failed\n");
- + goto fail;
- + }
- +
- + for (numcnv=0 ; cpv_parse_name_val(cpvp, &cnv[numcnv]) == 0 ; numcnv++) {
- + }
- +
- + for (i=0 ; i < numcnv ; i++) {
- + cnv_cur = &cnv[i];
- + if (!strcmp("localgroupname", cnv_cur->cpv_name)) {
- + localgroupname = cnv_cur->cpv_value;
- + }
- + else if (!strcmp("localgid", cnv_cur->cpv_name)) {
- + errno = 0;
- + gid = strtol(cnv_cur->cpv_value, NULL, 10);
- + if (errno != 0)
- + goto fail;
- + }
- + }
- +
- + if (res_group_name)
- + (void)strcpy_s(res_group_name, VAL_LEN, localgroupname);
- + *res_gid = gid;
- + res = 0;
- +
- +fail:
- + if (script_pipe)
- + (void)_pclose(script_pipe);
- +
- + for (i=0 ; i < numcnv ; i++) {
- + cpv_free_name_val_data(&cnv[i]);
- + }
- +
- + cpv_free_parser(cpvp);
- +
- + if (res == 0) {
- + dprintf(CYGWINIDLVL, "<-- cygwin_getent_group('%s'): "
- + "returning res_gid=%lu, res_group_name='%s'\n",
- + name,
- + (unsigned long)(*res_gid),
- + res_group_name?res_group_name:"<NULL>");
- + }
- + else {
- + dprintf(CYGWINIDLVL, "<-- cygwin_getent_group('%s'): no match found\n",
- + name);
- + }
- +
- + return res;
- +}
- +#endif /* NFS41_DRIVER_FEATURE_NAMESERVICE_CYGWIN */
- +
idmapper prototype rework 2023-11-27
Posted by Anonymous on Mon 27th Nov 2023 19:07
raw | new post
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.