mirror of
https://github.com/hashcat/hashcat.git
synced 2025-07-01 12:22:37 +00:00
- Fix memory leak in python bridge
- Fix Python header validation in Makefile - Improve some tunings
This commit is contained in:
parent
ac2ed9f402
commit
d5934f9e3d
@ -47,11 +47,11 @@ def term(ctx):
|
||||
# Read passwords from stdin
|
||||
|
||||
if __name__ == '__main__':
|
||||
ctx = {
|
||||
"salts_buf": bytes(568),
|
||||
"esalts_buf": bytes(131080),
|
||||
"st_salts_buf": bytes(568),
|
||||
"st_esalts_buf": bytes(131080)
|
||||
ctx = {
|
||||
"salts_buf": bytes(568),
|
||||
"esalts_buf": bytes(131080),
|
||||
"st_salts_buf": bytes(568),
|
||||
"st_esalts_buf": bytes(131080)
|
||||
}
|
||||
init(ctx)
|
||||
hashcat_passwords = 256
|
||||
|
@ -11,9 +11,9 @@ ST_PASS = "hashcat"
|
||||
|
||||
def calc_hash(password: bytes, salt: dict) -> str:
|
||||
salt_buf = hcshared.get_salt_buf(salt)
|
||||
hash = hashlib.sha256(salt_buf + password)
|
||||
for i in range(10000):
|
||||
hash = hashlib.sha256(hash.digest())
|
||||
hash = hashlib.sha256(salt_buf + password)
|
||||
for i in range(10000):
|
||||
hash = hashlib.sha256(hash.digest())
|
||||
return hash.hexdigest()
|
||||
|
||||
# ...except when using an esalt. The esalt void* structure is both dynamic and specific to a hash mode.
|
||||
@ -47,11 +47,11 @@ def term(ctx):
|
||||
# Read passwords from stdin
|
||||
|
||||
if __name__ == '__main__':
|
||||
ctx = {
|
||||
"salts_buf": bytes(568),
|
||||
"esalts_buf": bytes(131080),
|
||||
"st_salts_buf": bytes(568),
|
||||
"st_esalts_buf": bytes(131080)
|
||||
ctx = {
|
||||
"salts_buf": bytes(568),
|
||||
"esalts_buf": bytes(131080),
|
||||
"st_salts_buf": bytes(568),
|
||||
"st_esalts_buf": bytes(131080)
|
||||
}
|
||||
init(ctx)
|
||||
hashcat_passwords = 256
|
||||
|
@ -702,8 +702,8 @@ void *platform_init (user_options_t *user_options)
|
||||
PyObject *sys = python->PyImport_ImportModule ("sys");
|
||||
PyObject *path = python->PyObject_GetAttrString (sys, "path");
|
||||
python->PyList_Append (path, python->PyUnicode_FromString ("./Python"));
|
||||
//python->Py_DecRef (path);
|
||||
//python->Py_DecRef (sys);
|
||||
python->Py_DecRef (path);
|
||||
python->Py_DecRef (sys);
|
||||
|
||||
if (units_init (python_interpreter) == false)
|
||||
{
|
||||
@ -740,7 +740,7 @@ void *platform_init (user_options_t *user_options)
|
||||
return false;
|
||||
}
|
||||
|
||||
//python->Py_DecRef (pName);
|
||||
python->Py_DecRef (pName);
|
||||
|
||||
unit_buf->pFunc_Init = python->PyObject_GetAttrString (unit_buf->pModule, "init");
|
||||
|
||||
@ -810,12 +810,12 @@ void platform_term (void *platform_context)
|
||||
|
||||
unit_buf->gstate = python->PyGILState_Ensure ();
|
||||
|
||||
//python->Py_DecRef (unit_buf->pFunc_kernel_loop);
|
||||
//python->Py_DecRef (unit_buf->pFunc_Term);
|
||||
//python->Py_DecRef (unit_buf->pFunc_Init);
|
||||
//python->Py_DecRef (unit_buf->pModule);
|
||||
//python->Py_DecRef (unit_buf->pContext);
|
||||
//python->Py_DecRef (unit_buf->pArgs);
|
||||
python->Py_DecRef (unit_buf->pArgs);
|
||||
python->Py_DecRef (unit_buf->pContext);
|
||||
python->Py_DecRef (unit_buf->pFunc_kernel_loop);
|
||||
python->Py_DecRef (unit_buf->pFunc_Term);
|
||||
python->Py_DecRef (unit_buf->pFunc_Init);
|
||||
python->Py_DecRef (unit_buf->pModule);
|
||||
|
||||
//python->PyEval_RestoreThread (python_interpreter->tstate);
|
||||
|
||||
@ -872,9 +872,16 @@ bool thread_init (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
|
||||
python->PyTuple_SetItem (pArgs, 0, unit_buf->pContext);
|
||||
|
||||
python->PyObject_CallObject (unit_buf->pFunc_Init, pArgs);
|
||||
PyObject *pReturn = python->PyObject_CallObject (unit_buf->pFunc_Init, pArgs);
|
||||
|
||||
//python->Py_DecRef (pArgs);
|
||||
if (pReturn == NULL)
|
||||
{
|
||||
python->PyErr_Print ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
python->Py_DecRef (pReturn);
|
||||
|
||||
python->PyGILState_Release (unit_buf->gstate);
|
||||
|
||||
@ -906,21 +913,6 @@ void thread_term (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
|
||||
python->PyObject_CallObject (unit_buf->pFunc_Term, pArgs);
|
||||
|
||||
//python->Py_DecRef (pArgs);
|
||||
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "salts_cnt"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "salts_size"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "salts_buf"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "esalts_cnt"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "esalts_size"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "esalts_buf"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_salts_cnt"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_salts_size"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_salts_buf"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_esalts_cnt"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_esalts_size"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_esalts_buf"));
|
||||
|
||||
python->PyDict_DelItemString (unit_buf->pContext, "salts_cnt");
|
||||
python->PyDict_DelItemString (unit_buf->pContext, "salts_size");
|
||||
python->PyDict_DelItemString (unit_buf->pContext, "salts_buf");
|
||||
@ -995,8 +987,6 @@ bool launch_loop (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
|
||||
python->PyList_SetItem (pws, i, pw);
|
||||
|
||||
// python->Py_DecRef (pw);
|
||||
|
||||
generic_io_tmp++;
|
||||
}
|
||||
|
||||
@ -1021,8 +1011,6 @@ bool launch_loop (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
return false;
|
||||
}
|
||||
|
||||
// python->Py_DecRef (pws);
|
||||
|
||||
Py_ssize_t retsz = python->PyList_Size (pReturn);
|
||||
|
||||
if (retsz != (Py_ssize_t) pws_cnt) return false;
|
||||
@ -1044,14 +1032,12 @@ bool launch_loop (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
generic_io_tmp->out_len = len;
|
||||
}
|
||||
|
||||
//python->Py_DecRef (hash);
|
||||
|
||||
generic_io_tmp++;
|
||||
}
|
||||
|
||||
//python->Py_DecRef (pReturn);
|
||||
python->Py_DecRef (pReturn);
|
||||
|
||||
python->PyGILState_Release(unit_buf->gstate);
|
||||
python->PyGILState_Release (unit_buf->gstate);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1077,6 +1063,8 @@ const char *st_update_hash (MAYBE_UNUSED void *platform_context)
|
||||
|
||||
const char *s = python->PyUnicode_AsUTF8 (constant);
|
||||
|
||||
python->Py_DecRef (constant);
|
||||
|
||||
python->PyGILState_Release (unit_buf->gstate);
|
||||
|
||||
return s;
|
||||
@ -1103,6 +1091,8 @@ const char *st_update_pass (MAYBE_UNUSED void *platform_context)
|
||||
|
||||
const char *s = python->PyUnicode_AsUTF8 (constant);
|
||||
|
||||
python->Py_DecRef (constant);
|
||||
|
||||
python->PyGILState_Release (unit_buf->gstate);
|
||||
|
||||
return s;
|
||||
|
@ -769,8 +769,8 @@ bool thread_init (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
PyObject *sys = python->PyImport_ImportModule ("sys");
|
||||
PyObject *path = python->PyObject_GetAttrString (sys, "path");
|
||||
python->PyList_Append (path, python->PyUnicode_FromString ("./Python"));
|
||||
//python->Py_DecRef (path);
|
||||
//python->Py_DecRef (sys);
|
||||
python->Py_DecRef (path);
|
||||
python->Py_DecRef (sys);
|
||||
|
||||
PyObject *pName = python->PyUnicode_DecodeFSDefault (python_interpreter->source_filename);
|
||||
|
||||
@ -790,7 +790,7 @@ bool thread_init (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
return false;
|
||||
}
|
||||
|
||||
//python->Py_DecRef (pName);
|
||||
python->Py_DecRef (pName);
|
||||
|
||||
unit_buf->pFunc_Init = python->PyObject_GetAttrString (unit_buf->pModule, "init");
|
||||
|
||||
@ -863,7 +863,18 @@ bool thread_init (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
|
||||
python->PyTuple_SetItem (pArgs, 0, unit_buf->pContext);
|
||||
|
||||
python->PyObject_CallObject (unit_buf->pFunc_Init, pArgs);
|
||||
PyObject *pReturn = python->PyObject_CallObject (unit_buf->pFunc_Init, pArgs);
|
||||
|
||||
if (pReturn == NULL)
|
||||
{
|
||||
python->PyErr_Print ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
python->Py_DecRef (pReturn);
|
||||
|
||||
//python->Py_DecRef (pArgs);
|
||||
|
||||
// for later calls
|
||||
|
||||
@ -893,19 +904,6 @@ void thread_term (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
|
||||
hc_python_lib_t *python = python_interpreter->python;
|
||||
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "salts_cnt"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "salts_size"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "salts_buf"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "esalts_cnt"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "esalts_size"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "esalts_buf"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_salts_cnt"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_salts_size"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_salts_buf"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_esalts_cnt"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_esalts_size"));
|
||||
//python->Py_DecRef (python->PyDict_GetItemString (unit_buf->pContext, "st_esalts_buf"));
|
||||
|
||||
python->PyDict_DelItemString (unit_buf->pContext, "salts_cnt");
|
||||
python->PyDict_DelItemString (unit_buf->pContext, "salts_size");
|
||||
python->PyDict_DelItemString (unit_buf->pContext, "salts_buf");
|
||||
@ -932,13 +930,14 @@ void thread_term (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
|
||||
python->PyObject_CallObject (unit_buf->pFunc_Term, pArgs);
|
||||
|
||||
//python->Py_DecRef (pArgs);
|
||||
//python->Py_DecRef (unit_buf->pFunc_kernel_loop);
|
||||
//python->Py_DecRef (unit_buf->pFunc_Term);
|
||||
//python->Py_DecRef (unit_buf->pFunc_Init);
|
||||
//python->Py_DecRef (unit_buf->pModule);
|
||||
//python->Py_DecRef (unit_buf->pContext);
|
||||
//python->Py_DecRef (unit_buf->pArgs);
|
||||
python->Py_DecRef (pArgs);
|
||||
|
||||
python->Py_DecRef (unit_buf->pArgs);
|
||||
python->Py_DecRef (unit_buf->pContext);
|
||||
python->Py_DecRef (unit_buf->pFunc_kernel_loop);
|
||||
python->Py_DecRef (unit_buf->pFunc_Term);
|
||||
python->Py_DecRef (unit_buf->pFunc_Init);
|
||||
python->Py_DecRef (unit_buf->pModule);
|
||||
|
||||
python->Py_EndInterpreter (unit_buf->tstate);
|
||||
}
|
||||
@ -1023,8 +1022,6 @@ bool launch_loop (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
return false;
|
||||
}
|
||||
|
||||
//python->Py_DecRef (pws);
|
||||
|
||||
Py_ssize_t retsz = python->PyList_Size (pReturn);
|
||||
|
||||
if (retsz != (Py_ssize_t) pws_cnt) return false;
|
||||
@ -1046,12 +1043,10 @@ bool launch_loop (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa
|
||||
generic_io_tmp->out_len = len;
|
||||
}
|
||||
|
||||
//python->Py_DecRef (hash);
|
||||
|
||||
generic_io_tmp++;
|
||||
}
|
||||
|
||||
//python->Py_DecRef (pReturn);
|
||||
python->Py_DecRef (pReturn);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1067,8 +1062,8 @@ const char *st_update_hash (MAYBE_UNUSED void *platform_context)
|
||||
PyObject *sys = python->PyImport_ImportModule ("sys");
|
||||
PyObject *path = python->PyObject_GetAttrString (sys, "path");
|
||||
python->PyList_Append (path, python->PyUnicode_FromString ("./Python"));
|
||||
//python->Py_DecRef (path);
|
||||
//python->Py_DecRef (sys);
|
||||
python->Py_DecRef (path);
|
||||
python->Py_DecRef (sys);
|
||||
|
||||
PyObject *pName = python->PyUnicode_DecodeFSDefault (python_interpreter->source_filename);
|
||||
|
||||
@ -1103,6 +1098,8 @@ const char *st_update_hash (MAYBE_UNUSED void *platform_context)
|
||||
|
||||
const char *s = python->PyUnicode_AsUTF8 (constant);
|
||||
|
||||
python->Py_DecRef (constant);
|
||||
|
||||
python_interpreter->thread_state = python->PyEval_SaveThread ();
|
||||
|
||||
return s;
|
||||
@ -1119,8 +1116,8 @@ const char *st_update_pass (MAYBE_UNUSED void *platform_context)
|
||||
PyObject *sys = python->PyImport_ImportModule ("sys");
|
||||
PyObject *path = python->PyObject_GetAttrString (sys, "path");
|
||||
python->PyList_Append (path, python->PyUnicode_FromString ("./Python"));
|
||||
//python->Py_DecRef (path);
|
||||
//python->Py_DecRef (sys);
|
||||
python->Py_DecRef (path);
|
||||
python->Py_DecRef (sys);
|
||||
|
||||
PyObject *pName = python->PyUnicode_DecodeFSDefault (python_interpreter->source_filename);
|
||||
|
||||
@ -1155,6 +1152,8 @@ const char *st_update_pass (MAYBE_UNUSED void *platform_context)
|
||||
|
||||
const char *s = python->PyUnicode_AsUTF8 (constant);
|
||||
|
||||
python->Py_DecRef (constant);
|
||||
|
||||
python_interpreter->thread_state = python->PyEval_SaveThread ();
|
||||
|
||||
return s;
|
||||
|
@ -18,15 +18,32 @@ bridges/bridge_python_generic_hash_sp.$(BRIDGE_SUFFIX): src/bridges/bridge_pytho
|
||||
endif
|
||||
endif
|
||||
|
||||
PYTHON_INCLUDE_PATH := $(shell echo $(PYTHON_CONFIG_FLAGS_LINUX) | sed -n 's/-I\([^ ]*\).*/\1/p')
|
||||
PYTHON_HAS_OWN_GIL := $(shell grep -r -q 'PyInterpreterConfig_OWN_GIL' $(PYTHON_INCLUDE_PATH) && echo yes || echo no)
|
||||
|
||||
ifeq ($(BRIDGE_SUFFIX),so)
|
||||
ifeq ($(PYTHON_HAS_OWN_GIL),no)
|
||||
|
||||
PYTHON_INCLUDE_PATH := $(shell echo "$(PYTHON_CFLAGS)" | sed -n 's/-I\([^ ]*\).*/\1/p')
|
||||
PYTHON_HAS_OWN_GIL := $(shell grep -r -q 'PyInterpreterConfig_OWN_GIL' "$(PYTHON_INCLUDE_PATH)" && echo true || echo false)
|
||||
|
||||
REPORTS_MISSING := false
|
||||
|
||||
ifeq ($(PYTHON_INCLUDE_PATH),)
|
||||
REPORTS_MISSING := true
|
||||
endif
|
||||
|
||||
ifeq ($(PYTHON_HAS_OWN_GIL),false)
|
||||
REPORTS_MISSING := true
|
||||
endif
|
||||
|
||||
RED = \033[1;31m
|
||||
RESET = \033[0m
|
||||
|
||||
ifeq ($(REPORTS_MISSING),true)
|
||||
bridges/bridge_python_generic_hash_sp.so:
|
||||
@echo ""
|
||||
@echo "WARNING: Skipping freethreaded plugin 70200: Python 3.12+ headers not found."
|
||||
@echo " Please read 'docs/hashcat-python-plugin-requirements.md'."
|
||||
@echo "$(RED)WARNING$(RESET): Skipping freethreaded plugin 70200: Python 3.12+ headers not found."
|
||||
@echo " To use -m 70200, you must install the required Python headers."
|
||||
@echo " Otherwise, you can safely ignore this warning."
|
||||
@echo " For more information, see 'docs/hashcat-python-plugin-requirements.md'."
|
||||
@echo ""
|
||||
endif
|
||||
|
||||
endif
|
||||
|
@ -27,6 +27,7 @@ GeForce_GTX_1080 * 8900 1 15
|
||||
GeForce_RTX_2080_Ti * 8900 1 68 A
|
||||
GeForce_RTX_3060_Ti * 8900 1 51 A
|
||||
GeForce_RTX_3070 * 8900 1 46 A
|
||||
GeForce_RTX_3080_Ti_Laptop_GPU * 8900 1 46 A
|
||||
GeForce_RTX_3090 * 8900 1 82 A
|
||||
GeForce_RTX_3090_Ti * 8900 1 84 A
|
||||
GeForce_RTX_4090 * 8900 1 180 A
|
||||
|
@ -27,6 +27,7 @@ GeForce_GTX_1080 * 9300 1 256
|
||||
GeForce_RTX_2080_Ti * 9300 1 528 A
|
||||
GeForce_RTX_3060_Ti * 9300 1 256 A
|
||||
GeForce_RTX_3070 * 9300 1 368 A
|
||||
GeForce_RTX_3080_Ti_Laptop_GPU * 9300 1 272 A
|
||||
GeForce_RTX_3090 * 9300 1 984 A
|
||||
ALIAS_AMD_RX480 * 9300 1 232 A
|
||||
ALIAS_AMD_Vega64 * 9300 1 440 A
|
||||
|
@ -27,6 +27,7 @@ GeForce_GTX_1080 * 15700 1 28
|
||||
GeForce_RTX_2080_Ti * 15700 1 68 A
|
||||
GeForce_RTX_3060_Ti * 15700 1 11 A
|
||||
GeForce_RTX_3070 * 15700 1 22 A
|
||||
GeForce_RTX_3080_Ti_Laptop_GPU * 15700 1 22 A
|
||||
GeForce_RTX_3090 * 15700 1 82 A
|
||||
GeForce_RTX_3090_Ti * 15700 1 84 A
|
||||
GeForce_RTX_4090 * 15700 1 180 A
|
||||
|
@ -27,6 +27,7 @@ GeForce_GTX_1080 * 22700 1 15
|
||||
GeForce_RTX_2080_Ti * 22700 1 68 A
|
||||
GeForce_RTX_3060_Ti * 22700 1 51 A
|
||||
GeForce_RTX_3070 * 22700 1 46 A
|
||||
GeForce_RTX_3080_Ti_Laptop_GPU * 22700 1 46 A
|
||||
GeForce_RTX_3090 * 22700 1 82 A
|
||||
GeForce_RTX_3090_Ti * 22700 1 84 A
|
||||
GeForce_RTX_4090 * 22700 1 180 A
|
||||
|
@ -27,6 +27,7 @@ GeForce_GTX_1080 * 27700 1 15
|
||||
GeForce_RTX_2080_Ti * 27700 1 68 A
|
||||
GeForce_RTX_3060_Ti * 27700 1 51 A
|
||||
GeForce_RTX_3070 * 27700 1 46 A
|
||||
GeForce_RTX_3080_Ti_Laptop_GPU * 27700 1 46 A
|
||||
GeForce_RTX_3090 * 27700 1 82 A
|
||||
GeForce_RTX_3090_Ti * 27700 1 84 A
|
||||
GeForce_RTX_4090 * 27700 1 180 A
|
||||
|
@ -27,6 +27,7 @@ GeForce_GTX_1080 * 28200 1 15
|
||||
GeForce_RTX_2080_Ti * 28200 1 68 A
|
||||
GeForce_RTX_3060_Ti * 28200 1 51 A
|
||||
GeForce_RTX_3070 * 28200 1 46 A
|
||||
GeForce_RTX_3080_Ti_Laptop_GPU * 28200 1 46 A
|
||||
GeForce_RTX_3090 * 28200 1 82 A
|
||||
GeForce_RTX_3090_Ti * 28200 1 84 A
|
||||
GeForce_RTX_4090 * 28200 1 180 A
|
||||
|
@ -26,6 +26,7 @@ GeForce_GTX_1070_Ti * 29800 1 14
|
||||
GeForce_GTX_1080 * 29800 1 14 A
|
||||
GeForce_GTX_1080_Ti * 29800 1 20 A
|
||||
GeForce_RTX_2080_Ti * 29800 1 40 A
|
||||
GeForce_RTX_3080_Ti_Laptop_GPU * 29800 1 23 A
|
||||
GeForce_RTX_3090 * 29800 1 82 A
|
||||
|
||||
ALIAS_AMD_RX6900XT * 29800 1 28 A
|
||||
|
Loading…
Reference in New Issue
Block a user