diff --git a/src/Makefile b/src/Makefile index a97e52d..34d816a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -32,7 +32,7 @@ LIB_LIBS += Com SHRLIB_VERSION ?= $(EPICS_PVA_MAJOR_VERSION).$(EPICS_PVA_MINOR_VERSION).$(EPICS_PVA_MAINTENANCE_VERSION) # needed for Windows -LIB_SYS_LIBS_WIN32 += ws2_32 +LIB_SYS_LIBS_WIN32 += netapi32 ws2_32 include $(TOP)/configure/RULES diff --git a/src/remote/pv/security.h b/src/remote/pv/security.h index 68f2e5b..87cab62 100644 --- a/src/remote/pv/security.h +++ b/src/remote/pv/security.h @@ -299,6 +299,13 @@ public: void run(const std::tr1::shared_ptr& peer); }; +/** @brief Query OS specific DB for role/group names assocated with a user account. + * @param account User name + * @param roles Role names are added to this set. Existing names are not removed. + */ +epicsShareFunc +void osdGetRoles(const std::string &account, PeerInfo::roles_t& roles); + } } diff --git a/src/utils/Makefile b/src/utils/Makefile index 0cbe92a..fd35b02 100644 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -14,6 +14,7 @@ INC += pv/fairQueue.h INC += pv/requester.h INC += pv/destroyable.h +pvAccess_SRCS += getgroups.cpp pvAccess_SRCS += hexDump.cpp pvAccess_SRCS += inetAddressUtil.cpp pvAccess_SRCS += logger.cpp diff --git a/src/utils/getgroups.cpp b/src/utils/getgroups.cpp new file mode 100644 index 0000000..e3580b5 --- /dev/null +++ b/src/utils/getgroups.cpp @@ -0,0 +1,132 @@ + +#include + +#if defined(_WIN32) +# define USE_LANMAN +#elif !defined(__rtems__) && !defined(vxWorks) +# define USE_UNIX_GROUPS +#endif + +/* conditionally include any system headers */ +#if defined(USE_UNIX_GROUPS) + +#include +#include +#include +#include +#include + +#elif defined(USE_LANMAN) + +#include +#include +#include + +#endif + +#define epicsExportSharedSymbols +#include + +namespace epics { +namespace pvAccess { + +#if defined(USE_UNIX_GROUPS) + +void osdGetRoles(const std::string& account, PeerInfo::roles_t& roles) +{ + passwd *user = getpwnam(account.c_str()); + if(!user) + return; // don't know who this is + + typedef std::set gids_t; + gids_t gids; + + gids.insert(user->pw_gid); // include primary group + + // include supplementary groups + { + std::vector gtemp(16); + int gcount = int(gtemp.size()); + + if(getgrouplist(user->pw_name, user->pw_gid, >emp[0], &gcount)==-1 && gcount>=0 && gcount<=NGROUPS_MAX) { + gtemp.resize(gcount); + // try again. This time if we fail, then there is some other error + getgrouplist(user->pw_name, user->pw_gid, >emp[0], &gcount); + } + gtemp.resize(std::min(gcount, NGROUPS_MAX)); + + for(size_t i=0, N=gtemp.size(); igr_name); + } +} + +#elif defined(USE_LANMAN) + +void osdGetRoles(const std::string& account, PeerInfo::roles_t& roles) +{ + NET_API_STATUS sts; + LPLOCALGROUP_USERS_INFO_0 pinfo = NULL; + DWORD ninfo = 0, nmaxinfo = 0; + std::vector wbuf; + + { + size_t N = mbstowcs(NULL, account.c_str(), 0); + if(N==size_t(-1)) + return; // username has invalid MB char + wbuf.resize(N+1); + N = mbstowcs(&wbuf[0], account.c_str(), account.size()); + assert(N+1==wbuf.size()); + wbuf[N] = 0; // paranoia + } + + // this call may involve network I/O + sts = NetUserGetLocalGroups(NULL, &wbuf[0], 0, + LG_INCLUDE_INDIRECT, + (LPBYTE*)&pinfo, + MAX_PREFERRED_LENGTH, + &ninfo, &nmaxinfo); + + if(sts!=NERR_Success) + return; // silently do nothing. + + try { + std::vector buf; + + for(DWORD i=0; i