92 lines
2.7 KiB
Python
92 lines
2.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
ldap.controls.ppolicy - classes for Password Policy controls
|
|
(see https://tools.ietf.org/html/draft-behera-ldap-password-policy)
|
|
|
|
See https://www.python-ldap.org/ for project details.
|
|
"""
|
|
|
|
__all__ = [
|
|
'PasswordPolicyControl'
|
|
]
|
|
|
|
# Imports from python-ldap 2.4+
|
|
from ldap.controls import (
|
|
ResponseControl, ValueLessRequestControl, KNOWN_RESPONSE_CONTROLS
|
|
)
|
|
|
|
# Imports from pyasn1
|
|
from pyasn1.type import tag,namedtype,namedval,univ,constraint
|
|
from pyasn1.codec.der import decoder
|
|
|
|
|
|
class PasswordPolicyWarning(univ.Choice):
|
|
componentType = namedtype.NamedTypes(
|
|
namedtype.NamedType('timeBeforeExpiration',univ.Integer().subtype(
|
|
implicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatSimple,0)
|
|
)),
|
|
namedtype.NamedType('graceAuthNsRemaining',univ.Integer().subtype(
|
|
implicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatSimple,1)
|
|
)),
|
|
)
|
|
|
|
|
|
class PasswordPolicyError(univ.Enumerated):
|
|
namedValues = namedval.NamedValues(
|
|
('passwordExpired',0),
|
|
('accountLocked',1),
|
|
('changeAfterReset',2),
|
|
('passwordModNotAllowed',3),
|
|
('mustSupplyOldPassword',4),
|
|
('insufficientPasswordQuality',5),
|
|
('passwordTooShort',6),
|
|
('passwordTooYoung',7),
|
|
('passwordInHistory',8)
|
|
)
|
|
subtypeSpec = univ.Enumerated.subtypeSpec + constraint.SingleValueConstraint(0,1,2,3,4,5,6,7,8)
|
|
|
|
|
|
class PasswordPolicyResponseValue(univ.Sequence):
|
|
componentType = namedtype.NamedTypes(
|
|
namedtype.OptionalNamedType(
|
|
'warning',
|
|
PasswordPolicyWarning().subtype(
|
|
implicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatSimple,0)
|
|
),
|
|
),
|
|
namedtype.OptionalNamedType(
|
|
'error',PasswordPolicyError().subtype(
|
|
implicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatSimple,1)
|
|
)
|
|
),
|
|
)
|
|
|
|
|
|
class PasswordPolicyControl(ValueLessRequestControl,ResponseControl):
|
|
controlType = '1.3.6.1.4.1.42.2.27.8.5.1'
|
|
|
|
def __init__(self,criticality=False):
|
|
self.criticality = criticality
|
|
|
|
def decodeControlValue(self,encodedControlValue):
|
|
ppolicyValue,_ = decoder.decode(encodedControlValue,asn1Spec=PasswordPolicyResponseValue())
|
|
self.timeBeforeExpiration = None
|
|
self.graceAuthNsRemaining = None
|
|
self.error = None
|
|
|
|
warning = ppolicyValue.getComponentByName('warning')
|
|
if warning.hasValue():
|
|
if 'timeBeforeExpiration' in warning:
|
|
self.timeBeforeExpiration = int(
|
|
warning.getComponentByName('timeBeforeExpiration'))
|
|
if 'graceAuthNsRemaining' in warning:
|
|
self.graceAuthNsRemaining = int(
|
|
warning.getComponentByName('graceAuthNsRemaining'))
|
|
|
|
error = ppolicyValue.getComponentByName('error')
|
|
if error.hasValue():
|
|
self.error = int(error)
|
|
|
|
|
|
KNOWN_RESPONSE_CONTROLS[PasswordPolicyControl.controlType] = PasswordPolicyControl
|