2017-08-02 19:11:49 +03:00
/*
* Unix SMB / CIFS implementation .
* Utils for caching sid2name and name2sid
* Copyright ( C ) Volker Lendecke 2017
*
* 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 "replace.h"
# include "namemap_cache.h"
# include "source3/lib/gencache.h"
# include "lib/util/debug.h"
# include "lib/util/strv.h"
2019-01-28 14:54:07 +03:00
# include "lib/util/util.h"
2017-08-02 19:11:49 +03:00
# include "lib/util/talloc_stack.h"
# include "lib/util/charset/charset.h"
# include "libcli/security/dom_sid.h"
bool namemap_cache_set_sid2name ( const struct dom_sid * sid ,
const char * domain , const char * name ,
enum lsa_SidType type , time_t timeout )
{
char typebuf [ 16 ] ;
2018-10-26 09:25:14 +03:00
struct dom_sid_buf sidbuf ;
char keybuf [ sizeof ( sidbuf . buf ) + 10 ] ;
2017-08-02 19:11:49 +03:00
char * val = NULL ;
DATA_BLOB data ;
int ret ;
bool ok = false ;
if ( ( sid = = NULL ) | | is_null_sid ( sid ) ) {
return true ;
}
if ( domain = = NULL ) {
domain = " " ;
}
if ( name = = NULL ) {
name = " " ;
}
if ( type = = SID_NAME_UNKNOWN ) {
domain = " " ;
name = " " ;
}
snprintf ( typebuf , sizeof ( typebuf ) , " %d " , ( int ) type ) ;
ret = strv_add ( talloc_tos ( ) , & val , domain ) ;
if ( ret ! = 0 ) {
DBG_DEBUG ( " strv_add failed: %s \n " , strerror ( ret ) ) ;
goto fail ;
}
ret = strv_add ( NULL , & val , name ) ;
if ( ret ! = 0 ) {
DBG_DEBUG ( " strv_add failed: %s \n " , strerror ( ret ) ) ;
goto fail ;
}
ret = strv_add ( NULL , & val , typebuf ) ;
if ( ret ! = 0 ) {
DBG_DEBUG ( " strv_add failed: %s \n " , strerror ( ret ) ) ;
goto fail ;
}
2018-10-26 09:25:14 +03:00
dom_sid_str_buf ( sid , & sidbuf ) ;
snprintf ( keybuf , sizeof ( keybuf ) , " SID2NAME/%s " , sidbuf . buf ) ;
2017-08-02 19:11:49 +03:00
data = data_blob_const ( val , talloc_get_size ( val ) ) ;
ok = gencache_set_data_blob ( keybuf , data , timeout ) ;
if ( ! ok ) {
DBG_DEBUG ( " gencache_set_data_blob failed \n " ) ;
}
fail :
TALLOC_FREE ( val ) ;
return ok ;
}
struct namemap_cache_find_sid_state {
2018-10-13 13:01:41 +03:00
void ( * fn ) ( const char * domain ,
const char * name ,
enum lsa_SidType type ,
bool expired ,
2017-08-02 19:11:49 +03:00
void * private_data ) ;
void * private_data ;
bool ok ;
} ;
2018-10-13 14:41:59 +03:00
static void namemap_cache_find_sid_parser (
const struct gencache_timeout * timeout ,
DATA_BLOB blob ,
void * private_data )
2017-08-02 19:11:49 +03:00
{
struct namemap_cache_find_sid_state * state = private_data ;
const char * strv = ( const char * ) blob . data ;
size_t strv_len = blob . length ;
const char * domain ;
const char * name ;
const char * typebuf ;
2019-01-28 14:54:07 +03:00
int error = 0 ;
2017-08-02 19:11:49 +03:00
unsigned long type ;
state - > ok = false ;
domain = strv_len_next ( strv , strv_len , NULL ) ;
if ( domain = = NULL ) {
return ;
}
name = strv_len_next ( strv , strv_len , domain ) ;
if ( name = = NULL ) {
return ;
}
typebuf = strv_len_next ( strv , strv_len , name ) ;
if ( typebuf = = NULL ) {
return ;
}
2019-06-04 10:04:15 +03:00
type = smb_strtoul ( typebuf , NULL , 10 , & error , SMB_STR_FULL_STR_CONV ) ;
if ( error ! = 0 ) {
2017-08-02 19:11:49 +03:00
return ;
}
2018-10-13 13:01:41 +03:00
state - > fn ( domain ,
name ,
( enum lsa_SidType ) type ,
2018-10-13 14:41:59 +03:00
gencache_timeout_expired ( timeout ) ,
2017-08-02 19:11:49 +03:00
state - > private_data ) ;
state - > ok = true ;
}
bool namemap_cache_find_sid ( const struct dom_sid * sid ,
2018-10-13 13:01:41 +03:00
void ( * fn ) ( const char * domain ,
const char * name ,
enum lsa_SidType type ,
bool expired ,
2017-08-02 19:11:49 +03:00
void * private_data ) ,
void * private_data )
{
struct namemap_cache_find_sid_state state = {
. fn = fn , . private_data = private_data
} ;
2018-10-26 09:25:14 +03:00
struct dom_sid_buf sidbuf ;
char keybuf [ sizeof ( sidbuf . buf ) + 10 ] ;
2017-08-02 19:11:49 +03:00
bool ok ;
2018-10-26 09:25:14 +03:00
dom_sid_str_buf ( sid , & sidbuf ) ;
snprintf ( keybuf , sizeof ( keybuf ) , " SID2NAME/%s " , sidbuf . buf ) ;
2017-08-02 19:11:49 +03:00
ok = gencache_parse ( keybuf , namemap_cache_find_sid_parser , & state ) ;
if ( ! ok ) {
DBG_DEBUG ( " gencache_parse(%s) failed \n " , keybuf ) ;
return false ;
}
if ( ! state . ok ) {
DBG_DEBUG ( " Could not parse %s, deleting \n " , keybuf ) ;
gencache_del ( keybuf ) ;
return false ;
}
return true ;
}
bool namemap_cache_set_name2sid ( const char * domain , const char * name ,
const struct dom_sid * sid ,
enum lsa_SidType type ,
time_t timeout )
{
char typebuf [ 16 ] ;
2018-10-26 09:25:14 +03:00
struct dom_sid_buf sidbuf = { { 0 } } ;
2017-08-02 19:11:49 +03:00
char * key ;
char * key_upper ;
char * val = NULL ;
DATA_BLOB data ;
int ret ;
bool ok = false ;
if ( domain = = NULL ) {
domain = " " ;
}
if ( name = = NULL ) {
name = " " ;
}
2018-10-26 09:25:14 +03:00
if ( type ! = SID_NAME_UNKNOWN ) {
dom_sid_str_buf ( sid , & sidbuf ) ;
2017-08-02 19:11:49 +03:00
}
snprintf ( typebuf , sizeof ( typebuf ) , " %d " , ( int ) type ) ;
key = talloc_asprintf ( talloc_tos ( ) , " NAME2SID/%s \\ %s " , domain , name ) ;
if ( key = = NULL ) {
DBG_DEBUG ( " talloc_asprintf failed \n " ) ;
goto fail ;
}
key_upper = strupper_talloc ( key , key ) ;
if ( key_upper = = NULL ) {
DBG_DEBUG ( " strupper_talloc failed \n " ) ;
goto fail ;
}
2018-10-26 09:25:14 +03:00
ret = strv_add ( key , & val , sidbuf . buf ) ;
2017-08-02 19:11:49 +03:00
if ( ret ! = 0 ) {
DBG_DEBUG ( " strv_add failed: %s \n " , strerror ( ret ) ) ;
goto fail ;
}
ret = strv_add ( NULL , & val , typebuf ) ;
if ( ret ! = 0 ) {
DBG_DEBUG ( " strv_add failed: %s \n " , strerror ( ret ) ) ;
goto fail ;
}
data = data_blob_const ( val , talloc_get_size ( val ) ) ;
ok = gencache_set_data_blob ( key_upper , data , timeout ) ;
if ( ! ok ) {
DBG_DEBUG ( " gencache_set_data_blob failed \n " ) ;
}
fail :
TALLOC_FREE ( key ) ;
return ok ;
}
struct namemap_cache_find_name_state {
void ( * fn ) ( const struct dom_sid * sid ,
2018-10-13 13:01:41 +03:00
enum lsa_SidType type ,
bool expired ,
2017-08-02 19:11:49 +03:00
void * private_data ) ;
void * private_data ;
bool ok ;
} ;
2018-10-13 14:41:59 +03:00
static void namemap_cache_find_name_parser (
const struct gencache_timeout * timeout ,
DATA_BLOB blob ,
void * private_data )
2017-08-02 19:11:49 +03:00
{
struct namemap_cache_find_name_state * state = private_data ;
const char * strv = ( const char * ) blob . data ;
size_t strv_len = blob . length ;
const char * sidbuf ;
const char * sid_endptr ;
const char * typebuf ;
2019-01-28 14:54:07 +03:00
int error = 0 ;
2017-08-02 19:11:49 +03:00
struct dom_sid sid ;
unsigned long type ;
bool ok ;
state - > ok = false ;
sidbuf = strv_len_next ( strv , strv_len , NULL ) ;
if ( sidbuf = = NULL ) {
return ;
}
typebuf = strv_len_next ( strv , strv_len , sidbuf ) ;
if ( typebuf = = NULL ) {
return ;
}
ok = dom_sid_parse_endp ( sidbuf , & sid , & sid_endptr ) ;
if ( ! ok ) {
return ;
}
if ( * sid_endptr ! = ' \0 ' ) {
return ;
}
2019-06-04 10:04:15 +03:00
type = smb_strtoul ( typebuf , NULL , 10 , & error , SMB_STR_FULL_STR_CONV ) ;
if ( error ! = 0 ) {
2017-08-02 19:11:49 +03:00
return ;
}
2018-10-13 13:01:41 +03:00
state - > fn ( & sid ,
( enum lsa_SidType ) type ,
2018-10-13 14:41:59 +03:00
gencache_timeout_expired ( timeout ) ,
2018-10-13 13:01:41 +03:00
state - > private_data ) ;
2017-08-02 19:11:49 +03:00
state - > ok = true ;
}
2018-10-13 13:01:41 +03:00
bool namemap_cache_find_name ( const char * domain ,
const char * name ,
2017-08-02 19:11:49 +03:00
void ( * fn ) ( const struct dom_sid * sid ,
2018-10-13 13:01:41 +03:00
enum lsa_SidType type ,
bool expired ,
2017-08-02 19:11:49 +03:00
void * private_data ) ,
void * private_data )
{
struct namemap_cache_find_name_state state = {
. fn = fn , . private_data = private_data
} ;
char * key ;
char * key_upper ;
bool ret = false ;
bool ok ;
key = talloc_asprintf ( talloc_tos ( ) , " NAME2SID/%s \\ %s " , domain , name ) ;
if ( key = = NULL ) {
DBG_DEBUG ( " talloc_asprintf failed \n " ) ;
return false ;
}
key_upper = strupper_talloc ( key , key ) ;
if ( key_upper = = NULL ) {
DBG_DEBUG ( " strupper_talloc failed \n " ) ;
goto fail ;
}
ok = gencache_parse ( key_upper , namemap_cache_find_name_parser , & state ) ;
if ( ! ok ) {
DBG_DEBUG ( " gencache_parse(%s) failed \n " , key_upper ) ;
goto fail ;
}
if ( ! state . ok ) {
DBG_DEBUG ( " Could not parse %s, deleting \n " , key_upper ) ;
goto fail ;
}
ret = true ;
fail :
TALLOC_FREE ( key ) ;
return ret ;
}