Skip to content

Instantly share code, notes, and snippets.

@yds
Created July 26, 2020 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yds/2e1b2ca7a0f5f1eaed6b5f360bb48e50 to your computer and use it in GitHub Desktop.
Save yds/2e1b2ca7a0f5f1eaed6b5f360bb48e50 to your computer and use it in GitHub Desktop.
Check if sysvol is on filesystem with ZFS ACLs cherry picked from <https://Bugs.FreeBSD.org/bugzilla/show_bug.cgi?id=239105#c47>
From 2664c997587416a2c8c911a75158485a5c98b70b Mon Sep 17 00:00:00 2001
From: John Hixon <john@ixsystems.com>
Date: Sat, 20 May 2017 04:39:37 +0200
Subject: [PATCH] Zfs provision (#1)
Cherry-pick ZFS provisioning code by iXsystems Inc.
* Check if sysvol is on filesystem with ZFS ACLs
(cherry picked from <https://Bugs.FreeBSD.org/bugzilla/show_bug.cgi?id=239105#c47>)
* Check if sysvol is on filesystem with NFSv4 ACLs
(cherry picked from commit ca86f52b78a7b6e7537454a69cf93e7b96210cba)
* Only check targetdir if it is defined (I had assumed it was)
(cherry picked from commit a29050cb2978ce23e3c04a859340dc2664c77a8a)
* Kick samba a little bit into understanding NFSv4 ACLs
(cherry picked from commit 1c7542ff4904b729e311e17464ee76582760c219)
Signed-off-by: Timur I. Bakeyev <timur@iXsystems.com>
diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py
index 5de986463a5..cd3b91f41b9 100644
--- a/python/samba/provision/__init__.py
+++ b/python/samba/provision/__init__.py
@@ -1679,12 +1679,17 @@
s3conf = s3param.get_context()
s3conf.load(lp.configfile)
- file = tempfile.NamedTemporaryFile(dir=os.path.abspath(sysvol))
+ sysvol_dir = os.path.abspath(sysvol)
+
+ file = tempfile.NamedTemporaryFile(dir=sysvol_dir)
try:
try:
- smbd.set_simple_acl(file.name, 0o755, system_session_unix(), gid)
+ if smbd.has_nfsv4_acls(sysvol_dir):
+ smbd.set_simple_nfsv4_acl(file.name, 0o755, gid)
+ else:
+ smbd.set_simple_acl(file.name, 0o755, system_session_unix(), gid)
except OSError:
- if not smbd.have_posix_acls():
+ if not smbd.have_posix_acls() and not smbd.have_nfsv4_acls():
# This clue is only strictly correct for RPM and
# Debian-like Linux systems, but hopefully other users
# will get enough clue from it.
@@ -1973,6 +1978,9 @@
samdb.transaction_commit()
if serverrole == "active directory domain controller":
+ if targetdir and smbd.have_nfsv4_acls() and smbd.has_nfsv4_acls(targetdir):
+ smbd.set_nfsv4_defaults()
+
# Continue setting up sysvol for GPO. This appears to require being
# outside a transaction.
if not skip_sysvolacl:
@@ -2328,6 +2336,9 @@
if not os.path.isdir(paths.netlogon):
os.makedirs(paths.netlogon, 0o755)
+
+ if smbd.have_nfsv4_acls() and smbd.has_nfsv4_acls(paths.sysvol):
+ smbd.set_nfsv4_defaults()
if adminpass is None:
adminpass = samba.generate_random_password(12, 32)
diff --git a/source3/lib/sysacls.c b/source3/lib/sysacls.c
index 0bf3c37edfa..786cd39b5bc 100644
--- a/source3/lib/sysacls.c
+++ b/source3/lib/sysacls.c
@@ -38,6 +38,16 @@
#include "modules/vfs_hpuxacl.h"
#endif
+/*
+ * NFSv4 ACL's should be understood and a first class citizen. Work
+ * needs to be done in librpc/idl/smb_acl.idl for this to occur.
+ */
+#if defined(HAVE_LIBSUNACL) && defined(FREEBSD)
+#if 0
+#include "modules/nfs4_acls.h"
+#endif
+#endif
+
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_ACLS
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index a2fcc4246c9..4b676897fc1 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -2803,9 +2803,24 @@
} else {
if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
+ } else if (pathconf(get_dyn_STATEDIR(), _PC_ACL_NFS4) == 1){
+ /*
+ * By default, the samba sysvol is located in the statedir.
+ * Provisioning will fail in setntacl unless we have zfsacl enabled.
+ * Unfortunately, at this point the smb.conf has not been generated.
+ * This workaround is freebsd-specific.
+ */
+ lp_do_parameter(-1, "vfs objects", "dfs_samba4 zfsacl");
} else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
} else {
+ /*
+ * This should only set dfs_samba4 and leave acl_xattr
+ * to be set later (or zfsacl). The only reason the
+ * decision can't be made here to load acl_xattr or
+ * zfsacl is that we don't have access to what the
+ * target directory is.
+ */
lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
}
}
diff --git a/source3/smbd/pysmbd.c b/source3/smbd/pysmbd.c
index 63fc5d68c33..f5a536ee186 100644
--- a/source3/smbd/pysmbd.c
+++ b/source3/smbd/pysmbd.c
@@ -419,6 +419,20 @@
return acl;
}
+static SMB_ACL_T make_simple_nfsv4_acl(TALLOC_CTX *mem_ctx,
+ gid_t gid,
+ mode_t chmod_mode)
+{
+ /*
+ * This function needs to create an NFSv4 ACL. Currently, the only way
+ * to do so is to use the operating system interface, or to use the
+ * functions in source3/modules/nfs4_acls.c. These seems ugly and
+ * hacky. NFSv4 ACL's should be a first class citizen and
+ * librpc/idl/smb_acl.idl should be modified accordingly.
+ */
+ return NULL;
+}
+
/*
set a simple ACL on a file, as a test
*/
@@ -491,7 +505,58 @@
Py_RETURN_NONE;
}
+
/*
+ set a simple NFSv4 ACL on a file, as a test
+ */
+static PyObject *py_smbd_set_simple_nfsv4_acl(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ const char * const kwnames[] = { "fname", "mode", "gid", "service", NULL };
+ char *fname, *service = NULL;
+ int ret;
+ int mode, gid = -1;
+ SMB_ACL_T acl;
+ TALLOC_CTX *frame;
+ connection_struct *conn;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si|iz",
+ discard_const_p(char *, kwnames),
+ &fname, &mode, &gid, &service))
+ return NULL;
+
+ frame = talloc_stackframe();
+
+ acl = make_simple_nfsv4_acl(frame, gid, mode);
+ if (acl == NULL) {
+ TALLOC_FREE(frame);
+ Py_RETURN_NONE;
+ }
+
+ conn = get_conn_tos(service, NULL);
+ if (!conn) {
+ TALLOC_FREE(frame);
+ Py_RETURN_NONE;
+ }
+
+ /*
+ * SMB_ACL_TYPE_ACCESS -> ACL_TYPE_ACCESS -> Not valid for NFSv4 ACL
+ */
+ ret = 0;
+
+ /* ret = set_sys_acl_conn(fname, SMB_ACL_TYPE_ACCESS, acl, conn); */
+
+ if (ret != 0) {
+ TALLOC_FREE(frame);
+ errno = ret;
+ return PyErr_SetFromErrno(PyExc_OSError);
+ }
+
+ TALLOC_FREE(frame);
+
+ Py_RETURN_NONE;
+}
+
+/*
chown a file
*/
static PyObject *py_smbd_chown(PyObject *self, PyObject *args, PyObject *kwargs)
@@ -665,7 +730,7 @@
}
/*
- check if we have ACL support
+ check if we have POSIX.1e ACL support
*/
static PyObject *py_smbd_have_posix_acls(PyObject *self,
PyObject *Py_UNUSED(ignored))
@@ -677,7 +742,87 @@
#endif
}
+static PyObject *py_smbd_has_posix_acls(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ const char * const kwnames[] = { "path", NULL };
+ char *path = NULL;
+ TALLOC_CTX *frame;
+ struct statfs fs;
+ int ret = false;
+
+ frame = talloc_stackframe();
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|z",
+ discard_const_p(char *, kwnames), &path)) {
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+
+ if (statfs(path, &fs) != 0) {
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+
+ if (fs.f_flags & MNT_ACLS)
+ ret = true;
+
+ TALLOC_FREE(frame);
+ return PyBool_FromLong(ret);
+}
+
/*
+ check if we have NFSv4 ACL support
+ */
+static PyObject *py_smbd_have_nfsv4_acls(PyObject *self)
+{
+#ifdef HAVE_LIBSUNACL
+ return PyBool_FromLong(true);
+#else
+ return PyBool_FromLong(false);
+#endif
+}
+
+static PyObject *py_smbd_has_nfsv4_acls(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ const char * const kwnames[] = { "path", NULL };
+ char *path = NULL;
+ TALLOC_CTX *frame;
+ struct statfs fs;
+ int ret = false;
+
+ frame = talloc_stackframe();
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|z",
+ discard_const_p(char *, kwnames), &path)) {
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+
+ if (statfs(path, &fs) != 0) {
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+
+ if (fs.f_flags & MNT_NFS4ACLS)
+ ret = true;
+
+ TALLOC_FREE(frame);
+ return PyBool_FromLong(ret);
+}
+
+
+static PyObject *py_smbd_set_nfsv4_defaults(PyObject *self)
+{
+ /*
+ * This should really be done in source3/param/loadparm.c
+ */
+#if defined(HAVE_LIBSUNACL) && defined(FREEBSD)
+ lp_do_parameter(-1, "vfs objects", "dfs_samba4 zfsacl");
+#endif
+ Py_RETURN_NONE;
+}
+
+/*
set the NT ACL on a file
*/
static PyObject *py_smbd_set_nt_acl(PyObject *self, PyObject *args, PyObject *kwargs)
@@ -1124,8 +1269,26 @@
{ "have_posix_acls",
(PyCFunction)py_smbd_have_posix_acls, METH_NOARGS,
NULL },
+ { "has_posix_acls",
+ PY_DISCARD_FUNC_SIG(PyCFunction, py_smbd_has_posix_acls),
+ METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "have_nfsv4_acls",
+ (PyCFunction)py_smbd_have_nfsv4_acls, METH_NOARGS,
+ NULL },
+ { "has_nfsv4_acls",
+ PY_DISCARD_FUNC_SIG(PyCFunction, py_smbd_has_nfsv4_acls),
+ METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "set_nfsv4_defaults",
+ (PyCFunction)py_smbd_set_nfsv4_defaults, METH_NOARGS,
+ NULL },
{ "set_simple_acl",
PY_DISCARD_FUNC_SIG(PyCFunction, py_smbd_set_simple_acl),
+ METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "set_simple_nfsv4_acl",
+ PY_DISCARD_FUNC_SIG(PyCFunction, py_smbd_set_simple_nfsv4_acl),
METH_VARARGS|METH_KEYWORDS,
NULL },
{ "set_nt_acl",
--
2.14.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment