diff --git a/client/interfaceAdm/InventarioSoftware.py b/client/interfaceAdm/InventarioSoftware.py old mode 100644 new mode 100755 index 928681b..7812388 --- a/client/interfaceAdm/InventarioSoftware.py +++ b/client/interfaceAdm/InventarioSoftware.py @@ -7,13 +7,13 @@ import sys def main(arg1, arg2, dest_file): start_time = time.time() - # Load the engine configurator from the engine.cfg file + # Cargar la configuración del motor desde el archivo engine.cfg og_engine_configurate = os.getenv('OGENGINECONFIGURATE') if not og_engine_configurate: with open('/opt/opengnsys/etc/engine.cfg') as f: exec(f.read()) - # Clear the temporary files used as log tracking for httpdlog + # Limpiar los archivos temporales usados como log para httpdlog og_log_session = os.getenv('OGLOGSESSION') og_log_command = os.getenv('OGLOGCOMMAND') if og_log_session and og_log_command: @@ -24,26 +24,35 @@ def main(arg1, arg2, dest_file): with open(f"{og_log_command}.tmp", 'w') as f: f.write(" ") - # Log the start of execution + # Registrar el inicio de ejecución msg_interface_start = os.getenv('MSG_INTERFACE_START') if msg_interface_start: subprocess.run(['ogEcho', 'log', 'session', f"{msg_interface_start} {__file__} {arg1} {arg2}"]) - # Get the software info file and copy it to the destination - # Call the actual listSoftwareInfo function - file = listSoftwareInfo(arg1, arg2) + # Ejecutar el script listSoftwareInfo y capturar el archivo de salida + try: + result = subprocess.run( + ["python3", "/opt/opengnsys/scripts/listSoftwareInfo.py", arg1, arg2], + capture_output=True, + text=True, + check=True + ) + file = result.stdout.strip() # Captura la salida del script + except subprocess.CalledProcessError as e: + print(f"Error al ejecutar listSoftwareInfo: {e.stderr}") + sys.exit(e.returncode) + + # Copiar el archivo resultante a dest_file shutil.copy(file, dest_file) - # Log the execution time + # Registrar el tiempo de ejecución elapsed_time = time.time() - start_time msg_scripts_time_partial = os.getenv('MSG_SCRIPTS_TIME_PARTIAL') if msg_scripts_time_partial: subprocess.run(['ogEcho', 'log', 'session', f" [ ] {msg_scripts_time_partial} : {int(elapsed_time // 60)}m {int(elapsed_time % 60)}s"]) - - if __name__ == "__main__": if len(sys.argv) != 4: print("Usage: python InventarioSoftware.py ") sys.exit(1) - main(sys.argv[1], sys.argv[2], sys.argv[3]) \ No newline at end of file + main(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py new file mode 100755 index 0000000..32ef764 --- /dev/null +++ b/client/lib/engine/bin/RegistryLib.py @@ -0,0 +1,179 @@ +import subprocess +import os +import re + +#from engine.FileLib import * +#from engine.SystemLib import * + +def chntpw(*args): + chntpw_path = subprocess.check_output(['which', 'drbl-chntpw']).decode().strip() + if not chntpw_path: + chntpw_path = subprocess.check_output(['which', 'chntpw']).decode().strip() + subprocess.run([chntpw_path, '-e'] + list(args), timeout=5) + +def ogAddRegistryKey(path_mountpoint, str_hive, str_key): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Añadir nueva clave. + chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0]) + chntpw(FILE, 'nk', str_key.rsplit('\\', 1)[-1]) + chntpw(FILE, 'q') + chntpw(FILE, 'y') + +def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_valuetype=''): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Determine the value type. + if str_valuetype.upper() == 'STRING' or str_valuetype == '': + TYPE = 1 + elif str_valuetype.upper() == 'BINARY': + TYPE = 3 + elif str_valuetype.upper() == 'DWORD': + TYPE = 4 + else: + ogRaiseError(OG_ERR_OUTOFLIMIT, str_valuetype) + return + + # Add the registry value. + chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0]) + chntpw(FILE, 'nv', str_valuename.rsplit('\\', 1)[-1], TYPE) + chntpw(FILE, 'q') + chntpw(FILE, 'y') + +def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Delete the registry key. + subprocess.run(['chntpw', FILE], input=f"cd {str_key.rsplit('\\', 1)[0]}\ndk {str_key.rsplit('\\', 1)[-1]}\nq\ny\n".encode(), timeout=5) + +def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Delete the registry value. + chntpw(FILE, 'cd', str_valuename.rsplit('\\', 1)[0]) + chntpw(FILE, 'dv', str_valuename.rsplit('\\', 1)[-1]) + chntpw(FILE, 'q') + chntpw(FILE, 'y') + +def ogGetHivePath(path_mountpoint, str_hive): + # Variables locales. + FILE = None + + # Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad). + FILE = ogGetPath(f"/{path_mountpoint}/Windows/System32/config/{str_hive}") + if not FILE: + FILE = ogGetPath(f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT") + if not FILE: + FILE = ogGetPath(f"/{path_mountpoint}/winnt/system32/config/{str_hive}") + if not FILE: + FILE = ogGetPath(f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT") + if FILE and os.path.isfile(FILE): + return FILE + else: + ogRaiseError(OG_ERR_NOTFOUND, f"{path_mountpoint} {str_hive}") + return None + +def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Devolver el dato del valor de registro. + chntpw_cmd = f''' + chntpw "{FILE}" << EOT 2> /dev/null | awk '/> Value/ {{ + if (index($0, "REG_BINARY") > 0) {{ + data="" + }} else {{ + getline + data=$0 + }} + }} + /^:[0-9A-F]+ / {{ + data=data""substr($0, 9, 48) + }} + END {{ + print data + }}' + cd {str_valuename.rsplit('\\', 1)[0]} + cat {str_valuename.rsplit('\\', 1)[-1]} + q + EOT + ''' + subprocess.run(chntpw_cmd, shell=True, timeout=5) + +def ogListRegistryKeys(path_mountpoint, str_hive, str_key): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Devolver la lista de claves de registro. + chntpw_cmd = f''' + chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/^ $/ {{print $2}}' + ls {str_key} + q + EOT + ''' + subprocess.run(chntpw_cmd, shell=True, timeout=5) + +def ogListRegistryValues(path_mountpoint, str_hive, str_key): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Devolver la lista de valores de registro. + chntpw_cmd = f''' + chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/REG_/ {{print $2}}' + ls {str_key} + q + EOT + ''' + subprocess.run(chntpw_cmd, shell=True, timeout=5) + +def ogSetRegistryValue(path_mountpoint, str_hive, str_valuename, str_data): + # Variables locales. + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: + return + + # Fichero temporal para componer la entrada al comando "chntpw". + tmpfile = "/tmp/chntpw$$" + try: + # Comprobar tipo de datos del valor del registro. + with open(tmpfile, 'w') as f: + f.write(f"ls {str_valuename.rsplit('\\', 1)[0]}\nq\n") + output = subprocess.check_output(['chntpw', FILE], input=open(tmpfile, 'rb'), stderr=subprocess.DEVNULL).decode() + if f"BINARY.*<{str_valuename.rsplit('\\', 1)[-1]}>" in output: + # Procesar tipo binario (incluir nº de bytes y líneas de 16 parejas hexadecimales). + if not re.match(r'^([0-9A-F]{2} )*$', str_data): + ogRaiseError(OG_ERR_FORMAT, f'"{str_data}"') + return + n = len(str_data) + 1 + with open(tmpfile, 'w') as f: + f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{int(n/3)}\n") + for i in range(0, n, 48): + f.write(f":{i//3:05x} {str_data[i:i+48]}\n") + f.write("s\nq\ny\n") + else: + # Cambiar el dato del valor de registro para cadenas y bytes. + with open(tmpfile, 'w') as f: + f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{str_data}\nq\ny\n") + + # Aplicar cambios. + subprocess.run(['chntpw', FILE], input=open(tmpfile, 'rb'), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + finally: + os.remove(tmpfile) diff --git a/client/shared/scripts/listSoftwareInfo.py b/client/shared/scripts/listSoftwareInfo.py old mode 100644 new mode 100755 index eaac54a..31c2e8d --- a/client/shared/scripts/listSoftwareInfo.py +++ b/client/shared/scripts/listSoftwareInfo.py @@ -1,56 +1,37 @@ import sys import os -import re -import subprocess +sys.path.append('/opt/opengnsys/lib/engine/bin') +from NetLib import ogGetIpAddress +from SystemLib import ogRaiseError +from InventoryLib import ogListSoftware -#!/usr/bin/env python3 +REDUCED = False -def main(): - PROG = os.path.basename(__file__) - REDUCED = "no" - - if len(sys.argv) > 1 and sys.argv[1] == "-r": - REDUCED = "yes" - sys.argv.pop(1) - - if len(sys.argv) != 3: - og_raise_error(1, f"Usage: {PROG} [-r] ndisk npart") - - ndisk = sys.argv[1] - npart = sys.argv[2] - - OGLOG = "/path/to/log" # Replace with actual log path - SERVERLOGDIR = None - - # Simulate the mount command and awk processing - mounts = subprocess.check_output(['mount']).decode('utf-8') - for line in mounts.splitlines(): - parts = line.split() - if len(parts) > 3 and parts[2] == OGLOG: - SERVERLOGDIR = parts[1] - break - - if SERVERLOGDIR is None: - og_raise_error(1, "Could not determine server log directory") - - SOFTFILE = f"soft-{og_get_ip_address()}-{ndisk}-{npart}" - softfile_path = os.path.join(OGLOG, SOFTFILE) - - try: - if REDUCED == "no": - software_list = og_list_software(ndisk, npart) - else: - software_list = "\n".join( - line for line in og_list_software(ndisk, npart).splitlines() - if not re.search(r"\(KB[0-9]{6}\)", line) - ) - - with open(softfile_path, 'w') as f: - f.write(software_list) - except Exception as e: - og_raise_error(1, str(e)) - - print(softfile_path) +if len(sys.argv) > 1 and sys.argv[1] == "-r": + REDUCED = True + sys.argv.pop(1) -if __name__ == "__main__": - main() \ No newline at end of file +if len(sys.argv) != 3: + og_raise_error("OG_ERR_FORMAT", "Usage: listSoftwareInfo [-r] disk partition") + sys.exit(1) + +disk = sys.argv[1] +partition = sys.argv[2] + +# Directorio del servidor donde se exportan los ficheros de registro +server_log_dir = "/mnt/oglog" # Assuming OGLOG is mounted at /mnt/oglog + +# Fichero de listado: soft-IP-disk-partition +soft_file = f"soft-{ogGetIpAddress()}-{disk}-{partition}" +log_path = os.path.join(server_log_dir, soft_file) + +# Redirigir salida al fichero de listado +with open(log_path, "w") as log_file: + if not REDUCED: + ogListSoftware(disk, partition, log_file) + else: + for line in og_list_software(disk, partition): + if "(KB" not in line: + log_file.write(line + "\n") + +print(log_path)