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 ) ;
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 ;
ctx - > data = talloc_realloc ( ctx , ctx - > data , struct keyval_pair * , ctx - > keyval_count + 1 ) ;
2009-04-20 21:15:32 +04:00
ctx - > data [ ctx - > keyval_count ] = talloc_zero ( ctx , struct keyval_pair ) ;
2009-04-20 16:57:33 +04:00
ctx - > data [ ctx - > keyval_count ] - > key = talloc_asprintf ( ctx , " %s:%s " , ctx - > current_section , key ) ;
ctx - > data [ ctx - > keyval_count ] - > val = talloc_strdup ( ctx , value ) ;
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 ;
2007-08-14 19:17:50 +04:00
if ( ! filename_out ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2009-04-20 16:57:33 +04:00
data_in = ( uint8_t * ) file_load ( filename_in , & n , 0 , NULL ) ;
2007-08-14 19:17:50 +04:00
if ( ! data_in ) {
status = NT_STATUS_NO_SUCH_FILE ;
goto out ;
}
tmp_name = talloc_asprintf ( mem_ctx , " %s/convert_file_from_ucs2.XXXXXX " ,
tmpdir ( ) ) ;
if ( ! tmp_name ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2009-04-20 16:57:33 +04:00
tmp_fd = mkstemp ( tmp_name ) ;
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 ;
}
/* skip utf8 BOM */
DEBUG ( 11 , ( " convert_file_from_ucs2: "
" data_out[0]: 0x%x, data_out[1]: 0x%x, data_out[2]: 0x%x \n " ,
data_out [ 0 ] , data_out [ 1 ] , data_out [ 2 ] ) ) ;
if ( ( data_out [ 0 ] = = 0xef ) & & ( data_out [ 1 ] = = 0xbb ) & &
( data_out [ 2 ] = = 0xbf ) ) {
DEBUG ( 11 , ( " convert_file_from_ucs2: "
" %s skipping utf8 BOM \n " , tmp_name ) ) ;
data_out + = 3 ;
2008-04-30 01:36:24 +04:00
converted_size - = 3 ;
2007-08-14 19:17:50 +04:00
}
2009-04-20 16:57:33 +04:00
if ( write ( tmp_fd , data_out , 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 ) ;
2007-08-14 19:17:50 +04:00
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-04-20 16:57:33 +04:00
NTSTATUS gp_inifile_getstring ( struct gp_inifile_context * ctx , const char * key , char * * ret )
{
int i ;
for ( i = 0 ; i < ctx - > keyval_count ; i + + ) {
if ( strcmp ( ctx - > data [ i ] - > key , key ) = = 0 ) {
* ret = ctx - > data [ i ] - > val ;
return NT_STATUS_OK ;
}
}
return NT_STATUS_NOT_FOUND ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS gp_inifile_getint ( struct gp_inifile_context * ctx , const char * key , int * ret )
{
char * value ;
NTSTATUS result ;
result = gp_inifile_getstring ( ctx , key , & value ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
* ret = ( int ) strtol ( value , NULL , 10 ) ;
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 ;
}
2009-04-20 18:51:33 +04:00
rv = pm_process ( tmp_filename , change_section , store_keyval_pair , ctx ) ;
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 ;
}
/****************************************************************
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 ;
2007-08-14 19:17:50 +04:00
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
}