Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Robert Dubner
OpenLDAP
Commits
b0b70c01
Commit
b0b70c01
authored
Sep 09, 2021
by
Robert Dubner
Browse files
Simplify using LDAP search
parent
6b9e7b4c
Changes
3
Hide whitespace changes
Inline
Side-by-side
contrib/slapd-modules/radiusov/radius.c
View file @
b0b70c01
...
...
@@ -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:
...
...
contrib/slapd-modules/radiusov/radiusov.c
View file @
b0b70c01
...
...
@@ -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
);
...
...
contrib/slapd-modules/radiusov/radiusov.h
View file @
b0b70c01
...
...
@@ -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
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment