You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
5.1 KiB

10 years ago
  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. package ldap
  30. import (
  31. "errors"
  32. "log"
  33. "github.com/gogits/gogs/modules/asn1-ber"
  34. )
  35. const (
  36. AddAttribute = 0
  37. DeleteAttribute = 1
  38. ReplaceAttribute = 2
  39. )
  40. type PartialAttribute struct {
  41. attrType string
  42. attrVals []string
  43. }
  44. func (p *PartialAttribute) encode() *ber.Packet {
  45. seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "PartialAttribute")
  46. seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, p.attrType, "Type"))
  47. set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
  48. for _, value := range p.attrVals {
  49. set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
  50. }
  51. seq.AppendChild(set)
  52. return seq
  53. }
  54. type ModifyRequest struct {
  55. dn string
  56. addAttributes []PartialAttribute
  57. deleteAttributes []PartialAttribute
  58. replaceAttributes []PartialAttribute
  59. }
  60. func (m *ModifyRequest) Add(attrType string, attrVals []string) {
  61. m.addAttributes = append(m.addAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
  62. }
  63. func (m *ModifyRequest) Delete(attrType string, attrVals []string) {
  64. m.deleteAttributes = append(m.deleteAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
  65. }
  66. func (m *ModifyRequest) Replace(attrType string, attrVals []string) {
  67. m.replaceAttributes = append(m.replaceAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
  68. }
  69. func (m ModifyRequest) encode() *ber.Packet {
  70. request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyRequest, nil, "Modify Request")
  71. request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.dn, "DN"))
  72. changes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Changes")
  73. for _, attribute := range m.addAttributes {
  74. change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
  75. change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(AddAttribute), "Operation"))
  76. change.AppendChild(attribute.encode())
  77. changes.AppendChild(change)
  78. }
  79. for _, attribute := range m.deleteAttributes {
  80. change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
  81. change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(DeleteAttribute), "Operation"))
  82. change.AppendChild(attribute.encode())
  83. changes.AppendChild(change)
  84. }
  85. for _, attribute := range m.replaceAttributes {
  86. change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
  87. change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(ReplaceAttribute), "Operation"))
  88. change.AppendChild(attribute.encode())
  89. changes.AppendChild(change)
  90. }
  91. request.AppendChild(changes)
  92. return request
  93. }
  94. func NewModifyRequest(
  95. dn string,
  96. ) *ModifyRequest {
  97. return &ModifyRequest{
  98. dn: dn,
  99. }
  100. }
  101. func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
  102. messageID := l.nextMessageID()
  103. packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
  104. packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
  105. packet.AppendChild(modifyRequest.encode())
  106. l.Debug.PrintPacket(packet)
  107. channel, err := l.sendMessage(packet)
  108. if err != nil {
  109. return err
  110. }
  111. if channel == nil {
  112. return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
  113. }
  114. defer l.finishMessage(messageID)
  115. l.Debug.Printf("%d: waiting for response", messageID)
  116. packet = <-channel
  117. l.Debug.Printf("%d: got response %p", messageID, packet)
  118. if packet == nil {
  119. return NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
  120. }
  121. if l.Debug {
  122. if err := addLDAPDescriptions(packet); err != nil {
  123. return err
  124. }
  125. ber.PrintPacket(packet)
  126. }
  127. if packet.Children[1].Tag == ApplicationModifyResponse {
  128. resultCode, resultDescription := getLDAPResultCode(packet)
  129. if resultCode != 0 {
  130. return NewError(resultCode, errors.New(resultDescription))
  131. }
  132. } else {
  133. log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
  134. }
  135. l.Debug.Printf("%d: returning", messageID)
  136. return nil
  137. }