Mailinglist Archive: opensuse-commit (1023 mails)

< Previous Next >
commit permissions for openSUSE:Factory
  • From: root@xxxxxxxxxxxxxxx (h_root)
  • Date: Wed, 10 Nov 2010 20:26:53 +0100
  • Message-id: <20101110192653.AC0BC2020D@xxxxxxxxxxxxxxx>

Hello community,

here is the log from the commit of package permissions for openSUSE:Factory
checked in at Wed Nov 10 20:26:53 CET 2010.



--------
--- permissions/permissions.changes 2010-10-18 15:38:41.000000000 +0200
+++ permissions/permissions.changes 2010-11-09 13:51:35.000000000 +0100
@@ -1,0 +2,30 @@
+Tue Nov 9 12:51:10 UTC 2010 - lnussel@xxxxxxx
+
+- add permissions man page
+- update docu
+- add --level option
+- set perms for setuid files always if owner changes
+- strip root dir when printing file names
+
+-------------------------------------------------------------------
+Tue Nov 9 09:25:17 UTC 2010 - lnussel@xxxxxxx
+
+- add option to explicitly warn only
+
+-------------------------------------------------------------------
+Fri Nov 5 14:00:30 UTC 2010 - lnussel@xxxxxxx
+
+- reimplement the core features in chkstat itself instead of
+ SuSEconfig.permissions
+
+-------------------------------------------------------------------
+Thu Nov 4 16:17:25 UTC 2010 - lnussel@xxxxxxx
+
+- don't make changes if not called explicitly
+
+-------------------------------------------------------------------
+Wed Nov 3 14:16:54 UTC 2010 - lnussel@xxxxxxx
+
+- add support for file system capabilities
+
+-------------------------------------------------------------------

calling whatdependson for head-i586


Old:
----
permissions-2010.10.18.1537.tar.bz2

New:
----
permissions-2010.11.09.1206.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ permissions.spec ++++++
--- /var/tmp/diff_new_pack.QcgxAn/_old 2010-11-10 20:21:57.000000000 +0100
+++ /var/tmp/diff_new_pack.QcgxAn/_new 2010-11-10 20:21:57.000000000 +0100
@@ -1,5 +1,5 @@
#
-# spec file for package permissions (Version 2010.10.18.1537)
+# spec file for package permissions (Version 2010.11.09.1206)
#
# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany.
#
@@ -18,12 +18,13 @@
# norootforbuild
# icecream 0

+BuildRequires: libcap-devel

Name: permissions
License: GPLv2+
Group: Productivity/Security
AutoReqProv: on
-Version: 2010.10.18.1537
+Version: 2010.11.09.1206
Release: 1
Provides: aaa_base:/etc/permissions
Requires: /sbin/SuSEconfig
@@ -68,6 +69,7 @@
%config /etc/permissions.paranoid
%config(noreplace) /etc/permissions.local
%{_bindir}/chkstat
+%{_mandir}/man5/permissions.5*
%{_mandir}/man8/chkstat.8*
/sbin/conf.d/SuSEconfig.permissions
/var/adm/fillup-templates/sysconfig.security

++++++ permissions-2010.10.18.1537.tar.bz2 ->
permissions-2010.11.09.1206.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/permissions-2010.10.18.1537/Makefile
new/permissions-2010.11.09.1206/Makefile
--- old/permissions-2010.10.18.1537/Makefile 2010-10-18 15:37:12.000000000
+0200
+++ new/permissions-2010.11.09.1206/Makefile 2010-11-09 12:06:11.000000000
+0100
@@ -1,6 +1,7 @@
CFLAGS=-W -Wall -g -O2
CC=gcc
DESTDIR=
+LDLIBS=-lcap
prefix=/usr
sysconfdir=/etc
bindir=$(prefix)/bin
@@ -9,15 +10,17 @@
datadir=$(prefix)/share
mandir=$(datadir)/man
man8dir=$(mandir)/man8
+man5dir=$(mandir)/man5

all: chkstat

install: all
- @for i in $(bindir) $(suseconfigdir) $(man8dir) $(fillupdir)
$(sysconfdir); \
+ @for i in $(bindir) $(suseconfigdir) $(man8dir) $(man5dir) $(fillupdir)
$(sysconfdir); \
do install -d -m 755 $(DESTDIR)$$i; done
@install -m 755 chkstat $(DESTDIR)$(bindir)
@install -m 755 SuSEconfig.permissions $(DESTDIR)$(suseconfigdir)
@install -m 644 chkstat.8 $(DESTDIR)$(man8dir)
+ @install -m 644 permissions.5 $(DESTDIR)$(man5dir)
@install -m 644 sysconfig.security $(DESTDIR)$(fillupdir)
@for i in permissions{,.local,.easy,.secure,.paranoid}; \
do install -m 644 $$i $(DESTDIR)$(sysconfdir); done
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/permissions-2010.10.18.1537/SuSEconfig.permissions
new/permissions-2010.11.09.1206/SuSEconfig.permissions
--- old/permissions-2010.10.18.1537/SuSEconfig.permissions 2010-10-18
15:37:12.000000000 +0200
+++ new/permissions-2010.11.09.1206/SuSEconfig.permissions 2010-11-09
12:06:11.000000000 +0100
@@ -24,63 +24,9 @@

. /lib/YaST/SuSEconfig.functions || exit 1

-for i in /etc/sysconfig/security /etc/sysconfig/suseconfig ; do
- . $i || exit 1
-done
-
if test -n "$ENABLE_SUSECONFIG" -a "$ENABLE_SUSECONFIG" = "no" ; then
echo "SuSEconfig is disabled in /etc/sysconfig/suseconfig"
exit 0
fi

-mode=""
-case "$CHECK_PERMISSIONS" in
- set) mode="-set" ;;
- warn) ;;
- no|"") exit 0 ;;
- *) echo "invalid value '$CHECK_PERMISSIONS' for \$CHECK_PERMISSIONS" >&2 ;;
-esac
-
-
-
-# collect files that contain permission specifications
-#
-# 1. central fixed permissions file
-files="/etc/permissions"
-
-# 2. central easy, secure paranoid as those are defined by SUSE
-for level in $PERMISSION_SECURITY; do
- case "$level" in
- easy|secure|paranoid)
- if [ -e /etc/permissions.$level ]; then
- files="$files /etc/permissions.$level"
- fi
- ;;
- esac
-done
-
-# 3. package specific permissions
-pkgfiles=(/etc/permissions.d/*)
-pkgfiles=(${pkgfiles[*]##*/})
-pkgfiles=(${pkgfiles[*]%%.*})
-pkgfiles=(`for i in ${pkgfiles[@]}; do echo $i; done | /usr/bin/sort -u`)
-
-for file in ${pkgfiles[@]}; do
- file=/etc/permissions.d/$file
- [ -e $file ] && files="$files $file"
- for level in $PERMISSION_SECURITY; do
- [ -e $file.$level ] && files="$files $file.$level"
- done
-done
-
-# 4. central permissions files with user defined level incl 'local'
-for level in $PERMISSION_SECURITY; do
- case "$level" in
- easy|secure|paranoid) continue ;;
- esac
- if [ -e /etc/permissions.$level ]; then
- files="$files /etc/permissions.$level"
- fi
-done
-
-/usr/bin/chkstat $mode $files
+/usr/bin/chkstat --suseconfig $mode
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/permissions-2010.10.18.1537/checkpermissionfiles.pl
new/permissions-2010.11.09.1206/checkpermissionfiles.pl
--- old/permissions-2010.10.18.1537/checkpermissionfiles.pl 2010-10-18
15:37:12.000000000 +0200
+++ new/permissions-2010.11.09.1206/checkpermissionfiles.pl 2010-11-09
12:06:11.000000000 +0100
@@ -87,8 +87,11 @@
{
chomp;
s/#.*//;
+ s/^\s.*//;
next if(/^$/);

+ next if(/^\+/); # XXX ext line
+
my ($file, $owner, $mode) = split(/\s+/);

if(!$nodups && exists($perms{$file}{$level}))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/permissions-2010.10.18.1537/chkstat.8
new/permissions-2010.11.09.1206/chkstat.8
--- old/permissions-2010.10.18.1537/chkstat.8 2010-10-18 15:37:12.000000000
+0200
+++ new/permissions-2010.11.09.1206/chkstat.8 2010-11-09 12:06:11.000000000
+0100
@@ -3,7 +3,7 @@
.\"
.\" Author: Ruediger Oertel
.\"
-.TH CHKSTAT 8 "2008-04-17" "SUSE Linux" "Tool to check and set file
permissions"
+.TH CHKSTAT 8 "2010-11-09" "SUSE Linux" "Tool to check and set file
permissions"
.\"
.UC 8
.SH NAME
@@ -12,67 +12,81 @@
.SH SYNOPSIS
.\"
.B chkstat
-.RB \|[\| \-\-set|\-set ]
-.RB \|[\| \-\-noheader ]
-.RB \|[\|\|[\| \-\-examine\ file\ ] ... ]
-.RB \|[\|\|[\| \-\-files\ filelist\ ] ... ]
-.RB \|[\|\|[\| \-\-root\ directory\ ] ... ]
-.B permission-file ...
+.RB [OPTIONS]
+.B <permission-files...>
+
+.B chkstat
+.RB \-\-system
+.RB [OPTIONS]
+.B <files...>
.\"
.SH DESCRIPTION
The program
.I /usr/bin/chkstat
is a tool to check and set file permissions.
.PP
-Multiple permissions files can be given on the commandline.
-If the permission files contain multiple entries for a single
-file, the last entry found will be used.
+chkstat can either operate in system mode or on individually
+specified permission files. In system mode /etc/permissions/security
+determines which level to use and whether to actually apply
+permission changes.
.PP
.\"
-.SS General Options
+.SS OPTIONS
+.TP
+.IR \-\-system
+Run in system mode. Parses \fI/etc/sysconfig/security\fR to
+determine which security level to use (\fIPERMISSION_SECURITY\fR)
+and whether to set or merely warn about permission changes
+(\fICHECK_PERMISSIONS\fR). In system mode non-option arguments refer
+to files. Ie just as if the \-\-examine option was specified for them.
.TP
-.IR \-\-set ,\ \-set
-This option enables setting the file permissions,
-the default is to check and warn only.
+.IR \-\-set
+Actually apply the file permissions. The default is to check and
+warn only unless in system mode where \fICHECK_PERMISSIONS\fR
+specifies the default behavior.
+.TP
+.IR \-\-warn
+Opposite of --set, ie warn only but don't make actual changes
.TP
.IR \-\-noheader
Omit printing the output header lines.
.TP
+.IR \-\-fscaps,\ \-\-no\-fscaps
+Force or disable use of fscaps. Default is to automatically
+determine whether the running kernel supports fscaps.
+.TP
.IR \-\-examine\ file
-Check permissions for this file and not all files listed in the permissions
files.
+Check permissions for this file instead of all files listed in the permissions
files.
.TP
.IR \-\-files\ filelist
Check permissions for the files listed in
.IR filelist
-and not for all files listed in the permissions files.
+and instead of all files listed in the permissions files.
.TP
.IR \-\-root\ directory
-Prefix the files given in the permissions files by this directory.
-.PP
-.SH EXAMPLE
+Check files relative to the specified directory.
.PP
-The command
+.SH EXAMPLES
.PP
-.RS
-.B chkstat -set /etc/permissions
-.RE
+.B chkstat --set /etc/permissions /etc/permissions.secure
.PP
-will parse the file /etc/permissions and set the access mode and the
-user- and group memberships each file listed. The format
-for the input file is
+parses the files /etc/permissions and /etc/permissions and sets the
+access mode and the user- and group memberships for each file listed.
.PP
-.B FILEPATH
-.B OWNER:GROUP
-.B MODE
+.B chkstat --system /bin/ping
.PP
-and wildcards are not supported for the filepath. Lines starting
-with '#' and empty lines are treated as comments.
+Run in system mode and only correct permissions of /bin/ping
+.
+.SH "SEE ALSO"
+.sp
+permissions(5)
+.
.SH COPYRIGHT
1996-2003 SuSE Linux AG, Nuernberg, Germany.

-2008 SUSE LINUX Products GmbH
+2008-2010 SUSE LINUX Products GmbH
.SH AUTHORS
-Reinhold Sojer, Ruediger Oertel, Michael Schroeder
+Reinhold Sojer, Ruediger Oertel, Michael Schroeder, Ludwig Nussel
.PP
Useful changes and additions by Tobias Burnus

diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/permissions-2010.10.18.1537/chkstat.c
new/permissions-2010.11.09.1206/chkstat.c
--- old/permissions-2010.10.18.1537/chkstat.c 2010-10-18 15:37:12.000000000
+0200
+++ new/permissions-2010.11.09.1206/chkstat.c 2010-11-09 12:06:11.000000000
+0100
@@ -27,9 +27,13 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <dirent.h>
+#include <sys/capability.h>
#define __USE_GNU
#include <fcntl.h>

+#define BAD_LINE() \
+ fprintf(stderr, "bad permissions line %s:%d\n", argv[i], lcnt);

struct perm {
struct perm *next;
@@ -37,6 +41,7 @@
char *owner;
char *group;
mode_t mode;
+ cap_t caps;
};

struct perm *permlist;
@@ -45,8 +50,15 @@
uid_t euid;
char *root;
int rootl;
+int nlevel;
+char** level;
+int do_set = -1;
+int default_set = 0;
+char** permfiles = NULL;
+int npermfiles = 0;
+char* force_level;

-void
+struct perm*
add_permlist(char *file, char *owner, char *group, mode_t mode)
{
struct perm *ec, **epp;
@@ -94,8 +106,10 @@
ec->owner = owner;
ec->group = group;
ec->mode = mode;
+ ec->caps = NULL;
ec->next = 0;
*epp = ec;
+ return ec;
}

int
@@ -155,10 +169,244 @@
return 1;
}

+int
+in_level(char *e)
+{
+ int i;
+ for (i = 0; i < nlevel; i++)
+ if (!strcmp(e, level[i]))
+ return 1;
+ return 0;
+}
+
+void
+ensure_array(void** array, int* size)
+{
+ if ((*size & 63) == 0)
+ {
+ if (*array == NULL)
+ *array = malloc(sizeof(char *) * (*size + 64));
+ else
+ *array = realloc(*array, sizeof(char *) * (*size + 64));
+ if (*array == NULL)
+ {
+ perror("array alloc");
+ exit(1);
+ }
+ }
+}
+
+void
+add_level(char *e)
+{
+ if (in_level(e))
+ return;
+ e = strdup(e);
+ if (e == 0)
+ {
+ perror("level entry alloc");
+ exit(1);
+ }
+ ensure_array((void**)&level, &nlevel);
+ level[nlevel++] = e;
+}
+
+static inline int isquote(char c)
+{
+ return (c == '"' || c == '\'');
+}
+
+int
+parse_sysconf(const char* file)
+{
+ FILE* fp;
+ char line[1024];
+ char* p;
+ if ((fp = fopen(file, "r")) == 0)
+ {
+ fprintf(stderr, "error opening: %s: %s\n", file, strerror(errno));
+ return 0;
+ }
+ while (readline(fp, line, sizeof(line)))
+ {
+ if (!*line)
+ continue;
+ for (p = line; *p == ' '; ++p);
+ if (!*p || *p == '#')
+ continue;
+ if (!strncmp(p, "PERMISSION_SECURITY=", 20))
+ {
+ if (force_level)
+ continue;
+
+ p+=20;
+ if (isquote(*p))
+ ++p;
+ p = strtok(p, " ");
+ if (p && !isquote(*p))
+ {
+ do
+ {
+ if (isquote(p[strlen(p)-1]))
+ {
+ p[strlen(p)-1] = '\0';
+ }
+ if (*p && strcmp(p, "local"))
+ add_level(p);
+ }
+ while ((p = strtok(NULL, " ")));
+ }
+ }
+ else if (!strncmp(p, "CHECK_PERMISSIONS=", 18))
+ {
+ p+=18;
+ if (isquote(*p))
+ ++p;
+ if (!strncmp(p, "set", 3))
+ {
+ p+=3;
+ if (isquote(*p) || !*p)
+ default_set=1;
+ }
+ else if ((!strncmp(p, "no", 2) && (!p[3] || isquote(p[3]))) || !*p ||
isquote(*p))
+ {
+ p+=2;
+ if (isquote(*p) || !*p)
+ {
+ default_set = -1;
+ }
+ }
+ else
+ {
+ //fprintf(stderr, "invalid value for CHECK_PERMISSIONS (must be
'set', 'warn' or 'no')\n");
+ }
+ }
+ }
+ fclose(fp);
+ return 0;
+}
+
+static int
+compare(const void* a, const void* b)
+{
+ return strcmp(*(char* const*)a, *(char* const*)b);
+}
+
+static void
+collect_permfiles()
+{
+ int i;
+ DIR* dir;
+
+ ensure_array((void**)&permfiles, &npermfiles);
+ // 1. central fixed permissions file
+ permfiles[npermfiles++] = strdup("/etc/permissions");
+
+ // 2. central easy, secure paranoid as those are defined by SUSE
+ for (i = 0; i < nlevel; ++i)
+ {
+ if (!strcmp(level[i], "easy")
+ || !strcmp(level[i], "secure")
+ || !strcmp(level[i], "paranoid"))
+ {
+ char fn[4096];
+ snprintf(fn, sizeof(fn), "/etc/permissions.%s", level[i]);
+ if (access(fn, R_OK) == 0)
+ {
+ ensure_array((void**)&permfiles, &npermfiles);
+ permfiles[npermfiles++] = strdup(fn);
+ }
+ }
+ }
+ // 3. package specific permissions
+ dir = opendir("/etc/permissions.d");
+ if (dir)
+ {
+ char** files = NULL;
+ int nfiles = 0;
+ struct dirent* d;
+ while ((d = readdir(dir)))
+ {
+ char* p;
+ if (!strcmp("..", d->d_name) || !strcmp(".", d->d_name))
+ continue;
+ ensure_array((void**)&files, &nfiles);
+ if ((p = strchr(d->d_name, '.')))
+ {
+ *p = '\0';
+ }
+ files[nfiles++] = strdup(d->d_name);
+ }
+ closedir(dir);
+ if (nfiles)
+ {
+ qsort(files, nfiles, sizeof(char*), compare);
+ for (i = 0; i < nfiles; ++i)
+ {
+ char fn[4096];
+ int l;
+ // skip duplicates
+ if (i && !strcmp(files[i-1], files[i]))
+ continue;
+
+ snprintf(fn, sizeof(fn), "/etc/permissions.d/%s", files[i]);
+ if (access(fn, R_OK) == 0)
+ {
+ ensure_array((void**)&permfiles, &npermfiles);
+ permfiles[npermfiles++] = strdup(fn);
+ }
+
+ for (l = 0; l < nlevel; ++l)
+ {
+ snprintf(fn, sizeof(fn), "/etc/permissions.d/%s.%s",
files[i], level[l]);
+
+ if (access(fn, R_OK) == 0)
+ {
+ ensure_array((void**)&permfiles, &npermfiles);
+ permfiles[npermfiles++] = strdup(fn);
+ }
+ }
+
+ }
+ }
+ }
+ // 4. central permissions files with user defined level incl 'local'
+ for (i = 0; i < nlevel; ++i)
+ {
+ char fn[4096];
+
+ if (!strcmp(level[i], "easy") || !strcmp(level[i], "secure") ||
!strcmp(level[i], "paranoid"))
+ continue;
+
+ snprintf(fn, sizeof(fn), "/etc/permissions.%s", level[i]);
+ if (access(fn, R_OK) == 0)
+ {
+ ensure_array((void**)&permfiles, &npermfiles);
+ permfiles[npermfiles++] = strdup(fn);
+ }
+ }
+}
+
+
void
usage(int x)
{
- fprintf(stderr, "Usage: chkstat [--set] [--noheader] [[--examine file] ...]
[ [--files filelist] ...] permission-file ...\n");
+ printf("Usage:\n"
+"a) chkstat [OPTIONS] <permission-files>...\n"
+"b) chkstat --system [OPTIONS] <files>...\n"
+"\n"
+"Options:\n"
+" --set apply changes\n"
+" --warn only tell which changes are needed\n"
+" --noheader don't print intro message\n"
+" --fscaps force use of fscaps\n"
+" --no-fscaps disable use of fscaps\n"
+" --system system mode, act according to
/etc/permissions/security\n"
+" --level LEVEL force use LEVEL (only with --system)\n"
+" --examine FILE apply to specified file only\n"
+" --files FILELIST read list of files to apply from FILELIST\n"
+" --root DIR check files relative to DIR\n"
+);
exit(x);
}

@@ -173,7 +421,7 @@

lcnt = 0;
l2 = strlen(path);
- if (l2 >= sizeof(pathbuf))
+ if ((unsigned)l2 >= sizeof(pathbuf))
return 0;
strcpy(pathbuf, path);
if (pathbuf[0] != '/')
@@ -192,11 +440,11 @@
if (++lcnt >= 256)
return 0;
l = readlink(pathbuf, linkbuf, sizeof(linkbuf));
- if (l <= 0 || l >= sizeof(linkbuf))
+ if (l <= 0 || (unsigned)l >= sizeof(linkbuf))
return 0;
while(l && linkbuf[l - 1] == '/')
l--;
- if (l + 1 >= sizeof(linkbuf))
+ if ((unsigned)l + 1 >= sizeof(linkbuf))
return 0;
linkbuf[l++] = '/';
linkbuf[l] = 0;
@@ -228,7 +476,7 @@
l2 -= (p - p2);
p = p2;
}
- if (l + l2 >= sizeof(pathbuf))
+ if ((unsigned)(l + l2) >= sizeof(pathbuf))
return 0;
memmove(p + l, p, pathbuf + l2 - p + 1);
memmove(p, linkbuf, l);
@@ -261,13 +509,39 @@
}
}

+/* that's really ugly. There should be sysctl or something */
+static int
+check_fscaps_cmdline()
+{
+ FILE* fp;
+ char line[4096];
+ if ((fp = fopen("/proc/cmdline", "r")) == 0)
+ {
+ return 0;
+ }
+ if (readline(fp, line, sizeof(line)))
+ {
+ char* p;
+ if ((p = strstr(line, "file_caps")))
+ {
+ if (p - line < 3 || strncmp("no_", p, 3))
+ {
+ return 1;
+ }
+ }
+ }
+ fclose(fp);
+ return 0;
+}
+
int
main(int argc, char **argv)
{
- char *opt, *p;
- int set = 0;
+ char *opt, *p, *str;
int told = 0;
int use_checklist = 0;
+ int systemmode = 0;
+ int suseconfig = 0;
FILE *fp;
char line[512];
char *part[4];
@@ -282,6 +556,8 @@
gid_t gid;
int fd, r;
int errors = 0;
+ cap_t caps = NULL;
+ int have_fscaps = -1;

while (argc > 1)
{
@@ -290,9 +566,46 @@
break;
if (*opt == '-' && opt[1] == '-')
opt++;
+ if (!strcmp(opt, "-system"))
+ {
+ argc--;
+ argv++;
+ systemmode = 1;
+ continue;
+ }
+ // hidden option for use by suseconfig only
+ if (!strcmp(opt, "-suseconfig"))
+ {
+ argc--;
+ argv++;
+ suseconfig = 1;
+ systemmode = 1;
+ continue;
+ }
+ if (!strcmp(opt, "-fscaps"))
+ {
+ argc--;
+ argv++;
+ have_fscaps = 1;
+ continue;
+ }
+ if (!strcmp(opt, "-no-fscaps"))
+ {
+ argc--;
+ argv++;
+ have_fscaps = 0;
+ continue;
+ }
if (!strcmp(opt, "-s") || !strcmp(opt, "-set"))
{
- set = 1;
+ do_set=1;
+ argc--;
+ argv++;
+ continue;
+ }
+ if (!strcmp(opt, "-warn"))
+ {
+ do_set=0;
argc--;
argv++;
continue;
@@ -319,6 +632,20 @@
argv++;
continue;
}
+ if (!strcmp(opt, "-level"))
+ {
+ argc--;
+ argv++;
+ if (argc == 1)
+ {
+ fprintf(stderr, "level: argument required\n");
+ exit(1);
+ }
+ force_level = argv[1];
+ argc--;
+ argv++;
+ continue;
+ }
if (!strcmp(opt, "-f") || !strcmp(opt, "-files"))
{
argc--;
@@ -369,18 +696,78 @@
usage(!strcmp(opt, "-h") || !strcmp(opt, "-help") ? 0 : 1);
break;
}
- if (argc <= 1)
+
+ if (have_fscaps == -1)
+ have_fscaps = check_fscaps_cmdline();
+
+ if (systemmode)
+ {
+ const char file[] = "/etc/sysconfig/security";
+ parse_sysconf(file);
+ if(do_set == -1)
+ {
+ if (default_set < 0)
+ {
+ fprintf(stderr, "permissions handling disabled in %s\n", file);
+ exit(0);
+ }
+ if (suseconfig && default_set)
+ {
+ char* module = getenv("ONLY_MODULE");
+ if (!module || strcmp(module, "permissions"))
+ {
+ puts("no permissions will be changed if not called
explicitly");
+ default_set = 0;
+ }
+ }
+ do_set = default_set;
+ }
+ if (force_level)
+ {
+ char *p = strtok(force_level, " ");
+ do
+ {
+ add_level(p);
+ }
+ while ((p = strtok(NULL, " ")));
+ }
+
+ if (!nlevel)
+ add_level("secure");
+ add_level("local"); // always add local
+
+ for (i = 1; i < argc; i++)
+ {
+ add_checklist(argv[i]);
+ use_checklist = 1;
+ continue;
+ }
+ collect_permfiles();
+ }
+ else if (argc <= 1)
usage(1);
- for (i = 1; i < argc; i++)
+ else
{
- if ((fp = fopen(argv[i], "r")) == 0)
+ npermfiles = argc-1;
+ permfiles = &argv[1];
+ }
+
+ if (do_set == -1)
+ do_set = 0;
+
+ for (i = 0; i < npermfiles; i++)
+ {
+ if ((fp = fopen(permfiles[i], "r")) == 0)
{
perror(argv[i]);
exit(1);
}
lcnt = 0;
+ struct perm* last = NULL;
+ int extline;
while (readline(fp, line, sizeof(line)))
{
+ extline = 0;
lcnt++;
if (*line == 0 || *line == '#' || *line == '$')
continue;
@@ -398,6 +785,11 @@
}
continue;
}
+ if (pcnt == 0 && !inpart && *p == '+')
+ {
+ extline = 1;
+ break;
+ }
if (!inpart)
{
inpart = 1;
@@ -406,11 +798,34 @@
part[pcnt] = p;
}
}
+ if (extline)
+ {
+ if (!last)
+ {
+ BAD_LINE();
+ continue;
+ }
+ if (!strncmp(p, "+capabilities ", 14))
+ {
+ if (!have_fscaps)
+ continue;
+ p += 14;
+ caps = cap_from_text(p);
+ if (caps)
+ {
+ cap_free(last->caps);
+ last->caps = caps;
+ }
+ continue;
+ }
+ BAD_LINE();
+ continue;
+ }
if (inpart)
pcnt++;
if (pcnt != 3)
{
- fprintf(stderr, "bad permissions line %s:%d\n", argv[i], lcnt);
+ BAD_LINE();
continue;
}
part[3] = part[2];
@@ -419,17 +834,17 @@
part[2] = strchr(part[1], '.');
if (!part[2])
{
- fprintf(stderr, "bad permissions line %s:%d\n", argv[i], lcnt);
+ BAD_LINE();
continue;
}
*part[2]++ = 0;
mode = strtoul(part[3], part + 3, 8);
if (mode > 07777 || part[3][0])
{
- fprintf(stderr, "bad permissions line %s:%d\n", argv[i], lcnt);
+ BAD_LINE();
continue;
}
- add_permlist(part[0], part[1], part[2], mode);
+ last = add_permlist(part[0], part[1], part[2], mode);
}
fclose(fp);
}
@@ -445,33 +860,74 @@
continue;
if ((!pwd || strcmp(pwd->pw_name, e->owner)) && (pwd =
getpwnam(e->owner)) == 0)
{
- fprintf(stderr, "%s: unknown user %s\n", e->file, e->owner);
+ fprintf(stderr, "%s: unknown user %s\n", e->file+rootl, e->owner);
continue;
}
if ((!grp || strcmp(grp->gr_name, e->group)) && (grp =
getgrnam(e->group)) == 0)
{
- fprintf(stderr, "%s: unknown group %s\n", e->file, e->group);
+ fprintf(stderr, "%s: unknown group %s\n", e->file+rootl, e->group);
continue;
}
uid = pwd->pw_uid;
gid = grp->gr_gid;
- if ((stb.st_mode & 07777) == e->mode && stb.st_uid == uid && stb.st_gid
== gid)
+ caps = cap_get_file(e->file);
+ if (!caps)
+ {
+ cap_free(caps);
+ caps = NULL;
+ if (errno == EOPNOTSUPP)
+ {
+ //fprintf(stderr, "%s: fscaps not supported\n", e->file+rootl);
+ cap_free(e->caps);
+ e->caps = NULL;
+ }
+ }
+ if (e->caps)
+ {
+ e->mode &= 0777;
+ }
+
+ int perm_ok = (stb.st_mode & 07777) == e->mode;
+ int owner_ok = stb.st_uid == uid && stb.st_gid == gid;
+ int caps_ok = 0;
+
+ if (!caps && !e->caps)
+ caps_ok = 1;
+ else if (caps && e->caps && !cap_compare(e->caps, caps))
+ caps_ok = 1;
+
+ if (perm_ok && owner_ok && caps_ok)
continue;

if (!told)
{
told = 1;
printf("Checking permissions and ownerships - using the permissions
files\n");
- for (i = 1; i < argc; i++)
- printf("\t%s\n", argv[i]);
+ for (i = 0; i < npermfiles; i++)
+ printf("\t%s\n", permfiles[i]);
+ if (!have_fscaps)
+ {
+ printf("fscaps support disabled (file_caps missing in
/proc/cmdline).\n");
+ }
+ if (rootl)
+ {
+ printf("Using root %s\n", root);
+ }
}

- if (!set)
- printf("%s should be %s:%s %04o.", e->file, e->owner, e->group,
e->mode);
+ if (!do_set)
+ printf("%s should be %s:%s %04o", e->file+rootl, e->owner, e->group,
e->mode);
else
- printf("setting %s to %s:%s %04o.", e->file, e->owner, e->group,
e->mode);
- printf(" (wrong");
- if (stb.st_uid != uid || stb.st_gid != gid)
+ printf("setting %s to %s:%s %04o", e->file+rootl, e->owner, e->group,
e->mode);
+
+ if (!caps_ok && e->caps)
+ {
+ str = cap_to_text(e->caps, NULL);
+ printf(" \"%s\"", str);
+ cap_free(str);
+ }
+ printf(". (wrong");
+ if (!owner_ok)
{
pwd = getpwuid(stb.st_uid);
grp = getgrgid(stb.st_gid);
@@ -486,12 +942,29 @@
pwd = 0;
grp = 0;
}
- if ((stb.st_mode & 07777) != e->mode)
+
+ if (!perm_ok)
printf(" permissions %04o", (int)(stb.st_mode & 07777));
+
+ if (!caps_ok)
+ {
+ if (!perm_ok || !owner_ok)
+ {
+ fputc(',', stdout);
+ }
+ if (caps)
+ {
+ str = cap_to_text(caps, NULL);
+ printf(" capabilities \"%s\"", str);
+ cap_free(str);
+ }
+ else
+ fputs(" missing capabilities", stdout);
+ }
putchar(')');
putchar('\n');

- if (!set)
+ if (!do_set)
continue;

fd = -1;
@@ -518,13 +991,13 @@
continue;
if (stb.st_mode != stb2.st_mode || stb.st_nlink != stb2.st_nlink ||
stb.st_dev != stb2.st_dev || stb.st_ino != stb2.st_ino)
{
- fprintf(stderr, "%s: too fluctuating\n", e->file);
+ fprintf(stderr, "%s: too fluctuating\n", e->file+rootl);
errors++;
continue;
}
if (stb.st_nlink > 1 && !safepath(e->file, 0, 0))
{
- fprintf(stderr, "%s: on an insecure path\n", e->file);
+ fprintf(stderr, "%s: on an insecure path\n", e->file+rootl);
errors++;
continue;
}
@@ -533,27 +1006,31 @@
/* extra checks for s-bits */
if (!safepath(e->file, (e->mode & 02000) == 0 ? uid : 0, (e->mode
& 04000) == 0 ? gid : 0))
{
- fprintf(stderr, "%s: will not give away s-bits on an insecure
path\n", e->file);
+ fprintf(stderr, "%s: will not give away s-bits on an insecure
path\n", e->file+rootl);
errors++;
continue;
}
}
}
- else if (strncmp(e->file, "/dev/", 4) != 0)
+ else if (strncmp(e->file, "/dev/", 5) != 0) // handle special files only
in /dev
{
- fprintf(stderr, "%s: don't know what to do with that type of file\n",
e->file);
+ fprintf(stderr, "%s: don't know what to do with that type of file\n",
e->file+rootl);
errors++;
continue;
}
- if (euid == 0 && (stb.st_uid != uid || stb.st_gid != gid))
+ if (euid == 0 && !owner_ok)
{
+ /* if we change owner or group of a setuid file the bit gets reset so
+ also set perms again */
+ if (e->mode & 06000)
+ perm_ok = 0;
if (fd >= 0)
r = fchown(fd, uid, gid);
else
r = chown(e->file, uid, gid);
if (r)
{
- fprintf(stderr, "%s: chown: %s\n", e->file, strerror(errno));
+ fprintf(stderr, "%s: chown: %s\n", e->file+rootl,
strerror(errno));
errors++;
}
if (fd >= 0)
@@ -562,12 +1039,12 @@
r = lstat(e->file, &stb);
if (r)
{
- fprintf(stderr, "%s: too fluctuating\n", e->file);
+ fprintf(stderr, "%s: too fluctuating\n", e->file+rootl);
errors++;
continue;
}
}
- if ((stb.st_mode & 07777) != e->mode)
+ if (!perm_ok)
{
if (fd >= 0)
r = fchmod(fd, e->mode);
@@ -575,7 +1052,19 @@
r = chmod(e->file, e->mode);
if (r)
{
- fprintf(stderr, "%s: chmod: %s\n", e->file, strerror(errno));
+ fprintf(stderr, "%s: chmod: %s\n", e->file+rootl,
strerror(errno));
+ errors++;
+ }
+ }
+ if (!caps_ok)
+ {
+ if (fd >= 0)
+ r = cap_set_fd(fd, e->caps);
+ else
+ r = cap_set_file(e->file, e->caps);
+ if (r)
+ {
+ fprintf(stderr, "%s: cap_set_file: %s\n", e->file+rootl,
strerror(errno));
errors++;
}
}
@@ -589,3 +1078,5 @@
}
exit(0);
}
+
+// vim: sw=4 cino+={.5s,n-.5s,^-.5s
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/permissions-2010.10.18.1537/permissions.5
new/permissions-2010.11.09.1206/permissions.5
--- old/permissions-2010.10.18.1537/permissions.5 1970-01-01
01:00:00.000000000 +0100
+++ new/permissions-2010.11.09.1206/permissions.5 2010-11-09
12:06:11.000000000 +0100
@@ -0,0 +1,48 @@
+.TH "PERMISSIONS" "5" "07/11/2010" "" ""
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+permission - default permission settings
+.SH "SYNOPSIS"
+The chkstat program sets permissions and ownerships according to the
+permission files\.
+.SH "DESCRIPTION"
+\- The files /etc/permissions\.* are line based and space delimited\.
+.br
+\- Lines starting with # are comments\.
+.br
+\- The first column specifies the file name\. Directory names have to
+end with a slash\.
+.br
+\- The second column specifies the owner and group\.
+.br
+\- The third column specifies the file mode\.
+.br
+\- The special value \fB+capabilities\fR in the first column extends
+the information of the previous line with with file capabilites.
+.br
+.SH "FILES"
+.sp
+/etc/permissions
+.br
+/etc/permissions\.easy
+.br
+/etc/permissions\.secure
+.br
+/etc/permissions\.paranoid
+.br
+/etc/permissions\.d/*
+.br
+/etc/permissions\.local
+.br
+.SH "SEE ALSO"
+chkstat(8)
+.sp
+.SH "AUTHOR"
+Written by Ludwig Nussel
+.sp
+.SH "REPORTING BUGS"
+Report bugs to https://bugzilla\.novell\.com/
+.sp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/permissions-2010.10.18.1537/permissions.easy
new/permissions-2010.11.09.1206/permissions.easy
--- old/permissions-2010.10.18.1537/permissions.easy 2010-10-18
15:37:12.000000000 +0200
+++ new/permissions-2010.11.09.1206/permissions.easy 2010-11-09
12:06:11.000000000 +0100
@@ -197,7 +197,9 @@
# networking (need root for the privileged socket)
#
/bin/ping root:root 4755
+ +capabilities cap_net_raw=ep
/bin/ping6 root:root 4755
+ +capabilities cap_net_raw=ep
# mtr is linked against ncurses. For dialout only.
/usr/sbin/mtr root:dialout 4750
/usr/bin/rcp root:root 4755
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/permissions-2010.10.18.1537/permissions.secure
new/permissions-2010.11.09.1206/permissions.secure
--- old/permissions-2010.10.18.1537/permissions.secure 2010-10-18
15:37:12.000000000 +0200
+++ new/permissions-2010.11.09.1206/permissions.secure 2010-11-09
12:06:11.000000000 +0100
@@ -235,7 +235,9 @@
# networking (need root for the privileged socket)
#
/bin/ping root:root 4755
+ +capabilities cap_net_raw=ep
/bin/ping6 root:root 4755
+ +capabilities cap_net_raw=ep
# mtr is linked against ncurses. no suid bit, for root only:
/usr/sbin/mtr root:dialout 0755
/usr/bin/rcp root:root 4755


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



Remember to have fun...

--
To unsubscribe, e-mail: opensuse-commit+unsubscribe@xxxxxxxxxxxx
For additional commands, e-mail: opensuse-commit+help@xxxxxxxxxxxx

< Previous Next >
This Thread