Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Tero Saarni
OpenLDAP
Commits
094848b6
Commit
094848b6
authored
Jun 23, 2020
by
Ondřej Kuzník
Committed by
Quanah Gibson-Mount
Jul 22, 2020
Browse files
ITS#9279 Implement Netscape password policy controls in ppolicy
parent
0687e289
Changes
2
Hide whitespace changes
Inline
Side-by-side
doc/man/man5/slapo-ppolicy.5
View file @
094848b6
...
...
@@ -36,6 +36,9 @@ when considering a single-valued password attribute, while
the userPassword attribute allows multiple values. This implementation
enforces a single value for the userPassword attribute, despite
its specification.
.P
In addition to supporting the IETF Password Policy, this module can
send the Netscape Password validity controls when configured to do so.
.SH CONFIGURATION
These
...
...
@@ -84,6 +87,12 @@ that sending the
error code provides useful information
to an attacker; sites that are sensitive to security issues should not
enable this option.
.TP
.B ppolicy_send_netscape_controls
If set, ppolicy will send the password policy expired (2.16.840.1.113730.3.4.4)
and password policy expiring (2.16.840.1.113730.3.4.5) controls when
appropriate. The controls are not sent for bind requests where the Password
policy control has already been requested. Default is not to send the controls.
.SH OBJECT CLASS
The
...
...
servers/slapd/overlays/ppolicy.c
View file @
094848b6
...
...
@@ -55,6 +55,7 @@ typedef struct pp_info {
int
use_lockout
;
/* send AccountLocked result? */
int
hash_passwords
;
/* transparently hash cleartext pwds */
int
forward_updates
;
/* use frontend for policy state updates */
int
send_netscape_controls
;
/* send netscape password controls */
}
pp_info
;
/* Our per-connection info - note, it is not per-instance, it is
...
...
@@ -243,6 +244,13 @@ static ConfigTable ppolicycfg[] = {
"( OLcfgOvAt:12.3 NAME 'olcPPolicyUseLockout' "
"DESC 'Warn clients with AccountLocked' "
"SYNTAX OMsBoolean SINGLE-VALUE )"
,
NULL
,
NULL
},
{
"ppolicy_send_netscape_controls"
,
"on|off"
,
1
,
2
,
0
,
ARG_ON_OFF
|
ARG_OFFSET
,
(
void
*
)
offsetof
(
pp_info
,
send_netscape_controls
),
"( OLcfgOvAt:12.6 NAME 'olcPPolicySendNetscapeControls' "
"DESC 'Send Netscape policy controls' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )"
,
NULL
,
NULL
},
{
NULL
,
NULL
,
0
,
0
,
0
,
ARG_IGNORED
}
};
...
...
@@ -252,7 +260,8 @@ static ConfigOCs ppolicyocs[] = {
"DESC 'Password Policy configuration' "
"SUP olcOverlayConfig "
"MAY ( olcPPolicyDefault $ olcPPolicyHashCleartext $ "
"olcPPolicyUseLockout $ olcPPolicyForwardUpdates ) )"
,
"olcPPolicyUseLockout $ olcPPolicyForwardUpdates $ "
"olcPPolicySendNetscapeControls ) )"
,
Cft_Overlay
,
ppolicycfg
},
{
NULL
,
0
,
NULL
}
};
...
...
@@ -376,6 +385,8 @@ account_locked( Operation *op, Entry *e,
#define PPOLICY_GRACE 0x81L
/* primitive + 1 */
static
const
char
ppolicy_ctrl_oid
[]
=
LDAP_CONTROL_PASSWORDPOLICYRESPONSE
;
static
const
char
ppolicy_pwd_expired_oid
[]
=
LDAP_CONTROL_X_PASSWORD_EXPIRED
;
static
const
char
ppolicy_pwd_expiring_oid
[]
=
LDAP_CONTROL_X_PASSWORD_EXPIRING
;
static
LDAPControl
*
create_passcontrol
(
Operation
*
op
,
int
exptime
,
int
grace
,
LDAPPasswordPolicyError
err
)
...
...
@@ -435,6 +446,42 @@ fail:
return
cp
;
}
static
LDAPControl
*
create_passexpiry
(
Operation
*
op
,
int
expired
,
int
warn
)
{
BerElementBuffer
berbuf
;
BerElement
*
ber
=
(
BerElement
*
)
&
berbuf
;
LDAPControl
c
=
{
0
},
*
cp
;
char
buf
[
sizeof
(
"-2147483648"
)];
struct
berval
bv
=
{
.
bv_val
=
buf
,
.
bv_len
=
sizeof
(
buf
)
};
int
rc
;
BER_BVZERO
(
&
c
.
ldctl_value
);
bv
.
bv_len
=
snprintf
(
bv
.
bv_val
,
bv
.
bv_len
,
"%d"
,
warn
);
ber_init2
(
ber
,
NULL
,
LBER_USE_DER
);
ber_printf
(
ber
,
"O"
,
&
bv
);
if
(
ber_flatten2
(
ber
,
&
c
.
ldctl_value
,
0
)
==
-
1
)
{
return
NULL
;
}
cp
=
op
->
o_tmpalloc
(
sizeof
(
LDAPControl
)
+
c
.
ldctl_value
.
bv_len
,
op
->
o_tmpmemctx
);
if
(
expired
)
{
cp
->
ldctl_oid
=
(
char
*
)
ppolicy_pwd_expired_oid
;
}
else
{
cp
->
ldctl_oid
=
(
char
*
)
ppolicy_pwd_expiring_oid
;
}
cp
->
ldctl_iscritical
=
0
;
cp
->
ldctl_value
.
bv_val
=
(
char
*
)
&
cp
[
1
];
cp
->
ldctl_value
.
bv_len
=
c
.
ldctl_value
.
bv_len
;
AC_MEMCPY
(
cp
->
ldctl_value
.
bv_val
,
c
.
ldctl_value
.
bv_val
,
c
.
ldctl_value
.
bv_len
);
fail:
(
void
)
ber_free_buf
(
ber
);
return
cp
;
}
static
LDAPControl
**
add_passcontrol
(
Operation
*
op
,
SlapReply
*
rs
,
LDAPControl
*
ctrl
)
{
...
...
@@ -913,7 +960,9 @@ ctrls_cleanup( Operation *op, SlapReply *rs, LDAPControl **oldctrls )
assert
(
rs
->
sr_ctrls
[
0
]
!=
NULL
);
for
(
n
=
0
;
rs
->
sr_ctrls
[
n
];
n
++
)
{
if
(
rs
->
sr_ctrls
[
n
]
->
ldctl_oid
==
ppolicy_ctrl_oid
)
{
if
(
rs
->
sr_ctrls
[
n
]
->
ldctl_oid
==
ppolicy_ctrl_oid
||
rs
->
sr_ctrls
[
n
]
->
ldctl_oid
==
ppolicy_pwd_expired_oid
||
rs
->
sr_ctrls
[
n
]
->
ldctl_oid
==
ppolicy_pwd_expiring_oid
)
{
op
->
o_tmpfree
(
rs
->
sr_ctrls
[
n
],
op
->
o_tmpmemctx
);
rs
->
sr_ctrls
[
n
]
=
(
LDAPControl
*
)(
-
1
);
break
;
...
...
@@ -944,6 +993,7 @@ ppolicy_bind_response( Operation *op, SlapReply *rs )
{
ppbind
*
ppb
=
op
->
o_callback
->
sc_private
;
slap_overinst
*
on
=
ppb
->
on
;
pp_info
*
pi
=
on
->
on_bi
.
bi_private
;
Modifications
*
mod
=
ppb
->
mod
,
*
m
;
int
pwExpired
=
0
;
int
ngut
=
-
1
,
warn
=
-
1
,
age
,
rc
;
...
...
@@ -955,6 +1005,7 @@ ppolicy_bind_response( Operation *op, SlapReply *rs )
char
nowstr_usec
[
LDAP_LUTIL_GENTIME_BUFSIZE
+
8
];
struct
berval
timestamp
,
timestamp_usec
;
BackendInfo
*
bi
=
op
->
o_bd
->
bd_info
;
LDAPControl
*
ctrl
=
NULL
;
Entry
*
e
;
/* If we already know it's locked, just get on with it */
...
...
@@ -1233,7 +1284,6 @@ locked:
Operation
op2
=
*
op
;
SlapReply
r2
=
{
REP_RESULT
};
slap_callback
cb
=
{
NULL
,
slap_null_cb
,
NULL
,
NULL
};
pp_info
*
pi
=
on
->
on_bi
.
bi_private
;
LDAPControl
c
,
*
ca
[
2
];
op2
.
o_tag
=
LDAP_REQ_MODIFY
;
...
...
@@ -1273,14 +1323,20 @@ locked:
}
if
(
ppb
->
send_ctrl
)
{
LDAPControl
*
ctrl
=
NULL
;
pp_info
*
pi
=
on
->
on_bi
.
bi_private
;
/* Do we really want to tell that the account is locked? */
if
(
ppb
->
pErr
==
PP_accountLocked
&&
!
pi
->
use_lockout
)
{
ppb
->
pErr
=
PP_noError
;
}
ctrl
=
create_passcontrol
(
op
,
warn
,
ngut
,
ppb
->
pErr
);
}
else
if
(
pi
->
send_netscape_controls
)
{
if
(
ppb
->
pErr
!=
PP_noError
||
ngut
>
0
)
{
ctrl
=
create_passexpiry
(
op
,
1
,
0
);
}
else
if
(
warn
>
0
)
{
ctrl
=
create_passexpiry
(
op
,
0
,
warn
);
}
}
if
(
ctrl
)
{
ppb
->
oldctrls
=
add_passcontrol
(
op
,
rs
,
ctrl
);
op
->
o_callback
->
sc_cleanup
=
ppolicy_ctrls_cleanup
;
}
...
...
@@ -2512,6 +2568,21 @@ int ppolicy_initialize()
return
code
;
}
/* We don't expect to receive these controls, only send them */
code
=
register_supported_control
(
LDAP_CONTROL_X_PASSWORD_EXPIRED
,
0
,
NULL
,
NULL
,
NULL
);
if
(
code
!=
LDAP_SUCCESS
)
{
Debug
(
LDAP_DEBUG_ANY
,
"Failed to register control %d
\n
"
,
code
,
0
,
0
);
return
code
;
}
code
=
register_supported_control
(
LDAP_CONTROL_X_PASSWORD_EXPIRING
,
0
,
NULL
,
NULL
,
NULL
);
if
(
code
!=
LDAP_SUCCESS
)
{
Debug
(
LDAP_DEBUG_ANY
,
"Failed to register control %d
\n
"
,
code
,
0
,
0
);
return
code
;
}
ldap_pvt_thread_mutex_init
(
&
chk_syntax_mutex
);
ppolicy
.
on_bi
.
bi_type
=
"ppolicy"
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment