· 8 years ago · Apr 11, 2018, 05:56 AM
1## ------------------------------------------------------------------------------------------------------------------------------
2import re
3import sqlite3
4#import mysqldb
5import sys
6
7import getpass
8
9try:
10 conn = sqlite3.connect('userpass.db')
11except:
12 print ("Cannot Find Any DB")
13 exit()
14c = conn.cursor()
15
16##### NOTE
17##### First Time Users Uncomment the next two lines, until I make a feature rich installer
18#c.execute('''CREATE TABLE if not exists userpass(user text, pass text)''')
19#c.execute('''CREATE TABLE if not exixts p_history(user text, pass text)''')
20
21### NOTE (Sankrant):
22## This is my first time working with a structured database, I still do not know the left join correctly. So here you have it,
23## two redundant tables to solve the triple password problem. A better design would be to make a primary key linked with the user
24## on the first table, and use that key instead
25
26## This is also a nightmare in security practice according to some database guys
27## I should have created another secure storage for passwords doing some magic fu linking. Will come back to it later
28
29## TODO (Sankrant): maybe hide the password entry by ****
30
31## -------------------------------------------------------------------------------------------------------------------------------
32
33
34def add_user():
35 username = input("Please Enter Username: ")
36 if user_exists(username) == 1:
37 print ("User Already Exists")
38 exit()
39 if check_user(username) == -1:
40 print("Wrong Format: Please check formating by typing help as argument")
41 exit()
42 try:
43 c.execute("INSERT INTO userpass VALUES (?, '')", (username,))
44 print ("User Added")
45 except:
46 print("The database query did not work")
47 comDB()
48
49## Sometimes Regex is too complex to put your head around
50## Good old C style coding
51
52def issym(ch):
53 if (ch == '!' or ch == '@' or ch == '#' or ch == '$' or ch == '%' or ch == '^' or ch == '&' or ch == '*' or ch == '(' or ch == ')' or ch == '-' or ch == '=' or ch == '+' or ch == '[' or ch == ']' or ch == '{' or ch == '}' or ch == '<' or ch == '>' or ch == '.' or ch == '?' or ch == ':' or ch == '|' or ch == '\\' or ch == '/' or ch == '`' or ch == '~'):
54 return True;
55 else:
56 return False
57
58def check_7(password):
59 for ind,ch in enumerate(password[:-2]):
60 if ch.isupper() and password[ind+1].isupper() and password[ind+2].isupper():
61 return -1
62 elif ch.islower() and password[ind+1].islower() and password[ind+2].islower():
63 return -2
64 elif ch.isdigit() and password[ind+1].isdigit() and password[ind+2].isdigit():
65 return -3
66 elif issym(ch) and issym(password[ind+1]) and issym(password[ind+2]):
67 return -4
68 return 0
69
70
71def add_pass(username):
72 password = input("Enter Password: ")
73 check_password_count(username, password)
74 if pass_check(password) == -1:
75 print ("Follow the Password Rules")
76 exit()
77 elif pass_check(password) == 0:
78 password_re = input("Retype Password: ")
79 if (password == password_re):
80 try:
81 c.execute("INSERT INTO p_history VALUES (?, ?)", (username, password))
82 c.execute("UPDATE userpass SET pass = ? WHERE user = ?", (password, username))
83 except:
84 print("Cant Connect to DB")
85 exit()
86 comDB()
87 print ("Password Added for User")
88 else:
89 print ("The passwords do not match")
90 exit()
91
92def CLIHelp():
93 print (
94 '''
95 Usage : python zdbdemo.py [option] [arg]
96
97 Options
98 --------
99 useradd : Prompts for adding a Username to the database with an empty password
100
101 passwd : Add a Strong Password and take Username as an argument
102
103 help : Display help
104
105 '''
106 )
107
108def Help():
109 print('''
110
111 User Rules
112 ----------
113
114A) To create new user :
115
116 program_name useradd
117
118 If the user does not exist, it will create a user and then prompt for a password for the user ( the password complexity is defined below ). This user will be stored in a DB or Flat file .
119 If the username exists, it will fail letting the user know that the user already exists.
120 The username can contain only _ or . As special character and nothing else .
121 The username should not be greater than 10 characters.
122 The username should not start with a number .
123
124B) To change password :
125
126 program_name passwd $username
127
128 The password check will be as below :
129
130 The password length should be more than 8 characters.
131 The password length should be less than 15 characters.
132 The password should have atleast one [a-z] ( class 1)
133 The password should have atleast one [0-9] ( class 2)
134 The password should have at least one special character ( class 3 )
135 The password should not have characters /, ~, ` .
136 One cannot have more than two same class characters adjacent to each other .
137 One cannot use the same password which he/she has used in the past three times . Which means you will have to store the username and corresponding password either in some DB or you can even use a flat file and maintain a history of 3 for each user .
138 The password should be entered twice and matched .
139
140
141 ''')
142
143## HELPER FUNCTIONS
144## ----------------------------------------------------------------------------------------------------------------------------------
145
146def purgeOldTable():
147 #if __counterCheck__() == 1:
148 c.execute("DELETE FROM p_history")
149
150def pass_exists(username, password):
151 c.execute("Select count(pass) from p_history where user=? and pass=?", (username, password))
152 asdf = c.fetchone()[0]
153 c.execute("Select count(pass) from p_history where user=?", (username, ))
154
155 ## TODO(Sankrant): Checking this stuff without pdb is frustating, do some debug
156
157 ## TODO(Sankrant): Encapsulate all of this in clean functions
158
159 qwer = c.fetchone()[0]
160 if (qwer >= 3):
161 purgeOldTable()
162 if (asdf >= 1):
163 return 1
164 else:
165 return 0
166
167def username_exists(password):
168 try:
169 fetch2 = c.execute("select user from p_history where pass=?", (pass_exists(username, password))).fetchone()[0]
170 return fetch2
171 except:
172 return 0
173
174def user_exists(username):
175 try:
176 c.execute('''SELECT user FROM userpass WHERE user=?''', (username,))
177 except:
178 print("Can not execute query")
179 exit()
180 exists = c.fetchall()
181 if exists:
182 return 1
183
184def pass_check(password):
185 ## TODO (Sankrant): Regular Expressions can be executed in a more elegant manner?????
186 if (len(password) < 8 and len(password) > 15):
187 flag = -1
188 elif not re.search("[a-z]", password):
189 flag = -1
190 elif not re.search("[A-Z]", password):
191 flag = -1
192 elif not re.search("[0-9]", password):
193 flag = -1
194 elif not re.search("[_@$!#$%^&*()\\\]", password):
195 flag = -1
196 elif re.search("[/~`]", password):
197 flag = -1
198 elif check_7(password) != 0:
199 flag = -1
200 else:
201 flag = 0
202
203 return flag
204
205def check_user(username):
206 if (len(username) > 10):
207 flag = -1
208 elif re.search("[_.]", username):
209 flag = -1
210 else:
211 flag = 1
212 return flag
213
214def check_password_count(username, password):
215
216 if pass_exists(username, password) == 1:
217 print("Please Enter Another Password as this has been used before")
218 exit()
219
220def comDB():
221 conn.commit()
222
223def do_nothing():
224 return
225
226
227## -------------------------------------------------------------------------------------------------------------------------------------------
228## MAIN
229## DONE (Sankrant): It is trivial to do the entry point function now, I might do it before the final show
230
231def main():
232 if(sys.argv[0] == "zdbdemo.py"):
233 CLIHelp()
234
235 if(sys.argv[1] == "useradd"):
236 add_user()
237
238 elif(sys.argv[1] == "useradd" and sys.argv[2] == "-p"):
239 add_user()
240 add_pass(username)
241
242 elif(sys.argv[1] == "passwd" and sys.argv[2]):
243 if (user_exists(sys.argv[2])):
244 add_pass(sys.argv[2])
245 else:
246 print("No user by the name of %s", %(sys.argv[2]))
247 elif(sys.argv[1] == "help"):
248 Help()
249
250 else:
251 do_nothing()
252
253
254if __name__ == "__main__":
255 main()