2002-02-01 19:15:53 +03:00
/*
Unix SMB / CIFS implementation .
2002-02-01 19:58:01 +03:00
ads ( active directory ) printer utility library
2003-08-01 19:21:20 +04:00
Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2002
2002-02-01 19:15:53 +03: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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2002-02-01 19:15:53 +03:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2002-02-01 19:15:53 +03:00
*/
# include "includes.h"
2010-07-02 02:32:52 +04:00
# include "ads.h"
2011-04-13 16:32:16 +04:00
# include "rpc_client/rpc_client.h"
2011-01-15 13:44:23 +03:00
# include "../librpc/gen_ndr/ndr_spoolss_c.h"
2010-05-18 20:26:48 +04:00
# include "rpc_client/cli_spoolss.h"
2012-04-18 18:06:07 +04:00
# include "registry.h"
# include "libcli/registry/util_reg.h"
2002-02-01 19:15:53 +03:00
# ifdef HAVE_ADS
2002-02-02 05:04:01 +03:00
/*
find a printer given the name and the hostname
Note that results " res " may be allocated on return so that the
results can be used . It should be freed using ads_msgfree .
*/
2006-09-04 01:07:16 +04:00
ADS_STATUS ads_find_printer_on_server ( ADS_STRUCT * ads , LDAPMessage * * res ,
const char * printer ,
const char * servername )
2002-02-02 05:04:01 +03:00
{
ADS_STATUS status ;
2008-12-23 22:27:19 +03:00
char * srv_dn , * * srv_cn , * s = NULL ;
2002-02-02 05:04:01 +03:00
const char * attrs [ ] = { " * " , " nTSecurityDescriptor " , NULL } ;
status = ads_find_machine_acct ( ads , res , servername ) ;
if ( ! ADS_ERR_OK ( status ) ) {
2004-09-23 23:24:02 +04:00
DEBUG ( 1 , ( " ads_find_printer_on_server: cannot find host %s in ads \n " ,
2002-02-02 05:04:01 +03:00
servername ) ) ;
return status ;
}
2006-10-02 16:06:49 +04:00
if ( ads_count_replies ( ads , * res ) ! = 1 ) {
2011-03-21 12:46:53 +03:00
ads_msgfree ( ads , * res ) ;
* res = NULL ;
2006-10-02 16:06:49 +04:00
return ADS_ERROR ( LDAP_NO_SUCH_OBJECT ) ;
}
2007-07-16 15:08:00 +04:00
srv_dn = ldap_get_dn ( ads - > ldap . ld , * res ) ;
2006-10-02 16:06:49 +04:00
if ( srv_dn = = NULL ) {
2011-03-21 12:46:53 +03:00
ads_msgfree ( ads , * res ) ;
* res = NULL ;
2006-10-02 16:06:49 +04:00
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
2002-07-15 14:35:28 +04:00
srv_cn = ldap_explode_dn ( srv_dn , 1 ) ;
2006-10-02 16:06:49 +04:00
if ( srv_cn = = NULL ) {
ldap_memfree ( srv_dn ) ;
2008-12-23 22:27:19 +03:00
ads_msgfree ( ads , * res ) ;
* res = NULL ;
2011-03-21 12:46:53 +03:00
return ADS_ERROR ( LDAP_INVALID_DN_SYNTAX ) ;
2008-12-23 22:27:19 +03:00
}
2011-03-21 12:46:53 +03:00
ads_msgfree ( ads , * res ) ;
* res = NULL ;
2002-02-02 05:04:01 +03:00
2008-12-23 22:27:19 +03:00
if ( asprintf ( & s , " (cn=%s-%s) " , srv_cn [ 0 ] , printer ) = = - 1 ) {
ldap_memfree ( srv_dn ) ;
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
2003-06-13 08:29:20 +04:00
status = ads_search ( ads , res , s , attrs ) ;
2002-02-02 05:04:01 +03:00
2002-07-15 14:35:28 +04:00
ldap_memfree ( srv_dn ) ;
ldap_value_free ( srv_cn ) ;
2008-12-23 22:27:19 +03:00
SAFE_FREE ( s ) ;
2002-02-02 05:04:01 +03:00
return status ;
}
2006-09-04 01:07:16 +04:00
ADS_STATUS ads_find_printers ( ADS_STRUCT * ads , LDAPMessage * * res )
2003-07-03 09:08:51 +04:00
{
2005-07-21 13:28:12 +04:00
const char * ldap_expr ;
2003-07-03 09:08:51 +04:00
const char * attrs [ ] = { " objectClass " , " printerName " , " location " , " driverName " ,
" serverName " , " description " , NULL } ;
/* For the moment only display all printers */
2005-05-31 17:46:45 +04:00
ldap_expr = " (&(!(showInAdvancedViewOnly=TRUE))(uncName=*) "
" (objectCategory=printQueue)) " ;
2003-07-03 09:08:51 +04:00
return ads_search ( ads , res , ldap_expr , attrs ) ;
}
2002-02-01 19:15:53 +03:00
/*
2002-11-18 22:59:58 +03:00
modify a printer entry in the directory
2002-02-01 19:15:53 +03:00
*/
ADS_STATUS ads_mod_printer_entry ( ADS_STRUCT * ads , char * prt_dn ,
2002-11-18 22:59:58 +03:00
TALLOC_CTX * ctx , const ADS_MODLIST * mods )
2002-02-01 19:15:53 +03:00
{
2002-11-18 22:59:58 +03:00
return ads_gen_mod ( ads , prt_dn , * mods ) ;
2002-02-01 19:15:53 +03:00
}
/*
add a printer to the directory
*/
2002-11-18 22:59:58 +03:00
ADS_STATUS ads_add_printer_entry ( ADS_STRUCT * ads , char * prt_dn ,
TALLOC_CTX * ctx , ADS_MODLIST * mods )
2002-02-01 19:15:53 +03:00
{
2002-11-18 22:59:58 +03:00
ads_mod_str ( ctx , mods , " objectClass " , " printQueue " ) ;
return ads_gen_add ( ads , prt_dn , * mods ) ;
}
2002-02-12 21:22:47 +03:00
2002-11-18 22:59:58 +03:00
/*
map a REG_SZ to an ldap mod
*/
2012-04-18 18:06:07 +04:00
static bool map_sz ( TALLOC_CTX * ctx , ADS_MODLIST * mods ,
const char * name , struct registry_value * value )
2002-11-18 22:59:58 +03:00
{
2012-04-18 18:06:07 +04:00
const char * str_value = NULL ;
2002-11-18 23:45:46 +03:00
ADS_STATUS status ;
2002-02-12 21:22:47 +03:00
2012-04-18 18:06:07 +04:00
if ( value - > type ! = REG_SZ )
2008-04-30 01:36:24 +04:00
return false ;
2002-02-12 21:22:47 +03:00
2012-04-18 18:06:07 +04:00
if ( value - > data . length & & value - > data . data ) {
if ( ! pull_reg_sz ( ctx , & value - > data , & str_value ) ) {
2008-04-30 01:36:24 +04:00
return false ;
}
2012-04-18 18:06:07 +04:00
status = ads_mod_str ( ctx , mods , name , str_value ) ;
2002-11-18 23:45:46 +03:00
return ADS_ERR_OK ( status ) ;
2002-11-18 22:59:58 +03:00
}
2008-04-30 01:36:24 +04:00
return true ;
2002-11-18 22:59:58 +03:00
}
2002-02-12 21:22:47 +03:00
2002-11-18 22:59:58 +03:00
/*
map a REG_DWORD to an ldap mod
*/
2012-04-18 18:06:07 +04:00
static bool map_dword ( TALLOC_CTX * ctx , ADS_MODLIST * mods ,
const char * name , struct registry_value * value )
2002-11-18 22:59:58 +03:00
{
char * str_value = NULL ;
2002-11-18 23:45:46 +03:00
ADS_STATUS status ;
2002-02-12 21:22:47 +03:00
2012-04-18 18:06:07 +04:00
if ( value - > type ! = REG_DWORD ) {
return false ;
}
2015-04-18 18:40:14 +03:00
if ( value - > data . length ! = sizeof ( uint32_t ) ) {
2012-04-18 18:06:07 +04:00
return false ;
}
str_value = talloc_asprintf ( ctx , " %d " , IVAL ( value - > data . data , 0 ) ) ;
2006-06-17 03:26:48 +04:00
if ( ! str_value ) {
2012-04-18 18:06:07 +04:00
return false ;
2006-06-17 03:26:48 +04:00
}
2012-04-18 18:06:07 +04:00
status = ads_mod_str ( ctx , mods , name , str_value ) ;
2002-11-18 23:45:46 +03:00
return ADS_ERR_OK ( status ) ;
2002-11-18 22:59:58 +03:00
}
2002-02-12 21:22:47 +03:00
2002-11-18 22:59:58 +03:00
/*
map a boolean REG_BINARY to an ldap mod
*/
2007-10-19 04:40:25 +04:00
static bool map_bool ( TALLOC_CTX * ctx , ADS_MODLIST * mods ,
2012-04-18 18:06:07 +04:00
const char * name , struct registry_value * value )
2002-11-18 22:59:58 +03:00
{
2012-04-18 18:06:07 +04:00
const char * str_value ;
2002-11-18 23:45:46 +03:00
ADS_STATUS status ;
2002-02-01 19:15:53 +03:00
2012-04-18 18:06:07 +04:00
if ( value - > type ! = REG_BINARY ) {
return false ;
}
if ( value - > data . length ! = 1 ) {
return false ;
2006-06-17 03:26:48 +04:00
}
2012-04-18 18:06:07 +04:00
str_value = * value - > data . data ? " TRUE " : " FALSE " ;
status = ads_mod_str ( ctx , mods , name , str_value ) ;
2002-11-18 23:45:46 +03:00
return ADS_ERR_OK ( status ) ;
2002-02-01 19:15:53 +03:00
}
/*
2002-11-18 22:59:58 +03:00
map a REG_MULTI_SZ to an ldap mod
2002-02-01 19:15:53 +03:00
*/
2007-10-19 04:40:25 +04:00
static bool map_multi_sz ( TALLOC_CTX * ctx , ADS_MODLIST * mods ,
2012-04-18 18:06:07 +04:00
const char * name , struct registry_value * value )
2002-02-01 19:15:53 +03:00
{
2012-04-18 18:06:07 +04:00
const char * * str_values = NULL ;
2002-11-18 23:45:46 +03:00
ADS_STATUS status ;
2002-11-18 22:59:58 +03:00
2012-04-18 18:06:07 +04:00
if ( value - > type ! = REG_MULTI_SZ ) {
return false ;
}
2002-11-18 22:59:58 +03:00
2012-04-18 18:06:07 +04:00
if ( value - > data . length & & value - > data . data ) {
if ( ! pull_reg_multi_sz ( ctx , & value - > data , & str_values ) ) {
return false ;
2008-04-30 01:36:24 +04:00
}
2012-04-18 18:06:07 +04:00
status = ads_mod_strlist ( ctx , mods , name , str_values ) ;
2002-11-18 23:45:46 +03:00
return ADS_ERR_OK ( status ) ;
2012-04-18 18:06:07 +04:00
}
return true ;
2002-11-18 22:59:58 +03:00
}
2002-02-01 19:15:53 +03:00
2002-11-18 22:59:58 +03:00
struct valmap_to_ads {
2003-01-03 11:28:12 +03:00
const char * valname ;
2012-04-18 18:06:07 +04:00
bool ( * fn ) ( TALLOC_CTX * , ADS_MODLIST * , const char * , struct registry_value * ) ;
2002-11-18 22:59:58 +03:00
} ;
/*
map a REG_SZ to an ldap mod
*/
static void map_regval_to_ads ( TALLOC_CTX * ctx , ADS_MODLIST * mods ,
2012-04-18 18:06:07 +04:00
const char * name , struct registry_value * value )
2002-11-18 22:59:58 +03:00
{
2003-01-03 11:28:12 +03:00
const struct valmap_to_ads map [ ] = {
2002-12-03 22:42:39 +03:00
{ SPOOL_REG_ASSETNUMBER , map_sz } ,
{ SPOOL_REG_BYTESPERMINUTE , map_dword } ,
{ SPOOL_REG_DEFAULTPRIORITY , map_dword } ,
2002-12-05 22:13:40 +03:00
{ SPOOL_REG_DESCRIPTION , map_sz } ,
2002-12-03 22:42:39 +03:00
{ SPOOL_REG_DRIVERNAME , map_sz } ,
{ SPOOL_REG_DRIVERVERSION , map_dword } ,
{ SPOOL_REG_FLAGS , map_dword } ,
{ SPOOL_REG_LOCATION , map_sz } ,
{ SPOOL_REG_OPERATINGSYSTEM , map_sz } ,
{ SPOOL_REG_OPERATINGSYSTEMHOTFIX , map_sz } ,
{ SPOOL_REG_OPERATINGSYSTEMSERVICEPACK , map_sz } ,
{ SPOOL_REG_OPERATINGSYSTEMVERSION , map_sz } ,
{ SPOOL_REG_PORTNAME , map_multi_sz } ,
{ SPOOL_REG_PRINTATTRIBUTES , map_dword } ,
{ SPOOL_REG_PRINTBINNAMES , map_multi_sz } ,
{ SPOOL_REG_PRINTCOLLATE , map_bool } ,
{ SPOOL_REG_PRINTCOLOR , map_bool } ,
{ SPOOL_REG_PRINTDUPLEXSUPPORTED , map_bool } ,
{ SPOOL_REG_PRINTENDTIME , map_dword } ,
{ SPOOL_REG_PRINTFORMNAME , map_sz } ,
{ SPOOL_REG_PRINTKEEPPRINTEDJOBS , map_bool } ,
{ SPOOL_REG_PRINTLANGUAGE , map_multi_sz } ,
{ SPOOL_REG_PRINTMACADDRESS , map_sz } ,
{ SPOOL_REG_PRINTMAXCOPIES , map_sz } ,
{ SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED , map_dword } ,
{ SPOOL_REG_PRINTMAXXEXTENT , map_dword } ,
{ SPOOL_REG_PRINTMAXYEXTENT , map_dword } ,
{ SPOOL_REG_PRINTMEDIAREADY , map_multi_sz } ,
{ SPOOL_REG_PRINTMEDIASUPPORTED , map_multi_sz } ,
{ SPOOL_REG_PRINTMEMORY , map_dword } ,
{ SPOOL_REG_PRINTMINXEXTENT , map_dword } ,
{ SPOOL_REG_PRINTMINYEXTENT , map_dword } ,
{ SPOOL_REG_PRINTNETWORKADDRESS , map_sz } ,
{ SPOOL_REG_PRINTNOTIFY , map_sz } ,
{ SPOOL_REG_PRINTNUMBERUP , map_dword } ,
{ SPOOL_REG_PRINTORIENTATIONSSUPPORTED , map_multi_sz } ,
{ SPOOL_REG_PRINTOWNER , map_sz } ,
{ SPOOL_REG_PRINTPAGESPERMINUTE , map_dword } ,
{ SPOOL_REG_PRINTRATE , map_dword } ,
{ SPOOL_REG_PRINTRATEUNIT , map_sz } ,
{ SPOOL_REG_PRINTSEPARATORFILE , map_sz } ,
{ SPOOL_REG_PRINTSHARENAME , map_sz } ,
{ SPOOL_REG_PRINTSPOOLING , map_sz } ,
{ SPOOL_REG_PRINTSTAPLINGSUPPORTED , map_bool } ,
{ SPOOL_REG_PRINTSTARTTIME , map_dword } ,
{ SPOOL_REG_PRINTSTATUS , map_sz } ,
{ SPOOL_REG_PRIORITY , map_dword } ,
{ SPOOL_REG_SERVERNAME , map_sz } ,
{ SPOOL_REG_SHORTSERVERNAME , map_sz } ,
{ SPOOL_REG_UNCNAME , map_sz } ,
{ SPOOL_REG_URL , map_sz } ,
{ SPOOL_REG_VERSIONNUMBER , map_dword } ,
2002-11-18 22:59:58 +03:00
{ NULL , NULL }
} ;
int i ;
for ( i = 0 ; map [ i ] . valname ; i + + ) {
2012-04-18 18:06:07 +04:00
if ( strcasecmp_m ( map [ i ] . valname , name ) = = 0 ) {
if ( ! map [ i ] . fn ( ctx , mods , name , value ) ) {
DEBUG ( 5 , ( " Add of value %s to modlist failed \n " , name ) ) ;
2002-11-18 22:59:58 +03:00
} else {
2012-04-18 18:06:07 +04:00
DEBUG ( 7 , ( " Mapped value %s \n " , name ) ) ;
2002-11-18 22:59:58 +03:00
}
2002-02-01 19:15:53 +03:00
}
}
2002-11-18 22:59:58 +03:00
}
2002-02-01 19:15:53 +03:00
2005-09-30 21:13:37 +04:00
WERROR get_remote_printer_publishing_data ( struct rpc_pipe_client * cli ,
2002-11-18 22:59:58 +03:00
TALLOC_CTX * mem_ctx ,
ADS_MODLIST * mods ,
2003-01-03 11:28:12 +03:00
const char * printer )
2002-11-18 22:59:58 +03:00
{
2011-01-15 13:44:23 +03:00
struct dcerpc_binding_handle * b = cli - > binding_handle ;
2002-11-18 22:59:58 +03:00
WERROR result ;
2009-02-09 20:10:18 +03:00
char * printername ;
2009-03-18 04:33:18 +03:00
struct spoolss_PrinterEnumValues * info ;
uint32_t count ;
2015-04-18 18:40:14 +03:00
uint32_t i ;
2009-03-19 00:49:41 +03:00
struct policy_handle pol ;
2011-01-15 13:44:23 +03:00
WERROR werr ;
2002-11-18 22:59:58 +03:00
2009-02-09 20:10:18 +03:00
if ( ( asprintf ( & printername , " %s \\ %s " , cli - > srv_name_slash , printer ) = = - 1 ) ) {
2002-11-18 22:59:58 +03:00
DEBUG ( 3 , ( " Insufficient memory \n " ) ) ;
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2002-11-18 22:59:58 +03:00
}
2009-02-09 20:49:34 +03:00
result = rpccli_spoolss_openprinter_ex ( cli , mem_ctx ,
printername ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& pol ) ;
2002-11-18 22:59:58 +03:00
if ( ! W_ERROR_IS_OK ( result ) ) {
DEBUG ( 3 , ( " Unable to open printer %s, error is %s. \n " ,
2008-11-01 19:19:26 +03:00
printername , win_errstr ( result ) ) ) ;
2009-02-10 12:45:55 +03:00
SAFE_FREE ( printername ) ;
2002-11-18 22:59:58 +03:00
return result ;
}
2005-08-29 18:55:40 +04:00
2009-03-18 04:33:18 +03:00
result = rpccli_spoolss_enumprinterdataex ( cli , mem_ctx , & pol ,
SPOOL_DSDRIVER_KEY ,
0 ,
& count ,
& info ) ;
2002-11-18 22:59:58 +03:00
if ( ! W_ERROR_IS_OK ( result ) ) {
DEBUG ( 3 , ( " Unable to do enumdataex on %s, error is %s. \n " ,
2008-11-01 19:19:26 +03:00
printername , win_errstr ( result ) ) ) ;
2002-12-03 22:42:39 +03:00
} else {
/* Have the data we need now, so start building */
2009-03-18 04:33:18 +03:00
for ( i = 0 ; i < count ; i + + ) {
2012-04-18 18:06:07 +04:00
struct registry_value v ;
v . type = info [ i ] . type ;
v . data = * info [ i ] . data ;
2010-03-04 19:58:49 +03:00
2012-04-18 18:06:07 +04:00
map_regval_to_ads ( mem_ctx , mods , info [ i ] . value_name , & v ) ;
2005-08-29 18:55:40 +04:00
}
2002-12-03 22:42:39 +03:00
}
2002-11-18 22:59:58 +03:00
2009-03-18 04:33:18 +03:00
result = rpccli_spoolss_enumprinterdataex ( cli , mem_ctx , & pol ,
SPOOL_DSSPOOLER_KEY ,
0 ,
& count ,
& info ) ;
2002-11-18 22:59:58 +03:00
if ( ! W_ERROR_IS_OK ( result ) ) {
DEBUG ( 3 , ( " Unable to do enumdataex on %s, error is %s. \n " ,
2008-11-01 19:19:26 +03:00
printername , win_errstr ( result ) ) ) ;
2002-12-03 22:42:39 +03:00
} else {
2009-03-18 04:33:18 +03:00
for ( i = 0 ; i < count ; i + + ) {
2012-04-18 18:06:07 +04:00
struct registry_value v ;
v . type = info [ i ] . type ;
v . data = * info [ i ] . data ;
2010-03-04 19:58:49 +03:00
2012-04-18 18:06:07 +04:00
map_regval_to_ads ( mem_ctx , mods , info [ i ] . value_name , & v ) ;
2005-08-29 18:55:40 +04:00
}
2002-02-11 18:48:01 +03:00
}
2009-03-18 04:33:18 +03:00
ads_mod_str ( mem_ctx , mods , SPOOL_REG_PRINTERNAME , printer ) ;
2005-08-29 18:55:40 +04:00
2011-01-15 13:44:23 +03:00
dcerpc_spoolss_ClosePrinter ( b , mem_ctx , & pol , & werr ) ;
2009-02-10 12:45:55 +03:00
SAFE_FREE ( printername ) ;
2002-02-11 18:48:01 +03:00
2002-11-18 22:59:58 +03:00
return result ;
}
2002-02-01 19:15:53 +03:00
# endif