diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index 5ea70796f6..66c911b025 100644 --- a/lib/dns/dst_api.c +++ b/lib/dns/dst_api.c @@ -29,18 +29,21 @@ /*! \file */ +#include +#include #include #include #include #include +#include #include #include #include -#include #include #include #include +#include #include #include #include @@ -893,6 +896,66 @@ out: return (result); } +FILE * +dst_key_open(char *tmpname, mode_t mode) { + /* Create public key file. */ + int fd = mkstemp(tmpname); + if (fd == -1) { + return (NULL); + } + + if (fchmod(fd, mode & ~isc_os_umask()) != 0) { + goto error; + } + + FILE *fp = fdopen(fd, "w"); + if (fp == NULL) { + goto error; + } + + return (fp); +error: + (void)close(fd); + (void)unlink(tmpname); + return (NULL); +} + +isc_result_t +dst_key_close(char *tmpname, FILE *fp, char *filename) { + if ((fflush(fp) != 0) || (ferror(fp) != 0)) { + return (dst_key_cleanup(tmpname, fp)); + } + + if (rename(tmpname, filename) != 0) { + return (dst_key_cleanup(tmpname, fp)); + } + + if (fclose(fp) != 0) { + /* + * This is in fact error, but we don't care at this point, + * as the file has been already flushed to disk. + */ + } + + return (ISC_R_SUCCESS); +} + +isc_result_t +dst_key_cleanup(char *tmpname, FILE *fp) { + if (ftruncate(fileno(fp), 0) != 0) { + /* + * ftruncate() result can't be ignored, but we don't care, as + * any sensitive data are protected by the permissions, and + * unlinked in the next step, this is just a good practice. + */ + } + + (void)unlink(tmpname); + (void)fclose(fp); + + return (DST_R_WRITEERROR); +} + isc_result_t dst_key_buildinternal(const dns_name_t *name, unsigned int alg, unsigned int bits, unsigned int flags, @@ -1368,7 +1431,8 @@ dst_key_buildfilename(const dst_key_t *key, int type, const char *directory, isc_buffer_t *out) { REQUIRE(VALID_KEY(key)); REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC || - type == DST_TYPE_STATE || type == 0); + type == DST_TYPE_STATE || type == DST_TYPE_TEMPLATE || + type == 0); return (buildfilename(key->key_name, key->key_id, key->key_alg, type, directory, out)); @@ -1988,9 +2052,10 @@ static isc_result_t write_key_state(const dst_key_t *key, int type, const char *directory) { FILE *fp; isc_buffer_t fileb; + isc_buffer_t tmpb; char filename[NAME_MAX]; - isc_result_t ret; - isc_fsaccess_t access; + char tmpname[NAME_MAX]; + isc_result_t result; REQUIRE(VALID_KEY(key)); @@ -1998,33 +2063,33 @@ write_key_state(const dst_key_t *key, int type, const char *directory) { * Make the filename. */ isc_buffer_init(&fileb, filename, sizeof(filename)); - ret = dst_key_buildfilename(key, DST_TYPE_STATE, directory, &fileb); - if (ret != ISC_R_SUCCESS) { - return (ret); + result = dst_key_buildfilename(key, DST_TYPE_STATE, directory, &fileb); + if (result != ISC_R_SUCCESS) { + return (result); } - /* - * Create public key file. - */ - if ((fp = fopen(filename, "w")) == NULL) { + isc_buffer_init(&tmpb, tmpname, sizeof(tmpname)); + result = dst_key_buildfilename(key, DST_TYPE_TEMPLATE, directory, + &tmpb); + if (result != ISC_R_SUCCESS) { + return (result); + } + + mode_t mode = issymmetric(key) ? S_IRUSR | S_IWUSR + : S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + + /* Create temporary public key file. */ + fp = dst_key_open(tmpname, mode); + if (fp == NULL) { return (DST_R_WRITEERROR); } - if (issymmetric(key)) { - access = 0; - isc_fsaccess_add(ISC_FSACCESS_OWNER, - ISC_FSACCESS_READ | ISC_FSACCESS_WRITE, - &access); - (void)isc_fsaccess_set(filename, access); - } - /* Write key state */ if ((type & DST_TYPE_KEY) == 0) { fprintf(fp, "; This is the state of key %d, for ", key->key_id); - ret = dns_name_print(key->key_name, fp); - if (ret != ISC_R_SUCCESS) { - fclose(fp); - return (ret); + result = dns_name_print(key->key_name, fp); + if (result != ISC_R_SUCCESS) { + return (dst_key_cleanup(tmpname, fp)); } fputc('\n', fp); @@ -2064,13 +2129,11 @@ write_key_state(const dst_key_t *key, int type, const char *directory) { printstate(key, DST_KEY_GOAL, "GoalState", fp); } - fflush(fp); - if (ferror(fp)) { - ret = DST_R_WRITEERROR; + if (result != ISC_R_SUCCESS) { + return (dst_key_cleanup(tmpname, fp)); } - fclose(fp); - return (ret); + return (dst_key_close(tmpname, fp, filename)); } /*% @@ -2079,15 +2142,15 @@ write_key_state(const dst_key_t *key, int type, const char *directory) { static isc_result_t write_public_key(const dst_key_t *key, int type, const char *directory) { FILE *fp; - isc_buffer_t keyb, textb, fileb, classb; + isc_buffer_t keyb, tmpb, textb, fileb, classb; isc_region_t r; + char tmpname[NAME_MAX]; char filename[NAME_MAX]; unsigned char key_array[DST_KEY_MAXSIZE]; char text_array[DST_KEY_MAXTEXTSIZE]; char class_array[10]; isc_result_t ret; dns_rdata_t rdata = DNS_RDATA_INIT; - isc_fsaccess_t access; REQUIRE(VALID_KEY(key)); @@ -2122,19 +2185,19 @@ write_public_key(const dst_key_t *key, int type, const char *directory) { return (ret); } - /* - * Create public key file. - */ - if ((fp = fopen(filename, "w")) == NULL) { - return (DST_R_WRITEERROR); + isc_buffer_init(&tmpb, tmpname, sizeof(tmpname)); + ret = dst_key_buildfilename(key, DST_TYPE_TEMPLATE, directory, &tmpb); + if (ret != ISC_R_SUCCESS) { + return (ret); } - if (issymmetric(key)) { - access = 0; - isc_fsaccess_add(ISC_FSACCESS_OWNER, - ISC_FSACCESS_READ | ISC_FSACCESS_WRITE, - &access); - (void)isc_fsaccess_set(filename, access); + /* Create temporary public key file. */ + mode_t mode = issymmetric(key) ? S_IRUSR | S_IWUSR + : S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + + fp = dst_key_open(tmpname, mode); + if (fp == NULL) { + return (DST_R_WRITEERROR); } /* Write key information in comments */ @@ -2164,6 +2227,9 @@ write_public_key(const dst_key_t *key, int type, const char *directory) { /* Now print the actual key */ ret = dns_name_print(key->key_name, fp); + if (ret != ISC_R_SUCCESS) { + return (dst_key_cleanup(tmpname, fp)); + } fprintf(fp, " "); if (key->key_ttl != 0) { @@ -2172,7 +2238,7 @@ write_public_key(const dst_key_t *key, int type, const char *directory) { isc_buffer_usedregion(&classb, &r); if ((unsigned int)fwrite(r.base, 1, r.length, fp) != r.length) { - ret = DST_R_WRITEERROR; + return (dst_key_cleanup(tmpname, fp)); } if ((type & DST_TYPE_KEY) != 0) { @@ -2183,17 +2249,16 @@ write_public_key(const dst_key_t *key, int type, const char *directory) { isc_buffer_usedregion(&textb, &r); if ((unsigned int)fwrite(r.base, 1, r.length, fp) != r.length) { - ret = DST_R_WRITEERROR; + return (dst_key_cleanup(tmpname, fp)); } fputc('\n', fp); - fflush(fp); - if (ferror(fp)) { - ret = DST_R_WRITEERROR; - } - fclose(fp); - return (ret); + if (ret != ISC_R_SUCCESS) { + return (dst_key_cleanup(tmpname, fp)); + } + + return (dst_key_close(tmpname, fp, filename)); } static isc_result_t @@ -2203,12 +2268,15 @@ buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg, isc_result_t result; REQUIRE(out != NULL); + if ((type & DST_TYPE_PRIVATE) != 0) { suffix = ".private"; } else if ((type & DST_TYPE_PUBLIC) != 0) { suffix = ".key"; } else if ((type & DST_TYPE_STATE) != 0) { suffix = ".state"; + } else if ((type & DST_TYPE_TEMPLATE) != 0) { + suffix = ".XXXXXX"; } if (directory != NULL) { diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h index aa8fda3d7e..40b54dd029 100644 --- a/lib/dns/dst_internal.h +++ b/lib/dns/dst_internal.h @@ -238,6 +238,16 @@ dst__mem_free(void *ptr); void * dst__mem_realloc(void *ptr, size_t size); +/*% + * Secure private file handling + */ +FILE * +dst_key_open(char *tmpname, mode_t mode); +isc_result_t +dst_key_close(char *tmpname, FILE *fp, char *filename); +isc_result_t +dst_key_cleanup(char *tmpname, FILE *fp); + ISC_LANG_ENDDECLS /*! \file */ diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c index 6f6d7b2871..375c1bcf8f 100644 --- a/lib/dns/dst_parse.c +++ b/lib/dns/dst_parse.c @@ -30,11 +30,11 @@ #include "dst_parse.h" #include #include +#include #include #include #include -#include #include #include #include @@ -593,11 +593,13 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, FILE *fp; isc_result_t result; char filename[NAME_MAX]; + char tmpname[NAME_MAX]; char buffer[MAXFIELDSIZE * 2]; - isc_fsaccess_t access; isc_stdtime_t when; uint32_t value; isc_buffer_t b; + isc_buffer_t fileb; + isc_buffer_t tmpb; isc_region_t r; int major, minor; mode_t mode; @@ -612,14 +614,15 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, return (ret); } - isc_buffer_init(&b, filename, sizeof(filename)); - result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &b); + isc_buffer_init(&fileb, filename, sizeof(filename)); + result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, + &fileb); if (result != ISC_R_SUCCESS) { return (result); } result = isc_file_mode(filename, &mode); - if (result == ISC_R_SUCCESS && mode != 0600) { + if (result == ISC_R_SUCCESS && mode != (S_IRUSR | S_IWUSR)) { /* File exists; warn that we are changing its permissions */ int level; @@ -632,14 +635,17 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, filename, (unsigned int)mode); } - if ((fp = fopen(filename, "w")) == NULL) { - return (DST_R_WRITEERROR); + isc_buffer_init(&tmpb, tmpname, sizeof(tmpname)); + result = dst_key_buildfilename(key, DST_TYPE_TEMPLATE, directory, + &tmpb); + if (result != ISC_R_SUCCESS) { + return (result); } - access = 0; - isc_fsaccess_add(ISC_FSACCESS_OWNER, - ISC_FSACCESS_READ | ISC_FSACCESS_WRITE, &access); - (void)isc_fsaccess_set(filename, access); + fp = dst_key_open(tmpname, S_IRUSR | S_IWUSR); + if (fp == NULL) { + return (DST_R_WRITEERROR); + } dst_key_getprivateformat(key, &major, &minor); if (major == 0 && minor == 0) { @@ -710,8 +716,7 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, isc_buffer_init(&b, buffer, sizeof(buffer)); result = isc_base64_totext(&r, sizeof(buffer), "", &b); if (result != ISC_R_SUCCESS) { - fclose(fp); - return (DST_R_INVALIDPRIVATEKEY); + return (dst_key_cleanup(tmpname, fp)); } isc_buffer_usedregion(&b, &r); @@ -742,8 +747,7 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, isc_buffer_init(&b, buffer, sizeof(buffer)); result = dns_time32_totext(when, &b); if (result != ISC_R_SUCCESS) { - fclose(fp); - return (DST_R_INVALIDPRIVATEKEY); + return (dst_key_cleanup(tmpname, fp)); } isc_buffer_usedregion(&b, &r); @@ -755,9 +759,7 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, } } - fflush(fp); - result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS; - fclose(fp); + result = dst_key_close(tmpname, fp, filename); return (result); } diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h index e127aedd19..4f5cf76286 100644 --- a/lib/dns/include/dst/dst.h +++ b/lib/dns/include/dst/dst.h @@ -119,10 +119,11 @@ typedef enum dst_algorithm { #define DST_KEY_MAXTEXTSIZE 2048 /*% 'Type' for dst_read_key() */ -#define DST_TYPE_KEY 0x1000000 /* KEY key */ -#define DST_TYPE_PRIVATE 0x2000000 -#define DST_TYPE_PUBLIC 0x4000000 -#define DST_TYPE_STATE 0x8000000 +#define DST_TYPE_KEY 0x1000000 /* KEY key */ +#define DST_TYPE_PRIVATE 0x2000000 +#define DST_TYPE_PUBLIC 0x4000000 +#define DST_TYPE_STATE 0x8000000 +#define DST_TYPE_TEMPLATE 0x10000000 /* Key timing metadata definitions */ #define DST_TIME_CREATED 0 @@ -772,11 +773,13 @@ dst_key_buildfilename(const dst_key_t *key, int type, const char *directory, /*%< * Generates the filename used by dst to store the specified key. * If directory is NULL, the current directory is assumed. + * If tmp is not NULL, generates a template for mkstemp(). * * Requires: *\li "key" is a valid key *\li "type" is either DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or 0 for no suffix. *\li "out" is a valid buffer + *\li "tmp" is a valid buffer or NULL * * Ensures: *\li the file name will be written to "out", and the used pointer will diff --git a/lib/isc/Makefile.am b/lib/isc/Makefile.am index 9963c8cc60..fb2faba58c 100644 --- a/lib/isc/Makefile.am +++ b/lib/isc/Makefile.am @@ -29,7 +29,6 @@ libisc_la_HEADERS = \ include/isc/error.h \ include/isc/file.h \ include/isc/formatcheck.h \ - include/isc/fsaccess.h \ include/isc/fuzz.h \ include/isc/getaddresses.h \ include/isc/hash.h \ @@ -130,9 +129,6 @@ libisc_la_SOURCES = \ errno2result.h \ error.c \ file.c \ - fsaccess.c \ - fsaccess_common.c \ - fsaccess_common_p.h \ getaddresses.c \ hash.c \ hashmap.c \ diff --git a/lib/isc/fsaccess.c b/lib/isc/fsaccess.c deleted file mode 100644 index 0e5fe650b5..0000000000 --- a/lib/isc/fsaccess.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include "../fsaccess_common_p.h" -#include "errno2result.h" - -isc_result_t -isc_fsaccess_set(const char *path, isc_fsaccess_t access) { - struct stat statb; - mode_t mode; - bool is_dir = false; - isc_fsaccess_t bits; - isc_result_t result; - - if (stat(path, &statb) != 0) { - return (isc__errno2result(errno)); - } - - if ((statb.st_mode & S_IFDIR) != 0) { - is_dir = true; - } else if ((statb.st_mode & S_IFREG) == 0) { - return (ISC_R_INVALIDFILE); - } - - result = isc__fsaccess_check_bad_bits(access, is_dir); - if (result != ISC_R_SUCCESS) { - return (result); - } - - /* - * Done with checking bad bits. Set mode_t. - */ - mode = 0; - -#define SET_AND_CLEAR1(modebit) \ - if ((access & bits) != 0) { \ - mode |= modebit; \ - access &= ~bits; \ - } -#define SET_AND_CLEAR(user, group, other) \ - SET_AND_CLEAR1(user); \ - bits <<= STEP; \ - SET_AND_CLEAR1(group); \ - bits <<= STEP; \ - SET_AND_CLEAR1(other); - - bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY; - - SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH); - - bits = ISC_FSACCESS_WRITE | ISC_FSACCESS_CREATECHILD | - ISC_FSACCESS_DELETECHILD; - - SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH); - - bits = ISC_FSACCESS_EXECUTE | ISC_FSACCESS_ACCESSCHILD; - - SET_AND_CLEAR(S_IXUSR, S_IXGRP, S_IXOTH); - - INSIST(access == 0); - - if (chmod(path, mode) < 0) { - return (isc__errno2result(errno)); - } - - return (ISC_R_SUCCESS); -} diff --git a/lib/isc/fsaccess_common.c b/lib/isc/fsaccess_common.c deleted file mode 100644 index ca497e9758..0000000000 --- a/lib/isc/fsaccess_common.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -/*! \file - * \brief - * This file contains the OS-independent functionality of the API. - */ -#include - -#include -#include -#include -#include - -#include "fsaccess_common_p.h" - -void -isc_fsaccess_add(int trustee, int permission, isc_fsaccess_t *access) { - REQUIRE(trustee <= 0x7); - REQUIRE(permission <= 0xFF); - - if ((trustee & ISC_FSACCESS_OWNER) != 0) { - *access |= permission; - } - - if ((trustee & ISC_FSACCESS_GROUP) != 0) { - *access |= (permission << GROUP); - } - - if ((trustee & ISC_FSACCESS_OTHER) != 0) { - *access |= (permission << OTHER); - } -} - -void -isc_fsaccess_remove(int trustee, int permission, isc_fsaccess_t *access) { - REQUIRE(trustee <= 0x7); - REQUIRE(permission <= 0xFF); - - if ((trustee & ISC_FSACCESS_OWNER) != 0) { - *access &= ~permission; - } - - if ((trustee & ISC_FSACCESS_GROUP) != 0) { - *access &= ~(permission << GROUP); - } - - if ((trustee & ISC_FSACCESS_OTHER) != 0) { - *access &= ~(permission << OTHER); - } -} - -isc_result_t -isc__fsaccess_check_bad_bits(isc_fsaccess_t access, bool is_dir) { - isc_fsaccess_t bits; - - /* - * Check for disallowed user bits. - */ - if (is_dir) { - bits = ISC_FSACCESS_READ | ISC_FSACCESS_WRITE | - ISC_FSACCESS_EXECUTE; - } else { - bits = ISC_FSACCESS_CREATECHILD | ISC_FSACCESS_ACCESSCHILD | - ISC_FSACCESS_DELETECHILD | ISC_FSACCESS_LISTDIRECTORY; - } - - /* - * Set group bad bits. - */ - bits |= bits << STEP; - /* - * Set other bad bits. - */ - bits |= bits << STEP; - - if ((access & bits) != 0) { - if (is_dir) { - return (ISC_R_NOTFILE); - } else { - return (ISC_R_NOTDIRECTORY); - } - } - - return (ISC_R_SUCCESS); -} diff --git a/lib/isc/fsaccess_common_p.h b/lib/isc/fsaccess_common_p.h deleted file mode 100644 index e4ee01f233..0000000000 --- a/lib/isc/fsaccess_common_p.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#pragma once - -/*! - * Shorthand. Maybe ISC__FSACCESS_PERMISSIONBITS should not even be in - * . Could check consistency with sizeof(isc_fsaccess_t) - * and the number of bits in each function. - */ -#define STEP (ISC__FSACCESS_PERMISSIONBITS) -#define GROUP (STEP) -#define OTHER (STEP * 2) - -isc_result_t -isc__fsaccess_check_bad_bits(isc_fsaccess_t access, bool is_dir); diff --git a/lib/isc/include/isc/fsaccess.h b/lib/isc/include/isc/fsaccess.h deleted file mode 100644 index e06903037e..0000000000 --- a/lib/isc/include/isc/fsaccess.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#pragma once - -/*! \file isc/fsaccess.h - * \brief The ISC filesystem access module encapsulates the setting of file - * and directory access permissions into one API that is meant to be - * portable to multiple operating systems. - * - * The two primary operating system flavors that are initially accommodated - * are POSIX and Windows NT 4.0 and later. The Windows NT access model is - * considerable more flexible than POSIX's model (as much as I am loathe to - * admit it), and so the ISC API has a higher degree of complexity than would - * be needed to simply address POSIX's needs. - * - * The full breadth of NT's flexibility is not available either, for the - * present time. Much of it is to provide compatibility with what Unix - * programmers are expecting. This is also due to not yet really needing all - * of the functionality of an NT system (or, for that matter, a POSIX system) - * in BIND9, and so resolving how to handle the various incompatibilities has - * been a purely theoretical exercise with no operational experience to - * indicate how flawed the thinking may be. - * - * Some of the more notable dumbing down of NT for this API includes: - * - *\li Each of FILE_READ_DATA and FILE_READ_EA are set with #ISC_FSACCESS_READ. - * - * \li All of FILE_WRITE_DATA, FILE_WRITE_EA and FILE_APPEND_DATA are - * set with #ISC_FSACCESS_WRITE. FILE_WRITE_ATTRIBUTES is not set - * so as to be consistent with Unix, where only the owner of the file - * or the superuser can change the attributes/mode of a file. - * - * \li Both of FILE_ADD_FILE and FILE_ADD_SUBDIRECTORY are set with - * #ISC_FSACCESS_CREATECHILD. This is similar to setting the WRITE - * permission on a Unix directory. - * - * \li SYNCHRONIZE is always set for files and directories, unless someone - * can give me a reason why this is a bad idea. - * - * \li READ_CONTROL and FILE_READ_ATTRIBUTES are always set; this is - * consistent with Unix, where any file or directory can be stat()'d - * unless the directory path disallows complete access somewhere along - * the way. - * - * \li WRITE_DAC is only set for the owner. This too is consistent with - * Unix, and is tighter security than allowing anyone else to be - * able to set permissions. - * - * \li DELETE is only set for the owner. On Unix the ability to delete - * a file is controlled by the directory permissions, but it isn't - * currently clear to me what happens on NT if the directory has - * FILE_DELETE_CHILD set but a file within it does not have DELETE - * set. Always setting DELETE on the file/directory for the owner - * gives maximum flexibility to the owner without exposing the - * file to deletion by others. - * - * \li WRITE_OWNER is never set. This too is consistent with Unix, - * and is also tighter security than allowing anyone to change the - * ownership of the file apart from the superu..ahem, Administrator. - * - * \li Inheritance is set to NO_INHERITANCE. - * - * Unix's dumbing down includes: - * - * \li The sticky bit cannot be set. - * - * \li setuid and setgid cannot be set. - * - * \li Only regular files and directories can be set. - * - * The rest of this comment discusses a few of the incompatibilities - * between the two systems that need more thought if this API is to - * be extended to accommodate them. - * - * The Windows standard access right "DELETE" doesn't have a direct - * equivalent in the Unix world, so it isn't clear what should be done - * with it. - * - * The Unix sticky bit is not supported. While NT does have a concept - * of allowing users to create files in a directory but not delete or - * rename them, it does not have a concept of allowing them to be deleted - * if they are owned by the user trying to delete/rename. While it is - * probable that something could be cobbled together in NT 5 with inheritance, - * it can't really be done in NT 4 as a single property that you could - * set on a directory. You'd need to coordinate something with file creation - * so that every file created had DELETE set for the owner but no one else. - * - * On Unix systems, setting #ISC_FSACCESS_LISTDIRECTORY sets READ. - * ... setting either #ISC_FSACCESS_CREATECHILD or #ISC_FSACCESS_DELETECHILD - * sets WRITE. - * ... setting #ISC_FSACCESS_ACCESSCHILD sets EXECUTE. - * - * On NT systems, setting #ISC_FSACCESS_LISTDIRECTORY sets FILE_LIST_DIRECTORY. - * ... setting #ISC_FSACCESS_CREATECHILD sets FILE_CREATE_CHILD independently. - * ... setting #ISC_FSACCESS_DELETECHILD sets FILE_DELETE_CHILD independently. - * ... setting #ISC_FSACCESS_ACCESSCHILD sets FILE_TRAVERSE. - * - * Unresolved: XXXDCL - * \li What NT access right controls the ability to rename a file? - * \li How does DELETE work? If a directory has FILE_DELETE_CHILD but a - * file or directory within it does not have DELETE, is that file - * or directory deletable? - * \li To implement isc_fsaccess_get(), mapping an existing Unix permission - * mode_t back to an isc_fsaccess_t is pretty trivial; however, mapping - * an NT DACL could be impossible to do in a responsible way. - * \li Similarly, trying to implement the functionality of being able to - * say "add group writability to whatever permissions already exist" - * could be tricky on NT because of the order-of-entry issue combined - * with possibly having one or more matching ACEs already explicitly - * granting or denying access. Because this functionality is - * not yet needed by the ISC, no code has been written to try to - * solve this problem. - */ - -#include - -#include -#include - -/* - * Trustees. - */ -#define ISC_FSACCESS_OWNER 0x1 /*%< User account. */ -#define ISC_FSACCESS_GROUP 0x2 /*%< Primary group owner. */ -#define ISC_FSACCESS_OTHER 0x4 /*%< Not the owner or the group owner. */ -#define ISC_FSACCESS_WORLD 0x7 /*%< User, Group, Other. */ - -/* - * Types of permission. - */ -#define ISC_FSACCESS_READ 0x00000001 /*%< File only. */ -#define ISC_FSACCESS_WRITE 0x00000002 /*%< File only. */ -#define ISC_FSACCESS_EXECUTE 0x00000004 /*%< File only. */ -#define ISC_FSACCESS_CREATECHILD 0x00000008 /*%< Dir only. */ -#define ISC_FSACCESS_DELETECHILD 0x00000010 /*%< Dir only. */ -#define ISC_FSACCESS_LISTDIRECTORY 0x00000020 /*%< Dir only. */ -#define ISC_FSACCESS_ACCESSCHILD 0x00000040 /*%< Dir only. */ - -/*% - * Adding any permission bits beyond 0x200 would mean typedef'ing - * isc_fsaccess_t as uint64_t, and redefining this value to - * reflect the new range of permission types, Probably to 21 for - * maximum flexibility. The number of bits has to accommodate all of - * the permission types, and three full sets of them have to fit - * within an isc_fsaccess_t. - */ -#define ISC__FSACCESS_PERMISSIONBITS 10 - -ISC_LANG_BEGINDECLS - -void -isc_fsaccess_add(int trustee, int permission, isc_fsaccess_t *access); - -void -isc_fsaccess_remove(int trustee, int permission, isc_fsaccess_t *access); - -isc_result_t -isc_fsaccess_set(const char *path, isc_fsaccess_t access); - -ISC_LANG_ENDDECLS diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h index 0c0b609bc1..09c5527b33 100644 --- a/lib/isc/include/isc/types.h +++ b/lib/isc/include/isc/types.h @@ -38,7 +38,6 @@ typedef struct isc_constregion isc_constregion_t; /*%< Const region */ typedef struct isc_consttextregion isc_consttextregion_t; /*%< Const Text Region */ typedef struct isc_counter isc_counter_t; /*%< Counter */ -typedef uint32_t isc_fsaccess_t; /*%< FS Access */ typedef struct isc_hash isc_hash_t; /*%< Hash */ typedef struct isc_httpd isc_httpd_t; /*%< HTTP client */ typedef void(isc_httpdfree_t)(isc_buffer_t *, void *); /*%< HTTP free function