...

Source file src/github.com/go-ldap/ldap/v3/passwdmodify.go

Documentation: github.com/go-ldap/ldap/v3

     1  package ldap
     2  
     3  import (
     4  	"fmt"
     5  
     6  	ber "github.com/go-asn1-ber/asn1-ber"
     7  )
     8  
     9  const (
    10  	passwordModifyOID = "1.3.6.1.4.1.4203.1.11.1"
    11  )
    12  
    13  // PasswordModifyRequest implements the Password Modify Extended Operation as defined in https://www.ietf.org/rfc/rfc3062.txt
    14  type PasswordModifyRequest struct {
    15  	// UserIdentity is an optional string representation of the user associated with the request.
    16  	// This string may or may not be an LDAPDN [RFC2253].
    17  	// If no UserIdentity field is present, the request acts up upon the password of the user currently associated with the LDAP session
    18  	UserIdentity string
    19  	// OldPassword, if present, contains the user's current password
    20  	OldPassword string
    21  	// NewPassword, if present, contains the desired password for this user
    22  	NewPassword string
    23  }
    24  
    25  // PasswordModifyResult holds the server response to a PasswordModifyRequest
    26  type PasswordModifyResult struct {
    27  	// GeneratedPassword holds a password generated by the server, if present
    28  	GeneratedPassword string
    29  	// Referral are the returned referral
    30  	Referral string
    31  }
    32  
    33  func (req *PasswordModifyRequest) appendTo(envelope *ber.Packet) error {
    34  	pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationExtendedRequest, nil, "Password Modify Extended Operation")
    35  	pkt.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, passwordModifyOID, "Extended Request Name: Password Modify OID"))
    36  
    37  	extendedRequestValue := ber.Encode(ber.ClassContext, ber.TypePrimitive, 1, nil, "Extended Request Value: Password Modify Request")
    38  	passwordModifyRequestValue := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Password Modify Request")
    39  	if req.UserIdentity != "" {
    40  		passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, req.UserIdentity, "User Identity"))
    41  	}
    42  	if req.OldPassword != "" {
    43  		passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 1, req.OldPassword, "Old Password"))
    44  	}
    45  	if req.NewPassword != "" {
    46  		passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 2, req.NewPassword, "New Password"))
    47  	}
    48  	extendedRequestValue.AppendChild(passwordModifyRequestValue)
    49  
    50  	pkt.AppendChild(extendedRequestValue)
    51  
    52  	envelope.AppendChild(pkt)
    53  
    54  	return nil
    55  }
    56  
    57  // NewPasswordModifyRequest creates a new PasswordModifyRequest
    58  //
    59  // According to the RFC 3602 (https://tools.ietf.org/html/rfc3062):
    60  // userIdentity is a string representing the user associated with the request.
    61  // This string may or may not be an LDAPDN (RFC 2253).
    62  // If userIdentity is empty then the operation will act on the user associated
    63  // with the session.
    64  //
    65  // oldPassword is the current user's password, it can be empty or it can be
    66  // needed depending on the session user access rights (usually an administrator
    67  // can change a user's password without knowing the current one) and the
    68  // password policy (see pwdSafeModify password policy's attribute)
    69  //
    70  // newPassword is the desired user's password. If empty the server can return
    71  // an error or generate a new password that will be available in the
    72  // PasswordModifyResult.GeneratedPassword
    73  func NewPasswordModifyRequest(userIdentity string, oldPassword string, newPassword string) *PasswordModifyRequest {
    74  	return &PasswordModifyRequest{
    75  		UserIdentity: userIdentity,
    76  		OldPassword:  oldPassword,
    77  		NewPassword:  newPassword,
    78  	}
    79  }
    80  
    81  // PasswordModify performs the modification request
    82  func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error) {
    83  	msgCtx, err := l.doRequest(passwordModifyRequest)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	defer l.finishMessage(msgCtx)
    88  
    89  	packet, err := l.readPacket(msgCtx)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  
    94  	result := &PasswordModifyResult{}
    95  
    96  	if packet.Children[1].Tag == ApplicationExtendedResponse {
    97  		if err = GetLDAPError(packet); err != nil {
    98  			result.Referral = getReferral(err, packet)
    99  
   100  			return result, err
   101  		}
   102  	} else {
   103  		return nil, NewError(ErrorUnexpectedResponse, fmt.Errorf("unexpected Response: %d", packet.Children[1].Tag))
   104  	}
   105  
   106  	extendedResponse := packet.Children[1]
   107  	for _, child := range extendedResponse.Children {
   108  		if child.Tag == ber.TagEmbeddedPDV {
   109  			passwordModifyResponseValue := ber.DecodePacket(child.Data.Bytes())
   110  			if len(passwordModifyResponseValue.Children) == 1 {
   111  				if passwordModifyResponseValue.Children[0].Tag == ber.TagEOC {
   112  					result.GeneratedPassword = ber.DecodeString(passwordModifyResponseValue.Children[0].Data.Bytes())
   113  				}
   114  			}
   115  		}
   116  	}
   117  
   118  	return result, nil
   119  }
   120  

View as plain text