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.

104 lines
3.2 KiB

  1. // Package ldap - moddn.go contains ModifyDN functionality
  2. //
  3. // https://tools.ietf.org/html/rfc4511
  4. // ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
  5. // entry LDAPDN,
  6. // newrdn RelativeLDAPDN,
  7. // deleteoldrdn BOOLEAN,
  8. // newSuperior [0] LDAPDN OPTIONAL }
  9. //
  10. //
  11. package ldap
  12. import (
  13. "errors"
  14. "log"
  15. "gopkg.in/asn1-ber.v1"
  16. )
  17. // ModifyDNRequest holds the request to modify a DN
  18. type ModifyDNRequest struct {
  19. DN string
  20. NewRDN string
  21. DeleteOldRDN bool
  22. NewSuperior string
  23. }
  24. // NewModifyDNRequest creates a new request which can be passed to ModifyDN().
  25. //
  26. // To move an object in the tree, set the "newSup" to the new parent entry DN. Use an
  27. // empty string for just changing the object's RDN.
  28. //
  29. // For moving the object without renaming, the "rdn" must be the first
  30. // RDN of the given DN.
  31. //
  32. // A call like
  33. // mdnReq := NewModifyDNRequest("uid=someone,dc=example,dc=org", "uid=newname", true, "")
  34. // will setup the request to just rename uid=someone,dc=example,dc=org to
  35. // uid=newname,dc=example,dc=org.
  36. func NewModifyDNRequest(dn string, rdn string, delOld bool, newSup string) *ModifyDNRequest {
  37. return &ModifyDNRequest{
  38. DN: dn,
  39. NewRDN: rdn,
  40. DeleteOldRDN: delOld,
  41. NewSuperior: newSup,
  42. }
  43. }
  44. func (m ModifyDNRequest) encode() *ber.Packet {
  45. request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyDNRequest, nil, "Modify DN Request")
  46. request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.DN, "DN"))
  47. request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.NewRDN, "New RDN"))
  48. request.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, m.DeleteOldRDN, "Delete old RDN"))
  49. if m.NewSuperior != "" {
  50. request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, m.NewSuperior, "New Superior"))
  51. }
  52. return request
  53. }
  54. // ModifyDN renames the given DN and optionally move to another base (when the "newSup" argument
  55. // to NewModifyDNRequest() is not "").
  56. func (l *Conn) ModifyDN(m *ModifyDNRequest) error {
  57. packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
  58. packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
  59. packet.AppendChild(m.encode())
  60. l.Debug.PrintPacket(packet)
  61. msgCtx, err := l.sendMessage(packet)
  62. if err != nil {
  63. return err
  64. }
  65. defer l.finishMessage(msgCtx)
  66. l.Debug.Printf("%d: waiting for response", msgCtx.id)
  67. packetResponse, ok := <-msgCtx.responses
  68. if !ok {
  69. return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
  70. }
  71. packet, err = packetResponse.ReadPacket()
  72. l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
  73. if err != nil {
  74. return err
  75. }
  76. if l.Debug {
  77. if err := addLDAPDescriptions(packet); err != nil {
  78. return err
  79. }
  80. ber.PrintPacket(packet)
  81. }
  82. if packet.Children[1].Tag == ApplicationModifyDNResponse {
  83. err := GetLDAPError(packet)
  84. if err != nil {
  85. return err
  86. }
  87. } else {
  88. log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
  89. }
  90. l.Debug.Printf("%d: returning", msgCtx.id)
  91. return nil
  92. }