Skip to content
Permalink
Browse files
some language improvements; ok markus
  • Loading branch information
djmdjm committed Jul 5, 2020
1 parent ffe6168 commit 5bde2954c180034a27b079acaff46073dc75139b
@@ -140,7 +140,7 @@ window space and may be sent even if no window space is available.
NB. due to certain broken SSH implementations aborting upon receipt
of this message (in contravention of RFC4254 section 5.4), this
message is only sent to OpenSSH peers (identified by banner).
Other SSH implementations may be whitelisted to receive this message
Other SSH implementations may be listed to receive this message
upon request.

2.2. connection: disallow additional sessions extension
@@ -169,7 +169,7 @@ Note that this is not a general defence against compromised clients
NB. due to certain broken SSH implementations aborting upon receipt
of this message, the no-more-sessions request is only sent to OpenSSH
servers (identified by banner). Other SSH implementations may be
whitelisted to receive this message upon request.
listed to receive this message upon request.

2.3. connection: Tunnel forward extension "tun@openssh.com"

@@ -496,4 +496,4 @@ OpenSSH's connection multiplexing uses messages as described in
PROTOCOL.mux over a Unix domain socket for communications between a
master instance and later clients.

$OpenBSD: PROTOCOL,v 1.37 2020/02/21 00:04:43 dtucker Exp $
$OpenBSD: PROTOCOL,v 1.38 2020/07/05 23:59:45 djm Exp $
@@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.133 2020/01/25 22:49:38 djm Exp $ */
/* $OpenBSD: channels.h,v 1.134 2020/07/05 23:59:45 djm Exp $ */

/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -52,11 +52,11 @@
#define SSH_CHANNEL_DYNAMIC 13
#define SSH_CHANNEL_ZOMBIE 14 /* Almost dead. */
#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux client */
#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */
#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-slave */
#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-client */
#define SSH_CHANNEL_RDYNAMIC_OPEN 21 /* reverse SOCKS, parsing request */
#define SSH_CHANNEL_RDYNAMIC_FINISH 22 /* reverse SOCKS, finishing connect */
#define SSH_CHANNEL_MAX_TYPE 23
@@ -1,4 +1,4 @@
/* $OpenBSD: compat.c,v 1.114 2020/06/01 07:11:38 dtucker Exp $ */
/* $OpenBSD: compat.c,v 1.115 2020/07/05 23:59:45 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@@ -161,8 +161,8 @@ compat_cipher_proposal(char *cipher_prop)
if (!(datafellows & SSH_BUG_BIGENDIANAES))
return cipher_prop;
debug2("%s: original cipher proposal: %s", __func__, cipher_prop);
if ((cipher_prop = match_filter_blacklist(cipher_prop, "aes*")) == NULL)
fatal("match_filter_blacklist failed");
if ((cipher_prop = match_filter_denylist(cipher_prop, "aes*")) == NULL)
fatal("match_filter_denylist failed");
debug2("%s: compat cipher proposal: %s", __func__, cipher_prop);
if (*cipher_prop == '\0')
fatal("No supported ciphers found");
@@ -175,8 +175,8 @@ compat_pkalg_proposal(char *pkalg_prop)
if (!(datafellows & SSH_BUG_RSASIGMD5))
return pkalg_prop;
debug2("%s: original public key proposal: %s", __func__, pkalg_prop);
if ((pkalg_prop = match_filter_blacklist(pkalg_prop, "ssh-rsa")) == NULL)
fatal("match_filter_blacklist failed");
if ((pkalg_prop = match_filter_denylist(pkalg_prop, "ssh-rsa")) == NULL)
fatal("match_filter_denylist failed");
debug2("%s: compat public key proposal: %s", __func__, pkalg_prop);
if (*pkalg_prop == '\0')
fatal("No supported PK algorithms found");
@@ -190,14 +190,14 @@ compat_kex_proposal(char *p)
return p;
debug2("%s: original KEX proposal: %s", __func__, p);
if ((datafellows & SSH_BUG_CURVE25519PAD) != 0)
if ((p = match_filter_blacklist(p,
if ((p = match_filter_denylist(p,
"curve25519-sha256@libssh.org")) == NULL)
fatal("match_filter_blacklist failed");
fatal("match_filter_denylist failed");
if ((datafellows & SSH_OLD_DHGEX) != 0) {
if ((p = match_filter_blacklist(p,
if ((p = match_filter_denylist(p,
"diffie-hellman-group-exchange-sha256,"
"diffie-hellman-group-exchange-sha1")) == NULL)
fatal("match_filter_blacklist failed");
fatal("match_filter_denylist failed");
}
debug2("%s: compat KEX proposal: %s", __func__, p);
if (*p == '\0')
@@ -1,4 +1,4 @@
/* $OpenBSD: kex.c,v 1.158 2020/03/13 04:01:56 djm Exp $ */
/* $OpenBSD: kex.c,v 1.159 2020/07/05 23:59:45 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@@ -234,7 +234,7 @@ kex_assemble_names(char **listp, const char *def, const char *all)
list = tmp;
} else if (*list == '-') {
/* Remove names from default list */
if ((*listp = match_filter_blacklist(def, list + 1)) == NULL) {
if ((*listp = match_filter_denylist(def, list + 1)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
@@ -271,7 +271,7 @@ kex_assemble_names(char **listp, const char *def, const char *all)
goto fail;
}
free(matching);
if ((matching = match_filter_whitelist(all, cp)) == NULL) {
if ((matching = match_filter_allowlist(all, cp)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
@@ -1,4 +1,4 @@
/* $OpenBSD: match.c,v 1.41 2019/11/13 04:47:52 deraadt Exp $ */
/* $OpenBSD: match.c,v 1.42 2020/07/05 23:59:45 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -302,13 +302,13 @@ match_list(const char *client, const char *server, u_int *next)

/*
* Filter proposal using pattern-list filter.
* "blacklist" determines sense of filter:
* "denylist" determines sense of filter:
* non-zero indicates that items matching filter should be excluded.
* zero indicates that only items matching filter should be included.
* returns NULL on allocation error, otherwise caller must free result.
*/
static char *
filter_list(const char *proposal, const char *filter, int blacklist)
filter_list(const char *proposal, const char *filter, int denylist)
{
size_t len = strlen(proposal) + 1;
char *fix_prop = malloc(len);
@@ -326,7 +326,7 @@ filter_list(const char *proposal, const char *filter, int blacklist)
*fix_prop = '\0';
while ((cp = strsep(&tmp, ",")) != NULL) {
r = match_pattern_list(cp, filter, 0);
if ((blacklist && r != 1) || (!blacklist && r == 1)) {
if ((denylist && r != 1) || (!denylist && r == 1)) {
if (*fix_prop != '\0')
strlcat(fix_prop, ",", len);
strlcat(fix_prop, cp, len);
@@ -341,7 +341,7 @@ filter_list(const char *proposal, const char *filter, int blacklist)
* the 'filter' pattern list. Caller must free returned string.
*/
char *
match_filter_blacklist(const char *proposal, const char *filter)
match_filter_denylist(const char *proposal, const char *filter)
{
return filter_list(proposal, filter, 1);
}
@@ -351,7 +351,7 @@ match_filter_blacklist(const char *proposal, const char *filter)
* the 'filter' pattern list. Caller must free returned string.
*/
char *
match_filter_whitelist(const char *proposal, const char *filter)
match_filter_allowlist(const char *proposal, const char *filter)
{
return filter_list(proposal, filter, 0);
}
@@ -1,4 +1,4 @@
/* $OpenBSD: match.h,v 1.19 2019/03/06 22:14:23 dtucker Exp $ */
/* $OpenBSD: match.h,v 1.20 2020/07/05 23:59:45 djm Exp $ */

/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -21,8 +21,8 @@ int match_hostname(const char *, const char *);
int match_host_and_ip(const char *, const char *, const char *);
int match_user(const char *, const char *, const char *, const char *);
char *match_list(const char *, const char *, u_int *);
char *match_filter_blacklist(const char *, const char *);
char *match_filter_whitelist(const char *, const char *);
char *match_filter_denylist(const char *, const char *);
char *match_filter_allowlist(const char *, const char *);

/* addrmatch.c */
int addr_match_list(const char *, const char *);
@@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.210 2020/03/13 03:17:07 djm Exp $ */
/* $OpenBSD: monitor.c,v 1.211 2020/07/05 23:59:45 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -1324,7 +1324,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
if (fd0 != 0)
error("%s: fd0 %d != 0", __func__, fd0);

/* slave is not needed */
/* only need pty master side */

This comment has been minimized.

Copy link
@Cactii1

Cactii1 Jul 19, 2020

Author can't even get it right...

close(s->ttyfd);
s->ttyfd = s->ptyfd;
/* no need to dup() because nobody closes ptyfd */
@@ -1,4 +1,4 @@
/* $OpenBSD: mux.c,v 1.82 2020/04/30 17:12:20 markus Exp $ */
/* $OpenBSD: mux.c,v 1.83 2020/07/05 23:59:45 djm Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
@@ -174,7 +174,7 @@ static const struct {
{ 0, NULL }
};

/* Cleanup callback fired on closure of mux slave _session_ channel */
/* Cleanup callback fired on closure of mux client _session_ channel */
/* ARGSUSED */
static void
mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused)
@@ -196,7 +196,7 @@ mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused)
channel_cancel_cleanup(ssh, c->self);
}

/* Cleanup callback fired on closure of mux slave _control_ channel */
/* Cleanup callback fired on closure of mux client _control_ channel */
/* ARGSUSED */
static void
mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused)
@@ -274,7 +274,7 @@ mux_master_process_hello(struct ssh *ssh, u_int rid,
"(expected %u)", __func__, ver, SSHMUX_VER);
return -1;
}
debug2("%s: channel %d slave version %u", __func__, c->self, ver);
debug2("%s: channel %d client version %u", __func__, c->self, ver);

/* No extensions are presently defined */
while (sshbuf_len(m) > 0) {
@@ -388,7 +388,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
/* Gather fds from client */
for(i = 0; i < 3; i++) {
if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
error("%s: failed to receive fd %d from slave",
error("%s: failed to receive fd %d from client",
__func__, i);
for (j = 0; j < i; j++)
close(new_fd[j]);
@@ -981,7 +981,7 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid,
/* Gather fds from client */
for(i = 0; i < 2; i++) {
if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
error("%s: failed to receive fd %d from slave",
error("%s: failed to receive fd %d from client",
__func__, i);
for (j = 0; j < i; j++)
close(new_fd[j]);
@@ -1141,7 +1141,7 @@ mux_master_process_proxy(struct ssh *ssh, u_int rid,
return 0;
}

/* Channel callbacks fired on read/write from mux slave fd */
/* Channel callbacks fired on read/write from mux client fd */
static int
mux_master_read_cb(struct ssh *ssh, Channel *c)
{
@@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.295 2020/07/01 16:28:31 markus Exp $ */
/* $OpenBSD: packet.c,v 1.296 2020/07/05 23:59:45 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2416,7 +2416,7 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
(r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0)
return r;
/*
* We set the time here so that in post-auth privsep slave we
* We set the time here so that in post-auth privsep child we
* count from the completion of the authentication.
*/
state->rekey_time = monotime();
@@ -1,4 +1,4 @@
/* $OpenBSD: readconf.c,v 1.331 2020/05/29 04:25:40 dtucker Exp $ */
/* $OpenBSD: readconf.c,v 1.332 2020/07/05 23:59:45 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2200,11 +2200,11 @@ fill_default_options(Options * options)
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
/* remove unsupported algos from default lists */
def_cipher = match_filter_whitelist(KEX_CLIENT_ENCRYPT, all_cipher);
def_mac = match_filter_whitelist(KEX_CLIENT_MAC, all_mac);
def_kex = match_filter_whitelist(KEX_CLIENT_KEX, all_kex);
def_key = match_filter_whitelist(KEX_DEFAULT_PK_ALG, all_key);
def_sig = match_filter_whitelist(SSH_ALLOWED_CA_SIGALGS, all_sig);
def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&options->what, \
@@ -1,5 +1,5 @@

/* $OpenBSD: servconf.c,v 1.366 2020/06/24 15:09:53 markus Exp $ */
/* $OpenBSD: servconf.c,v 1.367 2020/07/05 23:59:45 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -123,7 +123,7 @@ initialize_server_options(ServerOptions *options)
options->challenge_response_authentication = -1;
options->permit_empty_passwd = -1;
options->permit_user_env = -1;
options->permit_user_env_whitelist = NULL;
options->permit_user_env_allowlist = NULL;
options->compression = -1;
options->rekey_limit = -1;
options->rekey_interval = -1;
@@ -195,11 +195,11 @@ assemble_algorithms(ServerOptions *o)
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
/* remove unsupported algos from default lists */
def_cipher = match_filter_whitelist(KEX_SERVER_ENCRYPT, all_cipher);
def_mac = match_filter_whitelist(KEX_SERVER_MAC, all_mac);
def_kex = match_filter_whitelist(KEX_SERVER_KEX, all_kex);
def_key = match_filter_whitelist(KEX_DEFAULT_PK_ALG, all_key);
def_sig = match_filter_whitelist(SSH_ALLOWED_CA_SIGALGS, all_sig);
def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher);
def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac);
def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex);
def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
@@ -365,7 +365,7 @@ fill_default_server_options(ServerOptions *options)
options->permit_empty_passwd = 0;
if (options->permit_user_env == -1) {
options->permit_user_env = 0;
options->permit_user_env_whitelist = NULL;
options->permit_user_env_allowlist = NULL;
}
if (options->compression == -1)
#ifdef WITH_ZLIB
@@ -1563,7 +1563,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,

case sPermitUserEnvironment:
intptr = &options->permit_user_env;
charptr = &options->permit_user_env_whitelist;
charptr = &options->permit_user_env_allowlist;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing argument.",
@@ -2845,11 +2845,11 @@ dump_config(ServerOptions *o)
}
printf("\n");

if (o->permit_user_env_whitelist == NULL) {
if (o->permit_user_env_allowlist == NULL) {
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
} else {
printf("permituserenvironment %s\n",
o->permit_user_env_whitelist);
o->permit_user_env_allowlist);
}

printf("pubkeyauthoptions");
@@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.144 2020/04/17 03:30:05 djm Exp $ */
/* $OpenBSD: servconf.h,v 1.145 2020/07/05 23:59:45 djm Exp $ */

/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -146,7 +146,7 @@ typedef struct {
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int permit_user_env; /* If true, read ~/.ssh/environment */
char *permit_user_env_whitelist; /* pattern-list whitelist */
char *permit_user_env_allowlist; /* pattern-list of allowed env names */
int compression; /* If true, compression is allowed */
int allow_tcp_forwarding; /* One of FORWARD_* */
int allow_streamlocal_forwarding; /* One of FORWARD_* */
@@ -248,7 +248,7 @@ TAILQ_HEAD(include_list, include_item);
/*
* These are string config options that must be copied between the
* Match sub-config and the main config, and must be sent from the
* privsep slave to the privsep master. We use a macro to ensure all
* privsep child to the privsep master. We use a macro to ensure all
* the options are copied and the copies are done in the correct order.
*
* NB. an option must appear in servconf.c:copy_set_server_options() or
@@ -267,7 +267,7 @@ TAILQ_HEAD(include_list, include_item);
M_CP_STROPT(pubkey_key_types); \
M_CP_STROPT(ca_sign_algorithms); \
M_CP_STROPT(routing_domain); \
M_CP_STROPT(permit_user_env_whitelist); \
M_CP_STROPT(permit_user_env_allowlist); \
M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
M_CP_STRARRAYOPT(allow_users, num_allow_users); \
M_CP_STRARRAYOPT(deny_users, num_deny_users); \

10 comments on commit 5bde295

@paranoidbashthot
Copy link

@paranoidbashthot paranoidbashthot commented on 5bde295 Jul 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dare I say this is a little over the top, some of these terms have been in IT for decades. Should we also ban all spanish people from saying black?

@OstapKryvytskyy
Copy link

@OstapKryvytskyy OstapKryvytskyy commented on 5bde295 Jul 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yesterday's slave is today's client. I laughed based on the comarison between versions.
However nowaday's version fits better, on my humble opinion.
No slavery is allowed nowadays except if the person wants that specifically. So it is more correct to reflect that in the code as a newcomer reads it and will read it in the future. I support the new version, however it is needed to show to the person from which version it evolved, so this comparison is a perfect place to be seen if a person evolved from a decade-old books and documentation, where this was shown as old version.

@digmorepaka
Copy link

@digmorepaka digmorepaka commented on 5bde295 Jul 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is important to distinguish the reason this change has been done for, was it done for modernization, or is it done due to a vocal minority complaining about political correctness. To me it seems like a change done out of "let's change something for the sake of changing something so we look progressive". While the naming might not make sense at first, this is standard naming that has been in use for decades and does not pose any ill-effect directly or indirectly in a way. Changing rule of thumb standards for the sake of changing something is not a good thing.

EDIT: A good analogy in my opinion for it would be renaming sidewalks to roadside non-vehicle transport lane because sidewalk might offend those who have to use a wheelchair

@janv37
Copy link

@janv37 janv37 commented on 5bde295 Jul 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guys, listen to Alan Watts, especially about the game of black and white and how the western civilization tries to play white must win. This is getting out of hand and would end up bad. Check C.G. Jung for enantiodromia. And check with Taoists too!

@fullmetal1
Copy link

@fullmetal1 fullmetal1 commented on 5bde295 Jul 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think excluding the kind of person who gets offended by whitelist/blacklist and master/slave terminology is preferable to the endless purity spiral and 'cancelling' of persons for their privately held political opinions. The kinds of people who get offended by these terms are the same sort of people who will demand respectable productive contributors to be banned from participating for their privately held views. I don't develop for openbsd, and I've never used it and likely never will, but you should be aware that these seemingly small changes will eventually add up, and you may one day be the subject of wrath at the hands of the kinds of people who can not even handle innocuous terminology.

@nullenvk
Copy link

@nullenvk nullenvk commented on 5bde295 Jul 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guys, do you even know that this is just a git mirror? If you want to rant about this, go to the mailing lists.

@CampGrounds
Copy link

@CampGrounds CampGrounds commented on 5bde295 Jul 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so fucking stupid.

@SharpOB
Copy link

@SharpOB SharpOB commented on 5bde295 Jul 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cringe!!!!

@dimethyltriptamine
Copy link

@dimethyltriptamine dimethyltriptamine commented on 5bde295 Jul 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put me in the screenshot

@yamashirogumi
Copy link

@yamashirogumi yamashirogumi commented on 5bde295 Jul 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guys, listen to Alan Watts, especially about the game of black and white and how the western civilization tries to play white must win. This is getting out of hand and would end up bad. Check C.G. Jung for enantiodromia. And check with Taoists too!

Absolutely retarded, dropping names and books does not make a case for this tomfoolery, either come up with your own arguments or shut the fuck up, you "ex oriente lux" tard.

Please sign in to comment.