summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-ldap/ldap/passwdmodify.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-ldap/ldap/passwdmodify.go')
-rw-r--r--vendor/github.com/go-ldap/ldap/passwdmodify.go144
1 files changed, 144 insertions, 0 deletions
diff --git a/vendor/github.com/go-ldap/ldap/passwdmodify.go b/vendor/github.com/go-ldap/ldap/passwdmodify.go
new file mode 100644
index 000000000..6d5ca975a
--- /dev/null
+++ b/vendor/github.com/go-ldap/ldap/passwdmodify.go
@@ -0,0 +1,144 @@
+// This file contains the password modify extended operation as specified in rfc 3062
+//
+// https://tools.ietf.org/html/rfc3062
+//
+
+package ldap
+
+import (
+ "errors"
+ "fmt"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+const (
+ passwordModifyOID = "1.3.6.1.4.1.4203.1.11.1"
+)
+
+type PasswordModifyRequest struct {
+ UserIdentity string
+ OldPassword string
+ NewPassword string
+}
+
+type PasswordModifyResult struct {
+ GeneratedPassword string
+}
+
+func (r *PasswordModifyRequest) encode() (*ber.Packet, error) {
+ request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationExtendedRequest, nil, "Password Modify Extended Operation")
+ request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, passwordModifyOID, "Extended Request Name: Password Modify OID"))
+ extendedRequestValue := ber.Encode(ber.ClassContext, ber.TypePrimitive, 1, nil, "Extended Request Value: Password Modify Request")
+ passwordModifyRequestValue := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Password Modify Request")
+ if r.UserIdentity != "" {
+ passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, r.UserIdentity, "User Identity"))
+ }
+ if r.OldPassword != "" {
+ passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 1, r.OldPassword, "Old Password"))
+ }
+ if r.NewPassword != "" {
+ passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 2, r.NewPassword, "New Password"))
+ }
+
+ extendedRequestValue.AppendChild(passwordModifyRequestValue)
+ request.AppendChild(extendedRequestValue)
+
+ return request, nil
+}
+
+// Create a new PasswordModifyRequest
+//
+// According to the RFC 3602:
+// userIdentity is a string representing the user associated with the request.
+// This string may or may not be an LDAPDN (RFC 2253).
+// If userIdentity is empty then the operation will act on the user associated
+// with the session.
+//
+// oldPassword is the current user's password, it can be empty or it can be
+// needed depending on the session user access rights (usually an administrator
+// can change a user's password without knowing the current one) and the
+// password policy (see pwdSafeModify password policy's attribute)
+//
+// newPassword is the desired user's password. If empty the server can return
+// an error or generate a new password that will be available in the
+// PasswordModifyResult.GeneratedPassword
+//
+func NewPasswordModifyRequest(userIdentity string, oldPassword string, newPassword string) *PasswordModifyRequest {
+ return &PasswordModifyRequest{
+ UserIdentity: userIdentity,
+ OldPassword: oldPassword,
+ NewPassword: newPassword,
+ }
+}
+
+func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error) {
+ messageID := l.nextMessageID()
+
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+
+ encodedPasswordModifyRequest, err := passwordModifyRequest.encode()
+ if err != nil {
+ return nil, err
+ }
+ packet.AppendChild(encodedPasswordModifyRequest)
+
+ l.Debug.PrintPacket(packet)
+
+ channel, err := l.sendMessage(packet)
+ if err != nil {
+ return nil, err
+ }
+ if channel == nil {
+ return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
+ }
+ defer l.finishMessage(messageID)
+
+ result := &PasswordModifyResult{}
+
+ l.Debug.Printf("%d: waiting for response", messageID)
+ packetResponse, ok := <-channel
+ if !ok {
+ return nil, NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ }
+ packet, err = packetResponse.ReadPacket()
+ l.Debug.Printf("%d: got response %p", messageID, packet)
+ if err != nil {
+ return nil, err
+ }
+
+ if packet == nil {
+ return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
+ }
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ return nil, err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ if packet.Children[1].Tag == ApplicationExtendedResponse {
+ resultCode, resultDescription := getLDAPResultCode(packet)
+ if resultCode != 0 {
+ return nil, NewError(resultCode, errors.New(resultDescription))
+ }
+ } else {
+ return nil, NewError(ErrorUnexpectedResponse, fmt.Errorf("Unexpected Response: %d", packet.Children[1].Tag))
+ }
+
+ extendedResponse := packet.Children[1]
+ for _, child := range extendedResponse.Children {
+ if child.Tag == 11 {
+ passwordModifyReponseValue := ber.DecodePacket(child.Data.Bytes())
+ if len(passwordModifyReponseValue.Children) == 1 {
+ if passwordModifyReponseValue.Children[0].Tag == 0 {
+ result.GeneratedPassword = ber.DecodeString(passwordModifyReponseValue.Children[0].Data.Bytes())
+ }
+ }
+ }
+ }
+
+ return result, nil
+}