mirror of
https://git.FreeBSD.org/ports.git
synced 2025-01-01 05:45:45 +00:00
Fix build on -CURRENT by conditionalizing S/Key support and adding OPIE
support. Reported by: bento
This commit is contained in:
parent
cbb3e83c08
commit
92df255ffd
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=71433
@ -7,6 +7,7 @@
|
||||
|
||||
PORTNAME= tac_plus
|
||||
PORTVERSION= F4.0.4
|
||||
PORTREVISION= 1
|
||||
CATEGORIES= net
|
||||
MASTER_SITES= ftp://ftp-eng.cisco.com/pub/tacacs/
|
||||
DISTNAME= tac_plus.F4.0.4.alpha
|
||||
@ -38,6 +39,14 @@ CFLAGS+= -DTAC_IOS_VERSION=${TAC_IOS_VERSION}
|
||||
CFLAGS+= -DTAC_IOS_VERSION=11
|
||||
.endif
|
||||
|
||||
.if exists(/usr/include/skey.h) && !defined(WITHOUT_SKEY)
|
||||
MAKE_ENV+= WITH_SKEY=1
|
||||
.endif
|
||||
|
||||
.if exists(/usr/include/opie.h) && !defined(WITHOUT_OPIE)
|
||||
MAKE_ENV+= WITH_OPIE=1
|
||||
.endif
|
||||
|
||||
do-install:
|
||||
${INSTALL_PROGRAM} ${WRKSRC}/tac_plus ${PREFIX}/sbin
|
||||
${INSTALL_MAN} ${WRKSRC}/tac_plus.1 ${PREFIX}/man/man1/tac_plus.1
|
||||
|
@ -1,5 +1,5 @@
|
||||
--- Makefile.orig Sun Jun 18 19:26:54 2000
|
||||
+++ Makefile Mon Jan 22 20:22:57 2001
|
||||
--- Makefile.orig Sun Jun 18 13:26:54 2000
|
||||
+++ Makefile Sun Dec 8 15:18:58 2002
|
||||
@@ -19,7 +19,7 @@
|
||||
# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
@ -27,15 +27,22 @@
|
||||
# NOTE: If you want your password encryption to be compatible with
|
||||
# e.g. SunOS, you may need to instead use:
|
||||
# OSLIBS=-ldescrypt
|
||||
@@ -64,12 +64,12 @@
|
||||
@@ -64,12 +64,19 @@
|
||||
# FLAGS = -DTAC_PLUS_USERID=$(USERID) -DTAC_PLUS_GROUPID=$(GROUPID)
|
||||
|
||||
# Definitions for SKEY functionality
|
||||
-# DEFINES = -DSKEY
|
||||
-# LIBS = ../crimelab/skey/src/libskey.a
|
||||
+.if defined(WITH_SKEY)
|
||||
+DEFINES = -DSKEY
|
||||
+LIBS = -lskey -lmd
|
||||
# INCLUDES = -I../crimelab/skey/src
|
||||
+.endif
|
||||
+
|
||||
+.if defined(WITH_OPIE)
|
||||
+DEFINES += -DOPIE
|
||||
+LIBS += -lopie -lmd
|
||||
+.endif
|
||||
|
||||
# Debugging flags
|
||||
-DEBUG = -g
|
||||
@ -43,7 +50,7 @@
|
||||
|
||||
# Enforce a limit on maximum sessions per user. See the user's guide
|
||||
# for more information.
|
||||
@@ -85,13 +85,13 @@
|
||||
@@ -85,13 +92,13 @@
|
||||
# possible), containing its process id. Uncomment and modify the
|
||||
# following line to change this filename
|
||||
|
||||
@ -59,7 +66,16 @@
|
||||
|
||||
HFILES = expire.h parse.h regmagic.h md5.h regexp.h tac_plus.h
|
||||
|
||||
@@ -130,8 +130,8 @@
|
||||
@@ -99,7 +106,7 @@
|
||||
do_author.c dump.c encrypt.c expire.c $(MSCHAP_MD4_SRC) md5.c \
|
||||
packet.c report.c sendauth.c tac_plus.c utils.c pw.c hash.c \
|
||||
parse.c regexp.c programs.c enable.c pwlib.c default_fn.c \
|
||||
- skey_fn.c default_v0_fn.c sendpass.c maxsess.c
|
||||
+ skey_fn.c opie_fn.c default_v0_fn.c sendpass.c maxsess.c
|
||||
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
@@ -130,8 +137,8 @@
|
||||
-rm -f *.o *~ *.BAK tac_plus generate_passwd
|
||||
|
||||
install:
|
||||
|
@ -1,28 +1,18 @@
|
||||
*** skey_fn.c.orig Sat Jul 29 02:49:18 1995
|
||||
--- skey_fn.c Mon Mar 3 17:33:57 1997
|
||||
***************
|
||||
*** 153,158 ****
|
||||
--- 153,163 ----
|
||||
char buf[256];
|
||||
sprintf(buf, "%s\nPassword: ", skeyprompt);
|
||||
data->server_msg = tac_strdup(buf);
|
||||
+
|
||||
+ /* We try to make it in accordance of standard FreeBSD
|
||||
+ * behaviour in order to avoid surprises for user */
|
||||
+ data->flags = TAC_PLUS_AUTHEN_FLAG_NOECHO;
|
||||
+
|
||||
data->status = TAC_PLUS_AUTHEN_STATUS_GETPASS;
|
||||
p->state = STATE_AUTHEN_GETPASS;
|
||||
return (0);
|
||||
*** tac_plus.h.orig Sat Jul 29 02:49:19 1995
|
||||
--- tac_plus.h Mon Mar 3 17:35:51 1997
|
||||
***************
|
||||
*** 91,96 ****
|
||||
--- 91,97 ----
|
||||
#ifdef FREEBSD
|
||||
#define CONST_SYSERRLIST
|
||||
#define STDLIB_MALLOC
|
||||
+ #define NO_PWAGE
|
||||
#define VOIDSIG
|
||||
#endif
|
||||
|
||||
--- tac_plus.h.orig Sun Jun 18 13:26:54 2000
|
||||
+++ tac_plus.h Sun Dec 8 15:24:27 2002
|
||||
@@ -137,6 +137,7 @@
|
||||
#ifdef FREEBSD
|
||||
#define CONST_SYSERRLIST
|
||||
#define STDLIB_MALLOC
|
||||
+#define NO_PWAGE
|
||||
#define VOIDSIG
|
||||
#define NO_PWAGE
|
||||
#endif
|
||||
@@ -701,6 +702,7 @@
|
||||
extern int default_fn();
|
||||
extern int default_v0_fn();
|
||||
extern int skey_fn();
|
||||
+extern int opie_fn();
|
||||
#ifdef MSCHAP
|
||||
extern void mschap_lmchallengeresponse();
|
||||
extern void mschap_ntchallengeresponse();
|
||||
|
@ -27,23 +27,3 @@
|
||||
contains the process id of the currently running daemon. The port
|
||||
number is appended to the filename only if the port being used is not
|
||||
the default one of 49.
|
||||
--- users_guide.orig Sat Apr 3 08:03:48 1999
|
||||
+++ users_guide Tue Nov 9 21:57:03 1999
|
||||
@@ -1368,7 +1368,7 @@
|
||||
and then send the daemon a SIGUSR1. This will cause it to reinitialize
|
||||
itself and re-read the configuration file.
|
||||
|
||||
-On startup, tac_plus creates the file /etc/tac_plus.pid , if possible,
|
||||
+On startup, tac_plus creates the file /var/run/tac_plus.pid , if possible,
|
||||
containing its process id. If you invoke the daemon so that it listens
|
||||
on a non-standard port, the file created is /etc/tac_plus.pid.<port>
|
||||
instead, where <port> is the port number the daemon is listening on.
|
||||
@@ -1376,7 +1376,7 @@
|
||||
Assuming you are listening on the default port 49, something like the
|
||||
following should work:
|
||||
|
||||
-# kill -USR1 `cat /etc/tac_plus.pid`
|
||||
+# kill -USR1 `cat /var/run/tac_plus.pid`
|
||||
|
||||
It's a good idea to check that the daemon is still running after
|
||||
sending it a SIGUSR1, since a syntactically incorrect configuration
|
||||
|
32
net/tac_plus4/files/patch-choose_authen.c
Normal file
32
net/tac_plus4/files/patch-choose_authen.c
Normal file
@ -0,0 +1,32 @@
|
||||
--- choose_authen.c.orig Sun Jun 18 13:26:53 2000
|
||||
+++ choose_authen.c Sun Dec 8 15:26:08 2002
|
||||
@@ -118,10 +118,27 @@
|
||||
#else /* SKEY */
|
||||
report(LOG_ERR,
|
||||
"%s %s: user %s s/key support has not been compiled in",
|
||||
- name ? name : "<unknown>",
|
||||
- session.peer, session.port);
|
||||
+ session.peer, session.port,
|
||||
+ name ? name : "<unknown>");
|
||||
return(CHOOSE_FAILED);
|
||||
#endif /* SKEY */
|
||||
+ }
|
||||
+
|
||||
+ if (cfg_passwd && STREQ(cfg_passwd, "opie")) {
|
||||
+ if (debug & DEBUG_PASSWD_FLAG)
|
||||
+ report(LOG_DEBUG, "%s %s: user %s requires opie",
|
||||
+ session.peer, session.port, name);
|
||||
+#ifdef OPIE
|
||||
+ type->authen_func = opie_fn;
|
||||
+ strcpy(type->authen_name, "opie_fn");
|
||||
+ return (CHOOSE_OK);
|
||||
+#else /* OPIE */
|
||||
+ report(LOG_ERR,
|
||||
+ "%s %s: user %s opie support has not been compiled in",
|
||||
+ session.peer, session.port,
|
||||
+ name ? name : "<unknown>");
|
||||
+ return(CHOOSE_FAILED);
|
||||
+#endif /* OPIE */
|
||||
}
|
||||
|
||||
/* Not an skey user. Must be none, des, cleartext or file password */
|
242
net/tac_plus4/files/patch-opie_fn.c
Normal file
242
net/tac_plus4/files/patch-opie_fn.c
Normal file
@ -0,0 +1,242 @@
|
||||
--- opie_fn.c.orig Sun Dec 8 15:26:20 2002
|
||||
+++ opie_fn.c Sun Dec 8 15:27:01 2002
|
||||
@@ -0,0 +1,239 @@
|
||||
+/*
|
||||
+ Copyright (c) 1995-2000 by Cisco systems, Inc.
|
||||
+
|
||||
+ Permission to use, copy, modify, and distribute modified and
|
||||
+ unmodified copies of this software for any purpose and without fee is
|
||||
+ hereby granted, provided that (a) this copyright and permission notice
|
||||
+ appear on all copies of the software and supporting documentation, (b)
|
||||
+ the name of Cisco Systems, Inc. not be used in advertising or
|
||||
+ publicity pertaining to distribution of the program without specific
|
||||
+ prior permission, and (c) notice be given in supporting documentation
|
||||
+ that use, modification, copying and distribution is by permission of
|
||||
+ Cisco Systems, Inc.
|
||||
+
|
||||
+ Cisco Systems, Inc. makes no representations about the suitability
|
||||
+ of this software for any purpose. THIS SOFTWARE IS PROVIDED ``AS
|
||||
+ IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||
+ WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
+ FITNESS FOR A PARTICULAR PURPOSE.
|
||||
+*/
|
||||
+
|
||||
+#ifdef OPIE
|
||||
+#include "tac_plus.h"
|
||||
+#include "expire.h"
|
||||
+
|
||||
+/* internal state variables */
|
||||
+#define STATE_AUTHEN_START 0 /* no requests issued */
|
||||
+#define STATE_AUTHEN_GETUSER 1 /* username has been requested */
|
||||
+#define STATE_AUTHEN_GETPASS 2 /* password has been requested */
|
||||
+
|
||||
+#include <opie.h>
|
||||
+
|
||||
+struct private_data {
|
||||
+ struct opie opiedata;
|
||||
+ char password[MAX_PASSWD_LEN + 1];
|
||||
+ int state;
|
||||
+};
|
||||
+
|
||||
+/* Use s/key to verify a supplied password using state set up earlier
|
||||
+when the username was supplied */
|
||||
+
|
||||
+static int
|
||||
+opie_verify(passwd, data)
|
||||
+char *passwd;
|
||||
+struct authen_data *data;
|
||||
+{
|
||||
+ struct private_data *p = data->method_data;
|
||||
+ struct opie *opiep = &p->opiedata;
|
||||
+
|
||||
+ data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
|
||||
+
|
||||
+ if (opieverify(opiep, passwd) == 0) {
|
||||
+ /* S/Key authentication succeeded */
|
||||
+ data->status = TAC_PLUS_AUTHEN_STATUS_PASS;
|
||||
+ if (opiep->opie_n < 5) {
|
||||
+ data->server_msg = tac_strdup("Password will expire soon");
|
||||
+ return (1);
|
||||
+ }
|
||||
+ }
|
||||
+ return (0);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Skey tacacs login authentication function. Wants a username
|
||||
+ * and a password, and tries to verify them via opie.
|
||||
+ *
|
||||
+ * Choose_authen will ensure that we already have a username before this
|
||||
+ * gets called.
|
||||
+ *
|
||||
+ * We will query for a password and keep it in the method_data.
|
||||
+ *
|
||||
+ * Any strings returned via pointers in authen_data must come from the
|
||||
+ * heap. They will get freed by the caller.
|
||||
+ *
|
||||
+ * Return 0 if data->status is valid, otherwise 1
|
||||
+ */
|
||||
+
|
||||
+int
|
||||
+opie_fn(data)
|
||||
+struct authen_data *data;
|
||||
+{
|
||||
+ char *name, *passwd;
|
||||
+ struct private_data *p;
|
||||
+ char *prompt;
|
||||
+ int pwlen;
|
||||
+
|
||||
+ p = (struct private_data *) data->method_data;
|
||||
+
|
||||
+ /* An abort has been received. Clean up and return */
|
||||
+ if (data->flags & TAC_PLUS_CONTINUE_FLAG_ABORT) {
|
||||
+ if (data->method_data)
|
||||
+ free(data->method_data);
|
||||
+ data->method_data = NULL;
|
||||
+ return (1);
|
||||
+ }
|
||||
+ /* Initialise method_data if first time through */
|
||||
+ if (!p) {
|
||||
+ p = (struct private_data *) tac_malloc(sizeof(struct private_data));
|
||||
+ bzero(p, sizeof(struct private_data));
|
||||
+ data->method_data = p;
|
||||
+ p->state = STATE_AUTHEN_START;
|
||||
+ }
|
||||
+
|
||||
+ /* Unless we're enabling, we need a username */
|
||||
+ if (data->service != TAC_PLUS_AUTHEN_SVC_ENABLE &&
|
||||
+ !(char) data->NAS_id->username[0]) {
|
||||
+ switch (p->state) {
|
||||
+
|
||||
+ case STATE_AUTHEN_GETUSER:
|
||||
+ /* we have previously asked for a username but none came back.
|
||||
+ * This is a gross error */
|
||||
+ data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
|
||||
+ report(LOG_ERR, "%s: No username supplied after GETUSER",
|
||||
+ session.peer);
|
||||
+ return (0);
|
||||
+
|
||||
+ case STATE_AUTHEN_START:
|
||||
+ /* No username. Try requesting one */
|
||||
+ data->status = TAC_PLUS_AUTHEN_STATUS_GETUSER;
|
||||
+ if (data->service == TAC_PLUS_AUTHEN_SVC_LOGIN) {
|
||||
+ prompt = "\nUser Access Verification\n\nUsername: ";
|
||||
+ } else {
|
||||
+ prompt = "Username: ";
|
||||
+ }
|
||||
+ data->server_msg = tac_strdup(prompt);
|
||||
+ p->state = STATE_AUTHEN_GETUSER;
|
||||
+ return (0);
|
||||
+
|
||||
+ default:
|
||||
+ /* something awful has happened. Give up and die */
|
||||
+ report(LOG_ERR, "%s: opie_fn bad state %d",
|
||||
+ session.peer, p->state);
|
||||
+ return (1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* we now have a username if we needed one */
|
||||
+ name = data->NAS_id->username;
|
||||
+
|
||||
+ /* Do we have a password? */
|
||||
+ passwd = p->password;
|
||||
+
|
||||
+ if (!passwd[0]) {
|
||||
+ char opieprompt[80];
|
||||
+
|
||||
+ /* no password yet. Either we need to ask for one and expect to get
|
||||
+ * called again, or we asked but nothing came back, which is fatal */
|
||||
+
|
||||
+ switch (p->state) {
|
||||
+ case STATE_AUTHEN_GETPASS:
|
||||
+ /* We already asked for a password. This should be the reply */
|
||||
+ if (data->client_msg) {
|
||||
+ pwlen = MIN(strlen(data->client_msg), MAX_PASSWD_LEN);
|
||||
+ } else {
|
||||
+ pwlen = 0;
|
||||
+ }
|
||||
+ strncpy(passwd, data->client_msg, pwlen);
|
||||
+ passwd[pwlen] = '\0';
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ /* Request a password */
|
||||
+ passwd = cfg_get_login_secret(name, TAC_PLUS_RECURSE);
|
||||
+ if (!passwd && !STREQ(passwd, "opie")) {
|
||||
+ report(LOG_ERR, "Cannot find opie password declaration for %s",
|
||||
+ name);
|
||||
+ data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
|
||||
+ return(1);
|
||||
+ }
|
||||
+
|
||||
+ if (opiechallenge(&p->opiedata, name, opieprompt) == 0) {
|
||||
+ char buf[256];
|
||||
+ sprintf(buf, "%s\nPassword: ", opieprompt);
|
||||
+ data->server_msg = tac_strdup(buf);
|
||||
+
|
||||
+ /* We try to make it in accordance of standard FreeBSD
|
||||
+ * behaviour in order to avoid surprises for user */
|
||||
+ data->flags = TAC_PLUS_AUTHEN_FLAG_NOECHO;
|
||||
+
|
||||
+ data->status = TAC_PLUS_AUTHEN_STATUS_GETPASS;
|
||||
+ p->state = STATE_AUTHEN_GETPASS;
|
||||
+ return (0);
|
||||
+ }
|
||||
+
|
||||
+ data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
|
||||
+ report(LOG_ERR, "Cannot generate opie prompt for %s", name);
|
||||
+ return(1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* We have a username and password. Try validating */
|
||||
+
|
||||
+ /* Assume the worst */
|
||||
+ data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
|
||||
+
|
||||
+ switch (data->service) {
|
||||
+ case TAC_PLUS_AUTHEN_SVC_LOGIN:
|
||||
+ opie_verify(passwd, data);
|
||||
+ if (debug)
|
||||
+ report(LOG_INFO, "login query for '%s' %s from %s %s",
|
||||
+ name && name[0] ? name : "unknown",
|
||||
+ data->NAS_id->NAS_port && data->NAS_id->NAS_port[0] ?
|
||||
+ data->NAS_id->NAS_port : "unknown",
|
||||
+ session.peer,
|
||||
+ (data->status == TAC_PLUS_AUTHEN_STATUS_PASS) ?
|
||||
+ "accepted" : "rejected");
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
|
||||
+ report(LOG_ERR, "%s: Bogus service value %d from packet",
|
||||
+ session.peer, data->service);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (data->method_data)
|
||||
+ free(data->method_data);
|
||||
+ data->method_data = NULL;
|
||||
+
|
||||
+ switch (data->status) {
|
||||
+ case TAC_PLUS_AUTHEN_STATUS_ERROR:
|
||||
+ case TAC_PLUS_AUTHEN_STATUS_FAIL:
|
||||
+ case TAC_PLUS_AUTHEN_STATUS_PASS:
|
||||
+ return (0);
|
||||
+ default:
|
||||
+ report(LOG_ERR, "%s: opie_fn couldn't set recognizable status %d",
|
||||
+ session.peer, data->status);
|
||||
+ data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
|
||||
+ return (1);
|
||||
+ }
|
||||
+}
|
||||
+#else /* OPIE */
|
||||
+
|
||||
+/* The following code is not needed or used. It exists solely to
|
||||
+ prevent compilers from "helpfully" complaining that this source
|
||||
+ file is empty, which upsets novices building the software */
|
||||
+
|
||||
+static int dummy = 0;
|
||||
+
|
||||
+#endif /* OPIE */
|
7
net/tac_plus4/files/patch-parse.h
Normal file
7
net/tac_plus4/files/patch-parse.h
Normal file
@ -0,0 +1,7 @@
|
||||
--- parse.h.orig Sun Dec 8 15:22:51 2002
|
||||
+++ parse.h Sun Dec 8 15:23:26 2002
|
||||
@@ -76,3 +76,4 @@
|
||||
#ifdef MSCHAP
|
||||
#define S_mschap 42
|
||||
#endif /* MSCHAP */
|
||||
+#define S_opie 43
|
48
net/tac_plus4/files/patch-users_guide
Normal file
48
net/tac_plus4/files/patch-users_guide
Normal file
@ -0,0 +1,48 @@
|
||||
--- users_guide.orig Sun Jun 18 13:26:54 2000
|
||||
+++ users_guide Sun Dec 8 15:14:01 2002
|
||||
@@ -166,7 +166,10 @@
|
||||
crimelab.com but now it appears the only source is ftp.bellcore.com. I
|
||||
suggest you try a web search for s/key source code.
|
||||
|
||||
-Note: S/KEY is a trademark of Bell Communications Research (Bellcore).
|
||||
+To use OPIE, you must have built tac_plus with the -DWITH_OPIE flag.
|
||||
+
|
||||
+Note: S/KEY and OPIE are a trademark of Bell Communications Research
|
||||
+(Bellcore).
|
||||
|
||||
Should you need them, there are routines for accessing password files
|
||||
(getpwnam,setpwent,endpwent,setpwfile) in pw.c.
|
||||
@@ -436,6 +439,15 @@
|
||||
login = skey
|
||||
}
|
||||
|
||||
+4. Authentication using opie.
|
||||
+
|
||||
+If you have successfully built tac_plus with opie support, you can specify
|
||||
+a user be authenticated via opie, as follows:
|
||||
+
|
||||
+ user = marcus {
|
||||
+ login = opie
|
||||
+ }
|
||||
+
|
||||
RECURSIVE PASSWORD LOOKUPS
|
||||
---------------------------
|
||||
|
||||
@@ -1370,7 +1382,7 @@
|
||||
and then send the daemon a SIGUSR1. This will cause it to reinitialize
|
||||
itself and re-read the configuration file.
|
||||
|
||||
-On startup, tac_plus creates the file /etc/tac_plus.pid , if possible,
|
||||
+On startup, tac_plus creates the file /var/run/tac_plus.pid , if possible,
|
||||
containing its process id. If you invoke the daemon so that it listens
|
||||
on a non-standard port, the file created is /etc/tac_plus.pid.<port>
|
||||
instead, where <port> is the port number the daemon is listening on.
|
||||
@@ -1378,7 +1390,7 @@
|
||||
Assuming you are listening on the default port 49, something like the
|
||||
following should work:
|
||||
|
||||
-# kill -USR1 `cat /etc/tac_plus.pid`
|
||||
+# kill -USR1 `cat /var/run/tac_plus.pid`
|
||||
|
||||
It's a good idea to check that the daemon is still running after
|
||||
sending it a SIGUSR1, since a syntactically incorrect configuration
|
Loading…
Reference in New Issue
Block a user