source: internals/2016/linuxloginsmartcardwizard/trunk/project1/config.py @ 16364

Last change on this file since 16364 was 16364, checked in by dcorreia, 4 years ago

Added reset to default configuration feature

File size: 9.4 KB
Line 
1#!/usr/bin/python3
2import os
3import subprocess
4import sys
5import shutil
6import inspect
7
8
9INSTALL_COMMAND = "apt-get install "        # Package installation
10HASHLINK_COMMAND = "pkcs11_make_hash_link"  # PKCS11 hash links creation
11WGET_COMMAND = "wget "                      # Download file with wget
12GUNZIP_COMMAND = "gunzip "                  # Extract zipped files with gunzip
13MV_COMMAND = "mv "                          # Move/Rename file
14INSPECT_COMMAND = "pkcs11_inspect"          # PKCS11 inspect card data
15COMMONAUTH = "/etc/pam.d/common-auth"       # PAM file with authentication configurations
16TRASH_OUTPUT = open(os.devnull, "wb")       # Send output to trash file
17TEMP_OUTPUT = "/tmp/cardData"               # Send output to temporary file
18USEMODULE_OPTION = "use_pkcs11_module"      # Configuration option to choose the active module
19USEMAPPERS_OPTION = "use_mappers"           # Configuration option to choose the active mappers
20# PKCS11 update for common-auth
21PKCS11AUTH = "auth\tsufficient\tpam_pkcs11.so config_file=/etc/pam_pkcs11/pam_pkcs11.conf"
22BACKUP_DIRPATH = "/tmp/backup_pam.d"
23REMOVEFILES_COMMAND = "rm "
24REMOVEDIRS_COMMAND = "rm -r "
25
26
27def executeCommand(command, outputPath=None):
28    """
29    Executes a shell command and redirects output (optional)
30    :param command: command to execute
31    :param outputPath: path to redirect output (optional)
32    :return: no return value
33    """
34    try:
35        process = subprocess.Popen(command, shell=True, stdout=outputPath, stderr=subprocess.PIPE)
36        process.wait()
37        print("DEBUG: executeCommand (%s) - %s" % (command, process.stderr.read()), file=sys.stderr)
38    except subprocess.CalledProcessError as error:
39        print("DEBUG: executeCommand (%s) - %s" % (command, error), file=sys.stderr)
40
41
42def executeCommandInDirectory(command, directoryPath, outputPath=None):
43    """
44    Executes a shell command in a specific directory and redirects output (optional)
45    :param command: command to execute
46    :param directoryPath: path of the directory
47    :param outputPath: path to redirect output (optional)
48    :return: no return value
49    """
50    oldDirectory = os.getcwd()
51    os.chdir(directoryPath)
52    executeCommand(command, outputPath)
53    os.chdir(oldDirectory)
54
55
56def printDebugInfo(debugData):
57    """
58    Prints debug information
59    :param debugData: string of debug data
60    :return: no return value
61    """
62    print("DEBUG: %s - %s" % (inspect.stack()[1][3], debugData), file=sys.stderr)
63
64
65def installPackage(packageName):
66    """
67    Installs package using apt-get
68    :param packageName: name of the package
69    :return: no return value
70    """
71    executeCommand(INSTALL_COMMAND+packageName, TRASH_OUTPUT)
72
73
74def makeDirectory(directoryPath):
75    """
76    Creates a new directory
77    :param directoryPath: path of the new directory
78    :return: no return value
79    """
80    try:
81        os.mkdir(directoryPath)
82        printDebugInfo("created directory with path "+directoryPath)
83    except OSError as error:
84        printDebugInfo(error)
85
86
87def copyFileToDirectory(filePath, directoryPath):
88    """
89    Copy a file to a directory
90    :param filePath: path of the file to copy
91    :param directoryPath: path of the directory
92    :return: no return value
93    """
94    try:
95        shutil.copy2(filePath, directoryPath)
96    except FileNotFoundError as error:
97        printDebugInfo(error)
98
99
100def readFileToList(filePath):
101    """
102    Reads the file and returns a list with the content
103    :param filePath: path of the file
104    :return: list of strings with content of the file
105    """
106    return open(filePath, mode="r").readlines()
107
108
109def readFileToString(filePath):
110    """
111    Reads a file and returns a string with the content
112    :param filePath: path of the file
113    :return: string of content of the file
114    """
115    return "".join(readFileToList(filePath))
116
117
118def writeStringToFile(filePath, stringData):
119    """
120    Writes input string in the file
121    :param filePath: path of the file
122    :param stringData: string to write
123    :return: no return value
124    """
125    open(filePath, mode="w").write(stringData)
126
127
128def writeListToFile(filePath, listData):
129    """
130    Write input list of data in the file
131    :param filePath: path of the file
132    :param listData: list of data to write
133    :return: no return value
134    """
135    writeStringToFile(filePath, "".join(listData))
136
137
138def appendStringToFile(filePath, stringData):
139    """
140    Append input string to the end of the file
141    :param filePath: path of the file
142    :param stringData: string of data to write
143    :return: no return value
144    """
145    open(filePath, mode="a").write(stringData)
146
147
148def makeHashLinks(directoryPath):
149    """
150    Make pkcs11 hash links in a directory
151    :param directoryPath: path of directory
152    :return: no return value
153    """
154    executeCommandInDirectory(HASHLINK_COMMAND, directoryPath)
155
156
157def getCRLFile(crlWebLink, directoryPath):
158    """
159    Download crl file into a directory
160    :param crlWebLink: link of the crl file
161    :param directoryPath: path of the directory
162    :return: no return value
163    """
164    executeCommandInDirectory(WGET_COMMAND+crlWebLink, directoryPath)
165
166
167def makeConfigFile(configZipPath, configPath, directoryPath):
168    """
169    Make pam_pkcs11.conf configuration file
170    :param configZipPath: path of the configuration file example zip archive
171    :param configPath: path to store the configuration file
172    :param directoryPath: path of the directory for shell commands execution
173    :return: no return value
174    """
175    copyFileToDirectory(configZipPath, directoryPath)
176    executeCommandInDirectory(GUNZIP_COMMAND+"pam_pkcs11.conf.example.gz", directoryPath)
177    executeCommandInDirectory(MV_COMMAND+"pam_pkcs11.conf.example "+configPath, directoryPath)
178
179
180def addConfigModule(moduleFileName, configPath):
181    """
182    Add a configuration module to the pam_pkcs11.conf configuration file
183    :param moduleFileName: name of the module data file
184    :param configPath: path of the configuration file
185    :return: no return value
186    """
187    configData = readFileToList(configPath)
188    configData[-1] = readFileToString(moduleFileName) + "\n" + configData[-1]
189    writeListToFile(configPath, configData)
190
191
192def getIndexOfToken(token, listData):
193    """
194    Gets index of list element that contains the input token
195    :param token: token to find
196    :param listData: list of data
197    :return: index where the token was found
198    """
199    for i in range(0, len(listData)):
200        if token in listData[i]:
201            return i
202
203
204def setConfigurationOption(option, newValue, configPath):
205    """
206    Sets value of a configuration option
207    :param option: the configuration option
208    :param newValue: the new value to be set
209    :param configPath: path of the configuration file
210    :return: no return value
211    """
212    configData = readFileToList(configPath)
213    moduleIndex = getIndexOfToken(option, configData)
214    configData[moduleIndex] = "  " + option + " = " + newValue + ";\n"
215    writeListToFile(configPath, configData)
216
217
218def changeUseModule(newModule, configPath):
219    """
220    Changes module of the use_pkcs11_module configuration option
221    :param newModule: new module to be used
222    :param configPath: path of the configuration file
223    :return: no return value
224    """
225    setConfigurationOption(USEMODULE_OPTION, newModule, configPath)
226
227
228def changeUseMappers(newMappers, configPath):
229    """
230    Changes mappers of the use_mappers configuration option
231    :param newMappers: new mappers to be used
232    :param configPath: path of the configuration file
233    :return: no return value
234    """
235    setConfigurationOption(USEMAPPERS_OPTION, newMappers, configPath)
236
237
238def getCardAuthCertificate():
239    """
240    Gets authentication certificate from the card
241    :return: certificate in string format
242    """
243    executeCommand(INSPECT_COMMAND, open(TEMP_OUTPUT, mode="w"))
244    cardData = readFileToList(TEMP_OUTPUT)
245    for line in cardData:
246        if "Autentica" in line and "serialNumber=" in line:
247            return line
248
249
250def addUserMapping(mappingConfigPath, username):
251    """
252    Add a user mapping with a certificate
253    :param mappingConfigPath: path of the mapping configurations file
254    :param username: name of the user
255    :return: True on success and False on failure
256    """
257    certificate = getCardAuthCertificate()
258    if certificate is None:
259        printDebugInfo("No certificate found. Make sure the card is inserted and the PIN is correct")
260        return False
261    else:
262        combo = certificate.strip() + " -> " + username + "\n"
263        appendStringToFile(mappingConfigPath, combo)
264        return True
265
266
267def runPamAuthUpdate(mode="enable"):
268    """
269    Simulates the execution of pam-auth-update
270    :return: no return value
271    """
272    authData = readFileToList(COMMONAUTH)
273    pkcs11Index = getIndexOfToken("pam_pkcs11.so", authData)
274    unixIndex = getIndexOfToken("pam_unix.so", authData)
275
276    if pkcs11Index is None and mode == "enable":
277        printDebugInfo("Enabling pam_pkcs11 at pam.d")
278        authData[unixIndex] = PKCS11AUTH + "\n" + authData[unixIndex]
279        writeListToFile(COMMONAUTH, authData)
280
281    elif pkcs11Index is not None and mode == "disable":
282        printDebugInfo("Disabling pam_pkcs11 at pam.d")
283        authData[pkcs11Index] = ""
284        writeListToFile(COMMONAUTH, authData)
285
286
287def resetPamAuth():
288    runPamAuthUpdate("disable")
289
290
291def deleteTemporaryData():
292    deleteDirectory(BACKUP_DIRPATH)
293    deleteFile(TEMP_OUTPUT)
294
295
296def deleteFile(filePath):
297    executeCommand(REMOVEFILES_COMMAND + filePath)
298
299
300def deleteDirectory(directoryPath):
301    executeCommand(REMOVEDIRS_COMMAND + directoryPath)
Note: See TracBrowser for help on using the repository browser.