From: mike Date: Sat, 16 Apr 2011 01:25:40 +0000 (+0000) Subject: Normalize the permission checking code, and check permissions in more places. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4da946678c2ae9366976459b11de206c0dd6afdf;p=thirdparty%2Fcups.git Normalize the permission checking code, and check permissions in more places. git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@9692 7a7537e8-13f0-0310-91df-b6672ffda945 --- diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c index 3d6f113a4a..dd334a2076 100644 --- a/backend/usb-darwin.c +++ b/backend/usb-darwin.c @@ -1428,28 +1428,21 @@ static kern_return_t load_classdriver(CFStringRef driverPath, return (kr); } else if (bundleinfo.st_uid || - (bundleinfo.st_gid && (bundleinfo.st_mode & S_IWGRP)) || + (bundleinfo.st_gid && bundleinfo.st_gid != 80 && + (bundleinfo.st_mode & S_IWGRP)) || + (bundleinfo.st_mode & S_ISUID) || (bundleinfo.st_mode & S_IWOTH)) { fprintf(stderr, "DEBUG: Class driver \"%s\" has insecure file " "permissions (0%o/uid=%d/gid=%d).\n", bundlestr, bundleinfo.st_mode, (int)bundleinfo.st_uid, (int)bundleinfo.st_gid); - if (bundleinfo.st_uid || - (bundleinfo.st_gid && bundleinfo.st_gid != 80 && - (bundleinfo.st_mode & S_IWGRP)) || - (bundleinfo.st_mode & (S_ISUID | S_IWOTH))) - fputs("STATE: +cups-insecure-filter-warning\n", stderr); - - if (bundleinfo.st_uid || - (bundleinfo.st_gid && bundleinfo.st_gid != 80 && - (bundleinfo.st_mode & S_IWOTH))) - { - if (driverPath) - return (load_classdriver(NULL, intf, printerDriver)); - else - return (kr); - } + fputs("STATE: +cups-insecure-filter-warning\n", stderr); + + if (driverPath) + return (load_classdriver(NULL, intf, printerDriver)); + else + return (kr); } /* diff --git a/scheduler/conf.h b/scheduler/conf.h index c3479e1720..e4725ff82a 100644 --- a/scheduler/conf.h +++ b/scheduler/conf.h @@ -268,6 +268,7 @@ extern int cupsdCheckPermissions(const char *filename, const char *suffix, int mode, int user, int group, int is_dir, int create_dir); +extern int cupsdCheckProgram(const char *filename, cupsd_printer_t *p); extern void cupsdFreeAliases(cups_array_t *aliases); extern char *cupsdGetDateTime(struct timeval *t, cupsd_time_t format); #ifdef HAVE_GSSAPI diff --git a/scheduler/cups-deviced.c b/scheduler/cups-deviced.c index 62bf20801d..f2d99c8a71 100644 --- a/scheduler/cups-deviced.c +++ b/scheduler/cups-deviced.c @@ -3,7 +3,7 @@ * * Device scanning mini-daemon for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -767,6 +767,9 @@ start_backend(const char *name, /* I - Backend to run */ snprintf(program, sizeof(program), "%s/backend/%s", server_bin, name); + if (!cupsdCheckProgram(program)) + return (-1); + backend = backends + num_backends; argv[0] = (char *)name; diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx index 8f78df3b86..58ceb8c369 100644 --- a/scheduler/cups-driverd.cxx +++ b/scheduler/cups-driverd.cxx @@ -1606,9 +1606,13 @@ load_drivers(cups_array_t *include, /* I - Drivers to include */ * Run the driver with no arguments and collect the output... */ - argv[0] = dent->filename; snprintf(filename, sizeof(filename), "%s/%s", drivers, dent->filename); + if (!cupsdCheckProgram(filename)) + continue; + + argv[0] = dent->filename; + if ((fp = cupsdPipeCommand(&pid, filename, argv, 0)) != NULL) { while (cupsFileGets(fp, line, sizeof(line))) diff --git a/scheduler/printers.c b/scheduler/printers.c index 8d9a7f78b2..f705bf3bb6 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -3563,9 +3563,8 @@ add_printer_filter( size_t maxsize = 0; /* Maximum supported file size */ mime_type_t *temptype, /* MIME type looping var */ *desttype; /* Destination MIME type */ - char filename[1024], /* Full filter filename */ - *dirsep; /* Pointer to directory separator */ - struct stat fileinfo; /* File information */ + mime_filter_t *filterptr; /* MIME filter */ + char filename[1024]; /* Full filter filename */ cupsdLogMessage(CUPSD_LOG_DEBUG2, @@ -3633,8 +3632,7 @@ add_printer_filter( } /* - * See if the filter program exists; if not, stop the printer and flag - * the error! + * Check permissions on the filter and its containing directory... */ if (strcmp(program, "-")) @@ -3644,74 +3642,7 @@ add_printer_filter( else snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program); - if (stat(filename, &fileinfo)) - { - memset(&fileinfo, 0, sizeof(fileinfo)); - - snprintf(p->state_message, sizeof(p->state_message), - "Printer driver \"%s\" not available: %s", filename, - strerror(errno)); - cupsdSetPrinterReasons(p, "+cups-missing-filter-warning"); - - cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message); - } - - /* - * When running as root, do additional security checks... - */ - - else if (!RunUser) - { - /* - * Only use filters that are owned by root and do not have world write - * permissions. - */ - - if (fileinfo.st_uid || - (fileinfo.st_gid && (fileinfo.st_mode & S_IWGRP)) || - (fileinfo.st_mode & (S_ISUID | S_IWOTH)) != 0) - { - snprintf(p->state_message, sizeof(p->state_message), - "Printer driver \"%s\" has insecure permissions " - "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode, - (int)fileinfo.st_uid, (int)fileinfo.st_gid); - -#ifdef __APPLE__ /* Don't flag filters with group write for "admin" */ - if (fileinfo.st_uid || - (fileinfo.st_gid && fileinfo.st_gid != 80 && - (fileinfo.st_mode & S_IWGRP)) || - (fileinfo.st_mode & (S_ISUID | S_IWOTH))) -#endif /* __APPLE__ */ - cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning"); - - cupsdLogMessage(CUPSD_LOG_WARN, "%s: %s", p->name, p->state_message); - } - else if (fileinfo.st_mode) - { - /* - * Similarly, check that the parent directory is also owned by root and - * does not have world write permissions. - */ - - if ((dirsep = strrchr(filename, '/')) != NULL) - *dirsep = '\0'; - - if (!stat(filename, &fileinfo) && - (fileinfo.st_uid || - (fileinfo.st_gid && (fileinfo.st_mode & S_IWGRP)) || - (fileinfo.st_mode & (S_ISUID | S_IWOTH)) != 0)) - { - snprintf(p->state_message, sizeof(p->state_message), - "Printer driver directory \"%s\" has insecure permissions " - "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode, - (int)fileinfo.st_uid, (int)fileinfo.st_gid); - - cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning"); - - cupsdLogMessage(CUPSD_LOG_WARN, "%s: %s", p->name, p->state_message); - } - } - } + cupsdCheckProgram(filename, p); } /* @@ -3732,7 +3663,8 @@ add_printer_filter( "%s", p->name, temptype->super, temptype->type, desttype->super, desttype->type, cost, program); - mimeAddFilter(MimeDatabase, temptype, desttype, cost, program); + filterptr = mimeAddFilter(MimeDatabase, temptype, desttype, cost, + program); if (!mimeFilterLookup(MimeDatabase, desttype, filtertype)) { @@ -3750,8 +3682,12 @@ add_printer_filter( "%s", p->name, temptype->super, temptype->type, filtertype->super, filtertype->type, cost, program); - mimeAddFilter(MimeDatabase, temptype, filtertype, cost, program); + filterptr = mimeAddFilter(MimeDatabase, temptype, filtertype, cost, + program); } + + if (filterptr) + filterptr->maxsize = maxsize; } } diff --git a/scheduler/process.c b/scheduler/process.c index 0bd534639b..4063dac37f 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -14,6 +14,8 @@ * * Contents: * + * cupsdCheckProgram() - Check the permissions of the given program and its + * containing directory. * cupsdCreateProfile() - Create an execution profile for a subprocess. * cupsdDestroyProfile() - Delete an execution profile. * cupsdEndProcess() - End a process. @@ -63,6 +65,201 @@ static char *cupsd_requote(char *dst, const char *src, size_t dstsize); #endif /* HAVE_SANDBOX_H */ +/* + * 'cupsdCheckProgram()' - Check the permissions of the given program and its + * containing directory. + */ + +int /* O - 1 if OK, 0 if not OK */ +cupsdCheckProgram( + const char *filename, /* I - Filename to check */ + cupsd_printer_t *p) /* I - Printer, if any */ +{ + struct stat fileinfo; /* File information */ + char temp[1024], /* Parent directory filename */ + *ptr; /* Pointer into parent directory */ + + + /* + * Does the program even exist and is it accessible? + */ + + if (stat(filename, &fileinfo)) + { + /* + * Nope... + */ + + if (p) + { + snprintf(p->state_message, sizeof(p->state_message), + "Printer driver \"%s\" not available: %s", filename, + strerror(errno)); + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message); + + if (cupsdSetPrinterReasons(p, "+cups-missing-filter-warning")) + cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, p, NULL, + "Printer driver \"%s\" not available.", filename); + } + else + cupsdLogMessage(CUPSD_LOG_ERROR, "Program \"%s\" not available: %s", + filename, strerror(errno)); + + return (0); + } + + /* + * Are we running as root? + */ + + if (RunUser) + { + /* + * Nope, so anything goes... + */ + + return (1); + } + + /* + * Verify permission of the program itself: + * + * 1. Must be owned by root + * 2. Must not be writable by group unless group is root/wheel/admin + * 3. Must not be setuid + * 4. Must not be writable by others + */ + + if (fileinfo.st_uid || /* 1. Must be owned by root */ +#ifdef __APPLE__ + ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid && + fileinfo.st_gid != 80) || /* 2. Must not be writable by group */ +#else + ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid) || + /* 2. Must not be writable by group */ +#endif /* __APPLE__ */ + (fileinfo.st_mode & S_ISUID) || /* 3. Must not be setuid */ + (fileinfo.st_mode & S_IWOTH)) /* 4. Must not be writable by others */ + { + if (p) + { + snprintf(p->state_message, sizeof(p->state_message), + "Printer driver \"%s\" has insecure permissions " + "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode, + (int)fileinfo.st_uid, (int)fileinfo.st_gid); + + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message); + + if (cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning")) + cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, p, NULL, "%s", + p->state_message); + } + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Program \"%s\" has insecure permissions " + "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode, + (int)fileinfo.st_uid, (int)fileinfo.st_gid); + + errno = EPERM; + + return (0); + } + + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "%s%s \"%s\" permissions OK " + "(0%o/uid=%d/gid=%d).", p ? p->name : "", + p ? ": Printer driver" : "Program", filename, + fileinfo.st_mode, (int)fileinfo.st_uid, + (int)fileinfo.st_gid); + + /* + * Now check the containing directory... + */ + + strlcpy(temp, filename, sizeof(temp)); + if ((ptr = strrchr(temp, '/')) != NULL) + { + if (ptr == temp) + ptr[1] = '\0'; + else + *ptr = '\0'; + } + + if (stat(temp, &fileinfo)) + { + /* + * Doesn't exist... + */ + + if (p) + { + snprintf(p->state_message, sizeof(p->state_message), + "Printer driver directory \"%s\" not available: %s", temp, + strerror(errno)); + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message); + + if (cupsdSetPrinterReasons(p, "+cups-missing-filter-warning")) + cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, p, NULL, + "Printer driver directory \"%s\" not available.", temp); + } + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Program directory \"%s\" not available: %s", temp, + strerror(errno)); + + return (0); + } + + if (fileinfo.st_uid || /* 1. Must be owned by root */ +#ifdef __APPLE__ + ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid && + fileinfo.st_gid != 80) || /* 2. Must not be writable by group */ +#else + ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid) || + /* 2. Must not be writable by group */ +#endif /* __APPLE__ */ + (fileinfo.st_mode & S_ISUID) || /* 3. Must not be setuid */ + (fileinfo.st_mode & S_IWOTH)) /* 4. Must not be writable by others */ + { + if (p) + { + snprintf(p->state_message, sizeof(p->state_message), + "Printer driver directory \"%s\" has insecure permissions " + "(0%o/uid=%d/gid=%d).", temp, fileinfo.st_mode, + (int)fileinfo.st_uid, (int)fileinfo.st_gid); + + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message); + + if (cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning")) + cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, p, NULL, "%s", + p->state_message); + } + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Program directory \"%s\" has insecure permissions " + "(0%o/uid=%d/gid=%d).", temp, fileinfo.st_mode, + (int)fileinfo.st_uid, (int)fileinfo.st_gid); + + errno = EPERM; + + return (0); + } + + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "%s%s directory \"%s\" permissions OK " + "(0%o/uid=%d/gid=%d).", p ? p->name : "", + p ? ": Printer driver" : "Program", temp, + fileinfo.st_mode, (int)fileinfo.st_uid, + (int)fileinfo.st_gid); + + /* + * If we get here then we can "safely" run this program... + */ + + return (1); +} + + /* * 'cupsdCreateProfile()' - Create an execution profile for a subprocess. */ @@ -317,7 +514,6 @@ cupsdStartProcess( char *real_argv[103], /* Real command-line arguments */ cups_exec[1024]; /* Path to "cups-exec" program */ int user; /* Command UID */ - struct stat commandinfo; /* Command file information */ cupsd_proc_t *proc; /* New process record */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* POSIX signal handler */ @@ -329,6 +525,8 @@ cupsdStartProcess( #endif /* __APPLE__ */ + *pid = 0; + /* * Figure out the UID for the child process... */ @@ -344,110 +542,8 @@ cupsdStartProcess( * Check the permissions of the command we are running... */ - if (stat(command, &commandinfo)) - { - *pid = 0; - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, " - "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, " - "profile=%p, job=%p(%d), pid=%p) = %d", - command, argv, envp, infd, outfd, errfd, backfd, sidefd, - root, profile, job, job ? job->id : 0, pid, *pid); - cupsdLogMessage(CUPSD_LOG_ERROR, - "%s%s \"%s\" not available: %s", - job && job->printer ? job->printer->name : "", - job && job->printer ? ": Printer driver" : "Program", - command, strerror(errno)); - - if (job && job->printer) - { - if (cupsdSetPrinterReasons(job->printer, "+cups-missing-filter-warning")) - cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, job->printer, NULL, - "Printer driver \"%s\" not available.", command); - } - - return (0); - } - else if (!RunUser && - ((commandinfo.st_mode & (S_ISUID | S_IWOTH)) || - commandinfo.st_uid)) - { - *pid = 0; - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, " - "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, " - "profile=%p, job=%p(%d), pid=%p) = %d", - command, argv, envp, infd, outfd, errfd, backfd, sidefd, - root, profile, job, job ? job->id : 0, pid, *pid); - cupsdLogMessage(CUPSD_LOG_ERROR, - "%s%s \"%s\" has insecure permissions " - "(0%o/uid=%d/gid=%d).", - job && job->printer ? job->printer->name : "", - job && job->printer ? ": Printer driver" : "Program", - command, commandinfo.st_mode, - (int)commandinfo.st_uid, (int)commandinfo.st_gid); - - if (job && job->printer) - { - if (cupsdSetPrinterReasons(job->printer, "+cups-insecure-filter-warning")) - cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, job->printer, NULL, - "Printer driver \"%s\" has insecure permissions " - "(0%o/uid=%d/gid=%d).", command, commandinfo.st_mode, - (int)commandinfo.st_uid, (int)commandinfo.st_gid); - } - - errno = EPERM; - - return (0); - } - else if ((commandinfo.st_uid != user || !(commandinfo.st_mode & S_IXUSR)) && - (commandinfo.st_gid != Group || !(commandinfo.st_mode & S_IXGRP)) && - !(commandinfo.st_mode & S_IXOTH)) - { - *pid = 0; - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, " - "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, " - "profile=%p, job=%p(%d), pid=%p) = %d", - command, argv, envp, infd, outfd, errfd, backfd, sidefd, - root, profile, job, job ? job->id : 0, pid, *pid); - cupsdLogMessage(CUPSD_LOG_ERROR, - "%s%s \"%s\" does not have execute permissions " - "(0%o/uid=%d/gid=%d).", - job && job->printer ? job->printer->name : "", - job && job->printer ? ": Printer driver" : "Program", - command, commandinfo.st_mode, (int)commandinfo.st_uid, - (int)commandinfo.st_gid); - - errno = EPERM; + if (!cupsdCheckProgram(command, job ? job->printer : NULL)) return (0); - } - else if (!RunUser && commandinfo.st_gid && (commandinfo.st_mode & S_IWGRP)) - { - cupsdLogMessage(CUPSD_LOG_WARN, - "%s%s \"%s\" has insecure permissions " - "(0%o/uid=%d/gid=%d).", - job && job->printer ? job->printer->name : "", - job && job->printer ? ": Printer driver" : "Program", - command, commandinfo.st_mode, - (int)commandinfo.st_uid, (int)commandinfo.st_gid); - -#ifdef __APPLE__ /* Don't flag filters with group write for "admin" */ - if (commandinfo.st_gid != 80 && job && job->printer) -#else - if (job && job->printer) -#endif /* __APPLE__ */ - { - if (cupsdSetPrinterReasons(job->printer, "+cups-insecure-filter-warning")) - cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, job->printer, NULL, - "Printer driver \"%s\" has insecure permissions " - "(0%o/uid=%d/gid=%d).", command, commandinfo.st_mode, - (int)commandinfo.st_uid, (int)commandinfo.st_gid); - } - } #if defined(__APPLE__) if (envp) diff --git a/scheduler/util.c b/scheduler/util.c index c0006efa8b..ee3404f513 100644 --- a/scheduler/util.c +++ b/scheduler/util.c @@ -3,7 +3,7 @@ * * Mini-daemon utility functions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -14,6 +14,8 @@ * * Contents: * + * cupsdCheckProgram() - Check the permissions of the given program and + * its containing directory. * cupsdCompareNames() - Compare two names. * cupsdCreateStringsArray() - Create a CUPS array of strings. * cupsdExec() - Run a program with the correct environment. @@ -39,6 +41,145 @@ extern char **environ; #endif /* __APPLE__ */ +/* + * 'cupsdCheckProgram()' - Check the permissions of the given program and its + * containing directory. + * + * Note: This function is a parallel implementation of the scheduler function + * of the same name. + */ + +int /* O - 1 if OK, 0 if not OK */ +cupsdCheckProgram( + const char *filename) /* I - Filename to check */ +{ + struct stat fileinfo; /* File information */ + char temp[1024], /* Parent directory filename */ + *ptr; /* Pointer into parent directory */ + + + /* + * Does the program even exist and is it accessible? + */ + + if (stat(filename, &fileinfo)) + { + /* + * Nope... + */ + + fprintf(stderr, "ERROR: Program \"%s\" not available: %s", filename, + strerror(errno)); + + return (0); + } + + /* + * Are we running as root? + */ + + if (geteuid()) + { + /* + * Nope, so anything goes... + */ + + return (1); + } + + /* + * Verify permission of the program itself: + * + * 1. Must be owned by root + * 2. Must not be writable by group unless group is root/wheel/admin + * 3. Must not be setuid + * 4. Must not be writable by others + */ + + if (fileinfo.st_uid || /* 1. Must be owned by root */ +#ifdef __APPLE__ + ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid && + fileinfo.st_gid != 80) || /* 2. Must not be writable by group */ +#else + ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid) || + /* 2. Must not be writable by group */ +#endif /* __APPLE__ */ + (fileinfo.st_mode & S_ISUID) || /* 3. Must not be setuid */ + (fileinfo.st_mode & S_IWOTH)) /* 4. Must not be writable by others */ + { + fprintf(stderr, + "ERROR: Program \"%s\" has insecure permissions " + "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode, + (int)fileinfo.st_uid, (int)fileinfo.st_gid); + + errno = EPERM; + + return (0); + } + + fprintf(stderr, "DEBUG2: Program \"%s\" permissions OK (0%o/uid=%d/gid=%d).", + filename, fileinfo.st_mode, (int)fileinfo.st_uid, + (int)fileinfo.st_gid); + + /* + * Now check the containing directory... + */ + + strlcpy(temp, filename, sizeof(temp)); + if ((ptr = strrchr(temp, '/')) != NULL) + { + if (ptr == temp) + ptr[1] = '\0'; + else + *ptr = '\0'; + } + + if (stat(temp, &fileinfo)) + { + /* + * Doesn't exist... + */ + + fprintf(stderr, "ERROR: Program directory \"%s\" not available: %s", temp, + strerror(errno)); + + return (0); + } + + if (fileinfo.st_uid || /* 1. Must be owned by root */ +#ifdef __APPLE__ + ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid && + fileinfo.st_gid != 80) || /* 2. Must not be writable by group */ +#else + ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid) || + /* 2. Must not be writable by group */ +#endif /* __APPLE__ */ + (fileinfo.st_mode & S_ISUID) || /* 3. Must not be setuid */ + (fileinfo.st_mode & S_IWOTH)) /* 4. Must not be writable by others */ + { + fprintf(stderr, + "ERROR: Program directory \"%s\" has insecure permissions " + "(0%o/uid=%d/gid=%d).", temp, fileinfo.st_mode, + (int)fileinfo.st_uid, (int)fileinfo.st_gid); + + errno = EPERM; + + return (0); + } + + fprintf(stderr, + "DEBUG2: Program directory \"%s\" permissions OK " + "(0%o/uid=%d/gid=%d).", temp, fileinfo.st_mode, (int)fileinfo.st_uid, + (int)fileinfo.st_gid); + + /* + * If we get here then we can "safely" run this program... + */ + + return (1); +} + + /* * 'cupsdCompareNames()' - Compare two names. * diff --git a/scheduler/util.h b/scheduler/util.h index ad4172f69a..d62e7947ce 100644 --- a/scheduler/util.h +++ b/scheduler/util.h @@ -3,7 +3,7 @@ * * Mini-daemon utility definitions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -44,6 +44,7 @@ typedef int (*cupsd_compare_func_t)(const void *, const void *); * Prototypes... */ +extern int cupsdCheckProgram(const char *filename); extern int cupsdCompareNames(const char *s, const char *t); extern cups_array_t *cupsdCreateStringsArray(const char *s); extern int cupsdExec(const char *command, char **argv);