You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Bill Speirs <bi...@gmail.com> on 2010/12/13 15:33:50 UTC
Re: dev Digest of: get.23632
On Fri, Dec 10, 2010 at 1:12 PM, <de...@apr.apache.org> wrote:
> From: "William A. Rowe Jr." <wr...@rowe-clan.net>
> To: dev@apr.apache.org
> Date: Thu, 09 Dec 2010 22:09:20 -0600
> Subject: Re: Getting the groups a user belongs to
>
> It seems sensible, the only hassle is the performance penalty that could be assessed
> for hitting the domain server. Can you check this out and benchmark it?
I can try, but what are you looking for specifically: Win Vs. Linux or
Domain Vs. No Domain?
Domain Vs. No Domain is going to be tough for me as my domain
controller and workstation are on the same network, so the latency
won't really show. Whereas, in a production environment that is under
heavy load, your mileage will greatly vary.
>> The other issue is that on Windows I get back a char* for the groups; whereas, on
>> Unix/Linux I get back a gid list. Is there a preference? Would people rather a function
>> that returns a gid list or a char* list?
>
> Well, we should treat them as apr_gid_t, which on win32 would devolve to a pointer
> to a full UUID of the appropriate group (and we then unwind the identifier into a
> human-readable string with the appropriate apr_group_name_get function).
In Linux this is a non-issue as the function naturally returns
apr_gid_t; whereas, with Windows I only get back a char* for the
group. I can call LookupAccountName on each name to get the
SID/apr_gid_t. If there is a function to get apr_gid_ts for the groups
a user is a member of, I am unaware of such a function.
Bill-
P.S. Sorry for the late response...
Re: Getting the groups a user belongs to
Posted by William R Speirs <bi...@gmail.com>.
Bump...
Haven't heard anything, but it was over the holidays so I figured most people
had checked-out.
Thanks...
Bill-
On 12/23/2010 04:08 PM, William R Speirs wrote:
> I took a first stab at the Windows code for this... it's ugly. There is a lot of
> apr_wchar_t* <-> char* conversion code. Is there an easier way to do this?
>
> If not, then maybe it would be helpful to create two functions with the
> following signatures that do all of the string length and allocation work for you:
>
> apr_wchar_t* apr_conv_utf8_to_ucs2(char *str, apr_pool_t *p);
> char* apr_conv_ucs2_to_utf8(apr_wchar_t *str, apr_pool_t *p);
>
>
> Here is my code, not sure if this name is 100% consistent with the rest of the
> codebase:
>
> APR_DECLARE(apr_status_t) apr_uid_groups_get(apr_gid_t **groups, int *ngroup,
> const char *username, apr_pool_t *p)
> {
> #ifdef _WIN32_WCE
> return APR_ENOTIMPL;
> #else
> GROUP_USERS_INFO_0 *pGroups = NULL;
> DWORD entriesRead = 0;
> DWORD totalEntries = 0;
> NET_API_STATUS status;
> FIXED_INFO *pFixedInfo = NULL;
> ULONG infoSize = 0;
> DWORD i;
>
> apr_wchar_t *wUsername;
> apr_size_t wUsernameLen;
>
> apr_wchar_t *fullDomain;
> apr_size_t fullDomainLen;
> apr_size_t domainLen;
>
> char *groupName;
>
> // first call is to get the size
> status = GetNetworkParams(pFixedInfo, &infoSize);
>
> pFixedInfo = (FIXED_INFO*)apr_palloc(p, infoSize);
>
> // now make the actual call
> status = GetNetworkParams(pFixedInfo, &infoSize);
>
> // printf("DOMAIN: %s\n", pFixedInfo->DomainName);
>
> if(NERR_Success != status)
> return APR_EINVAL;
>
> // convert the username to an apr_wchar_t
> domainLen = lstrlen(username); // re-use of var here
> wUsernameLen = lstrlen(username) * sizeof(apr_wchar_t);
> wUsername = (apr_wchar_t*)apr_palloc(p, wUsernameLen);
> apr_conv_utf8_to_ucs2(username, &domainLen, wUsername, &wUsernameLen);
>
> // get the length of the domain string
> domainLen = lstrlenA(pFixedInfo->DomainName);
>
> // if there is no domain name, then get local groups
> if(0 == domainLen) {
> // printf("NO DOMAIN\n");
>
> status = NetUserGetLocalGroups(NULL, wUsername, 0,
> LG_INCLUDE_INDIRECT,
> (LPBYTE*) &pGroups,
> MAX_PREFERRED_LENGTH,
> &entriesRead, &totalEntries);
>
> if(NERR_Success != status) {
> NetApiBufferFree(pGroups);
> return APR_EINVAL;
> }
>
> } else { // we have a domain, get those groups
> domainLen = lstrlen(pFixedInfo->DomainName);
> fullDomainLen = (2 + domainLen) * sizeof(apr_wchar_t);
> fullDomain = (apr_wchar_t*)apr_palloc(p, fullDomainLen);
>
> // add the \\ to the start of the domain
> fullDomain[0] = '\\';
> fullDomain[1] = '\\';
> fullDomainLen -= 2;
>
> // convert over to an apr_wchar_t
> apr_conv_utf8_to_ucs2(pFixedInfo->DomainName, &domainLen,
> fullDomain+2, &fullDomainLen);
>
> status = NetUserGetGroups(fullDomain, wUsername, 0,
> (LPBYTE*) &pGroups,
> MAX_PREFERRED_LENGTH,
> &entriesRead, &totalEntries);
>
> if(NERR_Success != status) {
> NetApiBufferFree(pGroups);
> return APR_EINVAL;
> }
> }
>
> // allocate space for all of the apr_gid_t
> *groups = (apr_gid_t*)apr_palloc(p, entriesRead);
> *ngroup = entriesRead;
>
> // we have all of the groups, but as strings
> for(i=0; i < entriesRead; ++i) {
> printf("GROUP: %S\n", pGroups[i].grui0_name);
>
> // convert the wchar_t group name to a char* group name
> domainLen = lstrlenW(pGroups[i].grui0_name);
> wUsernameLen = domainLen * sizeof(char);
> groupName = (char*)apr_palloc(p, wUsernameLen);
> apr_conv_ucs2_to_utf8(pGroups[i].grui0_name, &domainLen,
> groupName, &wUsernameLen);
>
> apr_gid_get(*groups[i], groupName, p);
> }
>
> // free the memory associated with the groups
> NetApiBufferFree(pGroups);
>
> return APR_SUCCESS;
>
> #endif
> }
>
>
>
> Thoughts?
>
> Bill-
>
> On 12/13/2010 09:33 AM, Bill Speirs wrote:
>>>> The other issue is that on Windows I get back a char* for the groups;
>>>> whereas, on
>>>> Unix/Linux I get back a gid list. Is there a preference? Would people rather
>>>> a function
>>>> that returns a gid list or a char* list?
>>>
>>> Well, we should treat them as apr_gid_t, which on win32 would devolve to a
>>> pointer
>>> to a full UUID of the appropriate group (and we then unwind the identifier
>>> into a
>>> human-readable string with the appropriate apr_group_name_get function).
>>
>> In Linux this is a non-issue as the function naturally returns
>> apr_gid_t; whereas, with Windows I only get back a char* for the
>> group. I can call LookupAccountName on each name to get the
>> SID/apr_gid_t. If there is a function to get apr_gid_ts for the groups
>> a user is a member of, I am unaware of such a function.
>>
>> Bill-
Re: Getting the groups a user belongs to
Posted by William R Speirs <bi...@gmail.com>.
I took a first stab at the Windows code for this... it's ugly. There is a lot of
apr_wchar_t* <-> char* conversion code. Is there an easier way to do this?
If not, then maybe it would be helpful to create two functions with the
following signatures that do all of the string length and allocation work for you:
apr_wchar_t* apr_conv_utf8_to_ucs2(char *str, apr_pool_t *p);
char* apr_conv_ucs2_to_utf8(apr_wchar_t *str, apr_pool_t *p);
Here is my code, not sure if this name is 100% consistent with the rest of the
codebase:
APR_DECLARE(apr_status_t) apr_uid_groups_get(apr_gid_t **groups, int *ngroup,
const char *username, apr_pool_t *p)
{
#ifdef _WIN32_WCE
return APR_ENOTIMPL;
#else
GROUP_USERS_INFO_0 *pGroups = NULL;
DWORD entriesRead = 0;
DWORD totalEntries = 0;
NET_API_STATUS status;
FIXED_INFO *pFixedInfo = NULL;
ULONG infoSize = 0;
DWORD i;
apr_wchar_t *wUsername;
apr_size_t wUsernameLen;
apr_wchar_t *fullDomain;
apr_size_t fullDomainLen;
apr_size_t domainLen;
char *groupName;
// first call is to get the size
status = GetNetworkParams(pFixedInfo, &infoSize);
pFixedInfo = (FIXED_INFO*)apr_palloc(p, infoSize);
// now make the actual call
status = GetNetworkParams(pFixedInfo, &infoSize);
// printf("DOMAIN: %s\n", pFixedInfo->DomainName);
if(NERR_Success != status)
return APR_EINVAL;
// convert the username to an apr_wchar_t
domainLen = lstrlen(username); // re-use of var here
wUsernameLen = lstrlen(username) * sizeof(apr_wchar_t);
wUsername = (apr_wchar_t*)apr_palloc(p, wUsernameLen);
apr_conv_utf8_to_ucs2(username, &domainLen, wUsername, &wUsernameLen);
// get the length of the domain string
domainLen = lstrlenA(pFixedInfo->DomainName);
// if there is no domain name, then get local groups
if(0 == domainLen) {
// printf("NO DOMAIN\n");
status = NetUserGetLocalGroups(NULL, wUsername, 0,
LG_INCLUDE_INDIRECT,
(LPBYTE*) &pGroups,
MAX_PREFERRED_LENGTH,
&entriesRead, &totalEntries);
if(NERR_Success != status) {
NetApiBufferFree(pGroups);
return APR_EINVAL;
}
} else { // we have a domain, get those groups
domainLen = lstrlen(pFixedInfo->DomainName);
fullDomainLen = (2 + domainLen) * sizeof(apr_wchar_t);
fullDomain = (apr_wchar_t*)apr_palloc(p, fullDomainLen);
// add the \\ to the start of the domain
fullDomain[0] = '\\';
fullDomain[1] = '\\';
fullDomainLen -= 2;
// convert over to an apr_wchar_t
apr_conv_utf8_to_ucs2(pFixedInfo->DomainName, &domainLen,
fullDomain+2, &fullDomainLen);
status = NetUserGetGroups(fullDomain, wUsername, 0,
(LPBYTE*) &pGroups,
MAX_PREFERRED_LENGTH,
&entriesRead, &totalEntries);
if(NERR_Success != status) {
NetApiBufferFree(pGroups);
return APR_EINVAL;
}
}
// allocate space for all of the apr_gid_t
*groups = (apr_gid_t*)apr_palloc(p, entriesRead);
*ngroup = entriesRead;
// we have all of the groups, but as strings
for(i=0; i < entriesRead; ++i) {
printf("GROUP: %S\n", pGroups[i].grui0_name);
// convert the wchar_t group name to a char* group name
domainLen = lstrlenW(pGroups[i].grui0_name);
wUsernameLen = domainLen * sizeof(char);
groupName = (char*)apr_palloc(p, wUsernameLen);
apr_conv_ucs2_to_utf8(pGroups[i].grui0_name, &domainLen,
groupName, &wUsernameLen);
apr_gid_get(*groups[i], groupName, p);
}
// free the memory associated with the groups
NetApiBufferFree(pGroups);
return APR_SUCCESS;
#endif
}
Thoughts?
Bill-
On 12/13/2010 09:33 AM, Bill Speirs wrote:
>>> The other issue is that on Windows I get back a char* for the groups; whereas, on
>>> Unix/Linux I get back a gid list. Is there a preference? Would people rather a function
>>> that returns a gid list or a char* list?
>>
>> Well, we should treat them as apr_gid_t, which on win32 would devolve to a pointer
>> to a full UUID of the appropriate group (and we then unwind the identifier into a
>> human-readable string with the appropriate apr_group_name_get function).
>
> In Linux this is a non-issue as the function naturally returns
> apr_gid_t; whereas, with Windows I only get back a char* for the
> group. I can call LookupAccountName on each name to get the
> SID/apr_gid_t. If there is a function to get apr_gid_ts for the groups
> a user is a member of, I am unaware of such a function.
>
> Bill-