/*! \file */
+#include <errno.h>
+#include <fcntl.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
+#include <unistd.h>
#include <isc/buffer.h>
#include <isc/dir.h>
#include <isc/file.h>
-#include <isc/fsaccess.h>
#include <isc/lex.h>
#include <isc/mem.h>
#include <isc/once.h>
+#include <isc/os.h>
#include <isc/print.h>
#include <isc/random.h>
#include <isc/refcount.h>
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,
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));
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));
* 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) {
- 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);
}
- if (issymmetric(key)) {
- access = 0;
- isc_fsaccess_add(ISC_FSACCESS_OWNER,
- ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
- &access);
- (void)isc_fsaccess_set(filename, access);
+ 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);
}
/* 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);
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));
}
/*%
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));
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 */
/* 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) {
isc_buffer_usedregion(&classb, &r);
if ((unsigned)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) {
isc_buffer_usedregion(&textb, &r);
if ((unsigned)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;
+
+ if (ret != ISC_R_SUCCESS) {
+ return (dst_key_cleanup(tmpname, fp));
}
- fclose(fp);
- return (ret);
+ return (dst_key_close(tmpname, fp, filename));
}
static isc_result_t
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) {
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 */
#include "dst_parse.h"
#include <inttypes.h>
#include <stdbool.h>
+#include <unistd.h>
#include <isc/base64.h>
#include <isc/dir.h>
#include <isc/file.h>
-#include <isc/fsaccess.h>
#include <isc/lex.h>
#include <isc/mem.h>
#include <isc/print.h>
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;
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;
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) {
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);
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);
}
}
- fflush(fp);
- result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS;
- fclose(fp);
+ result = dst_key_close(tmpname, fp, filename);
return (result);
}
#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
/*%<
* 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
include/isc/eventclass.h \
include/isc/file.h \
include/isc/formatcheck.h \
- include/isc/fsaccess.h \
include/isc/fuzz.h \
include/isc/glob.h \
include/isc/hash.h \
error.c \
event.c \
file.c \
- fsaccess.c \
- fsaccess_common.c \
- fsaccess_common_p.h \
glob.c \
hash.c \
heap.c \
+++ /dev/null
-/*
- * 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 <errno.h>
-#include <stdbool.h>
-#include <sys/stat.h>
-
-#include <isc/fsaccess.h>
-#include <isc/result.h>
-#include <isc/types.h>
-#include <isc/util.h>
-
-#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);
-}
+++ /dev/null
-/*
- * 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 <stdbool.h>
-
-#include <isc/fsaccess.h>
-#include <isc/result.h>
-#include <isc/types.h>
-#include <isc/util.h>
-
-#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);
-}
+++ /dev/null
-/*
- * 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
- * <isc/fsaccess.h>. 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);
+++ /dev/null
-/*
- * 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 <inttypes.h>
-
-#include <isc/lang.h>
-#include <isc/types.h>
-
-/*
- * 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
typedef struct isc_event isc_event_t; /*%< Event */
typedef ISC_LIST(isc_event_t) isc_eventlist_t; /*%< Event List */
typedef unsigned int isc_eventtype_t; /*%< Event Type */
-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