You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by William R Speirs <bi...@gmail.com> on 2011/01/02 06:08:55 UTC

Re: Getting the groups a user belongs to

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-