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