Skip to content

Commit 4f6002d

Browse files
committed
Extract new password in passwd_s (#246)
1 parent 44a593d commit 4f6002d

File tree

4 files changed

+77
-2
lines changed

4 files changed

+77
-2
lines changed

Lib/ldap/extop/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,4 @@ def decodeResponseValue(self,value):
6565

6666
# Import sub-modules
6767
from ldap.extop.dds import *
68+
from ldap.extop.passwd import *

Lib/ldap/extop/passwd.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
ldap.extop.passwd - Classes for Password Modify extended operation
4+
(see RFC 3062)
5+
6+
See https://www.python-ldap.org/ for details.
7+
"""
8+
9+
from ldap.extop import ExtendedRequest,ExtendedResponse
10+
11+
# Imports from pyasn1
12+
from pyasn1.type import namedtype,univ,tag
13+
from pyasn1.codec.der import decoder
14+
15+
16+
class PasswordModifyResponse(ExtendedResponse):
17+
responseName = None
18+
19+
class PasswordModifyResponseValue(univ.Sequence):
20+
componentType = namedtype.NamedTypes(
21+
namedtype.OptionalNamedType(
22+
'genPasswd',
23+
univ.OctetString().subtype(
24+
implicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatSimple,0)
25+
)
26+
)
27+
)
28+
29+
def decodeResponseValue(self,value):
30+
respValue,_ = decoder.decode(value,asn1Spec=self.PasswordModifyResponseValue())
31+
self.genPasswd = bytes(respValue.getComponentByName('genPasswd'))
32+
return self.genPasswd

Lib/ldap/ldapobject.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
from ldap.schema import SCHEMA_ATTRS
2929
from ldap.controls import LDAPControl,DecodeControlTuples,RequestControlTuples
30-
from ldap.extop import ExtendedRequest,ExtendedResponse
30+
from ldap.extop import ExtendedRequest,ExtendedResponse,PasswordModifyResponse
3131
from ldap.compat import reraise
3232

3333
from ldap import LDAPError
@@ -658,7 +658,12 @@ def passwd(self,user,oldpw,newpw,serverctrls=None,clientctrls=None):
658658

659659
def passwd_s(self,user,oldpw,newpw,serverctrls=None,clientctrls=None):
660660
msgid = self.passwd(user,oldpw,newpw,serverctrls,clientctrls)
661-
return self.extop_result(msgid,all=1,timeout=self.timeout)
661+
respoid, respvalue = self.extop_result(msgid, all=1, timeout=self.timeout)
662+
if respoid != PasswordModifyResponse.responseName:
663+
raise ldap.PROTOCOL_ERROR("Unexpected OID %s in extended response!" % respoid)
664+
if respvalue:
665+
respvalue = PasswordModifyResponse(PasswordModifyResponse.responseName, respvalue)
666+
return (respoid, respvalue)
662667

663668
def rename(self,dn,newrdn,newsuperior=None,delold=1,serverctrls=None,clientctrls=None):
664669
"""

Tests/t_ldapobject.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,43 @@ def test_compare_s_invalidattr(self):
673673
with self.assertRaises(ldap.UNDEFINED_TYPE):
674674
result = l.compare_s('cn=Foo1,%s' % base, 'invalidattr', b'invalid')
675675

676+
def test_passwd_s(self):
677+
l = self._ldap_conn
678+
679+
# first, create a user to change password on
680+
dn = "cn=PasswordTest," + self.server.suffix
681+
result, pmsg, msgid, ctrls = l.add_ext_s(
682+
dn,
683+
[
684+
('objectClass', b'person'),
685+
('sn', b'PasswordTest'),
686+
('cn', b'PasswordTest'),
687+
('userPassword', b'initial'),
688+
]
689+
)
690+
self.assertEqual(result, ldap.RES_ADD)
691+
self.assertEqual(type(msgid), type(0))
692+
self.assertEqual(pmsg, [])
693+
self.assertEqual(ctrls, [])
694+
695+
# try changing password with a wrong old-pw
696+
with self.assertRaises(ldap.UNWILLING_TO_PERFORM):
697+
l.passwd_s(dn, b'bogus', b'ignored')
698+
699+
# have the server generate a new random pw
700+
respoid, respvalue = l.passwd_s(dn, b'initial', None)
701+
self.assertEqual(respoid, None)
702+
703+
password = respvalue.genPasswd
704+
self.assertEqual(type(password), bytes)
705+
706+
# try changing password back
707+
respoid, respvalue = l.passwd_s(dn, password, b'initial')
708+
self.assertEqual(respoid, None)
709+
self.assertEqual(respvalue, None)
710+
711+
l.delete_s(dn)
712+
676713

677714
class Test01_ReconnectLDAPObject(Test00_SimpleLDAPObject):
678715
"""

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy