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:
parent
5a0d1b7cc5
commit
878fa6ef7d
@ -5,12 +5,16 @@
|
|||||||
<description>
|
<description>
|
||||||
<para>The name of a program that can be used to check password
|
<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>
|
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
|
<para>The program must return 0 on a good password, or any other value
|
||||||
if the password is bad.
|
if the password is bad.
|
||||||
In case the password is considered weak (the program does not return 0) the
|
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>
|
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>
|
<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>
|
that uses cracklib to check the password quality.</para>
|
||||||
|
|
||||||
|
@ -27,20 +27,8 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
#include "system/filesys.h"
|
#include "system/filesys.h"
|
||||||
#include <tevent.h>
|
|
||||||
#include "../lib/util/tevent_unix.h"
|
#include "../lib/util/tevent_unix.h"
|
||||||
|
#include "../lib/util/util_runcmd.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;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int samba_runcmd_state_destructor(struct samba_runcmd_state *state)
|
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 "lib/socket/socket.h"
|
||||||
#include "librpc/gen_ndr/irpc.h"
|
#include "librpc/gen_ndr/irpc.h"
|
||||||
#include "libds/common/flag_mapping.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
|
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")
|
* 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 pwdProperties,
|
||||||
const uint32_t minPwdLength)
|
const uint32_t minPwdLength)
|
||||||
{
|
{
|
||||||
const char *utf8_pw = (const char *)utf8_blob->data;
|
const char *utf8_pw = (const char *)utf8_blob->data;
|
||||||
size_t utf8_len = strlen_m(utf8_pw);
|
size_t utf8_len = strlen_m(utf8_pw);
|
||||||
|
char *password_script = NULL;
|
||||||
|
|
||||||
/* checks if the "minPwdLength" property is satisfied */
|
/* checks if the "minPwdLength" property is satisfied */
|
||||||
if (minPwdLength > utf8_len) {
|
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;
|
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)) {
|
if (!check_password_quality(utf8_pw)) {
|
||||||
return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
|
return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
|
||||||
}
|
}
|
||||||
|
@ -2106,10 +2106,11 @@ done:
|
|||||||
|
|
||||||
static int check_password_restrictions(struct setup_password_fields_io *io)
|
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;
|
int ret;
|
||||||
|
struct loadparm_context *lp_ctx =
|
||||||
ldb = ldb_module_get_ctx(io->ac->module);
|
lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
|
||||||
|
struct loadparm_context);
|
||||||
|
|
||||||
if (!io->ac->update_password) {
|
if (!io->ac->update_password) {
|
||||||
return LDB_SUCCESS;
|
return LDB_SUCCESS;
|
||||||
@ -2175,7 +2176,8 @@ static int check_password_restrictions(struct setup_password_fields_io *io)
|
|||||||
*/
|
*/
|
||||||
if (io->n.cleartext_utf8 != NULL) {
|
if (io->n.cleartext_utf8 != NULL) {
|
||||||
enum samr_ValidationStatus vstat;
|
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.pwdProperties,
|
||||||
io->ac->status->domain_data.minPwdLength);
|
io->ac->status->domain_data.minPwdLength);
|
||||||
switch (vstat) {
|
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',
|
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',
|
autoproto='common/proto.h',
|
||||||
private_library=True,
|
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:
|
case NetValidatePasswordChange:
|
||||||
password = data_blob_const(r->in.req->req2.password.string,
|
password = data_blob_const(r->in.req->req2.password.string,
|
||||||
r->in.req->req2.password.length);
|
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.password_properties,
|
||||||
pwInfo.min_password_length);
|
pwInfo.min_password_length);
|
||||||
(*r->out.rep)->ctr2.status = res;
|
(*r->out.rep)->ctr2.status = res;
|
||||||
@ -4408,7 +4410,9 @@ static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call,
|
|||||||
case NetValidatePasswordReset:
|
case NetValidatePasswordReset:
|
||||||
password = data_blob_const(r->in.req->req3.password.string,
|
password = data_blob_const(r->in.req->req3.password.string,
|
||||||
r->in.req->req3.password.length);
|
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.password_properties,
|
||||||
pwInfo.min_password_length);
|
pwInfo.min_password_length);
|
||||||
(*r->out.rep)->ctr3.status = res;
|
(*r->out.rep)->ctr3.status = res;
|
||||||
|
Loading…
Reference in New Issue
Block a user