2007-08-14 19:17:50 +04:00
/*
* Unix SMB / CIFS implementation .
* Group Policy Support
* Copyright ( C ) Guenther Deschner 2007
2009-04-20 16:57:33 +04:00
* Copyright ( C ) Wilco Baan Hofman 2009
2007-08-14 19:17:50 +04:00
*
* 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"
2009-04-20 16:57:33 +04:00
# include "gpo.h"
2007-08-14 19:17:50 +04:00
# include "gpo_ini.h"
2009-04-20 16:57:33 +04:00
# include "system/filesys.h"
2007-08-14 19:17:50 +04:00
2009-04-20 16:57:33 +04:00
static bool change_section ( const char * section , void * ctx_ptr )
2007-08-14 19:17:50 +04:00
{
2009-04-20 16:57:33 +04:00
struct gp_inifile_context * ctx = ( struct gp_inifile_context * ) ctx_ptr ;
2007-08-14 19:17:50 +04:00
2009-04-20 16:57:33 +04:00
if ( ctx - > current_section ) {
talloc_free ( ctx - > current_section ) ;
2007-08-14 19:17:50 +04:00
}
2009-04-20 16:57:33 +04:00
ctx - > current_section = talloc_strdup ( ctx , section ) ;
2013-12-12 21:23:47 +04:00
if ( ! ctx - > current_section ) {
return false ;
}
2009-04-20 16:57:33 +04:00
return true ;
}
2007-08-14 19:17:50 +04:00
2009-04-20 16:57:33 +04:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-14 19:17:50 +04:00
2009-04-20 16:57:33 +04:00
static bool store_keyval_pair ( const char * key , const char * value , void * ctx_ptr )
{
struct gp_inifile_context * ctx = ( struct gp_inifile_context * ) ctx_ptr ;
2013-12-12 21:23:47 +04:00
2009-04-20 16:57:33 +04:00
ctx - > data = talloc_realloc ( ctx , ctx - > data , struct keyval_pair * , ctx - > keyval_count + 1 ) ;
2013-12-12 21:23:47 +04:00
if ( ! ctx - > data ) {
return false ;
}
2009-04-20 21:15:32 +04:00
ctx - > data [ ctx - > keyval_count ] = talloc_zero ( ctx , struct keyval_pair ) ;
2013-12-12 21:23:47 +04:00
if ( ! ctx - > data [ ctx - > keyval_count ] ) {
return false ;
}
2009-04-20 16:57:33 +04:00
ctx - > data [ ctx - > keyval_count ] - > key = talloc_asprintf ( ctx , " %s:%s " , ctx - > current_section , key ) ;
2016-09-19 18:11:19 +03:00
ctx - > data [ ctx - > keyval_count ] - > val = talloc_strdup ( ctx , value ? value : " " ) ;
2013-12-12 21:23:47 +04:00
if ( ! ctx - > data [ ctx - > keyval_count ] - > key | |
! ctx - > data [ ctx - > keyval_count ] - > val ) {
return false ;
}
2009-04-20 16:57:33 +04:00
ctx - > keyval_count + + ;
return true ;
2007-08-14 19:17:50 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS convert_file_from_ucs2 ( TALLOC_CTX * mem_ctx ,
const char * filename_in ,
char * * filename_out )
{
2008-03-23 19:49:04 +03:00
int tmp_fd = - 1 ;
2009-04-20 16:57:33 +04:00
uint8_t * data_in = NULL ;
uint8_t * data_out = NULL ;
2007-08-14 19:17:50 +04:00
char * tmp_name = NULL ;
NTSTATUS status ;
size_t n = 0 ;
2008-04-30 01:36:24 +04:00
size_t converted_size ;
2013-02-25 20:34:21 +04:00
mode_t mask ;
2007-08-14 19:17:50 +04:00
if ( ! filename_out ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2016-11-10 17:15:05 +03:00
data_in = ( uint8_t * ) file_load ( filename_in , & n , 0 , mem_ctx ) ;
2007-08-14 19:17:50 +04:00
if ( ! data_in ) {
status = NT_STATUS_NO_SUCH_FILE ;
goto out ;
}
2016-11-10 17:15:05 +03:00
DEBUG ( 11 , ( " convert_file_from_ucs2: "
" data_in[0]: 0x%x, data_in[1]: 0x%x, data_in[2]: 0x%x \n " ,
data_in [ 0 ] , data_in [ 1 ] , data_in [ 2 ] ) ) ;
if ( ( data_in [ 0 ] ! = 0xff ) | | ( data_in [ 1 ] ! = 0xfe ) | | ( data_in [ 2 ] ! = 0x0d ) ) {
* filename_out = NULL ;
status = NT_STATUS_OK ;
goto out ;
}
2007-08-14 19:17:50 +04:00
tmp_name = talloc_asprintf ( mem_ctx , " %s/convert_file_from_ucs2.XXXXXX " ,
tmpdir ( ) ) ;
if ( ! tmp_name ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2013-02-25 20:34:21 +04:00
mask = umask ( S_IRWXO | S_IRWXG ) ;
2009-04-20 16:57:33 +04:00
tmp_fd = mkstemp ( tmp_name ) ;
2013-02-25 20:34:21 +04:00
umask ( mask ) ;
2007-08-14 19:17:50 +04:00
if ( tmp_fd = = - 1 ) {
status = NT_STATUS_ACCESS_DENIED ;
goto out ;
}
2008-04-30 01:36:24 +04:00
if ( ! convert_string_talloc ( mem_ctx , CH_UTF16LE , CH_UNIX , data_in , n ,
2011-03-24 02:59:41 +03:00
( void * ) & data_out , & converted_size ) )
2008-04-30 01:36:24 +04:00
{
2007-08-14 19:17:50 +04:00
status = NT_STATUS_INVALID_BUFFER_SIZE ;
goto out ;
}
DEBUG ( 11 , ( " convert_file_from_ucs2: "
2016-11-10 17:15:05 +03:00
" %s skipping utf16-le BOM \n " , tmp_name ) ) ;
converted_size - = 3 ;
2007-08-14 19:17:50 +04:00
2016-11-10 17:15:05 +03:00
if ( write ( tmp_fd , data_out + 3 , converted_size ) ! = converted_size ) {
2011-06-20 08:55:32 +04:00
status = map_nt_error_from_unix_common ( errno ) ;
2007-08-14 19:17:50 +04:00
goto out ;
}
* filename_out = tmp_name ;
status = NT_STATUS_OK ;
out :
2008-03-23 19:49:04 +03:00
if ( tmp_fd ! = - 1 ) {
2007-08-14 19:17:50 +04:00
close ( tmp_fd ) ;
}
2009-04-20 16:57:33 +04:00
talloc_free ( data_in ) ;
2016-11-10 17:15:05 +03:00
talloc_free ( data_out ) ;
2007-08-14 19:17:50 +04:00
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-09-27 19:18:51 +03:00
NTSTATUS gp_inifile_getstring ( struct gp_inifile_context * ctx , const char * key , const char * * ret )
2009-04-20 16:57:33 +04:00
{
int i ;
for ( i = 0 ; i < ctx - > keyval_count ; i + + ) {
if ( strcmp ( ctx - > data [ i ] - > key , key ) = = 0 ) {
2013-12-12 21:24:47 +04:00
if ( ret ) {
* ret = ctx - > data [ i ] - > val ;
}
2009-04-20 16:57:33 +04:00
return NT_STATUS_OK ;
}
}
return NT_STATUS_NOT_FOUND ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS gp_inifile_getint ( struct gp_inifile_context * ctx , const char * key , int * ret )
{
2016-09-27 19:18:51 +03:00
const char * value ;
2009-04-20 16:57:33 +04:00
NTSTATUS result ;
result = gp_inifile_getstring ( ctx , key , & value ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
2013-12-12 21:24:47 +04:00
if ( ret ) {
* ret = ( int ) strtol ( value , NULL , 10 ) ;
}
2009-04-20 16:57:33 +04:00
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-11 03:44:49 +04:00
NTSTATUS gp_inifile_getbool ( struct gp_inifile_context * ctx , const char * key , bool * ret )
{
2016-09-27 19:18:51 +03:00
const char * value ;
2013-12-11 03:44:49 +04:00
NTSTATUS result ;
result = gp_inifile_getstring ( ctx , key , & value ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
2016-09-08 22:28:22 +03:00
if ( strequal ( value , " Yes " ) | |
strequal ( value , " True " ) ) {
2013-12-12 21:24:47 +04:00
if ( ret ) {
* ret = true ;
}
2013-12-11 03:44:49 +04:00
return NT_STATUS_OK ;
2016-09-08 22:28:22 +03:00
} else if ( strequal ( value , " No " ) | |
strequal ( value , " False " ) ) {
2013-12-12 21:24:47 +04:00
if ( ret ) {
* ret = false ;
}
2013-12-11 03:44:49 +04:00
return NT_STATUS_OK ;
}
return NT_STATUS_NOT_FOUND ;
}
2016-09-13 09:36:59 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS gp_inifile_enum_section ( struct gp_inifile_context * ctx ,
const char * section ,
size_t * num_ini_keys ,
const char * * * ini_keys ,
const char * * * ini_values )
{
NTSTATUS status ;
int i ;
size_t num_keys = 0 , num_vals = 0 ;
const char * * keys = NULL ;
const char * * values = NULL ;
if ( section = = NULL | | num_ini_keys = = NULL | |
ini_keys = = NULL | | ini_values = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
for ( i = 0 ; i < ctx - > keyval_count ; i + + ) {
bool ok ;
/*
* section : KEYNAME
* KEYNAME : value matches
* KEYNAME_OEM : value not
*/
if ( strlen ( section ) + 1 > strlen ( ctx - > data [ i ] - > key ) ) {
continue ;
}
if ( ! strnequal ( section , ctx - > data [ i ] - > key , strlen ( section ) ) ) {
continue ;
}
if ( ctx - > data [ i ] - > key [ strlen ( section ) ] ! = ' : ' ) {
continue ;
}
ok = add_string_to_array ( ctx , ctx - > data [ i ] - > key , & keys , & num_keys ) ;
if ( ! ok ) {
status = NT_STATUS_NO_MEMORY ;
goto failed ;
}
ok = add_string_to_array ( ctx , ctx - > data [ i ] - > val , & values , & num_vals ) ;
if ( ! ok ) {
status = NT_STATUS_NO_MEMORY ;
goto failed ;
}
if ( num_keys ! = num_vals ) {
status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
goto failed ;
}
}
* num_ini_keys = num_keys ;
* ini_keys = keys ;
* ini_values = values ;
return NT_STATUS_OK ;
failed :
talloc_free ( keys ) ;
talloc_free ( values ) ;
return status ;
}
2013-12-11 03:44:49 +04:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-04-20 16:57:33 +04:00
NTSTATUS gp_inifile_init_context ( TALLOC_CTX * mem_ctx ,
2007-08-14 19:17:50 +04:00
uint32_t flags ,
const char * unix_path ,
const char * suffix ,
struct gp_inifile_context * * ctx_ret )
{
struct gp_inifile_context * ctx = NULL ;
NTSTATUS status ;
2009-04-20 18:51:33 +04:00
int rv ;
2007-08-14 19:17:50 +04:00
char * tmp_filename = NULL ;
const char * ini_filename = NULL ;
if ( ! unix_path | | ! ctx_ret ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2009-04-20 16:57:33 +04:00
ctx = talloc_zero ( mem_ctx , struct gp_inifile_context ) ;
2007-08-14 19:17:50 +04:00
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
status = gp_find_file ( mem_ctx , flags , unix_path , suffix ,
& ini_filename ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto failed ;
}
status = convert_file_from_ucs2 ( mem_ctx , ini_filename ,
& tmp_filename ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto failed ;
}
2016-11-10 17:15:05 +03:00
rv = pm_process ( tmp_filename ! = NULL ? tmp_filename : ini_filename ,
change_section , store_keyval_pair , ctx ) ;
2009-04-20 18:51:33 +04:00
if ( ! rv ) {
return NT_STATUS_NO_SUCH_FILE ;
}
2007-08-14 19:17:50 +04:00
ctx - > generated_filename = tmp_filename ;
ctx - > mem_ctx = mem_ctx ;
* ctx_ret = ctx ;
return NT_STATUS_OK ;
failed :
2008-02-29 16:51:37 +03:00
DEBUG ( 1 , ( " gp_inifile_init_context failed: %s \n " ,
2007-08-14 19:17:50 +04:00
nt_errstr ( status ) ) ) ;
2009-04-20 16:57:33 +04:00
talloc_free ( ctx ) ;
2007-08-14 19:17:50 +04:00
return status ;
}
2016-09-11 13:48:14 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS gp_inifile_init_context_direct ( TALLOC_CTX * mem_ctx ,
const char * unix_path ,
struct gp_inifile_context * * pgp_ctx )
{
struct gp_inifile_context * gp_ctx = NULL ;
NTSTATUS status ;
2017-01-19 18:49:38 +03:00
bool rv ;
2016-09-11 13:48:14 +03:00
char * tmp_filename = NULL ;
if ( unix_path = = NULL | | pgp_ctx = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
gp_ctx = talloc_zero ( mem_ctx , struct gp_inifile_context ) ;
if ( gp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
status = convert_file_from_ucs2 ( mem_ctx , unix_path ,
& tmp_filename ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto failed ;
}
2016-09-14 19:13:39 +03:00
rv = pm_process_with_flags ( tmp_filename ! = NULL ? tmp_filename : unix_path ,
true ,
change_section ,
store_keyval_pair ,
gp_ctx ) ;
2017-01-19 18:49:38 +03:00
if ( ! rv ) {
2016-09-11 13:48:14 +03:00
return NT_STATUS_NO_SUCH_FILE ;
}
gp_ctx - > generated_filename = tmp_filename ;
gp_ctx - > mem_ctx = mem_ctx ;
* pgp_ctx = gp_ctx ;
return NT_STATUS_OK ;
failed :
DEBUG ( 1 , ( " gp_inifile_init_context_direct failed: %s \n " ,
nt_errstr ( status ) ) ) ;
talloc_free ( gp_ctx ) ;
return status ;
}
2007-08-14 19:17:50 +04:00
/****************************************************************
parse the local gpt . ini file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define GPT_INI_SECTION_GENERAL "General"
# define GPT_INI_PARAMETER_VERSION "Version"
# define GPT_INI_PARAMETER_DISPLAYNAME "displayName"
2009-04-20 18:51:33 +04:00
NTSTATUS parse_gpt_ini ( TALLOC_CTX * mem_ctx ,
2007-08-14 19:17:50 +04:00
const char * filename ,
uint32_t * version ,
char * * display_name )
{
NTSTATUS result ;
2009-04-20 16:57:33 +04:00
int rv ;
int v = 0 ;
2016-09-27 19:18:51 +03:00
const char * name = NULL ;
2009-04-20 18:51:33 +04:00
struct gp_inifile_context * ctx ;
2007-08-14 19:17:50 +04:00
if ( ! filename ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2009-04-20 18:51:33 +04:00
ctx = talloc_zero ( mem_ctx , struct gp_inifile_context ) ;
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
rv = pm_process ( filename , change_section , store_keyval_pair , ctx ) ;
2009-04-20 16:57:33 +04:00
if ( ! rv ) {
2007-08-14 19:17:50 +04:00
return NT_STATUS_NO_SUCH_FILE ;
}
2009-04-20 16:57:33 +04:00
result = gp_inifile_getstring ( ctx , GPT_INI_SECTION_GENERAL
" : " GPT_INI_PARAMETER_DISPLAYNAME , & name ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
2007-08-14 19:17:50 +04:00
/* the default domain policy and the default domain controller
* policy never have a displayname in their gpt . ini file */
DEBUG ( 10 , ( " parse_gpt_ini: no name in %s \n " , filename ) ) ;
}
if ( name & & display_name ) {
2009-04-20 16:57:33 +04:00
* display_name = talloc_strdup ( ctx , name ) ;
2007-08-14 19:17:50 +04:00
if ( * display_name = = NULL ) {
2009-04-20 16:57:33 +04:00
return NT_STATUS_NO_MEMORY ;
2007-08-14 19:17:50 +04:00
}
}
2009-04-20 16:57:33 +04:00
result = gp_inifile_getint ( ctx , GPT_INI_SECTION_GENERAL
" : " GPT_INI_PARAMETER_VERSION , & v ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
2007-08-14 19:17:50 +04:00
DEBUG ( 10 , ( " parse_gpt_ini: no version \n " ) ) ;
2009-04-20 16:57:33 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2007-08-14 19:17:50 +04:00
}
if ( version ) {
* version = v ;
}
2009-04-20 18:51:33 +04:00
talloc_free ( ctx ) ;
2007-08-14 19:17:50 +04:00
2009-04-20 18:51:33 +04:00
return NT_STATUS_OK ;
2007-08-14 19:17:50 +04:00
}