mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 12:00:56 +01:00
fixed memory leaks
This commit is contained in:
@@ -175,6 +175,11 @@ int pcpvault_addkey(PCPCTX *ptx, vault_t *vault, void *item, uint8_t type);
|
|||||||
*/
|
*/
|
||||||
int pcpvault_close(PCPCTX *ptx, vault_t *vault);
|
int pcpvault_close(PCPCTX *ptx, vault_t *vault);
|
||||||
|
|
||||||
|
/** Free vault resources
|
||||||
|
|
||||||
|
\param[in] vault The vault object.
|
||||||
|
*/
|
||||||
|
void pcpvault_free(vault_t *vault);
|
||||||
|
|
||||||
/** Reads in the vault contents.
|
/** Reads in the vault contents.
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,10 @@ void fatal(PCPCTX *ptx, const char * fmt, ...) {
|
|||||||
|
|
||||||
void fatals_reset(PCPCTX *ptx) {
|
void fatals_reset(PCPCTX *ptx) {
|
||||||
ptx->pcp_errset = 0;
|
ptx->pcp_errset = 0;
|
||||||
|
if(ptx->pcp_err != NULL) {
|
||||||
|
free(ptx->pcp_err);
|
||||||
|
ptx->pcp_err = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fatals_ifany(PCPCTX *ptx) {
|
void fatals_ifany(PCPCTX *ptx) {
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
|
|||||||
if(key->nonce[0] == 0) {
|
if(key->nonce[0] == 0) {
|
||||||
byte *nonce = pcp_gennonce();
|
byte *nonce = pcp_gennonce();
|
||||||
memcpy (key->nonce, nonce, crypto_secretbox_NONCEBYTES);
|
memcpy (key->nonce, nonce, crypto_secretbox_NONCEBYTES);
|
||||||
|
ucfree(nonce, crypto_secretbox_NONCEBYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
|
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "keyhash.h"
|
#include "keyhash.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
void pcphash_del(PCPCTX *ptx, void *key, int type) {
|
void pcphash_del(PCPCTX *ptx, void *key, int type) {
|
||||||
if(type == PCP_KEY_TYPE_SECRET) {
|
if(type == PCP_KEY_TYPE_SECRET) {
|
||||||
|
|||||||
@@ -340,11 +340,11 @@ pcp_ks_bundle_t *pcp_import_pub_rfc(PCPCTX *ptx, Buffer *blob) {
|
|||||||
pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) {
|
pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) {
|
||||||
char *date = ucmalloc(20);
|
char *date = ucmalloc(20);
|
||||||
char *parts = NULL;
|
char *parts = NULL;
|
||||||
byte *sig = ucmalloc(crypto_sign_BYTES);;
|
byte *sig = ucmalloc(crypto_sign_BYTES);
|
||||||
int pnum;
|
int pnum;
|
||||||
pbp_pubkey_t *b = ucmalloc(sizeof(pbp_pubkey_t));
|
pbp_pubkey_t *b = NULL;
|
||||||
pcp_pubkey_t *tmp = ucmalloc(sizeof(pcp_pubkey_t));
|
pcp_pubkey_t *tmp = NULL;
|
||||||
pcp_pubkey_t *pub = ucmalloc(sizeof(pcp_pubkey_t));
|
pcp_pubkey_t *pub = NULL;
|
||||||
|
|
||||||
buffer_get_chunk(blob, sig, crypto_sign_BYTES);
|
buffer_get_chunk(blob, sig, crypto_sign_BYTES);
|
||||||
|
|
||||||
@@ -354,6 +354,7 @@ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) {
|
|||||||
goto errimp2;
|
goto errimp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b = ucmalloc(sizeof(pbp_pubkey_t)); /* FIXME: separate type really needed? */
|
||||||
buffer_get_chunk(blob, b->sigpub, crypto_sign_PUBLICKEYBYTES);
|
buffer_get_chunk(blob, b->sigpub, crypto_sign_PUBLICKEYBYTES);
|
||||||
buffer_get_chunk(blob, b->edpub, crypto_sign_PUBLICKEYBYTES);
|
buffer_get_chunk(blob, b->edpub, crypto_sign_PUBLICKEYBYTES);
|
||||||
buffer_get_chunk(blob, b->pub, crypto_box_PUBLICKEYBYTES);
|
buffer_get_chunk(blob, b->pub, crypto_box_PUBLICKEYBYTES);
|
||||||
@@ -364,6 +365,7 @@ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) {
|
|||||||
if(strptime(date, "%Y-%m-%dT%H:%M:%S", &c) == NULL) {
|
if(strptime(date, "%Y-%m-%dT%H:%M:%S", &c) == NULL) {
|
||||||
fatal(ptx, "Failed to parse creation time in PBP public key file\n");
|
fatal(ptx, "Failed to parse creation time in PBP public key file\n");
|
||||||
free(date);
|
free(date);
|
||||||
|
ucfree(b, sizeof(pbp_pubkey_t));
|
||||||
goto errimp2;
|
goto errimp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,6 +375,7 @@ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) {
|
|||||||
/* parse the name */
|
/* parse the name */
|
||||||
parts = strtok (b->name, "<>");
|
parts = strtok (b->name, "<>");
|
||||||
pnum = 0;
|
pnum = 0;
|
||||||
|
pub = ucmalloc(sizeof(pcp_pubkey_t));
|
||||||
while (parts != NULL) {
|
while (parts != NULL) {
|
||||||
if(pnum == 0)
|
if(pnum == 0)
|
||||||
memcpy(pub->owner, parts, strlen(parts));
|
memcpy(pub->owner, parts, strlen(parts));
|
||||||
@@ -396,8 +399,10 @@ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) {
|
|||||||
memcpy(pub->edpub, b->edpub, crypto_sign_PUBLICKEYBYTES);
|
memcpy(pub->edpub, b->edpub, crypto_sign_PUBLICKEYBYTES);
|
||||||
memcpy(pub->id, pcp_getpubkeyid(pub), 17);
|
memcpy(pub->id, pcp_getpubkeyid(pub), 17);
|
||||||
_lc(pub->owner);
|
_lc(pub->owner);
|
||||||
|
ucfree(b, sizeof(pbp_pubkey_t));
|
||||||
|
|
||||||
/* edpub used for signing, might differ */
|
/* edpub used for signing, might differ */
|
||||||
|
tmp = ucmalloc(sizeof(pcp_pubkey_t));
|
||||||
memcpy(tmp->edpub, b->sigpub, crypto_sign_PUBLICKEYBYTES);
|
memcpy(tmp->edpub, b->sigpub, crypto_sign_PUBLICKEYBYTES);
|
||||||
|
|
||||||
byte *verify = pcp_ed_verify(ptx, buffer_get(blob), buffer_size(blob), tmp);
|
byte *verify = pcp_ed_verify(ptx, buffer_get(blob), buffer_size(blob), tmp);
|
||||||
@@ -421,11 +426,14 @@ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) {
|
|||||||
pub->valid = 1;
|
pub->valid = 1;
|
||||||
bundle->s = sk;
|
bundle->s = sk;
|
||||||
bundle->p = pub;
|
bundle->p = pub;
|
||||||
|
free(verify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(sig);
|
||||||
return bundle;
|
return bundle;
|
||||||
|
|
||||||
errimp2:
|
errimp2:
|
||||||
|
free(sig);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -819,7 +827,8 @@ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphras
|
|||||||
cipherlen = buffer_left(cipher);
|
cipherlen = buffer_left(cipher);
|
||||||
if(cipherlen < minlen) {
|
if(cipherlen < minlen) {
|
||||||
fatal(ptx, "failed to decrypt the secret key file:\n"
|
fatal(ptx, "failed to decrypt the secret key file:\n"
|
||||||
"expected encrypted secret key size %ld is less than minimum len %ld\n", cipherlen, minlen);
|
"expected encrypted secret key size %ld is less than minimum len %ld\n",
|
||||||
|
cipherlen, minlen);
|
||||||
goto impserr1;
|
goto impserr1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,17 +866,19 @@ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphras
|
|||||||
sk->version = buffer_get32na(blob);
|
sk->version = buffer_get32na(blob);
|
||||||
sk->serial = buffer_get32na(blob);
|
sk->serial = buffer_get32na(blob);
|
||||||
|
|
||||||
/* ready */
|
|
||||||
ucfree(clear, cipherlen - PCP_CRYPTO_ADD);
|
|
||||||
ucfree(nonce, crypto_secretbox_NONCEBYTES);
|
|
||||||
buffer_free(blob);
|
|
||||||
|
|
||||||
/* fill in the calculated fields */
|
/* fill in the calculated fields */
|
||||||
char *id = pcp_getkeyid(sk);
|
char *id = pcp_getkeyid(sk);
|
||||||
memcpy (sk->id, id, 17);
|
memcpy (sk->id, id, 17);
|
||||||
free(id);
|
|
||||||
sk->type = PCP_KEY_TYPE_SECRET;
|
sk->type = PCP_KEY_TYPE_SECRET;
|
||||||
|
|
||||||
|
/* ready */
|
||||||
|
ucfree(clear, cipherlen - PCP_CRYPTO_ADD);
|
||||||
|
ucfree(nonce, crypto_secretbox_NONCEBYTES);
|
||||||
|
buffer_free(blob);
|
||||||
|
ucfree(symkey, 64);
|
||||||
|
free(id);
|
||||||
|
|
||||||
return sk;
|
return sk;
|
||||||
|
|
||||||
impserr2:
|
impserr2:
|
||||||
@@ -877,5 +888,7 @@ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphras
|
|||||||
ucfree(nonce, crypto_secretbox_NONCEBYTES);
|
ucfree(nonce, crypto_secretbox_NONCEBYTES);
|
||||||
ucfree(sk, sizeof(pcp_key_t));
|
ucfree(sk, sizeof(pcp_key_t));
|
||||||
buffer_free(blob);
|
buffer_free(blob);
|
||||||
|
if(symkey != NULL)
|
||||||
|
ucfree(symkey, 64);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ void ps_setdetermine(Pcpstream *stream, size_t blocksize) {
|
|||||||
stream->determine = 1;
|
stream->determine = 1;
|
||||||
/* expand blocksize by the remainder of %5 plus another 5 bytes
|
/* expand blocksize by the remainder of %5 plus another 5 bytes
|
||||||
for the pad blob */
|
for the pad blob */
|
||||||
//stream->blocksize = blocksize + (5 - (blocksize % 5)) + 5;
|
|
||||||
stream->blocksize = blocksize + (blocksize / 4) + 5;
|
stream->blocksize = blocksize + (blocksize / 4) + 5;
|
||||||
//fprintf(stderr, "blocksize: %ld\n", stream->blocksize);
|
//fprintf(stderr, "blocksize: %ld\n", stream->blocksize);
|
||||||
if(stream->cache == NULL) {
|
if(stream->cache == NULL) {
|
||||||
@@ -243,6 +242,7 @@ size_t ps_read_next(Pcpstream *stream) {
|
|||||||
void *buf = ucmalloc(stream->blocksize);
|
void *buf = ucmalloc(stream->blocksize);
|
||||||
size_t got = ps_read_raw(stream, buf, stream->blocksize);
|
size_t got = ps_read_raw(stream, buf, stream->blocksize);
|
||||||
buffer_add(stream->next, buf, got);
|
buffer_add(stream->next, buf, got);
|
||||||
|
free(buf);
|
||||||
return got;
|
return got;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,6 +459,7 @@ size_t ps_read_decode(Pcpstream *stream) {
|
|||||||
else {
|
else {
|
||||||
/* yes, successfully decoded it, put into cache */
|
/* yes, successfully decoded it, put into cache */
|
||||||
buffer_add(stream->next, bin, binlen);
|
buffer_add(stream->next, bin, binlen);
|
||||||
|
free(bin);
|
||||||
outlen = binlen;
|
outlen = binlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,6 +530,7 @@ size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes) {
|
|||||||
/* there is an overlapping rest, put it into the cache
|
/* there is an overlapping rest, put it into the cache
|
||||||
the caller needs to call ps_finish() to put it out */
|
the caller needs to call ps_finish() to put it out */
|
||||||
buffer_add(stream->cache, aside, overlap);
|
buffer_add(stream->cache, aside, overlap);
|
||||||
|
free(aside);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ vault_t *pcpvault_new(PCPCTX *ptx, char *filename, int is_tmp) {
|
|||||||
return vault;
|
return vault;
|
||||||
|
|
||||||
errn:
|
errn:
|
||||||
free(vault);
|
pcpvault_free(vault);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +118,7 @@ int pcpvault_create(PCPCTX *ptx, vault_t *vault) {
|
|||||||
fseek(vault->fd, 0, SEEK_SET);
|
fseek(vault->fd, 0, SEEK_SET);
|
||||||
|
|
||||||
fwrite(header, sizeof(vault_header_t), 1, vault->fd);
|
fwrite(header, sizeof(vault_header_t), 1, vault->fd);
|
||||||
|
free(header);
|
||||||
|
|
||||||
if(ferror(vault->fd) != 0) {
|
if(ferror(vault->fd) != 0) {
|
||||||
fatal(ptx, "Failed to write fileheader to vault %s!\n", vault->filename);
|
fatal(ptx, "Failed to write fileheader to vault %s!\n", vault->filename);
|
||||||
@@ -138,6 +139,7 @@ int pcpvault_additem(PCPCTX *ptx, vault_t *vault, void *item, size_t itemsize, u
|
|||||||
ih2be(header);
|
ih2be(header);
|
||||||
|
|
||||||
fwrite(header, sizeof(vault_item_header_t), 1, vault->fd);
|
fwrite(header, sizeof(vault_item_header_t), 1, vault->fd);
|
||||||
|
free(header);
|
||||||
fwrite(item, itemsize, 1, vault->fd);
|
fwrite(item, itemsize, 1, vault->fd);
|
||||||
|
|
||||||
if(ferror(vault->fd) != 0) {
|
if(ferror(vault->fd) != 0) {
|
||||||
@@ -156,22 +158,21 @@ int pcpvault_addkey(PCPCTX *ptx, vault_t *vault, void *item, uint8_t type) {
|
|||||||
size_t itemsize;
|
size_t itemsize;
|
||||||
|
|
||||||
void *saveitem = NULL;
|
void *saveitem = NULL;
|
||||||
Buffer *blob = buffer_new(PCP_RAW_KEYSIZE, "bs");
|
Buffer *blob = NULL;
|
||||||
|
|
||||||
if(type == PCP_KEY_TYPE_PUBLIC) {
|
if(type == PCP_KEY_TYPE_PUBLIC) {
|
||||||
itemsize = PCP_RAW_PUBKEYSIZE;
|
itemsize = PCP_RAW_PUBKEYSIZE;
|
||||||
saveitem = ucmalloc(sizeof(pcp_pubkey_t));
|
saveitem = ucmalloc(sizeof(pcp_pubkey_t));
|
||||||
memcpy(saveitem, item, sizeof(pcp_pubkey_t));
|
memcpy(saveitem, item, sizeof(pcp_pubkey_t));
|
||||||
pubkey2be((pcp_pubkey_t *)item);
|
pubkey2be((pcp_pubkey_t *)item);
|
||||||
|
blob = buffer_new(PCP_RAW_KEYSIZE, "bs");
|
||||||
pcp_pubkeyblob(blob, (pcp_pubkey_t *)item);
|
pcp_pubkeyblob(blob, (pcp_pubkey_t *)item);
|
||||||
}
|
}
|
||||||
else if(type == PCP_KEYSIG_NATIVE || type == PCP_KEYSIG_NATIVE) {
|
else if(type == PCP_KEYSIG_NATIVE || type == PCP_KEYSIG_NATIVE) {
|
||||||
pcp_keysig_t *sk = (pcp_keysig_t *)item;
|
saveitem = ucmalloc(sizeof(pcp_keysig_t));
|
||||||
|
memcpy(saveitem, item, sizeof(pcp_keysig_t));
|
||||||
blob = pcp_keysig2blob(sk);
|
blob = pcp_keysig2blob(item);
|
||||||
itemsize = buffer_size(blob);
|
itemsize = buffer_size(blob);
|
||||||
|
|
||||||
saveitem = (void *)sk;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
itemsize = PCP_RAW_KEYSIZE;
|
itemsize = PCP_RAW_KEYSIZE;
|
||||||
@@ -182,7 +183,6 @@ int pcpvault_addkey(PCPCTX *ptx, vault_t *vault, void *item, uint8_t type) {
|
|||||||
pcp_seckeyblob(blob, (pcp_key_t *)item);
|
pcp_seckeyblob(blob, (pcp_key_t *)item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(tmp != NULL) {
|
if(tmp != NULL) {
|
||||||
if(pcpvault_copy(ptx, vault, tmp) != 0)
|
if(pcpvault_copy(ptx, vault, tmp) != 0)
|
||||||
goto errak1;
|
goto errak1;
|
||||||
@@ -200,7 +200,7 @@ int pcpvault_addkey(PCPCTX *ptx, vault_t *vault, void *item, uint8_t type) {
|
|||||||
goto errak1;
|
goto errak1;
|
||||||
}
|
}
|
||||||
buffer_free(blob);
|
buffer_free(blob);
|
||||||
free(tmp);
|
pcpvault_free(tmp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,11 +265,14 @@ void pcpvault_update_checksum(PCPCTX *ptx, vault_t *vault) {
|
|||||||
header->version = PCP_VAULT_VERSION;
|
header->version = PCP_VAULT_VERSION;
|
||||||
memcpy(header->checksum, checksum, 32);
|
memcpy(header->checksum, checksum, 32);
|
||||||
memcpy(vault->checksum, checksum, 32);
|
memcpy(vault->checksum, checksum, 32);
|
||||||
|
ucfree(checksum, 32);
|
||||||
|
|
||||||
vh2be(header);
|
vh2be(header);
|
||||||
|
|
||||||
fseek(vault->fd, 0, SEEK_SET);
|
fseek(vault->fd, 0, SEEK_SET);
|
||||||
fwrite(header, sizeof(vault_header_t), 1, vault->fd);
|
fwrite(header, sizeof(vault_header_t), 1, vault->fd);
|
||||||
|
free(header);
|
||||||
|
|
||||||
fseek(vault->fd, 0, SEEK_END);
|
fseek(vault->fd, 0, SEEK_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,8 +339,10 @@ int pcpvault_copy(PCPCTX *ptx, vault_t *tmp, vault_t *vault) {
|
|||||||
if(fwrite(in, tmpsize, 1, vault->fd) != 1) {
|
if(fwrite(in, tmpsize, 1, vault->fd) != 1) {
|
||||||
fatal(ptx, "Failed to copy %s to %s (write) [keeping %s]\n",
|
fatal(ptx, "Failed to copy %s to %s (write) [keeping %s]\n",
|
||||||
tmp->filename, vault->filename, tmp->filename);
|
tmp->filename, vault->filename, tmp->filename);
|
||||||
|
ucfree(in, tmpsize);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
ucfree(in, tmpsize);
|
||||||
|
|
||||||
if(fflush(vault->fd) != 0) {
|
if(fflush(vault->fd) != 0) {
|
||||||
fatal(ptx, "Failed to copy %s to %s (flush) [keeping %s]\n",
|
fatal(ptx, "Failed to copy %s to %s (flush) [keeping %s]\n",
|
||||||
@@ -372,13 +377,19 @@ int pcpvault_close(PCPCTX *ptx, vault_t *vault) {
|
|||||||
}
|
}
|
||||||
fclose(vault->fd);
|
fclose(vault->fd);
|
||||||
}
|
}
|
||||||
free(vault->filename);
|
pcpvault_free(vault);
|
||||||
free(vault);
|
|
||||||
vault = NULL;
|
vault = NULL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pcpvault_free(vault_t *vault) {
|
||||||
|
if(vault != NULL) {
|
||||||
|
free(vault->filename);
|
||||||
|
free(vault);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vault_header_t * vh2be(vault_header_t *h) {
|
vault_header_t * vh2be(vault_header_t *h) {
|
||||||
#ifdef __CPU_IS_BIG_ENDIAN
|
#ifdef __CPU_IS_BIG_ENDIAN
|
||||||
return h;
|
return h;
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ byte *pcp_z85_decode(PCPCTX *ptx, char *z85block, size_t *dstlen) {
|
|||||||
|
|
||||||
if(zmq_z85_decode(bin, z85block) == NULL) {
|
if(zmq_z85_decode(bin, z85block) == NULL) {
|
||||||
fatal(ptx, "zmq_z85_decode() failed, input size ! mod 5 (got %ld)\n", strlen(z85block));
|
fatal(ptx, "zmq_z85_decode() failed, input size ! mod 5 (got %ld)\n", strlen(z85block));
|
||||||
|
free(bin);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -667,7 +667,6 @@ int pcp_import (vault_t *vault, FILE *in, char *passwd) {
|
|||||||
if(pcp_storekey(sk) == 0) {
|
if(pcp_storekey(sk) == 0) {
|
||||||
pcpkey_printshortinfo(sk);
|
pcpkey_printshortinfo(sk);
|
||||||
success = 0;
|
success = 0;
|
||||||
sk = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user