Skip to content

Commit

Permalink
added gssapi sasl binding
Browse files Browse the repository at this point in the history
  • Loading branch information
paleg committed Sep 5, 2016
1 parent d5589c1 commit b5a582b
Show file tree
Hide file tree
Showing 9 changed files with 528 additions and 18 deletions.
75 changes: 64 additions & 11 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,35 @@ int main() {
}
"""

def sasl_mechanisms_source_file(meh):
return """
#include <sasl/sasl.h>
#include <cstdlib>
#include <string>
static sasl_callback_t client_interactions[] = {{
{{ SASL_CB_GETREALM, NULL, NULL }},
{{ SASL_CB_USER, NULL, NULL }},
{{ SASL_CB_AUTHNAME, NULL, NULL }},
{{ SASL_CB_PASS, NULL, NULL }},
{{ SASL_CB_LIST_END, NULL, NULL }}
}};
int main() {{
std::string method = "{}";
if (sasl_client_init(client_interactions) != SASL_OK) return 1;
sasl_conn_t *conn;
if (sasl_client_new("rcmd", "localhost", NULL, NULL, NULL, 0, &conn) != SASL_OK) return 1;
const char *mechlist = NULL;
if (sasl_listmech(conn, NULL, ",", ",", ",", &mechlist, NULL, NULL) == SASL_OK)
return (std::string(mechlist).find("," + method + ",") == std::string::npos);
return 1;
}}
""".format(meh)

LibPath = ['/usr/lib', '/usr/local/lib']
IncludePath = ['.', '/usr/local/include', '/usr/include']

Expand Down Expand Up @@ -65,33 +94,57 @@ def checkSundap(context):
context.Result(result[0])
return result[0]

def checkSASL_DIGEST_MD5(context):
context.Message('Checking for DIGEST-MD5 mechanisms in sasl ... ')
result = context.TryRun(sasl_mechanisms_source_file("DIGEST-MD5"), ".cpp")
context.Result(result[0])
return result[0]

def checkSASL_GSSAPI(context):
context.Message('Checking for GSSAPI mechanisms in sasl ... ')
result = context.TryRun(sasl_mechanisms_source_file("GSSAPI"), ".cpp")
context.Result(result[0])
return result[0]

krb5_sources = []

if not IGNORE:
conf = Configure(env, custom_tests = {'checkLdapVersion' : checkLdapVersion, 'openldap' : checkOpenLdap, 'sunldap':checkSundap})
conf = Configure(env, custom_tests = {'checkLdapVersion' : checkLdapVersion,
'openldap' : checkOpenLdap, 'sunldap':checkSundap,
'sasl_gssapi': checkSASL_GSSAPI, 'sasl_digestmd5': checkSASL_DIGEST_MD5})
check_c_funcs = ['strdup' , 'strlen', 'strcmp', 'memset', 'bzero']
for func in check_c_funcs:
if not conf.CheckFunc(func):
print "Failed."
print("Failed.")
Exit(1)

check_c_headers = ['ldap.h', 'sasl/sasl.h']
for file in check_c_headers:
if not conf.CheckCHeader(file):
print "Failed."
for header in check_c_headers:
if not conf.CheckCHeader(header):
print("Failed.")
Exit(1)

check_cxx_headers = ['string', 'vector']
for file in check_cxx_headers:
if not conf.CheckCXXHeader(file):
print "Failed."
for header in check_cxx_headers:
if not conf.CheckCXXHeader(header):
print("Failed.")
Exit(1)

env.Append(LIBS=["ldap", "sasl2", "resolv", "stdc++"])
#env.Append(LIBS=["ldap", "sasl2", "resolv", "stdc++"])
check_libs = ['ldap', 'sasl2', 'resolv', 'stdc++']
for lib in check_libs:
if not conf.CheckLib(lib):
print "Failed."
print("Failed.")
Exit(1)

if not conf.sasl_digestmd5():
print("Failed.")
Exit(1)

if conf.CheckCHeader("krb5.h") and conf.CheckLib("krb5") and conf.sasl_gssapi():
env.Append(CCFLAGS=" -DKRB5 ")
krb5_sources = ["adclient_krb.cpp"]

if conf.openldap():
env.Append(CCFLAGS=" -DOPENLDAP ")
elif conf.sunldap():
Expand All @@ -104,7 +157,7 @@ if platform.system() == "Darwin" and platform.mac_ver()[0] and platform.mac_ver(
# suppress OpenDirectory Framework warnings for OSX >= 10.11
env.Append(CCFLAGS=" -Wno-deprecated ")

libadclient_target = env.SharedLibrary('adclient', ['adclient.cpp', 'adclient_sasl.cpp'])
libadclient_target = env.SharedLibrary('adclient', ['adclient.cpp', 'adclient_sasl.cpp'] + krb5_sources)

lib_install_target = env.Install(PREFIX+'/lib', libadclient_target)
header_install_target = env.Install(PREFIX+'/include', 'adclient.h')
Expand Down
40 changes: 36 additions & 4 deletions adclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,26 @@ adclient::adclient() {
Constructor, to initialize default values of global variables.
*/
ds = NULL;
#ifdef KRB5
krb_param = new krb_struct;
krb_param->context = NULL;
#endif
}

adclient::~adclient() {
/*
Destructor, to automaticaly free initial values allocated at login().
*/
logout(ds);
#ifdef KRB5
delete krb_param;
#endif
}

void adclient::logout(LDAP *ds) {
#ifdef KRB5
krb5_cleanup(krb_param);
#endif
if (ds != NULL) {
ldap_unbind_ext(ds, NULL, NULL);
}
Expand Down Expand Up @@ -107,7 +117,7 @@ void adclient::login(LDAP **ds, adConnParams& _params) {
*/
logout(*ds);

int result, version, bindresult;
int result, version, bindresult = -1;

string error_msg;

Expand Down Expand Up @@ -167,15 +177,37 @@ void adclient::login(LDAP **ds, adConnParams& _params) {
error_msg.append(ldap_err2string(result));
throw ADBindException(error_msg, AD_SERVER_CONNECT_FAILURE);
}

if (_params.secured) {
bindresult = sasl_bind_digest_md5(*ds, _params.binddn, _params.bindpw);
#ifdef KRB5
if (_params.use_gssapi && (!_params.domain.empty()) && (krb5_create_cache(_params.domain.c_str(), krb_param) == 0)) {
_params.login_method = "GSSAPI";
bindresult = sasl_bind_gssapi(*ds);
if (bindresult == LDAP_SUCCESS) {
ldap_set_rebind_proc(*ds, sasl_rebind_gssapi, NULL);
} else {
error_msg = "Error while " + _params.login_method + " ldap binding to " + _params.uri + ": ";
error_msg.append(ldap_err2string(bindresult));
cout << error_msg << endl;
krb_param->context = NULL;
}
} else {
bindresult = -1;
krb_param->context = NULL;
}
if (bindresult != LDAP_SUCCESS) {
#endif
_params.login_method = "DIGEST-MD5";
bindresult = sasl_bind_digest_md5(*ds, _params.binddn, _params.bindpw);
#ifdef KRB5
}
#endif
} else {
_params.login_method = "SIMPLE";
bindresult = sasl_bind_simple(*ds, _params.binddn, _params.bindpw);
}

if (bindresult != LDAP_SUCCESS) {
error_msg = "Error while ldap binding to " + _params.uri + " with " + _params.binddn + " " + _params.bindpw + ": ";
error_msg = "Error while " + _params.login_method + " ldap binding to " + _params.uri + " with '" + _params.binddn + "': ";
error_msg.append(ldap_err2string(bindresult));
throw ADBindException(error_msg, AD_SERVER_CONNECT_FAILURE);
}
Expand Down
8 changes: 5 additions & 3 deletions adclient.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package adclient

// #cgo CPPFLAGS: -DOPENLDAP
// #cgo LDFLAGS: -lstdc++ -lldap -lsasl2 -lstdc++ -llber -lresolv
// #cgo CPPFLAGS: -DOPENLDAP -DKRB5
// #cgo LDFLAGS: -lstdc++ -lldap -lsasl2 -lstdc++ -llber -lresolv -lkrb5
import "C"

import "fmt"
Expand All @@ -21,6 +21,7 @@ type ADConnParams struct {
Bindpw string
Search_base string
Secured bool
UseGSSAPI bool
Nettimeout int
Timelimit int
}
Expand Down Expand Up @@ -123,6 +124,7 @@ func Login(_params ADConnParams) (err error) {
params.SetBindpw(_params.Bindpw)
params.SetSearch_base(_params.Search_base)
params.SetSecured(_params.Secured)
params.SetUse_gssapi(_params.UseGSSAPI)
params.SetNettimeout(_params.Nettimeout)
params.SetTimelimit(_params.Timelimit)

Expand All @@ -144,7 +146,7 @@ func LoginOld(uri interface{}, user string, passwd string, sb string, secured bo
args.Binddn = user
args.Bindpw = passwd
args.Search_base = sb
args.Secured = secured
args.UseGSSAPI = secured

switch uri.(type) {
case string:
Expand Down
25 changes: 25 additions & 0 deletions adclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

#include <ldap.h>

#ifdef KRB5
#include <krb5.h>
#endif

#if defined( OPENLDAP )
#define LDAPOPTSUCCESS LDAP_OPT_SUCCESS
#elif defined( SUNLDAP )
Expand Down Expand Up @@ -57,6 +61,14 @@ using std::string;
using std::cout;
using std::endl;

#ifdef KRB5
struct krb_struct {
krb5_context context;
char *mem_cache_env;
krb5_ccache cc;
};
#endif

class ADException {
public:
ADException(string _msg, int _code) { msg = _msg; code = _code; }
Expand Down Expand Up @@ -88,6 +100,7 @@ struct adConnParams {
string bindpw;
string search_base;
bool secured;
bool use_gssapi;

// LDAP_OPT_NETWORK_TIMEOUT, LDAP_OPT_TIMEOUT
int nettimeout;
Expand All @@ -96,6 +109,7 @@ struct adConnParams {

adConnParams() :
secured(true),
use_gssapi(false),
// by default do not touch timeouts
nettimeout(-1), timelimit(-1)
{};
Expand All @@ -104,6 +118,7 @@ struct adConnParams {

private:
string uri;
string login_method;
};


Expand All @@ -121,6 +136,7 @@ class adclient {

string binded_uri() { return params.uri; }
string search_base() { return params.search_base; }
string login_method() { return params.login_method; }

void groupAddUser(string group, string user);
void groupRemoveUser(string group, string user);
Expand Down Expand Up @@ -205,6 +221,9 @@ class adclient {
adConnParams params;

LDAP *ds;
#ifdef KRB5
krb_struct *krb_param;
#endif

void login(LDAP **ds, adConnParams& _params);
void logout(LDAP *ds);
Expand Down Expand Up @@ -352,5 +371,11 @@ inline string int2ip(string value) {

int sasl_bind_digest_md5(LDAP *ds, string binddn, string bindpw);
int sasl_bind_simple(LDAP *ds, string binddn, string bindpw);
#ifdef KRB5
int krb5_create_cache(const char *domain, krb_struct *krb_param);
void krb5_cleanup(krb_struct *krb_param);
int sasl_bind_gssapi(LDAP *ds);
int sasl_rebind_gssapi(LDAP * ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params);
#endif

#endif // _ADCLIENT_H_
1 change: 1 addition & 0 deletions adclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def __init__(self):
self.bindpw = ""
self.search_base = ""
self.secured = True
self.use_gssapi = False
self.nettimeout = -1
self.timelimit = -1
self.uries = []
Expand Down
Loading

0 comments on commit b5a582b

Please sign in to comment.