Adding new Resolver

104 views
Skip to first unread message

gfa...@soundhound.com

unread,
May 27, 2016, 7:45:45 PM5/27/16
to privacyidea
How easy/difficult is it to add a new resolver?
We use LDAP for user information, but Kerberos for the password
I would like to add a 'LDAP-Kerberos' resolver

Cornelius Kölbel

unread,
May 28, 2016, 1:19:42 AM5/28/16
to priva...@googlegroups.com
Hi,

I would say, the difficulty level is at 6.9.

You need to
1. write a resolver inherited from the baseclass.
This is relatively simple
http://privacyidea.readthedocs.io/en/latest/modules/useridresolvers.html#base-class

2. Then you need to add the resolver to certain code locations,
since we remove the dynamic loading. It was not worth it.
See these code occurences
https://github.com/privacyidea/privacyidea/blob/master/privacyidea/lib/config.py#L423
Oups, this looks like the only one.

Now it would be fully functional on an API level.

3. But you might also want to add some UI stuff.
The UI is angularJS and you would have to add a new config component
here
https://github.com/privacyidea/privacyidea/tree/master/privacyidea/static/components/config
Two states like
config.resolvers.addyourresolver
config.resolvers.edityourresolver
A view like
config.resolvers.yourresolver.html
and you might need to adapt one of the controllers or bring your own
controller.

Done.

But the question is, why you think, you need to do so. What Kerberos
implementation are you using? Verifying the password via the kerberos
protocol might be a bit difficult here. In which kind of backend is the
password stored? Or is a a flat file on your KDC?

Kind regards
Cornelius
> --
> Please read the blog post about getting help
> https://www.privacyidea.org/getting-help/.
>
> For professional services and consultancy regarding two factor
> authentication please visit
> https://netknights.it/en/leistungen/one-time-services/
>
> In an enterprise environment you should get a SERVICE LEVEL AGREEMENT
> which suites your needs for SECURITY, AVAILABILITY and LIABILITY:
> https://netknights.it/en/leistungen/service-level-agreements/
> ---
> You received this message because you are subscribed to the Google
> Groups "privacyidea" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to privacyidea...@googlegroups.com.
> To post to this group, send email to priva...@googlegroups.com.
> Visit this group at https://groups.google.com/group/privacyidea.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/privacyidea/603a9057-2465-4571-ad2a-696e098175aa%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

--
Cornelius Kölbel
corneliu...@netknights.it
+49 151 2960 1417

NetKnights GmbH
http://www.netknights.it
Landgraf-Karl-Str. 19, 34131 Kassel, Germany
Tel: +49 561 3166797, Fax: +49 561 3166798

Amtsgericht Kassel, HRB 16405
Geschäftsführer: Cornelius Kölbel


signature.asc

gfa...@soundhound.com

unread,
May 31, 2016, 5:22:21 PM5/31/16
to privacyidea
Hi Cornelius,

We're using MIT Kerberos for authentication/authorization and all other login information comes from LDAP (no passwords in LDAP though)
Passwords are stored in the 'standard' Kerberos database

Here's what I've done so far:
Copy privacyIDEA/lib/python2.7/site-packages/privacyidea/lib/resolvers/LDAPIdResolver.py to privacyIDEA/lib/python2.7/site-packages/privacyidea/lib/resolvers/LDAP-KerberosIdResolver.py
and make the following changes:
427c427
<         return 'ldapresolver'
---
>         return 'ldap-kerberosresolver'
555c555
<         descriptor['clazz'] = "useridresolver.LDAPIdResolver.IdResolver"
---
>         descriptor['clazz'] = "useridresolver.LDAP-KerberosIdResolver.IdResolver"

Modify privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/controllers/configControllers.js
497c497
<     $scope.availableResolverTypes = ['passwdresolver', 'ldapresolver', 'sqlresolver', 'scimresolver', 'ldap-kerberosresolver'];
---
>     $scope.availableResolverTypes = ['passwdresolver', 'ldapresolver', 'sqlresolver', 'scimresolver'];

Copy the LdapResolverController function as Ldap-KerberosResolverController and make the following changes:
1c1
< myApp.controller("LdapResolverController", function ($scope, ConfigFactory, $state,
---
> myApp.controller("Ldap-KerberosResolverController", function ($scope, ConfigFactory, $state,
13c13
<         type: 'ldapresolver',
---
>         type: 'ldap-kerberosresolver',
30c30
<             $scope.params.type = 'ldapresolver';
---
>             $scope.params.type = 'ldap-kerberosresolver';

Mofidy privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/states/states.js
64,71d63
<                 .state('config.resolvers.addldap-kerberosresolver', {
<                     url: "/ldap",
<                     templateUrl: configpath + "config.resolvers.ldap-kerberos.html"
<                 })
<                 .state('config.resolvers.editldap-kerberosresolver', {
<                     url: "/ldap/{resolvername:.*}",
<                     templateUrl: configpath + "config.resolvers.ldap-kerberos.html"
<                 })

Copy privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/views/config.resolvers.ldap.html to privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/views/config.resolvers.ldap-kerberos.html
Make changes:
1c1
< <div ng-controller="LdapResolverController">
---
> <div ng-controller="LdapKerberosResolverController">
5c5
<         translate>Edit LDAP Resolver {{ resolvername }}</h2>
---
>         translate>Edit LDAP-Kerberos Resolver {{ resolvername }}</h2>
8c8
<         translate>Create a new LDAP Resolver</h2>
---
>         translate>Create a new LDAP-Kerberos Resolver</h2>
10c10
< <form name="formResolverAddLdap" role="form" validate
---
> <form name="formResolverAddLdapKerberos" role="form" validate
185c185
<                 ng-disabled="formResolverAddLdap.$invalid"
---
>                 ng-disabled="formResolverAddLdapKerberos.$invalid"
187c187
<                 translate>Test LDAP Resolver
---
>                 translate>Test LDAP-Kerberos Resolver
189,190c189,190
<         <button ng-click="setLDAPResolver()"
<                 ng-disabled="formResolverAddLdap.$invalid"
---
>         <button ng-click="setLDAPKerberosResolver()"
>                 ng-disabled="formResolverAddLdapKerberos.$invalid"

If I now go to Config/Users, I see 'New ldap-kerberosresolver'
I can click 'new', fill in all the parameters and click 'Test LDAP Resolver' and it finds 262 users
'Save resolver' gets me a new resolver, but the type is listed as 'ldapresolver', so I seem to be tying in to the original ldapresolver somewhere

Any suggestions?

Gabriel

Cornelius Kölbel

unread,
May 31, 2016, 5:41:55 PM5/31/16
to priva...@googlegroups.com
Hi Gabriel,

I am not good in reading this kind of diff output.
Probably it is due to your angular routes.

But: Anyway. I very much recommend another approach. Everything in
privacyIDEA is an API. So everything is first developed in the backend.
And you have to come up with the corresponding tests, to at least
provide the impression of test driven development ;-)

Tests are located here:
https://github.com/privacyidea/privacyidea/blob/master/tests/test_lib_resolver.py#L431

I would get a step back and recommend documentation driven development.
First you need to write down, which additional information is needed to
authenticate a user and what you want to achieve.
Should a user provide a credentials: username/Password against the KDC -
what should happen then?

Should a user provide a kerberos ticket to authenticate?
The only method of interest to you is probably checkPass.
https://github.com/privacyidea/privacyidea/blob/master/privacyidea/lib/resolvers/LDAPIdResolver.py#L121
Since all other information is read from the LDAP anyway!

So first lets get clear, what you would like to achieve and how this can
be done.

Kind regards
Cornelius
> https://groups.google.com/d/msgid/privacyidea/a53f351c-fb4e-4781-83f8-d32773b125b3%40googlegroups.com.
signature.asc

Jochen Hein

unread,
Jun 1, 2016, 12:20:29 AM6/1/16
to gfa...@soundhound.com, privacyidea
gfa...@soundhound.com writes:

> Copy
> privacyIDEA/lib/python2.7/site-packages/privacyidea/lib/resolvers/LDAPIdResolver.py
> to
> privacyIDEA/lib/python2.7/site-packages/privacyidea/lib/resolvers/LDAP-KerberosIdResolver.py
> and make the following changes:

Can you use "diff -u" to provide the diff? That's much better readable,
because you also have some context for the changes.

Jochen

--
The only problem with troubleshooting is that the trouble shoots back.

Cornelius Kölbel

unread,
Jun 1, 2016, 4:02:41 AM6/1/16
to priva...@googlegroups.com
Thanks Jochen for pointing this out.

In addition I was trying to say, that you @Gabriel, first should think
about what your kerberos resolver should do.
And then you know
a) if it is a big deal and there is more effort to actually put into the
technical verification of the credentials or
b) it is no big deal and may it is easier to enhance the LDAP-resolver
or
c) ...
d) ...

It you are not defining tests (which I absolutely recommend), you should
run your chrome or firefox in developer mode (Ctrl-I). THen you can see
which data contains the request

POST /resolver

http://privacyidea.readthedocs.io/en/latest/modules/api/resolver.html#post--resolver-(resolver)

check if it contains the right resolver-type.

Kind regards
Cornelius
signature.asc

gfa...@soundhound.com

unread,
Jun 2, 2016, 4:35:31 PM6/2/16
to privacyidea
I wanted to start with a resolver with know functionality (LDAP), by just copying it to a new name
After testing that it still supplies the original functionality, I would have modified the 'checkPass' function for Kerberos authentication

Here are the requested 'diff -u's
--- privacyIDEA/lib/python2.7/site-packages/privacyidea/lib/resolvers/LDAPIdResolver.py 2016-05-18 10:46:04.000000000 -0700
+++ privacyIDEA/lib/python2.7/site-packages/privacyidea/lib/resolvers/LDAP-KerberosIdResolver.py        2016-05-27 13:43:27.267354778 -0700
@@ -424,7 +424,7 @@

     @staticmethod
     def getResolverClassType():
-        return 'ldapresolver'
+        return 'ldap-kerberosresolver'

     @staticmethod
     def getResolverDescriptor():
@@ -552,7 +552,7 @@
         """
         descriptor = {}
         typ = cls.getResolverType()
-        descriptor['clazz'] = "useridresolver.LDAPIdResolver.IdResolver"
+        descriptor['clazz'] = "useridresolver.LDAP-KerberosIdResolver.IdResolver"
         descriptor['config'] = {'LDAPURI': 'string',
                                 'LDAPBASE': 'string',
                                 'BINDDN': 'string',


--- privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/controllers/configControllers.js.orig  2016-05-18 10:46:04.000000000 -0700
+++ privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/controllers/configControllers.js       2016-05-19 11:33:35.528413238 -0700
@@ -494,7 +494,7 @@
     };

     // TODO: This information needs to be fetched from the server
-    $scope.availableResolverTypes = ['passwdresolver', 'ldapresolver', 'sqlresolver', 'scimresolver'];
+    $scope.availableResolverTypes = ['passwdresolver', 'ldapresolver', 'sqlresolver', 'scimresolver', 'ldap-kerberosresolver'];
     // TODO: This information needs to be fetched from the server
     $scope.availableMachineResolverTypes = ['hosts', 'ldap'];
     // TODO: This information needs to be fetched from the server
@@ -835,6 +835,84 @@
         });
     }

+    $scope.presetAD = function () {
+        $scope.params.LOGINNAMEATTRIBUTE = "sAMAccountName";
+        $scope.params.LDAPSEARCHFILTER = "(sAMAccountName=*)(objectClass=person)";
+        $scope.params.LDAPFILTER = "(&(sAMAccountName=%s)(objectClass=person))";
+        $scope.params.USERINFO = '{ "username": "sAMAccountName", "phone" : "telephoneNumber", "mobile" : "mobile", "email" : "mail", "surname" : "sn", "givenname" : "givenName" }';
+        $scope.params.NOREFERRALS = true;
+        $scope.params.SIZELIMIT = 500;
+        $scope.params.UIDTYPE = "objectGUID";
+        $scope.params.AUTHTYPE = "Simple";
+        $scope.params.SCOPE = "SUBTREE";
+    };
+
+    $scope.presetLDAP = function () {
+        $scope.params.LOGINNAMEATTRIBUTE = "uid";
+        $scope.params.LDAPSEARCHFILTER = "(uid=*)(objectClass=inetOrgPerson)";
+        $scope.params.LDAPFILTER = "(&(uid=%s)(objectClass=inetOrgPerson))";
+        $scope.params.USERINFO = '{ "username": "uid", "phone" : "telephoneNumber", "mobile" : "mobile", "email" : "mail", "surname" : "sn", "givenname" : "givenName" }';
+        $scope.params.NOREFERRALS = true;
+        $scope.params.SIZELIMIT = 500;
+        $scope.params.UIDTYPE = "entryUUID";
+        $scope.params.AUTHTYPE = "Simple";
+        $scope.params.SCOPE = "SUBTREE";
+    };
+
+    $scope.setLDAPResolver = function () {
+        ConfigFactory.setResolver($scope.resolvername, $scope.params, function (data) {
+            $scope.set_result = data.result.value;
+            $scope.getResolvers();
+            $state.go("config.resolvers.list");
+        });
+    };
+
+    $scope.testResolver = function () {
+        ConfigFactory.testResolver($scope.params, function (data) {
+            if (data.result.value === true) {
+                inform.add(data.detail.description,
+                    {type: "success", ttl: 10000});
+            } else {
+                inform.add(data.detail.description,
+                    {type: "danger", ttl: 10000});
+            }
+        });
+    };
+});
+
+myApp.controller("Ldap-KerberosResolverController", function ($scope, ConfigFactory, $state,
+                                                     $stateParams, inform,
+                                                     gettextCatalog) {
+    /*
+     BINDDN, BINDPW, LDAPURI, TIMEOUT, LDAPBASE, LOGINNAMEATTRIBUTE,
+     LDAPSEARCHFILTER,
+     LDAPFILTER, USERINFO, SIZELIMIT, NOREFERRALS, CACERTIFICATE, AUTHTYPE
+     */
+    $scope.params = {
+        SIZELIMIT: 500,
+        TIMEOUT: 5,
+        UIDTYPE: "DN",
+        type: 'ldap-kerberosresolver',
+        AUTHTYPE: "Simple",
+        SCOPE: "SUBTREE"
+    };
+    $scope.result = {};
+    $scope.resolvername = $stateParams.resolvername;
+    $scope.authtypes = ["Simple", "SASL Digest-MD5", "NTLM"];
+    $scope.scopes = ["SUBTREE", "BASE", "LEVEL"];
+
+    if ($scope.resolvername) {
+        /* If we have a resolvername, we do an Edit
+         and we need to fill all the $scope.params */
+        ConfigFactory.getResolver($scope.resolvername, function (data) {
+            var resolver = data.result.value[$scope.resolvername];
+            console.log(resolver);
+            $scope.params = resolver.data;
+            $scope.params.NOREFERRALS = ($scope.params.NOREFERRALS == "1");
+            $scope.params.type = 'ldap-kerberosresolver';
+        });
+    }
+
     $scope.presetAD = function () {
         $scope.params.LOGINNAMEATTRIBUTE = "sAMAccountName";
         $scope.params.LDAPSEARCHFILTER = "(sAMAccountName=*)(objectClass=person)";


--- privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/states/states.js.orig  2016-05-18 10:46:04.000000000 -0700
+++ privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/states/states.js       2016-05-31 14:05:48.028322964 -0700
@@ -61,6 +61,14 @@

                     url: "/ldap/{resolvername:.*}",
                     templateUrl: configpath + "config.resolvers.ldap.html"
                 })
+                .state('config.resolvers.addldap-kerberosresolver', {
+                    url: "/ldap",
+                    templateUrl: configpath + "config.resolvers.ldap-kerberos.html"
+                })
+                .state('config.resolvers.editldap-kerberosresolver', {
+                    url: "/ldap/{resolvername:.*}",
+                    templateUrl: configpath + "config.resolvers.ldap-kerberos.html"
+                })
                 .state('config.resolvers.addscimresolver', {
                     url: "/scim",
                     templateUrl: configpath + "config.resolvers.scim.html"

--- privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/views/config.resolvers.ldap.html       2016-05-18 10:46:04.000000000 -0700
+++ privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/views/config.resolvers.ldap-kerberos.html      2016-05-31 14:04:35.144274422 -0700
@@ -1,13 +1,13 @@
-<div ng-controller="LdapResolverController">
+<div ng-controller="LdapKerberosResolverController">

 <h2 class="form-signin-heading"
         ng-show="resolvername"
-        translate>Edit LDAP Resolver {{ resolvername }}</h2>
+        translate>Edit LDAP-Kerberos Resolver {{ resolvername }}</h2>
 <h2 class="form-signin-heading"
         ng-hide="resolvername"
-        translate>Create a new LDAP Resolver</h2>
+        translate>Create a new LDAP-Kerberos Resolver</h2>

-<form name="formResolverAddLdap" role="form" validate
+<form name="formResolverAddLdapKerberos" role="form" validate
       class="form-horizontal">

     <div class="form-group">
@@ -182,12 +182,12 @@

     <div class="text-center">
         <button ng-click="testResolver()"
-                ng-disabled="formResolverAddLdap.$invalid"
+                ng-disabled="formResolverAddLdapKerberos.$invalid"
                 class="btn btn-success"
-                translate>Test LDAP Resolver
+                translate>Test LDAP-Kerberos Resolver
         </button>
-        <button ng-click="setLDAPResolver()"
-                ng-disabled="formResolverAddLdap.$invalid"
+        <button ng-click="setLDAPKerberosResolver()"
+                ng-disabled="formResolverAddLdapKerberos.$invalid"
                 class="btn btn-primary"
                 translate>Save resolver
         </button>

Thanks

Cornelius Kölbel

unread,
Jun 2, 2016, 4:41:47 PM6/2/16
to priva...@googlegroups.com
Hello Gabriel,

thanks a lot.
Can you please take a look at the POST request, that creates your
resolver?
This takes ten seconds and then we know, If we need to take a look at
the UI or the backend.

THanks a lot
Cornelius

Am Donnerstag, den 02.06.2016, 13:35 -0700 schrieb
gfa...@soundhound.com:
> --
> Please read the blog post about getting help
> https://www.privacyidea.org/getting-help/.
>
> For professional services and consultancy regarding two factor
> authentication please visit
> https://netknights.it/en/leistungen/one-time-services/
>
> In an enterprise environment you should get a SERVICE LEVEL AGREEMENT
> which suites your needs for SECURITY, AVAILABILITY and LIABILITY:
> https://netknights.it/en/leistungen/service-level-agreements/
> ---
> You received this message because you are subscribed to the Google
> Groups "privacyidea" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to privacyidea...@googlegroups.com.
> To post to this group, send email to priva...@googlegroups.com.
> Visit this group at https://groups.google.com/group/privacyidea.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/privacyidea/c8152ad4-ff57-4566-8ff8-2c8e04ad90d0%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

signature.asc

Jochen Hein

unread,
Jun 3, 2016, 11:30:15 AM6/3/16
to gfa...@soundhound.com, privacyidea
gfa...@soundhound.com writes:

> I wanted to start with a resolver with know functionality (LDAP), by just
> copying it to a new name
> After testing that it still supplies the original functionality, I would
> have modified the 'checkPass' function for Kerberos authentication

That seems to be a good idea.

> privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/states/states.js.orig
> 2016-05-18 10:46:04.000000000 -0700
> +++
> privacyIDEA/lib/python2.7/site-packages/privacyidea/static/components/config/states/states.js
> 2016-05-31 14:05:48.028322964 -0700
> @@ -61,6 +61,14 @@
> url: "/ldap/{resolvername:.*}",
> templateUrl: configpath + "config.resolvers.ldap.html"
> })
> + .state('config.resolvers.addldap-kerberosresolver', {
> + url: "/ldap",

Should that be "/ldap-kerberos"? I'm not sure, but it might be.

> + templateUrl: configpath +
> "config.resolvers.ldap-kerberos.html"
> + })
> + .state('config.resolvers.editldap-kerberosresolver', {
> + url: "/ldap/{resolvername:.*}",

And here too?

Cornelius Kölbel

unread,
Jun 6, 2016, 11:32:24 AM6/6/16
to privacyidea, gfa...@soundhound.com
Hello Gabriel, hello Jochen,

I added a skeleton for a kerberos resolver in its own branch. Please see this commit:


The best way is to inherid the ldap resolver. One day, Gabrial you will only have to add the checkPass method.

You might want to start to adapt this HTML template:

Then we need to add its own angular js controller and replace this one:

setLDAPResolver

you are welcome to isse some pull requests on this branch.

Kind regards
Cornelius

Gabriel Faber

unread,
Jun 22, 2016, 5:16:25 PM6/22/16
to Cornelius Kölbel, privacyidea
Hi Cornelius,

Let me start by saying I'm not a Python programmer, so forgive if I ask
stupid questions
I installed the branch you created for me and that works fine
I created a 'resolver' of type 'kerberosresolver ', and a 'Realm' on top
of that
I created a token and can then use 'radclient' to authenticate
I created a 'passthru' 'authentication' policy and can use the (LDAP)
password to authenticate for a user with no token

Now I'm having trouble moving forward.
I added a 'checkPass' routine to KerberosIdResolver.py (the MELODIS.COM
is the Kerberos realm and will come from a configuration parameter in
the future):
def checkPass(self, uid, password):
"""
This function checks the password for a given uid.
- returns true in case of success
- false if password does not match

"""

server_pool = self.get_serverpool(self.uri, self.timeout)
password = to_utf8(password)
service = "krbtgt/MELODIS.COM"
realm = "MELODIS.COM"

try:
log.debug("(Kerberos) user : %s" % bind_user)
# Whatever happens. If we have an empty bind_user, we must
break
# since we must avoid anonymous binds!
if not bind_user or len(bind_user) < 1:
raise Exception("No valid user. Empty bind_user.")
kerberos.checkPassword(bind_user,password,service,realm)
except kerberos.BasicAuthError, e:
log.warning("failed to check password for %r/%r: %r"
% (uid, bind_user, e))
return False

return True

I also added 'import kerberos' near the top

If I test with radclient, I get an error:
[ro...@privacyidea-kerberos.sca httpd]# echo "User-Name=dummy,
User-Password=######" | radclient -sx localhost auth testing123
Sending Access-Request Id 188 from 0.0.0.0:33957 to 127.0.0.1:1812
User-Name = 'dummy'
User-Password = '######'
Received Access-Reject Id 188 from 127.0.0.1:1812 to 127.0.0.1:33957
length 53
Reply-Message = 'The user has no tokens assigned'
(0) -: Expected Access-Accept got Access-Reject
Packet summary:
Accepted : 0
Rejected : 1
Lost : 0
Passed filter : 0
Failed filter : 1

If I check the debug log (/var/log/privacyidea/privacyidea.log):
[2016-06-22
14:10:45,978][1910][139791492630272][DEBUG][privacyidea.lib.resolvers.LDAPIdResolver:145]
Authtype: Simple
[2016-06-22
14:10:45,978][1910][139791492630272][DEBUG][privacyidea.lib.resolvers.LDAPIdResolver:146]
user : uid=dummy,ou=People,dc=melodis,dc=com
[2016-06-22
14:10:45,980][1910][139791492630272][DEBUG][privacyidea.lib.resolvers.LDAPIdResolver:158]
bind result: False
[2016-06-22
14:10:45,980][1910][139791492630272][WARNING][privacyidea.lib.resolvers.LDAPIdResolver:165]
failed to check password for
u'f53c17ba-c90c-1035-9c35-7f8e6b5cf1e4'/'uid=dummy,ou=People,dc=melodis,dc=com':
Exception('Wrong credentials',)
[2016-06-22
14:10:45,981][1910][139791492630272][INFO][privacyidea.lib.user:339]
user User(login=u'dummy', realm=u'kerberos', resolver=u'LDAP_Kerberos')
failed to authenticate.
[2016-06-22
14:10:45,981][1910][139791492630272][DEBUG][privacyidea.lib.user:184]
Exiting check_password with result None

I see that it's still calling the checkPass routine in
LDAPIdResolver.py, which has:
log.debug("Authtype: {0!s}".format(self.authtype))
log.debug("user : {0!s}".format(bind_user))
where my new routine has:
log.debug("(Kerberos) user : %s" % bind_user)

Any help appreciated,

Gabriel

--
Gabriel Faber
Senior Operations Engineer
SoundHound Inc.
408-441-3267

Cornelius Kölbel

unread,
Jun 23, 2016, 2:23:13 AM6/23/16
to priva...@googlegroups.com
Hi Gabriel,

do you have the code somewhere at github?

1. please do not use RADIUS for testing. This adds an extra layer of
complexity, we do not want.
You can use the REST API /validate/check like
https://yourserver/validate/check?user=dummy?pass=static123456

2. These lines also indicate, that the LDAP resolver is used:
[2016-06-22
>
14:10:45,978][1910][139791492630272][DEBUG][privacyidea.lib.resolvers.LDAPIdResolver:145]

3. look at this:

14:10:45,980][1910][139791492630272][WARNING][privacyidea.lib.resolvers.LDAPIdResolver:165]
> failed to check password for
>
u'f53c17ba-c90c-1035-9c35-7f8e6b5cf1e4'/'uid=dummy,ou=People,dc=melodis,dc=com':
> Exception('Wrong credentials',)
> [2016-06-22
> 14:10:45,981][1910][139791492630272][INFO][privacyidea.lib.user:339]
> user User(login=u'dummy', realm=u'kerberos',
resolver=u'LDAP_Kerberos')
> failed to authenticate.

Are you using GUID or UUID? Please use DN as uid type, this will
simplify things!
(Do not add extra layers of complexity)

Kind regards
Cornelius
signature.asc

gfa...@soundhound.com

unread,
Jun 23, 2016, 1:43:59 PM6/23/16
to privacyidea
Hi Cornelius,

I do not have the code at github.(I have not used github before). I've attached the only file I've changed

As for 'GUID or UUID', I used the standard 'Preset OpenLDAP', but 'objectClass=account' instead of 'objectClass=inetOrgPerson'

If I do 'validate' in my browser, I get:
{"jsonrpc": "2.0", "signature": "3950417441791693604767928663283836051969466621902002007276767444723223890502807901319765066552020666596744777437276917014225347629822376032131880095131557153565551396693225310072459366432315266767168592149106767325799042005516053040322203606786349050391254873576072259618177305957325846130191519331797770229962754242695274624943494473141034142272407862935445218714272737570409992715097155824581098913178930687989658557569120116445198713784106528070089114206305225208287377027094097094691057534179247329367150660143254229733656132445906261731022565852184985098829774365780211310331592368949148441767497167176048049117", "detail": {"message": "The user has no tokens assigned"}, "versionnumber": "2.13dev0", "version": "privacyIDEA 2.13dev0", "result": {"status": true, "value": false}, "time": 1466697735.327017, "id": 1}

From the log file:
[2016-06-23 09:13:52,011][1910][139791501022976][DEBUG][privacyidea.lib.config:571] using the module list: set(['privacyidea.lib.resolvers.SQLIdResolver', 'privacyidea.lib.resolvers.LDAPIdResolver', 'privacyidea.lib.resolvers.KerberosIdResolver', 'privacyidea.lib.resolvers.PasswdIdResolver', 'privacyidea.lib.resolvers.SCIMIdResolver', 'privacyidea.lib.resolvers.UserIdResolver'])
[2016-06-23 09:13:52,011][1910][139791501022976][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.SQLIdResolver
[2016-06-23 09:13:52,011][1910][139791501022976][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.LDAPIdResolver
[2016-06-23 09:13:52,011][1910][139791501022976][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.KerberosIdResolver
[2016-06-23 09:13:52,011][1910][139791501022976][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.PasswdIdResolver
[2016-06-23 09:13:52,011][1910][139791501022976][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.SCIMIdResolver
[2016-06-23 09:13:52,011][1910][139791501022976][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.UserIdResolver
[2016-06-23 09:13:52,012][1910][139791501022976][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.SQLIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/SQLIdResolver.pyc'>
[2016-06-23 09:13:52,012][1910][139791501022976][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.LDAPIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/LDAPIdResolver.pyc'>
[2016-06-23 09:13:52,012][1910][139791501022976][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.KerberosIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/KerberosIdResolver.pyc'>
[2016-06-23 09:13:52,012][1910][139791501022976][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.PasswdIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/PasswdIdResolver.pyc'>
[2016-06-23 09:13:52,012][1910][139791501022976][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.SCIMIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/SCIMIdResolver.pyc'>
[2016-06-23 09:13:52,012][1910][139791501022976][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.UserIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/UserIdResolver.pyc'>
[2016-06-23 09:13:52,012][1910][139791501022976][DEBUG][privacyidea.lib.resolver:172] Entering get_resolver_config with arguments (u'LDAP_Kerberos',) and keywords {}
[2016-06-23 09:13:52,013][1910][139791501022976][DEBUG][privacyidea.lib.resolver:172] Entering get_resolver_list with arguments () and keywords {'filter_resolver_name': u'LDAP_Kerberos'}
[2016-06-23 09:13:52,018][1910][139791501022976][DEBUG][privacyidea.lib.crypto:172] Entering decryptPassword with arguments (u'0398be624f80f5a7c53b8181eee0f44d:41f08cce12cb2bd47e9ec01cf8510980',) and keywords {}
[2016-06-23 09:13:52,018][1910][139791501022976][DEBUG][privacyidea.lib.crypto:186] Exiting decryptPassword with result HIDDEN
[2016-06-23 09:13:52,018][1910][139791501022976][DEBUG][privacyidea.lib.resolver:186] Exiting get_resolver_list with result HIDDEN
[2016-06-23 09:13:52,018][1910][139791501022976][DEBUG][privacyidea.lib.resolver:186] Exiting get_resolver_config with result HIDDEN
[2016-06-23 09:13:52,021][1910][139791501022976][DEBUG][privacyidea.lib.resolver:184] Exiting get_resolver_object with result <privacyidea.lib.resolvers.KerberosIdResolver.IdResolver object at 0x7f23b42f5090>
[2016-06-23 09:13:52,022][1910][139791501022976][DEBUG][privacyidea.lib.resolvers.LDAPIdResolver:563] Added ldap1.sca.melodis.com, None, False to server pool.
[2016-06-23 09:13:52,029][1910][139791501022976][DEBUG][privacyidea.lib.resolvers.LDAPIdResolver:563] Added ldap1.sca.melodis.com, None, False to server pool.
[2016-06-23 09:13:52,035][1910][139791501022976][DEBUG][privacyidea.lib.resolvers.LDAPIdResolver:563] Added ldap1.sca.melodis.com, None, False to server pool.
[2016-06-23 09:13:52,035][1910][139791501022976][DEBUG][privacyidea.lib.resolvers.LDAPIdResolver:145] Authtype: Simple
[2016-06-23 09:13:52,036][1910][139791501022976][DEBUG][privacyidea.lib.resolvers.LDAPIdResolver:146] user    : uid=dummy,ou=People,dc=melodis,dc=com
[2016-06-23 09:13:52,038][1910][139791501022976][DEBUG][privacyidea.lib.resolvers.LDAPIdResolver:158] bind result: False
[2016-06-23 09:13:52,038][1910][139791501022976][WARNING][privacyidea.lib.resolvers.LDAPIdResolver:165] failed to check password for u'f53c17ba-c90c-1035-9c35-7f8e6b5cf1e4'/'uid=dummy,ou=People,dc=melodis,dc=com': Exception('Wrong credentials',)
[2016-06-23 09:13:52,038][1910][139791501022976][INFO][privacyidea.lib.user:339] user User(login=u'dummy', realm=u'kerberos', resolver=u'LDAP_Kerberos') failed to authenticate.

This line:
[2016-06-23 09:13:52,021][1910][139791501022976][DEBUG][privacyidea.lib.resolver:184] Exiting get_resolver_object with result <privacyidea.lib.resolvers.KerberosIdResolver.IdResolver object at 0x7f23b42f5090>
seems to tell me it found the right resolver

To make sure it's actually reading the KerberosIdResolver file, I renamed it (and the .pyc file):
./lib/python2.7/site-packages/privacyidea/lib/resolvers/KerberosIdResolver.pyc.no
./lib/python2.7/site-packages/privacyidea/lib/resolvers/KerberosIdResolver.py.no
and tested again
The log file shows no errors:
[2016-06-23 10:22:58,480][1910][139791534593792][DEBUG][privacyidea.lib.config:184] Exiting get_resolver_list with result set(['privacyidea.lib.resolvers.SQLIdResolver', 'privacyidea.lib.resolvers.LDAPIdResolver', 'privacyidea.lib.resolvers.KerberosIdResolver', 'privacyidea.lib.resolvers.PasswdIdResolver', 'privacyidea.lib.resolvers.SCIMIdResolver', 'privacyidea.lib.resolvers.UserIdResolver'])
[2016-06-23 10:22:58,480][1910][139791534593792][DEBUG][privacyidea.lib.config:571] using the module list: set(['privacyidea.lib.resolvers.SQLIdResolver', 'privacyidea.lib.resolvers.LDAPIdResolver', 'privacyidea.lib.resolvers.KerberosIdResolver', 'privacyidea.lib.resolvers.PasswdIdResolver', 'privacyidea.lib.resolvers.SCIMIdResolver', 'privacyidea.lib.resolvers.UserIdResolver'])
[2016-06-23 10:22:58,480][1910][139791534593792][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.SQLIdResolver
[2016-06-23 10:22:58,480][1910][139791534593792][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.LDAPIdResolver
[2016-06-23 10:22:58,480][1910][139791534593792][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.KerberosIdResolver
[2016-06-23 10:22:58,480][1910][139791534593792][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.PasswdIdResolver
[2016-06-23 10:22:58,480][1910][139791534593792][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.SCIMIdResolver
[2016-06-23 10:22:58,480][1910][139791534593792][DEBUG][privacyidea.lib.config:579] import module: privacyidea.lib.resolvers.UserIdResolver
[2016-06-23 10:22:58,480][1910][139791534593792][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.SQLIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/SQLIdResolver.pyc'>
[2016-06-23 10:22:58,481][1910][139791534593792][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.LDAPIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/LDAPIdResolver.pyc'>
[2016-06-23 10:22:58,481][1910][139791534593792][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.KerberosIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/KerberosIdResolver.pyc'>
[2016-06-23 10:22:58,481][1910][139791534593792][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.PasswdIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/PasswdIdResolver.pyc'>
[2016-06-23 10:22:58,481][1910][139791534593792][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.SCIMIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/SCIMIdResolver.pyc'>
[2016-06-23 10:22:58,481][1910][139791534593792][DEBUG][privacyidea.lib.config:388] module: <module 'privacyidea.lib.resolvers.UserIdResolver' from '/opt/privacyIDEA-kerberos/lib/python2.7/site-packages/privacyidea/lib/resolvers/UserIdResolver.pyc'>
[2016-06-23 10:22:58,481][1910][139791534593792][DEBUG][privacyidea.lib.resolver:172] Entering get_resolver_config with arguments (u'LDAP_Kerberos',) and keywords {}
[2016-06-23 10:22:58,482][1910][139791534593792][DEBUG][privacyidea.lib.resolver:172] Entering get_resolver_list with arguments () and keywords {'filter_resolver_name': u'LDAP_Kerberos'}
[2016-06-23 10:22:58,486][1910][139791534593792][DEBUG][privacyidea.lib.crypto:172] Entering decryptPassword with arguments (u'0398be624f80f5a7c53b8181eee0f44d:41f08cce12cb2bd47e9ec01cf8510980',) and keywords {}

This really confuses me

Gabriel

KerberosIdResolver.py.gz

gfa...@soundhound.com

unread,
Jun 23, 2016, 2:11:23 PM6/23/16
to privacyidea
My colleague was smart enough to suggest restarting Apache and that solves one problem:
[2016-06-23 10:55:51,499][7380][140457286936320][ERROR][privacyidea.lib.resolver:329] Can not find resolver with name LDAP_Kerberos
[2016-06-23 10:55:51,499][7380][140457286936320][DEBUG][privacyidea.lib.resolver:184] Exiting get_resolver_object with result None
[2016-06-23 10:55:51,499][7380][140457286936320][INFO][privacyidea.lib.user:182] Resolver u'LDAP_Kerberos' not found!

Continuing my efforts

gfa...@soundhound.com

unread,
Jun 23, 2016, 6:43:32 PM6/23/16
to privacyidea
Hi Cornelius,

As far as I can tell, I got it working
I modified KerberosIdResolver.py and config.resolvers.kerberos.html (I attached both of them)
From the browser (https://gfaber-privacyidea-kerberos.sca.melodis.com/validate/check?user=dummy&pass=XXXXXX):
{"jsonrpc": "2.0", "signature": "[Snip]", "detail": {"message": "The user authenticated against his userstore according to policy 'LDAP_Kerberos_passthru'."}, "versionnumber": "2.13dev0", "version": "privacyIDEA 2.13dev0", "result": {"status": true, "value": true}, "time": 1466720792.657061, "id": 1}

And with Radius:
[ro...@privacyidea-kerberos.sca privacyIDEA-kerberos]# echo "User-Name=dummy, User-Password=XXXXXX" | radclient -sx localhost auth testing123
Sending Access-Request Id 229 from 0.0.0.0:35611 to 127.0.0.1:1812
        User-Name = 'dummy'
        User-Password = 'XXXXXX'
Received Access-Accept Id 229 from 127.0.0.1:1812 to 127.0.0.1:35611 length 20
Packet summary:
        Accepted      : 1
        Rejected      : 0
        Lost          : 0
        Passed filter : 1
        Failed filter : 0

If I assign a token, it still works:
https://gfaber-privacyidea-kerberos.sca.melodis.com/validate/check?user=dummy&pass=0000385229
{"jsonrpc": "2.0", "signature": "[Snip]", "detail": {"message": "matching 1 tokens", "type": "totp", "serial": "TOTP000063E8"}, "versionnumber": "2.13dev0", "version": "privacyIDEA 2.13dev0", "result": {"status": true, "value": true}, "time": 1466721577.190234, "id": 1}

And Radius:
[ro...@privacyidea-kerberos.sca privacyIDEA-kerberos]# echo "User-Name=dummy, User-Password=0000285354" | radclient -sx localhost auth testing123
Sending Access-Request Id 230 from 0.0.0.0:54407 to 127.0.0.1:1812
        User-Name = 'dummy'
        User-Password = '0000285354'
Received Access-Accept Id 230 from 127.0.0.1:1812 to 127.0.0.1:54407 length 20
Packet summary:
        Accepted      : 1
        Rejected      : 0
        Lost          : 0
        Passed filter : 1
        Failed filter : 0

I am not sure what you mean by "Then we need to add its own angular js controller and replace this one: setLDAPResolver"

Regards,

Gabriel
config.resolvers.kerberos.html.gz
KerberosIdResolver.py.gz

Cornelius Kölbel

unread,
Jun 24, 2016, 6:12:45 AM6/24/16
to priva...@googlegroups.com
Hi Gabriel,

very cool.

The javascript setLDAPResolver saves the LDAP resolver to the database.
Usually we would have to have another function, that saves a
Kerberos-Resolver. But we avoided this by forcing the resolver type in
the html code.

<button ng-click="params.type='kerberosresolver';
setLDAPResolver()"
ng-disabled="formResolverAddLdap.$invalid"
class="btn btn-primary"
translate>Save resolver
</button>

But I have a basic question.
I fact your users are sill located in the LDAP, aren't they?
The only difference to the LDAP-Resolver is the verification of the
password. We inherited the LDAP-Resolver to define a Kerberos-Resolver.

Which kerberos package are you using? At the moment I am not sure, if
this is a good idea to verify the password. Please read this:
http://seclists.org/oss-sec/2015/q2/514
https://www.calendarserver.org/ticket/833

Anyway: The Kerberos-Resolver still resolves to LDAP, i.e. the users are
found in ldap, the loginname of the user resolves to an LDAP object -
isn't it?

Only the verification of the password differs.
So I think in my opinion it might make more sense to check if we can
enhance the existing LDAP-Resolver and choose within the LDAP-Resolver
the type of password verification being/ Bind type.

At the moment this is:

* simple
* NTLM
* SASL Digest MD5

Could we add

* SASL Kerberos?

This we could use SASL of the ldap3 module, which is already used
anyway.
http://ldap3.readthedocs.io/bind.html#sasl
http://ldap3.readthedocs.io/bind.html#kerberos
This would reduce code and complexity for the administrator.
What do you think?

Kind regards
Cornelius

Am Donnerstag, den 23.06.2016, 15:43 -0700 schrieb
gfa...@soundhound.com:
> --
> Please read the blog post about getting help
> https://www.privacyidea.org/getting-help/.
>
> For professional services and consultancy regarding two factor
> authentication please visit
> https://netknights.it/en/leistungen/one-time-services/
>
> In an enterprise environment you should get a SERVICE LEVEL AGREEMENT
> which suites your needs for SECURITY, AVAILABILITY and LIABILITY:
> https://netknights.it/en/leistungen/service-level-agreements/
> ---
> You received this message because you are subscribed to the Google
> Groups "privacyidea" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to privacyidea...@googlegroups.com.
> To post to this group, send email to priva...@googlegroups.com.
> Visit this group at https://groups.google.com/group/privacyidea.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/privacyidea/271e8399-d1f4-4ea7-9038-c61803b8eee3%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

signature.asc

gfa...@soundhound.com

unread,
Jun 24, 2016, 1:43:34 PM6/24/16
to privacyidea
We use Kerberos because our main (network) file system is AFS
Kerberos is authentication only. It has no provisions for UID/GID/home directory etc, so LDAP provides that to PAM

We're using MIT Kerberos (on CentOS)

Thanks for pointing out the insecurity. It doesn't worry me too much, as our Kerberos infrastructure is totally internal (I.e. we control both ends of the connection)

As far as I can tell, 'SASL Kerberos' will authenticate to the LDAP server with Kerberos, which we don't need currently. As there are no secrets in LDAP, we allow anonymous bind
I think it might make sense as an add-on to LDAP, not as a replacement for KerberosIdResolver

Gabriel

Reply all
Reply to author
Forward
0 new messages