The branch, master has been updated via 4ca9683 s3-param: added lp_set_cmdline() and --option= parameter via f6a631b s4-resolve: added resolve_name_ex_send() via cecc58e s4-auth: make the disabled acct messages a bit less verbose via b7060c7 s4-selftest: try DNS before bcast in selftest via efbc702 s4-resolve: add a default domain for unqualified names in file backend via 39599e9 s4-pidl: added a test for all generated rpc interfaces via 71f2ebc pidl: cope with dom_sid28 in python generator via eccb22c doc: patched bind9 is no longer needed via e2fdcf1 pynet: fixed ref count error on Py_None via 58d92ce pidl-python: cope with NULL pointers in more places via e7e3958 pytalloc: treat a NULL ptr as Py_None via 9f5dcb2 s4-net: use CommandError() in net rodc from 768475d s4:dsdb Fix attribute being searched for in dereference against Fedora DS
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 4ca96834f3b77757d1e03fbc5290677b6724b785 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Aug 11 13:35:14 2010 +1000 s3-param: added lp_set_cmdline() and --option= parameter Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit f6a631bdec3ec2aba8a923136b66edf36273d9f2 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Aug 31 14:00:37 2010 +1000 s4-resolve: added resolve_name_ex_send() this allows access to the flags that control name resolution Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit cecc58e0582a8574f239a26e354c00a6d570c3d5 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Aug 31 12:28:55 2010 +1000 s4-auth: make the disabled acct messages a bit less verbose raise the debug level Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit b7060c7c5c78d7a7416707c6217fe163c1183e2d Author: Andrew Tridgell <tri...@samba.org> Date: Tue Aug 31 12:07:40 2010 +1000 s4-selftest: try DNS before bcast in selftest this better reflects real usage commit efbc702b1eac7c35b0d64d45a8043db3642361a0 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Aug 31 12:07:07 2010 +1000 s4-resolve: add a default domain for unqualified names in file backend this better emulates what happens with real DNS commit 39599e949b9231fa5d88b1a6830b442c1faba1d9 Author: Andrew Tridgell <tri...@samba.org> Date: Mon Aug 30 15:41:22 2010 +1000 s4-pidl: added a test for all generated rpc interfaces this tries to instantiate all types in all generated python RPC interfaces, then checks that all attributes can be read, written and compared. commit 71f2ebcae09a3581cb27966b44387a10ea89236d Author: Andrew Tridgell <tri...@samba.org> Date: Mon Aug 30 15:37:11 2010 +1000 pidl: cope with dom_sid28 in python generator treated the same as dom_sid2 commit eccb22c9fb21f6b439dd6ced03e946f84dccd455 Author: Andrew Tridgell <tri...@samba.org> Date: Mon Aug 30 15:29:26 2010 +1000 doc: patched bind9 is no longer needed bind9.7.2rc1 contains all the patches needed to work with Samba4 krb5 DNS updates with w2k8r2. commit e2fdcf1a7a977d6984abae71d24b9dbdac19bbce Author: Andrew Tridgell <tri...@samba.org> Date: Sat Aug 28 22:18:00 2010 +1000 pynet: fixed ref count error on Py_None ensure we don't run out of None ... Pair-Programmed-With: Jelmer Vernooij <jel...@samba.org> commit 58d92cefe266e423f05dec3a2fef91ebc870c350 Author: Andrew Tridgell <tri...@samba.org> Date: Sat Aug 28 22:00:21 2010 +1000 pidl-python: cope with NULL pointers in more places NULL is converted to Py_None commit e7e39584a9dcfd7d98dc10b88baa53019a77e652 Author: Andrew Tridgell <tri...@samba.org> Date: Sat Aug 28 21:53:27 2010 +1000 pytalloc: treat a NULL ptr as Py_None commit 9f5dcb2235b42177bc325a48930917b5d68308e4 Author: Andrew Tridgell <tri...@samba.org> Date: Fri Aug 27 12:08:49 2010 +1000 s4-net: use CommandError() in net rodc this integrates better with the net command Pair-Programmed-With: Jelmer Vernooij <jel...@samba.org> ----------------------------------------------------------------------- Summary of changes: examples/bind9-patches/README | 6 + lib/talloc/pytalloc.c | 28 ++++- lib/talloc/pytalloc.h | 4 + pidl/lib/Parse/Pidl/Samba4/Python.pm | 16 +- selftest/target/Samba4.pm | 2 +- source3/include/proto.h | 2 + source3/include/smb.h | 1 + source3/lib/popt_common.c | 10 ++ source3/param/loadparm.c | 156 +++++++++++++++++++- source4/auth/sam.c | 12 +- source4/libcli/resolve/file.c | 20 ++- source4/libcli/resolve/resolve.c | 41 ++++- source4/libnet/py_net.c | 2 +- source4/scripting/python/samba/netcmd/rodc.py | 8 +- .../scripting/python/samba/tests/dcerpc/testrpc.py | 113 ++++++++++++++ 15 files changed, 382 insertions(+), 39 deletions(-) create mode 100644 source4/scripting/python/samba/tests/dcerpc/testrpc.py Changeset truncated at 500 lines: diff --git a/examples/bind9-patches/README b/examples/bind9-patches/README index 172d0e6..7bc965e 100644 --- a/examples/bind9-patches/README +++ b/examples/bind9-patches/README @@ -1,3 +1,9 @@ +NOTE! These patches are now incorporated in bind9 releases from +9.7.2RC1 and onwards. You no longer need a patched version of bind9 to +work with krb5 DNS updates and Samba4. + +--------------------------------- + These patches fix the TSIG-GSS dynamic DNS updates in bind9 to allow dynamic updates to work with recent windows versions. diff --git a/lib/talloc/pytalloc.c b/lib/talloc/pytalloc.c index 92b7b94..c9c6027 100644 --- a/lib/talloc/pytalloc.c +++ b/lib/talloc/pytalloc.c @@ -68,7 +68,13 @@ PyObject *py_talloc_steal(PyTypeObject *py_type, void *ptr) */ PyObject *py_talloc_reference_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr) { - py_talloc_Object *ret = (py_talloc_Object *)py_type->tp_alloc(py_type, 0); + py_talloc_Object *ret; + + if (ptr == NULL) { + Py_RETURN_NONE; + } + + ret = (py_talloc_Object *)py_type->tp_alloc(py_type, 0); ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { return NULL; @@ -100,5 +106,25 @@ static void py_cobject_talloc_free(void *ptr) PyObject *PyCObject_FromTallocPtr(void *ptr) { + if (ptr == NULL) { + Py_RETURN_NONE; + } return PyCObject_FromVoidPtr(ptr, py_cobject_talloc_free); } + +PyObject *PyString_FromString_check_null(const char *ptr) +{ + if (ptr == NULL) { + Py_RETURN_NONE; + } + return PyString_FromString(ptr); +} + +PyObject *PyUnicode_Decode_check_null(const void *ptr, size_t len, + const char *charset, const char *options) +{ + if (ptr == NULL) { + Py_RETURN_NONE; + } + return PyUnicode_Decode(ptr, len, charset, options); +} diff --git a/lib/talloc/pytalloc.h b/lib/talloc/pytalloc.h index cdcc57b..caa388a 100644 --- a/lib/talloc/pytalloc.h +++ b/lib/talloc/pytalloc.h @@ -54,4 +54,8 @@ PyObject *py_talloc_default_repr(PyObject *py_obj); PyObject *PyCObject_FromTallocPtr(void *); +PyObject *PyString_FromString_check_null(const char *ptr); +PyObject *PyUnicode_Decode_check_null(const void *ptr, size_t len, + const char *charset, const char *options); + #endif /* _PY_TALLOC_H_ */ diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm index 05c11be..e9956d3 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -769,7 +769,7 @@ sub use_type_variable($$) my ($self, $orig_ctype) = @_; # FIXME: Have a global lookup table for types that look different on the # wire than they are named in C? - if ($orig_ctype->{NAME} eq "dom_sid2") { + if ($orig_ctype->{NAME} eq "dom_sid2" or $orig_ctype->{NAME} eq "dom_sid28") { $orig_ctype->{NAME} = "dom_sid"; } my $ctype = resolveType($orig_ctype); @@ -873,7 +873,7 @@ sub ConvertObjectFromPythonData($$$$$$;$) my $ctype_name = $self->use_type_variable($ctype); unless (defined ($ctype_name)) { error($location, "Unable to determine origin of type `" . mapTypeName($ctype) . "'"); - $self->pidl("PyErr_SetString(PyExc_TypeError, \"Can not convert C Type " . mapTypeName($ctype) . " to Python\");"); + $self->pidl("PyErr_SetString(PyExc_TypeError, \"Can not convert C Type " . mapTypeName($ctype) . " from Python\");"); return; } $self->pidl("PY_CHECK_TYPE($ctype_name, $cvar, $fail);"); @@ -895,12 +895,12 @@ sub ConvertObjectFromPythonData($$$$$$;$) if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") { $self->pidl("$target = PyString_AsString($cvar);"); return; - } + } if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "dnsp_name") { $self->pidl("$target = PyString_AsString($cvar);"); return; - } + } if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") { @@ -1050,13 +1050,13 @@ sub ConvertScalarToPython($$$) } if (($ctypename eq "string" or $ctypename eq "nbt_string" or $ctypename eq "nbt_name" or $ctypename eq "wrepl_nbt_name")) { - return "PyString_FromString($cvar)"; + return "PyString_FromString_check_null($cvar)"; } # Not yet supported if ($ctypename eq "string_array") { return "PyCObject_FromTallocPtr($cvar)"; } - if ($ctypename eq "ipv4address") { return "PyString_FromString($cvar)"; } - if ($ctypename eq "dnsp_name") { return "PyString_FromString($cvar)"; } + if ($ctypename eq "ipv4address") { return "PyString_FromString_check_null($cvar)"; } + if ($ctypename eq "dnsp_name") { return "PyString_FromString_check_null($cvar)"; } if ($ctypename eq "pointer") { return "PyCObject_FromTallocPtr($cvar)"; } @@ -1139,7 +1139,7 @@ sub ConvertObjectToPythonLevel($$$$$$) if (is_charset_array($e, $l)) { # FIXME: Use Unix charset setting rather than utf-8 - $self->pidl("$py_var = PyUnicode_Decode($var_name, strlen($var_name), \"utf-8\", \"ignore\");"); + $self->pidl("$py_var = PyUnicode_Decode_check_null($var_name, strlen($var_name), \"utf-8\", \"ignore\");"); } else { die("No SIZE_IS for array $var_name") unless (defined($l->{SIZE_IS})); my $length = $l->{SIZE_IS}; diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 4072524..1ffb61c 100644 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -573,7 +573,7 @@ sub provision_raw_step1($$) winbindd privileged socket directory = $ctx->{winbindd_privileged_socket_dir} ntp signd socket directory = $ctx->{ntp_signd_socket_dir} winbind separator = / - name resolve order = bcast file + name resolve order = file bcast interfaces = $ctx->{interfaces} tls dh params file = $ctx->{tlsdir}/dhparms.pem panic action = $RealBin/gdb_backtrace \%PID% \%PROG% diff --git a/source3/include/proto.h b/source3/include/proto.h index a49aa66..180e1c0 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -3605,6 +3605,8 @@ const char *lp_ldap_group_suffix(void); const char *lp_ldap_idmap_suffix(void); void *lp_local_ptr_by_snum(int snum, void *ptr); bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue); +bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue); +bool lp_set_option(const char *option); void init_locals(void); bool lp_is_default(int snum, struct parm_struct *parm); bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal); diff --git a/source3/include/smb.h b/source3/include/smb.h index 129be1c..f109739 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -905,6 +905,7 @@ struct parm_struct { #define FLAG_HIDE 0x2000 /* options that should be hidden in SWAT */ #define FLAG_DOS_STRING 0x4000 /* convert from UNIX to DOS codepage when reading this string. */ #define FLAG_META 0x8000 /* A meta directive - not a real parameter */ +#define FLAG_CMDLINE 0x10000 /* option has been overridden */ struct bitmap { uint32 *b; diff --git a/source3/lib/popt_common.c b/source3/lib/popt_common.c index 9dd438b..a332cde 100644 --- a/source3/lib/popt_common.c +++ b/source3/lib/popt_common.c @@ -34,6 +34,8 @@ * -i,--scope */ +enum {OPT_OPTION=1}; + extern bool AllowDebugChange; extern bool override_logfile; @@ -96,6 +98,13 @@ static void popt_common_callback(poptContext con, } switch(opt->val) { + case OPT_OPTION: + if (!lp_set_option(arg)) { + fprintf(stderr, "Error setting option '%s'\n", arg); + exit(1); + } + break; + case 'd': if (arg) { debug_parse_levels(arg); @@ -164,6 +173,7 @@ struct poptOption popt_common_samba[] = { { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternate configuration file", "CONFIGFILE" }, { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Base name for log files", "LOGFILEBASE" }, { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" }, + { "option", 0, POPT_ARG_STRING, NULL, OPT_OPTION, "Set smb.conf option from command line", "name=value" }, POPT_TABLEEND }; diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 2981856..e3fc2d8 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -117,6 +117,7 @@ struct param_opt_struct { char *key; char *value; char **list; + unsigned flags; }; /* @@ -705,6 +706,7 @@ static void set_allowed_client_auth(void); static void *lp_local_ptr(struct service *service, void *ptr); static void add_to_file_list(const char *fname, const char *subfname); +static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values); static const struct enum_list enum_protocol[] = { {PROTOCOL_SMB2, "SMB2"}, @@ -4944,6 +4946,67 @@ static void free_global_parameters(void) free_parameters_by_snum(GLOBAL_SECTION_SNUM); } +static int map_parameter(const char *pszParmName); + +struct lp_stored_option { + struct lp_stored_option *prev, *next; + const char *label; + const char *value; +}; + +static struct lp_stored_option *stored_options; + +/* + save options set by lp_set_cmdline() into a list. This list is + re-applied when we do a globals reset, so that cmdline set options + are sticky across reloads of smb.conf + */ +static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue) +{ + struct lp_stored_option *entry = NULL; + for (entry = stored_options; entry != NULL; entry = entry->next) { + if (strcmp(pszParmName, entry->label) == 0) { + DLIST_REMOVE(stored_options, entry); + talloc_free(entry); + break; + } + } + + entry = talloc(NULL, struct lp_stored_option); + if (!entry) { + return false; + } + + entry->label = talloc_strdup(entry, pszParmName); + if (!entry->label) { + talloc_free(entry); + return false; + } + + entry->value = talloc_strdup(entry, pszParmValue); + if (!entry->value) { + talloc_free(entry); + return false; + } + + DLIST_ADD_END(stored_options, entry, struct lp_stored_option); + + return true; +} + +static bool apply_lp_set_cmdline(void) +{ + struct lp_stored_option *entry = NULL; + for (entry = stored_options; entry != NULL; entry = entry->next) { + if (!lp_set_cmdline_helper(entry->label, entry->value, false)) { + DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n", + entry->label, entry->value)); + return false; + } + } + return true; +} + /*************************************************************************** Initialise the global parameter structure. ***************************************************************************/ @@ -4971,6 +5034,10 @@ static void init_globals(bool reinit_globals) free_global_parameters(); } + /* This memset and the free_global_parameters() above will + * wipe out smb.conf options set with lp_set_cmdline(). The + * apply_lp_set_cmdline() call puts these values back in the + * table once the defaults are set */ memset((void *)&Globals, '\0', sizeof(Globals)); for (i = 0; parm_table[i].label; i++) { @@ -5287,6 +5354,9 @@ static void init_globals(bool reinit_globals) Globals.ismb2_max_read = 1024*1024; Globals.ismb2_max_write = 1024*1024; Globals.ismb2_max_trans = 1024*1024; + + /* Now put back the settings that were set with lp_set_cmdline() */ + apply_lp_set_cmdline(); } /******************************************************************* @@ -5816,7 +5886,6 @@ FN_GLOBAL_INTEGER(lp_client_ldap_sasl_wrapping, &Globals.client_ldap_sasl_wrappi /* local prototypes */ -static int map_parameter(const char *pszParmName); static int map_parameter_canonical(const char *pszParmName, bool *inverse); static const char *get_boolean(bool bool_value); static int getservicebyname(const char *pszServiceName, @@ -6819,7 +6888,8 @@ static int getservicebyname(const char *pszServiceName, struct service *pservice */ static void set_param_opt(struct param_opt_struct **opt_list, const char *opt_name, - const char *opt_value) + const char *opt_value, + unsigned flags) { struct param_opt_struct *new_opt, *opt; bool not_added; @@ -6835,9 +6905,16 @@ static void set_param_opt(struct param_opt_struct **opt_list, while (opt) { /* If we already have same option, override it */ if (strwicmp(opt->key, opt_name) == 0) { + if ((opt->flags & FLAG_CMDLINE) && + !(flags & FLAG_CMDLINE)) { + /* it's been marked as not to be + overridden */ + return; + } string_free(&opt->value); TALLOC_FREE(opt->list); opt->value = SMB_STRDUP(opt_value); + opt->flags = flags; not_added = false; break; } @@ -6848,6 +6925,7 @@ static void set_param_opt(struct param_opt_struct **opt_list, new_opt->key = SMB_STRDUP(opt_name); new_opt->value = SMB_STRDUP(opt_value); new_opt->list = NULL; + new_opt->flags = flags; DLIST_ADD(*opt_list, new_opt); } } @@ -6915,7 +6993,7 @@ static void copy_service(struct service *pserviceDest, struct service *pserviceS data = pserviceSource->param_opt; while (data) { - set_param_opt(&pserviceDest->param_opt, data->key, data->value); + set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->flags); data = data->next; } } @@ -7672,11 +7750,17 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue opt_list = (snum < 0) ? &Globals.param_opt : &ServicePtrs[snum]->param_opt; - set_param_opt(opt_list, pszParmName, pszParmValue); + set_param_opt(opt_list, pszParmName, pszParmValue, 0); return (True); } + /* if it's already been set by the command line, then we don't + override here */ + if (parm_table[parmnum].flags & FLAG_CMDLINE) { + return true; + } + if (parm_table[parmnum].flags & FLAG_DEPRECATED) { DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n", pszParmName)); @@ -7766,6 +7850,42 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue } /*************************************************************************** +set a parameter, marking it with FLAG_CMDLINE. Parameters marked as +FLAG_CMDLINE won't be overridden by loads from smb.conf. +***************************************************************************/ + +static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values) +{ + int parmnum; + parmnum = map_parameter(pszParmName); + if (parmnum >= 0) { + parm_table[parmnum].flags &= ~FLAG_CMDLINE; + if (!lp_do_parameter(-1, pszParmName, pszParmValue)) { + return false; + } + parm_table[parmnum].flags |= FLAG_CMDLINE; + + store_lp_set_cmdline(pszParmName, pszParmValue); + return true; + } + + /* it might be parametric */ + if (strchr(pszParmName, ':') != NULL) { + set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE); + store_lp_set_cmdline(pszParmName, pszParmValue); + return true; + } + + DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName)); + return true; +} + +bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue) +{ + return lp_set_cmdline_helper(pszParmName, pszParmValue, true); +} + +/*************************************************************************** Process a parameter. ***************************************************************************/ @@ -7781,7 +7901,33 @@ static bool do_parameter(const char *pszParmName, const char *pszParmValue, pszParmName, pszParmValue)); } -/*************************************************************************** +/* + set a option from the commandline in 'a=b' format. Use to support --option +*/ +bool lp_set_option(const char *option) +{ + char *p, *s; + bool ret; + + s = talloc_strdup(NULL, option); + if (!s) { + return false; + } + + p = strchr(s, '='); + if (!p) { + talloc_free(s); + return false; + } + + *p = 0; + + ret = lp_set_cmdline(s, p+1); + talloc_free(s); + return ret; +} + +/************************************************************************** Print a parameter of the specified type. ***************************************************************************/ diff --git a/source4/auth/sam.c b/source4/auth/sam.c index 0bb6bd8..6bf1d5f 100644 --- a/source4/auth/sam.c +++ b/source4/auth/sam.c @@ -178,20 +178,20 @@ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, /* Quit if the account was disabled. */ if (acct_flags & ACB_DISABLED) { - DEBUG(1,("authsam_account_ok: Account for user '%s' was disabled.\n", name_for_logs)); + DEBUG(2,("authsam_account_ok: Account for user '%s' was disabled.\n", name_for_logs)); return NT_STATUS_ACCOUNT_DISABLED; } /* Quit if the account was locked out. */ if (acct_flags & ACB_AUTOLOCK) { - DEBUG(1,("authsam_account_ok: Account for user %s was locked out.\n", name_for_logs)); + DEBUG(2,("authsam_account_ok: Account for user %s was locked out.\n", name_for_logs)); return NT_STATUS_ACCOUNT_LOCKED_OUT; } /* Test account expire time */ unix_to_nt_time(&now, time(NULL)); if (now > acct_expiry) { - DEBUG(1,("authsam_account_ok: Account for user '%s' has expired.\n", name_for_logs)); + DEBUG(2,("authsam_account_ok: Account for user '%s' has expired.\n", name_for_logs)); DEBUG(3,("authsam_account_ok: Account expired at '%s'.\n", nt_time_string(mem_ctx, acct_expiry))); return NT_STATUS_ACCOUNT_EXPIRED; @@ -199,16 +199,16 @@ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, /* check for immediate expiry "must change at next logon" (but not if this is a password change request) */ if ((must_change_time == 0) && !password_change) { - DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", + DEBUG(2,("sam_account_ok: Account for user '%s' password must change!.\n", -- Samba Shared Repository