Created
September 3, 2012 05:02
-
-
Save mbohun/3606810 to your computer and use it in GitHub Desktop.
test_ldap_threads-synchronous.cpp
This file contains hidden or 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
#ifdef _WIN32 | |
#include <windows.h> | |
#endif //WIN32 | |
#include <iostream> | |
#include <sstream> | |
#include <stdio.h> | |
#include <time.h> | |
#include <ctype.h> | |
#define LDAP_DEPRECATED 1 //AAA needs this | |
#include <ldap.h> | |
#include <lber.h> //for LDAP_CALL LDAP_CALLBACK (only mozilla SDK?) | |
#define TEST_LDAP_HOST "192.168.1.179" | |
#define TEST_LDAP_PORT LDAP_PORT //default 389 | |
#define TEST_LDAP_BASE_DN "dc=aaa,dc=test,dc=mbohun" | |
#define TEST_LDAP_USER_DN "cn=Administrator,cn=Users,dc=aaa,dc=test,dc=mbohun" | |
#define TEST_LDAP_USER_PASSWORD "abcABC666" | |
#define TEST_LDAP_FILTER "(sAMAccountName=tim)" | |
#define TEST_LDAP_TCP_TIMEOUT 12 //seconds | |
#define TEST_LDAP_REFERRAL_FILTER "ldap://ref.aaa.test.mbohun/DC=ref,DC=aaa,DC=test,DC=mbohun" | |
int dummy = 0; | |
/* | |
suggestions: | |
* add referrals filter (easy) (a set of referral URL to follow, ignore rest) | |
*/ | |
//simple filter for now, of course this is just a concept, we will have a proper set of URLs | |
static int is_valid_referral_url(const char* url) { | |
return (0 == strncmp(TEST_LDAP_REFERRAL_FILTER, url, sizeof(TEST_LDAP_REFERRAL_FILTER))); | |
} | |
static int rebind_callback (LDAP* h, | |
const char* url, | |
ber_tag_t req, | |
ber_int_t msgid, | |
void *args) { //use args instead of global vars!!! | |
/* | |
//check referral url against filter | |
if (!is_valid_referral_url(url)) { | |
std::cout << "rebind_callback, skipping:" << url << std::endl; | |
return LDAP_SUCCESS; | |
} else { | |
std::cout << "rebind_callback, match:" << url << std::endl; | |
} | |
*/ | |
//NOTE: synchronous bind | |
const int r = ldap_simple_bind_s(h, | |
TEST_LDAP_USER_DN, | |
TEST_LDAP_USER_PASSWORD); | |
/* | |
std::cout << "rebind_callback:" << r | |
<< ", (LDAP_SUCCESS=" << LDAP_SUCCESS << ")" | |
<< std::endl; | |
*/ | |
//TODO: handle error | |
return r; | |
} | |
int get_device_serial_number (void* args); | |
//DWORD WINAPI get_device_serial_number (LPVOID args); | |
int main(int argc, char* argv[]) { | |
//spawn 100 threads and search for device id for a given user | |
char* users[] = {"billy", "bob", "cal", "danny", "elm", "matt", | |
"tammy", "ted", "tim", "tom", "tony", "trevor" | |
}; | |
const int i = (int)(11.0*rand()/(RAND_MAX+1.0)); | |
get_device_serial_number(users[i]); | |
/* | |
HANDLE threads[100]; | |
DWORD thread_id[100]; | |
memset(threads, 0, sizeof(threads)/sizeof(threads[0])); | |
for (int t = 0; t < 100; t++ ) { | |
const int i = (int)(11.0*rand()/(RAND_MAX+1.0)); | |
threads[t] = CreateThread(NULL, | |
0, | |
get_device_serial_number, | |
users[i], | |
0, | |
&thread_id[t]); | |
} | |
WaitForMultipleObjects(100, threads, TRUE, INFINITE); | |
*/ | |
return 0; | |
} | |
// char* result = 0; | |
// get_device_serial_number(argv[1], &result); | |
// if (0 == result) { | |
// return -1; | |
// } | |
// std::cout << argv[1] << ":" << result << std::endl; | |
// free (result); | |
int get_device_serial_number (void* args) { | |
//DWORD WINAPI get_device_serial_number (LPVOID args) { | |
char* username = (char*)args; | |
std::stringstream ss; | |
ss << "(sAMAccountName="; | |
ss << username; | |
ss << ")"; | |
std::string s = ss.str(); | |
const char* search_filter = s.c_str(); | |
//std::cout << "using search filter:" << search_filter << std::endl; | |
LDAP* h = ldap_init(TEST_LDAP_HOST, TEST_LDAP_PORT); | |
if (NULL == h) { | |
perror("ldap_init"); | |
return -1; | |
} | |
int v = LDAP_VERSION3; | |
ldap_set_option(h, LDAP_OPT_PROTOCOL_VERSION, &v); | |
struct timeval t = {TEST_LDAP_TCP_TIMEOUT, 0}; | |
ldap_set_option(h, LDAP_OPT_NETWORK_TIMEOUT, &t); | |
//Question: How does automatic following of referrals mix with synchronous search? | |
ldap_set_option(h, LDAP_OPT_REFERRALS, LDAP_OPT_ON); //LDAP_OPT_ON (default?) / LDAP_OPT_OFF | |
ldap_set_rebind_proc(h, rebind_callback, &dummy); //OpenLDAP SDK | |
if (ldap_simple_bind_s(h, TEST_LDAP_USER_DN, TEST_LDAP_USER_PASSWORD) != LDAP_SUCCESS ) { | |
ldap_perror(h, "ldap_simple_bind_s" ); | |
return -1; | |
} | |
LDAPMessage* res =0; | |
char* attribute_filter[] = {"sAMAccountType", NULL }; | |
int rc; | |
for (int retry = 0; retry < 3; retry++) { | |
// unfortunatelly this is returning sometimes | |
// "ldap_search_ext_s: Operations error" | |
rc = ldap_search_ext_s(h, | |
TEST_LDAP_BASE_DN, | |
LDAP_SCOPE_SUBTREE, //scope: LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE | |
search_filter, | |
attribute_filter, //NOTE: for now return all attributes (NULL), later fix m_ppLdapQueryAttribName, | |
0, | |
NULL, | |
NULL, | |
&t,// LDAP_NO_LIMIT, | |
0, // LDAP_NO_LIMIT, | |
&res); | |
if (LDAP_SUCCESS != rc) { | |
if (retry < 2) { | |
std::cerr << "ldap_search_ext_s:" << ldap_err2string(rc) | |
<< ", attempt:" << retry | |
<< std::endl; | |
continue; | |
} | |
std::cerr << "ldap_search_ext_s:" << ldap_err2string(rc) | |
<< std::endl; | |
ldap_unbind_s(h); | |
return -1; | |
} else { | |
break; | |
} | |
} | |
int done = 0; | |
for (LDAPMessage* msg = ldap_first_message(h, res); | |
((0 == done) && (NULL!= msg)); | |
msg = ldap_next_message(h, msg) ) { | |
char* dn = 0; | |
int msgtype = ldap_msgtype(msg); | |
switch (msgtype) { | |
case LDAP_RES_SEARCH_ENTRY: | |
//std::cout << "LDAP_RES_SEARCH_ENTRY" << std::endl; | |
BerElement* ber; | |
LDAPMessage* entry; | |
entry = ldap_first_entry(h, res); | |
for (char* a = ldap_first_attribute(h, entry, &ber); | |
a != NULL; | |
a = ldap_next_attribute(h, entry, ber) ) { | |
char** vals; | |
if (NULL != (vals = ldap_get_values(h, entry, a))) { | |
for (int i = 0; vals[i] != NULL; i++ ) { | |
std::cout << username; | |
std::cout << ":" << vals[i] << std::endl; //fix this | |
} | |
ldap_value_free(vals); | |
} | |
ldap_memfree(a); | |
} | |
if (ber != NULL) { | |
ber_free(ber, 0); | |
} | |
done = 1; | |
break; | |
case LDAP_RES_SEARCH_REFERENCE: | |
// we are not using manual processing of referrals | |
//std::cout << "LDAP_RES_SEARCH_REFERENCE (ignored)" << std::endl; | |
break; | |
case LDAP_RES_SEARCH_RESULT: | |
//std::cout << "LDAP_RES_SEARCH_RESULT" << std::endl; | |
char* matched_msg; | |
char* error_msg; | |
char** referrals; | |
LDAPControl** serverctrls; | |
int parse_result_rc; | |
parse_result_rc = ldap_parse_result(h, | |
msg, | |
&rc, | |
&matched_msg, | |
&error_msg, | |
&referrals, // | |
&serverctrls, | |
1); //freeit: 0=don't free, 1=free | |
if (LDAP_SUCCESS != parse_result_rc) { | |
std::cerr << "ldap_parse_result:" | |
<< ldap_err2string(parse_result_rc) | |
<< std::endl; | |
ldap_unbind(h); | |
return -1; | |
} | |
/* | |
// Check the results of the LDAP search operation. | |
if ( rc != LDAP_SUCCESS ) { | |
fprintf( stderr, "ldap_search_ext: %s\n", ldap_err2string( rc ) ); | |
if ( error_msg != NULL & *error_msg != '\0' ) { | |
fprintf( stderr, "%s\n", error_msg ); | |
} | |
if ( matched_msg != NULL && *matched_msg != '\0' ) { | |
fprintf( stderr, "Part of the DN that matches an existing entry: %s\n", matched_msg ); | |
} | |
} else { | |
printf( "Search completed successfully.\n" | |
"Entries found: %d\n" | |
"Search references returned: %d\n", | |
num_entries, num_refs ); | |
} | |
*/ | |
//it should finish anyway because we are at the end of a for loop | |
done = 1; | |
break; | |
default: //well? | |
std::cout << "default?" << std::endl; | |
break; | |
} | |
} | |
ldap_unbind_s(h); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment