2007-12-21 20:57:34 +03:00
/*
Unix SMB / CIFS implementation .
Winbind client API
Copyright ( C ) Gerald ( Jerry ) Carter 2007
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
2008-11-23 18:36:01 +03:00
/** @brief The maximum number of pwent structs to get from winbindd
*
*/
# define MAX_GETPWENT_USERS 500
2008-11-23 19:11:09 +03:00
/** @brief The maximum number of grent structs to get from winbindd
*
*/
# define MAX_GETGRENT_GROUPS 500
2007-12-21 20:57:34 +03:00
/**
*
* */
2010-04-07 00:16:07 +04:00
static void wbcPasswdDestructor ( void * ptr )
2007-12-21 20:57:34 +03:00
{
2010-04-07 00:16:07 +04:00
struct passwd * pw = ( struct passwd * ) ptr ;
free ( pw - > pw_name ) ;
free ( pw - > pw_passwd ) ;
free ( pw - > pw_gecos ) ;
free ( pw - > pw_shell ) ;
free ( pw - > pw_dir ) ;
}
2007-12-21 20:57:34 +03:00
2010-04-07 00:16:07 +04:00
static struct passwd * copy_passwd_entry ( struct winbindd_pw * p )
{
struct passwd * pw = NULL ;
2007-12-21 20:57:34 +03:00
2010-04-07 00:16:07 +04:00
pw = ( struct passwd * ) wbcAllocateMemory ( 1 , sizeof ( struct passwd ) ,
wbcPasswdDestructor ) ;
if ( pw = = NULL ) {
return NULL ;
}
pw - > pw_name = strdup ( p - > pw_name ) ;
if ( pw - > pw_name = = NULL ) {
goto fail ;
}
pw - > pw_passwd = strdup ( p - > pw_passwd ) ;
if ( pw - > pw_passwd = = NULL ) {
goto fail ;
}
pw - > pw_gecos = strdup ( p - > pw_gecos ) ;
if ( pw - > pw_gecos = = NULL ) {
goto fail ;
}
pw - > pw_shell = strdup ( p - > pw_shell ) ;
if ( pw - > pw_shell = = NULL ) {
goto fail ;
}
pw - > pw_dir = strdup ( p - > pw_dir ) ;
if ( pw - > pw_dir = = NULL ) {
goto fail ;
2007-12-21 20:57:34 +03:00
}
2010-04-07 00:16:07 +04:00
pw - > pw_uid = p - > pw_uid ;
pw - > pw_gid = p - > pw_gid ;
return pw ;
2007-12-21 20:57:34 +03:00
2010-04-07 00:16:07 +04:00
fail :
wbcFreeMemory ( pw ) ;
return NULL ;
2007-12-21 20:57:34 +03:00
}
/**
*
* */
2010-04-07 00:16:32 +04:00
static void wbcGroupDestructor ( void * ptr )
{
struct group * gr = ( struct group * ) ptr ;
int i ;
free ( gr - > gr_name ) ;
free ( gr - > gr_passwd ) ;
2010-09-16 14:12:20 +04:00
/* if the array was partly created this can be NULL */
if ( gr - > gr_mem = = NULL ) {
return ;
}
2010-04-07 00:16:32 +04:00
for ( i = 0 ; gr - > gr_mem [ i ] ! = NULL ; i + + ) {
free ( gr - > gr_mem [ i ] ) ;
}
free ( gr - > gr_mem ) ;
}
2007-12-21 20:57:34 +03:00
static struct group * copy_group_entry ( struct winbindd_gr * g ,
char * mem_buf )
{
2010-04-07 00:16:32 +04:00
struct group * gr = NULL ;
2007-12-21 20:57:34 +03:00
int i ;
char * mem_p , * mem_q ;
2010-04-07 00:16:32 +04:00
gr = ( struct group * ) wbcAllocateMemory (
1 , sizeof ( struct group ) , wbcGroupDestructor ) ;
if ( gr = = NULL ) {
return NULL ;
}
2007-12-21 20:57:34 +03:00
2010-04-07 00:16:32 +04:00
gr - > gr_name = strdup ( g - > gr_name ) ;
if ( gr - > gr_name = = NULL ) {
goto fail ;
}
gr - > gr_passwd = strdup ( g - > gr_passwd ) ;
if ( gr - > gr_passwd = = NULL ) {
goto fail ;
}
gr - > gr_gid = g - > gr_gid ;
2007-12-21 20:57:34 +03:00
2010-04-07 00:16:32 +04:00
gr - > gr_mem = ( char * * ) calloc ( g - > num_gr_mem + 1 , sizeof ( char * ) ) ;
if ( gr - > gr_mem = = NULL ) {
goto fail ;
}
2007-12-21 20:57:34 +03:00
mem_p = mem_q = mem_buf ;
for ( i = 0 ; i < g - > num_gr_mem & & mem_p ; i + + ) {
2010-04-07 00:16:32 +04:00
mem_q = strchr ( mem_p , ' , ' ) ;
if ( mem_q ! = NULL ) {
2007-12-21 20:57:34 +03:00
* mem_q = ' \0 ' ;
}
2010-04-07 00:16:32 +04:00
gr - > gr_mem [ i ] = strdup ( mem_p ) ;
if ( gr - > gr_mem [ i ] = = NULL ) {
goto fail ;
}
2007-12-21 20:57:34 +03:00
2008-06-15 02:14:27 +04:00
if ( mem_q = = NULL ) {
i + = 1 ;
break ;
}
mem_p = mem_q + 1 ;
2007-12-21 20:57:34 +03:00
}
2010-04-07 00:16:32 +04:00
gr - > gr_mem [ i ] = NULL ;
2007-12-21 20:57:34 +03:00
2010-04-07 00:16:32 +04:00
return gr ;
2007-12-21 20:57:34 +03:00
2010-04-07 00:16:32 +04:00
fail :
wbcFreeMemory ( gr ) ;
return NULL ;
2007-12-21 20:57:34 +03:00
}
2008-12-09 15:18:06 +03:00
/* Fill in a struct passwd* for a domain user based on username */
2007-12-21 20:57:34 +03:00
wbcErr wbcGetpwnam ( const char * name , struct passwd * * pwd )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_response response ;
if ( ! name | | ! pwd ) {
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 . username , name , sizeof ( request . data . username ) - 1 ) ;
wbc_status = wbcRequestResponse ( WINBINDD_GETPWNAM ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
* pwd = copy_passwd_entry ( & response . data . pw ) ;
BAIL_ON_PTR_ERROR ( * pwd , wbc_status ) ;
done :
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Fill in a struct passwd* for a domain user based on uid */
2007-12-21 20:57:34 +03:00
wbcErr wbcGetpwuid ( uid_t uid , struct passwd * * pwd )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_response response ;
if ( ! pwd ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
/* Initialize request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
request . data . uid = uid ;
wbc_status = wbcRequestResponse ( WINBINDD_GETPWUID ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
* pwd = copy_passwd_entry ( & response . data . pw ) ;
BAIL_ON_PTR_ERROR ( * pwd , wbc_status ) ;
done :
return wbc_status ;
}
2009-02-10 22:06:44 +03:00
/* Fill in a struct passwd* for a domain user based on sid */
wbcErr wbcGetpwsid ( struct wbcDomainSid * sid , struct passwd * * pwd )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_response response ;
if ( ! pwd ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
/* 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 ) ) ;
2009-02-10 22:06:44 +03:00
wbc_status = wbcRequestResponse ( WINBINDD_GETPWSID ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
* pwd = copy_passwd_entry ( & response . data . pw ) ;
BAIL_ON_PTR_ERROR ( * pwd , wbc_status ) ;
done :
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Fill in a struct passwd* for a domain user based on username */
2007-12-21 20:57:34 +03:00
wbcErr wbcGetgrnam ( const char * name , struct group * * grp )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_response response ;
/* Initialize request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
2008-01-30 01:01:23 +03:00
if ( ! name | | ! grp ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2007-12-21 20:57:34 +03:00
/* dst is already null terminated from the memset above */
strncpy ( request . data . groupname , name , sizeof ( request . data . groupname ) - 1 ) ;
wbc_status = wbcRequestResponse ( WINBINDD_GETGRNAM ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
2008-01-03 14:10:27 +03:00
* grp = copy_group_entry ( & response . data . gr ,
2008-01-03 02:34:41 +03:00
( char * ) response . extra_data . data ) ;
2007-12-21 20:57:34 +03:00
BAIL_ON_PTR_ERROR ( * grp , wbc_status ) ;
done :
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & response ) ;
2008-01-03 14:10:27 +03:00
2007-12-21 20:57:34 +03:00
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Fill in a struct passwd* for a domain user based on uid */
2007-12-21 20:57:34 +03:00
wbcErr wbcGetgrgid ( gid_t gid , struct group * * grp )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_response response ;
/* Initialize request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
2008-01-30 01:01:23 +03:00
if ( ! grp ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2007-12-21 20:57:34 +03:00
request . data . gid = gid ;
wbc_status = wbcRequestResponse ( WINBINDD_GETGRGID ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
2008-01-03 14:10:27 +03:00
* grp = copy_group_entry ( & response . data . gr ,
2008-01-03 02:34:41 +03:00
( char * ) response . extra_data . data ) ;
2007-12-21 20:57:34 +03:00
BAIL_ON_PTR_ERROR ( * grp , wbc_status ) ;
done :
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & response ) ;
2007-12-21 20:57:34 +03:00
return wbc_status ;
}
2008-11-23 18:36:01 +03:00
/** @brief Number of cached passwd structs
*
*/
static uint32_t pw_cache_size ;
/** @brief Position of the pwent context
*
*/
static uint32_t pw_cache_idx ;
/** @brief Winbindd response containing the passwd structs
*
*/
static struct winbindd_response pw_response ;
2008-12-09 15:18:06 +03:00
/* Reset the passwd iterator */
2007-12-21 20:57:34 +03:00
wbcErr wbcSetpwent ( void )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
2008-11-23 18:36:01 +03:00
if ( pw_cache_size > 0 ) {
pw_cache_idx = pw_cache_size = 0 ;
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & pw_response ) ;
2008-11-23 18:36:01 +03:00
}
ZERO_STRUCT ( pw_response ) ;
2007-12-21 20:57:34 +03:00
wbc_status = wbcRequestResponse ( WINBINDD_SETPWENT ,
NULL , NULL ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Close the passwd iterator */
2007-12-21 20:57:34 +03:00
wbcErr wbcEndpwent ( void )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
2008-11-23 18:36:01 +03:00
if ( pw_cache_size > 0 ) {
pw_cache_idx = pw_cache_size = 0 ;
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & pw_response ) ;
2008-11-23 18:36:01 +03:00
}
2007-12-21 20:57:34 +03:00
wbc_status = wbcRequestResponse ( WINBINDD_ENDPWENT ,
NULL , NULL ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Return the next struct passwd* entry from the pwent iterator */
2007-12-21 20:57:34 +03:00
wbcErr wbcGetpwent ( struct passwd * * pwd )
{
2008-11-23 18:36:01 +03:00
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_pw * wb_pw ;
/* If there's a cached result, return that. */
if ( pw_cache_idx < pw_cache_size ) {
goto return_result ;
}
/* Otherwise, query winbindd for some entries. */
pw_cache_idx = 0 ;
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & pw_response ) ;
2008-11-23 18:36:01 +03:00
ZERO_STRUCT ( request ) ;
request . data . num_entries = MAX_GETPWENT_USERS ;
wbc_status = wbcRequestResponse ( WINBINDD_GETPWENT , & request ,
& pw_response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
pw_cache_size = pw_response . data . num_entries ;
return_result :
wb_pw = ( struct winbindd_pw * ) pw_response . extra_data . data ;
* pwd = copy_passwd_entry ( & wb_pw [ pw_cache_idx ] ) ;
BAIL_ON_PTR_ERROR ( * pwd , wbc_status ) ;
pw_cache_idx + + ;
done :
return wbc_status ;
2007-12-21 20:57:34 +03:00
}
2008-11-23 19:11:09 +03:00
/** @brief Number of cached group structs
*
*/
static uint32_t gr_cache_size ;
/** @brief Position of the grent context
*
*/
static uint32_t gr_cache_idx ;
/** @brief Winbindd response containing the group structs
*
*/
static struct winbindd_response gr_response ;
2008-12-09 15:18:06 +03:00
/* Reset the group iterator */
2007-12-21 20:57:34 +03:00
wbcErr wbcSetgrent ( void )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
2008-11-23 19:11:09 +03:00
if ( gr_cache_size > 0 ) {
gr_cache_idx = gr_cache_size = 0 ;
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & gr_response ) ;
2008-11-23 19:11:09 +03:00
}
ZERO_STRUCT ( gr_response ) ;
2007-12-21 20:57:34 +03:00
wbc_status = wbcRequestResponse ( WINBINDD_SETGRENT ,
NULL , NULL ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Close the group iterator */
2007-12-21 20:57:34 +03:00
wbcErr wbcEndgrent ( void )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
2008-11-23 19:11:09 +03:00
if ( gr_cache_size > 0 ) {
gr_cache_idx = gr_cache_size = 0 ;
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & gr_response ) ;
2008-11-23 19:11:09 +03:00
}
2007-12-21 20:57:34 +03:00
wbc_status = wbcRequestResponse ( WINBINDD_ENDGRENT ,
NULL , NULL ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Return the next struct group* entry from the pwent iterator */
2007-12-21 20:57:34 +03:00
wbcErr wbcGetgrent ( struct group * * grp )
{
2008-11-23 19:11:09 +03:00
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_gr * wb_gr ;
uint32_t mem_ofs ;
/* If there's a cached result, return that. */
if ( gr_cache_idx < gr_cache_size ) {
goto return_result ;
}
/* Otherwise, query winbindd for some entries. */
gr_cache_idx = 0 ;
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & gr_response ) ;
2008-11-23 19:11:09 +03:00
ZERO_STRUCT ( request ) ;
request . data . num_entries = MAX_GETGRENT_GROUPS ;
wbc_status = wbcRequestResponse ( WINBINDD_GETGRENT , & request ,
& gr_response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
gr_cache_size = gr_response . data . num_entries ;
return_result :
wb_gr = ( struct winbindd_gr * ) gr_response . extra_data . data ;
mem_ofs = wb_gr [ gr_cache_idx ] . gr_mem_ofs +
gr_cache_size * sizeof ( struct winbindd_gr ) ;
* grp = copy_group_entry ( & wb_gr [ gr_cache_idx ] ,
( ( char * ) gr_response . extra_data . data ) + mem_ofs ) ;
BAIL_ON_PTR_ERROR ( * grp , wbc_status ) ;
gr_cache_idx + + ;
done :
return wbc_status ;
2007-12-21 20:57:34 +03:00
}
2008-12-09 15:18:06 +03:00
/* Return the next struct group* entry from the pwent iterator */
2008-11-23 13:17:42 +03:00
wbcErr wbcGetgrlist ( struct group * * grp )
{
2008-11-23 19:11:09 +03:00
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_gr * wb_gr ;
/* If there's a cached result, return that. */
if ( gr_cache_idx < gr_cache_size ) {
goto return_result ;
}
/* Otherwise, query winbindd for some entries. */
gr_cache_idx = 0 ;
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & gr_response ) ;
ZERO_STRUCT ( gr_response ) ;
2008-11-23 19:11:09 +03:00
ZERO_STRUCT ( request ) ;
request . data . num_entries = MAX_GETGRENT_GROUPS ;
wbc_status = wbcRequestResponse ( WINBINDD_GETGRLST , & request ,
& gr_response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
gr_cache_size = gr_response . data . num_entries ;
return_result :
wb_gr = ( struct winbindd_gr * ) gr_response . extra_data . data ;
* grp = copy_group_entry ( & wb_gr [ gr_cache_idx ] , NULL ) ;
BAIL_ON_PTR_ERROR ( * grp , wbc_status ) ;
gr_cache_idx + + ;
done :
return wbc_status ;
2008-11-23 13:17:42 +03:00
}
2008-12-09 15:18:06 +03:00
/* Return the unix group array belonging to the given user */
2008-04-06 13:55:57 +04:00
wbcErr wbcGetGroups ( const char * account ,
uint32_t * num_groups ,
gid_t * * _groups )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
struct winbindd_request request ;
struct winbindd_response response ;
uint32_t i ;
gid_t * groups = NULL ;
/* Initialize request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
2008-06-15 02:22:47 +04:00
if ( ! account ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2008-04-06 13:55:57 +04:00
/* Send request */
strncpy ( request . data . username , account , sizeof ( request . data . username ) - 1 ) ;
wbc_status = wbcRequestResponse ( WINBINDD_GETGROUPS ,
& request ,
& response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
2010-04-04 00:20:04 +04:00
groups = ( gid_t * ) wbcAllocateMemory (
2010-11-27 21:02:33 +03:00
response . data . num_entries , sizeof ( gid_t ) , NULL ) ;
2008-04-06 13:55:57 +04:00
BAIL_ON_PTR_ERROR ( groups , wbc_status ) ;
for ( i = 0 ; i < response . data . num_entries ; i + + ) {
groups [ i ] = ( ( gid_t * ) response . extra_data . data ) [ i ] ;
}
* num_groups = response . data . num_entries ;
* _groups = groups ;
groups = NULL ;
wbc_status = WBC_ERR_SUCCESS ;
done :
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & response ) ;
2010-04-04 00:20:04 +04:00
wbcFreeMemory ( groups ) ;
2008-04-06 13:55:57 +04:00
return wbc_status ;
}