Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP4:Update
cups-filters.35881
cups-filters-1.25.0-0001-remove-cups-browsed-CV...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File cups-filters-1.25.0-0001-remove-cups-browsed-CVE-2024-47176.patch of Package cups-filters.35881
From 1d1072a0de573b7850958df614e9ec5b73ea0e0d Mon Sep 17 00:00:00 2001 From: Till Kamppeter <till.kamppeter@gmail.com> Date: Tue, 1 Oct 2024 00:59:58 +0200 Subject: [PATCH] Removed support for legacy CUPS browsing and for LDAP Legacy CUPS browsing is not needed any more. this functionality got removed from CUPS with version 1.6, more than a decade ago. In cups-browsed it was implemented as a legacy support layer for servers or clients running long-term-support enterprise distributions still using CUPS 1.5.x or older. Now the support life of all these distributions should have expired and so this legacy support by cups-browsed is not needed any more. In addition, the legacy CUPS browsing implementation in cups-browsed was listening for UDP packaets on port 631 and by default it accepted packets from any source, making it easy for attackers to set up forged printers which could make use of vulnerabilities of CUPS or just find out about the identity and properties of clients. This is CVE-2024-47176: https://ubuntu.com/security/CVE-2024-47176 https://github.com/OpenPrinting/cups-browsed/security/advisories/GHSA-rj88-6mr5-rcw8 https://openprinting.github.io/OpenPrinting-News-Flash-cups-browsed-Remote-Code-Execution-vulnerability/ The removal of the legacy CUPS browsing support removes also this vulnerability. The LDAP implementation in cups-browsed does not follow the LDAP printer schema RFC 7612 and is therefore of very limited use. --- INSTALL | 3 +- README | 53 +- configure.ac | 46 +- utils/cups-browsed.8 | 38 +- utils/cups-browsed.c | 1675 ++--------------------------------- utils/cups-browsed.conf.5 | 43 +- utils/cups-browsed.conf.in | 27 +- 8 files changed, 138 insertions(+), 1751 deletions(-) Index: cups-filters-1.25.0/README =================================================================== --- cups-filters-1.25.0.orig/README +++ cups-filters-1.25.0/README @@ -237,43 +237,33 @@ POSTSCRIPT PRINTING DEBUG MODE HELPER DAEMON FOR BROWSING REMOTE CUPS PRINTERS AND IPP NETWORK PRINTERS From version 1.6.0 on in CUPS the CUPS broadcasting/browsing - facility was dropped, in favour of Bonjour-based broadcasting of - shared printers. This is done as Bonjour broadcasting of shared + facility was dropped, in favour of DNS-SD-based broadcasting of + shared printers. This is done as DNS-SD broadcasting of shared printers is a standard, established by the PWG (Printing Working Group, http://www.pwg.org/), and most other network services (shared file systems, shared media files/streams, remote desktop - services, ...) are also broadcasted via Bonjour. + services, ...) are also broadcasted via DNS-SD. Problem is that CUPS only broadcasts its shared printers but does not browse broadcasts of other CUPS servers to make the shared remote printers available locally without any configuration efforts. This is a regression compared to the old CUPS broadcasting/browsing. The intention of CUPS upstream is that the - application's print dialogs browse the Bonjour broadcasts as an + application's print dialogs browse the DNS-SD broadcasts as an AirPrint-capable iPhone does, but it will take its time until all toolkit developers add the needed functionality, and programs using old toolkits or no toolkits at all, or the command line stay uncovered. - The solution is cups-browsed, a helper daemon running in parallel - to the CUPS daemon which listens to Bonjour broadcasts of shared - CUPS printers on remote machines in the local network via Avahi, - and can also listen for (and send) CUPS Browsing broadcasts. For - each reported remote printer it creates a local raw queue pointing - to the remote printer so that the printer appears in local print - dialogs and is also available for printing via the command - line. As with the former CUPS broadcasting/browsing with this - queue the driver on the server is used and the local print dialogs - give access to all options of the server-side printer driver. - - Note that CUPS broadcasting/browsing is available for legacy - support, to let the local CUPS daemon work seamlessly together - with remote CUPS daemons of version 1.5.x and older which only - support CUPS broadcasting/browsing. In networks with only CUPS - 1.6.x servers (or Ubuntu or Fedora/Red Hat servers with CUPS - 1.5.x) please use the native Bonjour broadcasting of your servers - and cups-browsed, configured for Bonjour browsing only on the - clients. + The solution is cups-browsed, a helper daemon running in parallel to + the CUPS daemon which listens to DNS-SD broadcasts of shared CUPS + printers on remote machines in the local network via Avahi. For each + reported remote printer it creates a local raw queue pointing to the + remote printer so that the printer appears in local print dialogs and + is also available for printing via the command line. As with the + former CUPS broadcasting/browsing with this queue the driver on the + server is used and the local print dialogs give access to all options + of the server-side printer driver. Also high availability with redundant print servers and load balancing is supported. If there is more than one server providing @@ -388,7 +378,7 @@ HELPER DAEMON FOR BROWSING REMOTE CUPS P of avahi-daemon. Here is some info on how cups-browsed works internally (first concept of a - daemon which does only Bonjour browsing): + daemon which does only DNS-SD browsing): - Daemon start o Wait for CUPS daemon if it is not running @@ -444,7 +434,7 @@ HELPER DAEMON FOR BROWSING REMOTE CUPS P of the others by one with simple name (mark old queue disappeared with timeout now-1 sec and create new queue with simple name). - Fill description of the created CUPS queue with the Bonjour + Fill description of the created CUPS queue with the DNS-SD service name (= original description) and location with the server name without .local. Index: cups-filters-1.25.0/configure.ac =================================================================== --- cups-filters-1.25.0.orig/configure.ac +++ cups-filters-1.25.0/configure.ac @@ -313,50 +313,6 @@ fi AC_SUBST(AVAHI_LIBS) AC_SUBST(AVAHI_CFLAGS) -dnl -dnl LDAP configuration stuff for CUPS. -dnl -dnl Copyright 2007-2011 by Apple Inc. -dnl Copyright 2003-2006 by Easy Software Products, all rights reserved. -dnl -dnl These coded instructions, statements, and computer programs are the -dnl property of Apple Inc. and are protected by Federal copyright -dnl law. Distribution and use rights are outlined in the file "COPYING" -dnl which should have been included with this file. -dnl - -AC_ARG_ENABLE([ldap], [AS_HELP_STRING([--disable-ldap], [disable LDAP support.])], - [enable_ldap="$enableval"], - [enable_ldap=yes] -) -AC_ARG_WITH([ldap-libs], [AS_HELP_STRING([--with-ldap-libs], [set directory for LDAP library.])], - LDFLAGS="-L$withval $LDFLAGS" - DSOFLAGS="-L$withval $DSOFLAGS",) -AC_ARG_WITH([ldap-includes], [AS_HELP_STRING([--with-ldap-includes], [set directory for LDAP includes.])], - CFLAGS="-I$withval $CFLAGS" - CPPFLAGS="-I$withval $CPPFLAGS",) - -if test x$enable_ldap != xno; then - - AC_CHECK_HEADER([ldap.h], [ - AC_SEARCH_LIBS([ldap_initialize], [ldap], [ - AC_DEFINE([HAVE_LDAP], [], [Define if LDAP support should be enabled]) - AC_DEFINE([HAVE_OPENLDAP], [], [If LDAP support is that of OpenLDAP]) - AC_CHECK_LIB([ldap], [ldap_start_tls], - AC_DEFINE([HAVE_LDAP_SSL], [], [If LDAP has SSL/TLS support enabled]))],[ - - AC_CHECK_LIB([ldap], [ldap_init], [ - AC_DEFINE([HAVE_LDAP], [], [Define if LDAP support should be enabled]) - AC_DEFINE([HAVE_MOZILLA_LDAP], [], [If LDAP support is that of Mozilla]) - AC_CHECK_HEADERS([ldap_ssl.h], [], [], [#include <ldap.h>]) - AC_CHECK_LIB([ldap], [ldapssl_init], - AC_DEFINE([HAVE_LDAP_SSL], [], [If LDAP has SSL/TLS support enabled]))])] - ) - AC_CHECK_LIB([ldap], [ldap_set_rebind_proc], AC_DEFINE([HAVE_LDAP_REBIND_PROC], [], [If libldap implements ldap_set_rebind_proc])) - ]) - -fi - PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.30.2]) AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) @@ -860,7 +816,7 @@ Build configuration: font directory: ${sysconfdir}/${FONTDIR} foomatic: ${enable_foomatic} init directory: ${INITDDIR} - cups dom socket: ${CUPS_DEFAULT_DOMAINSOCKET} + cups domain socket: ${CUPS_DEFAULT_DOMAINSOCKET} poppler: ${enable_poppler} ghostscript: ${enable_ghostscript} gs-path: ${with_gs_path} Index: cups-filters-1.25.0/utils/cups-browsed.8 =================================================================== --- cups-filters-1.25.0.orig/utils/cups-browsed.8 +++ cups-filters-1.25.0/utils/cups-browsed.8 @@ -16,20 +16,14 @@ .fam T .fi .SH DESCRIPTION -\fBcups-browsed\fP has four independently switchable functions: +\fBcups-browsed\fP has two independently switchable functions: .IP 1. 4 -Browse Bonjour broadcasts of remote printers and create/remove local -raw queues pointing to these printers. +Browse DNS-SD broadcasts of remote printers and create/remove local +CUPS queues pointing to these printers. .IP 2. 4 -Browse CUPS broadcasts of remote printers and create/remove local raw -queues pointing to these printers. -.IP 3. 4 -Browse an LDAP server for printers and create/remove local raw -queues pointing to these printers. -.IP 4. 4 -Broadcast local queues with the CUPS protocol. +Find shared printers on given CUPS servers and create local CUPS queues +pointing to them. .PP -Note that 2. and 4. are only to allow communication with legacy CUPS servers (1.5.x or older) on the remote machine(s). The standard method to broadcast for shared/network printers to broadcast their presence is Bonjour. The CUPS broadcasting/browsing protocol is deprecated. cups-browsed can be run permanently (from system boot to shutdown) or on-demand (for example to save resources on mobile devices). For running it on-demand an auto-shutdown feature can be activated to let cups-browsed terminate when it does not have queues any more to take care of. @@ -76,14 +70,6 @@ Display usage and version info and do no \fISIGUSR2\f1: Switches cups-browsed into auto shutdown mode. .SH NOTES -Please take references to cups 1.6.x to include newer versions. -Similarly, cups 1.5.x is intended to encompass older versions too. -.PP -In environments with only cups 1.6.x servers and clients (plus -\fBcups-browsed\fP on either server or client or both) the function described in 1. -enables the automatic discovery of remote queues and their display in -printing dialogues of applications and with command line tools. -.PP The facility provided by 3. allows printers that are registered in an LDAP server to be added as local queues. CUPS servers 1.5.x are able to automatically register printers in LDAP. The facility provided by \fBcups-browsed\fP allows Index: cups-filters-1.25.0/utils/cups-browsed.c =================================================================== --- cups-filters-1.25.0.orig/utils/cups-browsed.c +++ cups-filters-1.25.0/utils/cups-browsed.c @@ -53,72 +53,6 @@ #include <gio/gio.h> - -#ifdef HAVE_LDAP -# ifdef __sun -# include <lber.h> -# endif /* __sun */ -# include <ldap.h> -# ifdef HAVE_LDAP_SSL_H -# include <ldap_ssl.h> -# endif /* HAVE_LDAP_SSL_H */ -#endif /* HAVE_LDAP */ - - -#ifdef HAVE_LDAP -LDAP *BrowseLDAPHandle = NULL; - /* Handle to LDAP server */ -char *BrowseLDAPBindDN = NULL, - /* LDAP login DN */ - *BrowseLDAPDN = NULL, - /* LDAP search DN */ - *BrowseLDAPPassword = NULL, - /* LDAP login password */ - *BrowseLDAPServer = NULL, - /* LDAP server to use */ - *BrowseLDAPFilter = NULL; - /* LDAP query filter */ -int BrowseLDAPUpdate = TRUE, - /* enables LDAP updates */ - BrowseLDAPInitialised = FALSE; - /* the init stuff has been done */ -# ifdef HAVE_LDAP_SSL -char *BrowseLDAPCACertFile = NULL; - /* LDAP CA CERT file to use */ -# endif /* HAVE_LDAP_SSL */ -#endif /* HAVE_LDAP */ - - -#ifdef HAVE_LDAP -#define LDAP_BROWSE_FILTER "(objectclass=cupsPrinter)" -static LDAP *ldap_connect(void); -static LDAP *ldap_reconnect(void); -static void ldap_disconnect(LDAP *ld); -static int ldap_search_rec(LDAP *ld, char *base, int scope, - char *filter, char *attrs[], - int attrsonly, LDAPMessage **res); -static int ldap_getval_firststring(LDAP *ld, LDAPMessage *entry, - char *attr, char *retval, - unsigned long maxsize); -static void ldap_freeres(LDAPMessage *entry); -# ifdef HAVE_LDAP_REBIND_PROC -# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -static int ldap_rebind_proc(LDAP *RebindLDAPHandle, - LDAP_CONST char *refsp, - ber_tag_t request, - ber_int_t msgid, - void *params); -# else -static int ldap_rebind_proc(LDAP *RebindLDAPHandle, - char **dnp, - char **passwdp, - int *authmethodp, - int freeit, - void *arg); -# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */ -# endif /* HAVE_LDAP_REBIND_PROC */ -#endif /* HAVE_LDAP */ - #include <cups/cups.h> #include <cups/ppd.h> #include <cups/raster.h> @@ -267,17 +201,6 @@ typedef struct local_printer_s { gboolean cups_browsed_controlled; } local_printer_t; -/* Browse data to send for local printer */ -typedef struct browse_data_s { - int type; - int state; - char *uri; - char *location; - char *info; - char *make_model; - char *browse_options; -} browse_data_t; - /* Data structure for manual definition of load-balancing clusters */ typedef struct cluster_s { char *local_queue_name; @@ -385,8 +308,6 @@ static browsepoll_t *local_printers_cont static http_t *local_conn = NULL; static gboolean inhibit_local_printers_update = FALSE; -static GList *browse_data = NULL; - static CupsNotifier *cups_notifier = NULL; static GMainLoop *gmainloop = NULL; @@ -396,23 +317,10 @@ static AvahiClient *client = NULL; static AvahiServiceBrowser *sb1 = NULL, *sb2 = NULL; static int avahi_present = 0; #endif /* HAVE_AVAHI */ -#ifdef HAVE_LDAP -static const char * const ldap_attrs[] =/* CUPS LDAP attributes */ - { - "printerDescription", - "printerLocation", - "printerMakeAndModel", - "printerType", - "printerURI", - NULL - }; -#endif /* HAVE_LDAP */ static guint queues_timer_id = 0; static int browsesocket = -1; #define BROWSE_DNSSD (1<<0) -#define BROWSE_CUPS (1<<1) -#define BROWSE_LDAP (1<<2) static unsigned int BrowseLocalProtocols = 0; static unsigned int BrowseRemoteProtocols = BROWSE_DNSSD; static unsigned int BrowseInterval = 60; @@ -3561,296 +3469,6 @@ get_local_printers (void) cupsFreeDests (num_dests, dests); } -static browse_data_t * -new_browse_data (int type, int state, const gchar *uri, - const gchar *location, const gchar *info, - const gchar *make_model, const gchar *browse_options) -{ - browse_data_t *data = g_malloc (sizeof (browse_data_t)); - data->type = type; - data->state = state; - data->uri = g_strdup (uri); - data->location = g_strdup (location); - data->info = g_strdup (info); - data->make_model = g_strdup (make_model); - data->browse_options = g_strdup (browse_options); - return data; -} - -static void -browse_data_free (gpointer data) -{ - browse_data_t *bdata = data; - debug_printf("browse_data_free() in THREAD %ld\n", pthread_self()); - g_free (bdata->uri); - g_free (bdata->location); - g_free (bdata->info); - g_free (bdata->make_model); - g_free (bdata->browse_options); - g_free (bdata); -} - -static void -prepare_browse_data (void) -{ - static const char * const rattrs[] = { "printer-type", - "printer-state", - "printer-uri-supported", - "printer-info", - "printer-location", - "printer-make-and-model", - "auth-info-required", - "printer-uuid", - "job-template" }; - ipp_t *request, *response = NULL; - ipp_attribute_t *attr; - http_t *conn = NULL; - - conn = http_connect_local (); - - if (conn == NULL) { - debug_printf("Browse send failed to connect to localhost\n"); - goto fail; - } - - request = ippNewRequest(CUPS_GET_PRINTERS); - ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, - "requested-attributes", sizeof (rattrs) / sizeof (rattrs[0]), - NULL, rattrs); - ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requesting-user-name", NULL, cupsUser ()); - - debug_printf("preparing browse data\n"); - response = cupsDoRequest (conn, request, "/"); - if (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE) { - debug_printf("browse send failed for localhost: %s\n", - cupsLastErrorString ()); - goto fail; - } - - g_list_free_full (browse_data, browse_data_free); - browse_data = NULL; - for (attr = ippFirstAttribute(response); attr; - attr = ippNextAttribute(response)) { - int type = -1, state = -1; - const char *uri = NULL; - gchar *location = NULL; - gchar *info = NULL; - gchar *make_model = NULL; - GString *browse_options = g_string_new (""); - - /* Skip any non-printer attributes */ - while (attr && ippGetGroupTag(attr) != IPP_TAG_PRINTER) - attr = ippNextAttribute(response); - - if (!attr) - break; - - while (attr && ippGetGroupTag(attr) == IPP_TAG_PRINTER) { - const char *attrname = ippGetName(attr); - int value_tag = ippGetValueTag(attr); - - if (!strcasecmp(attrname, "printer-type") && - value_tag == IPP_TAG_ENUM) { - type = ippGetInteger(attr, 0); - if (type & CUPS_PRINTER_NOT_SHARED) { - /* Skip CUPS queues not marked as shared */ - state = -1; - type = -1; - break; - } - } else if (!strcasecmp(attrname, "printer-state") && - value_tag == IPP_TAG_ENUM) - state = ippGetInteger(attr, 0); - else if (!strcasecmp(attrname, "printer-uri-supported") && - value_tag == IPP_TAG_URI) - uri = ippGetString(attr, 0, NULL); - else if (!strcasecmp(attrname, "printer-location") && - value_tag == IPP_TAG_TEXT) { - /* Remove quotes */ - gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1); - location = g_strjoinv ("", tokens); - g_strfreev (tokens); - } else if (!strcasecmp(attrname, "printer-info") && - value_tag == IPP_TAG_TEXT) { - /* Remove quotes */ - gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1); - info = g_strjoinv ("", tokens); - g_strfreev (tokens); - } else if (!strcasecmp(attrname, "printer-make-and-model") && - value_tag == IPP_TAG_TEXT) { - /* Remove quotes */ - gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1); - make_model = g_strjoinv ("", tokens); - g_strfreev (tokens); - } else if (!strcasecmp(attrname, "auth-info-required") && - value_tag == IPP_TAG_KEYWORD) { - if (strcasecmp (ippGetString(attr, 0, NULL), "none")) - g_string_append_printf (browse_options, "auth-info-required=%s ", - ippGetString(attr, 0, NULL)); - } else if (!strcasecmp(attrname, "printer-uuid") && - value_tag == IPP_TAG_URI) - g_string_append_printf (browse_options, "uuid=%s ", - ippGetString(attr, 0, NULL)); - else if (!strcasecmp(attrname, "job-sheets-default") && - value_tag == IPP_TAG_NAME && - ippGetCount(attr) == 2) - g_string_append_printf (browse_options, "job-sheets=%s,%s ", - ippGetString(attr, 0, NULL), - ippGetString(attr, 1, NULL)); - else if (strstr(attrname, "-default")) { - gchar *name = g_strdup (attrname); - gchar *value = NULL; - *strstr (name, "-default") = '\0'; - - switch (value_tag) { - gchar **tokens; - - case IPP_TAG_KEYWORD: - case IPP_TAG_STRING: - case IPP_TAG_NAME: - /* Escape value */ - tokens = g_strsplit_set (ippGetString(attr, 0, NULL), - " \"\'\\", -1); - value = g_strjoinv ("\\", tokens); - g_strfreev (tokens); - break; - - default: - /* other values aren't needed? */ - debug_printf("skipping %s (%d)\n", name, value_tag); - break; - } - - if (value) { - g_string_append_printf (browse_options, "%s=%s ", name, value); - g_free (value); - } - - g_free (name); - } - - attr = ippNextAttribute(response); - } - - if (type != -1 && state != -1 && uri && location && info && make_model) { - gchar *browse_options_str = g_string_free (browse_options, FALSE); - browse_data_t *data; - browse_options = NULL; - g_strchomp (browse_options_str); - data = new_browse_data (type, state, uri, location, - info, make_model, browse_options_str); - browse_data = g_list_insert (browse_data, data, 0); - g_free (browse_options_str); - } - - if (make_model) - g_free (make_model); - - if (info) - g_free (info); - - if (location) - g_free (location); - - if (browse_options) - g_string_free (browse_options, TRUE); - - if (!attr) - break; - } - - fail: - if (response) - ippDelete(response); -} - -static void -update_local_printers (void) -{ - gboolean get_printers = FALSE; - http_t *conn; - - if (inhibit_local_printers_update) - return; - - conn = http_connect_local (); - if (conn && - (!local_printers_context || local_printers_context->can_subscribe)) { - if (!local_printers_context || - local_printers_context->subscription_id == -1) { - /* No subscription yet. First, create the subscription. */ - local_printers_create_subscription (conn); - get_printers = TRUE; - } else - /* We already have a subscription, so use it. */ - - /* Note: for the moment, browse_poll_get_notifications() just - * tells us whether we should re-fetch the printer list, so it - * is safe to use here. */ - get_printers = browse_poll_get_notifications (local_printers_context, - conn); - } else - get_printers = TRUE; - - if (get_printers) { - get_local_printers (); - - if (BrowseLocalProtocols & BROWSE_CUPS) - prepare_browse_data (); - } -} - -int -check_jobs () { - int num_jobs = 0; - cups_job_t *jobs = NULL; - remote_printer_t *p; - http_t *conn = NULL; - - conn = http_connect_local (); - if (conn == NULL) { - debug_printf("Cannot connect to local CUPS to check whether there are still jobs.\n"); - return 0; - } - - if (cupsArrayCount(remote_printers) > 0) - for (p = (remote_printer_t *)cupsArrayFirst(remote_printers); - p; - p = (remote_printer_t *)cupsArrayNext(remote_printers)) - if (!p->slave_of) { - num_jobs = cupsGetJobs2(conn, &jobs, p->queue_name, 0, - CUPS_WHICHJOBS_ACTIVE); - if (num_jobs > 0) { - debug_printf("Queue %s still has jobs!\n", p->queue_name); - cupsFreeJobs(num_jobs, jobs); - return 1; - } - } - - debug_printf("All our remote printers are without jobs.\n"); - return 0; -} - -gboolean -autoshutdown_execute (gpointer data) -{ - debug_printf("autoshutdown_execute() in THREAD %ld\n", pthread_self()); - /* Are we still in auto shutdown mode and are we still without queues or - jobs*/ - if (autoshutdown && - (cupsArrayCount(remote_printers) == 0 || - (autoshutdown_on == NO_JOBS && check_jobs() == 0))) { - debug_printf("Automatic shutdown as there are no print queues maintained by us or no jobs on them for %d sec.\n", - autoshutdown_timeout); - g_main_loop_quit(gmainloop); - g_main_context_wakeup(NULL); - } - - /* Stop this timeout handler, we needed it only once */ - return FALSE; -} - int color_space_score(const char *color_space) { @@ -3890,711 +3508,99 @@ color_space_score(const char *color_spac return score; } - -#ifdef HAVE_LDAP_REBIND_PROC -# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -/* - * 'ldap_rebind_proc()' - Callback function for LDAP rebind - */ - -static int /* O - Result code */ -ldap_rebind_proc(LDAP *RebindLDAPHandle, /* I - LDAP handle */ - LDAP_CONST char *refsp, /* I - ??? */ - ber_tag_t request, /* I - ??? */ - ber_int_t msgid, /* I - ??? */ - void *params) /* I - ??? */ -{ - int rc; /* Result code */ -# if LDAP_API_VERSION > 3000 - struct berval bval; /* Bind value */ -# endif /* LDAP_API_VERSION > 3000 */ - (void)request; - (void)msgid; - (void)params; - - /* - * Bind to new LDAP server... - */ - - debug_printf("ldap_rebind_proc: Rebind to %s\n", refsp); - -# if LDAP_API_VERSION > 3000 - bval.bv_val = BrowseLDAPPassword; - bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword); - - rc = ldap_sasl_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, LDAP_SASL_SIMPLE, - &bval, NULL, NULL, NULL); -# else - rc = ldap_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, BrowseLDAPPassword, - LDAP_AUTH_SIMPLE); -# endif /* LDAP_API_VERSION > 3000 */ - - return (rc); -} - - -# else /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */ -/* - * 'ldap_rebind_proc()' - Callback function for LDAP rebind - */ - -static int /* O - Result code */ -ldap_rebind_proc(LDAP *RebindLDAPHandle, /* I - LDAP handle */ - char **dnp, /* I - ??? */ - char **passwdp, /* I - ??? */ - int *authmethodp, /* I - ??? */ - int freeit, /* I - ??? */ - void *arg) /* I - ??? */ -{ - switch (freeit) { - case 1: - /* - * Free current values... - */ - - debug_printf("ldap_rebind_proc: Free values...\n"); - - if (dnp && *dnp) - free(*dnp); - - if (passwdp && *passwdp) - free(*passwdp); - break; - - case 0: - /* - * Return credentials for LDAP referal... - */ - - debug_printf("ldap_rebind_proc: Return necessary values...\n"); - - *dnp = strdup(BrowseLDAPBindDN); - *passwdp = strdup(BrowseLDAPPassword); - *authmethodp = LDAP_AUTH_SIMPLE; - break; - - default: - /* - * Should never happen... - */ - - debug_printf("LDAP rebind has been called with wrong freeit value!\n"); - break; - } - - return (LDAP_SUCCESS); -} -# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */ -#endif /* HAVE_LDAP_REBIND_PROC */ - - -#ifdef HAVE_LDAP -/* - * 'ldap_connect()' - Start new LDAP connection - */ - -static LDAP * /* O - LDAP handle */ -ldap_connect(void) -{ - int rc; /* LDAP API status */ - int version = 3; /* LDAP version */ - struct berval bv = {0, ""}; /* SASL bind value */ - LDAP *TempBrowseLDAPHandle=NULL; - /* Temporary LDAP Handle */ -# if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) - int ldap_ssl = 0; /* LDAP SSL indicator */ - int ssl_err = 0; /* LDAP SSL error value */ -# endif /* defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) */ - - -# ifdef HAVE_OPENLDAP -# ifdef HAVE_LDAP_SSL - /* - * Set the certificate file to use for encrypted LDAP sessions... - */ - - if (BrowseLDAPCACertFile) { - debug_printf("ldap_connect: Setting CA certificate file \"%s\"\n", - BrowseLDAPCACertFile); - - if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, - (void *)BrowseLDAPCACertFile)) != LDAP_SUCCESS) - debug_printf("Unable to set CA certificate file for LDAP " - "connections: %d - %s\n", rc, ldap_err2string(rc)); - } -# endif /* HAVE_LDAP_SSL */ - - /* - * Initialize OPENLDAP connection... - * LDAP stuff currently only supports ldapi EXTERNAL SASL binds... - */ - - if (!BrowseLDAPServer || !strcasecmp(BrowseLDAPServer, "localhost")) - rc = ldap_initialize(&TempBrowseLDAPHandle, "ldapi:///"); - else - rc = ldap_initialize(&TempBrowseLDAPHandle, BrowseLDAPServer); - -# else /* HAVE_OPENLDAP */ - - int ldap_port = 0; /* LDAP port */ - char ldap_protocol[11], /* LDAP protocol */ - ldap_host[255]; /* LDAP host */ - - /* - * Split LDAP URI into its components... - */ - - if (!BrowseLDAPServer) { - debug_printf("BrowseLDAPServer not configured!\n"); - debug_printf("Disabling LDAP browsing!\n"); - /*BrowseLocalProtocols &= ~BROWSE_LDAP;*/ - BrowseRemoteProtocols &= ~BROWSE_LDAP; - return (NULL); - } - - sscanf(BrowseLDAPServer, "%10[^:]://%254[^:/]:%d", ldap_protocol, ldap_host, - &ldap_port); - - if (!strcmp(ldap_protocol, "ldap")) - ldap_ssl = 0; - else if (!strcmp(ldap_protocol, "ldaps")) - ldap_ssl = 1; - else { - debug_printf("Unrecognized LDAP protocol (%s)!\n", - ldap_protocol); - debug_printf("Disabling LDAP browsing!\n"); - /*BrowseLocalProtocols &= ~BROWSE_LDAP;*/ - BrowseRemoteProtocols &= ~BROWSE_LDAP; - return (NULL); - } - - if (ldap_port == 0) { - if (ldap_ssl) - ldap_port = LDAPS_PORT; - else - ldap_port = LDAP_PORT; - } - - debug_printf("ldap_connect: PROT:%s HOST:%s PORT:%d\n", - ldap_protocol, ldap_host, ldap_port); - - /* - * Initialize LDAP connection... - */ - - if (!ldap_ssl) { - if ((TempBrowseLDAPHandle = ldap_init(ldap_host, ldap_port)) == NULL) - rc = LDAP_OPERATIONS_ERROR; - else - rc = LDAP_SUCCESS; - -# ifdef HAVE_LDAP_SSL - } else { - /* - * Initialize SSL LDAP connection... - */ - - if (BrowseLDAPCACertFile) { - rc = ldapssl_client_init(BrowseLDAPCACertFile, (void *)NULL); - if (rc != LDAP_SUCCESS) { - debug_printf("Failed to initialize LDAP SSL client!\n"); - rc = LDAP_OPERATIONS_ERROR; - } else { - if ((TempBrowseLDAPHandle = ldapssl_init(ldap_host, ldap_port, - 1)) == NULL) - rc = LDAP_OPERATIONS_ERROR; - else - rc = LDAP_SUCCESS; - } - } else { - debug_printf("LDAP SSL certificate file/database not configured!\n"); - rc = LDAP_OPERATIONS_ERROR; - } - -# else /* HAVE_LDAP_SSL */ - - /* - * Return error, because client libraries doesn't support SSL - */ - - debug_printf("LDAP client libraries do not support SSL\n"); - rc = LDAP_OPERATIONS_ERROR; - -# endif /* HAVE_LDAP_SSL */ - } -# endif /* HAVE_OPENLDAP */ - - /* - * Check return code from LDAP initialize... - */ - - if (rc != LDAP_SUCCESS) { - debug_printf("Unable to initialize LDAP!\n"); - - if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR) - debug_printf("Temporarily disabling LDAP browsing...\n"); - else { - debug_printf("Disabling LDAP browsing!\n"); - - /*BrowseLocalProtocols &= ~BROWSE_LDAP;*/ - BrowseRemoteProtocols &= ~BROWSE_LDAP; - } - - ldap_disconnect(TempBrowseLDAPHandle); - - return (NULL); - } - - /* - * Upgrade LDAP version... - */ - - if (ldap_set_option(TempBrowseLDAPHandle, LDAP_OPT_PROTOCOL_VERSION, - (const void *)&version) != LDAP_SUCCESS) { - debug_printf("Unable to set LDAP protocol version %d!\n", - version); - debug_printf("Disabling LDAP browsing!\n"); - - /*BrowseLocalProtocols &= ~BROWSE_LDAP;*/ - BrowseRemoteProtocols &= ~BROWSE_LDAP; - ldap_disconnect(TempBrowseLDAPHandle); - - return (NULL); - } - - /* - * Register LDAP rebind procedure... - */ - -# ifdef HAVE_LDAP_REBIND_PROC -# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) - - rc = ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc, - (void *)NULL); - if (rc != LDAP_SUCCESS) - debug_printf("Setting LDAP rebind function failed with status %d: %s\n", - rc, ldap_err2string(rc)); - -# else - - ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc, (void *)NULL); - -# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */ -# endif /* HAVE_LDAP_REBIND_PROC */ - - /* - * Start LDAP bind... - */ - -# if LDAP_API_VERSION > 3000 - struct berval bval; - bval.bv_val = BrowseLDAPPassword; - bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword); - - if (!BrowseLDAPServer || !strcasecmp(BrowseLDAPServer, "localhost")) - rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, NULL, "EXTERNAL", &bv, NULL, - NULL, NULL); - else - rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN, - LDAP_SASL_SIMPLE, &bval, NULL, NULL, NULL); - -# else - rc = ldap_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN, - BrowseLDAPPassword, LDAP_AUTH_SIMPLE); -# endif /* LDAP_API_VERSION > 3000 */ - - if (rc != LDAP_SUCCESS) { - debug_printf("LDAP bind failed with error %d: %s\n", - rc, ldap_err2string(rc)); - -# if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) - if (ldap_ssl && (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)) { - ssl_err = PORT_GetError(); - if (ssl_err != 0) - debug_printf("LDAP SSL error %d: %s\n", ssl_err, - ldapssl_err2string(ssl_err)); - } -# endif /* defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) */ - - ldap_disconnect(TempBrowseLDAPHandle); - - return (NULL); - } - - debug_printf("LDAP connection established\n"); - - return (TempBrowseLDAPHandle); -} - - -/* - * 'ldap_reconnect()' - Reconnect to LDAP Server - */ - -static LDAP * /* O - New LDAP handle */ -ldap_reconnect(void) -{ - LDAP *TempBrowseLDAPHandle = NULL; /* Temp Handle to LDAP server */ - - /* - * Get a new LDAP Handle and replace the global Handle - * if the new connection was successful. - */ - - debug_printf("Try LDAP reconnect...\n"); - - TempBrowseLDAPHandle = ldap_connect(); - - if (TempBrowseLDAPHandle != NULL) { - if (BrowseLDAPHandle != NULL) - ldap_disconnect(BrowseLDAPHandle); - - BrowseLDAPHandle = TempBrowseLDAPHandle; - } - - return (BrowseLDAPHandle); -} - - -/* - * 'ldap_disconnect()' - Disconnect from LDAP Server - */ - static void -ldap_disconnect(LDAP *ld) /* I - LDAP handle */ -{ - int rc; /* Return code */ - - /* - * Close LDAP handle... - */ - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - rc = ldap_unbind_ext_s(ld, NULL, NULL); -# else - rc = ldap_unbind_s(ld); -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - - if (rc != LDAP_SUCCESS) - debug_printf("Unbind from LDAP server failed with status %d: %s\n", - rc, ldap_err2string(rc)); -} - -/* - * 'cupsdUpdateLDAPBrowse()' - Scan for new printers via LDAP... - */ - -void -cupsdUpdateLDAPBrowse(void) +update_local_printers (void) { - char uri[HTTP_MAX_URI], /* Printer URI */ - host[HTTP_MAX_URI], /* Hostname */ - resource[HTTP_MAX_URI], /* Resource path */ - local_resource[HTTP_MAX_URI], /* Resource path */ - service_name[2048], - location[1024], /* Printer location */ - info[1024], /* Printer information */ - make_model[1024], /* Printer make and model */ - type_num[30], /* Printer type number */ - scheme[32], /* URI's scheme */ - username[64]; /* URI's username */ - int port; /* URI's port number */ - char *c; - int hl; - int rc; /* LDAP status */ - int limit; /* Size limit */ - LDAPMessage *res, /* LDAP search results */ - *e; /* Current entry from search */ - - debug_printf("UpdateLDAPBrowse\n"); - - /* - * Reconnect if LDAP Handle is invalid... - */ - - if (! BrowseLDAPHandle) { - ldap_reconnect(); - return; - } - - /* - * Search for cups printers in LDAP directory... - */ - - rc = ldap_search_rec(BrowseLDAPHandle, BrowseLDAPDN, LDAP_SCOPE_SUBTREE, - BrowseLDAPFilter, (char **)ldap_attrs, 0, &res); - - /* - * If ldap search was successfull then exit function - * and temporary disable LDAP updates... - */ - - if (rc != LDAP_SUCCESS) { - if (BrowseLDAPUpdate && ((rc == LDAP_SERVER_DOWN) || - (rc == LDAP_CONNECT_ERROR))) { - BrowseLDAPUpdate = FALSE; - debug_printf("LDAP update temporary disabled\n"); - } - return; - } - - /* - * If LDAP updates were disabled, we will reenable them... - */ - - if (!BrowseLDAPUpdate) { - BrowseLDAPUpdate = TRUE; - debug_printf("LDAP update enabled\n"); - } - - /* - * Count LDAP entries and return if no entry exist... - */ + gboolean get_printers = FALSE; + http_t *conn; - limit = ldap_count_entries(BrowseLDAPHandle, res); - debug_printf("LDAP search returned %d entries\n", limit); - if (limit < 1) { - ldap_freeres(res); + if (inhibit_local_printers_update) return; - } - - /* - * Loop through the available printers... - */ - - for (e = ldap_first_entry(BrowseLDAPHandle, res); - e; - e = ldap_next_entry(BrowseLDAPHandle, e)) { - /* - * Get the required values from this entry... - */ - - if (ldap_getval_firststring(BrowseLDAPHandle, e, - "printerDescription", info, sizeof(info)) == -1) - continue; - - if (ldap_getval_firststring(BrowseLDAPHandle, e, - "printerLocation", location, - sizeof(location)) == -1) - continue; - - if (ldap_getval_firststring(BrowseLDAPHandle, e, - "printerMakeAndModel", make_model, - sizeof(make_model)) == -1) - continue; - if (ldap_getval_firststring(BrowseLDAPHandle, e, - "printerType", type_num, - sizeof(type_num)) == -1) - continue; - - if (ldap_getval_firststring(BrowseLDAPHandle, e, - "printerURI", uri, sizeof(uri)) == -1) - continue; - - /* - * Process the entry... - */ - - memset(scheme, 0, sizeof(scheme)); - memset(username, 0, sizeof(username)); - memset(host, 0, sizeof(host)); - memset(resource, 0, sizeof(resource)); - memset(local_resource, 0, sizeof(local_resource)); - - httpSeparateURI (HTTP_URI_CODING_ALL, uri, - scheme, sizeof(scheme) - 1, - username, sizeof(username) - 1, - host, sizeof(host) - 1, - &port, - resource, sizeof(resource)- 1); - - if (strncasecmp (resource, "/printers/", 10) && - strncasecmp (resource, "/classes/", 9)) { - debug_printf("don't understand URI: %s\n", uri); - return; - } - - strncpy (local_resource, resource + 1, sizeof (local_resource) - 1); - local_resource[sizeof (local_resource) - 1] = '\0'; - c = strchr (local_resource, '?'); - if (c) - *c = '\0'; - - /* Build the DNS-SD service name which CUPS would give to this printer - when DNS-SD-broadcasting it */ - snprintf(service_name, sizeof (service_name), "%s @ %s", - (strlen(info) > 0 ? info : strchr(local_resource, '/') + 1), host); - /* Cut off trailing ".local" of host name */ - hl = strlen(service_name); - if (hl > 6 && !strcasecmp(service_name + hl - 6, ".local")) - service_name[hl - 6] = '\0'; - if (hl > 7 && !strcasecmp(service_name + hl - 7, ".local.")) - service_name[hl - 7] = '\0'; - /* DNS-SD service name has max. 63 characters */ - service_name[63] = '\0'; - - debug_printf("LDAP: Remote host: %s; Port: %d; Remote queue name: %s; Service Name: %s\n", - host, port, strchr(local_resource, '/') + 1, service_name); - - examine_discovered_printer_record(host, NULL, port, local_resource, - service_name, location, info, "", "", - NULL); - - } + conn = http_connect_local (); + if (conn && + (!local_printers_context || local_printers_context->can_subscribe)) + { + if (!local_printers_context || + local_printers_context->subscription_id == -1) + { + // No subscription yet. First, create the subscription. + local_printers_create_subscription (conn); + get_printers = TRUE; + } + else + { + // We already have a subscription, so use it. + // Note: for the moment, browse_poll_get_notifications() just + // tells us whether we should re-fetch the printer list, so it + // is safe to use here. + get_printers = browse_poll_get_notifications (local_printers_context, + conn); + } + } + else + get_printers = TRUE; - ldap_freeres(res); + if (get_printers) + get_local_printers (); } -/* - * 'ldap_search_rec()' - LDAP Search with reconnect - */ - -static int /* O - Return code */ -ldap_search_rec(LDAP *ld, /* I - LDAP handler */ - char *base, /* I - Base dn */ - int scope, /* I - LDAP search scope */ - char *filter, /* I - Filter string */ - char *attrs[], /* I - Requested attributes */ - int attrsonly, /* I - Return only attributes? */ - LDAPMessage **res) /* I - LDAP handler */ -{ - int rc; /* Return code */ - LDAP *ldr; /* LDAP handler after reconnect */ - - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - rc = ldap_search_ext_s(ld, base, scope, filter, attrs, attrsonly, NULL, NULL, - NULL, LDAP_NO_LIMIT, res); -# else - rc = ldap_search_s(ld, base, scope, filter, attrs, attrsonly, res); -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - /* - * If we have a connection problem try again... - */ +static int +check_jobs () +{ + int num_jobs = 0; + cups_job_t *jobs = NULL; + remote_printer_t *p; + http_t *conn = NULL; - if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR) { - debug_printf("LDAP search failed with status %d: %s\n", - rc, ldap_err2string(rc)); - debug_printf("We try the LDAP search once again after reconnecting to " - "the server\n"); - ldap_freeres(*res); - ldr = ldap_reconnect(); - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - rc = ldap_search_ext_s(ldr, base, scope, filter, attrs, attrsonly, NULL, - NULL, NULL, LDAP_NO_LIMIT, res); -# else - rc = ldap_search_s(ldr, base, scope, filter, attrs, attrsonly, res); -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - } - - if (rc == LDAP_NO_SUCH_OBJECT) - debug_printf("ldap_search_rec: LDAP entry/object not found\n"); - else if (rc != LDAP_SUCCESS) - debug_printf("ldap_search_rec: LDAP search failed with status %d: %s\n", - rc, ldap_err2string(rc)); + conn = http_connect_local (); + if (conn == NULL) + { + debug_printf("Cannot connect to local CUPS to check whether there are still jobs.\n"); + return (0); + } - if (rc != LDAP_SUCCESS) - ldap_freeres(*res); + if (cupsArrayCount(remote_printers) > 0) + for (p = (remote_printer_t *)cupsArrayFirst(remote_printers); + p; + p = (remote_printer_t *)cupsArrayNext(remote_printers)) + if (!p->slave_of) + { + num_jobs = cupsGetJobs2(conn, &jobs, p->queue_name, 0, + CUPS_WHICHJOBS_ACTIVE); + if (num_jobs > 0) + { + debug_printf("Queue %s still has jobs!\n", p->queue_name); + cupsFreeJobs(num_jobs, jobs); + return (1); + } + } - return (rc); + debug_printf("All our remote printers are without jobs.\n"); + return (0); } -/* - * 'ldap_freeres()' - Free LDAPMessage - */ - -static void -ldap_freeres(LDAPMessage *entry) /* I - LDAP handler */ +static gboolean +autoshutdown_execute (gpointer data) { - int rc; /* Return value */ - - rc = ldap_msgfree(entry); - if (rc == -1) - debug_printf("Can't free LDAPMessage!\n"); - else if (rc == 0) - debug_printf("Freeing LDAPMessage was unnecessary\n"); -} - - -/* - * 'ldap_getval_char()' - Get first LDAP value and convert to string - */ - -static int /* O - Return code */ -ldap_getval_firststring(LDAP *ld, /* I - LDAP handler */ - LDAPMessage *entry, /* I - LDAP message or search - result */ - char *attr, /* I - the wanted attribute */ - char *retval, /* O - String to return */ - unsigned long maxsize) /* I - Max string size */ -{ - char *dn; /* LDAP DN */ - int rc = 0; /* Return code */ -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - struct berval **bval; /* LDAP value array */ - unsigned long size; /* String size */ - - - /* - * Get value from LDAPMessage... - */ - - if ((bval = ldap_get_values_len(ld, entry, attr)) == NULL) { - rc = -1; - dn = ldap_get_dn(ld, entry); - debug_printf("Failed to get LDAP value %s for %s!\n", - attr, dn); - ldap_memfree(dn); - } else { - /* - * Check size and copy value into our string... - */ - - size = maxsize; - if (size < (bval[0]->bv_len + 1)) { - rc = -1; - dn = ldap_get_dn(ld, entry); - debug_printf("Attribute %s is too big! (dn: %s)\n", - attr, dn); - ldap_memfree(dn); - } else - size = bval[0]->bv_len + 1; - - strncpy(retval, bval[0]->bv_val, size); - if (size > 0) - retval[size - 1] = '\0'; - ldap_value_free_len(bval); - } -# else - char **value; /* LDAP value */ - - /* - * Get value from LDAPMessage... - */ - - if ((value = (char **)ldap_get_values(ld, entry, attr)) == NULL) { - rc = -1; - dn = ldap_get_dn(ld, entry); - debug_printf("Failed to get LDAP value %s for %s!\n", - attr, dn); - ldap_memfree(dn); - } else { - strncpy(retval, *value, maxsize); - if (maxsize > 0) - retval[maxsize - 1] = '\0'; - ldap_value_free(value); - } -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - - return (rc); + debug_printf("autoshutdown_execute() in THREAD %ld\n", pthread_self()); + // Are we still in auto shutdown mode and are we still without queues or + // jobs + if (autoshutdown && + (cupsArrayCount(remote_printers) == 0 || + (autoshutdown_on == NO_JOBS && check_jobs() == 0))) + { + debug_printf("Automatic shutdown as there are no print queues maintained by us or no jobs on them for %d sec.\n", + autoshutdown_timeout); + g_main_loop_quit(gmainloop); + g_main_context_wakeup(NULL); + } + // Stop this timeout handler, we needed it only once + return (FALSE); } -#endif /* HAVE_LDAP */ - static int create_subscription () @@ -9774,7 +8780,7 @@ void avahi_init() { #endif /* HAVE_AVAHI */ /* - * A CUPS printer has been discovered via CUPS Browsing + * A CUPS printer has been discovered via BrowsePoll * or with BrowsePoll */ void @@ -9843,7 +8849,7 @@ found_cups_printer (const char *remote_h /* DNS-SD service name has max. 63 characters */ service_name[63] = '\0'; - debug_printf("CUPS browsing: Remote host: %s; Port: %d; Remote queue name: %s; Service Name: %s\n", + debug_printf("BrowsePoll: Remote host: %s; Port: %d; Remote queue name: %s; Service Name: %s\n", host, port, strchr(local_resource, '/') + 1, service_name); printer = examine_discovered_printer_record(host, NULL, port, local_resource, @@ -9863,195 +8869,6 @@ found_cups_printer (const char *remote_h } } -gboolean -process_browse_data (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - char packet[2048]; - http_addr_t srcaddr; - socklen_t srclen; - ssize_t got; - unsigned int type; - unsigned int state; - char remote_host[256]; - char uri[1024]; - char location[1024]; - char info[1024]; - char *c = NULL, *end = NULL; - - debug_printf("process_browse_data() in THREAD %ld\n", pthread_self()); - - memset(packet, 0, sizeof(packet)); - memset(remote_host, 0, sizeof(remote_host)); - memset(uri, 0, sizeof(uri)); - memset(info, 0, sizeof(info)); - - srclen = sizeof (srcaddr); - got = recvfrom (browsesocket, packet, sizeof (packet) - 1, 0, - &srcaddr.addr, &srclen); - if (got == -1) { - debug_printf ("cupsd-browsed: error receiving browse packet: %s\n", - strerror (errno)); - /* Remove this I/O source */ - return FALSE; - } - - packet[got] = '\0'; - httpAddrString (&srcaddr, remote_host, sizeof (remote_host) - 1); - - /* Check this packet is allowed */ - if (!allowed ((struct sockaddr *) &srcaddr)) { - debug_printf("browse packet from %s disallowed\n", - remote_host); - return TRUE; - } - - debug_printf("browse packet received from %s\n", - remote_host); - - if (sscanf (packet, "%x%x%1023s", &type, &state, uri) < 3) { - debug_printf("incorrect browse packet format\n"); - return TRUE; - } - - info[0] = '\0'; - - /* do not read OOB */ - end = packet + sizeof(packet); - c = strchr (packet, '\"'); - if (c >= end) - return TRUE; - - if (c) { - /* Extract location field */ - { - int i; - c++; - for (i = 0; - i < sizeof (location) - 1 && *c != '\"' && c < end; - i++, c++) - location[i] = *c; - location[i] = '\0'; - debug_printf("process_browse_data: location: |%s|\n", location); /* !! */ - } - for (; c < end && *c != '\"'; c++) - ; - - if (c >= end) - return TRUE; - - if (*c == '\"') { - for (c++; c < end && isspace(*c); c++) - ; - } - - if (c >= end) - return TRUE; - - /* Is there an info field? */ - if (*c == '\"') { - int i; - c++; - for (i = 0; - i < sizeof (info) - 1 && *c != '\"' && c < end; - i++, c++) - info[i] = *c; - info[i] = '\0'; - debug_printf("process_browse_data: info: |%s|\n", info); /* !! */ - } - } - if (c >= end) - return TRUE; - - if (!(type & CUPS_PRINTER_DELETE)) - found_cups_printer (remote_host, uri, location, info); - - if (in_shutdown == 0) - recheck_timer (); - - /* Don't remove this I/O source */ - return TRUE; -} - -static void -broadcast_browse_packets (gpointer data, gpointer user_data) -{ - browse_data_t *bdata = data; - netif_t *browse; - char packet[2048]; - char uri[HTTP_MAX_URI]; - char scheme[32]; - char username[64]; - char host[HTTP_MAX_HOST]; - int port; - char resource[HTTP_MAX_URI]; - - debug_printf("broadcast_browse_packets() in THREAD %ld\n", pthread_self()); - - for (browse = (netif_t *)cupsArrayFirst (netifs); - browse != NULL; - browse = (netif_t *)cupsArrayNext (netifs)) { - /* Replace 'localhost' with our IP address on this interface */ - httpSeparateURI(HTTP_URI_CODING_ALL, bdata->uri, - scheme, sizeof(scheme), - username, sizeof(username), - host, sizeof(host), - &port, - resource, sizeof(resource)); - httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof (uri), - scheme, username, browse->address, port, resource); - - if (snprintf (packet, sizeof (packet), - "%x " /* type */ - "%x " /* state */ - "%s " /* uri */ - "\"%s\" " /* location */ - "\"%s\" " /* info */ - "\"%s\" " /* make-and-model */ - "lease-duration=%d" /* BrowseTimeout */ - "%s%s" /* other browse options */ - "\n", - bdata->type, - bdata->state, - uri, - bdata->location, - bdata->info, - bdata->make_model, - BrowseTimeout, - bdata->browse_options ? " " : "", - bdata->browse_options ? bdata->browse_options : "") - >= sizeof (packet)) { - debug_printf ("oversize packet not sent\n"); - continue; - } - - debug_printf("packet to send:\n%s", packet); - - int err = sendto (browsesocket, packet, - strlen (packet), 0, - &browse->broadcast.addr, - httpAddrLength (&browse->broadcast)); - if (err == -1) - debug_printf("cupsd-browsed: sendto returned %d: %s\n", - err, strerror (errno)); - } -} - -gboolean -send_browse_data (gpointer data) -{ - debug_printf("send_browse_data() in THREAD %ld\n", pthread_self()); - update_netifs (NULL); - res_init (); - update_local_printers (); - g_list_foreach (browse_data, broadcast_browse_packets, NULL); - g_timeout_add_seconds (BrowseInterval, send_browse_data, NULL); - - /* Stop this timeout handler, we called a new one */ - return FALSE; -} - static browsepoll_printer_t * new_browsepoll_printer (const char *uri_supported, const char *location, @@ -10438,72 +9255,6 @@ browse_poll (gpointer data) return FALSE; } -#ifdef HAVE_LDAP -gboolean -browse_ldap_poll (gpointer data) -{ - char *tmpFilter; /* Query filter */ - int filterLen; - - debug_printf("browse_ldap_poll() in THREAD %ld\n", pthread_self()); - - /* do real stuff here */ - if (!BrowseLDAPDN) { - debug_printf("Need to set BrowseLDAPDN to use LDAP browsing!\n"); - BrowseLocalProtocols &= ~BROWSE_LDAP; - BrowseRemoteProtocols &= ~BROWSE_LDAP; - - return FALSE; - } else { - if (!BrowseLDAPInitialised) { - BrowseLDAPInitialised = TRUE; - /* - * Query filter string - */ - if (BrowseLDAPFilter) - filterLen = snprintf(NULL, 0, "(&%s%s)", LDAP_BROWSE_FILTER, - BrowseLDAPFilter); - else - filterLen = strlen(LDAP_BROWSE_FILTER); - - tmpFilter = (char *)malloc(filterLen + 1); - if (!tmpFilter) { - debug_printf("Could not allocate memory for LDAP browse query filter!\n"); - BrowseLocalProtocols &= ~BROWSE_LDAP; - BrowseRemoteProtocols &= ~BROWSE_LDAP; - return FALSE; - } - - if (BrowseLDAPFilter) { - snprintf(tmpFilter, filterLen + 1, "(&%s%s)", LDAP_BROWSE_FILTER, - BrowseLDAPFilter); - free(BrowseLDAPFilter); - BrowseLDAPFilter = NULL; - } else - strcpy(tmpFilter, LDAP_BROWSE_FILTER); - - BrowseLDAPFilter = tmpFilter; - - /* - * Open LDAP handle... - */ - - BrowseLDAPHandle = ldap_connect(); - } - - cupsdUpdateLDAPBrowse(); - if (in_shutdown == 0) - recheck_timer(); - } - - /* Call a new timeout handler so that we run again */ - g_timeout_add_seconds (BrowseInterval, browse_ldap_poll, data); - - /* Stop this timeout handler, we called a new one */ - return FALSE; -} -#endif /* HAVE_LDAP */ - static void sigterm_handler(int sig) { (void)sig; /* remove compiler warnings... */ @@ -10708,10 +9459,6 @@ read_configuration (const char *filename while (p) { if (!strcasecmp(p, "dnssd")) protocols |= BROWSE_DNSSD; - else if (!strcasecmp(p, "cups")) - protocols |= BROWSE_CUPS; - else if (!strcasecmp(p, "ldap")) - protocols |= BROWSE_LDAP; else if (strcasecmp(p, "none")) debug_printf("Unknown protocol '%s'\n", p); @@ -11163,31 +9910,6 @@ read_configuration (const char *filename debug_printf("Invalid auto shutdown inactivity type value: %s\n", value); } -#ifdef HAVE_LDAP - else if (!strcasecmp(line, "BrowseLDAPBindDN") && value) { - if (value[0] != '\0') - BrowseLDAPBindDN = strdup(value); - } -# ifdef HAVE_LDAP_SSL - else if (!strcasecmp(line, "BrowseLDAPCACertFile") && value) { - if (value[0] != '\0') - BrowseLDAPCACertFile = strdup(value); - } -# endif /* HAVE_LDAP_SSL */ - else if (!strcasecmp(line, "BrowseLDAPDN") && value) { - if (value[0] != '\0') - BrowseLDAPDN = strdup(value); - } else if (!strcasecmp(line, "BrowseLDAPPassword") && value) { - if (value[0] != '\0') - BrowseLDAPPassword = strdup(value); - } else if (!strcasecmp(line, "BrowseLDAPServer") && value) { - if (value[0] != '\0') - BrowseLDAPServer = strdup(value); - } else if (!strcasecmp(line, "BrowseLDAPFilter") && value) { - if (value[0] != '\0') - BrowseLDAPFilter = strdup(value); - } -#endif /* HAVE_LDAP */ } if (browse_line_found == 0) { @@ -11263,11 +9985,7 @@ find_previous_queue (gpointer key, /* Mark as unconfirmed, if no Avahi report of this queue appears in a certain time frame, we will remove the queue */ p->status = STATUS_UNCONFIRMED; - - if (BrowseRemoteProtocols & BROWSE_CUPS) - p->timeout = time(NULL) + BrowseTimeout; - else - p->timeout = time(NULL) + TIMEOUT_CONFIRM; + p->timeout = time(NULL) + TIMEOUT_CONFIRM; p->slave_of = NULL; debug_printf("Found CUPS queue %s (URI: %s) from previous session.\n", @@ -11518,11 +10236,6 @@ int main(int argc, char*argv[]) { BrowseLocalProtocols &= ~BROWSE_DNSSD; } - if (BrowseLocalProtocols & BROWSE_LDAP) { - debug_printf("Local support for LDAP not implemented\n"); - BrowseLocalProtocols &= ~BROWSE_LDAP; - } - #ifndef HAVE_AVAHI if (BrowseRemoteProtocols & BROWSE_DNSSD) { debug_printf("Remote support for DNSSD not supported\n"); @@ -11530,13 +10243,6 @@ int main(int argc, char*argv[]) { } #endif /* HAVE_AVAHI */ -#ifndef HAVE_LDAP - if (BrowseRemoteProtocols & BROWSE_LDAP) { - debug_printf("Remote support for LDAP not supported\n"); - BrowseRemoteProtocols &= ~BROWSE_LDAP; - } -#endif /* HAVE_LDAP */ - /* Wait for CUPS daemon to start */ while ((http = http_connect_local ()) == NULL) sleep(1); @@ -11621,41 +10327,6 @@ int main(int argc, char*argv[]) { NULL); } } - - if (BrowseLocalProtocols & BROWSE_CUPS || - BrowseRemoteProtocols & BROWSE_CUPS) { - /* Set up our CUPS Browsing socket */ - browsesocket = socket (AF_INET, SOCK_DGRAM, 0); - if (browsesocket == -1) { - debug_printf("failed to create CUPS Browsing socket: %s\n", - strerror (errno)); - } else { - struct sockaddr_in addr; - memset (&addr, 0, sizeof (addr)); - addr.sin_addr.s_addr = htonl (INADDR_ANY); - addr.sin_family = AF_INET; - addr.sin_port = htons (BrowsePort); - if (bind (browsesocket, (struct sockaddr *)&addr, sizeof (addr))) { - debug_printf("failed to bind CUPS Browsing socket: %s\n", - strerror (errno)); - close (browsesocket); - browsesocket = -1; - } else { - int on = 1; - if (setsockopt (browsesocket, SOL_SOCKET, SO_BROADCAST, - &on, sizeof (on))) { - debug_printf("failed to allow broadcast: %s\n", - strerror (errno)); - BrowseLocalProtocols &= ~BROWSE_CUPS; - } - } - } - - if (browsesocket == -1) { - BrowseLocalProtocols &= ~BROWSE_CUPS; - BrowseRemoteProtocols &= ~BROWSE_CUPS; - } - } if (BrowseLocalProtocols == 0 && BrowseRemoteProtocols == 0 && @@ -11689,26 +10360,6 @@ int main(int argc, char*argv[]) { gmainloop = g_main_loop_new (NULL, FALSE); recheck_timer (); - if (BrowseRemoteProtocols & BROWSE_CUPS) { - GIOChannel *browse_channel = g_io_channel_unix_new (browsesocket); - g_io_channel_set_close_on_unref (browse_channel, FALSE); - g_io_add_watch (browse_channel, G_IO_IN, process_browse_data, NULL); - } - - if (BrowseLocalProtocols & BROWSE_CUPS) { - debug_printf ("will send browse data every %ds\n", - BrowseInterval); - g_idle_add (send_browse_data, NULL); - } - -#ifdef HAVE_LDAP - if (BrowseRemoteProtocols & BROWSE_LDAP) { - debug_printf ("will browse poll LDAP every %ds\n", - BrowseInterval); - g_idle_add (browse_ldap_poll, NULL); - } -#endif /* HAVE_LDAP */ - if (BrowsePoll) { size_t index; for (index = 0; @@ -11818,23 +10469,12 @@ fail: avahi_shutdown(); #endif /* HAVE_AVAHI */ -#ifdef HAVE_LDAP - if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_LDAP) && - BrowseLDAPHandle) { - ldap_disconnect(BrowseLDAPHandle); - BrowseLDAPHandle = NULL; - } -#endif /* HAVE_LDAP */ - if (browsesocket != -1) close (browsesocket); g_hash_table_destroy (local_printers); g_hash_table_destroy (cups_supported_remote_printers); - if (BrowseLocalProtocols & BROWSE_CUPS) - g_list_free_full (browse_data, browse_data_free); - /* Close log file if we have one */ if (debug_logfile == 1) stop_debug_logging(); Index: cups-filters-1.25.0/utils/cups-browsed.conf.5 =================================================================== --- cups-filters-1.25.0.orig/utils/cups-browsed.conf.5 +++ cups-filters-1.25.0/utils/cups-browsed.conf.5 @@ -47,7 +47,7 @@ journal or syslog. Only if you run cups- .fam T .fi -Only browse remote printers (via DNS-SD or CUPS browsing) from +Only browse remote printers (via DNS-SD) from selected servers using the "BrowseAllow", "BrowseDeny", and "BrowseOrder" directives .PP @@ -330,8 +330,6 @@ Printers from all servers except "prinse The BrowsePoll directive polls a server for available printers once every 60 seconds. Multiple BrowsePoll directives can be specified to poll multiple servers. The default port to connect to is 631. -BrowsePoll works independently of whether CUPS browsing is activated -in BrowseRemoteProtocols. .PP .nf .fam C @@ -345,12 +343,11 @@ in BrowseRemoteProtocols. The BrowseLocalProtocols directive specifies the protocols to use when advertising local shared printers on the network. The default is "none". Control of advertising of local shared printers using -dnssd is done in /etc/cups/cupsd.conf. +dnssd is done by CUPS and configured in /etc/cups/cupsd.conf. .PP .nf .fam C BrowseLocalProtocols none - BrowseLocalProtocols CUPS .fam T @@ -358,50 +355,26 @@ dnssd is done in /etc/cups/cupsd.conf. The BrowseRemoteProtocols directive specifies the protocols to use when finding remote shared printers on the network. Multiple protocols can be specified by separating them with spaces. -The default is "dnssd cups". +The default is "dnssd". .PP .nf .fam C BrowseRemoteProtocols none - BrowseRemoteProtocols CUPS dnssd - BrowseRemoteProtocols CUPS BrowseRemoteProtocols dnssd - BrowseRemoteProtocols ldap + .fam T .fi The BrowseProtocols directive specifies the protocols to use when finding remote shared printers on the network and advertising local -shared printers. "dnssd" and "ldap" are ignored for BrowseLocalProtocols. -Multiple protocols can be specified by separating them with spaces. The -default is "none" for BrowseLocalProtocols and "dnssd cups" for -BrowseRemoteProtocols. +shared printers. +Multiple protocols can be specified by separating them with spaces. .PP .nf .fam C BrowseProtocols none - BrowseProtocols CUPS dnssd - BrowseProtocols CUPS BrowseProtocols dnssd - BrowseProtocols ldap -.fam T -.fi -The configuration for the LDAP browsing mode define where the LDAP search -should be performed. If built with an LDAP library that supports TLS, the -path to the server's certificate, or to a certificates store, can be -specified. -The optional filter allows the LDAP search to be more specific, and is used -in addition to the hardcoded filter (objectclass=cupsPrinter). -.PP -.nf -.fam C - BrowseLDAPBindDN cn=cups-browsed,dc=domain,dc=tld - BrowseLDAPCACertFile /path/to/server/certificate.pem - BrowseLDAPDN ou=printers,dc=domain,dc=tld - BrowseLDAPFilter (printerLocation=/Office 1/*) - BrowseLDAPPassword s3cret - BrowseLDAPServer ldaps://ldap.domain.tld .fam T .fi @@ -459,8 +432,6 @@ The BrowseTimeout directive determines t browsing-related operations are allowed to take in seconds. Notably, adding or removing one printer queue is considered as one operation. The timeout applies to each one of those operations. -Especially queues discovered by CUPS broadcasts will be removed after -this timeout if no further broadcast from the server happens. .PP .nf .fam C Index: cups-filters-1.25.0/utils/cups-browsed.conf.in =================================================================== --- cups-filters-1.25.0.orig/utils/cups-browsed.conf.in +++ cups-filters-1.25.0/utils/cups-browsed.conf.in @@ -36,27 +36,27 @@ # Which protocols will we use to discover printers on the network? -# Can use DNSSD and/or CUPS and/or LDAP, or 'none' for neither. +# Can use DNSSD or 'none'. BrowseRemoteProtocols @BROWSEREMOTEPROTOCOLS@ # Which protocols will we use to broadcast shared local printers to the network? -# Can use DNSSD and/or CUPS, or 'none' for neither. -# Only CUPS is actually supported, as DNSSD is done by CUPS itself (we ignore -# DNSSD in this directive). +# Can use DNSSD or 'none'. +# Broadcasting is currently not supported, as DNSSD is done by CUPS itself +# (we ignore DNSSD in this directive). # BrowseLocalProtocols none # Settings of this directive apply to both BrowseRemoteProtocols and # BrowseLocalProtocols. -# Can use DNSSD and/or CUPS and/or LDAP, or 'none' for neither. +# Can use DNSSD or 'none'. # BrowseProtocols none -# Only browse remote printers (via DNS-SD or CUPS browsing) from +# Only browse remote printers (via DNS-SD) from # selected servers using the "BrowseAllow", "BrowseDeny", and # "BrowseOrder" directives @@ -120,8 +120,6 @@ BrowseRemoteProtocols @BROWSEREMOTEPROTO # Browsing-related operations such as adding or removing printer queues # and broadcasting are each allowed to take up to a given amount of time. # It can be configured, in seconds, with the BrowseTimeout directive. -# Especially queues discovered by CUPS broadcasts will be removed after -# this timeout if no further broadcast from the server happens. # BrowseTimeout 300 @@ -287,17 +285,6 @@ BrowseRemoteProtocols @BROWSEREMOTEPROTO # BrowsePoll cups.example.com:631/version=1.1 -# LDAP browsing configuration -# The default value for all options is an empty string. Example configuration: - -# BrowseLDAPBindDN cn=cups-browsed,dc=domain,dc=tld -# BrowseLDAPCACertFile /path/to/server/certificate.pem -# BrowseLDAPDN ou=printers,dc=domain,dc=tld -# BrowseLDAPFilter (printerLocation=/Office 1/*) -# BrowseLDAPPassword s3cret -# BrowseLDAPServer ldaps://ldap.domain.tld - - # Use DomainSocket to access the local CUPS daemon via another than the # default domain socket. "None" or "Off" lets cups-browsed not use CUPS' # domain socket.
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor