class LDAPException : public std::runtime_error
{
-public:
- explicit LDAPException( const std::string &str ) : std::runtime_error( str ) {}
+ public:
+ explicit LDAPException( const std::string &str ) : std::runtime_error( str ) {}
};
class LDAPTimeout : public LDAPException
{
-public:
- explicit LDAPTimeout() : LDAPException( "Timeout" ) {}
+ public:
+ explicit LDAPTimeout() : LDAPException( "Timeout" ) {}
};
class LDAPNoConnection : public LDAPException
{
-public:
- explicit LDAPNoConnection() : LDAPException( "No connection to LDAP server" ) {}
+ public:
+ explicit LDAPNoConnection() : LDAPException( "No connection to LDAP server" ) {}
};
#endif // LDAPEXCEPTIONS_HH
****************************/
LdapSimpleAuthenticator::LdapSimpleAuthenticator( const std::string& dn, const std::string& pw, int tmout )
- : binddn( dn ), bindpw( pw ), timeout( tmout )
+ : binddn( dn ), bindpw( pw ), timeout( tmout )
{
}
bool LdapSimpleAuthenticator::authenticate( LDAP *conn )
{
- int msgid;
+ int msgid;
#ifdef HAVE_LDAP_SASL_BIND
- int rc;
- struct berval passwd;
+ int rc;
+ struct berval passwd;
- passwd.bv_val = (char *)bindpw.c_str();
- passwd.bv_len = strlen( passwd.bv_val );
+ passwd.bv_val = (char *)bindpw.c_str();
+ passwd.bv_len = strlen( passwd.bv_val );
- if( ( rc = ldap_sasl_bind( conn, binddn.c_str(), LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid ) ) != LDAP_SUCCESS )
- {
- fillLastError( conn, rc );
- return false;
- }
+ if( ( rc = ldap_sasl_bind( conn, binddn.c_str(), LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid ) ) != LDAP_SUCCESS )
+ {
+ fillLastError( conn, rc );
+ return false;
+ }
#else
- if( ( msgid = ldap_bind( conn, binddn.c_str(), bindpw.c_str(), LDAP_AUTH_SIMPLE ) ) == -1 )
- {
- fillLastError( conn, msgid );
- return false;
- }
+ if( ( msgid = ldap_bind( conn, binddn.c_str(), bindpw.c_str(), LDAP_AUTH_SIMPLE ) ) == -1 )
+ {
+ fillLastError( conn, msgid );
+ return false;
+ }
#endif
- ldapWaitResult( conn, msgid, timeout, NULL );
- return true;
+ ldapWaitResult( conn, msgid, timeout, NULL );
+ return true;
}
std::string LdapSimpleAuthenticator::getError() const
{
- return lastError;
+ return lastError;
}
void LdapSimpleAuthenticator::fillLastError( LDAP* conn, int code )
{
- lastError = ldapGetError( conn, code );
+ lastError = ldapGetError( conn, code );
}
/*****************************
static int ldapGssapiAuthenticatorSaslInteractCallback( LDAP *conn, unsigned flags, void *defaults, void *in )
{
- return LDAP_SUCCESS;
+ return LDAP_SUCCESS;
}
LdapGssapiAuthenticator::LdapGssapiAuthenticator( const std::string& kt, const std::string &ccache, int tmout )
- : keytabFile( kt ), cCacheFile( ccache ), timeout( tmout )
+ : keytabFile( kt ), cCacheFile( ccache ), timeout( tmout )
{
}
bool LdapGssapiAuthenticator::authenticate( LDAP *conn )
{
- int code = attemptAuth( conn );
-
- if ( code == -1 ) {
- return false;
- }
- else if ( code == -2 ) {
- // Here it may be possible to retry after obtainting a fresh ticket
- L<<Logger::Debug << "LDAP GSSAPI" << "No TGT found, trying to acquire a new one" << std::endl;
- code = updateTgt();
-
- if ( attemptAuth( conn ) != 0 ) {
- L<<Logger::Error << "LDAP GSSAPI" << "Failed to acquire a TGT" << std::endl;
- return false;
- }
- }
-
- return true;
+ int code = attemptAuth( conn );
+
+ if ( code == -1 ) {
+ return false;
+ }
+ else if ( code == -2 ) {
+ // Here it may be possible to retry after obtainting a fresh ticket
+ L<<Logger::Debug << "LDAP GSSAPI" << "No TGT found, trying to acquire a new one" << std::endl;
+ code = updateTgt();
+
+ if ( attemptAuth( conn ) != 0 ) {
+ L<<Logger::Error << "LDAP GSSAPI" << "Failed to acquire a TGT" << std::endl;
+ return false;
+ }
+ }
+
+ return true;
}
std::string LdapGssapiAuthenticator::getError() const
{
- return lastError;
+ return lastError;
}
int LdapGssapiAuthenticator::attemptAuth( LDAP *conn )
{
- // Create SASL defaults
- SaslDefaults defaults;
- char *ldapOption = 0;
-
- ldap_get_option( conn, LDAP_OPT_X_SASL_MECH, ldapOption );
- if ( !ldapOption )
- defaults.mech = std::string( "GSSAPI" );
- else
- defaults.mech = std::string( ldapOption );
- ldap_memfree( ldapOption );
-
- ldap_get_option( conn, LDAP_OPT_X_SASL_REALM, ldapOption );
- if ( ldapOption )
- defaults.realm = std::string( ldapOption );
- ldap_memfree( ldapOption );
-
- ldap_get_option( conn, LDAP_OPT_X_SASL_AUTHCID, ldapOption );
- if ( ldapOption )
- defaults.authcid = std::string( ldapOption );
- ldap_memfree( ldapOption );
-
- ldap_get_option( conn, LDAP_OPT_X_SASL_AUTHZID, ldapOption );
- if ( ldapOption )
- defaults.authzid = std::string( ldapOption );
- ldap_memfree( ldapOption );
-
- // And now try to bind
- int rc = ldap_sasl_interactive_bind_s( conn, "", defaults.mech.c_str(),
- NULL, NULL, LDAP_SASL_QUIET,
- ldapGssapiAuthenticatorSaslInteractCallback, &defaults );
- L<<Logger::Debug << "LDAP GSSAPI" << "ldap_sasl_interactive_bind_s returned " << rc << std::endl;
-
- if ( rc == LDAP_LOCAL_ERROR ) {
- // This may mean that the ticket has expired, so let the caller know
- lastError = ldapGetError( conn, rc );
- return -2;
- }
- else if ( rc != LDAP_SUCCESS ) {
- lastError = ldapGetError( conn, rc );
- return -1;
- }
-
- return rc;
+ // Create SASL defaults
+ SaslDefaults defaults;
+ char *ldapOption = 0;
+
+ ldap_get_option( conn, LDAP_OPT_X_SASL_MECH, ldapOption );
+ if ( !ldapOption )
+ defaults.mech = std::string( "GSSAPI" );
+ else
+ defaults.mech = std::string( ldapOption );
+ ldap_memfree( ldapOption );
+
+ ldap_get_option( conn, LDAP_OPT_X_SASL_REALM, ldapOption );
+ if ( ldapOption )
+ defaults.realm = std::string( ldapOption );
+ ldap_memfree( ldapOption );
+
+ ldap_get_option( conn, LDAP_OPT_X_SASL_AUTHCID, ldapOption );
+ if ( ldapOption )
+ defaults.authcid = std::string( ldapOption );
+ ldap_memfree( ldapOption );
+
+ ldap_get_option( conn, LDAP_OPT_X_SASL_AUTHZID, ldapOption );
+ if ( ldapOption )
+ defaults.authzid = std::string( ldapOption );
+ ldap_memfree( ldapOption );
+
+ // And now try to bind
+ int rc = ldap_sasl_interactive_bind_s( conn, "", defaults.mech.c_str(),
+ NULL, NULL, LDAP_SASL_QUIET,
+ ldapGssapiAuthenticatorSaslInteractCallback, &defaults );
+ L<<Logger::Debug << "LDAP GSSAPI" << "ldap_sasl_interactive_bind_s returned " << rc << std::endl;
+
+ if ( rc == LDAP_LOCAL_ERROR ) {
+ // This may mean that the ticket has expired, so let the caller know
+ lastError = ldapGetError( conn, rc );
+ return -2;
+ }
+ else if ( rc != LDAP_SUCCESS ) {
+ lastError = ldapGetError( conn, rc );
+ return -1;
+ }
+
+ return rc;
}
int LdapGssapiAuthenticator::updateTgt()
{
- krb5_error_code code;
- krb5_context context;
- krb5_creds credentials;
- krb5_keytab keytab;
- krb5_principal principal;
- krb5_ccache ccache;
- krb5_get_init_creds_opt *options;
-
- if ( ( code = krb5_init_context( &context ) ) != 0 ) {
- L<<Logger::Error << "LDAP GSSAPI" << "Failed to init krb5 context" << std::endl;
- return code;
- }
-
- if ( !keytabFile.empty() ) {
- std::string keytabStr( "FILE:" + keytabFile );
- code = krb5_kt_resolve( context, keytabStr.c_str(), &keytab );
- }
- else {
- code = krb5_kt_default( context, &keytab );
- }
-
- if ( code != 0 ) {
- L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
- return code;
- }
-
- // Extract the principal name from the keytab
- krb5_kt_cursor cursor;
- if ( ( code = krb5_kt_start_seq_get( context, keytab, &cursor ) ) != 0 ) {
- L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
- krb5_kt_close( context, keytab );
- return code;
- }
-
- krb5_keytab_entry entry;
- if ( ( code = krb5_kt_next_entry( context, keytab, &entry, &cursor ) ) == 0 ) {
- code = krb5_copy_principal( context, entry.principal, &principal );
- krb5_kt_free_entry( context, &entry );
- }
-
- krb5_kt_end_seq_get( context, keytab, &cursor );
- if ( code != 0 ) {
- L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
- krb5_kt_close( context, keytab );
- krb5_free_principal( context, principal );
- return code;
- }
-
- // Locate the credentials cache file
- if ( !cCacheFile.empty() ) {
- std::string cCacheStr( "FILE:" + cCacheFile );
- code = krb5_cc_resolve( context, cCacheStr.c_str(), &ccache );
- }
- else {
- code = krb5_cc_default( context, &ccache );
- }
-
- if ( code != 0 ) {
- L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
- krb5_kt_close( context, keytab );
- krb5_free_principal( context, principal );
- return code;
- }
-
- // Initialize the credentials cache file
- if ( ( code = krb5_cc_initialize( context, ccache, principal ) ) != 0 ) {
- L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
- krb5_kt_close( context, keytab );
- krb5_free_principal( context, principal );
- return code;
- }
-
- if ( ( code = krb5_get_init_creds_opt_alloc( context, &options ) ) != 0 ) {
- L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
- krb5_kt_close( context, keytab );
- krb5_free_principal( context, principal );
- return code;
- }
- krb5_get_init_creds_opt_set_default_flags( context, "pdns", NULL, options );
-
- // And finally get the TGT!
- code = krb5_get_init_creds_keytab( context, &credentials, principal, keytab, 0, NULL, options );
- krb5_get_init_creds_opt_free( context, options );
- krb5_kt_close( context, keytab );
- krb5_free_principal( context, principal );
-
- if ( code == 0 ) {
- L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
- code = krb5_cc_store_cred( context, ccache, &credentials );
- krb5_free_cred_contents( context, &credentials );
- krb5_cc_close( context, ccache );
- }
-
- krb5_free_context( context );
- return code;
+ krb5_error_code code;
+ krb5_context context;
+ krb5_creds credentials;
+ krb5_keytab keytab;
+ krb5_principal principal;
+ krb5_ccache ccache;
+ krb5_get_init_creds_opt *options;
+
+ if ( ( code = krb5_init_context( &context ) ) != 0 ) {
+ L<<Logger::Error << "LDAP GSSAPI" << "Failed to init krb5 context" << std::endl;
+ return code;
+ }
+
+ if ( !keytabFile.empty() ) {
+ std::string keytabStr( "FILE:" + keytabFile );
+ code = krb5_kt_resolve( context, keytabStr.c_str(), &keytab );
+ }
+ else {
+ code = krb5_kt_default( context, &keytab );
+ }
+
+ if ( code != 0 ) {
+ L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
+ return code;
+ }
+
+ // Extract the principal name from the keytab
+ krb5_kt_cursor cursor;
+ if ( ( code = krb5_kt_start_seq_get( context, keytab, &cursor ) ) != 0 ) {
+ L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
+ krb5_kt_close( context, keytab );
+ return code;
+ }
+
+ krb5_keytab_entry entry;
+ if ( ( code = krb5_kt_next_entry( context, keytab, &entry, &cursor ) ) == 0 ) {
+ code = krb5_copy_principal( context, entry.principal, &principal );
+ krb5_kt_free_entry( context, &entry );
+ }
+
+ krb5_kt_end_seq_get( context, keytab, &cursor );
+ if ( code != 0 ) {
+ L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
+ krb5_kt_close( context, keytab );
+ krb5_free_principal( context, principal );
+ return code;
+ }
+
+ // Locate the credentials cache file
+ if ( !cCacheFile.empty() ) {
+ std::string cCacheStr( "FILE:" + cCacheFile );
+ code = krb5_cc_resolve( context, cCacheStr.c_str(), &ccache );
+ }
+ else {
+ code = krb5_cc_default( context, &ccache );
+ }
+
+ if ( code != 0 ) {
+ L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
+ krb5_kt_close( context, keytab );
+ krb5_free_principal( context, principal );
+ return code;
+ }
+
+ // Initialize the credentials cache file
+ if ( ( code = krb5_cc_initialize( context, ccache, principal ) ) != 0 ) {
+ L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
+ krb5_kt_close( context, keytab );
+ krb5_free_principal( context, principal );
+ return code;
+ }
+
+ if ( ( code = krb5_get_init_creds_opt_alloc( context, &options ) ) != 0 ) {
+ L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
+ krb5_kt_close( context, keytab );
+ krb5_free_principal( context, principal );
+ return code;
+ }
+ krb5_get_init_creds_opt_set_default_flags( context, "pdns", NULL, options );
+
+ // And finally get the TGT!
+ code = krb5_get_init_creds_keytab( context, &credentials, principal, keytab, 0, NULL, options );
+ krb5_get_init_creds_opt_free( context, options );
+ krb5_kt_close( context, keytab );
+ krb5_free_principal( context, principal );
+
+ if ( code == 0 ) {
+ L<<Logger::Error << "LDAP GSSAPI" << "krb5 error: " << std::string( krb5_get_error_message( context, code ) ) << std::endl;
+ code = krb5_cc_store_cred( context, ccache, &credentials );
+ krb5_free_cred_contents( context, &credentials );
+ krb5_cc_close( context, ccache );
+ }
+
+ krb5_free_context( context );
+ return code;
}
class LdapAuthenticator
{
-public:
- virtual ~LdapAuthenticator() {}
- virtual bool authenticate( LDAP *connection ) = 0;
- virtual std::string getError() const = 0;
+ public:
+ virtual ~LdapAuthenticator() {}
+ virtual bool authenticate( LDAP *connection ) = 0;
+ virtual std::string getError() const = 0;
};
#endif // LDAPAUTHENTICATOR_HH
class LdapSimpleAuthenticator : public LdapAuthenticator
{
- std::string binddn;
- std::string bindpw;
- int timeout;
- std::string lastError;
-
- void fillLastError( LDAP *conn, int code );
-
-public:
- LdapSimpleAuthenticator( const std::string &dn, const std::string &pw, int timeout );
- virtual bool authenticate( LDAP *conn );
- virtual std::string getError() const;
+ std::string binddn;
+ std::string bindpw;
+ int timeout;
+ std::string lastError;
+
+ void fillLastError( LDAP *conn, int code );
+
+ public:
+ LdapSimpleAuthenticator( const std::string &dn, const std::string &pw, int timeout );
+ virtual bool authenticate( LDAP *conn );
+ virtual std::string getError() const;
};
class LdapGssapiAuthenticator : public LdapAuthenticator
{
- std::string keytabFile;
- std::string cCacheFile;
- int timeout;
- std::string lastError;
-
- struct SaslDefaults {
- std::string mech;
- std::string realm;
- std::string authcid;
- std::string authzid;
- };
-
- int attemptAuth( LDAP *conn );
- int updateTgt();
-
-public:
- LdapGssapiAuthenticator( const std::string &keytab, const std::string &credsCache, int timeout );
- virtual bool authenticate( LDAP *conn );
- virtual std::string getError() const;
+ std::string keytabFile;
+ std::string cCacheFile;
+ int timeout;
+ std::string lastError;
+
+ struct SaslDefaults {
+ std::string mech;
+ std::string realm;
+ std::string authcid;
+ std::string authzid;
+ };
+
+ int attemptAuth( LDAP *conn );
+ int updateTgt();
+
+ public:
+ LdapGssapiAuthenticator( const std::string &keytab, const std::string &credsCache, int timeout );
+ virtual bool authenticate( LDAP *conn );
+ virtual std::string getError() const;
};
#endif // LDAPAUTHENTICATOR_P_HH
LdapBackend::LdapBackend( const string &suffix )
{
- string hoststr;
- unsigned int i, idx;
- vector<string> hosts;
-
-
- try
- {
- m_msgid = 0;
- m_qname.clear();
- m_pldap = NULL;
- m_authenticator = NULL;
- m_ttl = 0;
- m_axfrqlen = 0;
- m_last_modified = 0;
- m_qlog = arg().mustDo( "query-logging" );
- m_default_ttl = arg().asNum( "default-ttl" );
- m_myname = "[LdapBackend]";
-
- setArgPrefix( "ldap" + suffix );
-
- m_getdn = false;
- m_reconnect_attempts = getArgAsNum( "reconnect-attempts" );
- m_list_fcnt = &LdapBackend::list_simple;
- m_lookup_fcnt = &LdapBackend::lookup_simple;
- m_prepare_fcnt = &LdapBackend::prepare_simple;
-
- if( getArg( "method" ) == "tree" )
- {
- m_lookup_fcnt = &LdapBackend::lookup_tree;
- }
-
- if( getArg( "method" ) == "strict" || mustDo( "disable-ptrrecord" ) )
- {
- m_list_fcnt = &LdapBackend::list_strict;
- m_lookup_fcnt = &LdapBackend::lookup_strict;
- m_prepare_fcnt = &LdapBackend::prepare_strict;
- }
-
- stringtok( hosts, getArg( "host" ), ", " );
- idx = ldap_host_index++ % hosts.size();
- hoststr = hosts[idx];
-
- for( i = 1; i < hosts.size(); i++ )
- {
- hoststr += " " + hosts[ ( idx + i ) % hosts.size() ];
- }
-
- L << Logger::Info << m_myname << " LDAP servers = " << hoststr << endl;
-
- m_pldap = new PowerLDAP( hoststr.c_str(), LDAP_PORT, mustDo( "starttls" ) );
- m_pldap->setOption( LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS );
-
- string bindmethod = getArg( "bindmethod" );
- if ( bindmethod == "gssapi" ) {
- setenv( "KRB5CCNAME", getArg( "krb5-ccache" ).c_str(), 1 );
- m_authenticator = new LdapGssapiAuthenticator( getArg( "krb5-keytab" ), getArg( "krb5-ccache" ), getArgAsNum( "timeout" ) );
- }
- else {
- m_authenticator = new LdapSimpleAuthenticator( getArg( "binddn" ), getArg( "secret" ), getArgAsNum( "timeout" ) );
- }
- m_pldap->bind( m_authenticator );
-
- L << Logger::Notice << m_myname << " Ldap connection succeeded" << endl;
- return;
- }
- catch( LDAPTimeout < )
- {
- L << Logger::Error << m_myname << " Ldap connection to server failed because of timeout" << endl;
- }
- catch( LDAPException &le )
- {
- L << Logger::Error << m_myname << " Ldap connection to server failed: " << le.what() << endl;
- }
- catch( std::exception &e )
- {
- L << Logger::Error << m_myname << " Caught STL exception: " << e.what() << endl;
- }
-
- if( m_pldap != NULL ) { delete( m_pldap ); }
- throw( PDNSException( "Unable to connect to ldap server" ) );
+ string hoststr;
+ unsigned int i, idx;
+ vector<string> hosts;
+
+
+ try
+ {
+ m_msgid = 0;
+ m_qname.clear();
+ m_pldap = NULL;
+ m_authenticator = NULL;
+ m_ttl = 0;
+ m_axfrqlen = 0;
+ m_last_modified = 0;
+ m_qlog = arg().mustDo( "query-logging" );
+ m_default_ttl = arg().asNum( "default-ttl" );
+ m_myname = "[LdapBackend]";
+
+ setArgPrefix( "ldap" + suffix );
+
+ m_getdn = false;
+ m_reconnect_attempts = getArgAsNum( "reconnect-attempts" );
+ m_list_fcnt = &LdapBackend::list_simple;
+ m_lookup_fcnt = &LdapBackend::lookup_simple;
+ m_prepare_fcnt = &LdapBackend::prepare_simple;
+
+ if( getArg( "method" ) == "tree" )
+ {
+ m_lookup_fcnt = &LdapBackend::lookup_tree;
+ }
+
+ if( getArg( "method" ) == "strict" || mustDo( "disable-ptrrecord" ) )
+ {
+ m_list_fcnt = &LdapBackend::list_strict;
+ m_lookup_fcnt = &LdapBackend::lookup_strict;
+ m_prepare_fcnt = &LdapBackend::prepare_strict;
+ }
+
+ stringtok( hosts, getArg( "host" ), ", " );
+ idx = ldap_host_index++ % hosts.size();
+ hoststr = hosts[idx];
+
+ for( i = 1; i < hosts.size(); i++ )
+ {
+ hoststr += " " + hosts[ ( idx + i ) % hosts.size() ];
+ }
+
+ L << Logger::Info << m_myname << " LDAP servers = " << hoststr << endl;
+
+ m_pldap = new PowerLDAP( hoststr.c_str(), LDAP_PORT, mustDo( "starttls" ) );
+ m_pldap->setOption( LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS );
+
+ string bindmethod = getArg( "bindmethod" );
+ if ( bindmethod == "gssapi" ) {
+ setenv( "KRB5CCNAME", getArg( "krb5-ccache" ).c_str(), 1 );
+ m_authenticator = new LdapGssapiAuthenticator( getArg( "krb5-keytab" ), getArg( "krb5-ccache" ), getArgAsNum( "timeout" ) );
+ }
+ else {
+ m_authenticator = new LdapSimpleAuthenticator( getArg( "binddn" ), getArg( "secret" ), getArgAsNum( "timeout" ) );
+ }
+ m_pldap->bind( m_authenticator );
+
+ L << Logger::Notice << m_myname << " Ldap connection succeeded" << endl;
+ return;
+ }
+ catch( LDAPTimeout < )
+ {
+ L << Logger::Error << m_myname << " Ldap connection to server failed because of timeout" << endl;
+ }
+ catch( LDAPException &le )
+ {
+ L << Logger::Error << m_myname << " Ldap connection to server failed: " << le.what() << endl;
+ }
+ catch( std::exception &e )
+ {
+ L << Logger::Error << m_myname << " Caught STL exception: " << e.what() << endl;
+ }
+
+ if( m_pldap != NULL ) { delete( m_pldap ); }
+ throw( PDNSException( "Unable to connect to ldap server" ) );
}
LdapBackend::~LdapBackend()
{
- delete( m_pldap );
- delete( m_authenticator );
- L << Logger::Notice << m_myname << " Ldap connection closed" << endl;
+ delete( m_pldap );
+ delete( m_authenticator );
+ L << Logger::Notice << m_myname << " Ldap connection closed" << endl;
}
bool LdapBackend::reconnect()
{
- int attempts = m_reconnect_attempts;
- bool connected = false;
- while ( !connected && attempts > 0 ) {
- L << Logger::Debug << m_myname << " Reconnection attempts left: " << attempts << endl;
- connected = m_pldap->connect();
- if ( !connected )
- Utility::usleep( 250 );
- --attempts;
- }
-
- if ( connected )
- m_pldap->bind( m_authenticator );
-
- return connected;
+ int attempts = m_reconnect_attempts;
+ bool connected = false;
+ while ( !connected && attempts > 0 ) {
+ L << Logger::Debug << m_myname << " Reconnection attempts left: " << attempts << endl;
+ connected = m_pldap->connect();
+ if ( !connected )
+ Utility::usleep( 250 );
+ --attempts;
+ }
+
+ if ( connected )
+ m_pldap->bind( m_authenticator );
+
+ return connected;
}
bool LdapBackend::list( const DNSName& target, int domain_id, bool include_disabled )
{
- try
- {
- m_qname = target;
- m_axfrqlen = target.toStringRootDot().length();
- m_adomain = m_adomains.end(); // skip loops in get() first time
-
- return (this->*m_list_fcnt)( target, domain_id );
- }
- catch( LDAPTimeout < )
- {
- L << Logger::Warning << m_myname << " Unable to get zone " << target << " from LDAP directory: " << lt.what() << endl;
- throw( DBException( "LDAP server timeout" ) );
- }
- catch( LDAPNoConnection &lnc )
- {
- L << Logger::Warning << m_myname << " Connection to LDAP lost, trying to reconnect" << endl;
- if ( reconnect() )
- this->list( target, domain_id );
- else
- throw PDNSException( "Failed to reconnect to LDAP server" );
- }
- catch( LDAPException &le )
- {
- L << Logger::Error << m_myname << " Unable to get zone " << target << " from LDAP directory: " << le.what() << endl;
- throw( PDNSException( "LDAP server unreachable" ) ); // try to reconnect to another server
- }
- catch( std::exception &e )
- {
- L << Logger::Error << m_myname << " Caught STL exception for target " << target << ": " << e.what() << endl;
- throw( DBException( "STL exception" ) );
- }
-
- return false;
+ try
+ {
+ m_qname = target;
+ m_axfrqlen = target.toStringRootDot().length();
+ m_adomain = m_adomains.end(); // skip loops in get() first time
+
+ return (this->*m_list_fcnt)( target, domain_id );
+ }
+ catch( LDAPTimeout < )
+ {
+ L << Logger::Warning << m_myname << " Unable to get zone " << target << " from LDAP directory: " << lt.what() << endl;
+ throw( DBException( "LDAP server timeout" ) );
+ }
+ catch( LDAPNoConnection &lnc )
+ {
+ L << Logger::Warning << m_myname << " Connection to LDAP lost, trying to reconnect" << endl;
+ if ( reconnect() )
+ this->list( target, domain_id );
+ else
+ throw PDNSException( "Failed to reconnect to LDAP server" );
+ }
+ catch( LDAPException &le )
+ {
+ L << Logger::Error << m_myname << " Unable to get zone " << target << " from LDAP directory: " << le.what() << endl;
+ throw( PDNSException( "LDAP server unreachable" ) ); // try to reconnect to another server
+ }
+ catch( std::exception &e )
+ {
+ L << Logger::Error << m_myname << " Caught STL exception for target " << target << ": " << e.what() << endl;
+ throw( DBException( "STL exception" ) );
+ }
+
+ return false;
}
inline bool LdapBackend::list_simple( const DNSName& target, int domain_id )
{
- string dn;
- string filter;
- string qesc;
-
-
- dn = getArg( "basedn" );
- qesc = toLower( m_pldap->escape( target.toStringRootDot() ) );
-
- // search for SOARecord of target
- filter = strbind( ":target:", "&(associatedDomain=" + qesc + ")(sOARecord=*)", getArg( "filter-axfr" ) );
- m_msgid = m_pldap->search( dn, LDAP_SCOPE_SUBTREE, filter, (const char**) ldap_attrany );
- m_pldap->getSearchEntry( m_msgid, m_result, true );
-
- if( m_result.count( "dn" ) && !m_result["dn"].empty() )
- {
- if( !mustDo( "basedn-axfr-override" ) )
- {
- dn = m_result["dn"][0];
- }
- m_result.erase( "dn" );
- }
-
- prepare();
- filter = strbind( ":target:", "associatedDomain=*." + qesc, getArg( "filter-axfr" ) );
- DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << dn << ", filter: " << filter << endl );
- m_msgid = m_pldap->search( dn, LDAP_SCOPE_SUBTREE, filter, (const char**) ldap_attrany );
-
- return true;
+ string dn;
+ string filter;
+ string qesc;
+
+
+ dn = getArg( "basedn" );
+ qesc = toLower( m_pldap->escape( target.toStringRootDot() ) );
+
+ // search for SOARecord of target
+ filter = strbind( ":target:", "&(associatedDomain=" + qesc + ")(sOARecord=*)", getArg( "filter-axfr" ) );
+ m_msgid = m_pldap->search( dn, LDAP_SCOPE_SUBTREE, filter, (const char**) ldap_attrany );
+ m_pldap->getSearchEntry( m_msgid, m_result, true );
+
+ if( m_result.count( "dn" ) && !m_result["dn"].empty() )
+ {
+ if( !mustDo( "basedn-axfr-override" ) )
+ {
+ dn = m_result["dn"][0];
+ }
+ m_result.erase( "dn" );
+ }
+
+ prepare();
+ filter = strbind( ":target:", "associatedDomain=*." + qesc, getArg( "filter-axfr" ) );
+ DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << dn << ", filter: " << filter << endl );
+ m_msgid = m_pldap->search( dn, LDAP_SCOPE_SUBTREE, filter, (const char**) ldap_attrany );
+
+ return true;
}
inline bool LdapBackend::list_strict( const DNSName& target, int domain_id )
{
- if( target.isPartOf(DNSName("in-addr.arpa")) || target.isPartOf(DNSName(".ip6.arpa")) )
- {
- L << Logger::Warning << m_myname << " Request for reverse zone AXFR, but this is not supported in strict mode" << endl;
- return false; // AXFR isn't supported in strict mode. Use simple mode and additional PTR records
- }
+ if( target.isPartOf(DNSName("in-addr.arpa")) || target.isPartOf(DNSName(".ip6.arpa")) )
+ {
+ L << Logger::Warning << m_myname << " Request for reverse zone AXFR, but this is not supported in strict mode" << endl;
+ return false; // AXFR isn't supported in strict mode. Use simple mode and additional PTR records
+ }
- return list_simple( target, domain_id );
+ return list_simple( target, domain_id );
}
void LdapBackend::lookup( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid )
{
- try
- {
- m_axfrqlen = 0;
- m_qname = qname;
- m_adomain = m_adomains.end(); // skip loops in get() first time
- m_qtype = qtype;
-
- if( m_qlog ) { L.log( "Query: '" + qname.toStringRootDot() + "|" + qtype.getName() + "'", Logger::Error ); }
- (this->*m_lookup_fcnt)( qtype, qname, dnspkt, zoneid );
- }
- catch( LDAPTimeout < )
- {
- L << Logger::Warning << m_myname << " Unable to search LDAP directory: " << lt.what() << endl;
- throw( DBException( "LDAP server timeout" ) );
- }
- catch( LDAPNoConnection &lnc )
- {
- L << Logger::Warning << m_myname << " Connection to LDAP lost, trying to reconnect" << endl;
- if ( reconnect() )
- this->lookup( qtype, qname, dnspkt, zoneid );
- else
- throw PDNSException( "Failed to reconnect to LDAP server" );
- }
- catch( LDAPException &le )
- {
- L << Logger::Error << m_myname << " Unable to search LDAP directory: " << le.what() << endl;
- throw( PDNSException( "LDAP server unreachable" ) ); // try to reconnect to another server
- }
- catch( std::exception &e )
- {
- L << Logger::Error << m_myname << " Caught STL exception for qname " << qname << ": " << e.what() << endl;
- throw( DBException( "STL exception" ) );
- }
+ try
+ {
+ m_axfrqlen = 0;
+ m_qname = qname;
+ m_adomain = m_adomains.end(); // skip loops in get() first time
+ m_qtype = qtype;
+
+ if( m_qlog ) { L.log( "Query: '" + qname.toStringRootDot() + "|" + qtype.getName() + "'", Logger::Error ); }
+ (this->*m_lookup_fcnt)( qtype, qname, dnspkt, zoneid );
+ }
+ catch( LDAPTimeout < )
+ {
+ L << Logger::Warning << m_myname << " Unable to search LDAP directory: " << lt.what() << endl;
+ throw( DBException( "LDAP server timeout" ) );
+ }
+ catch( LDAPNoConnection &lnc )
+ {
+ L << Logger::Warning << m_myname << " Connection to LDAP lost, trying to reconnect" << endl;
+ if ( reconnect() )
+ this->lookup( qtype, qname, dnspkt, zoneid );
+ else
+ throw PDNSException( "Failed to reconnect to LDAP server" );
+ }
+ catch( LDAPException &le )
+ {
+ L << Logger::Error << m_myname << " Unable to search LDAP directory: " << le.what() << endl;
+ throw( PDNSException( "LDAP server unreachable" ) ); // try to reconnect to another server
+ }
+ catch( std::exception &e )
+ {
+ L << Logger::Error << m_myname << " Caught STL exception for qname " << qname << ": " << e.what() << endl;
+ throw( DBException( "STL exception" ) );
+ }
}
void LdapBackend::lookup_simple( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid )
{
- string filter, attr, qesc;
- const char** attributes = ldap_attrany + 1; // skip associatedDomain
- const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", NULL };
+ string filter, attr, qesc;
+ const char** attributes = ldap_attrany + 1; // skip associatedDomain
+ const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", NULL };
- qesc = toLower( m_pldap->escape( qname.toStringRootDot() ) );
- filter = "associatedDomain=" + qesc;
+ qesc = toLower( m_pldap->escape( qname.toStringRootDot() ) );
+ filter = "associatedDomain=" + qesc;
- if( qtype.getCode() != QType::ANY )
- {
- attr = qtype.getName() + "Record";
- filter = "&(" + filter + ")(" + attr + "=*)";
- attronly[0] = attr.c_str();
- attributes = attronly;
- }
+ if( qtype.getCode() != QType::ANY )
+ {
+ attr = qtype.getName() + "Record";
+ filter = "&(" + filter + ")(" + attr + "=*)";
+ attronly[0] = attr.c_str();
+ attributes = attronly;
+ }
- filter = strbind( ":target:", filter, getArg( "filter-lookup" ) );
+ filter = strbind( ":target:", filter, getArg( "filter-lookup" ) );
- DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl );
- m_msgid = m_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attributes );
+ DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl );
+ m_msgid = m_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attributes );
}
void LdapBackend::lookup_strict( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid )
{
- int len;
- vector<string> parts;
- string filter, attr, qesc;
- const char** attributes = ldap_attrany + 1; // skip associatedDomain
- const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", NULL };
-
-
- qesc = toLower( m_pldap->escape( qname.toStringRootDot() ) );
- stringtok( parts, qesc, "." );
- len = qesc.length();
-
- if( parts.size() == 6 && len > 13 && qesc.substr( len - 13, 13 ) == ".in-addr.arpa" ) // IPv4 reverse lookups
- {
- filter = "aRecord=" + ptr2ip4( parts );
- attronly[0] = "associatedDomain";
- attributes = attronly;
- }
- else if( parts.size() == 34 && len > 9 && ( qesc.substr( len - 9, 9 ) == ".ip6.arpa" ) ) // IPv6 reverse lookups
- {
- filter = "aAAARecord=" + ptr2ip6( parts );
- attronly[0] = "associatedDomain";
- attributes = attronly;
- }
- else // IPv4 and IPv6 lookups
- {
- filter = "associatedDomain=" + qesc;
- if( qtype.getCode() != QType::ANY )
- {
- attr = qtype.getName() + "Record";
- filter = "&(" + filter + ")(" + attr + "=*)";
- attronly[0] = attr.c_str();
- attributes = attronly;
- }
- }
-
- filter = strbind( ":target:", filter, getArg( "filter-lookup" ) );
-
- DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl );
- m_msgid = m_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attributes );
+ int len;
+ vector<string> parts;
+ string filter, attr, qesc;
+ const char** attributes = ldap_attrany + 1; // skip associatedDomain
+ const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", NULL };
+
+
+ qesc = toLower( m_pldap->escape( qname.toStringRootDot() ) );
+ stringtok( parts, qesc, "." );
+ len = qesc.length();
+
+ if( parts.size() == 6 && len > 13 && qesc.substr( len - 13, 13 ) == ".in-addr.arpa" ) // IPv4 reverse lookups
+ {
+ filter = "aRecord=" + ptr2ip4( parts );
+ attronly[0] = "associatedDomain";
+ attributes = attronly;
+ }
+ else if( parts.size() == 34 && len > 9 && ( qesc.substr( len - 9, 9 ) == ".ip6.arpa" ) ) // IPv6 reverse lookups
+ {
+ filter = "aAAARecord=" + ptr2ip6( parts );
+ attronly[0] = "associatedDomain";
+ attributes = attronly;
+ }
+ else // IPv4 and IPv6 lookups
+ {
+ filter = "associatedDomain=" + qesc;
+ if( qtype.getCode() != QType::ANY )
+ {
+ attr = qtype.getName() + "Record";
+ filter = "&(" + filter + ")(" + attr + "=*)";
+ attronly[0] = attr.c_str();
+ attributes = attronly;
+ }
+ }
+
+ filter = strbind( ":target:", filter, getArg( "filter-lookup" ) );
+
+ DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl );
+ m_msgid = m_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attributes );
}
void LdapBackend::lookup_tree( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid )
{
- string filter, attr, qesc, dn;
- const char** attributes = ldap_attrany + 1; // skip associatedDomain
- const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", NULL };
- vector<string> parts;
+ string filter, attr, qesc, dn;
+ const char** attributes = ldap_attrany + 1; // skip associatedDomain
+ const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", NULL };
+ vector<string> parts;
- qesc = toLower( m_pldap->escape( qname.toStringRootDot() ) );
- filter = "associatedDomain=" + qesc;
+ qesc = toLower( m_pldap->escape( qname.toStringRootDot() ) );
+ filter = "associatedDomain=" + qesc;
- if( qtype.getCode() != QType::ANY )
- {
- attr = qtype.getName() + "Record";
- filter = "&(" + filter + ")(" + attr + "=*)";
- attronly[0] = attr.c_str();
- attributes = attronly;
- }
+ if( qtype.getCode() != QType::ANY )
+ {
+ attr = qtype.getName() + "Record";
+ filter = "&(" + filter + ")(" + attr + "=*)";
+ attronly[0] = attr.c_str();
+ attributes = attronly;
+ }
- filter = strbind( ":target:", filter, getArg( "filter-lookup" ) );
+ filter = strbind( ":target:", filter, getArg( "filter-lookup" ) );
- stringtok( parts, toLower( qname.toString() ), "." );
- for(auto i = parts.crbegin(); i != parts.crend(); i++ )
- {
- dn = "dc=" + *i + "," + dn;
- }
+ stringtok( parts, toLower( qname.toString() ), "." );
+ for(auto i = parts.crbegin(); i != parts.crend(); i++ )
+ {
+ dn = "dc=" + *i + "," + dn;
+ }
- DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << dn + getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl );
- m_msgid = m_pldap->search( dn + getArg( "basedn" ), LDAP_SCOPE_BASE, filter, attributes );
+ DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << dn + getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl );
+ m_msgid = m_pldap->search( dn + getArg( "basedn" ), LDAP_SCOPE_BASE, filter, attributes );
}
inline bool LdapBackend::prepare()
{
- m_adomains.clear();
- m_ttl = m_default_ttl;
- m_last_modified = 0;
-
- if( m_result.count( "dNSTTL" ) && !m_result["dNSTTL"].empty() )
- {
- char* endptr;
-
- m_ttl = (uint32_t) strtol( m_result["dNSTTL"][0].c_str(), &endptr, 10 );
- if( *endptr != '\0' )
- {
- L << Logger::Warning << m_myname << " Invalid time to live for " << m_qname << ": " << m_result["dNSTTL"][0] << endl;
- m_ttl = m_default_ttl;
- }
- m_result.erase( "dNSTTL" );
- }
-
- if( m_result.count( "modifyTimestamp" ) && !m_result["modifyTimestamp"].empty() )
- {
- if( ( m_last_modified = str2tstamp( m_result["modifyTimestamp"][0] ) ) == 0 )
- {
- L << Logger::Warning << m_myname << " Invalid modifyTimestamp for " << m_qname << ": " << m_result["modifyTimestamp"][0] << endl;
- }
- m_result.erase( "modifyTimestamp" );
- }
-
- if( !(this->*m_prepare_fcnt)() )
- {
- return false;
- }
-
- m_adomain = m_adomains.begin();
- m_attribute = m_result.begin();
- m_value = m_attribute->second.begin();
-
- return true;
+ m_adomains.clear();
+ m_ttl = m_default_ttl;
+ m_last_modified = 0;
+
+ if( m_result.count( "dNSTTL" ) && !m_result["dNSTTL"].empty() )
+ {
+ char* endptr;
+
+ m_ttl = (uint32_t) strtol( m_result["dNSTTL"][0].c_str(), &endptr, 10 );
+ if( *endptr != '\0' )
+ {
+ L << Logger::Warning << m_myname << " Invalid time to live for " << m_qname << ": " << m_result["dNSTTL"][0] << endl;
+ m_ttl = m_default_ttl;
+ }
+ m_result.erase( "dNSTTL" );
+ }
+
+ if( m_result.count( "modifyTimestamp" ) && !m_result["modifyTimestamp"].empty() )
+ {
+ if( ( m_last_modified = str2tstamp( m_result["modifyTimestamp"][0] ) ) == 0 )
+ {
+ L << Logger::Warning << m_myname << " Invalid modifyTimestamp for " << m_qname << ": " << m_result["modifyTimestamp"][0] << endl;
+ }
+ m_result.erase( "modifyTimestamp" );
+ }
+
+ if( !(this->*m_prepare_fcnt)() )
+ {
+ return false;
+ }
+
+ m_adomain = m_adomains.begin();
+ m_attribute = m_result.begin();
+ m_value = m_attribute->second.begin();
+
+ return true;
}
inline bool LdapBackend::prepare_simple()
{
- if( !m_axfrqlen ) // request was a normal lookup()
- {
- m_adomains.push_back( m_qname );
- }
- else // request was a list() for AXFR
- {
- if( m_result.count( "associatedDomain" ) )
- {
- for(auto i = m_result["associatedDomain"].begin(); i != m_result["associatedDomain"].end(); i++ ) {
- if( i->size() >= m_axfrqlen && i->substr( i->size() - m_axfrqlen, m_axfrqlen ) == m_qname.toStringRootDot() /* ugh */ ) {
- m_adomains.push_back( DNSName(*i) );
- }
- }
- m_result.erase( "associatedDomain" );
- }
- }
-
- return true;
+ if( !m_axfrqlen ) // request was a normal lookup()
+ {
+ m_adomains.push_back( m_qname );
+ }
+ else // request was a list() for AXFR
+ {
+ if( m_result.count( "associatedDomain" ) )
+ {
+ for(auto i = m_result["associatedDomain"].begin(); i != m_result["associatedDomain"].end(); i++ ) {
+ if( i->size() >= m_axfrqlen && i->substr( i->size() - m_axfrqlen, m_axfrqlen ) == m_qname.toStringRootDot() /* ugh */ ) {
+ m_adomains.push_back( DNSName(*i) );
+ }
+ }
+ m_result.erase( "associatedDomain" );
+ }
+ }
+
+ return true;
}
inline bool LdapBackend::prepare_strict()
{
- if( !m_axfrqlen ) // request was a normal lookup()
- {
- m_adomains.push_back( m_qname );
- if( m_result.count( "associatedDomain" ) )
- {
- m_result["PTRRecord"] = m_result["associatedDomain"];
- m_result.erase( "associatedDomain" );
- }
- }
- else // request was a list() for AXFR
- {
- if( m_result.count( "associatedDomain" ) )
- {
- for(auto i = m_result["associatedDomain"].begin(); i != m_result["associatedDomain"].end(); i++ ) {
- if( i->size() >= m_axfrqlen && i->substr( i->size() - m_axfrqlen, m_axfrqlen ) == m_qname.toStringRootDot() /* ugh */ ) {
- m_adomains.push_back( DNSName(*i) );
- }
- }
- m_result.erase( "associatedDomain" );
- }
- }
-
- return true;
+ if( !m_axfrqlen ) // request was a normal lookup()
+ {
+ m_adomains.push_back( m_qname );
+ if( m_result.count( "associatedDomain" ) )
+ {
+ m_result["PTRRecord"] = m_result["associatedDomain"];
+ m_result.erase( "associatedDomain" );
+ }
+ }
+ else // request was a list() for AXFR
+ {
+ if( m_result.count( "associatedDomain" ) )
+ {
+ for(auto i = m_result["associatedDomain"].begin(); i != m_result["associatedDomain"].end(); i++ ) {
+ if( i->size() >= m_axfrqlen && i->substr( i->size() - m_axfrqlen, m_axfrqlen ) == m_qname.toStringRootDot() /* ugh */ ) {
+ m_adomains.push_back( DNSName(*i) );
+ }
+ }
+ m_result.erase( "associatedDomain" );
+ }
+ }
+
+ return true;
}
bool LdapBackend::get( DNSResourceRecord &rr )
{
- QType qt;
- vector<string> parts;
- string attrname, qstr;
-
-
- try
- {
- do
- {
- while( m_adomain != m_adomains.end() )
- {
- while( m_attribute != m_result.end() )
- {
- attrname = m_attribute->first;
- qstr = attrname.substr( 0, attrname.length() - 6 ); // extract qtype string from ldap attribute name
- qt = const_cast<char*>(toUpper( qstr ).c_str());
-
- while( m_value != m_attribute->second.end() )
- {
- if(m_qtype != qt && m_qtype != QType::ANY) {
- m_value++;
- continue;
- }
-
- rr.qtype = qt;
- rr.qname = *m_adomain;
- rr.ttl = m_ttl;
- rr.last_modified = m_last_modified;
- rr.content = *m_value;
- m_value++;
-
- DLOG( L << Logger::Debug << m_myname << " Record = qname: " << rr.qname << ", qtype: " << (rr.qtype).getName() << ", ttl: " << rr.ttl << ", content: " << rr.content << endl );
- return true;
- }
-
- m_attribute++;
- m_value = m_attribute->second.begin();
- }
- m_adomain++;
- m_attribute = m_result.begin();
- m_value = m_attribute->second.begin();
- }
- }
- while( m_pldap->getSearchEntry( m_msgid, m_result, m_getdn ) && prepare() );
-
- }
- catch( LDAPTimeout < )
- {
- L << Logger::Warning << m_myname << " Search failed: " << lt.what() << endl;
- throw( DBException( "LDAP server timeout" ) );
- }
- catch( LDAPException &le )
- {
- L << Logger::Error << m_myname << " Search failed: " << le.what() << endl;
- throw( PDNSException( "LDAP server unreachable" ) ); // try to reconnect to another server
- }
- catch( std::exception &e )
- {
- L << Logger::Error << m_myname << " Caught STL exception for " << m_qname << ": " << e.what() << endl;
- throw( DBException( "STL exception" ) );
- }
-
- return false;
+ QType qt;
+ vector<string> parts;
+ string attrname, qstr;
+
+
+ try
+ {
+ do
+ {
+ while( m_adomain != m_adomains.end() )
+ {
+ while( m_attribute != m_result.end() )
+ {
+ attrname = m_attribute->first;
+ qstr = attrname.substr( 0, attrname.length() - 6 ); // extract qtype string from ldap attribute name
+ qt = const_cast<char*>(toUpper( qstr ).c_str());
+
+ while( m_value != m_attribute->second.end() )
+ {
+ if(m_qtype != qt && m_qtype != QType::ANY) {
+ m_value++;
+ continue;
+ }
+
+
+ rr.qtype = qt;
+ rr.qname = *m_adomain;
+ rr.ttl = m_ttl;
+ rr.last_modified = m_last_modified;
+ rr.content = *m_value;
+ m_value++;
+
+ DLOG( L << Logger::Debug << m_myname << " Record = qname: " << rr.qname << ", qtype: " << (rr.qtype).getName() << ", ttl: " << rr.ttl << ", content: " << rr.content << endl );
+ return true;
+ }
+
+ m_attribute++;
+ m_value = m_attribute->second.begin();
+ }
+ m_adomain++;
+ m_attribute = m_result.begin();
+ m_value = m_attribute->second.begin();
+ }
+ }
+ while( m_pldap->getSearchEntry( m_msgid, m_result, m_getdn ) && prepare() );
+
+ }
+ catch( LDAPTimeout < )
+ {
+ L << Logger::Warning << m_myname << " Search failed: " << lt.what() << endl;
+ throw( DBException( "LDAP server timeout" ) );
+ }
+ catch( LDAPException &le )
+ {
+ L << Logger::Error << m_myname << " Search failed: " << le.what() << endl;
+ throw( PDNSException( "LDAP server unreachable" ) ); // try to reconnect to another server
+ }
+ catch( std::exception &e )
+ {
+ L << Logger::Error << m_myname << " Caught STL exception for " << m_qname << ": " << e.what() << endl;
+ throw( DBException( "STL exception" ) );
+ }
+
+ return false;
}
bool LdapBackend::getDomainInfo( const string& domain, DomainInfo& di )
{
- string filter;
- SOAData sd;
- const char* attronly[] = { "sOARecord", NULL };
+ string filter;
+ SOAData sd;
+ const char* attronly[] = { "sOARecord", NULL };
- // search for SOARecord of domain
- filter = "(&(associatedDomain=" + toLower( m_pldap->escape( domain ) ) + ")(SOARecord=*))";
- m_msgid = m_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attronly );
- m_pldap->getSearchEntry( m_msgid, m_result );
+ // search for SOARecord of domain
+ filter = "(&(associatedDomain=" + toLower( m_pldap->escape( domain ) ) + ")(SOARecord=*))";
+ m_msgid = m_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attronly );
+ m_pldap->getSearchEntry( m_msgid, m_result );
- if( m_result.count( "sOARecord" ) && !m_result["sOARecord"].empty() )
- {
- sd.serial = 0;
- fillSOAData( m_result["sOARecord"][0], sd );
+ if( m_result.count( "sOARecord" ) && !m_result["sOARecord"].empty() )
+ {
+ sd.serial = 0;
+ fillSOAData( m_result["sOARecord"][0], sd );
- di.id = 0;
- di.serial = sd.serial;
- di.zone = DNSName(domain);
- di.last_check = 0;
- di.backend = this;
- di.kind = DomainInfo::Master;
+ di.id = 0;
+ di.serial = sd.serial;
+ di.zone = DNSName(domain);
+ di.last_check = 0;
+ di.backend = this;
+ di.kind = DomainInfo::Master;
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
class LdapFactory : public BackendFactory
{
-
-public:
-
- LdapFactory() : BackendFactory( "ldap" ) {}
-
-
- void declareArguments( const string &suffix="" )
- {
- declare( suffix, "host", "One or more LDAP server with ports or LDAP URIs (separated by spaces)","ldap://127.0.0.1:389/" );
- declare( suffix, "starttls", "Use TLS to encrypt connection (unused for LDAP URIs)", "no" );
- declare( suffix, "basedn", "Search root in ldap tree (must be set)","" );
- declare( suffix, "basedn-axfr-override", "Override base dn for AXFR subtree search", "no" );
- declare( suffix, "bindmethod", "Bind method to use (simple or gssapi)", "simple" );
- declare( suffix, "binddn", "User dn for non anonymous binds","" );
- declare( suffix, "secret", "User password for non anonymous binds", "" );
- declare( suffix, "krb5-keytab", "The keytab to use for GSSAPI authentication", "" );
- declare( suffix, "krb5-ccache", "The credentials cache used for GSSAPI authentication", "" );
- declare( suffix, "timeout", "Seconds before connecting to server fails", "5" );
- declare( suffix, "method", "How to search entries (simple, strict or tree)", "simple" );
- declare( suffix, "filter-axfr", "LDAP filter for limiting AXFR results", "(:target:)" );
- declare( suffix, "filter-lookup", "LDAP filter for limiting IP or name lookups", "(:target:)" );
- declare( suffix, "disable-ptrrecord", "Deprecated, use ldap-method=strict instead", "no" );
- declare( suffix, "reconnect-attempts", "Number of attempts to re-establish a lost LDAP connection", "5" );
- }
-
-
- DNSBackend* make( const string &suffix="" )
- {
- return new LdapBackend( suffix );
- }
+ public:
+
+ LdapFactory() : BackendFactory( "ldap" ) {}
+
+ void declareArguments( const string &suffix="" )
+ {
+ declare( suffix, "host", "One or more LDAP server with ports or LDAP URIs (separated by spaces)","ldap://127.0.0.1:389/" );
+ declare( suffix, "starttls", "Use TLS to encrypt connection (unused for LDAP URIs)", "no" );
+ declare( suffix, "basedn", "Search root in ldap tree (must be set)","" );
+ declare( suffix, "basedn-axfr-override", "Override base dn for AXFR subtree search", "no" );
+ declare( suffix, "bindmethod", "Bind method to use (simple or gssapi)", "simple" );
+ declare( suffix, "binddn", "User dn for non anonymous binds","" );
+ declare( suffix, "secret", "User password for non anonymous binds", "" );
+ declare( suffix, "krb5-keytab", "The keytab to use for GSSAPI authentication", "" );
+ declare( suffix, "krb5-ccache", "The credentials cache used for GSSAPI authentication", "" );
+ declare( suffix, "timeout", "Seconds before connecting to server fails", "5" );
+ declare( suffix, "method", "How to search entries (simple, strict or tree)", "simple" );
+ declare( suffix, "filter-axfr", "LDAP filter for limiting AXFR results", "(:target:)" );
+ declare( suffix, "filter-lookup", "LDAP filter for limiting IP or name lookups", "(:target:)" );
+ declare( suffix, "disable-ptrrecord", "Deprecated, use ldap-method=strict instead", "no" );
+ declare( suffix, "reconnect-attempts", "Number of attempts to re-establish a lost LDAP connection", "5" );
+ }
+
+
+ DNSBackend* make( const string &suffix="" )
+ {
+ return new LdapBackend( suffix );
+ }
};
class LdapLoader
{
- LdapFactory factory;
+ LdapFactory factory;
-public:
+ public:
- LdapLoader()
- {
- BackendMakers().report( &factory );
- L << Logger::Info << "[ldapbackend] This is the ldap backend version " VERSION
+ LdapLoader()
+ {
+ BackendMakers().report( &factory );
+ L << Logger::Info << "[ldapbackend] This is the ldap backend version " VERSION
#ifndef REPRODUCIBLE
- << " (" __DATE__ " " __TIME__ ")"
+ << " (" __DATE__ " " __TIME__ ")"
#endif
- << " reporting" << endl;
- }
+ << " reporting" << endl;
+ }
};
*/
static const char* ldap_attrany[] = {
- "associatedDomain",
- "dNSTTL",
- "aRecord",
- "nSRecord",
- "cNAMERecord",
- "sOARecord",
- "pTRRecord",
- "hInfoRecord",
- "mXRecord",
- "tXTRecord",
- "rPRecord",
- "aFSDBRecord",
-// "SigRecord",
- "KeyRecord",
-// "gPosRecord",
- "aAAARecord",
- "lOCRecord",
- "sRVRecord",
- "nAPTRRecord",
- "kXRecord",
- "certRecord",
-// "a6Record",
-// "dNameRecord",
-// "aPLRecord",
- "dSRecord",
- "sSHFPRecord",
- "iPSecKeyRecord",
- "rRSIGRecord",
- "nSECRecord",
- "dNSKeyRecord",
- "dHCIDRecord",
- "sPFRecord",
- "TYPE65534Record",
- "EUI48Record",
- "EUI64Record",
- "TYPE65226Record",
- "modifyTimestamp",
- NULL
+ "associatedDomain",
+ "dNSTTL",
+ "aRecord",
+ "nSRecord",
+ "cNAMERecord",
+ "sOARecord",
+ "pTRRecord",
+ "hInfoRecord",
+ "mXRecord",
+ "tXTRecord",
+ "rPRecord",
+ "aFSDBRecord",
+// "SigRecord",
+ "KeyRecord",
+// "gPosRecord",
+ "aAAARecord",
+ "lOCRecord",
+ "sRVRecord",
+ "nAPTRRecord",
+ "kXRecord",
+ "certRecord",
+// "a6Record",
+// "dNameRecord",
+// "aPLRecord",
+ "dSRecord",
+ "sSHFPRecord",
+ "iPSecKeyRecord",
+ "rRSIGRecord",
+ "nSECRecord",
+ "dNSKeyRecord",
+ "dHCIDRecord",
+ "sPFRecord",
+ "TYPE65534Record",
+ "EUI48Record",
+ "EUI64Record",
+ "TYPE65226Record",
+ "modifyTimestamp",
+ NULL
};
class LdapBackend : public DNSBackend
{
- bool m_getdn;
- bool m_qlog;
- int m_msgid;
- uint32_t m_ttl;
- uint32_t m_default_ttl;
- unsigned int m_axfrqlen;
- time_t m_last_modified;
- string m_myname;
- DNSName m_qname;
- PowerLDAP* m_pldap;
- LdapAuthenticator *m_authenticator;
- PowerLDAP::sentry_t m_result;
- PowerLDAP::sentry_t::iterator m_attribute;
- vector<string>::iterator m_value;
- vector<DNSName>::iterator m_adomain;
- vector<DNSName> m_adomains;
- QType m_qtype;
- int m_reconnect_attempts;
-
- bool (LdapBackend::*m_list_fcnt)( const DNSName&, int );
- void (LdapBackend::*m_lookup_fcnt)( const QType&, const DNSName&, DNSPacket*, int );
- bool (LdapBackend::*m_prepare_fcnt)();
-
- bool list_simple( const DNSName& target, int domain_id );
- bool list_strict( const DNSName& target, int domain_id );
-
- void lookup_simple( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid );
- void lookup_strict( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid );
- void lookup_tree( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid );
-
- bool prepare();
- bool prepare_simple();
- bool prepare_strict();
-
- bool getDomainInfo( const string& domain, DomainInfo& di );
-
- bool reconnect();
-
-public:
-
- LdapBackend( const string &suffix="" );
- ~LdapBackend();
-
- bool list( const DNSName& target, int domain_id, bool include_disabled=false );
- void lookup( const QType& qtype, const DNSName& qdomain, DNSPacket* p = 0, int zoneid = -1 );
- bool get( DNSResourceRecord& rr );
+ bool m_getdn;
+ bool m_qlog;
+ int m_msgid;
+ uint32_t m_ttl;
+ uint32_t m_default_ttl;
+ unsigned int m_axfrqlen;
+ time_t m_last_modified;
+ string m_myname;
+ DNSName m_qname;
+ PowerLDAP* m_pldap;
+ LdapAuthenticator *m_authenticator;
+ PowerLDAP::sentry_t m_result;
+ PowerLDAP::sentry_t::iterator m_attribute;
+ vector<string>::iterator m_value;
+ vector<DNSName>::iterator m_adomain;
+ vector<DNSName> m_adomains;
+ QType m_qtype;
+ int m_reconnect_attempts;
+
+ bool (LdapBackend::*m_list_fcnt)( const DNSName&, int );
+ void (LdapBackend::*m_lookup_fcnt)( const QType&, const DNSName&, DNSPacket*, int );
+ bool (LdapBackend::*m_prepare_fcnt)();
+
+ bool list_simple( const DNSName& target, int domain_id );
+ bool list_strict( const DNSName& target, int domain_id );
+
+ void lookup_simple( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid );
+ void lookup_strict( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid );
+ void lookup_tree( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid );
+
+ bool prepare();
+ bool prepare_simple();
+ bool prepare_strict();
+
+ bool getDomainInfo( const string& domain, DomainInfo& di );
+
+ bool reconnect();
+
+ public:
+
+ LdapBackend( const string &suffix="" );
+ ~LdapBackend();
+
+ bool list( const DNSName& target, int domain_id, bool include_disabled=false );
+ void lookup( const QType& qtype, const DNSName& qdomain, DNSPacket* p = 0, int zoneid = -1 );
+ bool get( DNSResourceRecord& rr );
};
#endif /* LDAPBACKEND_HH */
void ldapSetOption( LDAP *conn, int option, void *value )
{
- if( ldap_set_option( conn, option, value ) != LDAP_OPT_SUCCESS )
- {
- throw( LDAPException( "Unable to set option" ) );
- }
+ if( ldap_set_option( conn, option, value ) != LDAP_OPT_SUCCESS )
+ {
+ throw( LDAPException( "Unable to set option" ) );
+ }
}
void ldapGetOption( LDAP *conn, int option, void *value )
{
- if( ldap_get_option( conn, option, value ) != LDAP_OPT_SUCCESS )
- {
- throw( LDAPException( "Unable to get option" ) );
- }
+ if( ldap_get_option( conn, option, value ) != LDAP_OPT_SUCCESS )
+ {
+ throw( LDAPException( "Unable to get option" ) );
+ }
}
std::string ldapGetError( LDAP *conn, int code )
{
- if ( code == -1 )
- ldapGetOption( conn, LDAP_OPT_ERROR_NUMBER, &code );
- return std::string( ldap_err2string( code ) );
+ if ( code == -1 )
+ ldapGetOption( conn, LDAP_OPT_ERROR_NUMBER, &code );
+ return std::string( ldap_err2string( code ) );
}
int ldapWaitResult( LDAP *conn, int msgid, int timeout, LDAPMessage** result )
{
- struct timeval tv;
- LDAPMessage* res;
+ struct timeval tv;
+ LDAPMessage* res;
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
- int rc = ldap_result( conn, msgid, LDAP_MSG_ONE, &tv, &res );
+ int rc = ldap_result( conn, msgid, LDAP_MSG_ONE, &tv, &res );
- if ( rc == -1 || rc == 0 )
- return rc;
+ if ( rc == -1 || rc == 0 )
+ return rc;
- if( result == NULL )
- {
- ldap_msgfree( res );
- return rc;
- }
+ if( result == NULL )
+ {
+ ldap_msgfree( res );
+ return rc;
+ }
- *result = res;
- return rc;
+ *result = res;
+ return rc;
}
PowerLDAP::PowerLDAP( const string& hosts, uint16_t port, bool tls )
{
- d_ld = 0;
- d_hosts = hosts;
- d_port = port;
- d_tls = tls;
- ensureConnect();
+ d_ld = 0;
+ d_hosts = hosts;
+ d_port = port;
+ d_tls = tls;
+ ensureConnect();
}
void PowerLDAP::ensureConnect()
{
- int err;
+ int err;
- if(d_ld) {
- ldap_unbind_ext( d_ld, NULL, NULL );
- }
+ if(d_ld) {
+ ldap_unbind_ext( d_ld, NULL, NULL );
+ }
#ifdef HAVE_LDAP_INITIALIZE
- if( ( err = ldap_initialize( &d_ld, d_hosts.c_str() ) ) != LDAP_SUCCESS )
- {
- string ldapuris;
- vector<string> uris;
- stringtok( uris, d_hosts );
-
- for( size_t i = 0; i < uris.size(); i++ )
- {
- ldapuris += " ldap://" + uris[i];
- }
-
- if( ( err = ldap_initialize( &d_ld, ldapuris.c_str() ) ) != LDAP_SUCCESS )
- {
- throw LDAPException( "Error initializing LDAP connection to '" + ldapuris + ": " + getError( err ) );
- }
- }
+ if( ( err = ldap_initialize( &d_ld, d_hosts.c_str() ) ) != LDAP_SUCCESS )
+ {
+ string ldapuris;
+ vector<string> uris;
+ stringtok( uris, d_hosts );
+
+ for( size_t i = 0; i < uris.size(); i++ )
+ {
+ ldapuris += " ldap://" + uris[i];
+ }
+
+ if( ( err = ldap_initialize( &d_ld, ldapuris.c_str() ) ) != LDAP_SUCCESS )
+ {
+ throw LDAPException( "Error initializing LDAP connection to '" + ldapuris + ": " + getError( err ) );
+ }
+ }
#else
- if( ( d_ld = ldap_init( d_hosts.c_str(), d_port ) ) == NULL )
- {
- throw LDAPException( "Error initializing LDAP connection to '" + d_hosts + "': " + string( strerror( errno ) ) );
- }
+ if( ( d_ld = ldap_init( d_hosts.c_str(), d_port ) ) == NULL )
+ {
+ throw LDAPException( "Error initializing LDAP connection to '" + d_hosts + "': " + string( strerror( errno ) ) );
+ }
#endif
- int protocol = LDAP_VERSION3;
- if( ldap_set_option( d_ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) != LDAP_OPT_SUCCESS )
- {
- protocol = LDAP_VERSION2;
- if( ldap_set_option( d_ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) != LDAP_OPT_SUCCESS )
- {
- ldap_unbind_ext( d_ld, NULL, NULL );
- throw LDAPException( "Couldn't set protocol version to LDAPv3 or LDAPv2" );
- }
- }
-
- if( d_tls && ( err = ldap_start_tls_s( d_ld, NULL, NULL ) ) != LDAP_SUCCESS )
- {
- ldap_unbind_ext( d_ld, NULL, NULL );
- throw LDAPException( "Couldn't perform STARTTLS: " + getError( err ) );
- }
+ int protocol = LDAP_VERSION3;
+ if( ldap_set_option( d_ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) != LDAP_OPT_SUCCESS )
+ {
+ protocol = LDAP_VERSION2;
+ if( ldap_set_option( d_ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) != LDAP_OPT_SUCCESS )
+ {
+ ldap_unbind_ext( d_ld, NULL, NULL );
+ throw LDAPException( "Couldn't set protocol version to LDAPv3 or LDAPv2" );
+ }
+ }
+
+ if( d_tls && ( err = ldap_start_tls_s( d_ld, NULL, NULL ) ) != LDAP_SUCCESS )
+ {
+ ldap_unbind_ext( d_ld, NULL, NULL );
+ throw LDAPException( "Couldn't perform STARTTLS: " + getError( err ) );
+ }
}
PowerLDAP::~PowerLDAP()
{
- ldap_unbind_ext( d_ld, NULL, NULL );
+ ldap_unbind_ext( d_ld, NULL, NULL );
}
bool PowerLDAP::connect()
{
- try
- {
- ensureConnect();
- return true;
- }
- catch( LDAPException &le )
- {
- return false;
- }
+ try
+ {
+ ensureConnect();
+ return true;
+ }
+ catch( LDAPException &le )
+ {
+ return false;
+ }
}
void PowerLDAP::setOption( int option, int value )
{
- ldapSetOption( d_ld, option, (void*) &value );
+ ldapSetOption( d_ld, option, (void*) &value );
}
void PowerLDAP::getOption( int option, int *value )
{
- ldapGetOption( d_ld, option, (void*) value );
+ ldapGetOption( d_ld, option, (void*) value );
}
void PowerLDAP::bind( LdapAuthenticator* authenticator )
{
- if ( !authenticator->authenticate( d_ld ) )
- throw LDAPException( "Failed to bind to LDAP server: " + authenticator->getError() );
+ if ( !authenticator->authenticate( d_ld ) )
+ throw LDAPException( "Failed to bind to LDAP server: " + authenticator->getError() );
}
void PowerLDAP::bind( const string& ldapbinddn, const string& ldapsecret, int method, int timeout )
{
- int msgid;
+ int msgid;
#ifdef HAVE_LDAP_SASL_BIND
- int rc;
- struct berval passwd;
+ int rc;
+ struct berval passwd;
- passwd.bv_val = (char *)ldapsecret.c_str();
- passwd.bv_len = strlen( passwd.bv_val );
+ passwd.bv_val = (char *)ldapsecret.c_str();
+ passwd.bv_len = strlen( passwd.bv_val );
- if( ( rc = ldap_sasl_bind( d_ld, ldapbinddn.c_str(), LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid ) ) != LDAP_SUCCESS )
- {
- throw LDAPException( "Failed to bind to LDAP server: " + getError( rc ) );
- }
+ if( ( rc = ldap_sasl_bind( d_ld, ldapbinddn.c_str(), LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid ) ) != LDAP_SUCCESS )
+ {
+ throw LDAPException( "Failed to bind to LDAP server: " + getError( rc ) );
+ }
#else
- if( ( msgid = ldap_bind( d_ld, ldapbinddn.c_str(), ldapsecret.c_str(), method ) ) == -1 )
- {
- throw LDAPException( "Failed to bind to LDAP server: " + getError( msgid ) );
- }
+ if( ( msgid = ldap_bind( d_ld, ldapbinddn.c_str(), ldapsecret.c_str(), method ) ) == -1 )
+ {
+ throw LDAPException( "Failed to bind to LDAP server: " + getError( msgid ) );
+ }
#endif
- waitResult( msgid, timeout, NULL );
+ waitResult( msgid, timeout, NULL );
}
void PowerLDAP::simpleBind( const string& ldapbinddn, const string& ldapsecret )
{
- this->bind( ldapbinddn, ldapsecret, LDAP_AUTH_SIMPLE, 30 );
+ this->bind( ldapbinddn, ldapsecret, LDAP_AUTH_SIMPLE, 30 );
}
int PowerLDAP::search( const string& base, int scope, const string& filter, const char** attr )
{
- int msgid, rc;
+ int msgid, rc;
- if ( ( rc = ldap_search_ext( d_ld, base.c_str(), scope, filter.c_str(), const_cast<char**> (attr), 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ) ) ) {
- throw LDAPException( "Starting LDAP search: " + getError( rc ) );
- }
+ if ( ( rc = ldap_search_ext( d_ld, base.c_str(), scope, filter.c_str(), const_cast<char**> (attr), 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ) ) ) {
+ throw LDAPException( "Starting LDAP search: " + getError( rc ) );
+ }
- return msgid;
+ return msgid;
}
int PowerLDAP::waitResult( int msgid, int timeout, LDAPMessage** result )
{
- return ldapWaitResult( d_ld, msgid, timeout, result );
+ return ldapWaitResult( d_ld, msgid, timeout, result );
}
bool PowerLDAP::getSearchEntry( int msgid, sentry_t& entry, bool dn, int timeout )
{
- int i;
- char* attr;
- BerElement* ber;
- struct berval** berval;
- vector<string> values;
- LDAPMessage* result;
- LDAPMessage* object;
- bool hasResult = false;
-
- while ( !hasResult ) {
- i = waitResult( msgid, timeout, &result );
- // Here we deliberately ignore LDAP_RES_SEARCH_REFERENCE as we don't follow them.
- // Instead we get the next result.
- // If the function returned an error (i <= 0) we'll deal with after this loop too.
- if ( i == LDAP_RES_SEARCH_ENTRY || i == LDAP_RES_SEARCH_RESULT || i <= 0 )
- hasResult = true;
- }
-
- if ( i == -1 ) {
- // Error while retrieving the message
- int err_code;
- ldapGetOption( d_ld, LDAP_OPT_ERROR_NUMBER, &err_code );
- if ( err_code == LDAP_SERVER_DOWN || err_code == LDAP_CONNECT_ERROR )
- throw LDAPNoConnection();
- else
- throw LDAPException( "PowerLDAP::getSearchEntry(): Error when retrieving LDAP result: " + getError( err_code ) );
- }
-
- if ( i == 0 ) {
- // Timeout expired before the message could be retrieved
- throw LDAPTimeout();
- }
-
- if ( i == LDAP_RES_SEARCH_RESULT ) {
- // We're done with this request
- ldap_msgfree( result );
- return false;
- }
-
- if( ( object = ldap_first_entry( d_ld, result ) ) == NULL )
+ int i;
+ char* attr;
+ BerElement* ber;
+ struct berval** berval;
+ vector<string> values;
+ LDAPMessage* result;
+ LDAPMessage* object;
+ bool hasResult = false;
+
+ while ( !hasResult ) {
+ i = waitResult( msgid, timeout, &result );
+ // Here we deliberately ignore LDAP_RES_SEARCH_REFERENCE as we don't follow them.
+ // Instead we get the next result.
+ // If the function returned an error (i <= 0) we'll deal with after this loop too.
+ if ( i == LDAP_RES_SEARCH_ENTRY || i == LDAP_RES_SEARCH_RESULT || i <= 0 )
+ hasResult = true;
+ }
+
+ if ( i == -1 ) {
+ // Error while retrieving the message
+ int err_code;
+ ldapGetOption( d_ld, LDAP_OPT_ERROR_NUMBER, &err_code );
+ if ( err_code == LDAP_SERVER_DOWN || err_code == LDAP_CONNECT_ERROR )
+ throw LDAPNoConnection();
+ else
+ throw LDAPException( "PowerLDAP::getSearchEntry(): Error when retrieving LDAP result: " + getError( err_code ) );
+ }
+
+ if ( i == 0 ) {
+ // Timeout expired before the message could be retrieved
+ throw LDAPTimeout();
+ }
+
+ if ( i == LDAP_RES_SEARCH_RESULT ) {
+ // We're done with this request
+ ldap_msgfree( result );
+ return false;
+ }
+
+ if( ( object = ldap_first_entry( d_ld, result ) ) == NULL )
+ {
+ ldap_msgfree( result );
+ throw LDAPException( "Couldn't get first result entry: " + getError() );
+ }
+
+ entry.clear();
+
+ if( dn )
+ {
+ attr = ldap_get_dn( d_ld, object );
+ values.push_back( string( attr ) );
+ ldap_memfree( attr );
+ entry["dn"] = values;
+ }
+
+ if( ( attr = ldap_first_attribute( d_ld, object, &ber ) ) != NULL )
+ {
+ do
+ {
+ if( ( berval = ldap_get_values_len( d_ld, object, attr ) ) != NULL )
+ {
+ values.clear();
+ for( i = 0; i < ldap_count_values_len( berval ); i++ )
{
- ldap_msgfree( result );
- throw LDAPException( "Couldn't get first result entry: " + getError() );
+ values.push_back( berval[i]->bv_val ); // use berval[i]->bv_len for non string values?
}
- entry.clear();
-
- if( dn )
- {
- attr = ldap_get_dn( d_ld, object );
- values.push_back( string( attr ) );
- ldap_memfree( attr );
- entry["dn"] = values;
- }
+ entry[attr] = values;
+ ldap_value_free_len( berval );
+ }
+ ldap_memfree( attr );
+ }
+ while( ( attr = ldap_next_attribute( d_ld, object, ber ) ) != NULL );
- if( ( attr = ldap_first_attribute( d_ld, object, &ber ) ) != NULL )
- {
- do
- {
- if( ( berval = ldap_get_values_len( d_ld, object, attr ) ) != NULL )
- {
- values.clear();
- for( i = 0; i < ldap_count_values_len( berval ); i++ )
- {
- values.push_back( berval[i]->bv_val ); // use berval[i]->bv_len for non string values?
- }
-
- entry[attr] = values;
- ldap_value_free_len( berval );
- }
- ldap_memfree( attr );
- }
- while( ( attr = ldap_next_attribute( d_ld, object, ber ) ) != NULL );
-
- ber_free( ber, 0 );
- }
+ ber_free( ber, 0 );
+ }
- ldap_msgfree( result );
- return true;
+ ldap_msgfree( result );
+ return true;
}
void PowerLDAP::getSearchResults( int msgid, sresult_t& result, bool dn, int timeout )
{
- sentry_t entry;
+ sentry_t entry;
- result.clear();
- while( getSearchEntry( msgid, entry, dn, timeout ) )
- {
- result.push_back( entry );
- }
+ result.clear();
+ while( getSearchEntry( msgid, entry, dn, timeout ) )
+ {
+ result.push_back( entry );
+ }
}
const string PowerLDAP::getError( int rc )
{
- return ldapGetError( d_ld, rc );
+ return ldapGetError( d_ld, rc );
}
const string PowerLDAP::escape( const string& str )
{
- string a;
- string::const_iterator i;
- char tmp[4];
-
- for( i = str.begin(); i != str.end(); i++ )
- {
- // RFC4515 3
- if( *i == '*' ||
- *i == '(' ||
- *i == ')' ||
- *i == '\\' ||
- *i == '\0' ||
- *i > 127)
- {
- sprintf(tmp,"\\%02x", (unsigned char)*i);
-
- a += tmp;
- }
- else
- a += *i;
- }
-
- return a;
+ string a;
+ string::const_iterator i;
+ char tmp[4];
+
+ for( i = str.begin(); i != str.end(); i++ )
+ {
+ // RFC4515 3
+ if( *i == '*' ||
+ *i == '(' ||
+ *i == ')' ||
+ *i == '\\' ||
+ *i == '\0' ||
+ *i > 127)
+ {
+ sprintf(tmp,"\\%02x", (unsigned char)*i);
+
+ a += tmp;
+ }
+ else
+ a += *i;
+ }
+
+ return a;
}
class PowerLDAP
{
- LDAP* d_ld;
- string d_hosts;
- int d_port;
- bool d_tls;
-
- const string getError( int rc = -1 );
- int waitResult( int msgid = LDAP_RES_ANY, int timeout = 0, LDAPMessage** result = NULL );
- void ensureConnect();
-
-public:
- typedef map<string, vector<string> > sentry_t;
- typedef vector<sentry_t> sresult_t;
-
- PowerLDAP( const string& hosts = "ldap://127.0.0.1/", uint16_t port = LDAP_PORT, bool tls = false );
- ~PowerLDAP();
-
- bool connect();
-
- void getOption( int option, int* value );
- void setOption( int option, int value );
-
- void bind( LdapAuthenticator *authenticator );
- void bind( const string& ldapbinddn = "", const string& ldapsecret = "", int method = LDAP_AUTH_SIMPLE, int timeout = 5 );
- void simpleBind( const string& ldapbinddn = "", const string& ldapsecret = "" );
- int search( const string& base, int scope, const string& filter, const char** attr = 0 );
-
- bool getSearchEntry( int msgid, sentry_t& entry, bool dn = false, int timeout = 5 );
- void getSearchResults( int msgid, sresult_t& result, bool dn = false, int timeout = 5 );
-
- static const string escape( const string& tobe );
+ LDAP* d_ld;
+ string d_hosts;
+ int d_port;
+ bool d_tls;
+
+ const string getError( int rc = -1 );
+ int waitResult( int msgid = LDAP_RES_ANY, int timeout = 0, LDAPMessage** result = NULL );
+ void ensureConnect();
+
+ public:
+ typedef map<string, vector<string> > sentry_t;
+ typedef vector<sentry_t> sresult_t;
+
+ PowerLDAP( const string& hosts = "ldap://127.0.0.1/", uint16_t port = LDAP_PORT, bool tls = false );
+ ~PowerLDAP();
+
+ bool connect();
+
+ void getOption( int option, int* value );
+ void setOption( int option, int value );
+
+ void bind( LdapAuthenticator *authenticator );
+ void bind( const string& ldapbinddn = "", const string& ldapsecret = "", int method = LDAP_AUTH_SIMPLE, int timeout = 5 );
+ void simpleBind( const string& ldapbinddn = "", const string& ldapsecret = "" );
+ int search( const string& base, int scope, const string& filter, const char** attr = 0 );
+
+ bool getSearchEntry( int msgid, sentry_t& entry, bool dn = false, int timeout = 5 );
+ void getSearchResults( int msgid, sresult_t& result, bool dn = false, int timeout = 5 );
+
+ static const string escape( const string& tobe );
};
inline string ptr2ip4( vector<string>& parts )
{
- string ip;
- parts.pop_back();
- parts.pop_back();
+ string ip;
+ parts.pop_back();
+ parts.pop_back();
- ip = parts.back();
- parts.pop_back();
+ ip = parts.back();
+ parts.pop_back();
- while( !parts.empty() )
- {
- ip += "." + parts.back();
- parts.pop_back();
- }
+ while( !parts.empty() )
+ {
+ ip += "." + parts.back();
+ parts.pop_back();
+ }
- return ip;
+ return ip;
}
inline string ptr2ip6( vector<string>& parts )
{
- int i = 0;
- string ip;
-
-
- parts.pop_back();
- parts.pop_back();
-
- while( i < 3 && parts.size() > 1 && parts.back() == "0" )
- {
- parts.pop_back();
- i++;
- }
-
- while( i++ < 4 && !parts.empty() )
- {
- ip += parts.back();
- parts.pop_back();
- }
-
- while( !parts.empty() )
- {
- i = 0;
- ip += ":";
-
- while( i < 3 && parts.size() > 1 && parts.back() == "0" )
- {
- parts.pop_back();
- i++;
- }
-
- while( i++ < 4 && !parts.empty() )
- {
- ip += parts.back();
- parts.pop_back();
- }
- }
-
- return ip;
+ int i = 0;
+ string ip;
+
+
+ parts.pop_back();
+ parts.pop_back();
+
+ while( i < 3 && parts.size() > 1 && parts.back() == "0" )
+ {
+ parts.pop_back();
+ i++;
+ }
+
+ while( i++ < 4 && !parts.empty() )
+ {
+ ip += parts.back();
+ parts.pop_back();
+ }
+
+ while( !parts.empty() )
+ {
+ i = 0;
+ ip += ":";
+
+ while( i < 3 && parts.size() > 1 && parts.back() == "0" )
+ {
+ parts.pop_back();
+ i++;
+ }
+
+ while( i++ < 4 && !parts.empty() )
+ {
+ ip += parts.back();
+ parts.pop_back();
+ }
+ }
+
+ return ip;
}
inline string ip2ptr4( const string& ip )
{
- string ptr;
- vector<string> parts;
+ string ptr;
+ vector<string> parts;
- stringtok( parts, ip, "." );
- while( !parts.empty() )
- {
- ptr += parts.back() + ".";
- parts.pop_back();
- }
+ stringtok( parts, ip, "." );
+ while( !parts.empty() )
+ {
+ ptr += parts.back() + ".";
+ parts.pop_back();
+ }
- return ptr + "in-addr.arpa";
+ return ptr + "in-addr.arpa";
}
inline string ip2ptr6( const string& ip )
{
- string ptr, part, defstr;
- vector<string> parts;
-
- stringtok( parts, ip, ":" );
- while( !parts.empty() )
- {
- defstr = "0.0.0.0.";
- part = parts.back();
-
- while( part.length() < 4 )
- {
- part = "0" + part;
- }
-
- defstr[0] = part[3];
- defstr[2] = part[2];
- defstr[4] = part[1];
- defstr[6] = part[0];
- ptr += defstr;
- parts.pop_back();
- }
-
- return ptr + "ip6.arpa";
+ string ptr, part, defstr;
+ vector<string> parts;
+
+ stringtok( parts, ip, ":" );
+ while( !parts.empty() )
+ {
+ defstr = "0.0.0.0.";
+ part = parts.back();
+
+ while( part.length() < 4 )
+ {
+ part = "0" + part;
+ }
+
+ defstr[0] = part[3];
+ defstr[2] = part[2];
+ defstr[4] = part[1];
+ defstr[6] = part[0];
+ ptr += defstr;
+ parts.pop_back();
+ }
+
+ return ptr + "ip6.arpa";
}
inline string strbind( const string& search, const string& replace, string subject )
{
- size_t pos = 0;
+ size_t pos = 0;
- while( ( pos = subject.find( search, pos ) ) != string::npos )
- {
- subject.replace( pos, search.size(), replace );
- pos += replace.size();
- }
+ while( ( pos = subject.find( search, pos ) ) != string::npos )
+ {
+ subject.replace( pos, search.size(), replace );
+ pos += replace.size();
+ }
- return subject;
+ return subject;
}
/*
inline time_t str2tstamp( const string& str )
{
- char* tmp;
- struct tm tm;
+ char* tmp;
+ struct tm tm;
- tmp = strptime( str.c_str(), "%Y%m%d%H%M%SZ", &tm );
+ tmp = strptime( str.c_str(), "%Y%m%d%H%M%SZ", &tm );
- if( tmp != NULL && *tmp == 0 )
- {
- return Utility::timegm( &tm );
- }
+ if( tmp != NULL && *tmp == 0 )
+ {
+ return Utility::timegm( &tm );
+ }
- return 0;
+ return 0;
}
#endif