Commit b0b70c01 authored by Robert Dubner's avatar Robert Dubner
Browse files

Simplify using LDAP search

parent 6b9e7b4c
......@@ -996,7 +996,8 @@ process_mschap_response(STATE *state)
int bad_search = radiusov_get_password_from_uid( volatiles->radius_info,
volatiles->sd,
p_username,
password);
password,
sizeof(password) );
if( bad_search )
{
Debug( LDAP_DEBUG_TRACE,
......@@ -1841,7 +1842,8 @@ respond_to_ttls_md5_challenge( EAP_MESSAGE *internal_eap_message,
int bad_search = radiusov_get_password_from_uid( volatiles->radius_info,
volatiles->sd,
username,
password);
password,
sizeof(password));
// We can now do the same calculation that the authenticating peer did:
......
......@@ -99,84 +99,6 @@ ber_lower(BerValue *bv)
}
}
static int
radiusov_name2dn_callback(Operation *op, SlapReply *rs)
{
Debug(LDAP_DEBUG_TRACE,"=> %s(): rs->sr_type is %d\n",__func__, rs->sr_type);
if ( rs->sr_type == REP_SEARCH )
{
struct berval *bv = op->o_callback->sc_private;
ber_dupbv_x( bv,
&rs->sr_un.sru_search.r_entry->e_name,
op->o_hdr->oh_tmpmemctx);
}
return 0;
}
static int
radiusov_get_dn_from_uid( RADIUS_INFO *radius_info,
search_descriptor *sd,
char *pszUsername,
struct berval *dn_retval)
{
Debug(LDAP_DEBUG_TRACE,"=> %s(). UID is %s\n",__func__, pszUsername);
int rc = 0; // One means Okay
Connection conn = {0};
OperationBuffer opbuf;
Operation *op;
SlapReply rs = {REP_RESULT};
void *thrctx = ldap_pvt_thread_pool_context();
connection_fake_init( &conn, &opbuf, thrctx );
op=&opbuf.ob_op;
op->o_bd = radius_info->radius_db;
// In order to successfully search regardless of ACL controls, we need
// to operate as the rootdn:
op->o_ndn = op->o_bd->be_rootndn;
char fbuf[1024];
struct berval filter = {sizeof(fbuf),fbuf};
slap_callback cb = {0};
filter.bv_len = sprintf(filter.bv_val,
sd->search_filter_template,
pszUsername);
dn_retval->bv_len = 0;
dn_retval->bv_val = ((void *)0);
cb.sc_private = dn_retval;
cb.sc_response = radiusov_name2dn_callback;
op->o_tag = LDAP_REQ_SEARCH;
op->o_callback = &cb;
op->o_req_dn.bv_val = (char *)sd->search_base;
op->o_req_dn.bv_len = strlen(op->o_req_dn.bv_val);
op->o_req_ndn = op->o_req_dn;
op->o_request.oq_search.rs_scope = sd->search_scope ;
op->o_request.oq_search.rs_filterstr = filter;
op->o_request.oq_search.rs_filter = str2filter_x( op, filter.bv_val );
op->o_request.oq_search.rs_attrs = slap_anlist_no_attrs;
op->o_request.oq_search.rs_tlimit = -1;
op->o_request.oq_search.rs_slimit = -1;
rc = op->o_bd->bd_info->bi_op_search( op, &rs );
filter_free_x( op, op->o_request.oq_search.rs_filter, 1 );
if( rc == 0 && dn_retval->bv_val == NULL )
{
rc = 1 ;
}
ldap_pvt_thread_pool_context_reset( thrctx );
return rc;
}
static int
radiusov_bind( RADIUS_INFO *radius_info,
BerValue *dn,
......@@ -219,39 +141,12 @@ radiusov_bind( RADIUS_INFO *radius_info,
return rc;
}
static int
radiusov_verify_username_password( void *ctx,
RADIUS_INFO *radius_info,
search_descriptor *sd,
char *pszUsername,
char *pszPassword)
{
Debug(LDAP_DEBUG_TRACE,"=> %s()\n",__func__);
// Starting with username, find its DN
BerValue dn;
int rc = radiusov_get_dn_from_uid(radius_info, sd, pszUsername, &dn);
if( rc == 0 )
{
// The DN search succeeded, so do the BIND
rc = radiusov_bind(radius_info, &dn, pszPassword);
if( rc )
{
rc = 1;
}
}
else
{
rc = 1;
}
return rc;
}
typedef struct _ATTRIBUTE_VALUE
{
char *attribute_name;
char *returned_value;
size_t len; // size of the returned_value. The last char will be '\0'
// even if that involves truncation.
// even if that involves truncation.
} ATTRIBUTE_VALUE;
static int
......@@ -274,8 +169,8 @@ radiusov_generalized_callback(Operation *op, SlapReply *rs)
{
to_be_copied = desired_attribute->len-1;
}
memcpy( desired_attribute->returned_value,
rs->sr_un.sru_search.r_entry->e_name.bv_val,
memcpy( desired_attribute->returned_value,
rs->sr_un.sru_search.r_entry->e_name.bv_val,
to_be_copied );
desired_attribute->returned_value[to_be_copied] = '\0';
}
......@@ -301,8 +196,8 @@ radiusov_generalized_callback(Operation *op, SlapReply *rs)
ber_name = &a->a_desc[i].ad_cname;
ber_attr = &a->a_nvals[i];
Debug(LDAP_DEBUG_TRACE, " There is an a_nval[%d] ber_name %s\n", i, ber_name->bv_val);
if( ber_name->bv_len == strlen(desired_attribute->attribute_name)
&& memcmp(ber_name->bv_val, desired_attribute->attribute_name, ber_name->bv_len) == 0 )
if( ber_name->bv_len == strlen(desired_attribute->attribute_name)
&& memcmp(ber_name->bv_val, desired_attribute->attribute_name, ber_name->bv_len) == 0 )
{
Debug(LDAP_DEBUG_TRACE, " Found you, my pretty!\n");
size_t to_be_copied = ber_attr->bv_len;
......@@ -310,8 +205,8 @@ radiusov_generalized_callback(Operation *op, SlapReply *rs)
{
to_be_copied = desired_attribute->len-1;
}
memcpy( desired_attribute->returned_value,
ber_attr->bv_val,
memcpy( desired_attribute->returned_value,
ber_attr->bv_val,
to_be_copied );
desired_attribute->returned_value[to_be_copied] = '\0';
break;
......@@ -325,13 +220,14 @@ radiusov_generalized_callback(Operation *op, SlapReply *rs)
int
radiusov_generalized_database_fetch(BackendDB *be,
search_descriptor *sd,
char *pszUsername,
char *attribute_name,
char *returned_value,
size_t len)
const char *base,
int scope,
const char *filter,
char *attribute_name,
char *returned_value,
size_t len)
{
Debug(LDAP_DEBUG_TRACE,"=> %s(): UID is %s\n",__func__, pszUsername);
Debug(LDAP_DEBUG_TRACE,"=> %s(): search string is %s\n",__func__, filter);
int rc = 0; // Zero means okay
Connection conn = {0};
......@@ -353,19 +249,17 @@ radiusov_generalized_database_fetch(BackendDB *be,
ber_printf( ber,
"{siiiib",
sd->search_base,
sd->search_scope,
base,
scope,
deref,
sizelimit,
timelimit,
attrsonly );
char fbuf[1024];
sprintf(fbuf,"(uid=%s)",pszUsername);
ldap_pvt_put_filter( ber, fbuf );
ldap_pvt_put_filter( ber, filter );
// This routine is designed for handling just one attribute.
// I am including that single attribute, although there doesn't seem to
// I am including that single attribute, although there doesn't seem to
// be any point.
ber_printf(ber, "{s}", "userPassword");
......@@ -386,7 +280,7 @@ radiusov_generalized_database_fetch(BackendDB *be,
ATTRIBUTE_VALUE attr_value;
attr_value.attribute_name = attribute_name;
attr_value.returned_value = returned_value;
attr_value.len = 32;
attr_value.len = len;
cb.sc_private = &attr_value;
cb.sc_response = radiusov_generalized_callback;
......@@ -410,141 +304,84 @@ radiusov_generalized_database_fetch(BackendDB *be,
}
static int
radiusov_password_callback(Operation *op, SlapReply *rs)
{
Debug(LDAP_DEBUG_TRACE,"=> %s(): rs->sr_type = %d\n", __func__,rs->sr_type);
if ( rs->sr_type == REP_SEARCH )
{
Attribute *a;
int i;
for( a = rs->sr_un.sru_search.r_entry->e_attrs; a != NULL; a = a->a_next )
{
for( i = 0; a->a_nvals[i].bv_val != NULL; i++ )
{
BerValue *ber_name;
BerValue *ber_attr;
ber_name = &a->a_desc[i].ad_cname;
ber_attr = &a->a_nvals[i];
if( strcmp(ber_name->bv_val, "userPassword") == 0 )
{
char *password = op->o_callback->sc_private;
strncpy(password, ber_attr->bv_val, MAXIMUM_PASSWORD_CHARACTERS);
password[MAXIMUM_PASSWORD_CHARACTERS] = '\0';
break;
}
}
}
}
return SLAP_CB_CONTINUE;
}
int
radiusov_get_password_from_uid( RADIUS_INFO *radius_info,
search_descriptor *sd,
char *pszUsername,
char *password)
radiusov_get_dn_from_uid( BackendDB *be,
const char *base,
int scope,
char *pszUsername,
struct berval *dn_retval,
size_t len)
{
// IMPORTANT: password has to point to a buffer of at
// least (MAXIMUM_PASSWORD_CHARACTERS+1) bytes
Debug(LDAP_DEBUG_TRACE,"=> %s(): UID is %s\n",__func__, pszUsername);
int rc = 0; // Zero means okay
Connection conn = {0};
OperationBuffer opbuf;
Operation *op;
SlapReply rs = {REP_RESULT};
void *thrctx = ldap_pvt_thread_pool_context();
connection_fake_init( &conn, &opbuf, thrctx );
op=&opbuf.ob_op;
op->o_bd = radius_info->radius_db;
/*
* Parse the search request. It looks like this:
*
* SearchRequest := [APPLICATION 3] SEQUENCE {
* baseObject DistinguishedName,
* scope ENUMERATED {
* baseObject (0),
* singleLevel (1),
* wholeSubtree (2),
* subordinate (3) -- OpenLDAP extension
* },
* derefAliases ENUMERATED {
* neverDerefaliases (0),
* derefInSearching (1),
* derefFindingBaseObj (2),
* alwaysDerefAliases (3)
* },
* sizelimit INTEGER (0 .. 65535),
* timelimit INTEGER (0 .. 65535),
* attrsOnly BOOLEAN,
* filter Filter,
* attributes SEQUENCE OF AttributeType
* }
*/
BerElement *ber = ber_alloc_t(LBER_USE_DER);
ber_int_t deref = 0;
ber_int_t sizelimit = 0;
ber_int_t timelimit = 0;
ber_int_t attrsonly = 0;
ber_printf( ber,
"{siiiib",
sd->search_base,
sd->search_scope,
deref,
sizelimit,
timelimit,
attrsonly );
char fbuf[1024];
sprintf(fbuf,"(uid=%s)",pszUsername);
ldap_pvt_put_filter( ber, fbuf );
Debug(LDAP_DEBUG_TRACE,"=> %s(). UID is %s\n",__func__, pszUsername);
// In this implementation, we don't need to specify attributes. The
// query automatically returns the entire record, with all the attributes,
// from the database. We sort that out in radiusov_password_callback
ber_printf(ber, "{s}", "");
int rc = 0; // Zero means Okay
ber_printf(ber,"}");
ber->ber_len = ber->ber_ptr - ber->ber_buf;
ber->ber_end = ber->ber_ptr;
ber->ber_ptr = ber->ber_buf;
op->o_ber=ber;
op->o_tag = LDAP_REQ_SEARCH;
char filter[1024];
sprintf(filter,"(uid=%s)",pszUsername);
// In order to successfully search regardless of ACL controls, we need
// to operate as the rootdn:
op->o_ndn = op->o_bd->be_rootndn;
rc = radiusov_generalized_database_fetch(be,
base,
scope,
filter,
"dn",
dn_retval->bv_val,
len);
dn_retval->bv_len = strlen(dn_retval->bv_val);
slap_callback cb = {0};
return rc;
}
cb.sc_private = password;
cb.sc_response = radiusov_password_callback;
op->o_callback = &cb;
static int
radiusov_verify_username_password( RADIUS_INFO *radius_info,
search_descriptor *sd,
char *pszUsername,
char *pszPassword)
{
Debug(LDAP_DEBUG_TRACE,"=> %s()\n",__func__);
// Starting with username, find its DN
// Should we do something to defeat
// send_search_entry ((op)->o_conn->c_send_search_entry) ?
char dnbuffer[1024];
BerValue dn = {0, dnbuffer};
int rc = radiusov_get_dn_from_uid(radius_info->radius_db,
sd->search_base,
sd->search_scope,
pszUsername,
&dn,
sizeof(dnbuffer) );
rc = do_search(op, &rs);
if( rc == 0 )
{
if( rs.sr_un.sru_search.r_nentries == 0 )
// The DN search succeeded, so do the BIND
rc = radiusov_bind(radius_info, &dn, pszPassword);
if( rc )
{
// We didn't find anything
rc = 1;
}
}
ber_free(ber, 1);
ber = NULL;
else
{
rc = 1;
}
return rc;
}
ldap_pvt_thread_pool_context_reset( thrctx );
int
radiusov_get_password_from_uid( RADIUS_INFO *radius_info,
search_descriptor *sd,
char *pszUsername,
char *password,
size_t len)
{
char filter[1024];
sprintf(filter,"(uid=%s)",pszUsername);
int rc = radiusov_generalized_database_fetch(
radius_info->radius_db,
sd->search_base,
sd->search_scope,
filter,
"userPassword",
password,
len);
return rc;
}
......@@ -599,8 +436,7 @@ radiusov_test_and_development( void *ctx,
return rc;
}
rc = radiusov_verify_username_password( ctx,
radius_info,
rc = radiusov_verify_username_password( radius_info,
sd,
pszUsername,
pszPassword);
......@@ -1044,6 +880,8 @@ radiusov_db_open(BackendDB *be, ConfigReply *cr)
//char achUri[] = "ldap:///configuration=server1,cn=radservercfg,dc=renbud,dc=com?ipa,port?one?";
char achUri[] = "ldap:///dc=renbud,dc=com?userPassword?one?(uid=$1)";
char achUsername[] = "proxy";
char achFilterString[256];
sprintf(achFilterString, "(uid=%s)", achUsername);
LDAPURLDesc *lud;
if( ldap_url_parse( achUri, &lud) )
......@@ -1056,15 +894,21 @@ radiusov_db_open(BackendDB *be, ConfigReply *cr)
Debug( LDAP_DEBUG_ANY,
"ldap_url_parse succeeded\n");
}
search_descriptor *sd = &search_descriptors[0];
char achPassword[256];
// Do something with be->be_rootndn
radiusov_verify_username_password( radius_info,
sd,
"proxy",
"xyzzy" );
int rc = radiusov_generalized_database_fetch(radius_info->radius_db,
sd,
achUsername,
sd->search_base,
sd->search_scope,
achFilterString,
"userPassword",
achPassword,
MAXIMUM_PASSWORD_CHARACTERS );
......
......@@ -180,7 +180,8 @@ void hmac_md5_final( MD5_CTX *context,
int radiusov_get_password_from_uid( RADIUS_INFO *radius_info,
search_descriptor *sd,
char *pszUsername,
char *password);
char *password,
size_t len);
extern STATE *tls_new_session(SSL_CTX *ctx, TLS_SERVER_CONF *conf);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment