2007-12-21 20:57:34 +03:00
/*
Unix SMB / CIFS implementation .
Winbind client API
Copyright ( C ) Gerald ( Jerry ) Carter 2007
2010-04-03 14:01:43 +04:00
Copyright ( C ) Volker Lendecke 2010
2007-12-21 20:57:34 +03:00
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 3 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
Library General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
/* Required Headers */
2009-06-05 00:32:21 +04:00
# include "replace.h"
2007-12-21 20:57:34 +03:00
# include "libwbclient.h"
2010-01-23 21:38:28 +03:00
# include "../winbind_client.h"
2007-12-21 20:57:34 +03:00
2011-03-04 07:38:04 +03:00
/* Convert a sid to a string into a buffer. Return the string
* length . If buflen is too small , return the string length that would
* result if it was long enough . */
int wbcSidToStringBuf ( const struct wbcDomainSid * sid , char * buf , int buflen )
2007-12-21 20:57:34 +03:00
{
2013-07-31 18:38:19 +04:00
uint64_t id_auth ;
2011-03-04 07:38:04 +03:00
int i , ofs ;
2007-12-21 20:57:34 +03:00
if ( ! sid ) {
2011-03-04 07:38:04 +03:00
strlcpy ( buf , " (NULL SID) " , buflen ) ;
return 10 ; /* strlen("(NULL SID)") */
2007-12-21 20:57:34 +03:00
}
2013-07-31 18:38:19 +04:00
id_auth = ( uint64_t ) sid - > id_auth [ 5 ] +
( ( uint64_t ) sid - > id_auth [ 4 ] < < 8 ) +
( ( uint64_t ) sid - > id_auth [ 3 ] < < 16 ) +
( ( uint64_t ) sid - > id_auth [ 2 ] < < 24 ) +
( ( uint64_t ) sid - > id_auth [ 1 ] < < 32 ) +
( ( uint64_t ) sid - > id_auth [ 0 ] < < 40 ) ;
ofs = snprintf ( buf , buflen , " S-%hhu- " , ( unsigned char ) sid - > sid_rev_num ) ;
if ( id_auth > = UINT32_MAX ) {
ofs + = snprintf ( buf + ofs , MAX ( buflen - ofs , 0 ) , " 0x%llx " ,
( unsigned long long ) id_auth ) ;
} else {
ofs + = snprintf ( buf + ofs , MAX ( buflen - ofs , 0 ) , " %llu " ,
( unsigned long long ) id_auth ) ;
}
2007-12-21 20:57:34 +03:00
2010-04-03 13:14:23 +04:00
for ( i = 0 ; i < sid - > num_auths ; i + + ) {
2013-07-31 18:38:19 +04:00
ofs + = snprintf ( buf + ofs , MAX ( buflen - ofs , 0 ) , " -%u " ,
( unsigned int ) sid - > sub_auths [ i ] ) ;
2007-12-21 20:57:34 +03:00
}
2011-03-04 07:38:04 +03:00
return ofs ;
}
/* Convert a binary SID to a character string */
wbcErr wbcSidToString ( const struct wbcDomainSid * sid ,
char * * sid_string )
{
char buf [ WBC_SID_STRING_BUFLEN ] ;
char * result ;
int len ;
if ( ! sid ) {
return WBC_ERR_INVALID_SID ;
}
len = wbcSidToStringBuf ( sid , buf , sizeof ( buf ) ) ;
if ( len + 1 > sizeof ( buf ) ) {
return WBC_ERR_INVALID_SID ;
}
result = ( char * ) wbcAllocateMemory ( len + 1 , 1 , NULL ) ;
if ( result = = NULL ) {
return WBC_ERR_NO_MEMORY ;
}
memcpy ( result , buf , len + 1 ) ;
2007-12-21 20:57:34 +03:00
2010-04-03 13:14:23 +04:00
* sid_string = result ;
return WBC_ERR_SUCCESS ;
2007-12-21 20:57:34 +03:00
}
2013-07-31 18:38:18 +04:00
# define AUTHORITY_MASK (~(0xffffffffffffULL))
2008-12-09 15:18:06 +03:00
/* Convert a character string to a binary SID */
2007-12-21 20:57:34 +03:00
wbcErr wbcStringToSid ( const char * str ,
struct wbcDomainSid * sid )
{
const char * p ;
char * q ;
2013-07-31 18:38:18 +04:00
uint64_t x ;
2007-12-21 20:57:34 +03:00
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
if ( ! sid ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
/* Sanity check for either "S-" or "s-" */
if ( ! str
| | ( str [ 0 ] ! = ' S ' & & str [ 0 ] ! = ' s ' )
2008-06-27 13:13:07 +04:00
| | ( str [ 1 ] ! = ' - ' ) )
2007-12-21 20:57:34 +03:00
{
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
/* Get the SID revision number */
p = str + 2 ;
2013-07-31 18:38:18 +04:00
x = ( uint64_t ) strtoul ( p , & q , 10 ) ;
if ( x = = 0 | | x > UINT8_MAX | | ! q | | * q ! = ' - ' ) {
2007-12-21 20:57:34 +03:00
wbc_status = WBC_ERR_INVALID_SID ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
sid - > sid_rev_num = ( uint8_t ) x ;
2013-07-31 18:38:18 +04:00
/*
* Next the Identifier Authority . This is stored big - endian in a
* 6 byte array . If the authority value is > = UINT_MAX , then it should
* be expressed as a hex value , according to MS - DTYP .
*/
2007-12-21 20:57:34 +03:00
p = q + 1 ;
2013-07-31 18:38:18 +04:00
x = strtoull ( p , & q , 0 ) ;
if ( ! q | | * q ! = ' - ' | | ( x & AUTHORITY_MASK ) ) {
2007-12-21 20:57:34 +03:00
wbc_status = WBC_ERR_INVALID_SID ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2013-07-31 18:38:18 +04:00
sid - > id_auth [ 5 ] = ( x & 0x0000000000ffULL ) ;
sid - > id_auth [ 4 ] = ( x & 0x00000000ff00ULL ) > > 8 ;
sid - > id_auth [ 3 ] = ( x & 0x000000ff0000ULL ) > > 16 ;
sid - > id_auth [ 2 ] = ( x & 0x0000ff000000ULL ) > > 24 ;
sid - > id_auth [ 1 ] = ( x & 0x00ff00000000ULL ) > > 32 ;
sid - > id_auth [ 0 ] = ( x & 0xff0000000000ULL ) > > 40 ;
2007-12-21 20:57:34 +03:00
/* now read the the subauthorities */
p = q + 1 ;
sid - > num_auths = 0 ;
2008-05-23 15:59:53 +04:00
while ( sid - > num_auths < WBC_MAXSUBAUTHS ) {
2013-07-31 18:38:18 +04:00
x = strtoull ( p , & q , 10 ) ;
2008-07-17 20:23:30 +04:00
if ( p = = q )
2007-12-21 20:57:34 +03:00
break ;
2013-07-31 18:38:18 +04:00
if ( x > UINT32_MAX ) {
2008-06-27 13:19:26 +04:00
wbc_status = WBC_ERR_INVALID_SID ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2007-12-21 20:57:34 +03:00
sid - > sub_auths [ sid - > num_auths + + ] = x ;
2011-03-08 20:24:08 +03:00
if ( * q ! = ' - ' ) {
2007-12-21 20:57:34 +03:00
break ;
2011-03-08 20:24:08 +03:00
}
2007-12-21 20:57:34 +03:00
p = q + 1 ;
}
/* IF we ended early, then the SID could not be converted */
if ( q & & * q ! = ' \0 ' ) {
wbc_status = WBC_ERR_INVALID_SID ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
wbc_status = WBC_ERR_SUCCESS ;
done :
return wbc_status ;
}
2009-05-28 02:57:32 +04:00
2008-12-09 15:18:06 +03:00
/* Convert a domain and name to SID */
2007-12-21 20:57:34 +03:00
wbcErr wbcLookupName ( const char * domain ,
const char * name ,
struct wbcDomainSid * sid ,
enum wbcSidType * name_type )
{
struct winbindd_request request ;
struct winbindd_response response ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
if ( ! sid | | ! name_type ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
/* Initialize request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
/* dst is already null terminated from the memset above */
strncpy ( request . data . name . dom_name , domain ,
sizeof ( request . data . name . dom_name ) - 1 ) ;
strncpy ( request . data . name . name , name ,
sizeof ( request . data . name . name ) - 1 ) ;
wbc_status = wbcRequestResponse ( WINBINDD_LOOKUPNAME ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
wbc_status = wbcStringToSid ( response . data . sid . sid , sid ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
* name_type = ( enum wbcSidType ) response . data . sid . type ;
wbc_status = WBC_ERR_SUCCESS ;
done :
return wbc_status ;
}
2009-04-24 18:24:56 +04:00
2008-12-09 15:18:06 +03:00
/* Convert a SID to a domain and name */
2007-12-21 20:57:34 +03:00
wbcErr wbcLookupSid ( const struct wbcDomainSid * sid ,
2008-06-17 16:53:07 +04:00
char * * pdomain ,
char * * pname ,
enum wbcSidType * pname_type )
2007-12-21 20:57:34 +03:00
{
struct winbindd_request request ;
struct winbindd_response response ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
2010-04-03 14:01:43 +04:00
char * domain , * name ;
2007-12-21 20:57:34 +03:00
if ( ! sid ) {
2010-04-03 14:01:43 +04:00
return WBC_ERR_INVALID_PARAM ;
2007-12-21 20:57:34 +03:00
}
/* Initialize request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
2011-03-04 07:44:23 +03:00
wbcSidToStringBuf ( sid , request . data . sid , sizeof ( request . data . sid ) ) ;
2007-12-21 20:57:34 +03:00
/* Make request */
2010-04-03 14:01:43 +04:00
wbc_status = wbcRequestResponse ( WINBINDD_LOOKUPSID , & request ,
& response ) ;
if ( ! WBC_ERROR_IS_OK ( wbc_status ) ) {
return wbc_status ;
}
2007-12-21 20:57:34 +03:00
/* Copy out result */
2010-04-03 14:01:43 +04:00
wbc_status = WBC_ERR_NO_MEMORY ;
domain = NULL ;
name = NULL ;
2007-12-21 20:57:34 +03:00
2010-04-03 14:01:43 +04:00
domain = wbcStrDup ( response . data . name . dom_name ) ;
if ( domain = = NULL ) {
goto done ;
2008-06-17 16:53:07 +04:00
}
2010-04-03 14:01:43 +04:00
name = wbcStrDup ( response . data . name . name ) ;
if ( name = = NULL ) {
goto done ;
2007-12-21 20:57:34 +03:00
}
2010-04-03 14:01:43 +04:00
if ( pdomain ! = NULL ) {
* pdomain = domain ;
domain = NULL ;
}
if ( pname ! = NULL ) {
* pname = name ;
name = NULL ;
}
if ( pname_type ! = NULL ) {
* pname_type = ( enum wbcSidType ) response . data . name . type ;
}
wbc_status = WBC_ERR_SUCCESS ;
done :
wbcFreeMemory ( name ) ;
wbcFreeMemory ( domain ) ;
2007-12-21 20:57:34 +03:00
return wbc_status ;
}
2011-03-08 20:01:21 +03:00
static void wbcDomainInfosDestructor ( void * ptr )
{
struct wbcDomainInfo * i = ( struct wbcDomainInfo * ) ptr ;
while ( i - > short_name ! = NULL ) {
wbcFreeMemory ( i - > short_name ) ;
wbcFreeMemory ( i - > dns_name ) ;
i + = 1 ;
}
}
static void wbcTranslatedNamesDestructor ( void * ptr )
{
struct wbcTranslatedName * n = ( struct wbcTranslatedName * ) ptr ;
while ( n - > name ! = NULL ) {
2012-05-15 21:58:26 +04:00
wbcFreeMemory ( n - > name ) ;
2011-03-08 20:01:21 +03:00
n + = 1 ;
}
}
wbcErr wbcLookupSids ( const struct wbcDomainSid * sids , int num_sids ,
struct wbcDomainInfo * * pdomains , int * pnum_domains ,
struct wbcTranslatedName * * pnames )
{
struct winbindd_request request ;
struct winbindd_response response ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
int buflen , i , extra_len , num_domains , num_names ;
char * sidlist , * p , * q , * extra_data ;
struct wbcDomainInfo * domains = NULL ;
struct wbcTranslatedName * names = NULL ;
buflen = num_sids * ( WBC_SID_STRING_BUFLEN + 1 ) + 1 ;
sidlist = ( char * ) malloc ( buflen ) ;
if ( sidlist = = NULL ) {
return WBC_ERR_NO_MEMORY ;
}
p = sidlist ;
for ( i = 0 ; i < num_sids ; i + + ) {
int remaining ;
int len ;
remaining = buflen - ( p - sidlist ) ;
len = wbcSidToStringBuf ( & sids [ i ] , p , remaining ) ;
if ( len > remaining ) {
free ( sidlist ) ;
return WBC_ERR_UNKNOWN_FAILURE ;
}
p + = len ;
* p + + = ' \n ' ;
}
* p + + = ' \0 ' ;
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
request . extra_data . data = sidlist ;
request . extra_len = p - sidlist ;
wbc_status = wbcRequestResponse ( WINBINDD_LOOKUPSIDS ,
& request , & response ) ;
free ( sidlist ) ;
if ( ! WBC_ERROR_IS_OK ( wbc_status ) ) {
return wbc_status ;
}
extra_len = response . length - sizeof ( struct winbindd_response ) ;
extra_data = ( char * ) response . extra_data . data ;
if ( ( extra_len < = 0 ) | | ( extra_data [ extra_len - 1 ] ! = ' \0 ' ) ) {
goto wbc_err_invalid ;
}
p = extra_data ;
num_domains = strtoul ( p , & q , 10 ) ;
if ( * q ! = ' \n ' ) {
goto wbc_err_invalid ;
}
p = q + 1 ;
domains = ( struct wbcDomainInfo * ) wbcAllocateMemory (
num_domains + 1 , sizeof ( struct wbcDomainInfo ) ,
wbcDomainInfosDestructor ) ;
if ( domains = = NULL ) {
wbc_status = WBC_ERR_NO_MEMORY ;
goto fail ;
}
for ( i = 0 ; i < num_domains ; i + + ) {
q = strchr ( p , ' ' ) ;
if ( q = = NULL ) {
goto wbc_err_invalid ;
}
* q = ' \0 ' ;
wbc_status = wbcStringToSid ( p , & domains [ i ] . sid ) ;
if ( ! WBC_ERROR_IS_OK ( wbc_status ) ) {
goto fail ;
}
p = q + 1 ;
q = strchr ( p , ' \n ' ) ;
if ( q = = NULL ) {
goto wbc_err_invalid ;
}
* q = ' \0 ' ;
domains [ i ] . short_name = wbcStrDup ( p ) ;
if ( domains [ i ] . short_name = = NULL ) {
wbc_status = WBC_ERR_NO_MEMORY ;
goto fail ;
}
p = q + 1 ;
}
num_names = strtoul ( p , & q , 10 ) ;
if ( * q ! = ' \n ' ) {
goto wbc_err_invalid ;
}
p = q + 1 ;
if ( num_names ! = num_sids ) {
goto wbc_err_invalid ;
}
names = ( struct wbcTranslatedName * ) wbcAllocateMemory (
num_names + 1 , sizeof ( struct wbcTranslatedName ) ,
wbcTranslatedNamesDestructor ) ;
if ( names = = NULL ) {
wbc_status = WBC_ERR_NO_MEMORY ;
goto fail ;
}
for ( i = 0 ; i < num_names ; i + + ) {
names [ i ] . domain_index = strtoul ( p , & q , 10 ) ;
2013-11-08 08:38:01 +04:00
if ( names [ i ] . domain_index < 0 ) {
goto wbc_err_invalid ;
}
if ( names [ i ] . domain_index > = num_domains ) {
goto wbc_err_invalid ;
}
2011-03-08 20:01:21 +03:00
if ( * q ! = ' ' ) {
goto wbc_err_invalid ;
}
p = q + 1 ;
names [ i ] . type = strtoul ( p , & q , 10 ) ;
if ( * q ! = ' ' ) {
goto wbc_err_invalid ;
}
p = q + 1 ;
q = strchr ( p , ' \n ' ) ;
if ( q = = NULL ) {
goto wbc_err_invalid ;
}
* q = ' \0 ' ;
names [ i ] . name = wbcStrDup ( p ) ;
if ( names [ i ] . name = = NULL ) {
wbc_status = WBC_ERR_NO_MEMORY ;
goto fail ;
}
p = q + 1 ;
}
if ( * p ! = ' \0 ' ) {
goto wbc_err_invalid ;
}
* pdomains = domains ;
* pnames = names ;
winbindd_free_response ( & response ) ;
return WBC_ERR_SUCCESS ;
wbc_err_invalid :
wbc_status = WBC_ERR_INVALID_RESPONSE ;
fail :
winbindd_free_response ( & response ) ;
wbcFreeMemory ( domains ) ;
wbcFreeMemory ( names ) ;
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Translate a collection of RIDs within a domain to names */
2007-12-21 20:57:34 +03:00
wbcErr wbcLookupRids ( struct wbcDomainSid * dom_sid ,
int num_rids ,
uint32_t * rids ,
2007-12-21 23:18:17 +03:00
const char * * pp_domain_name ,
2008-06-17 17:17:22 +04:00
const char * * * pnames ,
enum wbcSidType * * ptypes )
2007-12-21 20:57:34 +03:00
{
size_t i , len , ridbuf_size ;
char * ridlist ;
char * p ;
struct winbindd_request request ;
struct winbindd_response response ;
2007-12-21 23:18:17 +03:00
char * domain_name = NULL ;
2008-06-17 17:17:22 +04:00
const char * * names = NULL ;
enum wbcSidType * types = NULL ;
2007-12-21 20:57:34 +03:00
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
/* Initialise request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
2008-01-30 01:01:23 +03:00
if ( ! dom_sid | | ( num_rids = = 0 ) ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2011-03-04 07:44:23 +03:00
wbcSidToStringBuf ( dom_sid , request . data . sid , sizeof ( request . data . sid ) ) ;
2007-12-21 20:57:34 +03:00
/* Even if all the Rids were of maximum 32bit values,
we would only have 11 bytes per rid in the final array
( " 4294967296 " + \ n ) . Add one more byte for the
terminating ' \0 ' */
ridbuf_size = ( sizeof ( char ) * 11 ) * num_rids + 1 ;
2010-04-03 15:44:49 +04:00
ridlist = ( char * ) malloc ( ridbuf_size ) ;
2007-12-21 20:57:34 +03:00
BAIL_ON_PTR_ERROR ( ridlist , wbc_status ) ;
len = 0 ;
2010-04-03 15:44:49 +04:00
for ( i = 0 ; i < num_rids ; i + + ) {
len + = snprintf ( ridlist + len , ridbuf_size - len , " %u \n " ,
rids [ i ] ) ;
2007-12-21 20:57:34 +03:00
}
2010-04-03 15:44:49 +04:00
ridlist [ len ] = ' \0 ' ;
len + = 1 ;
2007-12-21 20:57:34 +03:00
request . extra_data . data = ridlist ;
2010-04-03 15:44:49 +04:00
request . extra_len = len ;
2007-12-21 20:57:34 +03:00
wbc_status = wbcRequestResponse ( WINBINDD_LOOKUPRIDS ,
& request ,
& response ) ;
2010-04-03 15:44:49 +04:00
free ( ridlist ) ;
2008-01-25 04:40:35 +03:00
BAIL_ON_WBC_ERROR ( wbc_status ) ;
2007-12-21 20:57:34 +03:00
2010-04-03 15:44:49 +04:00
domain_name = wbcStrDup ( response . data . domain_name ) ;
2007-12-21 23:18:17 +03:00
BAIL_ON_PTR_ERROR ( domain_name , wbc_status ) ;
2007-12-21 20:57:34 +03:00
2010-04-03 15:44:49 +04:00
names = wbcAllocateStringArray ( num_rids ) ;
2008-06-17 17:17:22 +04:00
BAIL_ON_PTR_ERROR ( names , wbc_status ) ;
2007-12-21 20:57:34 +03:00
2010-04-03 15:44:49 +04:00
types = ( enum wbcSidType * ) wbcAllocateMemory (
num_rids , sizeof ( enum wbcSidType ) , NULL ) ;
2008-06-17 17:17:22 +04:00
BAIL_ON_PTR_ERROR ( types , wbc_status ) ;
2007-12-21 20:57:34 +03:00
p = ( char * ) response . extra_data . data ;
for ( i = 0 ; i < num_rids ; i + + ) {
char * q ;
if ( * p = = ' \0 ' ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2010-04-03 15:45:20 +04:00
goto done ;
2007-12-21 20:57:34 +03:00
}
2008-06-17 17:17:22 +04:00
types [ i ] = ( enum wbcSidType ) strtoul ( p , & q , 10 ) ;
2007-12-21 20:57:34 +03:00
if ( * q ! = ' ' ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2010-04-03 15:45:20 +04:00
goto done ;
2007-12-21 20:57:34 +03:00
}
p = q + 1 ;
if ( ( q = strchr ( p , ' \n ' ) ) = = NULL ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2010-04-03 15:45:20 +04:00
goto done ;
2007-12-21 20:57:34 +03:00
}
* q = ' \0 ' ;
2010-04-03 15:44:49 +04:00
names [ i ] = strdup ( p ) ;
2008-06-17 17:17:22 +04:00
BAIL_ON_PTR_ERROR ( names [ i ] , wbc_status ) ;
2007-12-21 20:57:34 +03:00
p = q + 1 ;
}
if ( * p ! = ' \0 ' ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2010-04-03 15:45:20 +04:00
goto done ;
2007-12-21 20:57:34 +03:00
}
wbc_status = WBC_ERR_SUCCESS ;
done :
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & response ) ;
2008-01-03 14:10:27 +03:00
2008-06-17 17:17:22 +04:00
if ( WBC_ERROR_IS_OK ( wbc_status ) ) {
* pp_domain_name = domain_name ;
* pnames = names ;
* ptypes = types ;
}
else {
2010-04-03 15:44:49 +04:00
wbcFreeMemory ( domain_name ) ;
wbcFreeMemory ( names ) ;
wbcFreeMemory ( types ) ;
2007-12-21 20:57:34 +03:00
}
return wbc_status ;
2008-01-03 14:10:27 +03:00
}
2008-03-21 12:18:54 +03:00
2008-12-09 15:18:06 +03:00
/* Get the groups a user belongs to */
2008-03-21 12:18:54 +03:00
wbcErr wbcLookupUserSids ( const struct wbcDomainSid * user_sid ,
bool domain_groups_only ,
uint32_t * num_sids ,
struct wbcDomainSid * * _sids )
{
uint32_t i ;
const char * s ;
struct winbindd_request request ;
struct winbindd_response response ;
struct wbcDomainSid * sids = NULL ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
int cmd ;
/* Initialise request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
if ( ! user_sid ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2011-03-04 07:44:23 +03:00
wbcSidToStringBuf ( user_sid , request . data . sid , sizeof ( request . data . sid ) ) ;
2008-03-21 12:18:54 +03:00
if ( domain_groups_only ) {
cmd = WINBINDD_GETUSERDOMGROUPS ;
} else {
cmd = WINBINDD_GETUSERSIDS ;
}
wbc_status = wbcRequestResponse ( cmd ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
if ( response . data . num_entries & &
! response . extra_data . data ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2008-03-21 12:18:54 +03:00
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2010-04-03 15:45:36 +04:00
sids = ( struct wbcDomainSid * ) wbcAllocateMemory (
response . data . num_entries , sizeof ( struct wbcDomainSid ) ,
NULL ) ;
2008-03-21 12:18:54 +03:00
BAIL_ON_PTR_ERROR ( sids , wbc_status ) ;
s = ( const char * ) response . extra_data . data ;
for ( i = 0 ; i < response . data . num_entries ; i + + ) {
char * n = strchr ( s , ' \n ' ) ;
if ( n ) {
* n = ' \0 ' ;
}
wbc_status = wbcStringToSid ( s , & sids [ i ] ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
s + = strlen ( s ) + 1 ;
}
* num_sids = response . data . num_entries ;
* _sids = sids ;
sids = NULL ;
wbc_status = WBC_ERR_SUCCESS ;
done :
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & response ) ;
2008-03-21 12:18:54 +03:00
if ( sids ) {
2010-04-03 15:45:36 +04:00
wbcFreeMemory ( sids ) ;
2008-03-21 12:18:54 +03:00
}
return wbc_status ;
}
2008-03-24 22:31:37 +03:00
2009-02-11 00:59:10 +03:00
static inline
wbcErr _sid_to_rid ( struct wbcDomainSid * sid , uint32_t * rid )
{
if ( sid - > num_auths < 1 ) {
return WBC_ERR_INVALID_RESPONSE ;
}
* rid = sid - > sub_auths [ sid - > num_auths - 1 ] ;
return WBC_ERR_SUCCESS ;
}
/* Get alias membership for sids */
wbcErr wbcGetSidAliases ( const struct wbcDomainSid * dom_sid ,
struct wbcDomainSid * sids ,
uint32_t num_sids ,
uint32_t * * alias_rids ,
uint32_t * num_alias_rids )
{
uint32_t i ;
const char * s ;
struct winbindd_request request ;
struct winbindd_response response ;
ssize_t extra_data_len = 0 ;
char * extra_data = NULL ;
ssize_t buflen = 0 ;
struct wbcDomainSid sid ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
uint32_t * rids = NULL ;
/* Initialise request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
if ( ! dom_sid ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
2010-04-10 17:28:42 +04:00
goto done ;
2009-02-11 00:59:10 +03:00
}
2011-03-04 07:44:23 +03:00
wbcSidToStringBuf ( dom_sid , request . data . sid , sizeof ( request . data . sid ) ) ;
2009-02-11 00:59:10 +03:00
2010-04-10 14:57:13 +04:00
/* Lets assume each sid is around 57 characters
* S - 1 - 5 - 21 - AAAAAAAAAAA - BBBBBBBBBBB - CCCCCCCCCCC - DDDDDDDDDDD \ n */
buflen = 57 * num_sids ;
extra_data = ( char * ) malloc ( buflen ) ;
2009-02-11 00:59:10 +03:00
if ( ! extra_data ) {
wbc_status = WBC_ERR_NO_MEMORY ;
2010-04-10 17:28:42 +04:00
goto done ;
2009-02-11 00:59:10 +03:00
}
/* Build the sid list */
for ( i = 0 ; i < num_sids ; i + + ) {
2011-03-04 07:44:23 +03:00
char sid_str [ WBC_SID_STRING_BUFLEN ] ;
size_t sid_len ;
2009-02-11 00:59:10 +03:00
2011-03-04 07:44:23 +03:00
sid_len = wbcSidToStringBuf ( & sids [ i ] , sid_str , sizeof ( sid_str ) ) ;
2009-02-11 00:59:10 +03:00
if ( buflen < extra_data_len + sid_len + 2 ) {
buflen * = 2 ;
2010-04-10 14:58:14 +04:00
extra_data = ( char * ) realloc ( extra_data , buflen ) ;
2009-02-11 00:59:10 +03:00
if ( ! extra_data ) {
wbc_status = WBC_ERR_NO_MEMORY ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
}
2011-03-04 07:44:23 +03:00
strncpy ( & extra_data [ extra_data_len ] , sid_str ,
2009-02-11 00:59:10 +03:00
buflen - extra_data_len ) ;
extra_data_len + = sid_len ;
extra_data [ extra_data_len + + ] = ' \n ' ;
extra_data [ extra_data_len ] = ' \0 ' ;
}
2010-04-10 18:59:27 +04:00
extra_data_len + = 1 ;
2009-02-11 00:59:10 +03:00
request . extra_data . data = extra_data ;
request . extra_len = extra_data_len ;
wbc_status = wbcRequestResponse ( WINBINDD_GETSIDALIASES ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
if ( response . data . num_entries & &
! response . extra_data . data ) {
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2010-04-10 17:28:42 +04:00
goto done ;
2009-02-11 00:59:10 +03:00
}
2010-04-10 14:58:14 +04:00
rids = ( uint32_t * ) wbcAllocateMemory ( response . data . num_entries ,
sizeof ( uint32_t ) , NULL ) ;
2009-02-11 00:59:10 +03:00
BAIL_ON_PTR_ERROR ( sids , wbc_status ) ;
s = ( const char * ) response . extra_data . data ;
for ( i = 0 ; i < response . data . num_entries ; i + + ) {
char * n = strchr ( s , ' \n ' ) ;
if ( n ) {
* n = ' \0 ' ;
}
wbc_status = wbcStringToSid ( s , & sid ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
wbc_status = _sid_to_rid ( & sid , & rids [ i ] ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
s + = strlen ( s ) + 1 ;
}
* num_alias_rids = response . data . num_entries ;
* alias_rids = rids ;
rids = NULL ;
wbc_status = WBC_ERR_SUCCESS ;
done :
2010-04-10 14:58:14 +04:00
free ( extra_data ) ;
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & response ) ;
2010-04-10 14:58:14 +04:00
wbcFreeMemory ( rids ) ;
2009-02-11 00:59:10 +03:00
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Lists Users */
2008-03-24 22:31:37 +03:00
wbcErr wbcListUsers ( const char * domain_name ,
uint32_t * _num_users ,
const char * * * _users )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_response response ;
uint32_t num_users = 0 ;
const char * * users = NULL ;
const char * next ;
/* Initialise request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
if ( domain_name ) {
strncpy ( request . domain_name , domain_name ,
sizeof ( request . domain_name ) - 1 ) ;
}
wbc_status = wbcRequestResponse ( WINBINDD_LIST_USERS ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
2010-04-03 16:26:22 +04:00
users = wbcAllocateStringArray ( response . data . num_entries ) ;
if ( users = = NULL ) {
return WBC_ERR_NO_MEMORY ;
}
2008-03-24 22:31:37 +03:00
/* Look through extra data */
next = ( const char * ) response . extra_data . data ;
while ( next ) {
2010-04-19 17:50:11 +04:00
const char * current ;
char * k ;
if ( num_users > = response . data . num_entries ) {
wbc_status = WBC_ERR_INVALID_RESPONSE ;
goto done ;
}
current = next ;
k = strchr ( next , ' , ' ) ;
2008-03-24 22:31:37 +03:00
if ( k ) {
k [ 0 ] = ' \0 ' ;
next = k + 1 ;
} else {
next = NULL ;
}
2010-04-03 16:26:22 +04:00
users [ num_users ] = strdup ( current ) ;
2008-03-24 22:31:37 +03:00
BAIL_ON_PTR_ERROR ( users [ num_users ] , wbc_status ) ;
2010-04-03 16:26:22 +04:00
num_users + = 1 ;
}
if ( num_users ! = response . data . num_entries ) {
wbc_status = WBC_ERR_INVALID_RESPONSE ;
goto done ;
2008-03-24 22:31:37 +03:00
}
2010-04-03 16:26:22 +04:00
* _num_users = response . data . num_entries ;
2008-03-24 22:31:37 +03:00
* _users = users ;
users = NULL ;
wbc_status = WBC_ERR_SUCCESS ;
done :
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & response ) ;
2010-04-19 17:56:30 +04:00
wbcFreeMemory ( users ) ;
2008-03-24 22:31:37 +03:00
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Lists Groups */
2008-03-24 22:31:37 +03:00
wbcErr wbcListGroups ( const char * domain_name ,
uint32_t * _num_groups ,
const char * * * _groups )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_response response ;
uint32_t num_groups = 0 ;
const char * * groups = NULL ;
const char * next ;
/* Initialise request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
if ( domain_name ) {
strncpy ( request . domain_name , domain_name ,
sizeof ( request . domain_name ) - 1 ) ;
}
wbc_status = wbcRequestResponse ( WINBINDD_LIST_GROUPS ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
2010-04-03 16:31:57 +04:00
groups = wbcAllocateStringArray ( response . data . num_entries ) ;
if ( groups = = NULL ) {
return WBC_ERR_NO_MEMORY ;
}
2008-03-24 22:31:37 +03:00
/* Look through extra data */
next = ( const char * ) response . extra_data . data ;
while ( next ) {
2010-04-19 17:50:11 +04:00
const char * current ;
char * k ;
if ( num_groups > = response . data . num_entries ) {
wbc_status = WBC_ERR_INVALID_RESPONSE ;
goto done ;
}
current = next ;
k = strchr ( next , ' , ' ) ;
2008-03-24 22:31:37 +03:00
if ( k ) {
k [ 0 ] = ' \0 ' ;
next = k + 1 ;
} else {
next = NULL ;
}
2010-04-03 16:31:57 +04:00
groups [ num_groups ] = strdup ( current ) ;
2008-03-24 22:31:37 +03:00
BAIL_ON_PTR_ERROR ( groups [ num_groups ] , wbc_status ) ;
2010-04-03 16:31:57 +04:00
num_groups + = 1 ;
}
if ( num_groups ! = response . data . num_entries ) {
wbc_status = WBC_ERR_INVALID_RESPONSE ;
goto done ;
2008-03-24 22:31:37 +03:00
}
2010-04-03 16:31:57 +04:00
* _num_groups = response . data . num_entries ;
2008-03-24 22:31:37 +03:00
* _groups = groups ;
groups = NULL ;
wbc_status = WBC_ERR_SUCCESS ;
done :
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & response ) ;
2010-04-03 16:31:57 +04:00
wbcFreeMemory ( groups ) ;
2008-03-24 22:31:37 +03:00
return wbc_status ;
}
2008-10-21 19:11:29 +04:00
wbcErr wbcGetDisplayName ( const struct wbcDomainSid * sid ,
char * * pdomain ,
char * * pfullname ,
enum wbcSidType * pname_type )
{
wbcErr wbc_status ;
char * domain = NULL ;
char * name = NULL ;
enum wbcSidType name_type ;
wbc_status = wbcLookupSid ( sid , & domain , & name , & name_type ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
if ( name_type = = WBC_SID_NAME_USER ) {
uid_t uid ;
struct passwd * pwd ;
wbc_status = wbcSidToUid ( sid , & uid ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
wbc_status = wbcGetpwuid ( uid , & pwd ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
wbcFreeMemory ( name ) ;
2010-04-03 16:33:17 +04:00
name = wbcStrDup ( pwd - > pw_gecos ) ;
2010-04-10 18:34:53 +04:00
wbcFreeMemory ( pwd ) ;
2011-03-30 09:06:18 +04:00
BAIL_ON_PTR_ERROR ( name , wbc_status ) ;
2008-10-21 19:11:29 +04:00
}
wbc_status = WBC_ERR_SUCCESS ;
done :
if ( WBC_ERROR_IS_OK ( wbc_status ) ) {
* pdomain = domain ;
* pfullname = name ;
* pname_type = name_type ;
} else {
wbcFreeMemory ( domain ) ;
wbcFreeMemory ( name ) ;
}
return wbc_status ;
}
2009-08-12 19:41:23 +04:00
const char * wbcSidTypeString ( enum wbcSidType type )
{
switch ( type ) {
case WBC_SID_NAME_USE_NONE : return " SID_NONE " ;
case WBC_SID_NAME_USER : return " SID_USER " ;
case WBC_SID_NAME_DOM_GRP : return " SID_DOM_GROUP " ;
case WBC_SID_NAME_DOMAIN : return " SID_DOMAIN " ;
case WBC_SID_NAME_ALIAS : return " SID_ALIAS " ;
case WBC_SID_NAME_WKN_GRP : return " SID_WKN_GROUP " ;
case WBC_SID_NAME_DELETED : return " SID_DELETED " ;
case WBC_SID_NAME_INVALID : return " SID_INVALID " ;
case WBC_SID_NAME_UNKNOWN : return " SID_UNKNOWN " ;
case WBC_SID_NAME_COMPUTER : return " SID_COMPUTER " ;
default : return " Unknown type " ;
}
}