]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Clean up and simplify snap support.
authorMichael R Sweet <michael.r.sweet@gmail.com>
Wed, 6 Oct 2021 14:42:34 +0000 (10:42 -0400)
committerMichael R Sweet <michael.r.sweet@gmail.com>
Wed, 6 Oct 2021 14:42:55 +0000 (10:42 -0400)
config-scripts/cups-container.m4
configure
scheduler/auth.c
scheduler/cert.c
scheduler/conf.c
scheduler/cups-exec.c
scheduler/cupsfilter.c
scheduler/env.c
scheduler/process.c

index 2190103fddef88c5ed59914eed5088b544ab5d36..278f0d9a241b39adac66dd94b0b16fd201f5e109 100644 (file)
@@ -10,7 +10,7 @@ dnl
 dnl Specify a container mode
 CONTAINER="none"
 
-AC_ARG_WITH([container], AS_HELP_STRING([--with-container=...], [configure to use in container ('none', 'snap')]), [
+AC_ARG_WITH([container], AS_HELP_STRING([--with-container=...], [configure to use in container (none, snap)]), [
     CONTAINER="$withval"
 ])
 
index 43bcf2daa21861d081a5e80e7bd3d909497b6ad0..f2161c253635d92c48e959bcead9ee55b9c2f341 100755 (executable)
--- a/configure
+++ b/configure
@@ -694,7 +694,6 @@ ONDEMANDLIBS
 ONDEMANDFLAGS
 SNAPDGLIBLIBS
 APPARMORLIBS
-SNAPCTL
 IPPFIND_MAN
 IPPFIND_BIN
 DNSSD_BACKEND
@@ -904,11 +903,7 @@ enable_largefile
 with_dnssd
 with_dnssd_libs
 with_dnssd_includes
-enable_snapped_cupsd
-enable_snapped_clients
-with_our_snap_name
-with_snapctl
-with_cups_control_slot
+with_container
 with_ondemand
 with_systemd
 with_smfmanifestdir
@@ -1599,10 +1594,6 @@ Optional Features:
   --enable-gssapi         enable (deprecated) GSSAPI/Kerberos support
   --disable-pam           disable PAM support
   --disable-largefile     omit support for large files
-  --enable-snapped-cupsd  enable support for packaging CUPS in a Snap
-  --enable-snapped-clients
-                          enable support for CUPS controlling admin access
-                          from snapped clients
   --enable-page-logging   enable page_log by default
   --enable-sync-on-close  enable SyncOnClose (off by default)
   --disable-browsing      disable Browsing by default
@@ -1641,14 +1632,7 @@ Optional Packages:
                           mdnsresponder, no, yes)
   --with-dnssd-libs       set directory for DNS Service Discovery library
   --with-dnssd-includes   set directory for DNS Service Discovery header files
-  --with-our-snap-name    Set name of the Snap we are snapped in, only needed
-                          with --enable-snapped-cupsd, default=cups
-  --with-snapctl          Set path for snapctl, only needed with
-                          --enable-snapped-cupsd, default=/usr/bin/snapctl
-  --with-cups-control-slot
-                          Name for cups-control slot as defined in
-                          snapcraft.yaml, only needed with
-                          --enable-snapped-cupsd, default=cups-control
+  --with-container=...    configure to use in container (none, snap)
   --with-ondemand=...     Specify the on-demand launch interface (launchd,
                           systemd, upstart)
   --with-systemd          set directory for systemd service files
 
 
 
-# Check whether --enable-snapped_cupsd was given.
-if test ${enable_snapped_cupsd+y}
-then :
-  enableval=$enable_snapped_cupsd;
-fi
+CONTAINER="none"
 
-# Check whether --enable-snapped_clients was given.
-if test ${enable_snapped_clients+y}
-then :
-  enableval=$enable_snapped_clients;
-fi
 
-
-# Check whether --with-our-snap-name was given.
-if test ${with_our_snap_name+y}
+# Check whether --with-container was given.
+if test ${with_container+y}
 then :
-  withval=$with_our_snap_name;
-    OUR_SNAP_NAME="$withval"
-
-else $as_nop
-
-    OUR_SNAP_NAME="cups"
+  withval=$with_container;
+    CONTAINER="$withval"
 
 fi
 
 
-printf "%s\n" "#define OUR_SNAP_NAME \"$OUR_SNAP_NAME\"" >>confdefs.h
-
-
-# Check whether --with-snapctl was given.
-if test ${with_snapctl+y}
-then :
-  withval=$with_snapctl;
-    SNAPCTL="$withval"
-
-else $as_nop
-
-    SNAPCTL="/usr/bin/snapctl"
+case "$CONTAINER" in #(
+  none) :
 
-fi
-
-
-printf "%s\n" "#define SNAPCTL \"$SNAPCTL\"" >>confdefs.h
-
-
-# Check whether --with-cups_control_slot was given.
-if test ${with_cups_control_slot+y}
-then :
-  withval=$with_cups_control_slot;
-    CUPS_CONTROL_SLOT="$withval"
-
-else $as_nop
+    # No container in use
+ ;; #(
+  snap) :
 
-    CUPS_CONTROL_SLOT="cups-control"
+    # Building as a snap
 
-fi
+printf "%s\n" "#define CUPS_SNAP 1" >>confdefs.h
 
+ ;; #(
+  *) :
 
-printf "%s\n" "#define CUPS_CONTROL_SLOT \"$CUPS_CONTROL_SLOT\"" >>confdefs.h
+    as_fn_error $? "Unsupported container '$CONTAINER' specified." "$LINENO" 5
+ ;; #(
+  *) :
+     ;;
+esac
 
 
 APPARMORLIBS=""
 SNAPDGLIBLIBS=""
-ENABLE_SNAPPED_CUPSD="NO"
-ENABLE_SNAPPED_CLIENTS="NO"
 
-if test x$enable_snapped_cupsd = xyes
-then :
 
-    enable_snapped_clients="yes"
 
-fi
-
-if test "x$PKGCONFIG" != x -a x$enable_snapped_clients = xyes
+if "x$PKGCONFIG" != x
 then :
 
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libapparmor" >&5
@@ -10847,15 +10796,14 @@ then :
        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 printf "%s\n" "yes" >&6; }
 
-       CFLAGS="$CFLAGS $($PKGCONFIG --cflags libapparmor)"
-       APPARMORLIBS="$($PKGCONFIG --libs libapparmor)"
+       CFLAGS="$CFLAGS $($PKGCONFIG --cflags libapparmor)"
+       APPARMORLIBS="$($PKGCONFIG --libs libapparmor)"
 
-printf "%s\n" "#define HAVE_APPARMOR 1" >>confdefs.h
+printf "%s\n" "#define HAVE_LIBAPPARMOR 1" >>confdefs.h
 
 
        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsnapd-glib" >&5
 printf %s "checking for libsnapd-glib... " >&6; }
-
        if $PKGCONFIG --exists snapd-glib glib-2.0 gio-2.0
 then :
 
@@ -10864,266 +10812,34 @@ printf "%s\n" "yes" >&6; }
            CFLAGS="$CFLAGS $($PKGCONFIG --cflags snapd-glib glib-2.0 gio-2.0)"
            SNAPDGLIBLIBS="$($PKGCONFIG --libs snapd-glib glib-2.0 gio-2.0)"
 
-printf "%s\n" "#define HAVE_SNAPDGLIB 1" >>confdefs.h
-
-
-else $as_nop
-
-           { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
-printf "%s\n" "no" >&6; }
-
-fi
-
-       if test x$enable_snapped_cupsd = xyes
-then :
+printf "%s\n" "#define HAVE_LIBSNAPDGLIB 1" >>confdefs.h
 
-           { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for snapd_client_run_snapctl2_sync in -lsnapd-glib" >&5
-printf %s "checking for snapd_client_run_snapctl2_sync in -lsnapd-glib... " >&6; }
-if test ${ac_cv_lib_snapd_glib_snapd_client_run_snapctl2_sync+y}
-then :
-  printf %s "(cached) " >&6
-else $as_nop
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsnapd-glib  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-char snapd_client_run_snapctl2_sync ();
-int
-main (void)
-{
-return snapd_client_run_snapctl2_sync ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"
-then :
-  ac_cv_lib_snapd_glib_snapd_client_run_snapctl2_sync=yes
-else $as_nop
-  ac_cv_lib_snapd_glib_snapd_client_run_snapctl2_sync=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_snapd_glib_snapd_client_run_snapctl2_sync" >&5
-printf "%s\n" "$ac_cv_lib_snapd_glib_snapd_client_run_snapctl2_sync" >&6; }
-if test "x$ac_cv_lib_snapd_glib_snapd_client_run_snapctl2_sync" = xyes
+           SAVELIBS="$LIBS"
+           LIBS="$SNAPDGLIBLIBS $LIBS"
+           ac_fn_c_check_func "$LINENO" "snapd_client_run_snapctl2_sync" "ac_cv_func_snapd_client_run_snapctl2_sync"
+if test "x$ac_cv_func_snapd_client_run_snapctl2_sync" = xyes
 then :
 
 
 printf "%s\n" "#define HAVE_SNAPD_CLIENT_RUN_SNAPCTL2_SYNC 1" >>confdefs.h
 
 
-printf "%s\n" "#define SUPPORT_SNAPPED_CUPSD 1" >>confdefs.h
-
-
-printf "%s\n" "#define SUPPORT_SNAPPED_CLIENTS 1" >>confdefs.h
-
-               ENABLE_SNAPPED_CUPSD="YES"
-               ENABLE_SNAPPED_CLIENTS="YES"
-
-else $as_nop
-
-               if test "x$SNAPDGLIBLIBS" != "x"
-then :
-
-                   SNAPDGLIBLIBS=""
-
 fi
-               if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}snapctl", so it can be a program name with args.
-set dummy ${ac_tool_prefix}snapctl; ac_word=$2
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-printf %s "checking for $ac_word... " >&6; }
-if test ${ac_cv_path_SNAPCTL+y}
-then :
-  printf %s "(cached) " >&6
-else $as_nop
-  case $SNAPCTL in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_SNAPCTL="$SNAPCTL" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  case $as_dir in #(((
-    '') as_dir=./ ;;
-    */) ;;
-    *) as_dir=$as_dir/ ;;
-  esac
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
-    ac_cv_path_SNAPCTL="$as_dir$ac_word$ac_exec_ext"
-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
 
-  ;;
-esac
-fi
-SNAPCTL=$ac_cv_path_SNAPCTL
-if test -n "$SNAPCTL"; then
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SNAPCTL" >&5
-printf "%s\n" "$SNAPCTL" >&6; }
-else
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
-printf "%s\n" "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_path_SNAPCTL"; then
-  ac_pt_SNAPCTL=$SNAPCTL
-  # Extract the first word of "snapctl", so it can be a program name with args.
-set dummy snapctl; ac_word=$2
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-printf %s "checking for $ac_word... " >&6; }
-if test ${ac_cv_path_ac_pt_SNAPCTL+y}
-then :
-  printf %s "(cached) " >&6
-else $as_nop
-  case $ac_pt_SNAPCTL in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_ac_pt_SNAPCTL="$ac_pt_SNAPCTL" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  case $as_dir in #(((
-    '') as_dir=./ ;;
-    */) ;;
-    *) as_dir=$as_dir/ ;;
-  esac
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
-    ac_cv_path_ac_pt_SNAPCTL="$as_dir$ac_word$ac_exec_ext"
-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-ac_pt_SNAPCTL=$ac_cv_path_ac_pt_SNAPCTL
-if test -n "$ac_pt_SNAPCTL"; then
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_SNAPCTL" >&5
-printf "%s\n" "$ac_pt_SNAPCTL" >&6; }
-else
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
-printf "%s\n" "no" >&6; }
-fi
-
-  if test "x$ac_pt_SNAPCTL" = x; then
-    SNAPCTL=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    SNAPCTL=$ac_pt_SNAPCTL
-  fi
-else
-  SNAPCTL="$ac_cv_path_SNAPCTL"
-fi
-
-               { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for snapctl is-connected support" >&5
-printf %s "checking for snapctl is-connected support... " >&6; }
-               if test "x$SNAPCTL" != x && $SNAPCTL is-connected --help >/dev/null 2>&1
-then :
-
-                   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-printf "%s\n" "yes" >&6; }
-
-printf "%s\n" "#define HAVE_SNAPCTL_IS_CONNECTED 1" >>confdefs.h
-
-
-printf "%s\n" "#define SUPPORT_SNAPPED_CUPSD 1" >>confdefs.h
-
-
-printf "%s\n" "#define SUPPORT_SNAPPED_CLIENTS 1" >>confdefs.h
-
-                   ENABLE_SNAPPED_CUPSD="YES"
-                   ENABLE_SNAPPED_CLIENTS="YES"
-
-else $as_nop
-
-                   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
-printf "%s\n" "no" >&6; }
-
-fi
-
-fi
-
-
-else $as_nop
-
-           if test "x$SNAPDGLIBLIBS" != "x"
-then :
-
-
-printf "%s\n" "#define SUPPORT_SNAPPED_CLIENTS 1" >>confdefs.h
-
-               ENABLE_SNAPPED_CLIENTS="YES"
-
-fi
-
-fi
+           LIBS="$SAVELIBS"
 
 else $as_nop
 
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+           { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 fi
 
 fi
 
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Snap support" >&5
-printf %s "checking for Snap support... " >&6; }
-if test "x$ENABLE_SNAPPED_CLIENTS" != "xNO"
-then :
-
-    if test "x$ENABLE_SNAPPED_CUPSD" != "xNO"
-then :
-
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: cupsd + clients" >&5
-printf "%s\n" "yes: cupsd + clients" >&6; }
-
-else $as_nop
-
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: clients only" >&5
-printf "%s\n" "yes: clients only" >&6; }
-
-fi
-
-else $as_nop
-
-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
-printf "%s\n" "no" >&6; }
-
 fi
 
 
-
-
-
 ONDEMANDFLAGS=""
 ONDEMANDLIBS=""
 
index d124bfd1d5637fdb6ba719dcc90914f176d65c90..0de70e6b1b53a8c8d22afd4d197daa850a71a2c9 100644 (file)
@@ -65,7 +65,7 @@ typedef struct sockpeercred cupsd_ucred_t;
  * Local functions...
  */
 
-static int             check_admin_task(cupsd_client_t *con);
+static int             check_admin_access(cupsd_client_t *con);
 #ifdef HAVE_AUTHORIZATION_H
 static int             check_authref(cupsd_client_t *con, const char *right);
 #endif /* HAVE_AUTHORIZATION_H */
@@ -1841,7 +1841,7 @@ cupsdIsAuthorized(cupsd_client_t *con,    /* I - Connection */
       if (!_cups_strcasecmp(name, "@SYSTEM"))
       {
         for (i = 0; i < NumSystemGroups; i ++)
-         if (cupsdCheckGroup(username, pw, SystemGroups[i]) && check_admin_task(con))
+         if (cupsdCheckGroup(username, pw, SystemGroups[i]) && check_admin_access(con))
            return (HTTP_OK);
       }
     }
@@ -1884,7 +1884,7 @@ cupsdIsAuthorized(cupsd_client_t *con,    /* I - Connection */
       cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: Checking group \"%s\" membership...", name);
 
       for (i = 0; i < NumSystemGroups; i ++)
-       if (cupsdCheckGroup(username, pw, SystemGroups[i]) && check_admin_task(con))
+       if (cupsdCheckGroup(username, pw, SystemGroups[i]) && check_admin_access(con))
          return (HTTP_OK);
     }
   }
@@ -1940,481 +1940,209 @@ cupsdNewLocation(const char *location)        /* I - Location path */
 
 
 /*
- * 'check_admin_task()' - Do additional checks on administrative tasks
+ * 'check_admin_access()' - Verify that the client has administrative access.
  */
 
-static int                                      /* O - 1 if admin task authorized */
-check_admin_task(cupsd_client_t *con) /* I - Connection */
+static int                             // O - 1 if authorized, 0 otherwise
+check_admin_access(cupsd_client_t *con) // I - Client connection
 {
-  int ret = 1; /* Return value */
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Administrative task");
-
+#if defined(HAVE_LIBAPPARMOR) && defined(HAVE_LIBSNAPDGLIB)
  /*
   * If the client accesses locally via domain socket, find out whether it
-  * is a Snap. Grant access if it is not a Snap, if it is a classic Snap
-  * or if it is a confined Snap which plugs "cups-control", deny access
-  * if it is a confined Snap not plugging "cups-control" or if an error
-  * occurs in the process of finding this out.
-  */
-
-#if defined(AF_LOCAL) && defined(SUPPORT_SNAPPED_CLIENTS)
-
- /*
-  * Get the client's file descriptor and from this its AppArmor context
+  * is a Snap.  Grant access if it is not a Snap, if it is a classic Snap
+  * or if it is a confined Snap which plugs "cups-control".  Otherwise deny
+  * access.
   */
 
-  if (httpAddrFamily(con->http->hostaddr) == AF_LOCAL)
-  {
-    int                 peerfd;         /* Peer's file descriptor */
-
-    peerfd = httpGetFd(con->http);
-
-    if (peerfd < 0)
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: Unable to get peer file descriptor of client connecting via domain socket");
-    }
-    else
-    {
-      char *context = NULL;      /* AppArmor profile name of client */
-#  undef CHECK_METHOD_FOUND
-#  ifdef SUPPORT_SNAPPED_CUPSD
-      int status = 65535;        /* Status of client Snap context check */
-#    if defined(HAVE_SNAPDGLIB) && defined(HAVE_SNAPD_CLIENT_RUN_SNAPCTL2_SYNC)
-#      define CHECK_METHOD_FOUND 1
-      char *args[] = { "is-connected", "--apparmor-label", NULL, CUPS_CONTROL_SLOT, NULL }; /* snapctl arguments */
-      SnapdClient *client = NULL; /* Data structure of snapd access */
-      const char *cookie;        /* snapd access cookie */
-      GError *error = NULL;      /* Glib error */
-#    else
-#      ifdef HAVE_SNAPCTL_IS_CONNECTED
-#        define CHECK_METHOD_FOUND 1
-      char *args[] = { SNAPCTL, "is-connected", "--apparmor-label", NULL, CUPS_CONTROL_SLOT, NULL }; /* snapctl command line */
-      int fds[2],                /* Pipe file descriptors for stderr of
-                                   snapctl */
-         nullfd;                /* /dev/null file descriptor for stdout of
-                                   snapctl */
-      pid_t pid;                 /* PID of snapctl */
-      cups_file_t *snapctl_stderr; /* CUPS FP for stderr of snapctl */
-      char buf[1024];            /* Buffer for snapctl's stderr output */
-      int wstatus;               /* Wait result of forked snapctl process */
-#      endif /* HAVE_SNAPCTL_IS_CONNECTED */
-#    endif /* HAVE_SNAPDGLIB && HAVE_SNAPD_CLIENT_RUN_SNAPCTL2_SYNC */
-#  else
-#    if !defined(SUPPORT_SNAPPED_CUPSD) && defined(HAVE_SNAPDGLIB)
-#      define CHECK_METHOD_FOUND 1
-      char *snap_name = NULL;    /* Client Snap name */
-      char *dot;                 /* Pointer to dot in AppArmor profile name */
-      SnapdClient *snapd = NULL; /* Data structure of snapd access */
-      GError *error = NULL;      /* Glib error */
-      SnapdSnap *snap = NULL;    /* Data structure of client Snap */
-      GPtrArray *plugs = NULL;   /* Plug search result of client Snap */
-#    endif /* !SUPPORT_SNAPPED_CUPSD && HAVE_SNAPDGLIB */
-#  endif /* SUPPORT_SNAPPED_CUPSD */
-
-
-#  ifndef SUPPORT_SNAPPED_CUPSD
-
-      /* If AppArmor is not enabled, then we can't identify the client */
-      /* With cupsd running in a Snap, the "mount-observe" interface
-         needs to be plugged, therefore we do this only if not snapped. */
-      if (!aa_is_enabled())
-      {
-       cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: No AppArmor in use");
-       goto snap_check_done;
-      }
-
-#  endif /* !SUPPORT_SNAPPED_CUPSD */
-
-      if (aa_getpeercon(peerfd, &context, NULL) < 0)
-      {
-       cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: AppArmor profile could not be retrieved for client process - Error: %s", strerror(errno));
-       goto snap_check_done;
-      } else
-       cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: AppArmor profile of client process: %s", context);
-
-#  ifdef OUR_SNAP_NAME
-      /* Is the client one of the utilities of our Snap? */
-      if (!strncmp(context, "snap." OUR_SNAP_NAME ".", strlen(OUR_SNAP_NAME) + 6))
-      {
-       cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Client Snap is the same Snap we are running in, access granted");
-       goto snap_check_done;
-      }
-#  endif /* OUR_SNAP_NAME */
-
-#  ifdef SUPPORT_SNAPPED_CUPSD
-
-     /*
-      * Run
-      *
-      * snapctl is-connected --apparmor-label AA_CONTEXT CUPS_CONTROL_SLOT
-      *
-      * or an equivalent library function call using the
-      * snapd_client_run_snapctl2_sync() function of libsnapd-glib.
-      *
-      * Here AA_CONTEXT is the AppArmor profile name of the client, or
-      * "unconfined" for an unconfined client and CUPS_CONTROL_SLOT
-      * the name of the slot of the CUPS Snap to which clients plug
-      * with their cups-control plug in order to do administrative
-      * CUPS tasks.
-      *
-      * The exit status of the command/function call tells which type
-      * of client we have to do with:
-      *
-      *    0: The client is a confined Snap and plugs cups-control
-      *           -> Grant access
-      *    1: The client is a confined Snap and does not plug cups-control
-      *           -> Deny access
-      *   10: The client is a classic Snap
-      *           -> Grant access
-      *   11: The client is not a Snap
-      *           -> Grant access
-      *
-      * NOTE: This method only works if cupsd is running in a Snap
-      *       providing a slot for the client's "cups-control"
-      *       plug. Do not build CUPS with this method when intending
-      *       to use it unsnapped, for example in a Debian or RPM
-      *       package, or directly installed into your system. The
-      *       errors of snapctl missing or snapctl/the function
-      *       running without a Snap context will deny all
-      *       administrative accesses!
-      *
-      * When running inside a Snap this method is preferred, as it does not
-      * require full access to the snapd under which cupsd is running.
-      */
-
-#    if defined(HAVE_SNAPDGLIB) && defined(HAVE_SNAPD_CLIENT_RUN_SNAPCTL2_SYNC)
-
-     /*
-      * Use the snapd_client_run_snapctl2_sync() function of libsnapd-glib
-      */
-
-      /* Insert client Snap context in snapctl arguments */
-      args[2] = context;
-
-      /* Connect to snapd */
-      client = snapd_client_new();
-      if (!client)
-      {
-       cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Could not connect to snapd, permission denied");
-       ret = 0;
-       goto snap_check_done;
-      }
-
-      /* snapctl commands are sent over a this socket that is made
-        available within the snap sandbox */
-      snapd_client_set_socket_path(client, "/run/snapd-snap.socket");
+  int          fd = httpGetFd(con->http);
+                                       // Client socket file descriptor
+  char         *context = NULL;        // AppArmor profile name of client
+  SnapdClient  *client = NULL;         // Data structure of snapd access
+  GError       *error = NULL;          // Glib error
+  int          ret = 1;                // Return value
 
-      /* Take cookie from the environment if available */
-      cookie = g_getenv("SNAP_COOKIE");
-      if (!cookie)
-      {
-        cookie = "";
-       cupsdLogMessage(CUPSD_LOG_WARN, "check_admin_task: No SNAP_COOKIE set in the Snap environment, client Snap context check may not work");
-      }
-
-      /* Do the client Snap context check */
-      if (!snapd_client_run_snapctl2_sync(client, cookie, args, NULL, NULL, &status, NULL, &error)) {
-       cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Client Snap context check error - %s", error->message);
-       ret = 0;
-       goto snap_check_done;
-      }
-
-#    else
-#      ifdef HAVE_SNAPCTL_IS_CONNECTED
-
-     /*
-      * Call the snapctl executable using execv() in a fork
-      */
 
-      /* Insert client Snap context in snapctl command line */
-      args[3] = context;
-
-      /* Create a pipe to catch stderr output from snapctl */
-      if (pipe(fds))
-      {
-       fds[0] = -1;
-       fds[1] = -1;
-       cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: Unable to establish stderr pipe for snapctl call - %s", strerror(errno));
-       ret = 0;
-       goto snap_check_done;
-      }
-
-      /* Set the "close on exec" flag on each end of the pipe... */
-      if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC))
-      {
-       close(fds[0]);
-       close(fds[1]);
-       fds[0] = -1;
-       fds[1] = -1;
-       cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: Unable to set \"close on exec\" flag on read end of the stderr pipe for snapctl call - %s", strerror(errno));
-       ret = 0;
-       goto snap_check_done;
-      }
-      if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC))
-      {
-       close(fds[0]);
-       close(fds[1]);
-       cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: Unable to set \"close on exec\" flag on write end of the stderr pipe for snapctl call - %s", strerror(errno));
-       ret = 0;
-       goto snap_check_done;
-      }
-
-      if ((pid = fork()) == 0)
-      {
-       /* Couple pipe with stderr of Ghostscript process */
-       if (fds[1] >= 0) {
-         if (fds[1] != 2) {
-           if (dup2(fds[1], 2) < 0) {
-             cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: Unable to couple pipe with stderr of snapctl process - %s", strerror(errno));
-             exit(100);
-           }
-           close(fds[1]);
-         }
-         close(fds[0]);
-       } else {
-         cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: Invalid pipe file descriptor to couple with stderr of snapctl process - %s", strerror(errno));
-         exit(100);
-       }
-
-       /* Send snapctl's stdout to the Nirwana, as snapctl is supposed to
-          not output anything here */
-       if ((nullfd = open("/dev/null", O_RDWR)) > 2)
-       {
-         dup2(nullfd, 1);
-         close(nullfd);
-       }
-       else
-         close(nullfd);
-       fcntl(1, F_SETFL, O_NDELAY);
-
-       /* Execute snapctl command line ... */
-       cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Running command: " SNAPCTL " is-connected --apparmor-label %s " CUPS_CONTROL_SLOT, context);
-       execv(SNAPCTL, args);
-       cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: Unable to launch snapctl: %s", strerror(errno));
-       exit(100);
-      }
-      else if (pid < 0)
-      {
-       cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: Unable to fork for snapctl call - %s", strerror(errno));
-       ret = 0;
-       goto snap_check_done;
-      }
-      cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Started snapctl (PID %d)", pid);
-
-      close(fds[1]);
-
-      /* Read out stderr from snapctl */
-      buf[0] = '\0';
-      snapctl_stderr = cupsFileOpenFd(fds[0], "r");
-      if (snapctl_stderr)
-      {
-       while (cupsFileGets(snapctl_stderr, buf, sizeof(buf)) && buf[0])
-       {
-         cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: Error message from snapctl: %s", buf);
-         ret = 0;
-       }
-       cupsFileClose(snapctl_stderr);
-      }
-      close(fds[0]);
+#  ifdef AF_LOCAL
+  // Only check domain sockets...
+  if (httpAddrFamily(con->http->hostaddr) != AF_LOCAL)
+    return (1);
+#  endif // AF_LOCAL
 
-      /* Wait for snapctl to finish */
-    retry_wait:
-      if (waitpid (pid, &wstatus, 0) == -1)
-      {
-       if (errno == EINTR)
-         goto retry_wait;
-       cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: snapctl (PID %d) stopped with an error - %s", pid, strerror(errno));
-       ret = 0;
-       goto snap_check_done;
-      }
-      if (ret == 0)
-       goto snap_check_done;
-      cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: snapctl (PID %d) exited with no errors.", pid);
+#  if !CUPS_SNAP
+  // If AppArmor is not enabled, then we can't identify the client...
+  if (!aa_is_enabled())
+  {
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "AppArmor not in use.");
+    return (1);
+  }
+#  endif /* !CUPS_SNAP */
 
-      /* How did snapctl terminate */
-      if (WIFEXITED(wstatus))
-      {
-       /* Via regular exit */
-       status = WEXITSTATUS(wstatus);
-       if (status == 100)
-       {
-         cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: snapctl not executed");
-         ret = 0;
-         goto snap_check_done;
-       }
-      }
-      else if (WIFSIGNALED(wstatus))
-      {
-       /* Via signal */
-       cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: snapctl caught the signal %d", WTERMSIG(wstatus));
-       ret = 0;
-       goto snap_check_done;
-      }
+  // Get the client's AppArmor context using the socket...
+  if (aa_getpeercon(fd, &context, NULL) < 0)
+  {
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "AppArmor profile could not be retrieved: %s", strerror(errno));
+    return (1);
+  }
+  else
+  {
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "AppArmor profile is '%s'.", context);
+  }
 
-#      endif /* HAVE_SNAPCTL_IS_CONNECTED */
-#    endif /* HAVE_SNAPDGLIB && HAVE_SNAPD_CLIENT_RUN_SNAPCTL2_SYNC */
+  // Allow access from "cups" snap...
+  if (!strncmp(context, "snap.cups.", 10))
+    goto done;
 
-      switch (status)
-      {
-        case  0 :
-           cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Client Snap connecting via \"cups-control\" interface, access granted");
-           break;
-        case  1 :
-           cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Client Snap does not connect via \"cups-control\" interface, permission denied");
-           ret = 0;
-           break;
-        case 10 :
-           cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Client Snap under classic confinement, access granted");
-           break;
-        case 11 :
-           cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Client is not a Snap, access granted");
-           break;
-        default :
-           cupsdLogMessage(CUPSD_LOG_ERROR, "check_admin_task: snapctl exited with unknown status: %d", status);
-           ret = 0;
-           break;
-      }
+#  if CUPS_SNAP && defined(HAVE_SNAPD_CLIENT_RUN_SNAPCTL2_SYNC)
+ /*
+  * CUPS is snapped, so check whether the client is also snapped.  If so,
+  * determine whether the client snap has a "cups-control" plug which allows
+  * the application to perform CUPS administrative tasks.
+  */
 
-    snap_check_done:
-      if (context)
-       free(context);
-#    if defined(HAVE_SNAPDGLIB) && defined(HAVE_SNAPD_CLIENT_RUN_SNAPCTL2_SYNC)
-      g_clear_object(&client);
-#    endif /* HAVE_SNAPDGLIB && HAVE_SNAPD_CLIENT_RUN_SNAPCTL2_SYNC */
+  const char   *cookie;                // snapd access cookie
+  int          status = 65535;         // Status of client Snap context check
+  const char   *args[] =               // snapctl arguments
+  {
+    "is-connected",
+    "--apparmor-label",
+    NULL,
+    "cups-control",
+    NULL
+  };
+
+  // Connect to snapd
+  if ((client = snapd_client_new()) == NULL)
+  {
+    cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to connect to snapd.");
+    ret = 0;
+    goto done;
+  }
 
-#  else
-#    if !defined(SUPPORT_SNAPPED_CUPSD) && defined(HAVE_SNAPDGLIB)
+  // snapctl commands are sent over a domain socket
+  snapd_client_set_socket_path(client, "/run/snapd-snap.socket");
 
-     /*
-      * If the client is a Snap, extract the client Snap's name from
-      * the AppArmor context and then query snapd to find out about the
-      * Snap's confinement type and whether it plugs cups-control. Grant
-      * access if
-      *
-      *   - the client is not a Snap
-      *   - the client is a classic Snap
-      *   - the client is a confined Snap plugging "cups-control"
-      *
-      * We deny access if
-      *
-      *   - the client is a confined Snap not plugging "cups-control"
-      *   - an error occurs during the steps of this method
-      *
-      * NOTE: This method is only for use of cupsd when it is not
-      *       packaged in a Snap. In a Snap one would need to plug the
-      *       snapd-control interface, which gives full control on
-      *       snapd, a high security risk. Therefore one will not get
-      *       automatic connection of this interface granted in the
-      *       Snap Store. This is the reason why the snapctl method
-      *       (above) got created by the snapd developers.
-      *
-      * This is the preferred method to run CUPS unsnapped, as this is
-      * the only way to check Snap status on clients from an unsnapped
-      * cupsd.
-      */
+  // Take cookie from the environment if available
+  if ((cookie = g_getenv("SNAP_COOKIE")) == NULL)
+  {
+    cookie = "";
+    cupsdLogClient(CUPSD_LOG_WARN, "No SNAP_COOKIE set in the Snap environment.");
+  }
 
-      /* If the AppArmor context does not begin with "snap.", then this
-         is not a snap */
-      if (strncmp(context, "snap.", 5) != 0)
-      {
-       cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: AppArmor context not from a Snap");
-        goto snap_check_done;
-      }
+  // Do the client Snap context check...
+  args[2] = context;
 
-      dot = strchr(context + 5, '.');
-      if (dot == NULL)
-      {
-        cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Malformed snapd AppArmor profile name: %s", context);
-        goto snap_check_done;
-      }
-      snap_name = strndup(context + 5, (size_t)(dot - context - 5));
-      cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Client is the Snap %s", snap_name);
+  if (!snapd_client_run_snapctl2_sync(client, cookie, args, NULL, NULL, &status, NULL, &error))
+  {
+    cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to check snap context: %s", error->message);
+    ret = 0;
+    goto done;
+  }
 
-      /* Connect to snapd */
-      snapd = snapd_client_new();
-      if (!snapd)
-      {
-       cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Could not connect to snapd, permission denied");
+  switch (status)
+  {
+    case 0 : // The client is a confined Snap and plugs cups-control
+       cupsdLogClient(con, CUPSD_LOG_DEBUG, "Snap with cups-control plug - allowed.");
+       break;
+    case 1 : // The client is a confined Snap and does not plug cups-control
+       cupsdLogClient(con, CUPSD_LOG_DEBUG, "Snap without cups-control plug - denied.");
        ret = 0;
-       goto snap_check_done;
-      }
-
-      /* Check whether the client Snap is under classic confinement */
-      snap = snapd_client_get_snap_sync(snapd, snap_name, NULL, &error);
-      if (!snap)
-      {
-        cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Could not obtain client Snap data: \"%s\", permission denied", error->message);
+       break;
+    case 10 : // The client is a classic Snap
+       cupsdLogClient(con, CUPSD_LOG_DEBUG, "Classic snap - allowed.");
+       break;
+    case 11 : // The client is not a Snap
+       cupsdLogClient(con, CUPSD_LOG_DEBUG, "Not a snap - allowed.");
+       break;
+    default : // Unexpected status...
+       cupsdLogClient(con, CUPSD_LOG_ERROR, "Snap check returned unexpected status %d - denied.", status);
        ret = 0;
-       goto snap_check_done;
-      }
+       break;
+  }
 
-      /* Snaps using classic confinement are granted access */
-      if (snapd_snap_get_confinement(snap) == SNAPD_CONFINEMENT_CLASSIC)
-      {
-        cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Client Snap under classic confinement, access granted");
-        goto snap_check_done;
-      }
+#  elif !CUPS_SNAP
+ /*
+  * If CUPS is not snapped, check whether the client is snapped and if it has
+  * the "cups-control" plug.
+  */
 
-      /* Get list of interfaces to which the client Snap is plugging */
-      if (!snapd_client_get_connections2_sync(snapd, SNAPD_GET_CONNECTIONS_FLAGS_NONE, snap_name, "cups-control", NULL, NULL, &plugs, NULL, NULL, &error))
-      {
-        cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Could not obtain the client Snap's interface connections: \"%s\", permission denied", error->message);
-       ret = 0;
-       goto snap_check_done;
-      }
+  // Is the client a snapped application?
+  if (strncmp(context, "snap.", 5))
+  {
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "Not a snap - allowed.");
+    goto done;
+  }
 
-      if (plugs->len <= 0)
-      {
-       cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Client Snap does not connect via \"cups-control\" interface, permission denied");
-       ret = 0;
-       goto snap_check_done;
-      }
+  // Extract the snap name from the context (snap.name.instance)
+  char *snap_name = strdup(context + 5);// Snap name follows "snap."
+  char *ptr = strchr(snap_name, '.');  // instance follows the name...
+  if (!ptr)
+  {
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "Malformed snapd AppArmor profile name '%s' - denied.", context);
+    free(snap_name);
+    ret = 0;
+    goto done;
+  }
 
-      cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Client Snap connecting via \"cups-control\" interface, access granted");
+  *ptr = '\0';
+  cupsdLogClient(con, CUPSD_LOG_DEBUG, "Client snap is '%s'.", snap_name);
 
-    snap_check_done:
-      if (context)
-       free(context);
-      if (snap_name)
-       free(snap_name);
-      g_clear_object(&snapd);
-      g_clear_object(&snap);
-      if (plugs)
-       g_ptr_array_unref(plugs);
+  // Connect to snapd
+  if ((client = snapd_client_new()) == NULL)
+  {
+    cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to connect to snapd.");
+    free(snap_name);
+    ret = 0;
+    goto done;
+  }
 
-#    endif /* !SUPPORT_SNAPPED_CUPSD && HAVE_SNAPDGLIB */
-#  endif /* SUPPORT_SNAPPED_CUPSD */
+  // Check whether the client Snap is under classic confinement
+  GPtrArray *plugs = NULL;             // List of plugs for snap
 
-#  ifndef CHECK_METHOD_FOUND
+  if ((snap = snapd_client_get_snap_sync(client, snap_name, NULL, &error)) == NULL)
+  {
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "Unable to get client Snap data: %s", error->message);
+    ret = 0;
+  }
+  // Snaps using classic confinement are granted access
+  else if (snapd_snap_get_confinement(snap) == SNAPD_CONFINEMENT_CLASSIC)
+  {
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "Classic snap - allowed.");
+  }
+  // Check whether the client Snap has the cups-control plug
+  else if (!snapd_client_get_connections2_sync(snapd, SNAPD_GET_CONNECTIONS_FLAGS_NONE, snap_name, "cups-control", NULL, NULL, &plugs, NULL, NULL, &error))
+  {
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "Unable to get client Snap plugs: %s", error->message);
+    ret = 0;
+  }
+  else if (plugs->len <= 0)
+  {
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "Snap without cups-control plug - denied.");
+    ret = 0;
+  }
+  else
+  {
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "Snap with cups-control plug - allowed.");
+  }
 
-     /*
-      * Issue warning if requirements for building Snap-related access control
-      * not fulfilled
-      */
+  if (plugs)
+    g_ptr_array_unref(plugs);
 
-      cupsdLogMessage(CUPSD_LOG_WARN, "check_admin_task: Compiling problem: none of the three access control methods (libsnapd-glib snapd access, \"snapctl is-connected\", libsnapd-glib-based snapctl call) available, no Snap-related access control built!");
+  free(snap_name);
+  g_clear_object(&snap);
 
-    snap_check_done:
-      if (context)
-       free(context);
+#  endif // CUPS_SNAP
 
-#  endif /* !CHECK_METHOD_FOUND */
+  done:
 
-    }
-  }
+  free(context);
+  g_clear_object(&client);
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Access %s", ret == 1 ? "granted" : "denied");
+  return (ret);
 
 #else
-
-  (void)con;
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "check_admin_task: Access granted (no extra checking)");
-
-#endif /* AF_LOCAL && SUPPORT_SNAPPED_CLIENTS */
-
-  return ret;
+  // No AppArmor/snapd to deal with...
+  return (1);
+#endif // HAVE_LIBAPPARMOR && HAVE_LIBSNAPDGLIB
 }
 
 
index 9716bbf3559d5a080ef96e9d488e3d497dc4c0d8..a0c3941bd4e9b45d0eeace53f84e7853e8fd7b36 100644 (file)
@@ -1,10 +1,12 @@
 /*
  * Authentication certificate routines for the CUPS scheduler.
  *
- * Copyright 2007-2016 by Apple Inc.
- * Copyright 1997-2006 by Easy Software Products.
+ * Copyright © 2021 by OpenPrinting.
+ * Copyright © 2007-2016 by Apple Inc.
+ * Copyright © 1997-2006 by Easy Software Products.
  *
- * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
  */
 
 /*
@@ -83,7 +85,7 @@ cupsdAddCert(int        pid,          /* I - Process ID */
 
   if (pid == 0)
   {
-#if defined(HAVE_ACL_INIT) && !defined(SUPPORT_SNAPPED_CUPSD)
+#if defined(HAVE_ACL_INIT) && !CUPS_SNAP
     acl_t              acl;            /* ACL information */
     acl_entry_t                entry;          /* ACL entry */
     acl_permset_t      permset;        /* Permissions */
@@ -92,7 +94,7 @@ cupsdAddCert(int        pid,          /* I - Process ID */
 #  endif /* HAVE_MBR_UID_TO_UUID */
     static int         acls_not_supported = 0;
                                        /* Only warn once */
-#endif /* HAVE_ACL_INIT && !SUPPORT_SNAPPED_CUPSD */
+#endif /* HAVE_ACL_INIT && !CUPS_SNAP */
 
 
    /*
@@ -104,7 +106,7 @@ cupsdAddCert(int        pid,                /* I - Process ID */
     /* ACLs do not work when cupsd is running in a Snap, and certificates
        need root as group owner to be only accessible for CUPS and not the
        unprivileged sub-processes */
-#ifdef SUPPORT_SNAPPED_CUPSD
+#if CUPS_SNAP
     fchown(fd, RunUser, 0);
 #else
     fchown(fd, RunUser, SystemGroupIDs[0]);
@@ -238,7 +240,7 @@ cupsdAddCert(int        pid,                /* I - Process ID */
       acl_free(acl);
     }
 #  endif /* HAVE_ACL_INIT */
-#endif /* SUPPORT_SNAPPED_CUPSD */
+#endif /* CUPS_SNAP */
 
     RootCertTime = time(NULL);
   }
index 5d167e0fe8102b867833d9482033f93e35d9bbc7..e44736b77d4a4c4acb4c352ac86f7b9cdf7b63d5 100644 (file)
@@ -1121,16 +1121,11 @@ cupsdReadConfiguration(void)
                             Group, 1, 1) < 0 ||
        cupsdCheckPermissions(StateDir, NULL, 0755, RunUser,
                             Group, 1, 1) < 0 ||
-       /* Inside a Snap cupsd is running as root without CAP_DAC_OVERRIDE
-         capability, so certs directory has to be root.root-owned so that
-         cupsd can access but not its unprivileged sub-processes. */
-#ifdef SUPPORT_SNAPPED_CUPSD
-       cupsdCheckPermissions(StateDir, "certs", 0711, RunUser,
-                            0, 1, 1) < 0 ||
+#if CUPS_SNAP
+       cupsdCheckPermissions(StateDir, "certs", 0711, RunUser, 0, 1, 1) < 0 ||
 #else
-       cupsdCheckPermissions(StateDir, "certs", RunUser ? 0711 : 0511, User,
-                            SystemGroupIDs[0], 1, 1) < 0 ||
-#endif /* SUPPORT_SNAPPED_CUPSD */
+       cupsdCheckPermissions(StateDir, "certs", RunUser ? 0711 : 0511, User, SystemGroupIDs[0], 1, 1) < 0 ||
+#endif /* CUPS_SNAP */
        cupsdCheckPermissions(ServerRoot, NULL, 0755, RunUser,
                             Group, 1, 0) < 0 ||
        cupsdCheckPermissions(ServerRoot, "ppd", 0755, RunUser,
index dff5055158037f9f51e566a1e947c080e3b55ada..7b851d33c6eb47f23af44789a8e344530b8cac8e 100644 (file)
@@ -1,9 +1,11 @@
 /*
  * Sandbox helper for CUPS.
  *
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright © 2021 by OpenPrinting.
+ * Copyright © 2007-2014 by Apple Inc.
  *
- * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
  *
  * Usage:
  *
@@ -129,11 +131,11 @@ main(int  argc,                           /* I - Number of command-line args */
     if (setgid(gid))
       exit(errno + 100);
 
-#  ifdef SUPPORT_SNAPPED_CUPSD
+#  if CUPS_SNAP
     if (setgroups(0, NULL))
 #  else
     if (setgroups(1, &gid))
-#  endif /* SUPPORT_SNAPPED_CUPSD */
+#  endif /* CUPS_SNAP */
       exit(errno + 100);
 
     if (uid && setuid(uid))
index d9192b424215ca0da1b6ab41b1742f09e927ca2b..c6dbb8debba8d177875fdcb510cc04bea01760d5 100644 (file)
@@ -965,11 +965,7 @@ exec_filters(mime_type_t   *srctype,       /* I - Source type */
 {
   int          i;                      /* Looping var */
   const char   *argv[8],               /* Command-line arguments */
-#ifdef SUPPORT_SNAPPED_CUPSD
                *envp[21],              /* Environment variables */
-#else
-               *envp[17],              /* Environment variables */
-#endif /* SUPPORT_SNAPPED_CUPSD */
                *temp;                  /* Temporary string */
   char         *optstr,                /* Filter options */
                content_type[1024],     /* CONTENT_TYPE */
@@ -977,17 +973,9 @@ exec_filters(mime_type_t   *srctype,       /* I - Source type */
                cups_fontpath[1024],    /* CUPS_FONTPATH */
                cups_serverbin[1024],   /* CUPS_SERVERBIN */
                cups_serverroot[1024],  /* CUPS_SERVERROOT */
-#ifdef SUPPORT_SNAPPED_CUPSD
-               fontconfig_file[1024],  /* FONTCONFIG_FILE */
-               fontconfig_path[1024],  /* FONTCONFIG_PATH */
-               fontconfig_sysroot[1024], /* FONTCONFIG_SYSROOT */
-#endif /* SUPPORT_SNAPPED_CUPSD */
                final_content_type[1024] = "",
                                        /* FINAL_CONTENT_TYPE */
                lang[1024],             /* LANG */
-#ifdef SUPPORT_SNAPPED_CUPSD
-               ld_library_path[2048],  /* LD_LIBRARY_PATH */
-#endif /* SUPPORT_SNAPPED_CUPSD */
                path[1024],             /* PATH */
                ppd[1024],              /* PPD */
                printer_info[255],      /* PRINTER_INFO env variable */
@@ -995,6 +983,13 @@ exec_filters(mime_type_t   *srctype,       /* I - Source type */
                printer_name[255],      /* PRINTER env variable */
                rip_max_cache[1024],    /* RIP_MAX_CACHE */
                userenv[1024],          /* USER */
+#if CUPS_SNAP
+               fontconfig_file[1024],  /* FONTCONFIG_FILE */
+               fontconfig_path[1024],  /* FONTCONFIG_PATH */
+               fontconfig_sysroot[1024],
+                                       /* FONTCONFIG_SYSROOT */
+               ld_library_path[2048],  /* LD_LIBRARY_PATH */
+#endif /* CUPS_SNAP */
                program[1024];          /* Program to run */
   mime_filter_t        *filter,                /* Current filter */
                *next;                  /* Next filter */
@@ -1046,9 +1041,6 @@ exec_filters(mime_type_t   *srctype,      /* I - Source type */
   * Setup the filter environment and command-line...
   */
 
-  /* If we are running confined in a Snap, also pass on fontconfig-related
-     environment variables and LD_LIBRARY_PATH */
-
   optstr = escape_options(num_options, options);
 
   snprintf(content_type, sizeof(content_type), "CONTENT_TYPE=%s/%s",
@@ -1058,20 +1050,8 @@ exec_filters(mime_type_t   *srctype,     /* I - Source type */
            ServerBin);
   snprintf(cups_serverroot, sizeof(cups_serverroot), "CUPS_SERVERROOT=%s",
            ServerRoot);
-#ifdef SUPPORT_SNAPPED_CUPSD
-  snprintf(fontconfig_file, sizeof(fontconfig_file), "FONTCONFIG_FILE=%s",
-           getenv("FONTCONFIG_FILE"));
-  snprintf(fontconfig_path, sizeof(fontconfig_path), "FONTCONFIG_PATH=%s",
-           getenv("FONTCONFIG_PATH"));
-  snprintf(fontconfig_sysroot, sizeof(fontconfig_sysroot),
-          "FONTCONFIG_SYSROOT=%s", getenv("FONTCONFIG_SYSROOT"));
-#endif /* SUPPORT_SNAPPED_CUPSD */
   language = cupsLangDefault();
   snprintf(lang, sizeof(lang), "LANG=%s.UTF8", language->language);
-#ifdef SUPPORT_SNAPPED_CUPSD
-  snprintf(ld_library_path, sizeof(ld_library_path), "LD_LIBRARY_PATH=%s",
-          getenv("LD_LIBRARY_PATH"));
-#endif /* SUPPORT_SNAPPED_CUPSD */
   snprintf(path, sizeof(path), "PATH=%s", Path);
   if (ppdfile)
     snprintf(ppd, sizeof(ppd), "PPD=%s", ppdfile);
@@ -1090,8 +1070,9 @@ exec_filters(mime_type_t   *srctype,      /* I - Source type */
                  "Versions/A/Frameworks/PrintCore.framework/Versions/A/"
                 "Resources/Generic.ppd", sizeof(ppd));
 #else
-    snprintf(ppd, sizeof(ppd), "PPD=%s/model/laserjet.ppd", DataDir);
+  snprintf(ppd, sizeof(ppd), "PPD=%s/model/laserjet.ppd", DataDir);
 #endif /* __APPLE__ */
+
   snprintf(userenv, sizeof(userenv), "USER=%s", user);
 
   if (printer &&
@@ -1134,52 +1115,54 @@ exec_filters(mime_type_t   *srctype,    /* I - Source type */
   if (!argv[4])
     argv[4] = "1";
 
-  envp[0]  = "<CFProcessPath>";
-  envp[1]  = content_type;
-  envp[2]  = cups_datadir;
-  envp[3]  = cups_fontpath;
-  envp[4]  = cups_serverbin;
-  envp[5]  = cups_serverroot;
-  envp[6]  = lang;
-  envp[7]  = path;
-#ifdef SUPPORT_SNAPPED_CUPSD
-  envp[8]  = ld_library_path;
-  envp[9]  = ppd;
-  envp[10] = printer_info;
-  envp[11] = printer_location;
-  envp[12] = printer_name;
-  envp[13] = rip_max_cache;
-  envp[14] = userenv;
-  envp[15] = "CHARSET=utf-8";
-  envp[16] = fontconfig_file;
-  envp[17] = fontconfig_path;
-  envp[18] = fontconfig_sysroot;
+  for (i = 0; argv[i]; i ++)
+    fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]);
+
+  i = 0;
+#ifdef __APPLE__
+  envp[i ++] = "<CFProcessPath>";
+#endif /* __APPLE__ */
+  envp[i ++] = content_type;
+  envp[i ++] = cups_datadir;
+  envp[i ++] = cups_fontpath;
+  envp[i ++] = cups_serverbin;
+  envp[i ++] = cups_serverroot;
+  envp[i ++] = lang;
+  envp[i ++] = path;
+  envp[i ++] = ppd;
+  envp[i ++] = printer_info;
+  envp[i ++] = printer_location;
+  envp[i ++] = printer_name;
+  envp[i ++] = rip_max_cache;
+  envp[i ++] = userenv;
+  envp[i ++] = "CHARSET=utf-8";
   if (final_content_type[0])
+    envp[i ++] = final_content_type;
+
+#if CUPS_SNAP
+  if ((temp = getenv("FONTCONFIG_FILE")) != NULL)
   {
-    envp[19] = final_content_type;
-    envp[20] = NULL;
+    snprintf(fontconfig_file, sizeof(fontconfig_file), "FONTCONFIG_FILE=%s", temp);
+    envp[i ++] = fontconfig_file;
   }
-  else
-    envp[19] = NULL;
-#else
-  envp[8]  = ppd;
-  envp[9]  = printer_info;
-  envp[10] = printer_location;
-  envp[11] = printer_name;
-  envp[12] = rip_max_cache;
-  envp[13] = userenv;
-  envp[14] = "CHARSET=utf-8";
-  if (final_content_type[0])
+  if ((temp = getenv("FONTCONFIG_PATH")) != NULL)
   {
-    envp[15] = final_content_type;
-    envp[16] = NULL;
+    snprintf(fontconfig_path, sizeof(fontconfig_path), "FONTCONFIG_PATH=%s", temp);
+    envp[i ++] = fontconfig_path;
   }
-  else
-    envp[15] = NULL;
-#endif /* SUPPORT_SNAPPED_CUPSD */
+  if ((temp = getenv("FONTCONFIG_SYSROOT")) != NULL)
+  {
+    snprintf(fontconfig_sysroot, sizeof(fontconfig_sysroot), "FONTCONFIG_SYSROOT=%s", temp);
+    envp[i ++] = fontconfig_sysroot;
+  }
+  if ((temp = getenv("LD_LIBRARY_PATH")) != NULL)
+  {
+    snprintf(ld_library_path, sizeof(ld_library_path), "LD_LIBRARY_PATH=%s", temp);
+    envp[i ++] = ld_library_path;
+  }
+#endif /* CUPS_SNAP */
 
-  for (i = 0; argv[i]; i ++)
-    fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]);
+  envp[i] = NULL;
 
   for (i = 0; envp[i]; i ++)
     fprintf(stderr, "DEBUG: envp[%d]=\"%s\"\n", i, envp[i]);
@@ -1497,14 +1480,12 @@ read_cups_files_conf(
     cupsFileClose(fp);
   }
 
-  /* Set the PATH environment variable for external executables, pass
-     through the PATH from the environment in which cupsd was called
-     if we are running confined in a Snap */
-#ifdef SUPPORT_SNAPPED_CUPSD
-  snprintf(line, sizeof(line), "%s/filter:%s:" CUPS_BINDIR ":" CUPS_SBINDIR ":/bin:/usr/bin", ServerBin, getenv("PATH"));
-#else
+#if CUPS_SNAP
+  if ((temp = getenv("PATH")) != NULL)
+    snprintf(line, sizeof(line), "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR ":%s", ServerBin, temp);
+  else
+#endif /* CUPS_SNAP */
   snprintf(line, sizeof(line), "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR ":/bin:/usr/bin", ServerBin);
-#endif /* SUPPORT_SNAPPED_CUPSD */
   set_string(&Path, line);
 
   return (0);
index 09d79676c96b48b887c931b0adba1eed101488d7..87b9cdd35b1be85922287713c77a57b1012aa00e 100644 (file)
@@ -116,14 +116,13 @@ cupsdSetEnv(const char *name,             /* I - Name of variable */
     return;
 
  /*
-  * Do not allow dynamic linker variables when running as root and
-  * not being confined in a Snap...
+  * Do not allow dynamic linker variables when running as root outside a Snap...
   */
 
-#ifndef SUPPORT_SNAPPED_CUPSD
+#if !CUPS_SNAP
   if (!RunUser && (!strncmp(name, "DYLD_", 5) || !strncmp(name, "LD_", 3)))
     return;
-#endif /* !SUPPORT_SNAPPED_CUPSD */
+#endif /* !CUPS_SNAP */
 
  /*
   * See if this variable has already been defined...
@@ -212,18 +211,16 @@ cupsdUpdateEnv(void)
   set_if_undefined("LD_LIBRARY_PATH", NULL);
   set_if_undefined("LD_PRELOAD", NULL);
   set_if_undefined("NLSPATH", NULL);
-  /* Only if cupsd is confined in a Snap we pass the PATH environment
-     variable on for external executables we call */
   if (find_env("PATH") < 0)
   {
-#ifdef SUPPORT_SNAPPED_CUPSD
-    char *value;
-    if ((value = getenv("PATH")) != NULL)
+#if CUPS_SNAP
+    const char *path;                  // PATH environment variable
+
+    if ((path = getenv("PATH")) != NULL)
       cupsdSetEnvf("PATH", "%s/filter:%s", ServerBin, value);
     else
-#endif /* SUPPORT_SNAPPED_CUPSD */
-      cupsdSetEnvf("PATH", "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR
-                  ":/bin:/usr/bin", ServerBin);
+#endif /* CUPS_SNAP */
+    cupsdSetEnvf("PATH", "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR ":/bin:/usr/bin", ServerBin);
   }
   set_if_undefined("SERVER_ADMIN", ServerAdmin);
   set_if_undefined("SHLIB_PATH", NULL);
index 3b09efe24c2dd071855a16bfa6a7279d707db2a9..d995be231e7b6ba6c9f450f3a79e12edd6616b9a 100644 (file)
@@ -1,10 +1,12 @@
 /*
  * Process management routines for the CUPS scheduler.
  *
- * Copyright 2007-2017 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * Copyright © 2021 by OpenPrinting.
+ * Copyright © 2007-2017 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
  *
- * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
  */
 
 /*
@@ -744,11 +746,11 @@ cupsdStartProcess(
     if (!RunUser && setgid(Group))
       exit(errno + 100);
 
-#  ifdef SUPPORT_SNAPPED_CUPSD
+#  if CUPS_SNAP
     if (!RunUser && setgroups(0, NULL))
 #  else
     if (!RunUser && setgroups(1, &Group))
-#  endif /* SUPPORT_SNAPPED_CUPSD */
+#  endif /* CUPS_SNAP */
       exit(errno + 100);
 
    /*