|
|
@@ -192,6 +192,24 @@ func parseDSN(dsn string) (cfg *config, err error) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+// Returns the bool value of the input.
|
|
|
+// The 2nd return value indicates if the input was a valid bool value
|
|
|
+func readBool(input string) (value bool, valid bool) {
|
|
|
+ switch input {
|
|
|
+ case "1", "true", "TRUE", "True":
|
|
|
+ return true, true
|
|
|
+ case "0", "false", "FALSE", "False":
|
|
|
+ return false, true
|
|
|
+ }
|
|
|
+
|
|
|
+ // Not a valid bool value
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+/******************************************************************************
|
|
|
+* Authentication *
|
|
|
+******************************************************************************/
|
|
|
+
|
|
|
// Encrypt password using 4.1+ method
|
|
|
// http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#4.1_and_later
|
|
|
func scramblePassword(scramble, password []byte) []byte {
|
|
|
@@ -244,24 +262,27 @@ func (r *myRnd) Float64() float64 {
|
|
|
return float64(r.seed1) / myRndMaxVal
|
|
|
}
|
|
|
|
|
|
-// https://github.com/atcurtis/mariadb/blob/master/sql/password.c
|
|
|
func pwHash(password []byte) (result [2]uint32) {
|
|
|
- var nr, add, nr2, tmp uint32
|
|
|
- nr, add, nr2 = 1345345333, 7, 0x12345671
|
|
|
+ var add uint32 = 7
|
|
|
+ var tmp uint32
|
|
|
+
|
|
|
+ result[0] = 1345345333
|
|
|
+ result[1] = 0x12345671
|
|
|
|
|
|
for _, c := range password {
|
|
|
+ // skip spaces and tabs in password
|
|
|
if c == ' ' || c == '\t' {
|
|
|
- continue // skip space in password
|
|
|
+ continue
|
|
|
}
|
|
|
|
|
|
tmp = uint32(c)
|
|
|
- nr ^= (((nr & 63) + add) * tmp) + (nr << 8)
|
|
|
- nr2 += (nr2 << 8) ^ nr
|
|
|
+ result[0] ^= (((result[0] & 63) + add) * tmp) + (result[0] << 8)
|
|
|
+ result[1] += (result[1] << 8) ^ result[0]
|
|
|
add += tmp
|
|
|
}
|
|
|
|
|
|
- result[0] = nr & ((1 << 31) - 1) // Don't use sign bit (str2int)
|
|
|
- result[1] = nr2 & ((1 << 31) - 1)
|
|
|
+ result[0] &= (1 << 31) - 1 // Don't use sign bit (str2int)
|
|
|
+ result[1] &= (1 << 31) - 1
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -269,33 +290,25 @@ func scrambleOldPassword(scramble, password []byte) []byte {
|
|
|
if len(password) == 0 {
|
|
|
return nil
|
|
|
}
|
|
|
+
|
|
|
scramble = scramble[:8]
|
|
|
+
|
|
|
hashPw := pwHash(password)
|
|
|
hashSc := pwHash(scramble)
|
|
|
+
|
|
|
r := newMyRnd(hashPw[0]^hashSc[0], hashPw[1]^hashSc[1])
|
|
|
+
|
|
|
var out [8]byte
|
|
|
for i := range out {
|
|
|
out[i] = byte(math.Floor(r.Float64()*31) + 64)
|
|
|
}
|
|
|
- extra := byte(math.Floor(r.Float64() * 31))
|
|
|
- for i := range out {
|
|
|
- out[i] ^= extra
|
|
|
- }
|
|
|
- return out[:]
|
|
|
-}
|
|
|
|
|
|
-// Returns the bool value of the input.
|
|
|
-// The 2nd return value indicates if the input was a valid bool value
|
|
|
-func readBool(input string) (value bool, valid bool) {
|
|
|
- switch input {
|
|
|
- case "1", "true", "TRUE", "True":
|
|
|
- return true, true
|
|
|
- case "0", "false", "FALSE", "False":
|
|
|
- return false, true
|
|
|
+ mask := byte(math.Floor(r.Float64() * 31))
|
|
|
+ for i := range out {
|
|
|
+ out[i] ^= mask
|
|
|
}
|
|
|
|
|
|
- // Not a valid bool value
|
|
|
- return
|
|
|
+ return out[:]
|
|
|
}
|
|
|
|
|
|
/******************************************************************************
|