mirror of
https://github.com/joel16/3DSident.git
synced 2024-11-23 03:29:45 +00:00
Merge upstream changes
W.I.P changes include friend code, and device cert. Device cert doesn't print anything as of now. The NNID is displayed properly. This time it shows both your username and ID. Fixed a problem that caused crashes when de-initializing actu.
This commit is contained in:
parent
ccc5f21532
commit
529e11a058
@ -1,14 +1,92 @@
|
|||||||
#include <3ds.h>
|
#include "actu.h"
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
static Handle actHandle;
|
Result actInit(u32 sdkVer, u32 sharedMemSize)
|
||||||
|
{
|
||||||
|
Result ret=0;
|
||||||
|
|
||||||
Result actInit(void)
|
ret = srvGetServiceHandle(&actHandle, "act:u");
|
||||||
|
if (R_FAILED(ret)) ret = srvGetServiceHandle(&actHandle, "act:a");
|
||||||
|
if (R_SUCCEEDED(ret))
|
||||||
|
{
|
||||||
|
act_shareMemSize = sharedMemSize;
|
||||||
|
act_shareMemHandle = 0;
|
||||||
|
|
||||||
|
if(act_shareMemSize)
|
||||||
|
{
|
||||||
|
act_shareMemAddr = (u32*)memalign(0x1000, act_shareMemSize);
|
||||||
|
if(act_shareMemAddr != NULL)
|
||||||
|
{
|
||||||
|
memset((void*)act_shareMemAddr, 0, act_shareMemSize);
|
||||||
|
ret = svcCreateMemoryBlock(&act_shareMemHandle, (u32)act_shareMemAddr, act_shareMemSize, 0, MEMPERM_READ | MEMPERM_WRITE);
|
||||||
|
if(R_FAILED(ret))
|
||||||
|
actExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = ACT_Initialize(sdkVer, &act_shareMemHandle, act_shareMemSize);
|
||||||
|
|
||||||
|
if (R_FAILED(ret))
|
||||||
|
actExit();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void actExit(void)
|
||||||
|
{
|
||||||
|
if (AtomicDecrement(&actRefCount)) return;
|
||||||
|
svcCloseHandle(actHandle);
|
||||||
|
|
||||||
|
if(act_shareMemHandle)
|
||||||
|
{
|
||||||
|
svcUnmapMemoryBlock(act_shareMemHandle, (u32)act_shareMemAddr);
|
||||||
|
free(act_shareMemAddr);
|
||||||
|
act_shareMemAddr = NULL;
|
||||||
|
svcCloseHandle(act_shareMemHandle);
|
||||||
|
act_shareMemHandle = 0;
|
||||||
|
act_shareMemSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ACT_Initialize(u32 sdkVer, void *addr, u32 memSize)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x1,2,4); // 0x00010084
|
||||||
|
cmdbuf[1] = sdkVer;
|
||||||
|
cmdbuf[2] = memSize;
|
||||||
|
cmdbuf[3] = 0x20;
|
||||||
|
cmdbuf[4] = IPC_Desc_CurProcessHandle();
|
||||||
|
cmdbuf[5] = 0;
|
||||||
|
cmdbuf[6] = (u32)addr;
|
||||||
|
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(actHandle))) return ret;
|
||||||
|
|
||||||
|
return (Result)cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ACT_GetAccountInfo(void *buffer, u32 size, u32 blkId)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(6,3,2); // 0x00600C2
|
||||||
|
cmdbuf[1] = 0xFE;
|
||||||
|
cmdbuf[2] = size;
|
||||||
|
cmdbuf[3] = blkId;
|
||||||
|
cmdbuf[4] = 0x10 * size | 0xC;
|
||||||
|
cmdbuf[5] = (u32)buffer;
|
||||||
|
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(actHandle))) return ret;
|
||||||
|
|
||||||
|
return (Result)cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result actuInit(void)
|
||||||
{
|
{
|
||||||
return srvGetServiceHandle(&actHandle, "act:u");
|
return srvGetServiceHandle(&actHandle, "act:u");
|
||||||
}
|
}
|
||||||
|
|
||||||
Result actExit(void)
|
Result actuExit(void)
|
||||||
{
|
{
|
||||||
return svcCloseHandle(actHandle);
|
return svcCloseHandle(actHandle);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,21 @@
|
|||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
#include <malloc.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
Result actInit(void);
|
Handle actHandle;
|
||||||
Result actExit(void);
|
int actRefCount;
|
||||||
|
|
||||||
|
u32 *act_shareMemAddr;
|
||||||
|
u32 act_shareMemSize;
|
||||||
|
Handle act_shareMemHandle;
|
||||||
|
|
||||||
|
Result actInit(u32 sdkVer, u32 sharedMemSize);
|
||||||
|
void actExit(void);
|
||||||
|
Result ACT_Initialize(u32 sdkVer, void *addr, u32 memSize);
|
||||||
|
Result ACT_GetAccountInfo(void *buffer, u32 size, u32 blkId);
|
||||||
|
Result actuInit(void);
|
||||||
|
Result actuExit(void);
|
||||||
Result ACTU_Initialize(u32 sdkVersion, u32 unknown, Handle handle);
|
Result ACTU_Initialize(u32 sdkVersion, u32 unknown, Handle handle);
|
||||||
Result ACTU_GetAccountDataBlock(u32 unknown, u32 size, u32 blockId, void* output);
|
Result ACTU_GetAccountDataBlock(u32 unknown, u32 size, u32 blockId, void* output);
|
57
source/am.c
57
source/am.c
@ -1,6 +1,61 @@
|
|||||||
#include "am.h"
|
#include "am.h"
|
||||||
|
|
||||||
|
char * base64encode(const char * input)
|
||||||
|
{
|
||||||
|
int len = strlen(input);
|
||||||
|
int leftover = len % 3;
|
||||||
|
char *ret = malloc(((len/3) * 4) + ((leftover)?4:0) + 1);
|
||||||
|
int n = 0;
|
||||||
|
int outlen = 0;
|
||||||
|
uint8_t i = 0;
|
||||||
|
uint8_t *inp = (uint8_t *) input;
|
||||||
|
const char *index = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
|
"0123456789+/";
|
||||||
|
|
||||||
Result AMNet_GetDeviceCert(u8 *buffer)
|
if (ret == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Convert each 3 bytes of input to 4 bytes of output.
|
||||||
|
len -= leftover;
|
||||||
|
for (n = 0; n < len; n+=3) {
|
||||||
|
i = inp[n] >> 2;
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
|
||||||
|
i = (inp[n] & 0x03) << 4;
|
||||||
|
i |= (inp[n+1] & 0xf0) >> 4;
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
|
||||||
|
i = ((inp[n+1] & 0x0f) << 2);
|
||||||
|
i |= ((inp[n+2] & 0xc0) >> 6);
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
|
||||||
|
i = (inp[n+2] & 0x3f);
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle leftover 1 or 2 bytes.
|
||||||
|
if (leftover) {
|
||||||
|
i = (inp[n] >> 2);
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
|
||||||
|
i = (inp[n] & 0x03) << 4;
|
||||||
|
if (leftover == 2) {
|
||||||
|
i |= (inp[n+1] & 0xf0) >> 4;
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
|
||||||
|
i = ((inp[n+1] & 0x0f) << 2);
|
||||||
|
}
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
ret[outlen++] = '=';
|
||||||
|
if (leftover == 1)
|
||||||
|
ret[outlen++] = '=';
|
||||||
|
}
|
||||||
|
ret[outlen] = '\0';
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result amNetGetDeviceCert(u8 const * buffer)
|
||||||
{
|
{
|
||||||
Result ret = 0;
|
Result ret = 0;
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
Handle amHandle;
|
Handle amHandle;
|
||||||
|
|
||||||
Result AMNet_GetDeviceCert(u8 *buffer);
|
char * base64encode(const char * input);
|
||||||
|
Result amNetGetDeviceCert(u8 const * buffer);
|
||||||
|
13
source/frd.c
13
source/frd.c
@ -2,10 +2,15 @@
|
|||||||
|
|
||||||
Result frdInit(u32 sdkVer)
|
Result frdInit(u32 sdkVer)
|
||||||
{
|
{
|
||||||
srvGetServiceHandle(&frdHandle, "frd:u");
|
Result ret;
|
||||||
srvGetServiceHandle(&frdHandle, "frd:n");
|
|
||||||
srvGetServiceHandle(&frdHandle, "frd:a");
|
ret = srvGetServiceHandle(&frdHandle, "frd:u");
|
||||||
return frdSetClientSdkVersion(sdkVer);
|
if(R_FAILED(ret)) ret = srvGetServiceHandle(&frdHandle, "frd:n");
|
||||||
|
if(R_FAILED(ret)) ret = srvGetServiceHandle(&frdHandle, "frd:a");
|
||||||
|
|
||||||
|
frdSetClientSdkVersion(sdkVer);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result frdExit()
|
Result frdExit()
|
||||||
|
@ -6,10 +6,12 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "actu.h"
|
#include "actu.h"
|
||||||
|
#include "am.h"
|
||||||
#include "cfgs.h"
|
#include "cfgs.h"
|
||||||
#include "frd.h"
|
#include "frd.h"
|
||||||
#include "mcu.h"
|
#include "mcu.h"
|
||||||
#include "screenshot.h"
|
#include "screenshot.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#define SDK(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|d)
|
#define SDK(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|d)
|
||||||
|
|
||||||
@ -219,6 +221,21 @@ u64 getSoapId(void)
|
|||||||
return (tmp | (((u64) 4) << 32));
|
return (tmp | (((u64) 4) << 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char * getDeviceCert(void)
|
||||||
|
{
|
||||||
|
u8 const cert[0x180];
|
||||||
|
amNetGetDeviceCert(cert);
|
||||||
|
return base64Encode(cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
char * getNNID(void)
|
||||||
|
{
|
||||||
|
static char tmp[0x11];
|
||||||
|
ACT_GetAccountInfo(tmp, 0x11, 0x8);
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
gfxInitDefault();
|
gfxInitDefault();
|
||||||
@ -229,11 +246,20 @@ int main(int argc, char *argv[])
|
|||||||
ptmuInit();
|
ptmuInit();
|
||||||
mcuInit();
|
mcuInit();
|
||||||
amInit();
|
amInit();
|
||||||
|
amAppInit();
|
||||||
psInit();
|
psInit();
|
||||||
aptInit();
|
aptInit();
|
||||||
hidInit();
|
hidInit();
|
||||||
acInit();
|
actuInit();
|
||||||
|
actInit(SDK(11,2,0,200), 0x20000);
|
||||||
gspLcdInit();
|
gspLcdInit();
|
||||||
|
httpcInit(0x9000);
|
||||||
|
frdInit(SDK(11,4,0,200));
|
||||||
|
|
||||||
|
consoleInit(GFX_BOTTOM, NULL);
|
||||||
|
|
||||||
|
printf("\x1b[31;1m*\x1b[0m Device cert: \x1b[31;1m%s\x1b[0m \n\n", getDeviceCert());
|
||||||
|
|
||||||
consoleInit(GFX_TOP, NULL);
|
consoleInit(GFX_TOP, NULL);
|
||||||
|
|
||||||
//=====================================================================//
|
//=====================================================================//
|
||||||
@ -251,7 +277,7 @@ int main(int argc, char *argv[])
|
|||||||
while (aptMainLoop())
|
while (aptMainLoop())
|
||||||
{
|
{
|
||||||
printf("\x1b[0;0H"); //Move the cursor to the top left corner of the screen
|
printf("\x1b[0;0H"); //Move the cursor to the top left corner of the screen
|
||||||
printf("\x1b[32;1m3DSident 0.7\x1b[0m\n\n");
|
printf("\x1b[32;1m3DSident 0.7.1\x1b[0m\n\n");
|
||||||
|
|
||||||
//=====================================================================//
|
//=====================================================================//
|
||||||
//------------------------------Firm Info------------------------------//
|
//------------------------------Firm Info------------------------------//
|
||||||
@ -292,20 +318,19 @@ int main(int argc, char *argv[])
|
|||||||
printf("\x1b[31;1m*\x1b[0m Model: \x1b[31;1m%s %s\n\x1b[0m", getModel(), getRegion());
|
printf("\x1b[31;1m*\x1b[0m Model: \x1b[31;1m%s %s\n\x1b[0m", getModel(), getRegion());
|
||||||
getScreenType();
|
getScreenType();
|
||||||
printf("\x1b[31;1m*\x1b[0m Language: \x1b[31;1m%s\x1b[0m \n", getLang());
|
printf("\x1b[31;1m*\x1b[0m Language: \x1b[31;1m%s\x1b[0m \n", getLang());
|
||||||
|
printf("\x1b[31;1m*\x1b[0m NNID: \x1b[31;1m%s\x1b[0m ", (char*)getNNID());
|
||||||
|
|
||||||
nnidNum = 0xFFFFFFFF;
|
|
||||||
ret = actInit();
|
|
||||||
ret = ACTU_Initialize(0xB0002C8, 0, 0);
|
ret = ACTU_Initialize(0xB0002C8, 0, 0);
|
||||||
ret = ACTU_GetAccountDataBlock(0xFE, 4, 12, &nnidNum);
|
ret = ACTU_GetAccountDataBlock(0xFE, 4, 12, &nnidNum);
|
||||||
ret = actExit();
|
|
||||||
|
|
||||||
if (nnidNum != 0xFFFFFFFF)
|
if (nnidNum != 0xFFFFFFFF)
|
||||||
vaPrint("\x1b[31;1m*\x1b[0m NNID number: \x1b[31;1m%08X\x1b[0m \n", (int) nnidNum);
|
vaPrint("(\x1b[31;1m%08X\x1b[0m) \n", (int) nnidNum);
|
||||||
else
|
else
|
||||||
vaPrint("\x1b[31;1m*\x1b[0m NNID number: \x1b[31;1mError could not retrieve NNID\x1b[0m \n");
|
printf("\x1b[31;1mError could not retrieve NNID\x1b[0m\n");
|
||||||
|
|
||||||
printf("\x1b[31;1m*\x1b[0m Device ID: \x1b[31;1m%lu \n", getDeviceId());
|
printf("\x1b[31;1m*\x1b[0m Device ID: \x1b[31;1m%lu \n", getDeviceId());
|
||||||
printf("\x1b[31;1m*\x1b[0m ECS Device ID: \x1b[31;1m%llu \n", getSoapId());
|
printf("\x1b[31;1m*\x1b[0m ECS Device ID: \x1b[31;1m%llu \n", getSoapId());
|
||||||
|
printf("\x1b[31;1m*\x1b[0m Friend Code: \x1b[31;1m%llu \n", principalIdToFriendCode(getMyFriendKey().principalId));
|
||||||
printf("\x1b[31;1m*\x1b[0m MAC Address: \x1b[31;1m%s\x1b[0m \n", getMacAddress());
|
printf("\x1b[31;1m*\x1b[0m MAC Address: \x1b[31;1m%s\x1b[0m \n", getMacAddress());
|
||||||
printf("\x1b[31;1m*\x1b[0m Serial number: \x1b[31;1m%s\x1b[0m \n", getSerialNum());
|
printf("\x1b[31;1m*\x1b[0m Serial number: \x1b[31;1m%s\x1b[0m \n", getSerialNum());
|
||||||
|
|
||||||
@ -316,7 +341,7 @@ int main(int argc, char *argv[])
|
|||||||
buf[12], buf[13], buf[14], buf[15]);
|
buf[12], buf[13], buf[14], buf[15]);
|
||||||
|
|
||||||
FSUSER_GetNandCid(buf, 0x10);
|
FSUSER_GetNandCid(buf, 0x10);
|
||||||
printf("\x1b[31;1m*\x1b[0m NAND CID: \x1b[31;1m%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\x1b[0m\n \n",
|
printf("\x1b[31;1m*\x1b[0m NAND CID: \x1b[31;1m%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\x1b[0m \n\n",
|
||||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
|
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
|
||||||
buf[6], buf[7], buf[8], buf[9], buf[10], buf[11],
|
buf[6], buf[7], buf[8], buf[9], buf[10], buf[11],
|
||||||
buf[12], buf[13], buf[14], buf[15]);
|
buf[12], buf[13], buf[14], buf[15]);
|
||||||
@ -357,7 +382,7 @@ int main(int argc, char *argv[])
|
|||||||
_3dSliderPercent = (osGet3DSliderState() * 100.0);
|
_3dSliderPercent = (osGet3DSliderState() * 100.0);
|
||||||
printf("\x1b[32;1m*\x1b[0m 3D slider state: \x1b[32;1m%.1lf\x1b[0m (\x1b[32;1m%.0lf%%\x1b[0m) \n", osGet3DSliderState(), _3dSliderPercent);
|
printf("\x1b[32;1m*\x1b[0m 3D slider state: \x1b[32;1m%.1lf\x1b[0m (\x1b[32;1m%.0lf%%\x1b[0m) \n", osGet3DSliderState(), _3dSliderPercent);
|
||||||
|
|
||||||
printf("\n\x1b[32;1m> Press any key to exit =)\x1b[0m\n");
|
printf("\n\x1b[32;1m> Press any key to exit =)\x1b[0m");
|
||||||
|
|
||||||
gspWaitForVBlank();
|
gspWaitForVBlank();
|
||||||
hidScanInput();
|
hidScanInput();
|
||||||
@ -377,7 +402,10 @@ int main(int argc, char *argv[])
|
|||||||
free(str_ver);
|
free(str_ver);
|
||||||
free(str_sysver);
|
free(str_sysver);
|
||||||
|
|
||||||
|
frdExit();
|
||||||
|
httpcExit();
|
||||||
gspLcdExit();
|
gspLcdExit();
|
||||||
|
actuExit();
|
||||||
acExit();
|
acExit();
|
||||||
hidExit();
|
hidExit();
|
||||||
aptExit();
|
aptExit();
|
||||||
|
56
source/utils.c
Normal file
56
source/utils.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
char * base64Encode(u8 const * input)
|
||||||
|
{
|
||||||
|
int len = strlen((const char *)input);
|
||||||
|
int leftover = len % 3;
|
||||||
|
char *ret = malloc(((len/3) * 4) + ((leftover)?4:0) + 1);
|
||||||
|
int n = 0;
|
||||||
|
int outlen = 0;
|
||||||
|
uint8_t i = 0;
|
||||||
|
uint8_t *inp = (uint8_t *) input;
|
||||||
|
const char *index = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
|
"0123456789+/";
|
||||||
|
|
||||||
|
if (ret == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Convert each 3 bytes of input to 4 bytes of output.
|
||||||
|
len -= leftover;
|
||||||
|
for (n = 0; n < len; n+=3) {
|
||||||
|
i = inp[n] >> 2;
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
|
||||||
|
i = (inp[n] & 0x03) << 4;
|
||||||
|
i |= (inp[n+1] & 0xf0) >> 4;
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
|
||||||
|
i = ((inp[n+1] & 0x0f) << 2);
|
||||||
|
i |= ((inp[n+2] & 0xc0) >> 6);
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
|
||||||
|
i = (inp[n+2] & 0x3f);
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle leftover 1 or 2 bytes.
|
||||||
|
if (leftover) {
|
||||||
|
i = (inp[n] >> 2);
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
|
||||||
|
i = (inp[n] & 0x03) << 4;
|
||||||
|
if (leftover == 2) {
|
||||||
|
i |= (inp[n+1] & 0xf0) >> 4;
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
|
||||||
|
i = ((inp[n+1] & 0x0f) << 2);
|
||||||
|
}
|
||||||
|
ret[outlen++] = index[i];
|
||||||
|
ret[outlen++] = '=';
|
||||||
|
if (leftover == 1)
|
||||||
|
ret[outlen++] = '=';
|
||||||
|
}
|
||||||
|
ret[outlen] = '\0';
|
||||||
|
return ret;
|
||||||
|
}
|
6
source/utils.h
Normal file
6
source/utils.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <3ds.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char * base64Encode(u8 const * input);
|
Loading…
Reference in New Issue
Block a user