/* * * Copyright (C) 2012 - Marc Quinton. * * Use of this source code is governed by the MIT Licence : * http://opensource.org/licenses/mit-license.php * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package openldap /*#include #include #include #include int _berval_get_len(struct berval **ber, int i){ return ber[i]->bv_len; } char* _berval_get_value(struct berval **ber, int i){ return ber[i]->bv_val; } */ // #cgo CFLAGS: -DLDAP_DEPRECATED=1 // #cgo linux CFLAGS: -DLINUX=1 // #cgo LDFLAGS: -lldap -llber import "C" import ( "errors" "fmt" "unsafe" ) // ------------------------------------------ RESULTS methods --------------------------------------------- /* openldap C API : int ldap_count_messages( LDAP *ld, LdapMessage *result ) LdapMessage *ldap_first_message( LDAP *ld, LdapMessage *result ) LdapMessage *ldap_next_message ( LDAP *ld, LdapMessage *message ) int ldap_count_entries( LDAP *ld, LdapMessage *result ) LdapMessage *ldap_first_entry( LDAP *ld, LdapMessage *result ) LdapMessage *ldap_next_entry ( LDAP *ld, LdapMessage *entry ) char *ldap_first_attribute(LDAP *ld, LdapMessage *entry, BerElement **berptr ) char *ldap_next_attribute (LDAP *ld, LdapMessage *entry, BerElement *ber ) char **ldap_get_values(LDAP *ld, LdapMessage *entry, char *attr) struct berval **ldap_get_values_len(LDAP *ld, LdapMessage *entry,char *attr) int ldap_count_values(char **vals) int ldap_count_values_len(struct berval **vals) void ldap_value_free(char **vals) void ldap_value_free_len(struct berval **vals) */ func (self *LdapMessage) Count() int { // API : int ldap_count_messages(LDAP *ld, LDAPMessage *chain ) // err : (count = -1) count := int(C.ldap_count_messages(self.ldap.conn, self.msg)) if count == -1 { panic("LDAP::Count() (ldap_count_messages) error (-1)") } return count } func (self *LdapMessage) FirstMessage() *LdapMessage { var msg *C.LDAPMessage msg = C.ldap_first_message(self.ldap.conn, self.msg) if msg == nil { return nil } _msg := new(LdapMessage) _msg.ldap = self.ldap _msg.errno = 0 _msg.msg = msg return _msg } func (self *LdapMessage) NextMessage() *LdapMessage { var msg *C.LDAPMessage msg = C.ldap_next_message(self.ldap.conn, self.msg) if msg == nil { return nil } _msg := new(LdapMessage) _msg.ldap = self.ldap _msg.errno = 0 _msg.msg = msg return _msg } /* an alias to ldap_count_message() ? */ func (self *LdapEntry) CountEntries() int { // API : int ldap_count_messages(LDAP *ld, LDAPMessage *chain ) // err : (count = -1) return int(C.ldap_count_entries(self.ldap.conn, self.entry)) } func (self *LdapMessage) FirstEntry() *LdapEntry { var msg *C.LDAPMessage // API: LdapMessage *ldap_first_entry( LDAP *ld, LdapMessage *result ) msg = C.ldap_first_entry(self.ldap.conn, self.msg) if msg == nil { return nil } _msg := new(LdapEntry) _msg.ldap = self.ldap _msg.errno = 0 _msg.entry = msg return _msg } func (self *LdapEntry) NextEntry() *LdapEntry { var msg *C.LDAPMessage // API: LdapMessage *ldap_next_entry ( LDAP *ld, LdapMessage *entry ) msg = C.ldap_next_entry(self.ldap.conn, self.entry) if msg == nil { return nil } _msg := new(LdapEntry) _msg.ldap = self.ldap _msg.errno = 0 _msg.entry = msg return _msg } func (self *LdapEntry) FirstAttribute() (string, error) { var ber *C.BerElement // API: char *ldap_first_attribute(LDAP *ld, LdapMessage *entry, BerElement **berptr ) rv := C.ldap_first_attribute(self.ldap.conn, self.entry, &ber) if rv == nil { // error return "", nil } self.ber = ber return C.GoString(rv), nil } func (self *LdapEntry) NextAttribute() (string, error) { // API: char *ldap_next_attribute (LDAP *ld, LdapMessage *entry, BerElement *ber ) rv := C.ldap_next_attribute(self.ldap.conn, self.entry, self.ber) if rv == nil { // error return "", nil } return C.GoString(rv), nil } // private func func sptr(p uintptr) *C.char { return *(**C.char)(unsafe.Pointer(p)) } // private func used to convert null terminated char*[] to go []string func cstrings_array(x **C.char) []string { var s []string for p := uintptr(unsafe.Pointer(x)); sptr(p) != nil; p += unsafe.Sizeof(uintptr(0)) { s = append(s, C.GoString(sptr(p))) } return s } // GetValues() return an array of string containing values for LDAP attribute "attr". // Binary data are supported. func (self *LdapEntry) GetValues(attr string) []string { var s []string _attr := C.CString(attr) defer C.free(unsafe.Pointer(_attr)) var bv **C.struct_berval //API: struct berval **ldap_get_values_len(LDAP *ld, LDAPMessage *entry, char *attr) bv = C.ldap_get_values_len(self.ldap.conn, self.entry, _attr) var i int count := int(C.ldap_count_values_len(bv)) for i = 0 ; i < count; i++ { s = append(s, C.GoStringN(C._berval_get_value(bv, C.int(i)), C._berval_get_len(bv, C.int(i)))) } // free allocated array (bv) C.ldap_value_free_len(bv) return s } // ------------------------------------------------ RESULTS ----------------------------------------------- /* int ldap_result ( LDAP *ld, int msgid, int all, struct timeval *timeout, LdapMessage **result ); int ldap_msgfree( LdapMessage *msg ); int ldap_msgtype( LdapMessage *msg ); int ldap_msgid ( LdapMessage *msg ); */ // Result() // take care to free LdapMessage result with MsgFree() // func (self *Ldap) Result() (*LdapMessage, error) { var msgid int = 1 var all int = 1 var tv C.struct_timeval tv.tv_sec = 30 var msg *C.LDAPMessage // API: int ldap_result( LDAP *ld, int msgid, int all, struct timeval *timeout, LDAPMessage **result ); rv := C.ldap_result(self.conn, C.int(msgid), C.int(all), &tv, &msg) if rv != LDAP_OPT_SUCCESS { return nil, errors.New(fmt.Sprintf("LDAP::Result() error : %d (%s)", rv, ErrorToString(int(rv)))) } _msg := new(LdapMessage) _msg.ldap = self _msg.errno = int(rv) _msg.msg = msg return _msg, nil } // MsgFree() is used to free LDAP::Result() allocated data // // returns -1 on error. // func (self *LdapMessage) MsgFree() int{ if self.msg != nil { rv := C.ldap_msgfree(self.msg) self.msg = nil return int(rv) } return -1 } // ---------------------------------------- DN Methods --------------------------------------------------- /* char *ldap_get_dn( LDAP *ld, LdapMessage *entry) int ldap_str2dn( const char *str, LDAPDN *dn, unsigned flags) void ldap_dnfree( LDAPDN dn) int ldap_dn2str( LDAPDN dn, char **str, unsigned flags) char **ldap_explode_dn( const char *dn, int notypes) char **ldap_explode_rdn( const char *rdn, int notypes) char *ldap_dn2ufn ( const char * dn ) char *ldap_dn2dcedn( const char * dn ) char *ldap_dcedn2dn( const char * dn ) char *ldap_dn2ad_canonical( const char * dn ) */ // GetDn() return the DN (Distinguish Name) for self LdapEntry func (self *LdapEntry) GetDn() string { // API: char *ldap_get_dn( LDAP *ld, LDAPMessage *entry ) rv := C.ldap_get_dn(self.ldap.conn, self.entry) defer C.free(unsafe.Pointer(rv)) if rv == nil { err := self.ldap.Errno() panic(fmt.Sprintf("LDAP::GetDn() error %d (%s)", err, ErrorToString(err))) } val := C.GoString(rv) return val }