xref: /onnv-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/os/safechown.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright (c) 1998, by Sun Microsystems, Inc.
3*0Sstevel@tonic-gate  * All rights reserved.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*0Sstevel@tonic-gate 
8*0Sstevel@tonic-gate #include <stdio.h>
9*0Sstevel@tonic-gate #include <string.h>
10*0Sstevel@tonic-gate #include <stdlib.h>
11*0Sstevel@tonic-gate #include <unistd.h>
12*0Sstevel@tonic-gate #include <sys/types.h>
13*0Sstevel@tonic-gate #include <sys/stat.h>
14*0Sstevel@tonic-gate #include <fcntl.h>
15*0Sstevel@tonic-gate 
16*0Sstevel@tonic-gate /*
17*0Sstevel@tonic-gate  * safechown changes the owner ship of src to uid. If the mode parameter
18*0Sstevel@tonic-gate  * does not equal -1 changes the mode of src as well.
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * return -1 on failure and 0 on success.
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate 
23*0Sstevel@tonic-gate int
safechown(const char * src,uid_t uid,gid_t gid,int mode)24*0Sstevel@tonic-gate safechown(const char *src, uid_t uid, gid_t gid, int mode)
25*0Sstevel@tonic-gate {
26*0Sstevel@tonic-gate int fd;
27*0Sstevel@tonic-gate struct stat fdbuf;
28*0Sstevel@tonic-gate struct stat lbuf;
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate 	if ((fd = open(src, O_RDONLY, 0)) == -1)
31*0Sstevel@tonic-gate 		return (-1);
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate 	if (fstat(fd, &fdbuf)) {
34*0Sstevel@tonic-gate 		close(fd);
35*0Sstevel@tonic-gate 		return (-1);
36*0Sstevel@tonic-gate 	}
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate 	/* Make sure non directories are not hard links */
39*0Sstevel@tonic-gate 	if (!S_ISDIR(fdbuf.st_mode) && fdbuf.st_nlink != 1) {
40*0Sstevel@tonic-gate 		close(fd);
41*0Sstevel@tonic-gate 		return (-1);
42*0Sstevel@tonic-gate 	}
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate 	if (lstat(src, &lbuf)) {
45*0Sstevel@tonic-gate 		close(fd);
46*0Sstevel@tonic-gate 		return (-1);
47*0Sstevel@tonic-gate 	}
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate 	/* Make sure file is not a symlink */
50*0Sstevel@tonic-gate 	if (fdbuf.st_ino != lbuf.st_ino || fdbuf.st_dev != lbuf.st_dev ||
51*0Sstevel@tonic-gate 		fdbuf.st_mode != lbuf.st_mode) {
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate 		close(fd);
54*0Sstevel@tonic-gate 		return (-1);
55*0Sstevel@tonic-gate 	}
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate 	/* we should probably get the primary group id for uid here */
58*0Sstevel@tonic-gate 	if (fchown(fd, uid, gid)) {
59*0Sstevel@tonic-gate 		close(fd);
60*0Sstevel@tonic-gate 		return (-1);
61*0Sstevel@tonic-gate 	}
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate 	if (mode != -1) {
64*0Sstevel@tonic-gate 		if (fchmod(fd, (mode_t)mode)) {
65*0Sstevel@tonic-gate 		    close(fd);
66*0Sstevel@tonic-gate 		    return (-1);
67*0Sstevel@tonic-gate 		}
68*0Sstevel@tonic-gate 	}
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate 	close(fd);
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate 	return (0);
73*0Sstevel@tonic-gate }
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate #ifdef TEST
76*0Sstevel@tonic-gate void
usage(char * prg)77*0Sstevel@tonic-gate usage(char *prg)
78*0Sstevel@tonic-gate {
79*0Sstevel@tonic-gate 	fprintf(stderr, "Usage %s [-u uid] [-m mode] source\n", prg);
80*0Sstevel@tonic-gate 	exit(1);
81*0Sstevel@tonic-gate }
82*0Sstevel@tonic-gate 
main(int argc,char * argv[])83*0Sstevel@tonic-gate main(int argc, char *argv[])
84*0Sstevel@tonic-gate {
85*0Sstevel@tonic-gate 	int opt;
86*0Sstevel@tonic-gate 	int mode = -1;
87*0Sstevel@tonic-gate 	uid_t uid = 0;
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, "m:u:")) != EOF) {
90*0Sstevel@tonic-gate 		switch (opt) {
91*0Sstevel@tonic-gate 		case 'm':
92*0Sstevel@tonic-gate 			mode = strtol(optarg, 0, 8);
93*0Sstevel@tonic-gate 			break;
94*0Sstevel@tonic-gate 		case 'u':
95*0Sstevel@tonic-gate 			uid = atoi(optarg);
96*0Sstevel@tonic-gate 			break;
97*0Sstevel@tonic-gate 		default:
98*0Sstevel@tonic-gate 			usage(argv[0]);
99*0Sstevel@tonic-gate 	}
100*0Sstevel@tonic-gate }
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate     if (argc - optind != 1)
103*0Sstevel@tonic-gate 	usage(argv[0]);
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate     if (safechown(argv[optind], uid, getgid(), mode)) {
106*0Sstevel@tonic-gate 	perror("safechown");
107*0Sstevel@tonic-gate 	exit(1);
108*0Sstevel@tonic-gate     }
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate     return (0);
111*0Sstevel@tonic-gate }
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate #endif  /* TEST */
114