In contrast to source3, this is run as root and without substitution.
Signed-off-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
<description>
<para>The name of a program that can be used to check password
complexity. The password is sent to the program's standard input.</para>
-
+
<para>The program must return 0 on a good password, or any other value
if the password is bad.
In case the password is considered weak (the program does not return 0) the
user will be notified and the password change will fail.</para>
+ <para>In Samba AD, this script will be run <emphasis>AS ROOT</emphasis> by
+ <citerefentry><refentrytitle>samba</refentrytitle> <manvolnum>8</manvolnum>
+ </citerefentry> without any substitutions.</para>
+
<para>Note: In the example directory is a sample program called <command moreinfo="none">crackcheck</command>
that uses cracklib to check the password quality.</para>
#include "includes.h"
#include "system/filesys.h"
-#include <tevent.h>
#include "../lib/util/tevent_unix.h"
-
-struct samba_runcmd_state {
- int stdout_log_level;
- int stderr_log_level;
- struct tevent_fd *fde_stdout;
- struct tevent_fd *fde_stderr;
- int fd_stdin, fd_stdout, fd_stderr;
- char *arg0;
- pid_t pid;
- char buf[1024];
- uint16_t buf_used;
-};
+#include "../lib/util/util_runcmd.h"
static int samba_runcmd_state_destructor(struct samba_runcmd_state *state)
{
--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+
+ run a child command
+
+ Copyright (C) Andrew Tridgell 2010
+
+ 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 <tevent.h>
+
+struct samba_runcmd_state {
+ int stdout_log_level;
+ int stderr_log_level;
+ struct tevent_fd *fde_stdout;
+ struct tevent_fd *fde_stderr;
+ int fd_stdin, fd_stdout, fd_stderr;
+ char *arg0;
+ pid_t pid;
+ char buf[1024];
+ uint16_t buf_used;
+};
#include "lib/socket/socket.h"
#include "librpc/gen_ndr/irpc.h"
#include "libds/common/flag_mapping.h"
+#include "../lib/util/util_runcmd.h"
/*
search the sam for the specified attributes in a specific domain, filter on
*
* Result codes from "enum samr_ValidationStatus" (consider "samr.idl")
*/
-enum samr_ValidationStatus samdb_check_password(const DATA_BLOB *utf8_blob,
+enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ const DATA_BLOB *utf8_blob,
const uint32_t pwdProperties,
const uint32_t minPwdLength)
{
const char *utf8_pw = (const char *)utf8_blob->data;
size_t utf8_len = strlen_m(utf8_pw);
+ char *password_script = NULL;
/* checks if the "minPwdLength" property is satisfied */
if (minPwdLength > utf8_len) {
return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
}
+ password_script = lpcfg_check_password_script(lp_ctx, mem_ctx);
+ if (password_script != NULL && *password_script != '\0') {
+ int check_ret = 0;
+ int error = 0;
+ struct tevent_context *event_ctx = NULL;
+ struct tevent_req *req = NULL;
+ struct samba_runcmd_state *run_cmd = NULL;
+ const char * const cmd[4] = {
+ "/bin/sh", "-c",
+ password_script,
+ NULL
+ };
+
+ event_ctx = tevent_context_init(mem_ctx);
+ if (event_ctx == NULL) {
+ TALLOC_FREE(password_script);
+ return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
+ }
+
+ req = samba_runcmd_send(mem_ctx, event_ctx,
+ tevent_timeval_current_ofs(0, 10000000),
+ 100, 100, cmd, NULL);
+ run_cmd = tevent_req_data(req, struct samba_runcmd_state);
+ if (write(run_cmd->fd_stdin, utf8_pw, utf8_len) != utf8_len) {
+ TALLOC_FREE(password_script);
+ return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
+ }
+
+ close(run_cmd->fd_stdin);
+ run_cmd->fd_stdin = -1;
+
+ if (!tevent_req_poll(req, event_ctx)) {
+ TALLOC_FREE(password_script);
+ return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
+ }
+
+ check_ret = samba_runcmd_recv(req, &error);
+ TALLOC_FREE(req);
+
+ DEBUG(5,("check_password_complexity: check password script (%s) "
+ "returned [%d]\n", password_script, check_ret));
+ TALLOC_FREE(password_script);
+
+ if (check_ret != 0) {
+ DEBUG(1,("check_password_complexity: "
+ "check password script said new password is not good "
+ "enough!\n"));
+ return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
+ }
+
+ return SAMR_VALIDATION_STATUS_SUCCESS;
+ }
+
+ TALLOC_FREE(password_script);
+
if (!check_password_quality(utf8_pw)) {
return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
}
static int check_password_restrictions(struct setup_password_fields_io *io)
{
- struct ldb_context *ldb;
+ struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
int ret;
-
- ldb = ldb_module_get_ctx(io->ac->module);
+ struct loadparm_context *lp_ctx =
+ lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
+ struct loadparm_context);
if (!io->ac->update_password) {
return LDB_SUCCESS;
*/
if (io->n.cleartext_utf8 != NULL) {
enum samr_ValidationStatus vstat;
- vstat = samdb_check_password(io->n.cleartext_utf8,
+ vstat = samdb_check_password(io->ac, lp_ctx,
+ io->n.cleartext_utf8,
io->ac->status->domain_data.pwdProperties,
io->ac->status->domain_data.minPwdLength);
switch (vstat) {
source='common/util.c common/util_trusts.c common/util_groups.c common/util_samr.c common/dsdb_dn.c common/dsdb_access.c',
autoproto='common/proto.h',
private_library=True,
- deps='ldb NDR_DRSBLOBS util_ldb LIBCLI_AUTH samba-hostconfig samba_socket cli-ldap-common flag_mapping'
+ deps='ldb NDR_DRSBLOBS util_ldb LIBCLI_AUTH samba-hostconfig samba_socket cli-ldap-common flag_mapping UTIL_RUNCMD'
)
case NetValidatePasswordChange:
password = data_blob_const(r->in.req->req2.password.string,
r->in.req->req2.password.length);
- res = samdb_check_password(&password,
+ res = samdb_check_password(mem_ctx,
+ dce_call->conn->dce_ctx->lp_ctx,
+ &password,
pwInfo.password_properties,
pwInfo.min_password_length);
(*r->out.rep)->ctr2.status = res;
case NetValidatePasswordReset:
password = data_blob_const(r->in.req->req3.password.string,
r->in.req->req3.password.length);
- res = samdb_check_password(&password,
+ res = samdb_check_password(mem_ctx,
+ dce_call->conn->dce_ctx->lp_ctx,
+ &password,
pwInfo.password_properties,
pwInfo.min_password_length);
(*r->out.rep)->ctr3.status = res;