# Sequence Diagrams during authentication
The initial handshake is what described in the MySQL protocol.
```mermaid
---
title: Initial (not complete) Handshake
---
sequenceDiagram
autonumber
participant C as Client
participant S as Session
S ->> C: InitialHandshake
opt SSL handshake
C ->> S: SSL request
C -> S: SSL handshake
end
C ->> S: HandshakeResponse
Note over C, S: What happens next is described in
"flowchart after Initial Handshake"
```
1. implemented in `MySQL_Protocol::generate_pkt_initial_handshake()`
2. performed by the client
3. implemented in `handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE()` and `MySQL_Protocol::process_pkt_handshake_response()`
4. performed by the client
## flowchart after Initial Handshake
After the Initial Handshake (described above) different sequences are possible. In here we can distinguish sequences based on the authentication plugin based by ProxySQL and the Client, resulting in 4 different sequences.
```mermaid
flowchart
A[Initial Handshake]
PAM{proxysql auth}
CAM1{client auth}
CAM2{client auth}
A --> PAM
SA[Sequence A]
SB[Sequence B]
SC[Sequence C]
SD[Sequence D]
PAM -->|mysql_native_password| CAM1
PAM -->|caching_sha2_password| CAM2
CAM1 -->|mysql_native_password| SA
CAM1 -->|caching_sha2_password| SB
CAM2 -->|mysql_native_password| SC
CAM2 -->|caching_sha2_password| SD
```
## Sequence A
ProxySQL: mysql_native_password
client: mysql_native_password
```mermaid
---
title: "Sequence A"
---
sequenceDiagram
autonumber
participant C as Client
participant S as Session
S ->> C: InitialHandshake
opt SSL handshake
C ->> S: SSL request
C -> S: SSL handshake
end
C ->> S: HandshakeResponse
alt valid credential
S ->> C: OK
else invalid credential
S ->> C: Error
end
```
## Sequence B
ProxySQL: mysql_native_password
client: caching_sha2_password
When ProxySQL uses `mysql_native_password` but client uses `caching_sha2_password` , ProxySQL askes the client to switch to `mysql_native_password`.
The client can either:
* perform the authentication using `mysql_native_password` (point 6)
* disconnect (point 9)
```mermaid
---
title: "Sequence B"
---
sequenceDiagram
autonumber
participant C as Client
participant S as Session
S ->> C: InitialHandshake
opt SSL handshake
C ->> S: SSL request
C -> S: SSL handshake
end
C ->> S: HandshakeResponse
S ->> C: Authentication method switch
to mysql_native_password
alt client agrees to switch
C ->> S: hash (password + scramble)
alt valid credential
S ->> C: OK
else invalid credential
S ->> C: Error
end
else
C --x S: disconnect
end
```
## State Diagram of MySQL_Session during authentication
When a new session is created the status `session_status___NONE` is assigned by default.
After the initial handshake is sent, the status is set to `CONNECTING_CLIENT`.
The status is finally changed to `WAITING_CLIENT_DATA` if the authentication is completed. If the authentication is not successful the session is simply destroyed.
```mermaid
---
title: MySQL_Session status during authentication
---
stateDiagram-v2
session_status___NONE --> CONNECTING_CLIENT CONNECTING_CLIENT --> WAITING_CLIENT_DATA
```
## Generic flowchart of authentication (without subgraphs)
```mermaid
flowchart
A["generate_pkt_initial_handshake()"]
A1["status=CONNECTING_CLIENT"]
B["get_pkts_from_client()"]
C{status}
C1{client_myds->DSS}
D["handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE()"]
A --> A1
A1 --> B
B --> C
C -->|CONNECTING_CLIENT| C1
C1 -->|STATE_SERVER_HANDSHAKE| D
C1 -->|STATE_SSL_INIT| D
E["handshake_response_return = process_pkt_handshake_response()"]
D --> E
F{"handshake_response_return"}
F1{"client_myds->auth_in_progress != 0"}
E --> F
F -->|false| F1
F1 -->|Yes| B
F2{"is_encrypted == false
&&
client_myds->encrypted == true"}
F3[Initialize SSL]
F1 -->|No| F2
F2 -->|Yes| F3
F3 --> B
F2 -->|No| W
G{correct session_type}
F -->|true| G
G -->|false| W
OK["status=WAITING_CLIENT_DATA"]
SOK["send OK to client"]
G -->|true| SOK
SOK --> OK
OK --> B
W[Disconnect]
```
After the initial handshake is sent and , `status` is set to `CONNECTING_CLIENT`.
The main routine in `MySQL_Session` is `handler()` , and one of the main function it calls is `get_pkts_from_client()`.
As the name suggests, `get_pkts_from_client()` is responsible from retrieving packets sent by the client: then it performs actions based on `status`.
During authentication only `status==CONNECTING_CLIENT` is relevant.
If `status==CONNECTING_CLIENT` and `client_myds->DSS` (`client_myds` represents the Client `MySQL_Data_Stream` , and `DSS` respesents its status) is either `STATE_SERVER_HANDSHAKE` or `STATE_SSL_INIT` , then `handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE()` is executed.
`handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE()` calls `process_pkt_handshake_response()` and performs actions based on its return code.
`process_pkt_handshake_response()` historically was responsible for only processing **HandshakeResponse** packet, but over time became more complex to also handle **SSL Handshake** , **Authentication method switch** , **Fast Authentication** and **Full Authentication** . The details of `process_pkt_handshake_response()` will be described in more detailed flowcharts and diagrams.
For now it is worth to note that `process_pkt_handshake_response()` returns:
* `true` when authentication succeeded
* `false` when authentication failed or it is not completed yet (other status variables needs to ne evaluated)
If `handshake_response_return`:
* `true` : if `session_type` is correct (for example, a user defined in `mysql_users` table is not trying to connect to Admin, or viceversa) , the authentication succeeded, an OK packet is sent to the client, and status is changed to `WAITING_CLIENT_DATA`
* `false` :
* if authentication is still in progress : continue
* if SSL has been required: initialize SSL and: continue
* else: wrong credentials, disconnect
Below is the same flowchart with subgraphs.
## Generic flowchart of authentication (with subgraphs)
```mermaid
flowchart
subgraph sub0 [" "]
A["generate_pkt_initial_handshake()"]
A1["status=CONNECTING_CLIENT"]
A --> A1
end
A1 --> sub1
subgraph sub1 ["get_pkts_from_client()"]
B["get_pkts_from_client()"]
C{status}
C1{client_myds->DSS}
B --> C
C -->|CONNECTING_CLIENT| C1
end
subgraph sub2 ["handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE()"]
D["handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE()"]
D --> E
E["handshake_response_return = process_pkt_handshake_response()"]
F{"handshake_response_return"}
F1{"client_myds->auth_in_progress != 0"}
E --> F
F -->|false| F1
F1 -->|Yes| B
F2{"is_encrypted == false
&&
client_myds->encrypted == true"}
F3[Initialize SSL]
F1 -->|No| F2
F2 -->|Yes| F3
F3 --> B
F2 -->|No| W
G{correct session_type}
F -->|true| G
G -->|false| W
W[Disconnect]
OK["status=WAITING_CLIENT_DATA"]
SOK["send OK to client"]
G -->|true| SOK
SOK --> OK
OK --> B
end
C1 -->|STATE_SERVER_HANDSHAKE| D
C1 -->|STATE_SSL_INIT| D
```
See description in previous flowchart.
## Details about `MySQL_Protocol::process_pkt_handshake_response()`
Because `MySQL_Protocol::process_pkt_handshake_response()` grew over time and was then split into multiple methods, variables are passed to and from methods using 2 objects of the following 2 classes:
```mermaid
---
title: classes used by authentication functions
---
classDiagram
class MyProt_tmp_auth_vars{
unsigned char *user
char *db
char *db_tmp
unsigned char *pass
char *password
unsigned char *auth_plugin
void *sha1_pass=NULL
unsigned char *_ptr
unsigned int charset
uint32_t capabilities
uint32_t max_pkt
uint32_t pass_len
bool use_ssl
enum proxysql_session_type session_type
}
class MyProt_tmp_auth_attrs {
char *default_schema
char *attributes
int default_hostgroup
int max_connections
bool schema_locked
bool transaction_persistent
bool fast_forward
bool _ret_use_ssl
}
```
### Flowchart of `MySQL_Protocol::process_pkt_handshake_response()`
```mermaid
flowchart
A[Read packet header]
B{"username is
already known
from aprevious
packet"}
PPHR_1{"rc =
PPHR_1()"}
DOAUTH[__do_auth]
EXITDOAUTH[__exit_do_auth]
EXIT[__exit_process_pkt_handshake_response]
ASSERT["assert(0)"]
A --> B
PPHR_2{"bool_rc =
PPHR_2()"}
subgraph 16
B -->|Yes| PPHR_1
PPHR_1 -->|default| ASSERT
B -->|No| PPHR_2
PPHR_2 -->|true| PPHR_3["PPHR_3()"]
end
PPHR_1 -->|1| EXIT
PPHR_1 -->|2| DOAUTH
PPHR_2 -->|false| EXIT
SAPID{sent_auth_plugin_id}
PPHR_3 --> SAPID
APID1{auth_plugin_id}
APID2{auth_plugin_id}
SAPID -->|AUTH_MYSQL_NATIVE_PASSWORD| APID1
SAPID -->|AUTH_MYSQL_CACHING_SHA2_PASSWORD| APID2
subgraph 13
APID1_-1{"bool_rc =
PPHR_4auth0()"}
APID1 -->|AUTH_UNKNOWN_PLUGIN| APID1_-1
APID1_0{"bool_rc =
PPHR_4auth1()"}
APID1 -->|AUTH_MYSQL_NATIVE_PASSWORD| APID1_0
APID1 -->|default| a2["assert(0)"]
end
APID1_-1 -->|false| EXIT
APID1_-1 -->|true| DOAUTH
APID1_0 -->|false| EXIT
APID1_0 -->|true| DOAUTH
APID1 -->|AUTH_MYSQL_CLEAR_PASSWORD| DOAUTH
APID2_0{"bool_rc =
PPHR_4auth0()"}
subgraph 14
APID2 -->|AUTH_UNKNOWN_PLUGIN| APID2_0
APID2 -->|AUTH_MYSQL_NATIVE_PASSWORD| APID2_0
APID2_sha2_a{auth_in_progress}
APID2_sha2_s{switching_auth_stage}
APID2 -->|AUTH_MYSQL_CACHING_SHA2_PASSWORD| APID2_sha2_a
APID2_sha2_a -->|0| APID2_sha2_s
APID2_sha2_a -->|default| a3["assert(0)"]
end
APID2 -->|AUTH_MYSQL_CLEAR_PASSWORD| DOAUTH
APID2_0 -->|true| DOAUTH
APID2_0 -->|false| EXIT
APID2_sha2_s -->|0| DOAUTH
APID2_sha2_s -->|default| a3
getCharset[get client charset/collation]
DOAUTH --> getCharset
subgraph 18 [" "]
gcv{valid collation}
getCharset --> gcv
sessionType1{session_type}
gcv -->|true| sessionType1
P1Click["password = GloClickHouseAuth->lookup()"]
P1MySQL["password = GloMyAuth->lookup()"]
sessionType1 -->|PROXYSQL_SESSION_CLICKHOUSE| P1Click
sessionType1 -->|default| P1MySQL
P1NULL{password == NULL}
P1Click --> P1NULL
P1MySQL --> P1NULL
end
gcv -->|false| EXITDOAUTH
sessionType2{session_type}
PPHR_5passwordFalse_0["
PPHR_5passwordFalse_0()
If username and password are the one used
by MySQL_Monitor, set ret=true .
This allows connections from MySQL Monitor module.
"]
P1NULL -->|true| sessionType2
subgraph sub2
sessionType2 -->|PROXYSQL_SESSION_ADMIN| PPHR_5passwordFalse_0
sessionType2 -->|PROXYSQL_SESSION_STATS| PPHR_5passwordFalse_0
APID3{auth_plugin_id}
sessionType2 -->|default| APID3
PPHR_5passwordFalse_auth2["
PPHR_5passwordFalse_auth2()
Relevant only for LDAP Authentication.
TODO: Document it properly.
"]
APID3 -->|AUTH_MYSQL_CLEAR_PASSWORD| PPHR_5passwordFalse_auth2
end
PPHR_5passwordFalse_0 --> EXITDOAUTH
APID3 -->|default| EXITDOAUTH
PPHR_5passwordFalse_auth2 --> EXITDOAUTH
PPHR_5passwordTrue["PPHR_5passwordTrue()
Assignes all the variables retrieved
from the Authentication module to
related MySQL_Session object.
"]
P1NULL -->|false| PPHR_5passwordTrue
EP{"password == ''"}
PPHR_5passwordTrue --> EP
EP -->|true| RET1[ret=true]
RET1 --> EXITDOAUTH
APID_SHA2_PASS{"auth_plugin_id ==
AUTH_MYSQL_CACHING_SHA2_PASSWORD
&&
password in SHA2 format"}
EP -->|false| APID_SHA2_PASS
subgraph sub3
APID_SHA2_PASS -->|false| PASSCT
APID_SHA2_PASS -->|true| PPHR_sha2full1["PPHR_sha2full(AUTH_MYSQL_CACHING_SHA2_PASSWORD)"]
end
PPHR_sha2full1 --> EXITDOAUTH
PASSCT{"password in
cleartext format"}
subgraph sub4
PASSCT -->|true| APID4{auth_plugin_id}
APID4 -->|AUTH_MYSQL_NATIVE_PASSWORD| SM{scrambles match}
SM -->|true| RET2["ret=true"]
APID4 -->|AUTH_MYSQL_CLEAR_PASSWORD| PM{passwords match}
PM -->|true| RET3["ret=true"]
PPHR_6auth2["PPHR_6auth2()
Performs a fast authentication using
caching_sha2_password. Fast authentication
means that we already have the password in
clear text and we can compare the hash of
password and scramble generated by the client.
Sets ret=true if the hashes match.
"]
APID4 -->|AUTH_MYSQL_CACHING_SHA2_PASSWORD| PPHR_6auth2
PPHR_6auth2 --> RET4{ret == true}
RET4 -->|true| SFAS["send fast_auth_success"]
end
SM -->|false| EXITDOAUTH
PM -->|false| EXITDOAUTH
RET4 -->|false| EXITDOAUTH
SFAS --> EXITDOAUTH
RET2 --> EXITDOAUTH
RET3 --> EXITDOAUTH
PASS_SHA1{"password in
sha1 format"}
PASSCT -->|false| PASS_SHA1
subgraph sub5
PASS_SHA1 -->|true| APID5{auth_plugin_id}
PPHR_7auth1["PPHR_7auth1()
Used in mysql_native_password.
If SHA1 of password and scramble match:
ret = true
If sha1 wasn't available, save it in GloMyAuth
"]
PPHR_7auth2["PPHR_7auth2()
Used in mysql_clear_password and when
only double SHA1 is known.
If double SHA1 of password match:
ret = true
If sha1 wasn't available, save it in GloMyAuth
"]
APID5 -->|AUTH_MYSQL_NATIVE_PASSWORD| PPHR_7auth1
APID5 -->|AUTH_MYSQL_CLEAR_PASSWORD| PPHR_7auth2
APID5 -->|AUTH_MYSQL_CACHING_SHA2_PASSWORD| PPHR_sha2full2["PPHR_sha2full(AUTH_MYSQL_NATIVE_PASSWORD)"]
end
PASS_SHA1 -->|false| EXITDOAUTH
PPHR_7auth1 --> EXITDOAUTH
PPHR_7auth2 --> EXITDOAUTH
PPHR_sha2full2 --> EXITDOAUTH
EXITDOAUTH --> PPHR_SetConnAttrs["PPHR_SetConnAttrs()"]
v1use_ssl{vars1.use_ssl}
PPHR_SetConnAttrs --> v1use_ssl
v1use_ssl -->|true| RET5[ret=true]
RET5 --> EXIT
rc5{ret}
v1use_ssl -->|false| rc5
subgraph subrc5
rc5 -->|true| SETCC[Set correct credentials in userinfo]
rc5 -->|false| SETEC[Set empty credentials in userinfo]
SETCC --> CH["compute_hash()"]
SETEC --> CH["compute_hash()"]
end
CH --> EXIT
EXIT --> Cleanup["Perform cleanup of temporary variables"]
Cleanup --> rc6{ret}
rc6 -->|true| verify_user_attributes["verify_user_attributes()"]
rc6 -->|false| RetRet["return ret"]
verify_user_attributes --> RetRet
```
### Flowchart of `MySQL_Protocol::PPHR_1()`
```mermaid
flowchart
SAS1{switching_auth_stage}
SAS1 -->|1| sas2["switching_auth_stage = 2
It means: stage1 (used by MYSQL_NATIVE_PASSWORD)
is completed"]
SAS1 -->|4| sas5["switching_auth_stage = 5
It means: stage4 (used by CACHING_SHA2_PASSWORD)
is completed"]
AIP["auth_in_progress = 0
This signals that the authorization should complete now
"]
SAS1 --> AIP
sas2 --> AIP
sas5 --> AIP
PL{packet len}
AIP --> PL
PL -->|5| cd["Client disconnected
without performing the switch
"] --> ret1[return 1]
APID["
We previously stored the auth_plugin_id in myds->switching_auth_type
auth_plugin_id = myds->switching_auth_type
"]
PL --> APID
auth_plugin_id{auth_plugin_id}
APID --> auth_plugin_id
auth_plugin_id -->|AUTH_MYSQL_NATIVE_PASSWORD| PL1[password = the rest of the packet]
auth_plugin_id -->|default| PL2[password = NULL terminated C string]
Con1["Retrieve previously stored variables
from myds , userinfo, and myconn "]
PL1 --> Con1
PL2 --> Con1
Con1 --> ret2[return 2]
```
### Flowchart of `MySQL_Protocol::PPHR_2()`
This method is the one responsible for parsing the very first Handshake Response from the client.
```mermaid
flowchart
A["Parse capabilities and max_allowed_pkt,
and save them in myconn->options
"]
STS{"encrypted == false
&&
packet_length == header + 32
"}
A --> STS
SV["This is an SSLRequest.
Client wants to switch to SSL
encrypted = true
use_ssl = true
ret = false
"]
STS -->|Yes| SV
SV --> RF["return false"]
cv{charset == 0}
STS -->|No| cv
SDC["set charset = default SQL_CHARACTER_SET
See bug #810"]
cv -->|Yes| SDC
GetUser["Parse username"]
cv -->|No| GetUser
SDC --> GetUser
GetUser --> GetPass["Parse authentication data"] -- on error --> E1["ret = false"] --> RF
GetPass --> GetDB["Parse database name"]
GetDB --> GetAuthPlugin["Parse authentication plugin"]
GetAuthPlugin --> RT["return true"]
```
### Flowchart of `MySQL_Protocol::PPHR_3()`
This method is the one responsible for detecting the authentication plugin to use .
It opererates on three variables with similar names:
* `vars1.auth_plugin` : the plugin that the client wish to use
* `sent_auth_plugin_id` : member of `MySQL_Protocol` . It defines which default plugin was sent by ProxySQL to the client
* `auth_plugin_id` : member of `MySQL_Protocol` . It defines which plugin is being used
It is worth noticing that any unknown plugin is threated as unknown.
Also, if ProxySQL sends `mysql_native_password` and the client sends `caching_sha2_password` , ProxySQL will threat it as unknown, then forcing the client to switch to `mysql_native_password`.
```mermaid
flowchart
AP1{"vars1.auth_plugin
==
NULL"}
B["vars1.auth_plugin = mysql_native_password
auth_plugin_id = AUTH_MYSQL_NATIVE_PASSWORD
"]
AP1 -->|Yes| B
B -->APID
AP1 -->|No| APID
APID{"auth_plugin_id
==
AUTH_UNKNOWN_PLUGIN"}
APID -->|No| return
AP2{"vars1.auth_plugin"}
APID -->|Yes| AP2
AP2 -->|mysql_native_password| S1["auth_plugin_id =
AUTH_MYSQL_NATIVE_PASSWORD"]
AP2 -->|mysql_clear_password| S2["auth_plugin_id =
AUTH_MYSQL_CLEAR_PASSWORD"]
SAPID{sent_auth_plugin_id}
AP2 -->|caching_sha2_password| SAPID
SAPID -->|AUTH_MYSQL_NATIVE_PASSWORD| S3["auth_plugin_id =
AUTH_UNKNOWN_PLUGIN"]
SAPID -->|AUTH_MYSQL_CACHING_SHA2_PASSWORD| S4["auth_plugin_id =
AUTH_MYSQL_CACHING_SHA2_PASSWORD"]
S1 --> return
S2 --> return
S3 --> return
S4 --> return
```
### Flowchart of `MySQL_Protocol::PPHR_4auth0()`
TODO
### Flowchart of `MySQL_Protocol::PPHR_4auth1()`
This method is the one responsible for determining if ProxySQL can switch authentication to `mysql_clear_password` for LDAP plugin.
At its core, it verify that the requested user doesn't exist.
```mermaid
---
title: MySQL_Protocol::PPHR_4auth1()
---
flowchart
A{"LDAP
Authentication
enabled"}
SAS{"switching_auth_stage
==
0"}
UE{"
user_exists
=
GloMyAuth->exists
"}
A -->|Yes| SAS
A -->|No| RT
SAS -->|Yes| UE
SAS -->|No| RT
UE -->|No| RT
C1["
switching_auth_type = AUTH_MYSQL_CLEAR_PASSWORD
switching_auth_stage = 1
auth_in_progress = 1
"]
UE --> C1
C1 --> G["generate_pkt_auth_switch_request()"]
G --> RRF[ret = false]
RRF --> RF[return false]
RT[return true]
```
### `MySQL_Protocol::PPHR_5passwordTrue()`
Give all the attributes received from the Authentication module in `MyProt_tmp_auth_attrs& attr1` , `MySQL_Protocol::PPHR_5passwordTrue()` is responsible for assigning all the variables to related `MySQL_Session` object.
### `MySQL_Protocol::PPHR_5passwordFalse_0()`
If `username` and `password` are the one used by `MySQL_Monitor` , set `ret=true` .
This allows connections from MySQL Monitor module.
### `MySQL_Protocol::PPHR_5passwordFalse_auth2()`
TODO: document
### `MySQL_Protocol::PPHR_6auth2()`
Documented in the flowchart
### `MySQL_Protocol::PPHR_7auth1()`
Used for `mysql_native_password` authentication.
If SHA1 of password and scramble match, then sets `ret=true`.
If sha1 wasn't previous available, save it in `GloMyAuth` calling `GloMyAuth->set_SHA1()` .
Also set it in `userinfo->sha1_pass`.
### `MySQL_Protocol::PPHR_7auth2()`
Used for `mysql_clear_password` authentication when password is saved as double SHA1.
If the double SHA1 password match then sets `ret=true`.
If sha1 wasn't previous available, save it in `GloMyAuth` calling `GloMyAuth->set_SHA1()` .
Also set it in `userinfo->sha1_pass`.
### Flowchart of `MySQL_Protocol::PPHR_sha2full()`
This method is the one responsible to perform (start, or continue/complete) `caching_sha2_password` full authentication.
If `switching_auth_stage`:
* 0 : set it to 4, and **start** full authentication
* 5 : **continue/complete** full authentication
This function receives in `passformat` the format of the known password.
```mermaid
---
title: MySQL_Protocol::PPHR_sha2full()
---
flowchart
return
SAS{switching_auth_stage}
GOBP["generate_one_byte_pkt(perform_full_authentication)"]
SV["switching_auth_type = auth_plugin_id
switching_auth_stage = 4
auth_in_progress = 1
"]
SAS -->|0| GOBP --> SV --> return
PF1{"passformat"}
SAS -->|5| PF1
SAS -->|default| a1["assert(0)"]
B5N1[Generate double SHA1]
B5N2{"double
SHA1s
match"}
PF1 -->|AUTH_MYSQL_NATIVE_PASSWORD| B5N1 --> B5N2
B5C1["
Extract salt and rounds
of SHA256() from
encoded hashed password
"]
B5C2["
Run SHA256()
rounds times on
cleartext password"]
B5C3{"encoded hashed
passwords match"}
PF1 -->|AUTH_MYSQL_CACHING_SHA2_PASSWORD| B5C1 --> B5C2 --> B5C3
PF1 -->|default| a1
SRT["ret = true"]
B5N2 -->|No| RT
B5N2 -->|Yes| SRT
B5C3 -->|Yes| SRT
RT{ret}
SRT --> RT
B5C3 -->|No| RT
SCT["GloMyAuth->set_clear_text_password()
Save (cache) clear text password in
order to perform fast authentication.
This is exactly what 'caching' means
in caching_sha2_password
"]
RT -->|false| return
RT -->|true| SCT
SCT --> return
```