Audit chown(1)

Similar to the chgrp(1)-audit:
1) Refactor manpage so it's actually fun to read
2) BUGFIX: Call (l)chown properly when the H-flag is specified
   (only when depth > 0)
3) BUGFIX: Call (l)chown properly when the h-flag is specified
   (only when depth = 0).
4) BUGFIX: Only recurse() in chgrp() when the initial chownf()
   succeeds.
5) Style fixes, argv-basing.
6) Rename status to ret for consistency.
7) Add blank line before return.
This commit is contained in:
FRIGN 2015-03-09 00:37:34 +01:00
parent 8f436abde6
commit 3a04302c66
3 changed files with 52 additions and 43 deletions

2
README
View File

@ -14,7 +14,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
=*| cat yes none =*| cat yes none
=*| chgrp yes none =*| chgrp yes none
=*| chmod yes none =*| chmod yes none
=* chown yes none =*| chown yes none
=*| chroot non-posix none =*| chroot non-posix none
=* cksum yes none =* cksum yes none
=* cmp yes none =* cmp yes none

33
chown.1
View File

@ -1,4 +1,4 @@
.Dd February 17, 2015 .Dd March 9, 2015
.Dt CHOWN 1 .Dt CHOWN 1
.Os sbase .Os sbase
.Sh NAME .Sh NAME
@ -15,26 +15,35 @@
.Op Ar file ... .Op Ar file ...
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
changes the user or group ownership for the given sets the user or group id of each
.Ar files . .Ar file
to the uid of
.Ar owner
or the gid of
.Ar group
respectively.
.Sh OPTIONS .Sh OPTIONS
.Bl -tag -width Ds .Bl -tag -width Ds
.It Fl h .It Fl h
Change the user ID and/or group ID of the symlink itself. This flag cannot be used Preserve
with .Ar file
.Op Fl R . if it is a symbolic link.
.It Fl R .It Fl R
Change directory ownership recursively. Change file ownerships recursively.
.It Fl H .It Fl H
Only dereference symbolic links that are passed as command line arguments when Dereference
recursively traversing directories. .Ar file
if it is a symbolic link.
.It Fl L .It Fl L
Always dereference symbolic links while recursively traversing directories. Dereference all symbolic links.
.It Fl P .It Fl P
Don't dereference symbolic links (default). Preserve symbolic links. This is the default.
.El .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr chown 2 .Xr chmod 1 ,
.Xr chown 2 ,
.Xr getgrnam 3 ,
.Xr getpwnam 3
.Sh STANDARDS .Sh STANDARDS
The The
.Nm .Nm

60
chown.c
View File

@ -1,6 +1,7 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
#include <errno.h> #include <errno.h>
#include <grp.h> #include <grp.h>
#include <limits.h>
#include <pwd.h> #include <pwd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -8,45 +9,54 @@
#include "util.h" #include "util.h"
static int rflag = 0; static int hflag = 0;
static uid_t uid = -1; static int Rflag = 0;
static gid_t gid = -1; static uid_t uid = -1;
static int ret = 0; static gid_t gid = -1;
static char *chownf_name = "chown"; static int ret = 0;
static int (*chownf)(const char *, uid_t, gid_t) = chown;
static void static void
chownpwgr(const char *path, int depth) chownpwgr(const char *path, int depth)
{ {
char *chownf_name;
int (*chownf)(const char *, uid_t, gid_t);
if (recurse_follow == 'P' || (recurse_follow == 'H' && depth) || (hflag && !depth)) {
chownf_name = "lchown";
chownf = lchown;
} else {
chownf_name = "chown";
chownf = chown;
}
if (chownf(path, uid, gid) < 0) { if (chownf(path, uid, gid) < 0) {
weprintf("%s %s:", chownf_name, path); weprintf("%s %s:", chownf_name, path);
ret = 1; ret = 1;
} } else if (Rflag) {
if (rflag)
recurse(path, chownpwgr, depth); recurse(path, chownpwgr, depth);
}
} }
static void static void
usage(void) usage(void)
{ {
eprintf("usage: %s [-h] [-R [-H | -L | -P]] [owner][:[group]] file...\n", argv0); eprintf("usage: %s [-h] [-R [-H | -L | -P]] [owner][:[group]] file ...\n", argv0);
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
char *owner, *group, *end;
struct passwd *pw; struct passwd *pw;
struct group *gr; struct group *gr;
char *owner, *group;
ARGBEGIN { ARGBEGIN {
case 'h': case 'h':
chownf_name = "lchown"; hflag = 1;
chownf = lchown;
break; break;
case 'r': case 'r':
case 'R': case 'R':
rflag = 1; Rflag = 1;
break; break;
case 'H': case 'H':
case 'L': case 'L':
@ -57,16 +67,10 @@ main(int argc, char *argv[])
usage(); usage();
} ARGEND; } ARGEND;
if (argc == 0) if (argc < 2)
usage(); usage();
if (recurse_follow == 'P') {
chownf_name = "lchown";
chownf = lchown;
}
owner = argv[0]; owner = argv[0];
argv++;
argc--;
if ((group = strchr(owner, ':'))) if ((group = strchr(owner, ':')))
*group++ = '\0'; *group++ = '\0';
@ -76,11 +80,9 @@ main(int argc, char *argv[])
if (pw) { if (pw) {
uid = pw->pw_uid; uid = pw->pw_uid;
} else { } else {
if (errno != 0) if (errno)
eprintf("getpwnam %s:", owner); eprintf("getpwnam %s:", owner);
uid = strtoul(owner, &end, 10); uid = estrtonum(owner, 0, UINT_MAX);
if (*end != '\0')
eprintf("getpwnam %s: no such user\n", owner);
} }
} }
if (group && *group) { if (group && *group) {
@ -89,15 +91,13 @@ main(int argc, char *argv[])
if (gr) { if (gr) {
gid = gr->gr_gid; gid = gr->gr_gid;
} else { } else {
if (errno != 0) if (errno)
eprintf("getgrnam %s:", group); eprintf("getgrnam %s:", group);
gid = strtoul(group, &end, 10); gid = estrtonum(group, 0, UINT_MAX);
if (*end != '\0')
eprintf("getgrnam %s: no such group\n", group);
} }
} }
for (; argc > 0; argc--, argv++) for (argc--, argv++; *argv; argc--, argv++)
chownpwgr(argv[0], 0); chownpwgr(*argv, 0);
return ret; return ret;
} }