remove krb5_keytab.3
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@24289 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -1,482 +0,0 @@
|
|||||||
.\" Copyright (c) 2001 - 2005 Kungliga Tekniska Högskolan
|
|
||||||
.\" (Royal Institute of Technology, Stockholm, Sweden).
|
|
||||||
.\" All rights reserved.
|
|
||||||
.\"
|
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
|
||||||
.\" modification, are permitted provided that the following conditions
|
|
||||||
.\" are met:
|
|
||||||
.\"
|
|
||||||
.\" 1. Redistributions of source code must retain the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer.
|
|
||||||
.\"
|
|
||||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer in the
|
|
||||||
.\" documentation and/or other materials provided with the distribution.
|
|
||||||
.\"
|
|
||||||
.\" 3. Neither the name of the Institute nor the names of its contributors
|
|
||||||
.\" may be used to endorse or promote products derived from this software
|
|
||||||
.\" without specific prior written permission.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
||||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
.\" SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.\" $Id$
|
|
||||||
.\"
|
|
||||||
.Dd August 12, 2005
|
|
||||||
.Dt KRB5_KEYTAB 3
|
|
||||||
.Os HEIMDAL
|
|
||||||
.Sh NAME
|
|
||||||
.Nm krb5_kt_ops ,
|
|
||||||
.Nm krb5_keytab_entry ,
|
|
||||||
.Nm krb5_kt_cursor ,
|
|
||||||
.Nm krb5_kt_add_entry ,
|
|
||||||
.Nm krb5_kt_close ,
|
|
||||||
.Nm krb5_kt_compare ,
|
|
||||||
.Nm krb5_kt_copy_entry_contents ,
|
|
||||||
.Nm krb5_kt_default ,
|
|
||||||
.Nm krb5_kt_default_modify_name ,
|
|
||||||
.Nm krb5_kt_default_name ,
|
|
||||||
.Nm krb5_kt_end_seq_get ,
|
|
||||||
.Nm krb5_kt_free_entry ,
|
|
||||||
.Nm krb5_kt_get_entry ,
|
|
||||||
.Nm krb5_kt_get_name ,
|
|
||||||
.Nm krb5_kt_get_type ,
|
|
||||||
.Nm krb5_kt_next_entry ,
|
|
||||||
.Nm krb5_kt_read_service_key ,
|
|
||||||
.Nm krb5_kt_register ,
|
|
||||||
.Nm krb5_kt_remove_entry ,
|
|
||||||
.Nm krb5_kt_resolve ,
|
|
||||||
.Nm krb5_kt_start_seq_get
|
|
||||||
.Nd manage keytab (key storage) files
|
|
||||||
.Sh LIBRARY
|
|
||||||
Kerberos 5 Library (libkrb5, -lkrb5)
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.In krb5.h
|
|
||||||
.Pp
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_add_entry
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab id"
|
|
||||||
.Fa "krb5_keytab_entry *entry"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_close
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab id"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_boolean
|
|
||||||
.Fo krb5_kt_compare
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab_entry *entry"
|
|
||||||
.Fa "krb5_const_principal principal"
|
|
||||||
.Fa "krb5_kvno vno"
|
|
||||||
.Fa "krb5_enctype enctype"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_copy_entry_contents
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "const krb5_keytab_entry *in"
|
|
||||||
.Fa "krb5_keytab_entry *out"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_default
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab *id"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_default_modify_name
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "char *name"
|
|
||||||
.Fa "size_t namesize"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_default_name
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "char *name"
|
|
||||||
.Fa "size_t namesize"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_end_seq_get
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab id"
|
|
||||||
.Fa "krb5_kt_cursor *cursor"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_free_entry
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab_entry *entry"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_get_entry
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab id"
|
|
||||||
.Fa "krb5_const_principal principal"
|
|
||||||
.Fa "krb5_kvno kvno"
|
|
||||||
.Fa "krb5_enctype enctype"
|
|
||||||
.Fa "krb5_keytab_entry *entry"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_get_name
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab keytab"
|
|
||||||
.Fa "char *name"
|
|
||||||
.Fa "size_t namesize"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_get_type
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab keytab"
|
|
||||||
.Fa "char *prefix"
|
|
||||||
.Fa "size_t prefixsize"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_next_entry
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab id"
|
|
||||||
.Fa "krb5_keytab_entry *entry"
|
|
||||||
.Fa "krb5_kt_cursor *cursor"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_read_service_key
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_pointer keyprocarg"
|
|
||||||
.Fa "krb5_principal principal"
|
|
||||||
.Fa "krb5_kvno vno"
|
|
||||||
.Fa "krb5_enctype enctype"
|
|
||||||
.Fa "krb5_keyblock **key"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_register
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "const krb5_kt_ops *ops"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_remove_entry
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab id"
|
|
||||||
.Fa "krb5_keytab_entry *entry"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_resolve
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "const char *name"
|
|
||||||
.Fa "krb5_keytab *id"
|
|
||||||
.Fc
|
|
||||||
.Ft krb5_error_code
|
|
||||||
.Fo krb5_kt_start_seq_get
|
|
||||||
.Fa "krb5_context context"
|
|
||||||
.Fa "krb5_keytab id"
|
|
||||||
.Fa "krb5_kt_cursor *cursor"
|
|
||||||
.Fc
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
A keytab name is on the form
|
|
||||||
.Li type:residual .
|
|
||||||
The
|
|
||||||
.Li residual
|
|
||||||
part is specific to each keytab-type.
|
|
||||||
.Pp
|
|
||||||
When a keytab-name is resolved, the type is matched with an internal
|
|
||||||
list of keytab types. If there is no matching keytab type,
|
|
||||||
the default keytab is used. The current default type is
|
|
||||||
.Nm file .
|
|
||||||
The default value can be changed in the configuration file
|
|
||||||
.Pa /etc/krb5.conf
|
|
||||||
by setting the variable
|
|
||||||
.Li [defaults]default_keytab_name .
|
|
||||||
.Pp
|
|
||||||
The keytab types that are implemented in Heimdal
|
|
||||||
are:
|
|
||||||
.Bl -tag -width Ds
|
|
||||||
.It Nm file
|
|
||||||
store the keytab in a file, the type's name is
|
|
||||||
.Li FILE .
|
|
||||||
The residual part is a filename.
|
|
||||||
For compatibility with other Kerberos implemtation
|
|
||||||
.Li WRFILE
|
|
||||||
and
|
|
||||||
.LI JAVA14
|
|
||||||
is also accepted.
|
|
||||||
.Li WRFILE
|
|
||||||
has the same format as
|
|
||||||
.Li FILE .
|
|
||||||
.Li JAVA14
|
|
||||||
have a format that is compatible with older versions of MIT kerberos
|
|
||||||
and SUN's Java based installation. They store a truncted kvno, so
|
|
||||||
when the knvo excess 255, they are truncted in this format.
|
|
||||||
.It Nm keyfile
|
|
||||||
store the keytab in a
|
|
||||||
.Li AFS
|
|
||||||
keyfile (usually
|
|
||||||
.Pa /usr/afs/etc/KeyFile ) ,
|
|
||||||
the type's name is
|
|
||||||
.Li AFSKEYFILE .
|
|
||||||
The residual part is a filename.
|
|
||||||
.It Nm krb4
|
|
||||||
the keytab is a Kerberos 4
|
|
||||||
.Pa srvtab
|
|
||||||
that is on-the-fly converted to a keytab. The type's name is
|
|
||||||
.Li krb4 .
|
|
||||||
The residual part is a filename.
|
|
||||||
.It Nm memory
|
|
||||||
The keytab is stored in a memory segment. This allows sensitive and/or
|
|
||||||
temporary data not to be stored on disk. The type's name is
|
|
||||||
.Li MEMORY .
|
|
||||||
Each
|
|
||||||
.Li MEMORY
|
|
||||||
keytab is referenced counted by and opened by the residual name, so two
|
|
||||||
handles can point to the same memory area.
|
|
||||||
When the last user closes the entry, it disappears.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
.Nm krb5_keytab_entry
|
|
||||||
holds all data for an entry in a keytab file, like principal name,
|
|
||||||
key-type, key, key-version number, etc.
|
|
||||||
.Nm krb5_kt_cursor
|
|
||||||
holds the current position that is used when iterating through a
|
|
||||||
keytab entry with
|
|
||||||
.Fn krb5_kt_start_seq_get ,
|
|
||||||
.Fn krb5_kt_next_entry ,
|
|
||||||
and
|
|
||||||
.Fn krb5_kt_end_seq_get .
|
|
||||||
.Pp
|
|
||||||
.Nm krb5_kt_ops
|
|
||||||
contains the different operations that can be done to a keytab. This
|
|
||||||
structure is normally only used when doing a new keytab-type
|
|
||||||
implementation.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_resolve
|
|
||||||
is the equivalent of an
|
|
||||||
.Xr open 2
|
|
||||||
on keytab. Resolve the keytab name in
|
|
||||||
.Fa name
|
|
||||||
into a keytab in
|
|
||||||
.Fa id .
|
|
||||||
Returns 0 or an error. The opposite of
|
|
||||||
.Fn krb5_kt_resolve
|
|
||||||
is
|
|
||||||
.Fn krb5_kt_close .
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_close
|
|
||||||
frees all resources allocated to the keytab, even on failure.
|
|
||||||
Returns 0 or an error.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_default
|
|
||||||
sets the argument
|
|
||||||
.Fa id
|
|
||||||
to the default keytab.
|
|
||||||
Returns 0 or an error.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_default_modify_name
|
|
||||||
copies the name of the default modify keytab into
|
|
||||||
.Fa name .
|
|
||||||
Return 0 or KRB5_CONFIG_NOTENUFSPACE if
|
|
||||||
.Fa namesize
|
|
||||||
is too short.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_default_name
|
|
||||||
copies the name of the default keytab into
|
|
||||||
.Fa name .
|
|
||||||
Return 0 or KRB5_CONFIG_NOTENUFSPACE if
|
|
||||||
.Fa namesize
|
|
||||||
is too short.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_add_entry
|
|
||||||
adds a new
|
|
||||||
.Fa entry
|
|
||||||
to the keytab
|
|
||||||
.Fa id .
|
|
||||||
.Li KRB5_KT_NOWRITE
|
|
||||||
is returned if the keytab is a readonly keytab.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_compare
|
|
||||||
compares the passed in
|
|
||||||
.Fa entry
|
|
||||||
against
|
|
||||||
.Fa principal ,
|
|
||||||
.Fa vno ,
|
|
||||||
and
|
|
||||||
.Fa enctype .
|
|
||||||
Any of
|
|
||||||
.Fa principal ,
|
|
||||||
.Fa vno
|
|
||||||
or
|
|
||||||
.Fa enctype
|
|
||||||
might be 0 which acts as a wildcard. Return TRUE if they compare the
|
|
||||||
same, FALSE otherwise.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_copy_entry_contents
|
|
||||||
copies the contents of
|
|
||||||
.Fa in
|
|
||||||
into
|
|
||||||
.Fa out .
|
|
||||||
Returns 0 or an error.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_get_name
|
|
||||||
retrieves the name of the keytab
|
|
||||||
.Fa keytab
|
|
||||||
into
|
|
||||||
.Fa name ,
|
|
||||||
.Fa namesize .
|
|
||||||
Returns 0 or an error.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_get_type
|
|
||||||
retrieves the type of the keytab
|
|
||||||
.Fa keytab
|
|
||||||
and store the prefix/name for type of the keytab into
|
|
||||||
.Fa prefix ,
|
|
||||||
.Fa prefixsize .
|
|
||||||
The prefix will have the maximum length of
|
|
||||||
.Dv KRB5_KT_PREFIX_MAX_LEN
|
|
||||||
(including terminating
|
|
||||||
.Dv NUL ) .
|
|
||||||
Returns 0 or an error.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_free_entry
|
|
||||||
frees the contents of
|
|
||||||
.Fa entry .
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_start_seq_get
|
|
||||||
sets
|
|
||||||
.Fa cursor
|
|
||||||
to point at the beginning of
|
|
||||||
.Fa id .
|
|
||||||
Returns 0 or an error.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_next_entry
|
|
||||||
gets the next entry from
|
|
||||||
.Fa id
|
|
||||||
pointed to by
|
|
||||||
.Fa cursor
|
|
||||||
and advance the
|
|
||||||
.Fa cursor .
|
|
||||||
On success the returne entry must be freed with
|
|
||||||
.Fn krb5_kt_free_entry .
|
|
||||||
Returns 0 or an error.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_end_seq_get
|
|
||||||
releases all resources associated with
|
|
||||||
.Fa cursor .
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_get_entry
|
|
||||||
retrieves the keytab entry for
|
|
||||||
.Fa principal ,
|
|
||||||
.Fa kvno ,
|
|
||||||
.Fa enctype
|
|
||||||
into
|
|
||||||
.Fa entry
|
|
||||||
from the keytab
|
|
||||||
.Fa id .
|
|
||||||
When comparing an entry in the keytab to determine a match, the
|
|
||||||
function
|
|
||||||
.Fn krb5_kt_compare
|
|
||||||
is used, so the wildcard rules applies to the argument of
|
|
||||||
.F krb5_kt_get_entry
|
|
||||||
too.
|
|
||||||
On success the returne entry must be freed with
|
|
||||||
.Fn krb5_kt_free_entry .
|
|
||||||
Returns 0 or an error.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_read_service_key
|
|
||||||
reads the key identified by
|
|
||||||
.Fa ( principal ,
|
|
||||||
.Fa vno ,
|
|
||||||
.Fa enctype )
|
|
||||||
from the keytab in
|
|
||||||
.Fa keyprocarg
|
|
||||||
(the system default keytab if
|
|
||||||
.Dv NULL
|
|
||||||
is used) into
|
|
||||||
.Fa *key .
|
|
||||||
.Fa keyprocarg
|
|
||||||
is the same argument as to
|
|
||||||
.Fa name
|
|
||||||
argument to
|
|
||||||
.Fn krb5_kt_resolve .
|
|
||||||
Internal
|
|
||||||
.Fn krb5_kt_compare
|
|
||||||
will be used, so the same wildcard rules applies
|
|
||||||
to
|
|
||||||
.Fn krb5_kt_read_service_key .
|
|
||||||
On success the returned key must be freed with
|
|
||||||
.Fa krb5_free_keyblock .
|
|
||||||
Returns 0 or an error.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_remove_entry
|
|
||||||
removes the entry
|
|
||||||
.Fa entry
|
|
||||||
from the keytab
|
|
||||||
.Fa id .
|
|
||||||
When comparing an entry in the keytab to determine a match, the
|
|
||||||
function
|
|
||||||
.Fn krb5_kt_compare
|
|
||||||
is use, so the wildcard rules applies to the argument of
|
|
||||||
.Fn krb5_kt_remove_entry .
|
|
||||||
Returns 0,
|
|
||||||
.Dv KRB5_KT_NOTFOUND
|
|
||||||
if not entry matched or another error.
|
|
||||||
.Pp
|
|
||||||
.Fn krb5_kt_register
|
|
||||||
registers a new keytab type
|
|
||||||
.Fa ops .
|
|
||||||
Returns 0 or an error.
|
|
||||||
.Sh EXAMPLES
|
|
||||||
This is a minimalistic version of
|
|
||||||
.Nm ktutil .
|
|
||||||
.Pp
|
|
||||||
.Bd -literal
|
|
||||||
int
|
|
||||||
main (int argc, char **argv)
|
|
||||||
{
|
|
||||||
krb5_context context;
|
|
||||||
krb5_keytab keytab;
|
|
||||||
krb5_kt_cursor cursor;
|
|
||||||
krb5_keytab_entry entry;
|
|
||||||
krb5_error_code ret;
|
|
||||||
char *principal;
|
|
||||||
|
|
||||||
if (krb5_init_context (&context) != 0)
|
|
||||||
errx(1, "krb5_context");
|
|
||||||
|
|
||||||
ret = krb5_kt_default (context, &keytab);
|
|
||||||
if (ret)
|
|
||||||
krb5_err(context, 1, ret, "krb5_kt_default");
|
|
||||||
|
|
||||||
ret = krb5_kt_start_seq_get(context, keytab, &cursor);
|
|
||||||
if (ret)
|
|
||||||
krb5_err(context, 1, ret, "krb5_kt_start_seq_get");
|
|
||||||
while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
|
|
||||||
krb5_unparse_name_short(context, entry.principal, &principal);
|
|
||||||
printf("principal: %s\\n", principal);
|
|
||||||
free(principal);
|
|
||||||
krb5_kt_free_entry(context, &entry);
|
|
||||||
}
|
|
||||||
ret = krb5_kt_end_seq_get(context, keytab, &cursor);
|
|
||||||
if (ret)
|
|
||||||
krb5_err(context, 1, ret, "krb5_kt_end_seq_get");
|
|
||||||
ret = krb5_kt_close(context, keytab);
|
|
||||||
if (ret)
|
|
||||||
krb5_err(context, 1, ret, "krb5_kt_close");
|
|
||||||
krb5_free_context(context);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
.Ed
|
|
||||||
.Sh COMPATIBILITY
|
|
||||||
Heimdal stored the ticket flags in machine bit-field order before
|
|
||||||
Heimdal 0.7. The behavior is possible to change in with the option
|
|
||||||
.Li [libdefaults]fcc-mit-ticketflags .
|
|
||||||
Heimdal 0.7 also code to detech that ticket flags was in the wrong
|
|
||||||
order and correct them. This matters when doing delegation in GSS-API
|
|
||||||
because the client code looks at the flag to determin if it is possible
|
|
||||||
to do delegation if the user requested it.
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr krb5.conf 5 ,
|
|
||||||
.Xr kerberos 8
|
|
Reference in New Issue
Block a user