safechown.c revision 2
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* Solaris Kerberos: this file is unique to Solaris. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <stdio.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <string.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <stdlib.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <unistd.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/types.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/stat.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <fcntl.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * safechown changes the owner ship of src to uid. If the mode parameter
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * does not equal -1 changes the mode of src as well.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * return -1 on failure and 0 on success.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfint
ab0d082f1ff5e05e86ea99a5672d8c466563280dMark Logansafechown(const char *src, uid_t uid, gid_t gid, int mode)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
7dac2cd84b59ec865d350aeb91b90cd1469527e1Garrett D'Amoreint fd;
0c6eaab480b44a0c790ad94e7cb6084792411de9Hans Rosenfeldstruct stat fdbuf;
fbc2697c538d75e4d5d938d24a995afa043c99d2Igor Kozhukhovstruct stat lbuf;
7dac2cd84b59ec865d350aeb91b90cd1469527e1Garrett D'Amore
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((fd = open(src, O_RDONLY, 0)) == -1)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (fstat(fd, &fdbuf)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf close(fd);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Make sure non directories are not hard links */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!S_ISDIR(fdbuf.st_mode) && fdbuf.st_nlink != 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf close(fd);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (lstat(src, &lbuf)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf close(fd);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw return (-1);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Make sure file is not a symlink */
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik if (fdbuf.st_ino != lbuf.st_ino || fdbuf.st_dev != lbuf.st_dev ||
a78a9fafefff1ddbaa3ef65fa09190848e704a27Martin Faltesek fdbuf.st_mode != lbuf.st_mode) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf close(fd);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* we should probably get the primary group id for uid here */
63aa537723d4883425b44d96b6316b7ad14053fcAlan Perry if (fchown(fd, uid, gid)) {
63aa537723d4883425b44d96b6316b7ad14053fcAlan Perry close(fd);
63aa537723d4883425b44d96b6316b7ad14053fcAlan Perry return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
ab0d082f1ff5e05e86ea99a5672d8c466563280dMark Logan
ab0d082f1ff5e05e86ea99a5672d8c466563280dMark Logan if (mode != -1) {
ab0d082f1ff5e05e86ea99a5672d8c466563280dMark Logan if (fchmod(fd, (mode_t)mode)) {
ab0d082f1ff5e05e86ea99a5672d8c466563280dMark Logan close(fd);
ab0d082f1ff5e05e86ea99a5672d8c466563280dMark Logan return (-1);
ab0d082f1ff5e05e86ea99a5672d8c466563280dMark Logan }
ab0d082f1ff5e05e86ea99a5672d8c466563280dMark Logan }
ab0d082f1ff5e05e86ea99a5672d8c466563280dMark Logan
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf close(fd);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls return (0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef TEST
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfvoid
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfusage(char *prg)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf fprintf(stderr, "Usage %s [-u uid] [-m mode] source\n", prg);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang exit(1);
37a077ef1920ee044b2887247b2a802e726d3368ls}
37a077ef1920ee044b2887247b2a802e726d3368ls
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfmain(int argc, char *argv[])
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw{
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw int opt;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw int mode = -1;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw uid_t uid = 0;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw while ((opt = getopt(argc, argv, "m:u:")) != EOF) {
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw switch (opt) {
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw case 'm':
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw mode = strtol(optarg, 0, 8);
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw break;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw case 'u':
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw uid = atoi(optarg);
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw break;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw default:
c75976d12071ddd21443266260066ba036671682pawelw usage(argv[0]);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (argc - optind != 1)
c75976d12071ddd21443266260066ba036671682pawelw usage(argv[0]);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (safechown(argv[optind], uid, getgid(), mode)) {
c75976d12071ddd21443266260066ba036671682pawelw perror("safechown");
c75976d12071ddd21443266260066ba036671682pawelw exit(1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
7a70ede882eacbae00c8d5209afb443e7755684cpawelw}
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif /* TEST */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown