PAM Authentication on CentOS 6.5

1,049 views
Skip to first unread message

dadri...@googlemail.com

unread,
Mar 6, 2014, 10:15:55 AM3/6/14
to lin...@googlegroups.com
I'm currently testing the CE of LinOTP 2.6.0.3 on a machine that is running CentOS 6.5. I got it so far now that I can install tokens and they are verified by LinOTP when I use the web UI to validate them.

Now my next step was to add the PAM authentication module to the machine. I compiled it following the instructions on the LinOTP site and it did compile without error. But now that I'm trying to use the PAM LinOTP module for authentication with ssh I get the following errors in my log:

Mar 6 14:16:12 <My Server> sshd[16050]: PAM unable to dlopen(/lib64/security/pam_linotp.so): /lib64/libc.so.6: version `GLIBC_2.14' not found (required by /lib64/security/pam_linotp.so)
Mar 6 14:16:12 <My Server> sshd[16050]: PAM adding faulty module: /lib64/security/pam_linotp.so

I checked the repositories for CentOS 6.5 and they only provide the glibc version 2.12. Is there any way to get the PAM module running with that glibc version? Changing the glibc is not an option since I'm not allowed to upgrade that.

winkl...@gmail.com

unread,
Mar 6, 2014, 10:36:58 AM3/6/14
to lin...@googlegroups.com, dadri...@googlemail.com
Hi,

if you want to try, there is another option:
you can use the python module

pam_linotp.py

Though the one pypi is not the actual one due
to an packaging error :-(.

So I will attach it now - installation instruction
in the header

<pre>
'''
###############################################################################
# LinOTP authentication pam module - for usage under libpam-python
###############################################################################
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#
# Copyright 2013 linotp project <lin...@lsexperts.de>

Installation:
=============
Install this file in the directory:
/lib/security/

and setup a file:
/etc/pam.d/common-linotp

with this component:

---8<------8<------8<------8<------8<------8<------8<------8<------8<------8<--
## here are the per-package modules (the "Primary" block)
auth [success=1 default=ignore] pam_python.so /lib/security/pam_linotp.py \
debug url=https://localhost/validate/simplecheck

--->8------>8------>8------>8------>8------>8------>8------>8------>8------>8--
- compare to common auth and use it in the pam services.

Test:
=====

For test purpose, you can extend the /etc/pam.d/loggin by replacing the
common-auth:

# Standard Un*x authentication.
#@include common-auth
@include common-linotp

and start a "login user" from a root shell

Module Parameters:
==================

Paramters to the module are:

:param debug: display security relevant information in the syslog - critical -
:param utrl=: the LinOTP verification url
:param realm: the users LinOTP realm, which is requrired, if the user is not
in the default realm
:param prompt: the first password propmt (_ will be replaced with whitespaces)


Happy Authenticating!

'''

import syslog
import urllib
import urllib2
import pwd

LINOTP_FAIL = ":-/"
LINOTP_OK = ":-)"
LINOTP_REJECT = ":-("

def get_config( argv ):
'''
parse the module arguments and put them in a config dict

:param argv: array of arguments from the config file
:return: config dict
'''

config = {}
config["url"] = "https://localhost/validate/simplecheck"
config["prompt"] = "Your OTP:"
config["debug"] = False

# split the config parameters
if "debug" in argv:
config["debug"] = True

# parse parameter
for arg in argv:

if arg.startswith( "url=" ):
config["url"] = arg[len( "url=" ):]

if arg.startswith( "realm=" ):
config["realm"] = arg[len( "realm=" ):]

if arg.startswith( "prompt=" ):
prompt = arg[len( "prompt=" ):]
config["prompt"] = prompt.replace( "_", " " )

return config

def pam_sm_authenticate( pamh, flags, argv ):
'''
callback for the pam authentication

:param pamh: pam context handle
:param flags: ?? - unknown to me
:param argv: configuration arguments
'''

syslog.openlog( "pam_linotp", syslog.LOG_PID, syslog.LOG_AUTH )
result = pamh.PAM_AUTH_ERR

try:
config = get_config( argv )
debug = config.get( 'debug', False )
url = config.get( 'url', 'https://localhost/validate/simplecheck' )

if debug:
syslog.syslog( "start pam_linotp.py authentication: %s, %s" %
( flags, argv ) )

#log_debug("got user %s", user);
try:
pwd.getpwnam( pamh.user )
except KeyError:
return pamh.PAM_USER_UNKNOWN


## get the password of the user:
## either from the pam handle or request this
if pamh.authtok == None:
if debug:
syslog.syslog( "got no password in authtok - "
"trying through conversation" )
msg = pamh.Message( pamh.PAM_PROMPT_ECHO_OFF, config.get( 'prompt',
"[LinOTP] Password" ) )
rsp = pamh.conversation( msg )
pamh.authtok = rsp.resp

if debug:
syslog.syslog( "got password: " + pamh.authtok )

#
# check pamh.authtok against LinOTP with pamh.user and pamh.authtok
params = {}
params["user"] = pamh.user
params["pass"] = pamh.authtok

if config.has_key( "realm" ):
params["realm"] = config.get( "realm" )

if debug:
syslog.syslog( syslog.LOG_INFO, "calling url %s %r" %
( url, params ) )

data = urllib.urlencode( params )
req = urllib2.Request( url, data )

response = urllib2.urlopen( req )
ret = response.read()

if debug:
syslog.syslog( ret )

result = check_response( pamh, ret, pamh.user, config )

except Exception as exept:
syslog.syslog( "Error: %r" % exept )

finally:
syslog.closelog()

return result


def check_response( pamh, ret, user, config ):
"""
analyse the LinOTP result and return the corresponding return codes

:param pamh: the pam request handle
:param ret: the response of a former LinOTP request
:param user: the requesting user
:param config: the module configuration for accessin 'debug' or url

:return: pamh.PAM_AUTH_ERR or pamh.PAM_SUCCESS
"""

result = pamh.PAM_AUTH_ERR

## access failed - error report from LinOTP
if ret == LINOTP_FAIL:
syslog.syslog( syslog.LOG_INFO, "user failed to authenticate" )
result = pamh.PAM_AUTH_ERR

## access accepted
elif ret == LINOTP_OK:
syslog.syslog( syslog.LOG_INFO, "user successfully authenticated" )
result = pamh.PAM_SUCCESS

## access rejected
elif ret == LINOTP_REJECT:
syslog.syslog( syslog.LOG_INFO, "user rejected" )
result = pamh.PAM_AUTH_ERR

## challenge mode
elif len( ret ) > len( LINOTP_REJECT ) and ret.startswith( LINOTP_REJECT ):
syslog.syslog( "in challenge mode" )
parts = ret.split( ' ' )
challenge = "Otp: "
state = ""

if len( parts ) > 1:
state = parts[1]

if len( parts ) > 2:
del parts[0]
del parts[0]
challenge = " ".join( parts )

msg = pamh.Message( pamh.PAM_PROMPT_ECHO_OFF, challenge )
rsp = pamh.conversation( msg )
pamh.authtok = rsp.resp

syslog.syslog( "submitting response of challenge" )

## now redo the simplecheck
params = {}
params["user"] = user

params['pass'] = rsp.resp
params['state'] = state

data = urllib.urlencode( params )
req = urllib2.Request( config.get( 'url' ), data )

response = urllib2.urlopen( req )
ret = response.read()

if config.get( 'debug' ):
syslog.syslog( "challenge returned %s " % ret )

result = check_response( pamh, ret, user, config )

else:
syslog.syslog( syslog.LOG_INFO, "user failed to authenticate" )
result = pamh.PAM_AUTH_ERR


return result


def pam_sm_setcred( pamh, flags, argv ):
""" pam_sm_setcred """
syslog.syslog( syslog.LOG_INFO,
"Please note: pam_linotp does not support setcred" )
return pamh.PAM_CRED_UNAVAIL

def pam_sm_acct_mgmt( pamh, flags, argv ):
""" pam_sm_acct_mgmt """
syslog.syslog( syslog.LOG_INFO,
"Please note: pam_linotp does not support acct_mgmt" )
return pamh.PAM_SERVICE_ERR

def pam_sm_chauthtok( pamh, flags, argv ):
""" pam_sm_chauthtok """
syslog.syslog( syslog.LOG_INFO,
"Please note: pam_linotp does not support chauthtok" )
return pamh.PAM_SERVICE_ERR

def pam_sm_open_session( pamh, flags, argv ):
""" pam_sm_open_session """
syslog.syslog( syslog.LOG_INFO,
"Please note: pam_linotp does not support open_session" )
return pamh.PAM_SERVICE_ERR

def pam_sm_close_session( pamh, flags, argv ):
""" pam_sm_close_session """
syslog.syslog( syslog.LOG_INFO,
"Please note: pam_linotp does not support close_session" )
return pamh.PAM_SERVICE_ERR

##eof##########################################################################
</pre>

Cornelius

unread,
Mar 6, 2014, 10:57:50 AM3/6/14
to lin...@googlegroups.com
Hi,

could this be a remnant of the downloaded package?
I checked that there is an old build that contains GLIBC_2.14 in the
http://linotp.org/download/src/LinOTP-2.6-CE.tar.gz.
Which package did you download?

Please follow the steps in INSTALL.txt and do a "make clean" and asure
that there are no files left that contain GLIBC_2.14.

Kind regards
Cornelius

dadri...@googlemail.com

unread,
Mar 7, 2014, 5:36:53 AM3/7/14
to lin...@googlegroups.com
Yes, I did use the sources from the package you mentioned to compile the PAM module since it was the most recent package that I could find on the website. Is there another version that is more recent and does not have the dependency on the version 2.14? Because even after a new compile with a make clean before the compile did not solve the dependency.

Else I'm going to try and see if the Python module can work for me.

Cornelius Kölbel

unread,
Mar 7, 2014, 6:49:49 AM3/7/14
to lin...@googlegroups.com
Hi something goes defenitively wrong!
I just build the lib on a centos 6.5 and it contained GLIBC_2.2.5.
After "make clean" is there the file ./src/.libs/pam_linotp.so available?
Delete it.

For what its worth - I attached evily the so that I built on my centos
6.5 64bit.
It worked out for me after I disabled SELinux. I did not bother to
reconfigure it.

Kind regards
Cornelius

pam_linotp.so

dadri...@googlemail.com

unread,
Mar 7, 2014, 8:48:26 AM3/7/14
to lin...@googlegroups.com, co...@cornelinux.de
I got it working now after manually checking that there was no old pam_linotp.so left in the directory you specified :)

Now if you don't mind I got one other questions that I could not find a definitive answer in the documentation to. I want my users to be able to enroll their tokens by themself using the self service portal. Since I'm using the CE I can only use flatfile for the user ID resolver. Now I don't know how to combine these two, because when I enter the /etc/passwd file for the useridresolver in the management web UI I can't login in with my users on the machine.

Cornelius Kölbel

unread,
Mar 7, 2014, 8:55:06 AM3/7/14
to dadri...@googlemail.com, lin...@googlegroups.com
Am 07.03.2014 14:48, schrieb dadri...@googlemail.com:
> I got it working now after manually checking that there was no old pam_linotp.so left in the directory you specified :)
>
> Now if you don't mind I got one other questions that I could not find a definitive answer in the documentation to. I want my users to be able to enroll their tokens by themself using the self service portal. Since I'm using the CE I can only use flatfile for the user ID resolver. Now I don't know how to combine these two, because when I enter the /etc/passwd file for the useridresolver in the management web UI I can't login in with my users on the machine.
The etc/passwd does not contain a password!
And you need a password in the user source to login to selfservice.

So you can create a new flat file using the tool

linotp-create-passwd.... (i do not know exactly)

Create a new file containing the users and the passwords (alas - you
know the passwords).
Use this file in the resolver.
And the users will be able to log in to selfservice and tokens can be
assigned to users.

Voila.

Kind regards
Cornelius
Reply all
Reply to author
Forward
0 new messages