2010-05-13 02:05:40 +04:00
/*
Samba Unix / Linux SMB client library
Distributed SMB / CIFS Server Management Utility
Local printing tdb migration interface
Copyright ( C ) Guenther Deschner 2010
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"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2010-05-13 02:05:40 +04:00
# include "utils/net.h"
2011-04-13 16:32:16 +04:00
# include "rpc_client/rpc_client.h"
2011-07-01 17:39:11 +04:00
# include "rpc_client/cli_pipe.h"
2010-05-13 02:05:40 +04:00
# include "librpc/gen_ndr/ndr_ntprinting.h"
2011-07-01 17:02:26 +04:00
# include "librpc/gen_ndr/ndr_spoolss.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2010-05-28 04:19:32 +04:00
# include "../librpc/gen_ndr/ndr_security.h"
2011-07-01 17:39:11 +04:00
# include "../librpc/gen_ndr/ndr_winreg.h"
2011-05-05 13:25:29 +04:00
# include "util_tdb.h"
2011-07-01 17:02:26 +04:00
# include "printing/nt_printing_migrate.h"
2010-05-13 02:05:40 +04:00
# define FORMS_PREFIX "FORMS / "
# define DRIVERS_PREFIX "DRIVERS / "
# define PRINTERS_PREFIX "PRINTERS / "
2010-05-18 17:32:47 +04:00
# define SECDESC_PREFIX "SECDESC / "
2010-05-13 02:05:40 +04:00
static void dump_form ( TALLOC_CTX * mem_ctx ,
const char * key_name ,
unsigned char * data ,
size_t length )
{
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
char * s ;
struct ntprinting_form r ;
printf ( " found form: %s \n " , key_name ) ;
blob = data_blob_const ( data , length ) ;
ZERO_STRUCT ( r ) ;
ndr_err = ndr_pull_struct_blob ( & blob , mem_ctx , & r ,
( ndr_pull_flags_fn_t ) ndr_pull_ntprinting_form ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
d_fprintf ( stderr , _ ( " form pull failed: %s \n " ) ,
ndr_errstr ( ndr_err ) ) ;
return ;
}
s = NDR_PRINT_STRUCT_STRING ( mem_ctx , ntprinting_form , & r ) ;
if ( s ) {
printf ( " %s \n " , s ) ;
}
}
static void dump_driver ( TALLOC_CTX * mem_ctx ,
const char * key_name ,
unsigned char * data ,
size_t length )
{
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
char * s ;
struct ntprinting_driver r ;
printf ( " found driver: %s \n " , key_name ) ;
blob = data_blob_const ( data , length ) ;
ZERO_STRUCT ( r ) ;
ndr_err = ndr_pull_struct_blob ( & blob , mem_ctx , & r ,
( ndr_pull_flags_fn_t ) ndr_pull_ntprinting_driver ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
d_fprintf ( stderr , _ ( " driver pull failed: %s \n " ) ,
ndr_errstr ( ndr_err ) ) ;
return ;
}
s = NDR_PRINT_STRUCT_STRING ( mem_ctx , ntprinting_driver , & r ) ;
if ( s ) {
printf ( " %s \n " , s ) ;
}
}
static void dump_printer ( TALLOC_CTX * mem_ctx ,
const char * key_name ,
unsigned char * data ,
size_t length )
{
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
char * s ;
struct ntprinting_printer r ;
printf ( " found printer: %s \n " , key_name ) ;
blob = data_blob_const ( data , length ) ;
ZERO_STRUCT ( r ) ;
ndr_err = ndr_pull_struct_blob ( & blob , mem_ctx , & r ,
( ndr_pull_flags_fn_t ) ndr_pull_ntprinting_printer ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
d_fprintf ( stderr , _ ( " printer pull failed: %s \n " ) ,
ndr_errstr ( ndr_err ) ) ;
return ;
}
s = NDR_PRINT_STRUCT_STRING ( mem_ctx , ntprinting_printer , & r ) ;
if ( s ) {
printf ( " %s \n " , s ) ;
}
}
2010-05-18 17:32:47 +04:00
static void dump_sd ( TALLOC_CTX * mem_ctx ,
const char * key_name ,
unsigned char * data ,
size_t length )
{
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
char * s ;
struct sec_desc_buf r ;
printf ( " found security descriptor: %s \n " , key_name ) ;
blob = data_blob_const ( data , length ) ;
ZERO_STRUCT ( r ) ;
ndr_err = ndr_pull_struct_blob ( & blob , mem_ctx , & r ,
( ndr_pull_flags_fn_t ) ndr_pull_sec_desc_buf ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
d_fprintf ( stderr , _ ( " security descriptor pull failed: %s \n " ) ,
ndr_errstr ( ndr_err ) ) ;
return ;
}
s = NDR_PRINT_STRUCT_STRING ( mem_ctx , sec_desc_buf , & r ) ;
if ( s ) {
printf ( " %s \n " , s ) ;
}
}
2010-05-13 02:05:40 +04:00
static int net_printing_dump ( struct net_context * c , int argc ,
const char * * argv )
{
int ret = - 1 ;
TALLOC_CTX * ctx = talloc_stackframe ( ) ;
TDB_CONTEXT * tdb ;
2011-06-20 13:10:32 +04:00
TDB_DATA kbuf , dbuf ;
2010-05-13 02:05:40 +04:00
if ( argc < 1 | | c - > display_usage ) {
d_fprintf ( stderr , " %s \n net printing dump <file.tdb> \n " ,
_ ( " Usage: " ) ) ;
goto done ;
}
tdb = tdb_open_log ( argv [ 0 ] , 0 , TDB_DEFAULT , O_RDONLY , 0600 ) ;
if ( ! tdb ) {
d_fprintf ( stderr , _ ( " failed to open tdb file: %s \n " ) , argv [ 0 ] ) ;
goto done ;
}
2011-06-20 13:10:32 +04:00
for ( kbuf = tdb_firstkey_compat ( tdb ) ;
2010-05-13 02:05:40 +04:00
kbuf . dptr ;
2011-06-20 13:10:32 +04:00
kbuf = tdb_nextkey_compat ( tdb , kbuf ) )
2010-05-13 02:05:40 +04:00
{
2011-06-20 13:10:31 +04:00
dbuf = tdb_fetch_compat ( tdb , kbuf ) ;
2010-05-13 02:05:40 +04:00
if ( ! dbuf . dptr ) {
continue ;
}
if ( strncmp ( ( const char * ) kbuf . dptr , FORMS_PREFIX , strlen ( FORMS_PREFIX ) ) = = 0 ) {
dump_form ( ctx , ( const char * ) kbuf . dptr + strlen ( FORMS_PREFIX ) , dbuf . dptr , dbuf . dsize ) ;
SAFE_FREE ( dbuf . dptr ) ;
continue ;
}
if ( strncmp ( ( const char * ) kbuf . dptr , DRIVERS_PREFIX , strlen ( DRIVERS_PREFIX ) ) = = 0 ) {
dump_driver ( ctx , ( const char * ) kbuf . dptr + strlen ( DRIVERS_PREFIX ) , dbuf . dptr , dbuf . dsize ) ;
SAFE_FREE ( dbuf . dptr ) ;
continue ;
}
if ( strncmp ( ( const char * ) kbuf . dptr , PRINTERS_PREFIX , strlen ( PRINTERS_PREFIX ) ) = = 0 ) {
dump_printer ( ctx , ( const char * ) kbuf . dptr + strlen ( PRINTERS_PREFIX ) , dbuf . dptr , dbuf . dsize ) ;
SAFE_FREE ( dbuf . dptr ) ;
continue ;
}
2010-05-18 17:32:47 +04:00
if ( strncmp ( ( const char * ) kbuf . dptr , SECDESC_PREFIX , strlen ( SECDESC_PREFIX ) ) = = 0 ) {
dump_sd ( ctx , ( const char * ) kbuf . dptr + strlen ( SECDESC_PREFIX ) , dbuf . dptr , dbuf . dsize ) ;
SAFE_FREE ( dbuf . dptr ) ;
continue ;
}
2010-05-13 02:05:40 +04:00
}
ret = 0 ;
done :
talloc_free ( ctx ) ;
return ret ;
}
2010-05-17 16:01:18 +04:00
static NTSTATUS printing_migrate_internal ( struct net_context * c ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * domain_sid ,
2010-05-17 16:01:18 +04:00
const char * domain_name ,
struct cli_state * cli ,
struct rpc_pipe_client * pipe_hnd ,
TALLOC_CTX * mem_ctx ,
int argc ,
const char * * argv )
{
TALLOC_CTX * tmp_ctx ;
TDB_CONTEXT * tdb ;
2011-06-20 13:10:32 +04:00
TDB_DATA kbuf , dbuf ;
2010-05-17 16:01:18 +04:00
NTSTATUS status ;
2011-07-01 17:39:11 +04:00
struct rpc_pipe_client * winreg_pipe = NULL ;
2010-05-17 16:01:18 +04:00
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( tmp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2011-07-01 17:39:11 +04:00
status = cli_rpc_pipe_open_noauth ( rpc_pipe_np_smb_conn ( pipe_hnd ) ,
& ndr_table_winreg . syntax_id ,
& winreg_pipe ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_fprintf ( stderr , _ ( " failed to open winreg pipe: %s \n " ) ,
nt_errstr ( status ) ) ;
goto done ;
}
2010-05-17 16:01:18 +04:00
tdb = tdb_open_log ( argv [ 0 ] , 0 , TDB_DEFAULT , O_RDONLY , 0600 ) ;
if ( tdb = = NULL ) {
d_fprintf ( stderr , _ ( " failed to open tdb file: %s \n " ) , argv [ 0 ] ) ;
status = NT_STATUS_NO_SUCH_FILE ;
goto done ;
}
2011-06-20 13:10:32 +04:00
for ( kbuf = tdb_firstkey_compat ( tdb ) ;
2010-05-17 16:01:18 +04:00
kbuf . dptr ;
2011-06-20 13:10:32 +04:00
kbuf = tdb_nextkey_compat ( tdb , kbuf ) )
2010-05-17 16:01:18 +04:00
{
2011-06-20 13:10:31 +04:00
dbuf = tdb_fetch_compat ( tdb , kbuf ) ;
2010-05-17 16:01:18 +04:00
if ( ! dbuf . dptr ) {
continue ;
}
if ( strncmp ( ( const char * ) kbuf . dptr , FORMS_PREFIX , strlen ( FORMS_PREFIX ) ) = = 0 ) {
2011-07-01 17:02:26 +04:00
printing_tdb_migrate_form ( tmp_ctx ,
2010-05-17 16:01:18 +04:00
pipe_hnd ,
2011-07-01 17:39:11 +04:00
winreg_pipe ,
2010-05-17 16:01:18 +04:00
( const char * ) kbuf . dptr + strlen ( FORMS_PREFIX ) ,
dbuf . dptr ,
dbuf . dsize ) ;
SAFE_FREE ( dbuf . dptr ) ;
continue ;
}
if ( strncmp ( ( const char * ) kbuf . dptr , DRIVERS_PREFIX , strlen ( DRIVERS_PREFIX ) ) = = 0 ) {
2011-07-01 17:02:26 +04:00
printing_tdb_migrate_driver ( tmp_ctx ,
2010-05-17 16:01:18 +04:00
pipe_hnd ,
2011-07-01 17:39:11 +04:00
winreg_pipe ,
2010-05-17 16:01:18 +04:00
( const char * ) kbuf . dptr + strlen ( DRIVERS_PREFIX ) ,
dbuf . dptr ,
dbuf . dsize ) ;
SAFE_FREE ( dbuf . dptr ) ;
continue ;
}
if ( strncmp ( ( const char * ) kbuf . dptr , PRINTERS_PREFIX , strlen ( PRINTERS_PREFIX ) ) = = 0 ) {
2011-07-01 17:02:26 +04:00
printing_tdb_migrate_printer ( tmp_ctx ,
2010-05-17 16:01:18 +04:00
pipe_hnd ,
2011-07-01 17:39:11 +04:00
winreg_pipe ,
2010-05-17 16:01:18 +04:00
( const char * ) kbuf . dptr + strlen ( PRINTERS_PREFIX ) ,
dbuf . dptr ,
dbuf . dsize ) ;
SAFE_FREE ( dbuf . dptr ) ;
continue ;
}
if ( strncmp ( ( const char * ) kbuf . dptr , SECDESC_PREFIX , strlen ( SECDESC_PREFIX ) ) = = 0 ) {
2011-07-01 17:02:26 +04:00
printing_tdb_migrate_secdesc ( tmp_ctx ,
2010-05-17 16:01:18 +04:00
pipe_hnd ,
2011-07-01 17:39:11 +04:00
winreg_pipe ,
2010-05-17 16:01:18 +04:00
( const char * ) kbuf . dptr + strlen ( SECDESC_PREFIX ) ,
dbuf . dptr ,
dbuf . dsize ) ;
SAFE_FREE ( dbuf . dptr ) ;
continue ;
}
}
status = NT_STATUS_OK ;
done :
talloc_free ( tmp_ctx ) ;
return status ;
}
static int net_printing_migrate ( struct net_context * c ,
int argc ,
const char * * argv )
{
if ( argc < 1 | | c - > display_usage ) {
d_printf ( " %s \n "
" net printing migrate <file.tdb> \n "
" %s \n " ,
_ ( " Usage: " ) ,
_ ( " Migrate tdb printing files to new storage " ) ) ;
return 0 ;
}
return run_rpc_command ( c ,
NULL ,
& ndr_table_spoolss . syntax_id ,
0 ,
printing_migrate_internal ,
argc ,
argv ) ;
}
2010-05-13 02:05:40 +04:00
/**
* ' net printing ' entrypoint .
* @ param argc Standard main ( ) style argc .
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped .
* */
int net_printing ( struct net_context * c , int argc , const char * * argv )
{
int ret = - 1 ;
struct functable func [ ] = {
{
" dump " ,
net_printing_dump ,
NET_TRANSPORT_LOCAL ,
2010-08-06 19:38:15 +04:00
N_ ( " Dump printer databases " ) ,
2010-05-13 02:05:40 +04:00
N_ ( " net printing dump \n "
" Dump tdb printing file " )
} ,
2010-05-17 16:01:18 +04:00
{
" migrate " ,
net_printing_migrate ,
NET_TRANSPORT_LOCAL | NET_TRANSPORT_RPC ,
N_ ( " Migrate printer databases " ) ,
N_ ( " net printing migrate \n "
" Migrate tdb printing files to new storage " )
} ,
2010-05-13 02:05:40 +04:00
{ NULL , NULL , 0 , NULL , NULL }
} ;
ret = net_run_function ( c , argc , argv , " net printing " , func ) ;
return ret ;
}