Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
python-module-privacyidea-pam
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Eugene Omelyanovich
python-module-privacyidea-pam
Commits
006bb9dc
Commit
006bb9dc
authored
Feb 12, 2018
by
Cornelius Kölbel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow offline refill
In case of successful offline authentication we try to do an online refill to fill the offline values back to the number of configured OTP values. Closes #6
parent
f20b5df9
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
71 additions
and
6 deletions
+71
-6
privacyidea_pam.py
privacyidea_pam.py
+71
-6
No files found.
privacyidea_pam.py
View file @
006bb9dc
...
...
@@ -82,10 +82,10 @@ class Authenticator(object):
self
.
debug
=
config
.
get
(
"debug"
)
self
.
sqlfile
=
config
.
get
(
"sqlfile"
,
"/etc/privacyidea/pam.sqlite"
)
def
make_request
(
self
,
data
):
def
make_request
(
self
,
data
,
endpoint
=
"/validate/check"
):
# add a user-agent to be displayed in the Client Application Type
headers
=
{
'user-agent'
:
'PAM/2.15.0'
}
response
=
requests
.
post
(
self
.
URL
+
"/validate/check"
,
data
=
data
,
response
=
requests
.
post
(
self
.
URL
+
endpoint
,
data
=
data
,
headers
=
headers
,
verify
=
self
.
sslverify
)
json_response
=
response
.
json
...
...
@@ -95,13 +95,61 @@ class Authenticator(object):
return
json_response
def
offline_refill
(
self
,
serial
,
password
):
# get refilltoken
conn
=
sqlite3
.
connect
(
self
.
sqlfile
)
c
=
conn
.
cursor
()
refilltoken
=
None
# get all possible serial/tokens for a user
for
row
in
c
.
execute
(
"SELECT config_name, config_value FROM config where config_name=?"
,
(
"refilltoken"
,
)):
refilltoken
=
row
[
1
]
syslog
.
syslog
(
"Doing refill with token {0!s}"
.
format
(
refilltoken
))
if
refilltoken
:
data
=
{
"serial"
:
serial
,
"pass"
:
password
,
"refilltoken"
:
refilltoken
}
json_response
=
self
.
make_request
(
data
,
"/validate/offlinerefill"
)
result
=
json_response
.
get
(
"result"
)
auth_item
=
json_response
.
get
(
"auth_items"
)
detail
=
json_response
.
get
(
"detail"
)
or
{}
tokentype
=
detail
.
get
(
"type"
,
"unknown"
)
if
self
.
debug
:
syslog
.
syslog
(
syslog
.
LOG_DEBUG
,
"
%
s: result:
%
s"
%
(
__name__
,
result
))
syslog
.
syslog
(
syslog
.
LOG_DEBUG
,
"
%
s: detail:
%
s"
%
(
__name__
,
detail
))
if
result
.
get
(
"status"
):
if
result
.
get
(
"value"
):
save_auth_item
(
self
.
sqlfile
,
self
.
user
,
serial
,
tokentype
,
auth_item
)
else
:
syslog
.
syslog
(
syslog
.
LOG_ERR
,
"
%
s:
%
s"
%
(
__name__
,
result
.
get
(
"error"
)
.
get
(
"message"
)))
def
authenticate
(
self
,
password
):
rval
=
self
.
pamh
.
PAM_SYSTEM_ERR
# First we try to authenticate against the sqlitedb
if
check_offline_otp
(
self
.
user
,
password
,
self
.
sqlfile
,
window
=
10
):
r
,
serial
=
check_offline_otp
(
self
.
user
,
password
,
self
.
sqlfile
,
window
=
10
)
syslog
.
syslog
(
syslog
.
LOG_DEBUG
,
"offline check returned: {0!s}, {1!s}"
.
format
(
r
,
serial
))
if
r
:
syslog
.
syslog
(
syslog
.
LOG_DEBUG
,
"
%
s: successfully authenticated against offline "
"database
%
s"
%
(
__name__
,
self
.
sqlfile
))
# Try to refill
try
:
r
=
self
.
offline_refill
(
serial
,
password
)
syslog
.
syslog
(
syslog
.
LOG_DEBUG
,
"offline refill returned {0!s}"
.
format
(
r
))
except
Exception
as
e
:
# If the network is not reachable we will not refill.
syslog
.
syslog
(
syslog
.
LOG_DEBUG
,
"failed to refill {0!s}"
.
format
(
e
))
rval
=
self
.
pamh
.
PAM_SUCCESS
else
:
if
self
.
debug
:
...
...
@@ -255,6 +303,7 @@ class Authenticator(object):
return
rval
def
pam_sm_authenticate
(
pamh
,
flags
,
argv
):
config
=
_get_config
(
argv
)
debug
=
config
.
get
(
"debug"
)
...
...
@@ -322,7 +371,7 @@ def pam_sm_chauthtok(pamh, flags, argv):
return
pamh
.
PAM_SUCCESS
def
check_offline_otp
(
user
,
otp
,
sqlfile
,
window
=
10
):
def
check_offline_otp
(
user
,
otp
,
sqlfile
,
window
=
10
,
refill
=
True
):
"""
compare the given otp values with the next hashes of the user.
...
...
@@ -332,7 +381,7 @@ def check_offline_otp(user, otp, sqlfile, window=10):
:param user: The local user in the sql file
:param otp: The otp value
:param sqlfile: The sqlite file
:return: T
rue or False
:return: T
uple of (True or False, serial)
"""
res
=
False
conn
=
sqlite3
.
connect
(
sqlfile
)
...
...
@@ -340,6 +389,7 @@ def check_offline_otp(user, otp, sqlfile, window=10):
_create_table
(
c
)
# get all possible serial/tokens for a user
serials
=
[]
matching_serial
=
None
for
row
in
c
.
execute
(
"SELECT serial, user FROM authitems WHERE user=?"
"GROUP by serial"
,
(
user
,)):
serials
.
append
(
row
[
0
])
...
...
@@ -362,7 +412,7 @@ def check_offline_otp(user, otp, sqlfile, window=10):
(
matching_counter
,
matching_serial
))
conn
.
commit
()
conn
.
close
()
return
res
return
res
,
matching_serial
def
save_auth_item
(
sqlfile
,
user
,
serial
,
tokentype
,
authitem
):
...
...
@@ -400,6 +450,15 @@ def save_auth_item(sqlfile, user, serial, tokentype, authitem):
"tokenowner, otp) VALUES (?,?,?,?,?)"
,
(
counter
,
user
,
serial
,
tokenowner
,
otphash
))
refilltoken
=
offline
.
get
(
"refilltoken"
)
# delete old refilltoken
try
:
c
.
execute
(
'DELETE FROM config where config_name="refilltoken"'
)
except
:
pass
c
.
execute
(
"INSERT INTO config (config_name, config_value) VALUES (?,?)"
,
(
"refilltoken"
,
refilltoken
))
# Save (commit) the changes
conn
.
commit
()
...
...
@@ -420,3 +479,9 @@ def _create_table(c):
except
:
pass
try
:
# create config table
c
.
execute
(
"CREATE TABLE config (config_name text, config_value text)"
)
except
:
pass
Write
Preview
Markdown
is supported
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