2010-08-04 17:31:08 +04:00
/*
* Unix SMB / CIFS implementation .
* RPC Pipe client / server routines
* Copyright ( C ) Andrew Tridgell 1992 - 2000 ,
* Copyright ( C ) Jean François Micouleau 1998 - 2000.
* Copyright ( C ) Gerald Carter 2002 - 2005.
*
* 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 "../librpc/gen_ndr/spoolss.h"
2011-02-08 16:17:14 +03:00
# include "rpc_server/spoolss/srv_spoolss_util.h"
2010-08-04 17:31:08 +04:00
# include "nt_printing.h"
# include "ads.h"
2010-08-05 04:25:37 +04:00
# include "secrets.h"
2010-08-18 20:45:36 +04:00
# include "krb5_env.h"
2011-02-26 02:28:15 +03:00
# include "../libcli/registry/util_reg.h"
2011-03-24 16:12:42 +03:00
# include "auth.h"
2011-04-30 02:40:28 +04:00
# include "../librpc/ndr/libndr.h"
2011-07-05 02:16:47 +04:00
# include "rpc_client/cli_winreg_spoolss.h"
2010-08-04 17:31:08 +04:00
# ifdef HAVE_ADS
/*****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-12-18 18:13:27 +03:00
WERROR nt_printer_guid_store ( struct messaging_context * msg_ctx ,
const char * printer , struct GUID guid )
2010-08-04 17:31:08 +04:00
{
TALLOC_CTX * tmp_ctx ;
2014-12-18 18:13:27 +03:00
const struct auth_session_info * session_info ;
2010-08-04 17:31:08 +04:00
const char * guid_str ;
DATA_BLOB blob ;
WERROR result ;
tmp_ctx = talloc_new ( NULL ) ;
if ( ! tmp_ctx ) {
2014-12-18 18:13:27 +03:00
DEBUG ( 0 , ( " Out of memory?! \n " ) ) ;
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-08-04 17:31:08 +04:00
}
2014-12-18 18:13:27 +03:00
session_info = get_session_info_system ( ) ;
if ( session_info = = NULL ) {
DEBUG ( 0 , ( " Could not get system session_info \n " ) ) ;
2015-12-03 17:24:14 +03:00
result = WERR_NOT_ENOUGH_MEMORY ;
2010-08-04 17:31:08 +04:00
goto done ;
}
guid_str = GUID_string ( tmp_ctx , & guid ) ;
if ( ! guid_str ) {
2014-12-18 18:13:27 +03:00
DEBUG ( 0 , ( " Out of memory?! \n " ) ) ;
2015-12-03 17:24:14 +03:00
result = WERR_NOT_ENOUGH_MEMORY ;
2010-08-04 17:31:08 +04:00
goto done ;
}
/* We used to store this as a REG_BINARY but that causes
Vista to whine */
if ( ! push_reg_sz ( tmp_ctx , & blob , guid_str ) ) {
2014-12-18 18:13:27 +03:00
DEBUG ( 0 , ( " Could not marshall string %s for objectGUID \n " ,
2010-08-04 17:31:08 +04:00
guid_str ) ) ;
2015-12-03 17:24:14 +03:00
result = WERR_NOT_ENOUGH_MEMORY ;
2010-08-04 17:31:08 +04:00
goto done ;
}
2011-07-05 02:16:03 +04:00
result = winreg_set_printer_dataex_internal ( tmp_ctx , session_info , msg_ctx ,
2010-08-08 12:19:35 +04:00
printer ,
2010-08-04 17:31:08 +04:00
SPOOL_DSSPOOLER_KEY , " objectGUID " ,
REG_SZ , blob . data , blob . length ) ;
if ( ! W_ERROR_IS_OK ( result ) ) {
2014-12-18 18:13:27 +03:00
DEBUG ( 0 , ( " Failed to store GUID for printer %s \n " , printer ) ) ;
goto done ;
2010-08-04 17:31:08 +04:00
}
2014-12-18 18:13:27 +03:00
result = WERR_OK ;
2010-08-04 17:31:08 +04:00
done :
talloc_free ( tmp_ctx ) ;
2014-12-18 18:13:27 +03:00
return result ;
2010-08-04 17:31:08 +04:00
}
2014-12-18 20:18:21 +03:00
static WERROR nt_printer_dn_lookup ( TALLOC_CTX * mem_ctx ,
ADS_STRUCT * ads ,
const char * printer ,
char * * pprinter_dn )
{
char * printer_dn = NULL ;
char * srv_dn = NULL ;
char * srv_cn_0 = NULL ;
char * srv_cn_escaped = NULL ;
char * sharename_escaped = NULL ;
char * srv_dn_utf8 = NULL ;
char * * srv_cn_utf8 = NULL ;
size_t converted_size ;
ADS_STATUS ads_status ;
LDAPMessage * res ;
WERROR result ;
bool ok ;
ads_status = ads_find_machine_acct ( ads , & res , lp_netbios_name ( ) ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 2 , ( " Failed to find machine account for %s \n " ,
lp_netbios_name ( ) ) ) ;
result = WERR_NOT_FOUND ;
goto err_out ;
}
/*
* We use ldap_get_dn here as we need the answer in utf8 to call
* ldap_explode_dn ( ) . JRA .
*/
srv_dn_utf8 = ldap_get_dn ( ( LDAP * ) ads - > ldap . ld , ( LDAPMessage * ) res ) ;
ads_msgfree ( ads , res ) ;
if ( srv_dn_utf8 = = NULL ) {
2015-12-03 17:24:31 +03:00
result = WERR_RPC_S_SERVER_UNAVAILABLE ;
2014-12-18 20:18:21 +03:00
goto err_out ;
}
srv_cn_utf8 = ldap_explode_dn ( srv_dn_utf8 , 1 ) ;
if ( srv_cn_utf8 = = NULL ) {
ldap_memfree ( srv_dn_utf8 ) ;
2015-12-03 17:24:31 +03:00
result = WERR_RPC_S_SERVER_UNAVAILABLE ;
2014-12-18 20:18:21 +03:00
goto err_out ;
}
/* Now convert to CH_UNIX. */
ok = pull_utf8_talloc ( mem_ctx , & srv_dn , srv_dn_utf8 , & converted_size ) ;
ldap_memfree ( srv_dn_utf8 ) ;
if ( ! ok ) {
ldap_memfree ( srv_cn_utf8 ) ;
2015-12-03 17:24:31 +03:00
result = WERR_RPC_S_SERVER_UNAVAILABLE ;
2014-12-18 20:18:21 +03:00
goto err_out ;
}
ok = pull_utf8_talloc ( mem_ctx , & srv_cn_0 , srv_cn_utf8 [ 0 ] , & converted_size ) ;
ldap_memfree ( srv_cn_utf8 ) ;
if ( ! ok ) {
2015-12-03 17:24:31 +03:00
result = WERR_RPC_S_SERVER_UNAVAILABLE ;
2014-12-18 20:18:21 +03:00
goto err_out ;
}
srv_cn_escaped = escape_rdn_val_string_alloc ( srv_cn_0 ) ;
if ( srv_cn_escaped = = NULL ) {
2015-12-03 17:24:31 +03:00
result = WERR_RPC_S_SERVER_UNAVAILABLE ;
2014-12-18 20:18:21 +03:00
goto err_out ;
}
sharename_escaped = escape_rdn_val_string_alloc ( printer ) ;
if ( sharename_escaped = = NULL ) {
2015-12-03 17:24:31 +03:00
result = WERR_RPC_S_SERVER_UNAVAILABLE ;
2014-12-18 20:18:21 +03:00
goto err_out ;
}
printer_dn = talloc_asprintf ( mem_ctx ,
" cn=%s-%s,%s " ,
srv_cn_escaped ,
sharename_escaped ,
srv_dn ) ;
if ( printer_dn = = NULL ) {
2015-12-03 17:24:14 +03:00
result = WERR_NOT_ENOUGH_MEMORY ;
2014-12-18 20:18:21 +03:00
goto err_out ;
}
* pprinter_dn = printer_dn ;
result = WERR_OK ;
err_out :
SAFE_FREE ( sharename_escaped ) ;
SAFE_FREE ( srv_cn_escaped ) ;
TALLOC_FREE ( srv_cn_0 ) ;
TALLOC_FREE ( srv_dn ) ;
return result ;
}
static WERROR nt_printer_guid_retrieve_internal ( ADS_STRUCT * ads ,
const char * printer_dn ,
struct GUID * pguid )
{
ADS_STATUS ads_status ;
LDAPMessage * res ;
const char * attrs [ ] = { " objectGUID " , NULL } ;
struct GUID guid ;
bool ok ;
ads_status = ads_search_dn ( ads , & res , printer_dn , attrs ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 2 , ( " Failed to retrieve GUID from DC - %s \n " ,
ads_errstr ( ads_status ) ) ) ;
2015-12-03 17:24:11 +03:00
return WERR_FILE_NOT_FOUND ;
2014-12-18 20:18:21 +03:00
}
ZERO_STRUCT ( guid ) ;
ok = ads_pull_guid ( ads , res , & guid ) ;
ads_msgfree ( ads , res ) ;
if ( ! ok ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2014-12-18 20:18:21 +03:00
}
* pguid = guid ;
return WERR_OK ;
}
2014-12-18 20:23:11 +03:00
WERROR nt_printer_guid_retrieve ( TALLOC_CTX * mem_ctx , const char * printer ,
struct GUID * pguid )
{
ADS_STRUCT * ads = NULL ;
char * old_krb5ccname = NULL ;
char * printer_dn ;
WERROR result ;
ADS_STATUS ads_status ;
TALLOC_CTX * tmp_ctx ;
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( tmp_ctx = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2014-12-18 20:23:11 +03:00
}
ads = ads_init ( lp_realm ( ) , lp_workgroup ( ) , NULL ) ;
if ( ads = = NULL ) {
2015-12-03 17:24:31 +03:00
result = WERR_RPC_S_SERVER_UNAVAILABLE ;
2014-12-18 20:23:11 +03:00
goto out ;
}
old_krb5ccname = getenv ( KRB5_ENV_CCNAME ) ;
setenv ( KRB5_ENV_CCNAME , " MEMORY:prtpub_cache " , 1 ) ;
SAFE_FREE ( ads - > auth . password ) ;
ads - > auth . password = secrets_fetch_machine_password ( lp_workgroup ( ) ,
NULL , NULL ) ;
ads_status = ads_connect ( ads ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 3 , ( " ads_connect failed: %s \n " , ads_errstr ( ads_status ) ) ) ;
result = WERR_ACCESS_DENIED ;
goto out ;
}
result = nt_printer_dn_lookup ( tmp_ctx , ads , printer , & printer_dn ) ;
if ( ! W_ERROR_IS_OK ( result ) ) {
goto out ;
}
result = nt_printer_guid_retrieve_internal ( ads , printer_dn , pguid ) ;
out :
TALLOC_FREE ( tmp_ctx ) ;
ads_destroy ( & ads ) ;
ads_kdestroy ( " MEMORY:prtpub_cache " ) ;
unsetenv ( KRB5_ENV_CCNAME ) ;
if ( old_krb5ccname ! = NULL ) {
setenv ( KRB5_ENV_CCNAME , old_krb5ccname , 0 ) ;
}
return result ;
}
2013-05-29 12:43:33 +04:00
WERROR nt_printer_guid_get ( TALLOC_CTX * mem_ctx ,
const struct auth_session_info * session_info ,
struct messaging_context * msg_ctx ,
const char * printer , struct GUID * guid )
{
TALLOC_CTX * tmp_ctx ;
enum winreg_Type type ;
DATA_BLOB blob ;
uint32_t len ;
NTSTATUS status ;
WERROR result ;
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( tmp_ctx = = NULL ) {
DEBUG ( 0 , ( " out of memory?! \n " ) ) ;
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2013-05-29 12:43:33 +04:00
}
result = winreg_get_printer_dataex_internal ( tmp_ctx , session_info ,
msg_ctx , printer ,
SPOOL_DSSPOOLER_KEY ,
" objectGUID " ,
& type ,
& blob . data ,
& len ) ;
if ( ! W_ERROR_IS_OK ( result ) ) {
DEBUG ( 0 , ( " Failed to get GUID for printer %s \n " , printer ) ) ;
goto out_ctx_free ;
}
blob . length = ( size_t ) len ;
/* We used to store the guid as REG_BINARY, then swapped
to REG_SZ for Vista compatibility so check for both */
switch ( type ) {
case REG_SZ : {
bool ok ;
const char * guid_str ;
ok = pull_reg_sz ( tmp_ctx , & blob , & guid_str ) ;
if ( ! ok ) {
DEBUG ( 0 , ( " Failed to unmarshall GUID for printer %s \n " ,
printer ) ) ;
2015-12-03 17:24:28 +03:00
result = WERR_REGISTRY_CORRUPT ;
2013-05-29 12:43:33 +04:00
goto out_ctx_free ;
}
status = GUID_from_string ( guid_str , guid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " bad GUID for printer %s \n " , printer ) ) ;
result = ntstatus_to_werror ( status ) ;
goto out_ctx_free ;
}
break ;
}
case REG_BINARY :
if ( blob . length ! = sizeof ( struct GUID ) ) {
DEBUG ( 0 , ( " bad GUID for printer %s \n " , printer ) ) ;
2015-12-03 17:24:28 +03:00
result = WERR_REGISTRY_CORRUPT ;
2013-05-29 12:43:33 +04:00
goto out_ctx_free ;
}
memcpy ( guid , blob . data , sizeof ( struct GUID ) ) ;
break ;
default :
DEBUG ( 0 , ( " GUID value stored as invalid type (%d) \n " , type ) ) ;
2015-12-03 17:24:28 +03:00
result = WERR_REGISTRY_CORRUPT ;
2013-05-29 12:43:33 +04:00
goto out_ctx_free ;
break ;
}
result = WERR_OK ;
out_ctx_free :
talloc_free ( tmp_ctx ) ;
return result ;
}
2013-01-17 16:21:25 +04:00
static WERROR nt_printer_info_to_mods ( TALLOC_CTX * ctx ,
struct spoolss_PrinterInfo2 * info2 ,
ADS_MODLIST * mods )
{
char * info_str ;
ads_mod_str ( ctx , mods , SPOOL_REG_PRINTERNAME , info2 - > sharename ) ;
ads_mod_str ( ctx , mods , SPOOL_REG_SHORTSERVERNAME , lp_netbios_name ( ) ) ;
ads_mod_str ( ctx , mods , SPOOL_REG_SERVERNAME , get_mydnsfullname ( ) ) ;
info_str = talloc_asprintf ( ctx , " \\ \\ %s \\ %s " ,
get_mydnsfullname ( ) , info2 - > sharename ) ;
if ( info_str = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2013-01-17 16:21:25 +04:00
}
ads_mod_str ( ctx , mods , SPOOL_REG_UNCNAME , info_str ) ;
info_str = talloc_asprintf ( ctx , " %d " , 4 ) ;
if ( info_str = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2013-01-17 16:21:25 +04:00
}
ads_mod_str ( ctx , mods , SPOOL_REG_VERSIONNUMBER , info_str ) ;
/* empty strings in the mods list result in an attrubute error */
if ( strlen ( info2 - > drivername ) ! = 0 )
ads_mod_str ( ctx , mods , SPOOL_REG_DRIVERNAME , info2 - > drivername ) ;
if ( strlen ( info2 - > location ) ! = 0 )
ads_mod_str ( ctx , mods , SPOOL_REG_LOCATION , info2 - > location ) ;
if ( strlen ( info2 - > comment ) ! = 0 )
ads_mod_str ( ctx , mods , SPOOL_REG_DESCRIPTION , info2 - > comment ) ;
if ( strlen ( info2 - > portname ) ! = 0 )
ads_mod_str ( ctx , mods , SPOOL_REG_PORTNAME , info2 - > portname ) ;
if ( strlen ( info2 - > sepfile ) ! = 0 )
ads_mod_str ( ctx , mods , SPOOL_REG_PRINTSEPARATORFILE , info2 - > sepfile ) ;
info_str = talloc_asprintf ( ctx , " %u " , info2 - > starttime ) ;
if ( info_str = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2013-01-17 16:21:25 +04:00
}
ads_mod_str ( ctx , mods , SPOOL_REG_PRINTSTARTTIME , info_str ) ;
info_str = talloc_asprintf ( ctx , " %u " , info2 - > untiltime ) ;
if ( info_str = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2013-01-17 16:21:25 +04:00
}
ads_mod_str ( ctx , mods , SPOOL_REG_PRINTENDTIME , info_str ) ;
info_str = talloc_asprintf ( ctx , " %u " , info2 - > priority ) ;
if ( info_str = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2013-01-17 16:21:25 +04:00
}
ads_mod_str ( ctx , mods , SPOOL_REG_PRIORITY , info_str ) ;
if ( info2 - > attributes & PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS ) {
ads_mod_str ( ctx , mods , SPOOL_REG_PRINTKEEPPRINTEDJOBS , " TRUE " ) ;
} else {
ads_mod_str ( ctx , mods , SPOOL_REG_PRINTKEEPPRINTEDJOBS , " FALSE " ) ;
}
switch ( info2 - > attributes & 0x3 ) {
case 0 :
ads_mod_str ( ctx , mods , SPOOL_REG_PRINTSPOOLING ,
SPOOL_REGVAL_PRINTWHILESPOOLING ) ;
break ;
case 1 :
ads_mod_str ( ctx , mods , SPOOL_REG_PRINTSPOOLING ,
SPOOL_REGVAL_PRINTAFTERSPOOLED ) ;
break ;
case 2 :
ads_mod_str ( ctx , mods , SPOOL_REG_PRINTSPOOLING ,
SPOOL_REGVAL_PRINTDIRECT ) ;
break ;
default :
DEBUG ( 3 , ( " unsupported printer attributes %x \n " ,
info2 - > attributes ) ) ;
}
return WERR_OK ;
}
2010-08-08 16:33:45 +04:00
static WERROR nt_printer_publish_ads ( struct messaging_context * msg_ctx ,
ADS_STRUCT * ads ,
2010-08-04 17:31:08 +04:00
struct spoolss_PrinterInfo2 * pinfo2 )
{
ADS_STATUS ads_rc ;
TALLOC_CTX * ctx ;
ADS_MODLIST mods ;
struct GUID guid ;
WERROR win_rc = WERR_OK ;
const char * printer = pinfo2 - > sharename ;
2014-12-18 20:18:21 +03:00
char * printer_dn = NULL ;
2010-08-04 17:31:08 +04:00
/* build the ads mods */
ctx = talloc_init ( " nt_printer_publish_ads " ) ;
if ( ctx = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-08-04 17:31:08 +04:00
}
DEBUG ( 5 , ( " publishing printer %s \n " , printer ) ) ;
2014-12-18 20:18:21 +03:00
win_rc = nt_printer_dn_lookup ( ctx , ads , printer , & printer_dn ) ;
if ( ! W_ERROR_IS_OK ( win_rc ) ) {
DEBUG ( 2 , ( " Failed to create printer dn \n " ) ) ;
2010-08-04 17:31:08 +04:00
TALLOC_FREE ( ctx ) ;
2014-12-18 20:18:21 +03:00
return win_rc ;
2010-08-04 17:31:08 +04:00
}
mods = ads_init_mods ( ctx ) ;
if ( mods = = NULL ) {
TALLOC_FREE ( ctx ) ;
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-08-04 17:31:08 +04:00
}
2013-01-17 16:21:25 +04:00
win_rc = nt_printer_info_to_mods ( ctx , pinfo2 , & mods ) ;
if ( ! W_ERROR_IS_OK ( win_rc ) ) {
TALLOC_FREE ( ctx ) ;
return win_rc ;
}
2010-08-04 17:31:08 +04:00
/* publish it */
2014-12-18 20:18:21 +03:00
ads_rc = ads_mod_printer_entry ( ads , printer_dn , ctx , & mods ) ;
2010-08-04 17:31:08 +04:00
if ( ads_rc . err . rc = = LDAP_NO_SUCH_OBJECT ) {
int i ;
for ( i = 0 ; mods [ i ] ! = 0 ; i + + )
;
mods [ i ] = ( LDAPMod * ) - 1 ;
2014-12-18 20:18:21 +03:00
ads_rc = ads_add_printer_entry ( ads , printer_dn , ctx , & mods ) ;
2010-08-04 17:31:08 +04:00
}
if ( ! ADS_ERR_OK ( ads_rc ) ) {
DEBUG ( 3 , ( " error publishing %s: %s \n " ,
printer , ads_errstr ( ads_rc ) ) ) ;
2014-12-18 18:13:27 +03:00
/* XXX failed to publish, so no guid to retrieve */
2010-08-04 17:31:08 +04:00
}
2014-12-18 20:18:21 +03:00
win_rc = nt_printer_guid_retrieve_internal ( ads , printer_dn , & guid ) ;
if ( ! W_ERROR_IS_OK ( win_rc ) ) {
TALLOC_FREE ( ctx ) ;
return win_rc ;
2010-08-04 17:31:08 +04:00
}
2014-12-18 20:18:21 +03:00
2014-12-18 18:13:27 +03:00
win_rc = nt_printer_guid_store ( msg_ctx , printer , guid ) ;
if ( ! W_ERROR_IS_OK ( win_rc ) ) {
DEBUG ( 3 , ( " failed to store printer %s guid \n " ,
printer ) ) ;
/* not catastrophic, retrieve on next use */
win_rc = WERR_OK ;
}
2014-12-18 20:18:21 +03:00
2010-08-04 17:31:08 +04:00
TALLOC_FREE ( ctx ) ;
return win_rc ;
}
static WERROR nt_printer_unpublish_ads ( ADS_STRUCT * ads ,
const char * printer )
{
ADS_STATUS ads_rc ;
LDAPMessage * res = NULL ;
char * prt_dn = NULL ;
DEBUG ( 5 , ( " unpublishing printer %s \n " , printer ) ) ;
/* remove the printer from the directory */
ads_rc = ads_find_printer_on_server ( ads , & res ,
2011-06-09 09:31:03 +04:00
printer , lp_netbios_name ( ) ) ;
2010-08-04 17:31:08 +04:00
if ( ADS_ERR_OK ( ads_rc ) & & res & & ads_count_replies ( ads , res ) ) {
prt_dn = ads_get_dn ( ads , talloc_tos ( ) , res ) ;
if ( ! prt_dn ) {
ads_msgfree ( ads , res ) ;
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-08-04 17:31:08 +04:00
}
ads_rc = ads_del_dn ( ads , prt_dn ) ;
TALLOC_FREE ( prt_dn ) ;
}
if ( res ) {
ads_msgfree ( ads , res ) ;
}
return WERR_OK ;
}
/****************************************************************************
* Publish a printer in the directory
*
* @ param mem_ctx memory context
2011-02-21 12:25:52 +03:00
* @ param session_info session_info to access winreg pipe
2010-08-04 17:31:08 +04:00
* @ param pinfo2 printer information
* @ param action publish / unpublish action
* @ return WERROR indicating status of publishing
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR nt_printer_publish ( TALLOC_CTX * mem_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2010-08-08 16:35:50 +04:00
struct messaging_context * msg_ctx ,
2010-08-04 17:31:08 +04:00
struct spoolss_PrinterInfo2 * pinfo2 ,
int action )
{
uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES ;
struct spoolss_SetPrinterInfo2 * sinfo2 ;
ADS_STATUS ads_rc ;
ADS_STRUCT * ads = NULL ;
WERROR win_rc ;
2013-07-19 17:10:05 +04:00
char * old_krb5ccname = NULL ;
2010-08-04 17:31:08 +04:00
sinfo2 = talloc_zero ( mem_ctx , struct spoolss_SetPrinterInfo2 ) ;
if ( ! sinfo2 ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-08-04 17:31:08 +04:00
}
switch ( action ) {
case DSPRINT_PUBLISH :
case DSPRINT_UPDATE :
pinfo2 - > attributes | = PRINTER_ATTRIBUTE_PUBLISHED ;
break ;
case DSPRINT_UNPUBLISH :
2013-05-29 12:43:32 +04:00
pinfo2 - > attributes & = ( ~ PRINTER_ATTRIBUTE_PUBLISHED ) ;
2010-08-04 17:31:08 +04:00
break ;
default :
win_rc = WERR_NOT_SUPPORTED ;
goto done ;
}
sinfo2 - > attributes = pinfo2 - > attributes ;
2011-07-05 02:16:03 +04:00
win_rc = winreg_update_printer_internal ( mem_ctx , session_info , msg_ctx ,
2010-08-04 17:31:08 +04:00
pinfo2 - > sharename , info2_mask ,
sinfo2 , NULL , NULL ) ;
if ( ! W_ERROR_IS_OK ( win_rc ) ) {
2016-11-08 14:20:25 +03:00
DBG_NOTICE ( " Failed to update data for printer [%s] - %s \n " ,
pinfo2 - > sharename ,
win_errstr ( win_rc ) ) ;
2010-08-04 17:31:08 +04:00
goto done ;
}
TALLOC_FREE ( sinfo2 ) ;
ads = ads_init ( lp_realm ( ) , lp_workgroup ( ) , NULL ) ;
if ( ! ads ) {
DEBUG ( 3 , ( " ads_init() failed \n " ) ) ;
2015-12-03 17:24:31 +03:00
win_rc = WERR_RPC_S_SERVER_UNAVAILABLE ;
2010-08-04 17:31:08 +04:00
goto done ;
}
2013-07-19 17:10:05 +04:00
old_krb5ccname = getenv ( KRB5_ENV_CCNAME ) ;
2010-08-04 17:31:08 +04:00
setenv ( KRB5_ENV_CCNAME , " MEMORY:prtpub_cache " , 1 ) ;
SAFE_FREE ( ads - > auth . password ) ;
ads - > auth . password = secrets_fetch_machine_password ( lp_workgroup ( ) ,
NULL , NULL ) ;
/* ads_connect() will find the DC for us */
ads_rc = ads_connect ( ads ) ;
if ( ! ADS_ERR_OK ( ads_rc ) ) {
DEBUG ( 3 , ( " ads_connect failed: %s \n " , ads_errstr ( ads_rc ) ) ) ;
win_rc = WERR_ACCESS_DENIED ;
goto done ;
}
switch ( action ) {
case DSPRINT_PUBLISH :
case DSPRINT_UPDATE :
2010-08-08 16:35:50 +04:00
win_rc = nt_printer_publish_ads ( msg_ctx , ads , pinfo2 ) ;
2010-08-04 17:31:08 +04:00
break ;
case DSPRINT_UNPUBLISH :
win_rc = nt_printer_unpublish_ads ( ads , pinfo2 - > sharename ) ;
break ;
}
done :
ads_destroy ( & ads ) ;
2013-07-19 17:10:05 +04:00
ads_kdestroy ( " MEMORY:prtpub_cache " ) ;
unsetenv ( KRB5_ENV_CCNAME ) ;
if ( old_krb5ccname ) {
setenv ( KRB5_ENV_CCNAME , old_krb5ccname , 0 ) ;
}
2010-08-04 17:31:08 +04:00
return win_rc ;
}
2010-08-08 16:37:47 +04:00
WERROR check_published_printers ( struct messaging_context * msg_ctx )
2010-08-04 17:31:08 +04:00
{
ADS_STATUS ads_rc ;
ADS_STRUCT * ads = NULL ;
int snum ;
int n_services = lp_numservices ( ) ;
TALLOC_CTX * tmp_ctx = NULL ;
2011-07-18 07:06:47 +04:00
struct auth_session_info * session_info = NULL ;
2010-08-04 17:31:08 +04:00
struct spoolss_PrinterInfo2 * pinfo2 ;
NTSTATUS status ;
WERROR result ;
2013-07-19 17:10:05 +04:00
char * old_krb5ccname = NULL ;
2010-08-04 17:31:08 +04:00
tmp_ctx = talloc_new ( NULL ) ;
2015-12-03 17:24:14 +03:00
if ( ! tmp_ctx ) return WERR_NOT_ENOUGH_MEMORY ;
2010-08-04 17:31:08 +04:00
ads = ads_init ( lp_realm ( ) , lp_workgroup ( ) , NULL ) ;
if ( ! ads ) {
DEBUG ( 3 , ( " ads_init() failed \n " ) ) ;
2015-12-03 17:24:31 +03:00
return WERR_RPC_S_SERVER_UNAVAILABLE ;
2010-08-04 17:31:08 +04:00
}
2013-07-19 17:10:05 +04:00
old_krb5ccname = getenv ( KRB5_ENV_CCNAME ) ;
2010-08-04 17:31:08 +04:00
setenv ( KRB5_ENV_CCNAME , " MEMORY:prtpub_cache " , 1 ) ;
SAFE_FREE ( ads - > auth . password ) ;
ads - > auth . password = secrets_fetch_machine_password ( lp_workgroup ( ) ,
NULL , NULL ) ;
/* ads_connect() will find the DC for us */
ads_rc = ads_connect ( ads ) ;
if ( ! ADS_ERR_OK ( ads_rc ) ) {
DEBUG ( 3 , ( " ads_connect failed: %s \n " , ads_errstr ( ads_rc ) ) ) ;
result = WERR_ACCESS_DENIED ;
goto done ;
}
2011-02-21 12:25:52 +03:00
status = make_session_info_system ( tmp_ctx , & session_info ) ;
2010-08-04 17:31:08 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " check_published_printers: "
2011-02-21 12:25:52 +03:00
" Could not create system session_info \n " ) ) ;
2010-08-04 17:31:08 +04:00
result = WERR_ACCESS_DENIED ;
goto done ;
}
for ( snum = 0 ; snum < n_services ; snum + + ) {
2014-02-02 17:48:41 +04:00
if ( ! lp_snum_ok ( snum ) | | ! lp_printable ( snum ) ) {
2010-08-04 17:31:08 +04:00
continue ;
}
2011-07-05 02:16:03 +04:00
result = winreg_get_printer_internal ( tmp_ctx , session_info , msg_ctx ,
2012-07-18 09:37:23 +04:00
lp_servicename ( talloc_tos ( ) , snum ) ,
2010-08-08 16:37:47 +04:00
& pinfo2 ) ;
2010-08-04 17:31:08 +04:00
if ( ! W_ERROR_IS_OK ( result ) ) {
continue ;
}
if ( pinfo2 - > attributes & PRINTER_ATTRIBUTE_PUBLISHED ) {
2010-08-08 16:37:47 +04:00
nt_printer_publish_ads ( msg_ctx , ads , pinfo2 ) ;
2010-08-04 17:31:08 +04:00
}
TALLOC_FREE ( pinfo2 ) ;
}
result = WERR_OK ;
done :
ads_destroy ( & ads ) ;
ads_kdestroy ( " MEMORY:prtpub_cache " ) ;
2013-07-19 17:10:05 +04:00
unsetenv ( KRB5_ENV_CCNAME ) ;
if ( old_krb5ccname ) {
setenv ( KRB5_ENV_CCNAME , old_krb5ccname , 0 ) ;
}
2010-08-04 17:31:08 +04:00
talloc_free ( tmp_ctx ) ;
return result ;
}
bool is_printer_published ( TALLOC_CTX * mem_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2010-08-08 16:39:40 +04:00
struct messaging_context * msg_ctx ,
2012-02-10 16:45:24 +04:00
const char * servername ,
const char * printer ,
2010-08-04 17:31:08 +04:00
struct spoolss_PrinterInfo2 * * info2 )
{
struct spoolss_PrinterInfo2 * pinfo2 = NULL ;
WERROR result ;
2011-07-05 02:55:35 +04:00
struct dcerpc_binding_handle * b ;
2010-08-04 17:31:08 +04:00
2011-07-05 02:55:35 +04:00
result = winreg_printer_binding_handle ( mem_ctx ,
session_info ,
msg_ctx ,
& b ) ;
if ( ! W_ERROR_IS_OK ( result ) ) {
return false ;
}
result = winreg_get_printer ( mem_ctx , b ,
2010-09-29 06:51:56 +04:00
printer , & pinfo2 ) ;
2010-08-04 17:31:08 +04:00
if ( ! W_ERROR_IS_OK ( result ) ) {
return false ;
}
if ( ! ( pinfo2 - > attributes & PRINTER_ATTRIBUTE_PUBLISHED ) ) {
TALLOC_FREE ( pinfo2 ) ;
return false ;
}
if ( info2 ) {
* info2 = talloc_move ( mem_ctx , & pinfo2 ) ;
}
talloc_free ( pinfo2 ) ;
return true ;
}
# else
2014-12-18 18:13:27 +03:00
WERROR nt_printer_guid_store ( struct messaging_context * msg_ctx ,
const char * printer , struct GUID guid )
{
return WERR_NOT_SUPPORTED ;
}
2014-12-18 20:23:11 +03:00
WERROR nt_printer_guid_retrieve ( TALLOC_CTX * mem_ctx , const char * printer ,
struct GUID * pguid )
{
return WERR_NOT_SUPPORTED ;
}
2013-05-29 12:43:33 +04:00
WERROR nt_printer_guid_get ( TALLOC_CTX * mem_ctx ,
const struct auth_session_info * session_info ,
struct messaging_context * msg_ctx ,
const char * printer , struct GUID * guid )
{
return WERR_NOT_SUPPORTED ;
}
2010-08-04 17:31:08 +04:00
WERROR nt_printer_publish ( TALLOC_CTX * mem_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2010-08-08 18:46:48 +04:00
struct messaging_context * msg_ctx ,
2010-08-04 17:31:08 +04:00
struct spoolss_PrinterInfo2 * pinfo2 ,
int action )
{
return WERR_OK ;
}
2010-08-08 18:46:48 +04:00
WERROR check_published_printers ( struct messaging_context * msg_ctx )
2010-08-04 17:31:08 +04:00
{
return WERR_OK ;
}
bool is_printer_published ( TALLOC_CTX * mem_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2010-08-08 18:46:48 +04:00
struct messaging_context * msg_ctx ,
2012-02-10 16:45:24 +04:00
const char * servername ,
const char * printer ,
2010-08-04 17:31:08 +04:00
struct spoolss_PrinterInfo2 * * info2 )
{
return False ;
}
# endif /* HAVE_ADS */