1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +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:
Garming Sam 2016-04-01 10:10:57 +13:00 committed by Garming Sam
parent 5a0d1b7cc5
commit 878fa6ef7d
7 changed files with 114 additions and 22 deletions

View File

@ -11,6 +11,10 @@
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>

View File

@ -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
View 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;
};

View File

@ -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;
}

View File

@ -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) {

View File

@ -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'
)

View File

@ -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;