]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/dirsvc.c
Merge changes from CUPS 1.4svn-r8628.
[thirdparty/cups.git] / scheduler / dirsvc.c
index dfa996a86c59e58a4a7eb019b35220252d8ceba7..29ff94743340c685a57883dff6abb66e3ea2771f 100644 (file)
@@ -38,6 +38,7 @@
  *   cupsdUpdateLDAPBrowse()    - Scan for new printers via LDAP...
  *   cupsdUpdateSLPBrowse()     - Get browsing information via SLP.
  *   dequote()                  - Remote quotes from a string.
+ *   dnssdAddAlias()            - Add a DNS-SD alias name.
  *   dnssdBuildTxtRecord()      - Build a TXT record from printer info.
  *   dnssdComparePrinters()     - Compare the registered names of two printers.
  *   dnssdDeregisterPrinter()   - Stop sending broadcast information for a
  */
 
 static char    *dequote(char *d, const char *s, int dlen);
+static char    *get_auth_info_required(cupsd_printer_t *p, char *buffer,
+                                       size_t bufsize);
 #ifdef __APPLE__
 static int     get_hostconfig(const char *name);
 #endif /* __APPLE__ */
@@ -155,6 +158,10 @@ static void        update_smb(int onoff);
 
 
 #ifdef HAVE_DNSSD
+#  ifdef HAVE_COREFOUNDATION
+static void    dnssdAddAlias(const void *key, const void *value,
+                             void *context);
+#  endif /* HAVE_COREFOUNDATION */
 static char    *dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
                                     int for_lpd);
 static int     dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b);
@@ -245,7 +252,8 @@ cupsdDeregisterPrinter(
                  removeit);
 
   if (!Browsing || !p->shared ||
-      (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+      (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+                  CUPS_PRINTER_SCANNER)))
     return;
 
  /*
@@ -675,7 +683,8 @@ cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
                   p->name);
 
   if (!Browsing || !BrowseLocalProtocols ||
-      (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+      (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+                  CUPS_PRINTER_SCANNER)))
     return;
 
 #ifdef HAVE_LIBSLP
@@ -883,7 +892,8 @@ cupsdSendBrowseList(void)
     for (count = 0, p = (cupsd_printer_t *)cupsArrayFirst(Printers);
          count < max_count && p != NULL;
         p = (cupsd_printer_t *)cupsArrayNext(Printers))
-      if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) &&
+      if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+                       CUPS_PRINTER_SCANNER)) &&
           p->shared && p->browse_time < ut)
         count ++;
 
@@ -909,7 +919,8 @@ cupsdSendBrowseList(void)
 
       if (!p)
         break;
-      else if ((p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) ||
+      else if ((p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+                           CUPS_PRINTER_SCANNER)) ||
                !p->shared)
         continue;
       else if (p->browse_time < ut)
@@ -1664,7 +1675,8 @@ cupsdStartBrowsing(void)
   for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
        p;
        p = (cupsd_printer_t *)cupsArrayNext(Printers))
-    if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+    if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+                     CUPS_PRINTER_SCANNER)))
       cupsdRegisterPrinter(p);
 }
 
@@ -1748,7 +1760,7 @@ cupsdStartPolling(void)
     argv[1] = pollp->hostname;
 
     if (cupsdStartProcess(polld, argv, envp, -1, -1, statusfds[1], -1, -1,
-                          0, DefaultProfile, 0, &(pollp->pid)) < 0)
+                          0, DefaultProfile, NULL, &(pollp->pid)) < 0)
     {
       cupsdLogMessage(CUPSD_LOG_ERROR,
                       "cupsdStartPolling: Unable to fork polling daemon - %s",
@@ -1792,7 +1804,8 @@ cupsdStopBrowsing(void)
   for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
        p;
        p = (cupsd_printer_t *)cupsArrayNext(Printers))
-    if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+    if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+                     CUPS_PRINTER_SCANNER)))
       cupsdDeregisterPrinter(p, 1);
 
  /*
@@ -1895,9 +1908,10 @@ cupsdUpdateDNSSDName(void)
   DNSServiceErrorType error;           /* Error from service creation */
   char         webif[1024];            /* Web interface share name */
 #ifdef HAVE_COREFOUNDATION_H
-  CFStringRef  nameRef;                /* Computer name CFString */
+  SCDynamicStoreRef sc;                        /* Context for dynamic store */
+  CFDictionaryRef btmm;                        /* Back-to-My-Mac domains */
+  CFStringRef  nameRef;                /* Host name CFString */
   char         nameBuffer[1024];       /* C-string buffer */
-  CFStringEncoding nameEncoding;       /* Computer name encoding */
 #endif /* HAVE_COREFOUNDATION_H */
 
 
@@ -1906,6 +1920,7 @@ cupsdUpdateDNSSDName(void)
   * enabled...
   */
 
+
   if (!DNSSDPort)
     return;
 
@@ -1914,21 +1929,68 @@ cupsdUpdateDNSSDName(void)
   */
 
 #ifdef HAVE_COREFOUNDATION_H
-  cupsdClearString(&DNSSDName);
+  sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL);
 
-  if ((nameRef = SCDynamicStoreCopyComputerName(NULL,
-                                               &nameEncoding)) != NULL)
+  if (sc)
   {
-    if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
-                          kCFStringEncodingUTF8))
-      cupsdSetString(&DNSSDName, nameBuffer);
+   /*
+    * Get the computer name from the dynamic store...
+    */
 
-    CFRelease(nameRef);
-  }
+    cupsdClearString(&DNSSDName);
 
-#else
-  cupsdSetString(&DNSSDName, ServerName);
+    if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL)
+    {
+      if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
+                            kCFStringEncodingUTF8))
+      {
+        cupsdLogMessage(CUPSD_LOG_DEBUG,
+                       "Dynamic store host name is \"%s\".", nameBuffer);
+       cupsdSetString(&DNSSDName, nameBuffer);
+      }
+
+      CFRelease(nameRef);
+    }
+
+    if (!DNSSDName)
+    {
+     /*
+      * Use the ServerName instead...
+      */
+
+      cupsdLogMessage(CUPSD_LOG_DEBUG,
+                      "Using ServerName \"%s\" as host name.", ServerName);
+      cupsdSetString(&DNSSDName, ServerName);
+    }
+
+   /*
+    * Get any Back-to-My-Mac domains and add them as aliases...
+    */
+
+    cupsdFreeAliases(DNSSDAlias);
+    DNSSDAlias = NULL;
+
+    btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac"));
+    if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID())
+    {
+      cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.",
+                     (int)CFDictionaryGetCount(btmm));
+      CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL);
+    }
+    else if (btmm)
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                     "Bad Back to My Mac data in dynamic store!");
+    else
+      cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add.");
+
+    if (btmm)
+      CFRelease(btmm);
+
+    CFRelease(sc);
+  }
+  else
 #endif /* HAVE_COREFOUNDATION_H */
+  cupsdSetString(&DNSSDName, ServerName);
 
  /*
   * Then (re)register the web interface if enabled...
@@ -2199,6 +2261,41 @@ dequote(char       *d,                   /* I - Destination string */
 
 
 #ifdef HAVE_DNSSD
+#  ifdef HAVE_COREFOUNDATION
+/*
+ * 'dnssdAddAlias()' - Add a DNS-SD alias name.
+ */
+
+static void
+dnssdAddAlias(const void *key,         /* I - Key */
+              const void *value,       /* I - Value (domain) */
+             void       *context)      /* I - Unused */
+{
+  char valueStr[1024],                 /* Domain string */
+       hostname[1024];                 /* Complete hostname */
+
+
+  (void)context;
+
+  if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() &&
+      CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr),
+                         kCFStringEncodingUTF8))
+  {
+    snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDName, valueStr);
+    if (!DNSSDAlias)
+      DNSSDAlias = cupsArrayNew(NULL, NULL);
+
+    cupsdAddAlias(DNSSDAlias, hostname);
+    cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s",
+                   hostname);
+  }
+  else
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "Bad Back to My Mac domain in dynamic store!");
+}
+#  endif /* HAVE_COREFOUNDATION */
+
+
 /*
  * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
  */
@@ -2209,13 +2306,12 @@ dnssdBuildTxtRecord(
     cupsd_printer_t *p,                        /* I - Printer information */
     int             for_lpd)           /* I - 1 = LPD, 0 = IPP */
 {
-  int          i, j;                   /* Looping vars */
+  int          i;                      /* Looping var */
   char         type_str[32],           /* Type to string buffer */
                state_str[32],          /* State to string buffer */
                rp_str[1024],           /* Queue name string buffer */
                air_str[1024],          /* auth-info-required string buffer */
                *keyvalue[32][2];       /* Table of key/value pairs */
-  ipp_attribute_t *air_attr;           /* auth-info-required attribute */
 
 
  /*
@@ -2325,26 +2421,8 @@ dnssdBuildTxtRecord(
   keyvalue[i  ][0] = "pdl";
   keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript";
 
-  if ((air_attr = ippFindAttribute(p->attrs, "auth-info-required",
-                                   IPP_TAG_KEYWORD)) != NULL &&
-      strcmp(air_attr->values[0].string.text, "none"))
+  if (get_auth_info_required(p, air_str, sizeof(air_str)))
   {
-    char       *air = air_str;         /* Pointer into string */
-
-
-    for (j = 0; j < air_attr->num_values; j ++)
-    {
-      if (air >= (air_str + sizeof(air_str) - 2))
-        break;
-
-      if (j)
-        *air++ = ',';
-
-      strlcpy(air, air_attr->values[j].string.text,
-              sizeof(air_str) - (air - air_str));
-      air += strlen(air);
-    }
-
     keyvalue[i  ][0] = "air";
     keyvalue[i++][1] = air_str;
   }
@@ -2545,12 +2623,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
                        *nameptr;       /* Pointer into name */
   int                  ipp_len,        /* IPP TXT record length */
                        printer_len;    /* LPD TXT record length */
-  char                 resource[1024]; /* Resource path for printer */
   const char           *regtype;       /* Registration type */
-  const char           *domain;        /* Registration domain */
-  cupsd_location_t     *location,      /* Printer location */
-                       *policy;        /* Operation policy for Print-Job */
-  unsigned             address[4];     /* INADDR_ANY address */
 
 
   cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
@@ -2596,26 +2669,6 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
     cupsArrayAdd(DNSSDPrinters, p);
   }
 
- /*
-  * If 'Allow printing from the Internet' is enabled (i.e. from any address)
-  * let dnssd decide on the domain, otherwise restrict it to ".local".
-  */
-
-  if (p->type & CUPS_PRINTER_CLASS)
-    snprintf(resource, sizeof(resource), "/classes/%s", p->name);
-  else
-    snprintf(resource, sizeof(resource), "/printers/%s", p->name);
-
-  address[0] = address[1] = address[2] = address[3] = 0;
-  location   = cupsdFindBest(resource, HTTP_POST);
-  policy     = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
-
-  if ((location && !cupsdCheckAccess(address, "", 0, location)) ||
-      (policy && !cupsdCheckAccess(address, "", 0, policy)))
-    domain = "local.";
-  else
-    domain = NULL;
-
  /*
   * Register IPP and (optionally) LPD...
   */
@@ -2666,9 +2719,8 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
                                              "_ipp._tcp,_cups";
 
     cupsdLogMessage(CUPSD_LOG_DEBUG, 
-                   "Registering DNS-SD printer %s with name \"%s\", "
-                   "type \"%s\", and domain \"%s\"", p->name, name, regtype,
-                   domain ? domain : "(null)");
+                   "Registering DNS-SD printer %s with name \"%s\" and "
+                   "type \"%s\"", p->name, name, regtype);
 
    /*
     * Register the queue, dropping characters as needed until we succeed...
@@ -2680,7 +2732,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
     {
       p->ipp_ref = DNSSDRef;
       if ((se = DNSServiceRegister(&p->ipp_ref, kDNSServiceFlagsShareConnection,
-                                   0, name, regtype, domain, NULL,
+                                   0, name, regtype, NULL, NULL,
                                   htons(DNSSDPort), ipp_len, ipp_txt,
                                   dnssdRegisterCallback,
                                   p)) == kDNSServiceErr_BadParam)
@@ -2763,14 +2815,13 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
       */
 
       cupsdLogMessage(CUPSD_LOG_DEBUG, 
-                     "Registering DNS-SD printer %s with name \"%s\", "
-                     "type \"_printer._tcp\", and domain \"%s\"", p->name,
-                     name, domain ? domain : "(null)");
+                     "Registering DNS-SD printer %s with name \"%s\" and "
+                     "type \"_printer._tcp\"", p->name, name);
 
       p->printer_ref = DNSSDRef;
       if ((se = DNSServiceRegister(&p->printer_ref,
                                    kDNSServiceFlagsShareConnection,
-                                  0, name, "_printer._tcp", domain, NULL,
+                                  0, name, "_printer._tcp", NULL, NULL,
                                   htons(515), printer_len, printer_txt,
                                   dnssdRegisterCallback,
                                   p)) == kDNSServiceErr_NoError)
@@ -2859,6 +2910,85 @@ dnssdUpdate(void)
 #endif /* HAVE_DNSSD */
 
 
+/*
+ * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
+ */
+
+static char *                          /* O - String or NULL if none */
+get_auth_info_required(
+    cupsd_printer_t *p,                        /* I - Printer */
+    char            *buffer,           /* I - Value buffer */
+    size_t          bufsize)           /* I - Size of value buffer */
+{
+  cupsd_location_t *auth;              /* Pointer to authentication element */
+  char         resource[1024];         /* Printer/class resource path */
+
+
+ /*
+  * If auth-info-required is set for this printer, return that...
+  */
+
+  if (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none"))
+  {
+    int                i;                      /* Looping var */
+    char       *bufptr;                /* Pointer into buffer */
+
+    for (i = 0, bufptr = buffer; i < p->num_auth_info_required; i ++)
+    {
+      if (bufptr >= (buffer + bufsize - 2))
+       break;
+
+      if (i)
+       *bufptr++ = ',';
+
+      strlcpy(bufptr, p->auth_info_required[i], bufsize - (bufptr - buffer));
+      bufptr += strlen(bufptr);
+    }
+
+    return (buffer);
+  }
+
+ /*
+  * Figure out the authentication data requirements to advertise...
+  */
+
+  if (p->type & CUPS_PRINTER_CLASS)
+    snprintf(resource, sizeof(resource), "/classes/%s", p->name);
+  else
+    snprintf(resource, sizeof(resource), "/printers/%s", p->name);
+
+  if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
+      auth->type == CUPSD_AUTH_NONE)
+    auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
+
+  if (auth)
+  {
+    int        auth_type;                      /* Authentication type */
+
+    if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT)
+      auth_type = DefaultAuthType;
+
+    switch (auth_type)
+    {
+      case CUPSD_AUTH_NONE :
+          return (NULL);
+
+      case CUPSD_AUTH_NEGOTIATE :
+         strlcpy(buffer, "negotiate", bufsize);
+         break;
+
+      default :
+         strlcpy(buffer, "username,password", bufsize);
+         break;
+    }
+
+    return (buffer);
+  }
+
+  return (NULL);
+}
+
+
 #ifdef __APPLE__
 /*
  * 'get_hostconfig()' - Get an /etc/hostconfig service setting.
@@ -3619,8 +3749,9 @@ send_cups_browse(cupsd_printer_t *p)      /* I - Printer to send */
                        uri[1024],      /* Printer URI */
                        location[1024], /* printer-location */
                        info[1024],     /* printer-info */
-                       make_model[1024];
+                       make_model[1024],
                                        /* printer-make-and-model */
+                       air[1024];      /* auth-info-required */
   cupsd_netif_t                *iface;         /* Network interface */
 
 
@@ -3658,6 +3789,11 @@ send_cups_browse(cupsd_printer_t *p)     /* I - Printer to send */
   else
     strlcpy(make_model, "Local System V Printer", sizeof(make_model));
 
+  if (get_auth_info_required(p, packet, sizeof(packet)))
+    snprintf(air, sizeof(air), " auth-info-required=%s", packet);
+  else
+    air[0] = '\0';
+
  /*
   * Send a packet to each browse address...
   */
@@ -3694,9 +3830,9 @@ send_cups_browse(cupsd_printer_t *p)      /* I - Printer to send */
                           (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s" :
                                                            "/printers/%s",
                           p->name);
-         snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\" %s\n",
+         snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\" %s%s\n",
                   type, p->state, uri, location, info, make_model,
-                  p->browse_attrs ? p->browse_attrs : "");
+                  p->browse_attrs ? p->browse_attrs : "", air);
 
          bytes = strlen(packet);
 
@@ -3735,9 +3871,10 @@ send_cups_browse(cupsd_printer_t *p)     /* I - Printer to send */
                           (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s" :
                                                            "/printers/%s",
                           p->name);
-         snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\" %s\n",
+         snprintf(packet, sizeof(packet),
+                  "%x %x %s \"%s\" \"%s\" \"%s\" %s%s\n",
                   type, p->state, uri, location, info, make_model,
-                  p->browse_attrs ? p->browse_attrs : "");
+                  p->browse_attrs ? p->browse_attrs : "", air);
 
          bytes = strlen(packet);
 
@@ -3760,9 +3897,9 @@ send_cups_browse(cupsd_printer_t *p)      /* I - Printer to send */
       * the default server name...
       */
 
-      snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\" %s\n",
+      snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\" %s%s\n",
                       type, p->state, p->uri, location, info, make_model,
-              p->browse_attrs ? p->browse_attrs : "");
+              p->browse_attrs ? p->browse_attrs : "", air);
 
       bytes = strlen(packet);
       cupsdLogMessage(CUPSD_LOG_DEBUG2,
@@ -5273,7 +5410,7 @@ update_lpd(int onoff)                     /* - 1 = turn on, 0 = turn off */
     argv[4] = NULL;
 
     cupsdStartProcess("/bin/launchctl", argv, envp, -1, -1, -1, -1, -1, 1,
-                      NULL, 0, &pid);
+                      NULL, NULL, &pid);
   }
 #endif /* __APPLE__ */
   else