github.com/hxx258456/fabric-ca-gm@v0.0.3-0.20221111064038-a268ad7e3a37/ldap_v2/modify.go (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  //
     5  // File contains Modify functionality
     6  //
     7  // https://tools.ietf.org/html/rfc4511
     8  //
     9  // ModifyRequest ::= [APPLICATION 6] SEQUENCE {
    10  //      object          LDAPDN,
    11  //      changes         SEQUENCE OF change SEQUENCE {
    12  //           operation       ENUMERATED {
    13  //                add     (0),
    14  //                delete  (1),
    15  //                replace (2),
    16  //                ...  },
    17  //           modification    PartialAttribute } }
    18  //
    19  // PartialAttribute ::= SEQUENCE {
    20  //      type       AttributeDescription,
    21  //      vals       SET OF value AttributeValue }
    22  //
    23  // AttributeDescription ::= LDAPString
    24  //                         -- Constrained to <attributedescription>
    25  //                         -- [RFC4512]
    26  //
    27  // AttributeValue ::= OCTET STRING
    28  //
    29  
    30  package ldap
    31  
    32  import (
    33  	"errors"
    34  
    35  	log "gitee.com/zhaochuninhefei/zcgolog/zclog"
    36  	ber "gopkg.in/asn1-ber.v1"
    37  )
    38  
    39  // Change operation choices
    40  const (
    41  	AddAttribute     = 0
    42  	DeleteAttribute  = 1
    43  	ReplaceAttribute = 2
    44  )
    45  
    46  // PartialAttribute for a ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
    47  type PartialAttribute struct {
    48  	// Type is the type of the partial attribute
    49  	Type string
    50  	// Vals are the values of the partial attribute
    51  	Vals []string
    52  }
    53  
    54  func (p *PartialAttribute) encode() *ber.Packet {
    55  	seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "PartialAttribute")
    56  	seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, p.Type, "Type"))
    57  	set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
    58  	for _, value := range p.Vals {
    59  		set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
    60  	}
    61  	seq.AppendChild(set)
    62  	return seq
    63  }
    64  
    65  // ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
    66  type ModifyRequest struct {
    67  	// DN is the distinguishedName of the directory entry to modify
    68  	DN string
    69  	// AddAttributes contain the attributes to add
    70  	AddAttributes []PartialAttribute
    71  	// DeleteAttributes contain the attributes to delete
    72  	DeleteAttributes []PartialAttribute
    73  	// ReplaceAttributes contain the attributes to replace
    74  	ReplaceAttributes []PartialAttribute
    75  }
    76  
    77  // Add inserts the given attribute to the list of attributes to add
    78  func (m *ModifyRequest) Add(attrType string, attrVals []string) {
    79  	m.AddAttributes = append(m.AddAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
    80  }
    81  
    82  // Delete inserts the given attribute to the list of attributes to delete
    83  func (m *ModifyRequest) Delete(attrType string, attrVals []string) {
    84  	m.DeleteAttributes = append(m.DeleteAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
    85  }
    86  
    87  // Replace inserts the given attribute to the list of attributes to replace
    88  func (m *ModifyRequest) Replace(attrType string, attrVals []string) {
    89  	m.ReplaceAttributes = append(m.ReplaceAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
    90  }
    91  
    92  func (m ModifyRequest) encode() *ber.Packet {
    93  	request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyRequest, nil, "Modify Request")
    94  	request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.DN, "DN"))
    95  	changes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Changes")
    96  	for _, attribute := range m.AddAttributes {
    97  		change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
    98  		change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(AddAttribute), "Operation"))
    99  		change.AppendChild(attribute.encode())
   100  		changes.AppendChild(change)
   101  	}
   102  	for _, attribute := range m.DeleteAttributes {
   103  		change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
   104  		change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(DeleteAttribute), "Operation"))
   105  		change.AppendChild(attribute.encode())
   106  		changes.AppendChild(change)
   107  	}
   108  	for _, attribute := range m.ReplaceAttributes {
   109  		change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
   110  		change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(ReplaceAttribute), "Operation"))
   111  		change.AppendChild(attribute.encode())
   112  		changes.AppendChild(change)
   113  	}
   114  	request.AppendChild(changes)
   115  	return request
   116  }
   117  
   118  // NewModifyRequest creates a modify request for the given DN
   119  func NewModifyRequest(
   120  	dn string,
   121  ) *ModifyRequest {
   122  	return &ModifyRequest{
   123  		DN: dn,
   124  	}
   125  }
   126  
   127  // Modify performs the ModifyRequest
   128  func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
   129  	packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
   130  	packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
   131  	packet.AppendChild(modifyRequest.encode())
   132  
   133  	l.Debug.PrintPacket(packet)
   134  
   135  	msgCtx, err := l.sendMessage(packet)
   136  	if err != nil {
   137  		return err
   138  	}
   139  	defer l.finishMessage(msgCtx)
   140  
   141  	l.Debug.Printf("%d: waiting for response", msgCtx.id)
   142  	packetResponse, ok := <-msgCtx.responses
   143  	if !ok {
   144  		return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
   145  	}
   146  	packet, err = packetResponse.ReadPacket()
   147  	l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
   148  	if err != nil {
   149  		return err
   150  	}
   151  
   152  	if l.Debug {
   153  		if err := addLDAPDescriptions(packet); err != nil {
   154  			return err
   155  		}
   156  		ber.PrintPacket(packet)
   157  	}
   158  
   159  	if packet.Children[1].Tag == ApplicationModifyResponse {
   160  		resultCode, resultDescription := getLDAPResultCode(packet)
   161  		if resultCode != 0 {
   162  			return NewError(resultCode, errors.New(resultDescription))
   163  		}
   164  	} else {
   165  		log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
   166  	}
   167  
   168  	l.Debug.Printf("%d: returning", msgCtx.id)
   169  	return nil
   170  }