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"
])
ONDEMANDFLAGS
SNAPDGLIBLIBS
APPARMORLIBS
-SNAPCTL
IPPFIND_MAN
IPPFIND_BIN
DNSSD_BACKEND
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
--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
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
{ 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 :
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=""
* 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 */
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);
}
}
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);
}
}
/*
- * '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
}
/*
* 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.
*/
/*
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 */
# 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 */
/*
/* 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]);
acl_free(acl);
}
# endif /* HAVE_ACL_INIT */
-#endif /* SUPPORT_SNAPPED_CUPSD */
+#endif /* CUPS_SNAP */
RootCertTime = time(NULL);
}
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,
/*
* 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:
*
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))
{
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 */
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 */
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 */
* 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",
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);
"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 &&
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]);
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);
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...
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);
/*
* 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.
*/
/*
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);
/*