-
Notifications
You must be signed in to change notification settings - Fork 0
/
guard.py
executable file
·306 lines (261 loc) · 9.45 KB
/
guard.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
#!/usr/bin/env python
# -*- coding: utf-8 -*-
## @file guard.py
# @brief Programa Guarda.
# @details Usando cálculo de HMAC, permite garantir a autenticação
# de um conjunto de arquivos para uma determinada pasta (recursivamente).
# @since 09/10/2016
# @date 14/10/2016
# @author David Cardoso
# @copyright 2016 - All rights reserveds
# @sa https://github.com/davidcardoso-ti/guard-files-hmac/blob/master/guard.py
import os, sys # os, sys - recursos de sistema
import shutil # shutil - operações avançadas de sistema
import mmap # mmap - suporte à arquivo em memória
from collections import OrderedDict # OrderedDict - dicionário ordenado
from datetime import datetime # datetime - data e tempo
from string import split # split - separar strings de acordo com separador
from HMAC import HMAC # HMAC - classe para cálculo HMAC (Hash-based Message Authentication Code)
"""Variáveis"""
## negrito
BOLD = '\033[1m'
## cor padrão para impressões no terminal
NORMAL = '\033[0;0m'
## cor verde para destacar impressões no terminal
GREEN = BOLD+'\033[32m'
## cor azul para destacar impressões no terminal
BLUE = BOLD+'\033[34m'
## cor branca para destacar impressões no terminal
WHITE = BOLD+'\033[37m'
## cor amarela para destacar impressões no terminal
YELLOW = BOLD+'\033[93m'
## cor vermelha para destacar impressões no terminal
RED = BOLD+'\033[91m'
## quebra de linha
ENDL = "\n"
## tabulação
TAB = "\t"
## separador CSV
SEP = ";"
## objeto da classe HMAC
HMAC_OBJ = HMAC()
## dicionário para armazenar os HMACS dos arquivos
MATCHES = {}
## opção de ação do programa (-i, -t ou -x)
ARG_OPTION = ""
## diretório a ser aplicado a ação
ARG_PATH = ""
## diretório oculto para armazenar arquivos de rastreamento contendo o HMAC dos arquivos
HIDDEN = ".guard"
## nome do arquivo de rastreamento
TMP = datetime.now().strftime('%Y%m%d%H%M%S')
## extensão do arquivo de rastreamento
EXT = ""
## @brief Função para limpar console
def clearConsole():
os.system('cls' if os.name == 'nt' else 'reset')
## @brief Função printExampleArgs()
# @details Imprimir explicação dos argumentos via linha de comando
def printExampleArgs():
print '%sGive an option and a folder:%s' % (ENDL, ENDL)
print '-i %sto start folder guard%s' % (TAB, ENDL)
print '-t %sto track the folder%s' % (TAB, ENDL)
print '-x %sto stop folder guard%s' % (TAB, ENDL)
print 'Example: ./guard.py <option> <folder_path> %s' % (ENDL)
print 'Ending... %s' % (ENDL)
## @brief Função checkArgs()
# @details Validação dos argumentos passados via linha de comando
def checkArgs():
global ARG_OPTION, ARG_PATH
if sys.argv.__len__() == 3:
ARG_OPTION = str(sys.argv[1])
ARG_PATH = str(sys.argv[2])
if ARG_OPTION not in ('-i', '-t', '-x'):
print 'Invalid option!%s' % (ENDL)
printExampleArgs()
sys.exit()
else:
print 'Expected 2 arguments but %i was given!%s' % (sys.argv.__len__()-1, ENDL)
printExampleArgs()
sys.exit()
## @brief Função genHMAC()
# @details Gera HMAC dos arquivos do diretório de forma recursiva
# @param dir - caminho do diretório
def genHMAC(dir):
global MATCHES
# mudando diretorio
os.chdir(dir)
# caminho absoluto para diretorio
dir = os.getcwd()
# se existe pasta oculta
if HIDDEN in os.listdir(dir):
# percorre recursivamente todos os subdiretórios
for root, dirnames, filenames in os.walk(dir):
# percore todos os arquivos dos subdiretórios
for filename in filenames:
# ignora a pasta oculta
if root[-len(HIDDEN):] != HIDDEN:
# caminho completo
fullpath_filename = os.path.join(root, filename)
# abre arquivo e lê conteúdo
f = open(fullpath_filename, "r")
if f:
content = f.read()
f.close()
# objeto HMAC - submete CAMINHO + CONTEUDO
h = HMAC_OBJ.hmac(fullpath_filename+content)
# adiciona caminho absoluto do arquivo e seu respectivo HMAC ao dicionário
MATCHES.update( {fullpath_filename : h.hexdigest()} )
else:
MATCHES.update( {fullpath_filename : 'Error trying to open file!'} )
# ordenar dicionário por chave (fullpath_filename)
MATCHES = OrderedDict(sorted(MATCHES.items(), key=lambda t: t[0]))
# Diretório inválido ou arquivos inexistentes
if MATCHES.__len__() == 0:
print 'Invalid folder or there are no files in the folder!%s' % (ENDL)
printExampleArgs()
sys.exit()
else:
print "%sFolder '%s' not found! You need to start folder guard: %s" % (ENDL, HIDDEN, os.getcwd())
printExampleArgs()
sys.exit()
## @brief Função printHMAC()
# @details Imprimir dicionário contendo os arquivos e os respectivos HMACs
# @param dir - caminho do diretório
def printHMAC(dir):
# mudando para dir
os.chdir(dir)
# imprimir conteúdo do dicionário
for hash, filename in MATCHES.iteritems():
print hash+TAB+filename
# diretorio atual
print "%sFiles of the folder has been printed: %s" % ( ENDL, os.getcwd() )
## @brief Função startGuard()
# @details Iniciar a guarda do diretório
# @param dir - caminho do diretório
def startGuard(dir):
# mudando para dir
os.chdir(dir)
# cria pasta oculta se não existir
if HIDDEN not in os.listdir(dir):
print "%sEnabled folder guard: %s" % ( ENDL, os.getcwd() )
# cria pasta oculta
os.mkdir(HIDDEN)
# mudando para pasta oculta
os.chdir(HIDDEN)
# gerar dicionário com os HMACs
genHMAC(dir)
# gerar arquivo de rastreio
createTrackFile(dir)
else:
print "%sFolder already guarded: %s" % ( ENDL, os.getcwd() )
## @brief Função createTrackFile()
# @details Criar arquivo de rastreio contendo os arquivos e os respectivos HMACs
# @param dir - caminho do diretório
def createTrackFile(dir):
# se existe pasta oculta
if HIDDEN in os.listdir(dir):
# mudando para pasta oculta
os.chdir(dir+'/'+HIDDEN)
print "%sGenerating new tracking file: %s" % ( ENDL, TMP+EXT )
# salva dados do dicionário no arquivo de rastreio
track_file = open(TMP+EXT, "w+")
if track_file:
for filename, hash in MATCHES.iteritems():
track_file.write( str(hash+SEP+filename+ENDL) )
track_file.close()
print "%sTracking file saved in: %s" % ( ENDL, os.getcwd() )
else:
print "%sError trying to generate tracking file!" % (ENDL)
else:
print "%sFolder '%s' not found! You need to start folder guard: %s" % (ENDL, HIDDEN, os.getcwd())
printExampleArgs()
## @brief Função stopGuard()
# @details Finalizar a guarda do diretório
# @param dir - caminho do diretório
def stopGuard(dir):
# apaga o diretório oculto e seus arquivos de rastreio
if HIDDEN in os.listdir(dir):
# mudando para dir
os.chdir(dir)
# caminho absoluto da pasta oculta
path_del = os.getcwd()+'/'+HIDDEN
# apaga
shutil.rmtree(path_del)
print "%sDisabled folder guard: %s" % ( ENDL, os.getcwd() )
else:
print "%sFolder '%s' not found! You need to start folder guard: %s" % (ENDL, HIDDEN, os.getcwd())
printExampleArgs()
## @brief Função checkChanges()
# @details Verifica as alterações no diretório guardado
# @param dir - caminho do diretório
# @param hid - pasta oculta
def checkChanges(dir, hid):
# muda e seleciona caminho absoluto da pasta oculta
if hid in os.listdir(dir):
path = dir+'/'+hid
os.chdir(path)
path = os.getcwd()
# seleciona último arquivo de rastreio
track_files = sorted(os.listdir(path))
if track_files.__len__() > 1:
last_track = track_files[-1]
elif track_files.__len__() == 1:
last_track = track_files[0]
else:
last_track = False
# compara último arquivo de rastreio com situação atual do diretório guardado
if last_track:
print "%sComparing with the last tracking file: %s" % ( ENDL, last_track )
# abre último arquivo de rastreio
f = open(last_track, 'r')
# otimiza busca no arquivo em memória com o módulo mmap
s = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
# verifica: novos, modificados e não-modificados
count = 1
okay = 0
for filename, hash in MATCHES.iteritems():
if s.find(filename) != -1 and s.find(hash) == -1:
print "(%s) %s %s%s" % (str(count).zfill(4), RED+'Changed'+NORMAL, TAB, filename)
count += 1
elif s.find(filename) == -1 and s.find(hash) == -1:
print "(%s) %s %s%s" % (str(count).zfill(4), GREEN+'New'+NORMAL, TAB, filename)
count += 1
elif s.find(filename) != -1 and s.find(hash) != -1:
# print "(%s) %s %s%s" % (str(count).zfill(4), BLUE+'Okay'+NORMAL, TAB, filename)
okay += 1
# verifica: excluídos
for line in f.readlines():
exploded = split(line, ';')
if exploded[1][0:-1] not in MATCHES.keys():
print "(%s) %s %s%s" % (str(count).zfill(4), YELLOW+'Deleted'+NORMAL, TAB, exploded[1][0:-1])
count += 1
# imprime qtd de arquivos não-modificados
if okay > 0:
print "%s%s file(s) %s!" % (ENDL, BLUE+str(okay)+NORMAL, BLUE+'Okay'+NORMAL)
s.close()
f.close()
else:
print "%sEmpty folder: %s" % (ENDL, path)
# BLOCO PRINCIPAL DO PROGRAMA
if __name__ == "__main__":
# limpar console
clearConsole()
print "%s==> Software Guard" % (WHITE)
print " File Authentication using HMAC.%s%s" % (ENDL, NORMAL)
# validar argumentos
checkArgs()
# imprimir
#printHMAC(ARG_PATH)
# iniciar guarda no diretório
if ARG_OPTION == '-i':
startGuard(ARG_PATH)
# rastrear diretório
elif ARG_OPTION == '-t':
genHMAC(ARG_PATH)
checkChanges(ARG_PATH, HIDDEN)
createTrackFile(ARG_PATH)
# desativar guarda no diretório
elif ARG_OPTION == '-x':
stopGuard(ARG_PATH)
sys.exit()