ASN1_ITEM versions of ASN1_d2i_{fp, bio} and replacement of
most of the old wrappers. A few of the old versions remain because they are non standard and the corresponding ASN1 code has not been reimplemented yet.
This commit is contained in:
parent
78d3b819f0
commit
4e1209ebf8
5
CHANGES
5
CHANGES
@ -3,6 +3,11 @@
|
||||
|
||||
Changes between 0.9.6 and 0.9.7 [xx XXX 2000]
|
||||
|
||||
*) New functions or ASN1_item_d2i_fp() and ASN1_item_d2i_bio(). These
|
||||
replace the old function pointer based I/O routines. Change most of
|
||||
the *_d2i_bio() and *_d2i_fp() functions to use these.
|
||||
[Steve Henson]
|
||||
|
||||
*) Enhance mkdef.pl to be more accepting about spacing in C preprocessor
|
||||
lines, recognice more "algorithms" that can be deselected, and make
|
||||
it complain about algorithm deselection that isn't recognised.
|
||||
|
@ -61,9 +61,11 @@
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/asn1_mac.h>
|
||||
|
||||
#define HEADER_SIZE 8
|
||||
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
|
||||
|
||||
#ifndef NO_OLD_ASN1
|
||||
#ifndef NO_FP_API
|
||||
|
||||
char *ASN1_d2i_fp(char *(*xnew)(), char *(*d2i)(), FILE *in,
|
||||
unsigned char **x)
|
||||
{
|
||||
@ -85,10 +87,65 @@ char *ASN1_d2i_fp(char *(*xnew)(), char *(*d2i)(), FILE *in,
|
||||
char *ASN1_d2i_bio(char *(*xnew)(), char *(*d2i)(), BIO *in,
|
||||
unsigned char **x)
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
unsigned char *p;
|
||||
char *ret=NULL;
|
||||
int len;
|
||||
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if(len < 0) goto err;
|
||||
|
||||
p=(unsigned char *)b->data;
|
||||
ret=d2i(x,&p,len);
|
||||
err:
|
||||
if (b != NULL) BUF_MEM_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
unsigned char *p;
|
||||
void *ret=NULL;
|
||||
int len;
|
||||
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if(len < 0) goto err;
|
||||
|
||||
p=(unsigned char *)b->data;
|
||||
ret=ASN1_item_d2i(x,&p,len, it);
|
||||
err:
|
||||
if (b != NULL) BUF_MEM_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#ifndef NO_FP_API
|
||||
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
char *ret;
|
||||
|
||||
if ((b=BIO_new(BIO_s_file())) == NULL)
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_D2I_FP,ERR_R_BUF_LIB);
|
||||
return(NULL);
|
||||
}
|
||||
BIO_set_fp(b,in,BIO_NOCLOSE);
|
||||
ret=ASN1_item_d2i_bio(it,b,x);
|
||||
BIO_free(b);
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HEADER_SIZE 8
|
||||
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
|
||||
{
|
||||
BUF_MEM *b;
|
||||
unsigned char *p;
|
||||
int i;
|
||||
char *ret=NULL;
|
||||
int ret=-1;
|
||||
ASN1_CTX c;
|
||||
int want=HEADER_SIZE;
|
||||
int eos=0;
|
||||
@ -99,7 +156,7 @@ char *ASN1_d2i_bio(char *(*xnew)(), char *(*d2i)(), BIO *in,
|
||||
if (b == NULL)
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_D2I_BIO,ERR_R_MALLOC_FAILURE);
|
||||
return(NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
@ -187,8 +244,8 @@ char *ASN1_d2i_bio(char *(*xnew)(), char *(*d2i)(), BIO *in,
|
||||
}
|
||||
}
|
||||
|
||||
p=(unsigned char *)b->data;
|
||||
ret=d2i(x,&p,off);
|
||||
*pb = b;
|
||||
return off;
|
||||
err:
|
||||
if (b != NULL) BUF_MEM_free(b);
|
||||
return(ret);
|
||||
|
@ -61,6 +61,8 @@
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#ifndef NO_OLD_ASN1
|
||||
|
||||
#ifndef NO_FP_API
|
||||
int ASN1_i2d_fp(int (*i2d)(), FILE *out, unsigned char *x)
|
||||
{
|
||||
@ -111,3 +113,51 @@ int ASN1_i2d_bio(int (*i2d)(), BIO *out, unsigned char *x)
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef NO_FP_API
|
||||
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b=BIO_new(BIO_s_file())) == NULL)
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_I2D_FP,ERR_R_BUF_LIB);
|
||||
return(0);
|
||||
}
|
||||
BIO_set_fp(b,out,BIO_NOCLOSE);
|
||||
ret=ASN1_item_i2d_bio(it,b,x);
|
||||
BIO_free(b);
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
int i,j=0,n,ret=1;
|
||||
|
||||
n = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL)
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_I2D_BIO,ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
i=BIO_write(out,&(b[j]),n);
|
||||
if (i == n) break;
|
||||
if (i <= 0)
|
||||
{
|
||||
ret=0;
|
||||
break;
|
||||
}
|
||||
j+=i;
|
||||
n-=i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
@ -805,7 +805,9 @@ void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
|
||||
|
||||
#ifndef NO_FP_API
|
||||
char *ASN1_d2i_fp(char *(*xnew)(),char *(*d2i)(),FILE *fp,unsigned char **x);
|
||||
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
|
||||
int ASN1_i2d_fp(int (*i2d)(),FILE *out,unsigned char *x);
|
||||
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
|
||||
int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags);
|
||||
#endif
|
||||
|
||||
@ -813,7 +815,9 @@ int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in);
|
||||
|
||||
#ifndef NO_BIO
|
||||
char *ASN1_d2i_bio(char *(*xnew)(),char *(*d2i)(),BIO *bp,unsigned char **x);
|
||||
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
|
||||
int ASN1_i2d_bio(int (*i2d)(),BIO *out,unsigned char *x);
|
||||
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
|
||||
int ASN1_UTCTIME_print(BIO *fp,ASN1_UTCTIME *a);
|
||||
int ASN1_GENERALIZEDTIME_print(BIO *fp,ASN1_GENERALIZEDTIME *a);
|
||||
int ASN1_TIME_print(BIO *fp,ASN1_TIME *a);
|
||||
|
@ -60,6 +60,8 @@
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#ifndef NO_ASN1_OLD
|
||||
|
||||
/* ASN1 packing and unpacking functions */
|
||||
|
||||
/* Turn an ASN1 encoded SEQUENCE OF into a STACK of structures */
|
||||
@ -143,6 +145,8 @@ ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_STRING **oct)
|
||||
return octmp;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ASN1_ITEM versions of the above */
|
||||
|
||||
ASN1_STRING *ASN1_pack_item(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
|
||||
|
@ -68,49 +68,49 @@
|
||||
int X509_verify(X509 *a, EVP_PKEY *r)
|
||||
{
|
||||
return(ASN1_item_verify(&X509_CINF_it,a->sig_alg,
|
||||
a->signature,(char *)a->cert_info,r));
|
||||
a->signature,a->cert_info,r));
|
||||
}
|
||||
|
||||
int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
|
||||
{
|
||||
return( ASN1_item_verify(&X509_REQ_INFO_it,
|
||||
a->sig_alg,a->signature,(char *)a->req_info,r));
|
||||
a->sig_alg,a->signature,a->req_info,r));
|
||||
}
|
||||
|
||||
int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r)
|
||||
{
|
||||
return(ASN1_item_verify(&X509_CRL_INFO_it,
|
||||
a->sig_alg, a->signature,(char *)a->crl,r));
|
||||
a->sig_alg, a->signature,a->crl,r));
|
||||
}
|
||||
|
||||
int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r)
|
||||
{
|
||||
return(ASN1_item_verify(&NETSCAPE_SPKAC_it,
|
||||
a->sig_algor,a->signature, (char *)a->spkac,r));
|
||||
a->sig_algor,a->signature,a->spkac,r));
|
||||
}
|
||||
|
||||
int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
|
||||
{
|
||||
return(ASN1_item_sign(&X509_CINF_it, x->cert_info->signature,
|
||||
x->sig_alg, x->signature, (char *)x->cert_info,pkey,md));
|
||||
x->sig_alg, x->signature, x->cert_info,pkey,md));
|
||||
}
|
||||
|
||||
int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
|
||||
{
|
||||
return(ASN1_item_sign(&X509_REQ_INFO_it,x->sig_alg, NULL,
|
||||
x->signature, (char *)x->req_info,pkey,md));
|
||||
x->signature, x->req_info,pkey,md));
|
||||
}
|
||||
|
||||
int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md)
|
||||
{
|
||||
return(ASN1_item_sign(&X509_CRL_INFO_it,x->crl->sig_alg,
|
||||
x->sig_alg, x->signature, (char *)x->crl,pkey,md));
|
||||
x->sig_alg, x->signature, x->crl,pkey,md));
|
||||
}
|
||||
|
||||
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md)
|
||||
{
|
||||
return(ASN1_item_sign(&NETSCAPE_SPKAC_it, x->sig_algor,NULL,
|
||||
x->signature, (char *)x->spkac,pkey,md));
|
||||
x->signature, x->spkac,pkey,md));
|
||||
}
|
||||
|
||||
X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa)
|
||||
@ -131,25 +131,23 @@ X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex)
|
||||
#ifndef NO_FP_API
|
||||
X509 *d2i_X509_fp(FILE *fp, X509 **x509)
|
||||
{
|
||||
return((X509 *)ASN1_d2i_fp((char *(*)())X509_new,
|
||||
(char *(*)())d2i_X509, (fp),(unsigned char **)(x509)));
|
||||
return ASN1_item_d2i_fp(&X509_it, fp, x509);
|
||||
}
|
||||
|
||||
int i2d_X509_fp(FILE *fp, X509 *x509)
|
||||
{
|
||||
return(ASN1_i2d_fp(i2d_X509,fp,(unsigned char *)x509));
|
||||
return ASN1_item_i2d_fp(&X509_it, fp, x509);
|
||||
}
|
||||
#endif
|
||||
|
||||
X509 *d2i_X509_bio(BIO *bp, X509 **x509)
|
||||
{
|
||||
return((X509 *)ASN1_d2i_bio((char *(*)())X509_new,
|
||||
(char *(*)())d2i_X509, (bp),(unsigned char **)(x509)));
|
||||
return ASN1_item_d2i_bio(&X509_it, bp, x509);
|
||||
}
|
||||
|
||||
int i2d_X509_bio(BIO *bp, X509 *x509)
|
||||
{
|
||||
return(ASN1_i2d_bio(i2d_X509,bp,(unsigned char *)x509));
|
||||
return ASN1_item_i2d_bio(&X509_it, bp, x509);
|
||||
}
|
||||
|
||||
X509_CRL *X509_CRL_dup(X509_CRL *crl)
|
||||
@ -160,27 +158,23 @@ X509_CRL *X509_CRL_dup(X509_CRL *crl)
|
||||
#ifndef NO_FP_API
|
||||
X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl)
|
||||
{
|
||||
return((X509_CRL *)ASN1_d2i_fp((char *(*)())
|
||||
X509_CRL_new,(char *(*)())d2i_X509_CRL, (fp),
|
||||
(unsigned char **)(crl)));
|
||||
return ASN1_item_d2i_fp(&X509_CRL_it, fp, crl);
|
||||
}
|
||||
|
||||
int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl)
|
||||
{
|
||||
return(ASN1_i2d_fp(i2d_X509_CRL,fp,(unsigned char *)crl));
|
||||
return ASN1_item_i2d_fp(&X509_CRL_it, fp, crl);
|
||||
}
|
||||
#endif
|
||||
|
||||
X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl)
|
||||
{
|
||||
return((X509_CRL *)ASN1_d2i_bio((char *(*)())
|
||||
X509_CRL_new,(char *(*)())d2i_X509_CRL, (bp),
|
||||
(unsigned char **)(crl)));
|
||||
return ASN1_item_d2i_bio(&X509_CRL_it, bp, crl);
|
||||
}
|
||||
|
||||
int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl)
|
||||
{
|
||||
return(ASN1_i2d_bio(i2d_X509_CRL,bp,(unsigned char *)crl));
|
||||
return ASN1_item_i2d_bio(&X509_CRL_it, bp, crl);
|
||||
}
|
||||
|
||||
PKCS7 *PKCS7_dup(PKCS7 *p7)
|
||||
@ -191,27 +185,23 @@ PKCS7 *PKCS7_dup(PKCS7 *p7)
|
||||
#ifndef NO_FP_API
|
||||
PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7)
|
||||
{
|
||||
return((PKCS7 *)ASN1_d2i_fp((char *(*)())
|
||||
PKCS7_new,(char *(*)())d2i_PKCS7, (fp),
|
||||
(unsigned char **)(p7)));
|
||||
return ASN1_item_d2i_fp(&PKCS7_it, fp, p7);
|
||||
}
|
||||
|
||||
int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7)
|
||||
{
|
||||
return(ASN1_i2d_fp(i2d_PKCS7,fp,(unsigned char *)p7));
|
||||
return ASN1_item_i2d_fp(&PKCS7_it, fp, p7);
|
||||
}
|
||||
#endif
|
||||
|
||||
PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7)
|
||||
{
|
||||
return((PKCS7 *)ASN1_d2i_bio((char *(*)())
|
||||
PKCS7_new,(char *(*)())d2i_PKCS7, (bp),
|
||||
(unsigned char **)(p7)));
|
||||
return ASN1_item_d2i_bio(&PKCS7_it, bp, p7);
|
||||
}
|
||||
|
||||
int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7)
|
||||
{
|
||||
return(ASN1_i2d_bio(i2d_PKCS7,bp,(unsigned char *)p7));
|
||||
return ASN1_item_i2d_bio(&PKCS7_it, bp, p7);
|
||||
}
|
||||
|
||||
X509_REQ *X509_REQ_dup(X509_REQ *req)
|
||||
@ -222,27 +212,23 @@ X509_REQ *X509_REQ_dup(X509_REQ *req)
|
||||
#ifndef NO_FP_API
|
||||
X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req)
|
||||
{
|
||||
return((X509_REQ *)ASN1_d2i_fp((char *(*)())
|
||||
X509_REQ_new, (char *(*)())d2i_X509_REQ, (fp),
|
||||
(unsigned char **)(req)));
|
||||
return ASN1_item_d2i_fp(&X509_REQ_it, fp, req);
|
||||
}
|
||||
|
||||
int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req)
|
||||
{
|
||||
return(ASN1_i2d_fp(i2d_X509_REQ,fp,(unsigned char *)req));
|
||||
return ASN1_item_i2d_fp(&X509_REQ_it, fp, req);
|
||||
}
|
||||
#endif
|
||||
|
||||
X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req)
|
||||
{
|
||||
return((X509_REQ *)ASN1_d2i_bio((char *(*)())
|
||||
X509_REQ_new, (char *(*)())d2i_X509_REQ, (bp),
|
||||
(unsigned char **)(req)));
|
||||
return ASN1_item_d2i_bio(&X509_REQ_it, bp, req);
|
||||
}
|
||||
|
||||
int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req)
|
||||
{
|
||||
return(ASN1_i2d_bio(i2d_X509_REQ,bp,(unsigned char *)req));
|
||||
return ASN1_item_i2d_bio(&X509_REQ_it, bp, req);
|
||||
}
|
||||
|
||||
#ifndef NO_RSA
|
||||
@ -259,23 +245,20 @@ RSA *RSAPrivateKey_dup(RSA *rsa)
|
||||
#ifndef NO_FP_API
|
||||
RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
|
||||
{
|
||||
return((RSA *)ASN1_d2i_fp((char *(*)())
|
||||
RSA_new,(char *(*)())d2i_RSAPrivateKey, (fp),
|
||||
(unsigned char **)(rsa)));
|
||||
return ASN1_item_d2i_fp(&RSAPrivateKey_it, fp, rsa);
|
||||
}
|
||||
|
||||
int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa)
|
||||
{
|
||||
return(ASN1_i2d_fp(i2d_RSAPrivateKey,fp,(unsigned char *)rsa));
|
||||
return ASN1_item_i2d_fp(&RSAPrivateKey_it, fp, rsa);
|
||||
}
|
||||
|
||||
RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa)
|
||||
{
|
||||
return((RSA *)ASN1_d2i_fp((char *(*)())
|
||||
RSA_new,(char *(*)())d2i_RSAPublicKey, (fp),
|
||||
(unsigned char **)(rsa)));
|
||||
return ASN1_item_d2i_fp(&RSAPublicKey_it, fp, rsa);
|
||||
}
|
||||
|
||||
|
||||
RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
|
||||
{
|
||||
return((RSA *)ASN1_d2i_fp((char *(*)())
|
||||
@ -285,7 +268,7 @@ RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
|
||||
|
||||
int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa)
|
||||
{
|
||||
return(ASN1_i2d_fp(i2d_RSAPublicKey,fp,(unsigned char *)rsa));
|
||||
return ASN1_item_i2d_fp(&RSAPublicKey_it, fp, rsa);
|
||||
}
|
||||
|
||||
int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
|
||||
@ -296,23 +279,20 @@ int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
|
||||
|
||||
RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
|
||||
{
|
||||
return((RSA *)ASN1_d2i_bio((char *(*)())
|
||||
RSA_new,(char *(*)())d2i_RSAPrivateKey, (bp),
|
||||
(unsigned char **)(rsa)));
|
||||
return ASN1_item_d2i_bio(&RSAPrivateKey_it, bp, rsa);
|
||||
}
|
||||
|
||||
int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
|
||||
{
|
||||
return(ASN1_i2d_bio(i2d_RSAPrivateKey,bp,(unsigned char *)rsa));
|
||||
return ASN1_item_i2d_bio(&RSAPrivateKey_it, bp, rsa);
|
||||
}
|
||||
|
||||
RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)
|
||||
{
|
||||
return((RSA *)ASN1_d2i_bio((char *(*)())
|
||||
RSA_new,(char *(*)())d2i_RSAPublicKey, (bp),
|
||||
(unsigned char **)(rsa)));
|
||||
return ASN1_item_d2i_bio(&RSAPublicKey_it, bp, rsa);
|
||||
}
|
||||
|
||||
|
||||
RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
|
||||
{
|
||||
return((RSA *)ASN1_d2i_bio((char *(*)())
|
||||
@ -322,7 +302,7 @@ RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
|
||||
|
||||
int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa)
|
||||
{
|
||||
return(ASN1_i2d_bio(i2d_RSAPublicKey,bp,(unsigned char *)rsa));
|
||||
return ASN1_item_i2d_bio(&RSAPublicKey_it, bp, rsa);
|
||||
}
|
||||
|
||||
int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
|
||||
|
Loading…
Reference in New Issue
Block a user