| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- package ldap
- import (
- "fmt"
- ber "github.com/go-asn1-ber/asn1-ber"
- )
- const (
- passwordModifyOID = "1.3.6.1.4.1.4203.1.11.1"
- )
- // PasswordModifyRequest implements the Password Modify Extended Operation as defined in https://www.ietf.org/rfc/rfc3062.txt
- type PasswordModifyRequest struct {
- // UserIdentity is an optional string representation of the user associated with the request.
- // This string may or may not be an LDAPDN [RFC2253].
- // If no UserIdentity field is present, the request acts up upon the password of the user currently associated with the LDAP session
- UserIdentity string
- // OldPassword, if present, contains the user's current password
- OldPassword string
- // NewPassword, if present, contains the desired password for this user
- NewPassword string
- }
- // PasswordModifyResult holds the server response to a PasswordModifyRequest
- type PasswordModifyResult struct {
- // GeneratedPassword holds a password generated by the server, if present
- GeneratedPassword string
- // Referral are the returned referral
- Referral string
- }
- func (req *PasswordModifyRequest) appendTo(envelope *ber.Packet) error {
- pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationExtendedRequest, nil, "Password Modify Extended Operation")
- pkt.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 req.UserIdentity != "" {
- passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, req.UserIdentity, "User Identity"))
- }
- if req.OldPassword != "" {
- passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 1, req.OldPassword, "Old Password"))
- }
- if req.NewPassword != "" {
- passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 2, req.NewPassword, "New Password"))
- }
- extendedRequestValue.AppendChild(passwordModifyRequestValue)
- pkt.AppendChild(extendedRequestValue)
- envelope.AppendChild(pkt)
- return nil
- }
- // NewPasswordModifyRequest creates a new PasswordModifyRequest
- //
- // According to the RFC 3602 (https://tools.ietf.org/html/rfc3062):
- // 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,
- }
- }
- // PasswordModify performs the modification request
- func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error) {
- msgCtx, err := l.doRequest(passwordModifyRequest)
- if err != nil {
- return nil, err
- }
- defer l.finishMessage(msgCtx)
- packet, err := l.readPacket(msgCtx)
- if err != nil {
- return nil, err
- }
- result := &PasswordModifyResult{}
- if packet.Children[1].Tag == ApplicationExtendedResponse {
- err := GetLDAPError(packet)
- if err != nil {
- if IsErrorWithCode(err, LDAPResultReferral) {
- for _, child := range packet.Children[1].Children {
- if child.Tag == 3 {
- result.Referral = child.Children[0].Value.(string)
- }
- }
- }
- return result, err
- }
- } 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 {
- passwordModifyResponseValue := ber.DecodePacket(child.Data.Bytes())
- if len(passwordModifyResponseValue.Children) == 1 {
- if passwordModifyResponseValue.Children[0].Tag == 0 {
- result.GeneratedPassword = ber.DecodeString(passwordModifyResponseValue.Children[0].Data.Bytes())
- }
- }
- }
- }
- return result, nil
- }
|