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.

113 lines
3.3 KiB

  1. //
  2. // https://tools.ietf.org/html/rfc4511
  3. //
  4. // AddRequest ::= [APPLICATION 8] SEQUENCE {
  5. // entry LDAPDN,
  6. // attributes AttributeList }
  7. //
  8. // AttributeList ::= SEQUENCE OF attribute Attribute
  9. package ldap
  10. import (
  11. "errors"
  12. "log"
  13. "gopkg.in/asn1-ber.v1"
  14. )
  15. // Attribute represents an LDAP attribute
  16. type Attribute struct {
  17. // Type is the name of the LDAP attribute
  18. Type string
  19. // Vals are the LDAP attribute values
  20. Vals []string
  21. }
  22. func (a *Attribute) encode() *ber.Packet {
  23. seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute")
  24. seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.Type, "Type"))
  25. set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
  26. for _, value := range a.Vals {
  27. set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
  28. }
  29. seq.AppendChild(set)
  30. return seq
  31. }
  32. // AddRequest represents an LDAP AddRequest operation
  33. type AddRequest struct {
  34. // DN identifies the entry being added
  35. DN string
  36. // Attributes list the attributes of the new entry
  37. Attributes []Attribute
  38. }
  39. func (a AddRequest) encode() *ber.Packet {
  40. request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationAddRequest, nil, "Add Request")
  41. request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.DN, "DN"))
  42. attributes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
  43. for _, attribute := range a.Attributes {
  44. attributes.AppendChild(attribute.encode())
  45. }
  46. request.AppendChild(attributes)
  47. return request
  48. }
  49. // Attribute adds an attribute with the given type and values
  50. func (a *AddRequest) Attribute(attrType string, attrVals []string) {
  51. a.Attributes = append(a.Attributes, Attribute{Type: attrType, Vals: attrVals})
  52. }
  53. // NewAddRequest returns an AddRequest for the given DN, with no attributes
  54. func NewAddRequest(dn string) *AddRequest {
  55. return &AddRequest{
  56. DN: dn,
  57. }
  58. }
  59. // Add performs the given AddRequest
  60. func (l *Conn) Add(addRequest *AddRequest) error {
  61. packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
  62. packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
  63. packet.AppendChild(addRequest.encode())
  64. l.Debug.PrintPacket(packet)
  65. msgCtx, err := l.sendMessage(packet)
  66. if err != nil {
  67. return err
  68. }
  69. defer l.finishMessage(msgCtx)
  70. l.Debug.Printf("%d: waiting for response", msgCtx.id)
  71. packetResponse, ok := <-msgCtx.responses
  72. if !ok {
  73. return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
  74. }
  75. packet, err = packetResponse.ReadPacket()
  76. l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
  77. if err != nil {
  78. return err
  79. }
  80. if l.Debug {
  81. if err := addLDAPDescriptions(packet); err != nil {
  82. return err
  83. }
  84. ber.PrintPacket(packet)
  85. }
  86. if packet.Children[1].Tag == ApplicationAddResponse {
  87. resultCode, resultDescription := getLDAPResultCode(packet)
  88. if resultCode != 0 {
  89. return NewError(resultCode, errors.New(resultDescription))
  90. }
  91. } else {
  92. log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
  93. }
  94. l.Debug.Printf("%d: returning", msgCtx.id)
  95. return nil
  96. }