The branch, master has been updated via 7fa91fc smbd: Fix coredump on failing chdir during logoff via 0d3000b selftest: Add test for failing chdir call in smbd via b0e1fc7 selftest: Make location of log file available in tests via 8b6402f selftest: Add share for error injection testing via 24623d5 vfs_error_inject: Add new module via b468245 gpo: Test that unapply works via ac56f87 gpo: Only commit the earliest change to the log via 9ace234 gpo: Fix the empty apply log via 045d900 libgpo: Remedy some longer lines via 8065c2f libgpo: Tidy up some if statements via cb29ccc libgpo: typo credentaials -> credentials via a194fb3 libgpo: Always check for ldap_server argument from 964bc8d markdown: Rename ms_markdown.py -> ms_schema_markdown.py
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 7fa91fc4791d076c609eaf119753e38dd3c50a1c Author: Christof Schmitt <c...@samba.org> Date: Wed Dec 13 11:34:23 2017 -0700 smbd: Fix coredump on failing chdir during logoff server_exit does an internal tree disconnect which requires a chdir to the share directory. In case the file system encountered a problem and the chdir call returns an error, this triggers a SERVER_EXIT_ABNORMAL which in turn results in a panic and a coredump. As the log already indicates the problem (chdir returned an error), avoid the SERVER_EXIT_ABNORMAL in this case and not trigger a coredump. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13189 Signed-off-by: Christof Schmitt <c...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Sat Dec 16 01:56:06 CET 2017 on sn-devel-144 commit 0d3000be2af8f8c4a37892d95ae694ad834d7b3a Author: Christof Schmitt <c...@samba.org> Date: Wed Dec 13 12:58:18 2017 -0700 selftest: Add test for failing chdir call in smbd BUG: https://bugzilla.samba.org/show_bug.cgi?id=13189 Signed-off-by: Christof Schmitt <c...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit b0e1fc74fdacecb86f46b47e527b3fdf1906d27b Author: Christof Schmitt <c...@samba.org> Date: Wed Dec 13 12:47:31 2017 -0700 selftest: Make location of log file available in tests BUG: https://bugzilla.samba.org/show_bug.cgi?id=13189 Signed-off-by: Christof Schmitt <c...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 8b6402f3e5ff98c2701e626e47246b2400f76e5f Author: Christof Schmitt <c...@samba.org> Date: Wed Dec 13 11:34:05 2017 -0700 selftest: Add share for error injection testing BUG: https://bugzilla.samba.org/show_bug.cgi?id=13189 Signed-off-by: Christof Schmitt <c...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 24623d53256c2424563709dedc19af1a106ccc73 Author: Christof Schmitt <c...@samba.org> Date: Fri Dec 8 15:29:07 2017 -0700 vfs_error_inject: Add new module This module allow injecting errors in vfs calls. It only implements one case (return ESTALE from chdir), but the idea is to extend this to more vfs functions and more errors when needed. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13189 Signed-off-by: Christof Schmitt <c...@samba.org> Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit b468245c325bd9078b5a501972aec72533dd0d39 Author: David Mulder <dmul...@suse.com> Date: Wed Dec 6 10:16:11 2017 -0700 gpo: Test that unapply works Signed-off-by: David Mulder <dmul...@suse.com> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Jeremy Allison <j...@samba.org> commit ac56f870182054942aff462bf226d52edd927468 Author: David Mulder <dmul...@suse.com> Date: Fri Dec 1 11:18:55 2017 -0700 gpo: Only commit the earliest change to the log Otherwise we overwrite the original value, leaving the setting tattooed on unapplied Signed-off-by: David Mulder <dmul...@suse.com> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Jeremy Allison <j...@samba.org> commit 9ace2343ab24829a37bae6cbf0c72cb6d101cb9f Author: David Mulder <dmul...@suse.com> Date: Mon Nov 20 06:41:19 2017 -0700 gpo: Fix the empty apply log The apply log wasn't being saved, apparently the pointers to elements of the tree were getting lost. Signed-off-by: David Mulder <dmul...@suse.com> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Jeremy Allison <j...@samba.org> commit 045d900e8baa4f8b862064c36d9c0d1de0e96697 Author: Garming Sam <garm...@catalyst.net.nz> Date: Wed Nov 22 11:00:56 2017 +1300 libgpo: Remedy some longer lines Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Jeremy Allison <j...@samba.org> commit 8065c2f443a60f4d04a5257736ef9af9b3d0f832 Author: Garming Sam <garm...@catalyst.net.nz> Date: Wed Nov 22 11:00:35 2017 +1300 libgpo: Tidy up some if statements Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Jeremy Allison <j...@samba.org> commit cb29ccca722f887a1e29dcea72de1eb4037e01d8 Author: Garming Sam <garm...@catalyst.net.nz> Date: Wed Nov 22 10:58:55 2017 +1300 libgpo: typo credentaials -> credentials Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Jeremy Allison <j...@samba.org> commit a194fb3821ab72b3d5fa9d9047cccd8fa415c4a5 Author: Garming Sam <garm...@catalyst.net.nz> Date: Wed Nov 22 10:57:18 2017 +1300 libgpo: Always check for ldap_server argument Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: libgpo/pygpo.c | 118 +++++++++++++++++++----------- python/samba/gpclass.py | 67 +++++++++-------- selftest/selftest.pl | 1 + selftest/target/Samba3.pm | 4 ++ source3/modules/vfs_error_inject.c | 100 ++++++++++++++++++++++++++ source3/modules/wscript_build | 7 ++ source3/script/tests/test_smbd_error.sh | 56 +++++++++++++++ source3/selftest/tests.py | 3 + source3/smbd/server_exit.c | 4 -- source3/wscript | 1 + source4/scripting/bin/samba_gpoupdate | 4 +- source4/torture/gpo/apply.c | 124 +++++++++++++++++++++++++------- 12 files changed, 386 insertions(+), 103 deletions(-) create mode 100644 source3/modules/vfs_error_inject.c create mode 100755 source3/script/tests/test_smbd_error.sh Changeset truncated at 500 lines: diff --git a/libgpo/pygpo.c b/libgpo/pygpo.c index d7bb173..7a02a0d 100644 --- a/libgpo/pygpo.c +++ b/libgpo/pygpo.c @@ -54,11 +54,14 @@ static PyGetSetDef GPO_setters[] = { NULL}, {discard_const_p(char, "file_sys_path"), (getter)GPO_get_file_sys_path, NULL, NULL, NULL}, - {discard_const_p(char, "display_name"), (getter)GPO_get_display_name, NULL, - NULL, NULL}, - {discard_const_p(char, "name"), (getter)GPO_get_name, NULL, NULL, NULL}, - {discard_const_p(char, "link"), (getter)GPO_get_link, NULL, NULL, NULL}, - {discard_const_p(char, "user_extensions"), (getter)GPO_get_user_extensions, + {discard_const_p(char, "display_name"), (getter)GPO_get_display_name, + NULL, NULL, NULL}, + {discard_const_p(char, "name"), (getter)GPO_get_name, NULL, NULL, + NULL}, + {discard_const_p(char, "link"), (getter)GPO_get_link, NULL, NULL, + NULL}, + {discard_const_p(char, "user_extensions"), + (getter)GPO_get_user_extensions, NULL, NULL, NULL}, {discard_const_p(char, "machine_extensions"), (getter)GPO_get_machine_extensions, NULL, NULL, NULL}, @@ -81,7 +84,8 @@ static PyObject *py_gpo_get_unix_path(PyObject *self, PyObject *args, discard_const_p(char *, kwlist), &cache_dir)) { PyErr_SetString(PyExc_SystemError, - "Failed to parse arguments to gpo_get_unix_path()"); + "Failed to parse arguments to " + "gpo_get_unix_path()"); goto out; } @@ -113,7 +117,8 @@ out: } static PyMethodDef GPO_methods[] = { - {"get_unix_path", (PyCFunction)py_gpo_get_unix_path, METH_KEYWORDS, NULL }, + {"get_unix_path", (PyCFunction)py_gpo_get_unix_path, METH_KEYWORDS, + NULL }, {NULL} }; @@ -155,18 +160,20 @@ static int py_ads_init(ADS *self, PyObject *args, PyObject *kwds) PyObject *lp_obj = NULL; struct loadparm_context *lp_ctx = NULL; - static const char *kwlist[] = {"ldap_server", "loadparm_context", - "credentials", NULL}; + static const char *kwlist[] = { + "ldap_server", "loadparm_context", "credentials", NULL + }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|O", discard_const_p(char *, kwlist), - &ldap_server, &lp_obj, &py_creds)) + &ldap_server, &lp_obj, &py_creds)) { return -1; + } if (py_creds) { if (!py_check_dcerpc_type(py_creds, "samba.credentials", "Credentials")) { PyErr_Format(PyExc_TypeError, - "Expected samba.credentaials " + "Expected samba.credentials " "for credentials argument"); return -1; } @@ -192,11 +199,16 @@ static int py_ads_init(ADS *self, PyObject *args, PyObject *kwds) } else { realm = lp_realm(); workgroup = lp_workgroup(); - if (!ldap_server) return -1; } - if ( !(self->ads_ptr = ads_init(realm, workgroup, ldap_server)) ) + if (ldap_server == NULL) { return -1; + } + + self->ads_ptr = ads_init(realm, workgroup, ldap_server); + if (self->ads_ptr == NULL) { + return -1; + } return 0; } @@ -216,35 +228,43 @@ static PyObject* py_ads_connect(ADS *self) status = ads_connect_user_creds(self->ads_ptr); if (!ADS_ERR_OK(status)) { - PyErr_SetString(PyExc_SystemError, "ads_connect() failed"); + PyErr_SetString(PyExc_SystemError, + "ads_connect() failed"); TALLOC_FREE(frame); Py_RETURN_FALSE; } } else { - char *passwd; - - if (asprintf(&(self->ads_ptr->auth.user_name), "%s$", - lp_netbios_name()) == -1) { - PyErr_SetString(PyExc_SystemError, "Failed to asprintf"); + char *passwd = NULL; + int ret = asprintf(&(self->ads_ptr->auth.user_name), "%s$", + lp_netbios_name()); + if (ret == -1) { + PyErr_SetString(PyExc_SystemError, + "Failed to asprintf"); TALLOC_FREE(frame); Py_RETURN_FALSE; - } else + } else { self->ads_ptr->auth.flags |= ADS_AUTH_USER_CREDS; + } + if (!secrets_init()) { - PyErr_SetString(PyExc_SystemError, "secrets_init() failed"); + PyErr_SetString(PyExc_SystemError, + "secrets_init() failed"); TALLOC_FREE(frame); Py_RETURN_FALSE; } - if (!(passwd = - secrets_fetch_machine_password(self->ads_ptr->server.workgroup, - NULL, NULL))) { + + passwd = secrets_fetch_machine_password(self->ads_ptr->server.workgroup, + NULL, NULL); + if (passwd == NULL) { PyErr_SetString(PyExc_SystemError, - "Failed to fetch the machine account password"); + "Failed to fetch the machine account " + "password"); TALLOC_FREE(frame); Py_RETURN_FALSE; } self->ads_ptr->auth.password = smb_xstrdup(passwd); - self->ads_ptr->auth.realm = smb_xstrdup(self->ads_ptr->server.realm); + self->ads_ptr->auth.realm = + smb_xstrdup(self->ads_ptr->server.realm); if (!strupper_m(self->ads_ptr->auth.realm)) { PyErr_SetString(PyExc_SystemError, "Failed to strdup"); TALLOC_FREE(frame); @@ -254,7 +274,8 @@ static PyObject* py_ads_connect(ADS *self) status = ads_connect(self->ads_ptr); if (!ADS_ERR_OK(status)) { - PyErr_SetString(PyExc_SystemError, "ads_connect() failed"); + PyErr_SetString(PyExc_SystemError, + "ads_connect() failed"); TALLOC_FREE(frame); SAFE_FREE(passwd); Py_RETURN_FALSE; @@ -309,14 +330,15 @@ static ADS_STATUS find_samaccount(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char *dn = NULL; uint32_t uac = 0; - filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)", samaccountname); + filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)", + samaccountname); if (filter == NULL) { status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); goto out; } - status = ads_do_search_all(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE, - filter, attrs, &res); + status = ads_do_search_all(ads, ads->config.bind_path, + LDAP_SCOPE_SUBTREE, filter, attrs, &res); if (!ADS_ERR_OK(status)) { goto out; @@ -344,7 +366,7 @@ static ADS_STATUS find_samaccount(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, if (dn_ret) { *dn_ret = talloc_strdup(mem_ctx, dn); - if (!*dn_ret) { + if (*dn_ret == NULL) { status = ADS_ERROR(LDAP_NO_MEMORY); goto out; } @@ -376,22 +398,27 @@ static PyObject *py_ads_get_gpo_list(ADS *self, PyObject *args, PyObject *kwds) discard_const_p(char *, kwlist), &samaccountname)) { PyErr_SetString(PyExc_SystemError, - "Failed to parse arguments to py_ads_get_gpo_list()"); + "Failed to parse arguments to " + "py_ads_get_gpo_list()"); goto out; } frame = talloc_stackframe(); - status = find_samaccount(self->ads_ptr, frame, samaccountname, &uac, &dn); + status = find_samaccount(self->ads_ptr, frame, + samaccountname, &uac, &dn); if (!ADS_ERR_OK(status)) { TALLOC_FREE(frame); - PyErr_SetString(PyExc_SystemError, "Failed to find samAccountName"); + PyErr_SetString(PyExc_SystemError, + "Failed to find samAccountName"); goto out; } - if (uac & UF_WORKSTATION_TRUST_ACCOUNT || uac & UF_SERVER_TRUST_ACCOUNT) { + if (uac & UF_WORKSTATION_TRUST_ACCOUNT || + uac & UF_SERVER_TRUST_ACCOUNT) { flags |= GPO_LIST_FLAG_MACHINE; - status = gp_get_machine_token(self->ads_ptr, frame, dn, &token); + status = gp_get_machine_token(self->ads_ptr, frame, dn, + &token); } else { status = ads_get_sid_token(self->ads_ptr, frame, dn, &token); } @@ -444,7 +471,8 @@ out: static PyMethodDef ADS_methods[] = { { "connect", (PyCFunction)py_ads_connect, METH_NOARGS, "Connect to the LDAP server" }, - { "get_gpo_list", (PyCFunction)py_ads_get_gpo_list, METH_KEYWORDS, NULL }, + { "get_gpo_list", (PyCFunction)py_ads_get_gpo_list, METH_KEYWORDS, + NULL }, { NULL } }; @@ -460,7 +488,8 @@ static PyTypeObject ads_ADSType = { }; static PyMethodDef py_gpo_methods[] = { - {"gpo_get_sysvol_gpt_version", (PyCFunction) py_gpo_get_sysvol_gpt_version, + {"gpo_get_sysvol_gpt_version", + (PyCFunction)py_gpo_get_sysvol_gpt_version, METH_VARARGS, NULL}, {NULL} }; @@ -471,18 +500,25 @@ void initgpo(void) PyObject *m; debug_setup_talloc_log(); + /* Instantiate the types */ m = Py_InitModule3("gpo", py_gpo_methods, "libgpo python bindings"); - if (m == NULL) return; + if (m == NULL) { + return; + } + PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING)); - if (PyType_Ready(&ads_ADSType) < 0) + if (PyType_Ready(&ads_ADSType) < 0) { return; + } + PyModule_AddObject(m, "ADS_STRUCT", (PyObject *)&ads_ADSType); - if (pytalloc_BaseObject_PyType_Ready(&GPOType) < 0) + if (pytalloc_BaseObject_PyType_Ready(&GPOType) < 0) { return; + } Py_INCREF((PyObject *)(void *)&GPOType); PyModule_AddObject(m, "GROUP_POLICY_OBJECT", diff --git a/python/samba/gpclass.py b/python/samba/gpclass.py index 5a0ca9f..00330eb 100644 --- a/python/samba/gpclass.py +++ b/python/samba/gpclass.py @@ -95,10 +95,11 @@ class gp_log: self.gpdb = etree.fromstring(db_log) else: self.gpdb = etree.Element('gp') - self.user = self.gpdb.find('user[@name="%s"]' % user) - if self.user is None: - self.user = etree.SubElement(self.gpdb, 'user') - self.user.attrib['name'] = user + self.user = user + user_obj = self.gpdb.find('user[@name="%s"]' % user) + if user_obj is None: + user_obj = etree.SubElement(self.gpdb, 'user') + user_obj.attrib['name'] = user def state(self, value): ''' Policy application state @@ -113,7 +114,8 @@ class gp_log: ''' # If we're enforcing, but we've unapplied, apply instead if value == GPOSTATE.ENFORCE: - apply_log = self.user.find('applylog') + user_obj = self.gpdb.find('user[@name="%s"]' % self.user) + apply_log = user_obj.find('applylog') if apply_log is None or len(apply_log) == 0: self._state = GPOSTATE.APPLY else: @@ -126,14 +128,16 @@ class gp_log: param guid - guid value of the GPO from which we're applying policy ''' - self.guid = self.user.find('guid[@value="%s"]' % guid) - if self.guid is None: - self.guid = etree.SubElement(self.user, 'guid') - self.guid.attrib['value'] = guid + self.guid = guid + user_obj = self.gpdb.find('user[@name="%s"]' % self.user) + obj = user_obj.find('guid[@value="%s"]' % guid) + if obj is None: + obj = etree.SubElement(user_obj, 'guid') + obj.attrib['value'] = guid if self._state == GPOSTATE.APPLY: - apply_log = self.user.find('applylog') + apply_log = user_obj.find('applylog') if apply_log is None: - apply_log = etree.SubElement(self.user, 'applylog') + apply_log = etree.SubElement(user_obj, 'applylog') item = etree.SubElement(apply_log, 'guid') item.attrib['count'] = '%d' % (len(apply_log)-1) item.attrib['value'] = guid @@ -145,14 +149,15 @@ class gp_log: Removes the GPO guid last added to the list, which is the most recently applied GPO. ''' - apply_log = self.user.find('applylog') + user_obj = self.gpdb.find('user[@name="%s"]' % self.user) + apply_log = user_obj.find('applylog') if apply_log is not None: ret = apply_log.find('guid[@count="%d"]' % (len(apply_log)-1)) if ret is not None: apply_log.remove(ret) return ret.attrib['value'] - if len(apply_log) == 0 and apply_log in self.user: - self.user.remove(apply_log) + if len(apply_log) == 0 and apply_log in user_obj: + user_obj.remove(apply_log) return None def store(self, gp_ext_name, attribute, old_val): @@ -164,16 +169,18 @@ class gp_log: ''' if self._state == GPOSTATE.UNAPPLY or self._state == GPOSTATE.ENFORCE: return None - assert self.guid is not None, "gpo guid was not set" - ext = self.guid.find('gp_ext[@name="%s"]' % gp_ext_name) + user_obj = self.gpdb.find('user[@name="%s"]' % self.user) + guid_obj = user_obj.find('guid[@value="%s"]' % self.guid) + assert guid_obj is not None, "gpo guid was not set" + ext = guid_obj.find('gp_ext[@name="%s"]' % gp_ext_name) if ext is None: - ext = etree.SubElement(self.guid, 'gp_ext') + ext = etree.SubElement(guid_obj, 'gp_ext') ext.attrib['name'] = gp_ext_name attr = ext.find('attribute[@name="%s"]' % attribute) if attr is None: attr = etree.SubElement(ext, 'attribute') attr.attrib['name'] = attribute - attr.text = old_val + attr.text = old_val def retrieve(self, gp_ext_name, attribute): ''' Retrieve a stored attribute from the gp_log @@ -182,8 +189,10 @@ class gp_log: return - The value of the attribute prior to policy application ''' - assert self.guid is not None, "gpo guid was not set" - ext = self.guid.find('gp_ext[@name="%s"]' % gp_ext_name) + user_obj = self.gpdb.find('user[@name="%s"]' % self.user) + guid_obj = user_obj.find('guid[@value="%s"]' % self.guid) + assert guid_obj is not None, "gpo guid was not set" + ext = guid_obj.find('gp_ext[@name="%s"]' % gp_ext_name) if ext is not None: attr = ext.find('attribute[@name="%s"]' % attribute) if attr is not None: @@ -198,12 +207,14 @@ class gp_log: return - list of (attr, value, apply_func) tuples for unapplying policy ''' - assert self.guid is not None, "gpo guid was not set" + user_obj = self.gpdb.find('user[@name="%s"]' % self.user) + guid_obj = user_obj.find('guid[@value="%s"]' % self.guid) + assert guid_obj is not None, "gpo guid was not set" ret = [] data_maps = {} for gp_ext in gp_extensions: data_maps.update(gp_ext.apply_map()) - exts = self.guid.findall('gp_ext') + exts = guid_obj.findall('gp_ext') if exts is not None: for ext in exts: ext_map = {val[0]: val[1] for (key, val) in \ @@ -220,21 +231,19 @@ class gp_log: attribute param attribute - attribute to remove ''' - assert self.guid is not None, "gpo guid was not set" - ext = self.guid.find('gp_ext[@name="%s"]' % gp_ext_name) + user_obj = self.gpdb.find('user[@name="%s"]' % self.user) + guid_obj = user_obj.find('guid[@value="%s"]' % self.guid) + assert guid_obj is not None, "gpo guid was not set" + ext = guid_obj.find('gp_ext[@name="%s"]' % gp_ext_name) if ext is not None: attr = ext.find('attribute[@name="%s"]' % attribute) if attr is not None: ext.remove(attr) if len(ext) == 0: - self.guid.remove(ext) + guid_obj.remove(ext) def commit(self): ''' Write gp_log changes to disk ''' - if len(self.guid) == 0 and self.guid in self.user: - self.user.remove(self.guid) - if len(self.user) == 0 and self.user in self.gpdb: - self.gpdb.remove(self.user) self.gpostore.store(self.username, etree.tostring(self.gpdb, 'utf-8')) class GPOStorage: diff --git a/selftest/selftest.pl b/selftest/selftest.pl index e16696a..8c41459 100755 --- a/selftest/selftest.pl +++ b/selftest/selftest.pl @@ -877,6 +877,7 @@ my @exported_envvars = ( "RESOLV_CONF", "UNACCEPTABLE_PASSWORD", "LOCK_DIR", + "SMBD_TEST_LOG", # nss_wrapper "NSS_WRAPPER_PASSWD", diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index afbc795..229435d 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -2150,6 +2150,10 @@ sub provision($$$$$$$$$) [compound_find] copy = tmp smbd:find async delay usec = 10000 +[error_inject] + copy = tmp + vfs objects = error_inject + include = $libdir/error_inject.conf "; close(CONF); diff --git a/source3/modules/vfs_error_inject.c b/source3/modules/vfs_error_inject.c new file mode 100644 index 0000000..bb5477a --- /dev/null +++ b/source3/modules/vfs_error_inject.c @@ -0,0 +1,100 @@ +/* + * Unix SMB/CIFS implementation. + * Samba VFS module for error injection in VFS calls + * Copyright (C) Christof Schmitt 2017 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" +#include "smbd/smbd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + +struct unix_error_map { + const char *err_str; + int error; +} unix_error_map_array[] = { + { "ESTALE", ESTALE }, +}; + +static int find_unix_error_from_string(const char *err_str) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(unix_error_map_array); i++) { + struct unix_error_map *m = &unix_error_map_array[i]; + + if (strequal(err_str, m->err_str)) { + return m->error; + } + } + + return 0; +} + +static int inject_unix_error(const char *vfs_func, vfs_handle_struct *handle) +{ + const char *err_str; -- Samba Shared Repository