[SCM] Samba Shared Repository - branch v4-18-test updated
Jule Anger
janger at samba.org
Fri Aug 4 08:05:01 UTC 2023
The branch, v4-18-test has been updated
via e911424161d lib/cmdline: Also redact --newpassword in samba_cmdline_burn()
via c11b6d6b6a4 lib/cmdline: Also burn the --password2 parameter if given
via e724909ac06 samba-tool: Use samba.glue.get_burnt_cmdline rather than regex
via 8c2c1b5413a python: Add glue.burn_commandline() method
via 534425ba2f6 python: Remove const from PyList_AsStringList()
via 2ed39136875 python: Move PyList_AsStringList to common code so we can reuse
via 7f87d028516 lib/cmdline: Return if the commandline was redacted in samba_cmdline_burn()
from c40f1619d96 s3/modules: Fix DFS links when widelinks = yes
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-18-test
- Log -----------------------------------------------------------------
commit e911424161d838ab09cc582ae56843c84ee52bc1
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 21 15:39:28 2023 +1200
lib/cmdline: Also redact --newpassword in samba_cmdline_burn()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15289
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
Autobuild-Date(master): Fri Jul 21 06:16:30 UTC 2023 on atb-devel-224
(cherry picked from commit 76ad44f446c42832e87b2c60a4731a8de3a0018f)
RN: post-exec password redaction for samba-tool is more reliable for
fully random passwords as it no longer uses regular expressions
containing the password value itself.
Autobuild-User(v4-18-test): Jule Anger <janger at samba.org>
Autobuild-Date(v4-18-test): Fri Aug 4 08:05:00 UTC 2023 on atb-devel-224
commit c11b6d6b6a43730f49809eb725931900b99b941d
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 21 14:35:20 2023 +1200
lib/cmdline: Also burn the --password2 parameter if given
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15289
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
(cherry picked from commit 414b3803bb6a1b12c44b52ab1ff64a8b7f61fd03)
commit e724909ac0640bb2aa27275e4368b3758de7bde5
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 21 13:30:39 2023 +1200
samba-tool: Use samba.glue.get_burnt_cmdline rather than regex
This use avoids having two different methods to match on command-line
passwords. We already have a dependency on the setproctitle python
module, and this does not change as the (C) libbsd setproctitle()
can't be run from within a python module.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15289
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
(cherry picked from commit a53ebc288f47329c997d52325eeeb5e91ce43b75)
commit 8c2c1b5413a9e0d6b82b07e5571c43a6f3c50618
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 21 13:29:22 2023 +1200
python: Add glue.burn_commandline() method
This uses samba_cmdline_burn() to as to have common
command line redaction code.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15289
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
(cherry picked from commit 3f9e455898554b726bf1689f743b2d9cb6b59537)
commit 534425ba2f6527666401b9cab6960c977ca22308
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 21 14:32:46 2023 +1200
python: Remove const from PyList_AsStringList()
The returned strings are not owned by python, so need not be const.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15289
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
(cherry picked from commit 5afd206d1d8f0344a2f1fa7a238204d1fb164eda)
commit 2ed3913687513995cd006ca5590eac426ccfbeec
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 21 14:31:30 2023 +1200
python: Move PyList_AsStringList to common code so we can reuse
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15289
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
(cherry picked from commit fd81759e2ed44cac3bc67243a39256f953969103)
commit 7f87d028516b6f006c944efa44be92f84a8b1c52
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 21 15:27:00 2023 +1200
lib/cmdline: Return if the commandline was redacted in samba_cmdline_burn()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15289
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
(cherry picked from commit 848fea1a01a4ddc1598150823d5d0784d3ef0be4)
-----------------------------------------------------------------------
Summary of changes:
lib/cmdline/cmdline.c | 17 +++++++++--
lib/cmdline/cmdline.h | 4 ++-
python/modules.c | 35 +++++++++++++++++++++
python/modules.h | 7 +++++
python/pyglue.c | 60 ++++++++++++++++++++++++++++++++++++
python/samba/getopt.py | 69 ++++++++++++------------------------------
python/samba/tests/cred_opt.py | 14 ++++++---
python/wscript | 1 +
source4/auth/pyauth.c | 38 ++---------------------
source4/auth/wscript_build | 4 ++-
10 files changed, 156 insertions(+), 93 deletions(-)
Changeset truncated at 500 lines:
diff --git a/lib/cmdline/cmdline.c b/lib/cmdline/cmdline.c
index 9f4e964f289..aade4ca365e 100644
--- a/lib/cmdline/cmdline.c
+++ b/lib/cmdline/cmdline.c
@@ -134,8 +134,9 @@ void samba_cmdline_set_machine_account_fn(
cli_credentials_set_machine_account_fn = fn;
}
-void samba_cmdline_burn(int argc, char *argv[])
+bool samba_cmdline_burn(int argc, char *argv[])
{
+ bool burnt = false;
bool found = false;
bool is_user = false;
char *p = NULL;
@@ -145,9 +146,13 @@ void samba_cmdline_burn(int argc, char *argv[])
for (i = 0; i < argc; i++) {
p = argv[i];
if (p == NULL) {
- return;
+ return false;
}
+ /*
+ * Take care that this list must be in longest-match
+ * first order
+ */
if (strncmp(p, "-U", 2) == 0) {
ulen = 2;
found = true;
@@ -156,9 +161,15 @@ void samba_cmdline_burn(int argc, char *argv[])
ulen = 6;
found = true;
is_user = true;
+ } else if (strncmp(p, "--password2", 11) == 0) {
+ ulen = 11;
+ found = true;
} else if (strncmp(p, "--password", 10) == 0) {
ulen = 10;
found = true;
+ } else if (strncmp(p, "--newpassword", 13) == 0) {
+ ulen = 13;
+ found = true;
}
if (found) {
@@ -180,8 +191,10 @@ void samba_cmdline_burn(int argc, char *argv[])
memset_s(p, strlen(p), '\0', strlen(p));
found = false;
is_user = false;
+ burnt = true;
}
}
+ return burnt;
}
static bool is_popt_table_end(const struct poptOption *o)
diff --git a/lib/cmdline/cmdline.h b/lib/cmdline/cmdline.h
index e254a1db5c3..b9cb4764bea 100644
--- a/lib/cmdline/cmdline.h
+++ b/lib/cmdline/cmdline.h
@@ -147,8 +147,10 @@ void samba_cmdline_set_machine_account_fn(
* @param[in] argc The number of arguments.
*
* @param[in] argv[] The argument array we should remove secrets from.
+ *
+ * @return true if a password was removed, false otherwise.
*/
-void samba_cmdline_burn(int argc, char *argv[]);
+bool samba_cmdline_burn(int argc, char *argv[]);
/**
* @brief Sanity check the command line options.
diff --git a/python/modules.c b/python/modules.c
index d8b330b6b28..ca563ff07d2 100644
--- a/python/modules.c
+++ b/python/modules.c
@@ -71,3 +71,38 @@ error:
Py_XDECREF(mod_sys);
return false;
}
+
+char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
+ const char *paramname)
+{
+ char **ret;
+ Py_ssize_t i;
+ if (!PyList_Check(list)) {
+ PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
+ return NULL;
+ }
+ ret = talloc_array(NULL, char *, PyList_Size(list)+1);
+ if (ret == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ for (i = 0; i < PyList_Size(list); i++) {
+ const char *value;
+ Py_ssize_t size;
+ PyObject *item = PyList_GetItem(list, i);
+ if (!PyUnicode_Check(item)) {
+ PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
+ return NULL;
+ }
+ value = PyUnicode_AsUTF8AndSize(item, &size);
+ if (value == NULL) {
+ talloc_free(ret);
+ return NULL;
+ }
+ ret[i] = talloc_strndup(ret, value, size);
+ }
+ ret[i] = NULL;
+ return ret;
+}
+
diff --git a/python/modules.h b/python/modules.h
index 75108d77907..356937d71f9 100644
--- a/python/modules.h
+++ b/python/modules.h
@@ -20,7 +20,14 @@
#ifndef __SAMBA_PYTHON_MODULES_H__
#define __SAMBA_PYTHON_MODULES_H__
+#include <talloc.h>
+
bool py_update_path(void);
/* discard signature of 'func' in favour of 'target_sig' */
#define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func
+
+char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
+ const char *paramname);
+
#endif /* __SAMBA_PYTHON_MODULES_H__ */
+
diff --git a/python/pyglue.c b/python/pyglue.c
index 64be7389b70..8378aa797d4 100644
--- a/python/pyglue.c
+++ b/python/pyglue.c
@@ -20,11 +20,13 @@
#include <Python.h>
#include "python/py3compat.h"
#include "includes.h"
+#include "python/modules.h"
#include "version.h"
#include "param/pyparam.h"
#include "lib/socket/netif.h"
#include "lib/util/debug.h"
#include "librpc/ndr/ndr_private.h"
+#include "lib/cmdline/cmdline.h"
void init_glue(void);
static PyObject *PyExc_NTSTATUSError;
@@ -461,6 +463,62 @@ static PyObject *py_strstr_m(PyObject *self, PyObject *args)
return result;
}
+static PyObject *py_get_burnt_commandline(PyObject *self, PyObject *args)
+{
+ PyObject *cmdline_as_list, *ret;
+ char *burnt_cmdline = NULL;
+ Py_ssize_t i, argc;
+ char **argv = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+ bool burnt;
+
+ if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &cmdline_as_list))
+ {
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+
+ argc = PyList_GET_SIZE(cmdline_as_list);
+
+ if (argc == 0) {
+ TALLOC_FREE(frame);
+ Py_RETURN_NONE;
+ }
+
+ argv = PyList_AsStringList(frame, cmdline_as_list, "sys.argv");
+ if (argv == NULL) {
+ return NULL;
+ }
+
+ burnt = samba_cmdline_burn(argc, argv);
+ if (!burnt) {
+ TALLOC_FREE(frame);
+ Py_RETURN_NONE;
+ }
+
+ for (i = 0; i < argc; i++) {
+ if (i == 0) {
+ burnt_cmdline = talloc_strdup(frame,
+ argv[i]);
+ } else {
+ burnt_cmdline
+ = talloc_asprintf_append(burnt_cmdline,
+ " %s",
+ argv[i]);
+ }
+ if (burnt_cmdline == NULL) {
+ PyErr_NoMemory();
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+ }
+
+ ret = PyUnicode_FromString(burnt_cmdline);
+ TALLOC_FREE(frame);
+
+ return ret;
+}
+
static PyMethodDef py_misc_methods[] = {
{ "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
"generate_random_str(len) -> string\n"
@@ -520,6 +578,8 @@ static PyMethodDef py_misc_methods[] = {
METH_NOARGS, "is Samba built with selftest enabled?" },
{ "ndr_token_max_list_size", (PyCFunction)py_ndr_token_max_list_size,
METH_NOARGS, "How many NDR internal tokens is too many for this build?" },
+ { "get_burnt_commandline", (PyCFunction)py_get_burnt_commandline,
+ METH_VARARGS, "Return a redacted commandline to feed to setproctitle (None if no redaction required)" },
{0}
};
diff --git a/python/samba/getopt.py b/python/samba/getopt.py
index ff8aead3f8d..e9ff3de5b34 100644
--- a/python/samba/getopt.py
+++ b/python/samba/getopt.py
@@ -29,7 +29,7 @@ from samba.credentials import (
MUST_USE_KERBEROS,
)
import sys
-
+from samba._glue import get_burnt_commandline
OptionError = optparse.OptionValueError
@@ -40,6 +40,25 @@ class SambaOptions(optparse.OptionGroup):
def __init__(self, parser):
from samba import fault_setup
fault_setup()
+
+ # This removes passwords from the commandline via
+ # setproctitle() but makes no change to python sys.argv so we
+ # can continue to process as normal
+ #
+ # get_burnt_commandline returns None if no change is needed
+ new_proctitle = get_burnt_commandline(sys.argv)
+ if new_proctitle is not None:
+ try:
+ import setproctitle
+ setproctitle.setproctitle(new_proctitle)
+
+ except ModuleNotFoundError:
+ msg = ("WARNING: Using passwords on command line is insecure. "
+ "Installing the setproctitle python module will hide "
+ "these from shortly after program start.\n")
+ sys.stderr.write(msg)
+ sys.stderr.flush()
+
from samba.param import LoadParm
optparse.OptionGroup.__init__(self, parser, "Samba Common Options")
self.add_option("-s", "--configfile", action="callback",
@@ -203,53 +222,6 @@ class CredentialsOptions(optparse.OptionGroup):
help="DEPRECATED: Migrate to --use-kerberos", callback=self._set_kerberos_legacy)
self.creds = Credentials()
- def _ensure_secure_proctitle(self, opt_str, secret_data, data_type="password"):
- """ Make sure no sensitive data (e.g. password) resides in proctitle. """
- import re
- try:
- import setproctitle
- except ModuleNotFoundError:
- msg = ("WARNING: Using %s on command line is insecure. "
- "Please install the setproctitle python module.\n"
- % data_type)
- sys.stderr.write(msg)
- sys.stderr.flush()
- return False
- # Regex to search and replace secret data + option with.
- # .*[ ]+ -> Before the option must be one or more spaces.
- # [= ] -> The option and the secret data might be separated by space
- # or equal sign.
- # [ ]*.* -> After the secret data might be one, many or no space.
- pass_opt_re_str = "(.*[ ]+)(%s[= ]%s)([ ]*.*)" % (opt_str, secret_data)
- pass_opt_re = re.compile(pass_opt_re_str)
- # Get current proctitle.
- cur_proctitle = setproctitle.getproctitle()
- # Make sure we build the correct regex.
- if not pass_opt_re.match(cur_proctitle):
- msg = ("Unable to hide %s in proctitle. This is most likely "
- "a bug!\n" % data_type)
- sys.stderr.write(msg)
- sys.stderr.flush()
- return False
- # String to replace secret data with.
- secret_data_replacer = "xxx"
- # Build string to replace secret data and option with. And as we dont
- # want to change anything else than the secret data within the proctitle
- # we have to check if the option was passed with space or equal sign as
- # separator.
- opt_pass_with_eq = "%s=%s" % (opt_str, secret_data)
- opt_pass_part = re.sub(pass_opt_re_str, r'\2', cur_proctitle)
- if opt_pass_part == opt_pass_with_eq:
- replace_str = "%s=%s" % (opt_str, secret_data_replacer)
- else:
- replace_str = "%s %s" % (opt_str, secret_data_replacer)
- # Build new proctitle:
- new_proctitle = re.sub(pass_opt_re_str,
- r'\1' + replace_str + r'\3',
- cur_proctitle)
- # Set new proctitle.
- setproctitle.setproctitle(new_proctitle)
-
def _add_option(self, *args1, **kwargs):
if self.special_name is None:
return self.add_option(*args1, **kwargs)
@@ -269,7 +241,6 @@ class CredentialsOptions(optparse.OptionGroup):
self.creds.set_domain(arg)
def _set_password(self, option, opt_str, arg, parser):
- self._ensure_secure_proctitle(opt_str, arg, "password")
self.creds.set_password(arg)
self.ask_for_password = False
self.machine_pass = False
diff --git a/python/samba/tests/cred_opt.py b/python/samba/tests/cred_opt.py
index 82c6434d9c8..02019b5022a 100644
--- a/python/samba/tests/cred_opt.py
+++ b/python/samba/tests/cred_opt.py
@@ -22,13 +22,13 @@
import optparse
import os
from contextlib import contextmanager
-from samba.getopt import CredentialsOptions
+from samba.getopt import CredentialsOptions, SambaOptions
import samba.tests
import setproctitle
import sys
password_opt = '--password=super_secret_password'
-clear_password_opt = '--password=xxx'
+clear_password_opt = '--password '
@contextmanager
def auth_fle_opt(auth_file_path, long_opt=True):
@@ -48,11 +48,17 @@ class CredentialsOptionsTests(samba.tests.TestCase):
def setUp(self):
super(samba.tests.TestCase, self).setUp()
self.old_proctitle = setproctitle.getproctitle()
- setproctitle.setproctitle('%s %s' % (self.old_proctitle, password_opt))
- sys.argv.append(password_opt)
+
+ # We must append two options to get the " " we look for in the
+ # test after the redacted password
+ sys.argv.extend([password_opt, "--realm=samba.org"])
def test_clear_proctitle_password(self):
parser = optparse.OptionParser()
+
+ # The password burning is on the SambaOptions __init__()
+ sambaopts = SambaOptions(parser)
+ parser.add_option_group(sambaopts)
credopts = CredentialsOptions(parser)
parser.add_option_group(credopts)
(opts, args) = parser.parse_args()
diff --git a/python/wscript b/python/wscript
index abe88b00129..a4573c57c6e 100644
--- a/python/wscript
+++ b/python/wscript
@@ -117,6 +117,7 @@ def build(bld):
samba-util
netif
ndr
+ cmdline
%s
''' % (pyparam_util, pytalloc_util),
realname='samba/_glue.so')
diff --git a/source4/auth/pyauth.c b/source4/auth/pyauth.c
index ec6065d7d0a..b41108b7072 100644
--- a/source4/auth/pyauth.c
+++ b/source4/auth/pyauth.c
@@ -350,40 +350,6 @@ static PyObject *py_session_info_set_unix(PyObject *module,
}
-static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
- const char *paramname)
-{
- const char **ret;
- Py_ssize_t i;
- if (!PyList_Check(list)) {
- PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
- return NULL;
- }
- ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
- if (ret == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
-
- for (i = 0; i < PyList_Size(list); i++) {
- const char *value;
- Py_ssize_t size;
- PyObject *item = PyList_GetItem(list, i);
- if (!PyUnicode_Check(item)) {
- PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
- return NULL;
- }
- value = PyUnicode_AsUTF8AndSize(item, &size);
- if (value == NULL) {
- talloc_free(ret);
- return NULL;
- }
- ret[i] = talloc_strndup(ret, value, size);
- }
- ret[i] = NULL;
- return ret;
-}
-
static PyObject *PyAuthContext_FromContext(struct auth4_context *auth_context)
{
return pytalloc_reference(&PyAuthContext, auth_context);
@@ -401,7 +367,7 @@ static PyObject *py_auth_context_new(PyTypeObject *type, PyObject *args, PyObjec
struct tevent_context *ev;
struct ldb_context *ldb = NULL;
NTSTATUS nt_status;
- const char **methods;
+ const char *const *methods;
const char *const kwnames[] = {"lp_ctx", "ldb", "methods", NULL};
@@ -447,7 +413,7 @@ static PyObject *py_auth_context_new(PyTypeObject *type, PyObject *args, PyObjec
mem_ctx, ev, NULL, lp_ctx, &auth_context);
} else {
if (py_methods != Py_None) {
- methods = PyList_AsStringList(mem_ctx, py_methods, "methods");
+ methods = (const char * const *)PyList_AsStringList(mem_ctx, py_methods, "methods");
if (methods == NULL) {
talloc_free(mem_ctx);
return NULL;
diff --git a/source4/auth/wscript_build b/source4/auth/wscript_build
index 9b94143ba7c..57bb9f751c6 100644
--- a/source4/auth/wscript_build
+++ b/source4/auth/wscript_build
@@ -85,10 +85,12 @@ pytalloc_util = bld.pyembed_libname('pytalloc-util')
pyparam_util = bld.pyembed_libname('pyparam_util')
pyldb_util = bld.pyembed_libname('pyldb-util')
pycredentials = 'pycredentials'
+libpython = bld.pyembed_libname('LIBPYTHON')
+
bld.SAMBA_PYTHON('pyauth',
source='pyauth.c',
public_deps='auth_system_session',
- deps='samdb %s %s %s %s auth4' % (pytalloc_util, pyparam_util, pyldb_util, pycredentials),
+ deps=f'samdb {pytalloc_util} {pyparam_util} {pyldb_util} {pycredentials} {libpython} auth4',
realname='samba/auth.so'
)
--
Samba Shared Repository
More information about the samba-cvs
mailing list