2009-08-18 00:44:55 +04:00
/*
Unix SMB / CIFS implementation .
async fill_pwent
Copyright ( C ) Volker Lendecke 2009
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "winbindd.h"
2014-05-08 04:17:32 +04:00
# include "librpc/gen_ndr/ndr_winbind_c.h"
2009-08-18 00:44:55 +04:00
struct wb_fill_pwent_state {
struct tevent_context * ev ;
2016-02-02 16:21:32 +03:00
const struct wbint_userinfo * info ;
2009-08-18 00:44:55 +04:00
struct winbindd_pw * pw ;
} ;
2009-10-17 19:00:13 +04:00
static bool fillup_pw_field ( const char * lp_template ,
const char * username ,
2013-11-18 17:58:14 +04:00
const char * grpname ,
2009-10-17 19:00:13 +04:00
const char * domname ,
uid_t uid ,
gid_t gid ,
const char * in ,
fstring out ) ;
2009-08-18 00:44:55 +04:00
static void wb_fill_pwent_sid2uid_done ( struct tevent_req * subreq ) ;
2013-11-18 17:58:14 +04:00
static void wb_fill_pwent_getgrsid_done ( struct tevent_req * subreq ) ;
2009-08-18 00:44:55 +04:00
struct tevent_req * wb_fill_pwent_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
2016-02-02 16:21:32 +03:00
const struct wbint_userinfo * info ,
2009-08-18 00:44:55 +04:00
struct winbindd_pw * pw )
{
struct tevent_req * req , * subreq ;
struct wb_fill_pwent_state * state ;
req = tevent_req_create ( mem_ctx , & state , struct wb_fill_pwent_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > ev = ev ;
state - > info = info ;
state - > pw = pw ;
2012-11-23 19:40:48 +04:00
subreq = wb_sids2xids_send ( state , state - > ev , & state - > info - > user_sid , 1 ) ;
2009-08-18 00:44:55 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , wb_fill_pwent_sid2uid_done , req ) ;
return req ;
}
static void wb_fill_pwent_sid2uid_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct wb_fill_pwent_state * state = tevent_req_data (
req , struct wb_fill_pwent_state ) ;
NTSTATUS status ;
2015-03-05 22:59:16 +03:00
struct unixid xids [ 1 ] ;
2009-08-18 00:44:55 +04:00
2015-03-05 22:59:16 +03:00
status = wb_sids2xids_recv ( subreq , xids , ARRAY_SIZE ( xids ) ) ;
2009-08-18 00:44:55 +04:00
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-08-18 00:44:55 +04:00
return ;
}
2012-11-23 19:40:48 +04:00
/*
* We are filtering further down in sids2xids , but that filtering
* depends on the actual type of the sid handed in ( as determined
* by lookupsids ) . Here we need to filter for the type of object
* actually requested , in this case uid .
*/
2015-03-05 22:59:16 +03:00
if ( ! ( xids [ 0 ] . type = = ID_TYPE_UID | | xids [ 0 ] . type = = ID_TYPE_BOTH ) ) {
2012-11-23 19:40:48 +04:00
tevent_req_nterror ( req , NT_STATUS_NONE_MAPPED ) ;
return ;
}
2015-03-05 22:59:16 +03:00
state - > pw - > pw_uid = ( uid_t ) xids [ 0 ] . id ;
2012-11-23 19:40:48 +04:00
2014-01-16 19:10:25 +04:00
subreq = wb_getgrsid_send ( state , state - > ev , & state - > info - > group_sid , 0 ) ;
2009-08-18 00:44:55 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
2013-11-18 17:58:14 +04:00
tevent_req_set_callback ( subreq , wb_fill_pwent_getgrsid_done , req ) ;
2009-08-18 00:44:55 +04:00
}
2013-11-18 17:58:14 +04:00
static void wb_fill_pwent_getgrsid_done ( struct tevent_req * subreq )
2009-08-18 00:44:55 +04:00
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct wb_fill_pwent_state * state = tevent_req_data (
req , struct wb_fill_pwent_state ) ;
struct winbindd_domain * domain ;
2013-11-18 17:58:14 +04:00
const char * dom_name ;
const char * grp_name ;
2009-08-18 00:44:55 +04:00
fstring user_name , output_username ;
char * mapped_name = NULL ;
2013-11-18 17:58:14 +04:00
struct talloc_dict * members ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2009-08-18 00:44:55 +04:00
NTSTATUS status ;
2013-11-18 17:58:14 +04:00
bool ok ;
/* xid handling is done in getgrsid() */
status = wb_getgrsid_recv ( subreq ,
tmp_ctx ,
& dom_name ,
& grp_name ,
& state - > pw - > pw_gid ,
& members ) ;
2009-08-18 00:44:55 +04:00
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2013-11-18 17:58:14 +04:00
talloc_free ( tmp_ctx ) ;
2009-08-18 00:44:55 +04:00
return ;
}
domain = find_domain_from_sid_noinit ( & state - > info - > user_sid ) ;
if ( domain = = NULL ) {
2013-11-18 17:58:14 +04:00
talloc_free ( tmp_ctx ) ;
2009-08-18 00:44:55 +04:00
tevent_req_nterror ( req , NT_STATUS_NO_SUCH_USER ) ;
return ;
}
dom_name = domain - > name ;
/* Username */
fstrcpy ( user_name , state - > info - > acct_name ) ;
2012-08-09 04:01:00 +04:00
if ( ! strlower_m ( user_name ) ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
2009-08-18 00:44:55 +04:00
status = normalize_name_map ( state , domain , user_name , & mapped_name ) ;
/* Basic removal of whitespace */
if ( NT_STATUS_IS_OK ( status ) ) {
fill_domain_username ( output_username , dom_name , mapped_name ,
true ) ;
}
/* Complete name replacement */
else if ( NT_STATUS_EQUAL ( status , NT_STATUS_FILE_RENAMED ) ) {
fstrcpy ( output_username , mapped_name ) ;
}
/* No change at all */
else {
fill_domain_username ( output_username , dom_name , user_name ,
true ) ;
}
2011-05-04 22:38:26 +04:00
strlcpy ( state - > pw - > pw_name ,
output_username ,
sizeof ( state - > pw - > pw_name ) ) ;
2014-02-12 16:26:02 +04:00
/* FIXME The full_name can be longer than 255 chars */
strlcpy ( state - > pw - > pw_gecos ,
state - > info - > full_name ! = NULL ? state - > info - > full_name : " " ,
sizeof ( state - > pw - > pw_gecos ) ) ;
2009-08-18 00:44:55 +04:00
/* Home directory and shell */
2013-11-18 17:58:14 +04:00
ok = fillup_pw_field ( lp_template_homedir ( ) ,
user_name ,
grp_name ,
dom_name ,
state - > pw - > pw_uid ,
state - > pw - > pw_gid ,
state - > info - > homedir ,
state - > pw - > pw_dir ) ;
if ( ! ok ) {
talloc_free ( tmp_ctx ) ;
2009-08-18 00:44:55 +04:00
tevent_req_nterror ( req , NT_STATUS_NO_SUCH_USER ) ;
return ;
}
2013-11-18 17:58:14 +04:00
ok = fillup_pw_field ( lp_template_shell ( ) ,
user_name ,
grp_name ,
dom_name ,
state - > pw - > pw_uid ,
state - > pw - > pw_gid ,
state - > info - > shell ,
state - > pw - > pw_shell ) ;
talloc_free ( tmp_ctx ) ;
if ( ! ok ) {
2009-08-18 00:44:55 +04:00
tevent_req_nterror ( req , NT_STATUS_NO_SUCH_USER ) ;
return ;
}
/* Password - set to "*" as we can't generate anything useful here.
Authentication can be done using the pam_winbind module . */
fstrcpy ( state - > pw - > pw_passwd , " * " ) ;
tevent_req_done ( req ) ;
}
NTSTATUS wb_fill_pwent_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
2009-10-17 19:00:13 +04:00
static bool fillup_pw_field ( const char * lp_template ,
const char * username ,
2013-11-18 17:58:14 +04:00
const char * grpname ,
2009-10-17 19:00:13 +04:00
const char * domname ,
uid_t uid ,
gid_t gid ,
const char * in ,
fstring out )
{
2014-01-30 18:24:06 +04:00
const char * templ ;
char * result ;
2009-10-17 19:00:13 +04:00
if ( out = = NULL )
return False ;
2014-01-30 18:24:06 +04:00
templ = lp_template ;
2009-10-17 19:00:13 +04:00
if ( ( in ! = NULL ) & & ( in [ 0 ] ! = ' \0 ' ) & & ( lp_security ( ) = = SEC_ADS ) ) {
2014-01-30 18:24:06 +04:00
/*
* The backend has already filled in the required value . Use
* that instead of the template .
*/
templ = in ;
2009-10-17 19:00:13 +04:00
}
2014-01-30 18:24:06 +04:00
result = talloc_sub_specified ( talloc_tos ( ) , templ ,
username , grpname , domname ,
uid , gid ) ;
if ( result = = NULL ) {
2009-10-17 19:00:13 +04:00
return False ;
2014-01-30 18:24:06 +04:00
}
2009-10-17 19:00:13 +04:00
2014-10-03 04:21:06 +04:00
fstrcpy ( out , result ) ;
2014-01-30 18:24:06 +04:00
TALLOC_FREE ( result ) ;
2009-10-17 19:00:13 +04:00
return True ;
}