-
Notifications
You must be signed in to change notification settings - Fork 365
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add ModifyDN() - moddn/modrdn (#149)
Update README update docs, changes needed for #57 add ModifyDN() to client update to use msgCtx fix missing comma, add moddn_test.go with examples rename example functions to match the conventions for godoc add missing parens
- Loading branch information
Showing
4 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// Package ldap - moddn.go contains ModifyDN functionality | ||
// | ||
// https://tools.ietf.org/html/rfc4511 | ||
// ModifyDNRequest ::= [APPLICATION 12] SEQUENCE { | ||
// entry LDAPDN, | ||
// newrdn RelativeLDAPDN, | ||
// deleteoldrdn BOOLEAN, | ||
// newSuperior [0] LDAPDN OPTIONAL } | ||
// | ||
// | ||
package ldap | ||
|
||
import ( | ||
"errors" | ||
"log" | ||
|
||
"gopkg.in/asn1-ber.v1" | ||
) | ||
|
||
// ModifyDNRequest holds the request to modify a DN | ||
type ModifyDNRequest struct { | ||
DN string | ||
NewRDN string | ||
DeleteOldRDN bool | ||
NewSuperior string | ||
} | ||
|
||
// NewModifyDNRequest creates a new request which can be passed to ModifyDN(). | ||
// | ||
// To move an object in the tree, set the "newSup" to the new parent entry DN. Use an | ||
// empty string for just changing the object's RDN. | ||
// | ||
// For moving the object without renaming, the "rdn" must be the first | ||
// RDN of the given DN. | ||
// | ||
// A call like | ||
// mdnReq := NewModifyDNRequest("uid=someone,dc=example,dc=org", "uid=newname", true, "") | ||
// will setup the request to just rename uid=someone,dc=example,dc=org to | ||
// uid=newname,dc=example,dc=org. | ||
func NewModifyDNRequest(dn string, rdn string, delOld bool, newSup string) *ModifyDNRequest { | ||
return &ModifyDNRequest{ | ||
DN: dn, | ||
NewRDN: rdn, | ||
DeleteOldRDN: delOld, | ||
NewSuperior: newSup, | ||
} | ||
} | ||
|
||
func (m ModifyDNRequest) encode() *ber.Packet { | ||
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyDNRequest, nil, "Modify DN Request") | ||
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.DN, "DN")) | ||
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.NewRDN, "New RDN")) | ||
request.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, m.DeleteOldRDN, "Delete old RDN")) | ||
if m.NewSuperior != "" { | ||
request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, m.NewSuperior, "New Superior")) | ||
} | ||
return request | ||
} | ||
|
||
// ModifyDN renames the given DN and optionally move to another base (when the "newSup" argument | ||
// to NewModifyDNRequest() is not ""). | ||
func (l *Conn) ModifyDN(m *ModifyDNRequest) error { | ||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request") | ||
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID")) | ||
packet.AppendChild(m.encode()) | ||
|
||
l.Debug.PrintPacket(packet) | ||
|
||
msgCtx, err := l.sendMessage(packet) | ||
if err != nil { | ||
return err | ||
} | ||
defer l.finishMessage(msgCtx) | ||
|
||
l.Debug.Printf("%d: waiting for response", msgCtx.id) | ||
packetResponse, ok := <-msgCtx.responses | ||
if !ok { | ||
return NewError(ErrorNetwork, errors.New("ldap: channel closed")) | ||
} | ||
packet, err = packetResponse.ReadPacket() | ||
l.Debug.Printf("%d: got response %p", msgCtx.id, packet) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if l.Debug { | ||
if err := addLDAPDescriptions(packet); err != nil { | ||
return err | ||
} | ||
ber.PrintPacket(packet) | ||
} | ||
|
||
if packet.Children[1].Tag == ApplicationModifyDNResponse { | ||
resultCode, resultDescription := getLDAPResultCode(packet) | ||
if resultCode != 0 { | ||
return NewError(resultCode, errors.New(resultDescription)) | ||
} | ||
} else { | ||
log.Printf("Unexpected Response: %d", packet.Children[1].Tag) | ||
} | ||
|
||
l.Debug.Printf("%d: returning", msgCtx.id) | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package ldap_test | ||
|
||
import ( | ||
"log" | ||
|
||
"gopkg.in/ldap.v2" | ||
) | ||
|
||
// ExampleConn_ModifyDN_renameNoMove shows how to rename an entry without moving it | ||
func ExampleConn_ModifyDN_renameNoMove() { | ||
conn, err := ldap.Dial("tcp", "ldap.example.org:389") | ||
if err != nil { | ||
log.Fatalf("Failed to connect: %s\n", err) | ||
} | ||
defer conn.Close() | ||
|
||
_, err = conn.SimpleBind(&ldap.SimpleBindRequest{ | ||
Username: "uid=someone,ou=people,dc=example,dc=org", | ||
Password: "MySecretPass", | ||
}) | ||
if err != nil { | ||
log.Fatalf("Failed to bind: %s\n", err) | ||
} | ||
// just rename to uid=new,ou=people,dc=example,dc=org: | ||
req := ldap.NewModifyDNRequest("uid=user,ou=people,dc=example,dc=org", "uid=new", true, "") | ||
if err = conn.ModifyDN(req); err != nil { | ||
log.Fatalf("Failed to call ModifyDN(): %s\n", err) | ||
} | ||
} | ||
|
||
// ExampleConn_ModifyDN_renameAndMove shows how to rename an entry and moving it to a new base | ||
func ExampleConn_ModifyDN_renameAndMove() { | ||
conn, err := ldap.Dial("tcp", "ldap.example.org:389") | ||
if err != nil { | ||
log.Fatalf("Failed to connect: %s\n", err) | ||
} | ||
defer conn.Close() | ||
|
||
_, err = conn.SimpleBind(&ldap.SimpleBindRequest{ | ||
Username: "uid=someone,ou=people,dc=example,dc=org", | ||
Password: "MySecretPass", | ||
}) | ||
if err != nil { | ||
log.Fatalf("Failed to bind: %s\n", err) | ||
} | ||
// rename to uid=new,ou=people,dc=example,dc=org and move to ou=users,dc=example,dc=org -> | ||
// uid=new,ou=users,dc=example,dc=org | ||
req := ldap.NewModifyDNRequest("uid=user,ou=people,dc=example,dc=org", "uid=new", true, "ou=users,dc=example,dc=org") | ||
|
||
if err = conn.ModifyDN(req); err != nil { | ||
log.Fatalf("Failed to call ModifyDN(): %s\n", err) | ||
} | ||
} | ||
|
||
// ExampleConn_ModifyDN_moveOnly shows how to move an entry to a new base without renaming the RDN | ||
func ExampleConn_ModifyDN_moveOnly() { | ||
conn, err := ldap.Dial("tcp", "ldap.example.org:389") | ||
if err != nil { | ||
log.Fatalf("Failed to connect: %s\n", err) | ||
} | ||
defer conn.Close() | ||
|
||
_, err = conn.SimpleBind(&ldap.SimpleBindRequest{ | ||
Username: "uid=someone,ou=people,dc=example,dc=org", | ||
Password: "MySecretPass", | ||
}) | ||
if err != nil { | ||
log.Fatalf("Failed to bind: %s\n", err) | ||
} | ||
// move to ou=users,dc=example,dc=org -> uid=user,ou=users,dc=example,dc=org | ||
req := ldap.NewModifyDNRequest("uid=user,ou=people,dc=example,dc=org", "uid=user", true, "ou=users,dc=example,dc=org") | ||
if err = conn.ModifyDN(req); err != nil { | ||
log.Fatalf("Failed to call ModifyDN(): %s\n", err) | ||
} | ||
} |