42
42
import json
43
43
import requests
44
44
import syslog
45
- import sqlite3
46
45
import passlib .hash
47
46
import time
48
47
import traceback
49
48
import datetime
50
49
import yaml
50
+ import sqlite3
51
+ import mysql .connector
51
52
import re
52
53
54
+ SQLite = True
53
55
54
56
def _get_config (argv ):
55
57
"""
@@ -59,6 +61,7 @@ def _get_config(argv):
59
61
:param argv:
60
62
:return: dictionary with the parameters
61
63
"""
64
+ global SQLite
62
65
config = {}
63
66
argv .pop (0 )
64
67
if len (argv ) == 1 and "config_file" in argv [0 ]:
@@ -78,20 +81,17 @@ def _get_config(argv):
78
81
config ["users" ] = []
79
82
# SQL Connection type/default
80
83
if config .get ("mysql" ) is not None :
84
+ SQLite = False
81
85
mysql_settings = re .match ("mysql://([^:]+):([^@]+)@([^:/]+):([0-9]+)/(.+)" , config .get ("mysql" ))
82
86
config ["sql" ] = {
83
- 'lite' : False ,
84
87
'user' : mysql_settings .group (1 ),
85
88
'password' : mysql_settings .group (2 ),
86
89
'host' : mysql_settings .group (3 ),
87
90
'port' : mysql_settings .group (4 ),
88
91
'database' : mysql_settings .group (5 )
89
92
}
90
93
else :
91
- config ["sql" ] = {
92
- 'lite' : True ,
93
- 'file' : config .get ("sqlfile" , "/etc/privacyidea/pam.sqlite" )
94
- }
94
+ config ["sql" ] = config .get ("sqlfile" , "/etc/privacyidea/pam.sqlite" )
95
95
return config
96
96
97
97
@@ -246,10 +246,12 @@ def offline_refill(self, serial, password):
246
246
startdb (self .sql )
247
247
refilltoken = None
248
248
# get all possible serial/tokens for a user
249
- for row in c .execute ("SELECT refilltoken FROM refilltokens WHERE serial=?" ,
250
- (serial , )):
249
+ c .execute (sql_abstract ("SELECT refilltoken FROM refilltokens WHERE serial=?" ),
250
+ (serial , ))
251
+ for row in c .fetchall ():
251
252
refilltoken = row [0 ]
252
253
syslog .syslog ("Doing refill with token {0!s}" .format (refilltoken ))
254
+
253
255
closedb ()
254
256
255
257
if refilltoken :
@@ -484,7 +486,6 @@ def pam_sm_authenticate(pamh, flags, argv):
484
486
return pamh .PAM_AUTHINFO_UNAVAIL
485
487
486
488
try :
487
-
488
489
if grace_time is not None :
489
490
syslog .syslog (syslog .LOG_DEBUG ,
490
491
"Grace period in minutes: %s " % (str (grace_time )))
@@ -494,7 +495,6 @@ def pam_sm_authenticate(pamh, flags, argv):
494
495
rval = pamh .PAM_SUCCESS
495
496
496
497
if rval != pamh .PAM_SUCCESS :
497
-
498
498
# Check if user has tokens
499
499
Auth .check_user_tokens (Auth .user )
500
500
@@ -571,15 +571,18 @@ def check_offline_otp(sql_params, user, otp, window=10, refill=True):
571
571
# get all possible serial/tokens for a user
572
572
serials = []
573
573
matching_serial = None
574
- for row in c .execute ("SELECT serial, user FROM authitems WHERE user=?"
575
- "GROUP by serial" , (user ,)):
574
+
575
+ c .execute (sql_abstract ("SELECT serial, user FROM authitems WHERE user=?"
576
+ "GROUP by serial" ), (user ,))
577
+ for row in c .fetchall ():
576
578
serials .append (row [0 ])
577
579
578
580
for serial in serials :
579
- for row in c .execute ("SELECT counter, user, otp, serial FROM authitems "
581
+ c .execute ( sql_abstract ("SELECT counter, user, otp, serial FROM authitems "
580
582
"WHERE user=? and serial=? ORDER by counter "
581
- "LIMIT ?" ,
582
- (user , serial , window )):
583
+ "LIMIT ?" ),
584
+ (user , serial , window ))
585
+ for row in c .fetchall ():
583
586
hash_value = row [2 ]
584
587
if passlib .hash .pbkdf2_sha512 .verify (otp , hash_value ):
585
588
res = True
@@ -589,7 +592,7 @@ def check_offline_otp(sql_params, user, otp, window=10, refill=True):
589
592
590
593
# We found a matching password, so we remove the old entries
591
594
if res :
592
- c .execute ("DELETE from authitems WHERE counter <= ? and serial = ?" ,
595
+ c .execute (sql_abstract ( "DELETE from authitems WHERE counter <= ? and serial = ?" ) ,
593
596
(matching_counter , matching_serial ))
594
597
595
598
closedb ()
@@ -624,17 +627,17 @@ def save_auth_item(sql_params, user, serial, tokentype, authitem):
624
627
tokenowner = offline .get ("username" )
625
628
for counter , otphash in offline .get ("response" ).items ():
626
629
# Insert the OTP hash
627
- c .execute ("INSERT INTO authitems (counter, user, serial,"
628
- "tokenowner, otp) VALUES (?,?,?,?,?)" ,
630
+ c .execute (sql_abstract ( "INSERT INTO authitems (counter, user, serial,"
631
+ "tokenowner, otp) VALUES (?,?,?,?,?)" ) ,
629
632
(counter , user , serial , tokenowner , otphash ))
630
633
631
634
refilltoken = offline .get ("refilltoken" )
632
635
# delete old refilltoken
633
636
try :
634
- c .execute (' DELETE FROM refilltokens WHERE serial=?' , (serial ,))
637
+ c .execute (sql_abstract ( " DELETE FROM refilltokens WHERE serial=?" ) , (serial ,))
635
638
except sqlite3 .OperationalError :
636
639
pass
637
- c .execute ("INSERT INTO refilltokens (serial, refilltoken) VALUES (?,?)" ,
640
+ c .execute (sql_abstract ( "INSERT INTO refilltokens (serial, refilltoken) VALUES (?,?)" ) ,
638
641
(serial , refilltoken ))
639
642
640
643
closedb ()
@@ -660,11 +663,12 @@ def check_last_history(sql_params, user, rhost, grace_time, window=10):
660
663
res = False
661
664
events = []
662
665
663
- for row in c .execute ("SELECT user, rhost, serial, last_success, last_error "
666
+ c .execute ( sql_abstract ("SELECT user, rhost, serial, last_success, last_error "
664
667
"FROM history "
665
668
"WHERE user=? AND rhost=? ORDER by last_success "
666
- "LIMIT ?" ,
667
- (user , rhost , window )):
669
+ "LIMIT ?" ),
670
+ (user , rhost , window ))
671
+ for row in c .fetchall ():
668
672
events .append (row )
669
673
670
674
if len (events )> 0 :
@@ -714,37 +718,35 @@ def save_history_item(sql_params, user, rhost, serial, success):
714
718
__name__ , ("success" if success else "error" )))
715
719
if success :
716
720
# Insert the Event
717
- c .execute ("INSERT OR REPLACE INTO history (user, rhost, serial,"
718
- "error_counter, last_success) VALUES (?,?,?,?,?)" ,
721
+ c .execute (sql_abstract ( " REPLACE INTO history (user, rhost, serial,"
722
+ "error_counter, last_success) VALUES (?,?,?,?,?)" ) ,
719
723
(user , rhost , serial , 0 , datetime .datetime .now ()))
720
724
else :
721
725
# Insert the Event
722
- c .execute ("UPDATE history SET error_counter = error_counter + 1, "
726
+ c .execute (sql_abstract ( "UPDATE history SET error_counter = error_counter + 1, "
723
727
" serial = ? , last_error = ? "
724
- " WHERE user = ? AND rhost = ? " ,
728
+ " WHERE user = ? AND rhost = ? " ) ,
725
729
(serial , datetime .datetime .now (), user , rhost ))
726
730
727
731
syslog .syslog (syslog .LOG_DEBUG ,"Rows affected : %d " % c .rowcount )
728
732
if c .rowcount == 0 :
729
- c .execute ("INSERT INTO history (user, rhost, serial,"
730
- "error_counter, last_error) VALUES (?,?,?,?,?)" ,
733
+ c .execute (sql_abstract ( "INSERT INTO history (user, rhost, serial,"
734
+ "error_counter, last_error) VALUES (?,?,?,?,?)" ) ,
731
735
(user , rhost , serial , 1 , datetime .datetime .now ()))
732
736
733
737
closedb ()
734
738
735
-
736
739
# Start connection and create cursor
737
740
def startdb (sql_params ):
738
741
global conn , c
739
742
# Create connection
740
- if sql_params ["lite" ]:
741
- conn = sqlite3 .connect (sql_params ["file" ], detect_types = sqlite3 .PARSE_DECLTYPES )
742
- # Create a cursor object
743
- c = conn .cursor ()
743
+ if SQLite :
744
+ conn = sqlite3 .connect (sql_params , detect_types = sqlite3 .PARSE_DECLTYPES )
744
745
else :
745
- print ("Mysql" )
746
- # mysql.connector.connect(**connection_config_dict)
746
+ conn = mysql .connector .connect (** sql_params )
747
747
748
+ # Create a cursor object
749
+ c = conn .cursor ()
748
750
# Create table if does not exist
749
751
_create_table ()
750
752
@@ -767,7 +769,26 @@ def _create_table():
767
769
c .execute ("CREATE TABLE IF NOT EXISTS refilltokens (serial text, refilltoken text)" )
768
770
# create history table
769
771
c .execute ("CREATE TABLE IF NOT EXISTS history "
770
- "(user text , rhost text , serial text, error_counter int, "
772
+ "(user varchar(50) , rhost varchar(50) , serial text, error_counter int, "
771
773
"last_success timestamp, last_error timestamp)" )
772
- c .execute ("CREATE UNIQUE INDEX idx_user "
773
- "ON history (user, rhost);" )
774
+ try :
775
+ # create history table
776
+ c .execute ("CREATE TABLE IF NOT EXISTS history "
777
+ "(user text, rhost text, serial text, error_counter int, "
778
+ "last_success timestamp, last_error timestamp)" )
779
+ c .execute ("CREATE UNIQUE INDEX idx_user "
780
+ "ON history (user, rhost);" )
781
+ except mysql .connector .Error as err :
782
+ if err .errno == mysql .connector .errorcode .ER_DUP_KEYNAME :
783
+ pass
784
+ else :
785
+ raise
786
+ except sqlite3 .OperationalError :
787
+ pass
788
+
789
+ # Convert an SQLite statement to MySQL
790
+ def sql_abstract (sql_statement ):
791
+ if SQLite :
792
+ return sql_statement
793
+ else :
794
+ return sql_statement .replace ('?' ,'%s' )
0 commit comments