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 }