~ubuntu-branches/ubuntu/lucid/bind9/lucid

« back to all changes in this revision

Viewing changes to bin/named/unix/os.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2010-03-01 20:51:23 UTC
  • mfrom: (1.6.4 upstream) (10.1.5 experimental)
  • Revision ID: james.westby@ubuntu.com-20100301205123-kslpwaipx72vq1o1
Tags: 1:9.7.0.dfsg-1~build1
upload of -1 to lucid, LP#530107

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 * PERFORMANCE OF THIS SOFTWARE.
16
16
 */
17
17
 
18
 
/* $Id: os.c,v 1.89.12.5 2009/03/02 03:03:54 marka Exp $ */
 
18
/* $Id: os.c,v 1.101 2009/08/13 07:04:38 marka Exp $ */
19
19
 
20
20
/*! \file */
21
21
 
291
291
         */
292
292
        SET_CAP(CAP_SYS_RESOURCE);
293
293
 
 
294
        /*
 
295
         * We need to be able to set the ownership of the containing
 
296
         * directory of the pid file when we create it.
 
297
         */
 
298
        SET_CAP(CAP_CHOWN);
 
299
 
294
300
        linux_setcaps(caps);
295
301
 
296
302
#ifdef HAVE_LIBCAP
631
637
}
632
638
 
633
639
static int
634
 
safe_open(const char *filename, isc_boolean_t append) {
 
640
safe_open(const char *filename, mode_t mode, isc_boolean_t append) {
635
641
        int fd;
636
642
        struct stat sb;
637
643
 
644
650
        }
645
651
 
646
652
        if (append)
647
 
                fd = open(filename, O_WRONLY|O_CREAT|O_APPEND,
648
 
                          S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
 
653
                fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, mode);
649
654
        else {
650
655
                if (unlink(filename) < 0 && errno != ENOENT)
651
656
                        return (-1);
652
 
                fd = open(filename, O_WRONLY|O_CREAT|O_EXCL,
653
 
                          S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
 
657
                fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
654
658
        }
655
659
        return (fd);
656
660
}
686
690
                        }
687
691
                        if (mkdirpath(filename, report) == -1)
688
692
                                goto error;
 
693
                        /*
 
694
                         * Handle "//", "/./" and "/../" in path.
 
695
                         */
 
696
                        if (!strcmp(slash + 1, "") ||
 
697
                            !strcmp(slash + 1, ".") ||
 
698
                            !strcmp(slash + 1, "..")) {
 
699
                                *slash = '/';
 
700
                                return (0);
 
701
                        }
689
702
                        mode = S_IRUSR | S_IWUSR | S_IXUSR;     /* u=rwx */
690
703
                        mode |= S_IRGRP | S_IXGRP;              /* g=rx */
691
704
                        mode |= S_IROTH | S_IXOTH;              /* o=rx */
695
708
                                          strbuf);
696
709
                                goto error;
697
710
                        }
 
711
                        if (runas_pw != NULL &&
 
712
                            chown(filename, runas_pw->pw_uid,
 
713
                                  runas_pw->pw_gid) == -1) {
 
714
                                isc__strerror(errno, strbuf, sizeof(strbuf));
 
715
                                (*report)("couldn't chown '%s': %s", filename,
 
716
                                          strbuf);
 
717
                        }
698
718
                }
699
719
                *slash = '/';
700
720
        }
705
725
        return (-1);
706
726
}
707
727
 
 
728
static void
 
729
setperms(uid_t uid, gid_t gid) {
 
730
        char strbuf[ISC_STRERRORSIZE];
 
731
#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
 
732
        gid_t oldgid, tmpg;
 
733
#endif
 
734
#if !defined(HAVE_SETEUID) && defined(HAVE_SETRESUID)
 
735
        uid_t olduid, tmpu;
 
736
#endif
 
737
#if defined(HAVE_SETEGID)
 
738
        if (getegid() != gid && setegid(gid) == -1) {
 
739
                isc__strerror(errno, strbuf, sizeof(strbuf));
 
740
                ns_main_earlywarning("unable to set effective gid to %ld: %s",
 
741
                                     (long)gid, strbuf);
 
742
        }
 
743
#elif defined(HAVE_SETRESGID)
 
744
        if (getresgid(&tmpg, &oldgid, &tmpg) == -1 || oldgid != gid) {
 
745
                if (setresgid(-1, gid, -1) == -1) {
 
746
                        isc__strerror(errno, strbuf, sizeof(strbuf));
 
747
                        ns_main_earlywarning("unable to set effective "
 
748
                                             "gid to %d: %s", gid, strbuf);
 
749
                }
 
750
        }
 
751
#endif
 
752
 
 
753
#if defined(HAVE_SETEUID)
 
754
        if (geteuid() != uid && seteuid(uid) == -1) {
 
755
                isc__strerror(errno, strbuf, sizeof(strbuf));
 
756
                ns_main_earlywarning("unable to set effective uid to %ld: %s",
 
757
                                     (long)uid, strbuf);
 
758
        }
 
759
#elif defined(HAVE_SETRESUID)
 
760
        if (getresuid(&tmpu, &olduid, &tmpu) == -1 || olduid != uid) {
 
761
                if (setresuid(-1, uid, -1) == -1) {
 
762
                        isc__strerror(errno, strbuf, sizeof(strbuf));
 
763
                        ns_main_earlywarning("unable to set effective "
 
764
                                             "uid to %d: %s", uid, strbuf);
 
765
                }
 
766
        }
 
767
#endif
 
768
}
 
769
 
 
770
FILE *
 
771
ns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user) {
 
772
        char strbuf[ISC_STRERRORSIZE], *f;
 
773
        FILE *fp;
 
774
        int fd;
 
775
 
 
776
        /*
 
777
         * Make the containing directory if it doesn't exist.
 
778
         */
 
779
        f = strdup(filename);
 
780
        if (f == NULL) {
 
781
                isc__strerror(errno, strbuf, sizeof(strbuf));
 
782
                ns_main_earlywarning("couldn't strdup() '%s': %s",
 
783
                                     filename, strbuf);
 
784
                return (NULL);
 
785
        }
 
786
        if (mkdirpath(f, ns_main_earlywarning) == -1) {
 
787
                free(f);
 
788
                return (NULL);
 
789
        }
 
790
        free(f);
 
791
 
 
792
        if (switch_user && runas_pw != NULL) {
 
793
                /* Set UID/GID to the one we'll be running with eventually */
 
794
                setperms(runas_pw->pw_uid, runas_pw->pw_gid);
 
795
 
 
796
                fd = safe_open(filename, mode, ISC_FALSE);
 
797
 
 
798
#ifndef HAVE_LINUXTHREADS
 
799
                /* Restore UID/GID to root */
 
800
                setperms(0, 0);
 
801
#endif /* HAVE_LINUXTHREADS */
 
802
 
 
803
                if (fd == -1) {
 
804
#ifndef HAVE_LINUXTHREADS
 
805
                        fd = safe_open(filename, mode, ISC_FALSE);
 
806
                        if (fd != -1) {
 
807
                                ns_main_earlywarning("Required root "
 
808
                                                     "permissions to open "
 
809
                                                     "'%s'.", filename);
 
810
                        } else {
 
811
                                ns_main_earlywarning("Could not open "
 
812
                                                     "'%s'.", filename);
 
813
                        }
 
814
                        ns_main_earlywarning("Please check file and "
 
815
                                             "directory permissions "
 
816
                                             "or reconfigure the filename.");
 
817
#else /* HAVE_LINUXTHREADS */
 
818
                        ns_main_earlywarning("Could not open "
 
819
                                             "'%s'.", filename);
 
820
                        ns_main_earlywarning("Please check file and "
 
821
                                             "directory permissions "
 
822
                                             "or reconfigure the filename.");
 
823
#endif /* HAVE_LINUXTHREADS */
 
824
                }
 
825
        } else {
 
826
                fd = safe_open(filename, mode, ISC_FALSE);
 
827
        }
 
828
 
 
829
        if (fd < 0) {
 
830
                isc__strerror(errno, strbuf, sizeof(strbuf));
 
831
                ns_main_earlywarning("could not open file '%s': %s",
 
832
                                     filename, strbuf);
 
833
                return (NULL);
 
834
        }
 
835
 
 
836
        fp = fdopen(fd, "w");
 
837
        if (fp == NULL) {
 
838
                isc__strerror(errno, strbuf, sizeof(strbuf));
 
839
                ns_main_earlywarning("could not fdopen() file '%s': %s",
 
840
                                     filename, strbuf);
 
841
        }
 
842
 
 
843
        return (fp);
 
844
}
 
845
 
708
846
void
709
847
ns_os_writepidfile(const char *filename, isc_boolean_t first_time) {
710
 
        int fd;
711
848
        FILE *lockfile;
712
 
        size_t len;
713
849
        pid_t pid;
714
850
        char strbuf[ISC_STRERRORSIZE];
715
851
        void (*report)(const char *, ...);
725
861
        if (filename == NULL)
726
862
                return;
727
863
 
728
 
        len = strlen(filename);
729
 
        pidfile = malloc(len + 1);
 
864
        pidfile = strdup(filename);
730
865
        if (pidfile == NULL) {
731
866
                isc__strerror(errno, strbuf, sizeof(strbuf));
732
 
                (*report)("couldn't malloc '%s': %s", filename, strbuf);
733
 
                return;
734
 
        }
735
 
 
736
 
        /* This is safe. */
737
 
        strcpy(pidfile, filename);
738
 
 
739
 
        /*
740
 
         * Make the containing directory if it doesn't exist.
741
 
         */
742
 
        if (mkdirpath(pidfile, report) == -1) {
743
 
                free(pidfile);
744
 
                pidfile = NULL;
745
 
                return;
746
 
        }
747
 
 
748
 
        fd = safe_open(filename, ISC_FALSE);
749
 
        if (fd < 0) {
750
 
                isc__strerror(errno, strbuf, sizeof(strbuf));
751
 
                (*report)("couldn't open pid file '%s': %s", filename, strbuf);
752
 
                free(pidfile);
753
 
                pidfile = NULL;
754
 
                return;
755
 
        }
756
 
        lockfile = fdopen(fd, "w");
 
867
                (*report)("couldn't strdup() '%s': %s", filename, strbuf);
 
868
                return;
 
869
        }
 
870
 
 
871
        lockfile = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
 
872
                                  first_time);
757
873
        if (lockfile == NULL) {
758
 
                isc__strerror(errno, strbuf, sizeof(strbuf));
759
 
                (*report)("could not fdopen() pid file '%s': %s",
760
 
                          filename, strbuf);
761
 
                (void)close(fd);
762
874
                cleanup_pidfile();
763
875
                return;
764
876
        }