mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
check-password-script: Allow AD to execute these scripts
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>
This commit is contained in:
parent
5a0d1b7cc5
commit
878fa6ef7d
@ -5,12 +5,16 @@
|
||||
<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>
|
||||
|
||||
|
@ -27,20 +27,8 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
|
35
lib/util/util_runcmd.h
Normal file
35
lib/util/util_runcmd.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
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;
|
||||
};
|
@ -44,6 +44,7 @@
|
||||
#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
|
||||
@ -1988,12 +1989,15 @@ int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
|
||||
*
|
||||
* 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) {
|
||||
@ -2009,6 +2013,61 @@ enum samr_ValidationStatus samdb_check_password(const DATA_BLOB *utf8_blob,
|
||||
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;
|
||||
}
|
||||
|
@ -2106,10 +2106,11 @@ done:
|
||||
|
||||
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;
|
||||
@ -2175,7 +2176,8 @@ static int check_password_restrictions(struct setup_password_fields_io *io)
|
||||
*/
|
||||
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) {
|
||||
|
@ -16,7 +16,7 @@ bld.SAMBA_LIBRARY('samdb-common',
|
||||
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'
|
||||
)
|
||||
|
||||
|
||||
|
@ -4400,7 +4400,9 @@ static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call,
|
||||
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;
|
||||
@ -4408,7 +4410,9 @@ static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call,
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user