forked from TrueCloudLab/rclone
vendor: update github.com/t3rm1n4l/go-mega and dependencies
This is to fix a crash reported in #3140
This commit is contained in:
parent
48c09608ea
commit
8f89b03d7b
135 changed files with 27990 additions and 605 deletions
285
vendor/github.com/t3rm1n4l/go-mega/mega.go
generated
vendored
285
vendor/github.com/t3rm1n4l/go-mega/mega.go
generated
vendored
|
@ -336,7 +336,10 @@ func newMegaFS() *MegaFS {
|
|||
|
||||
func New() *Mega {
|
||||
max := big.NewInt(0x100000000)
|
||||
bigx, _ := rand.Int(rand.Reader, max)
|
||||
bigx, err := rand.Int(rand.Reader, max)
|
||||
if err != nil {
|
||||
panic(err) // this should be returned, but this is a public interface
|
||||
}
|
||||
cfg := newConfig()
|
||||
mgfs := newMegaFS()
|
||||
m := &Mega{
|
||||
|
@ -496,7 +499,10 @@ func (m *Mega) prelogin(email string) error {
|
|||
if len(res[0].Salt) == 0 {
|
||||
return errors.New("prelogin: no salt returned")
|
||||
}
|
||||
m.accountSalt = base64urldecode([]byte(res[0].Salt))
|
||||
m.accountSalt, err = base64urldecode([]byte(res[0].Salt))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
m.accountVersion = res[0].Version
|
||||
|
||||
|
@ -512,8 +518,14 @@ func (m *Mega) login(email string, passwd string) error {
|
|||
|
||||
email = strings.ToLower(email) // mega uses lowercased emails for login purposes
|
||||
|
||||
passkey := password_key(passwd)
|
||||
uhandle := stringhash(email, passkey)
|
||||
passkey, err := password_key(passwd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
uhandle, err := stringhash(email, passkey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.uh = make([]byte, len(uhandle))
|
||||
copy(m.uh, uhandle)
|
||||
|
||||
|
@ -536,9 +548,11 @@ func (m *Mega) login(email string, passwd string) error {
|
|||
msg[0].SessionKey = string(base64urlencode(sessionKey))
|
||||
}
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err = m.api_request(req)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -548,8 +562,14 @@ func (m *Mega) login(email string, passwd string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
m.k = base64urldecode([]byte(res[0].Key))
|
||||
m.k, err = base64urldecode([]byte(res[0].Key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cipher, err := aes.NewCipher(passkey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cipher.Decrypt(m.k, m.k)
|
||||
m.sid, err = decryptSessionId([]byte(res[0].Privk), []byte(res[0].Csid), m.k)
|
||||
if err != nil {
|
||||
|
@ -634,9 +654,11 @@ func (m *Mega) GetUser() (UserResp, error) {
|
|||
|
||||
msg[0].Cmd = "ug"
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return res[0], err
|
||||
}
|
||||
result, err := m.api_request(req)
|
||||
|
||||
if err != nil {
|
||||
return res[0], err
|
||||
}
|
||||
|
@ -654,7 +676,10 @@ func (m *Mega) GetQuota() (QuotaResp, error) {
|
|||
msg[0].Xfer = 1
|
||||
msg[0].Strg = 1
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return res[0], err
|
||||
}
|
||||
result, err := m.api_request(req)
|
||||
if err != nil {
|
||||
return res[0], err
|
||||
|
@ -671,7 +696,10 @@ func (m *Mega) addFSNode(itm FSNode) (*Node, error) {
|
|||
var node, parent *Node
|
||||
var err error
|
||||
|
||||
master_aes, _ := aes.NewCipher(m.k)
|
||||
master_aes, err := aes.NewCipher(m.k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case itm.T == FOLDER || itm.T == FILE:
|
||||
|
@ -680,43 +708,73 @@ func (m *Mega) addFSNode(itm FSNode) (*Node, error) {
|
|||
switch {
|
||||
// File or folder owned by current user
|
||||
case args[0] == itm.User:
|
||||
buf := base64urldecode([]byte(args[1]))
|
||||
buf, err := base64urldecode([]byte(args[1]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(master_aes, buf, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compkey = bytes_to_a32(buf)
|
||||
compkey, err = bytes_to_a32(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Shared folder
|
||||
case itm.SUser != "" && itm.SKey != "":
|
||||
sk := base64urldecode([]byte(itm.SKey))
|
||||
sk, err := base64urldecode([]byte(itm.SKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(master_aes, sk, sk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sk_aes, _ := aes.NewCipher(sk)
|
||||
sk_aes, err := aes.NewCipher(sk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.FS.skmap[itm.Hash] = itm.SKey
|
||||
buf := base64urldecode([]byte(args[1]))
|
||||
buf, err := base64urldecode([]byte(args[1]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(sk_aes, buf, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compkey = bytes_to_a32(buf)
|
||||
compkey, err = bytes_to_a32(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Shared file
|
||||
default:
|
||||
k := m.FS.skmap[args[0]]
|
||||
b := base64urldecode([]byte(k))
|
||||
b, err := base64urldecode([]byte(k))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(master_aes, b, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
block, _ := aes.NewCipher(b)
|
||||
buf := base64urldecode([]byte(args[1]))
|
||||
block, err := aes.NewCipher(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf, err := base64urldecode([]byte(args[1]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(block, buf, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compkey = bytes_to_a32(buf)
|
||||
compkey, err = bytes_to_a32(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
|
@ -726,10 +784,16 @@ func (m *Mega) addFSNode(itm FSNode) (*Node, error) {
|
|||
key = compkey
|
||||
}
|
||||
|
||||
attr, err = decryptAttr(a32_to_bytes(key), []byte(itm.Attr))
|
||||
// FIXME:
|
||||
bkey, err := a32_to_bytes(key)
|
||||
if err != nil {
|
||||
// FIXME:
|
||||
attr.Name = "BAD ATTRIBUTE"
|
||||
} else {
|
||||
attr, err = decryptAttr(bkey, []byte(itm.Attr))
|
||||
// FIXME:
|
||||
if err != nil {
|
||||
attr.Name = "BAD ATTRIBUTE"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,15 +833,33 @@ func (m *Mega) addFSNode(itm FSNode) (*Node, error) {
|
|||
switch {
|
||||
case itm.T == FILE:
|
||||
var meta NodeMeta
|
||||
meta.key = a32_to_bytes(key)
|
||||
meta.iv = a32_to_bytes([]uint32{compkey[4], compkey[5], 0, 0})
|
||||
meta.mac = a32_to_bytes([]uint32{compkey[6], compkey[7]})
|
||||
meta.compkey = a32_to_bytes(compkey)
|
||||
meta.key, err = a32_to_bytes(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta.iv, err = a32_to_bytes([]uint32{compkey[4], compkey[5], 0, 0})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta.mac, err = a32_to_bytes([]uint32{compkey[6], compkey[7]})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta.compkey, err = a32_to_bytes(compkey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node.meta = meta
|
||||
case itm.T == FOLDER:
|
||||
var meta NodeMeta
|
||||
meta.key = a32_to_bytes(key)
|
||||
meta.compkey = a32_to_bytes(compkey)
|
||||
meta.key, err = a32_to_bytes(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta.compkey, err = a32_to_bytes(compkey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node.meta = meta
|
||||
case itm.T == ROOT:
|
||||
attr.Name = "Cloud Drive"
|
||||
|
@ -814,9 +896,11 @@ func (m *Mega) getFileSystem() error {
|
|||
msg[0].Cmd = "f"
|
||||
msg[0].C = 1
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := m.api_request(req)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -908,9 +992,15 @@ func (m *Mega) NewDownload(src *Node) (*Download, error) {
|
|||
|
||||
mac_enc := cipher.NewCBCEncrypter(aes_block, zero_iv)
|
||||
m.FS.mutex.Lock()
|
||||
t := bytes_to_a32(src.meta.iv)
|
||||
t, err := bytes_to_a32(src.meta.iv)
|
||||
m.FS.mutex.Unlock()
|
||||
iv := a32_to_bytes([]uint32{t[0], t[1], t[0], t[1]})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iv, err := a32_to_bytes([]uint32{t[0], t[1], t[0], t[1]})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := &Download{
|
||||
m: m,
|
||||
|
@ -992,10 +1082,17 @@ func (d *Download) DownloadChunk(id int) (chunk []byte, err error) {
|
|||
}
|
||||
|
||||
// Decrypt the block
|
||||
ctr_iv := bytes_to_a32(d.src.meta.iv)
|
||||
ctr_iv, err := bytes_to_a32(d.src.meta.iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctr_iv[2] = uint32(uint64(chk_start) / 0x1000000000)
|
||||
ctr_iv[3] = uint32(chk_start / 0x10)
|
||||
ctr_aes := cipher.NewCTR(d.aes_block, a32_to_bytes(ctr_iv))
|
||||
bctr_iv, err := a32_to_bytes(ctr_iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctr_aes := cipher.NewCTR(d.aes_block, bctr_iv)
|
||||
ctr_aes.XORKeyStream(chunk, chunk)
|
||||
|
||||
// Update the chunk_macs
|
||||
|
@ -1035,8 +1132,15 @@ func (d *Download) Finish() (err error) {
|
|||
d.mac_enc.CryptBlocks(mac_data, v)
|
||||
}
|
||||
|
||||
tmac := bytes_to_a32(mac_data)
|
||||
if bytes.Equal(a32_to_bytes([]uint32{tmac[0] ^ tmac[1], tmac[2] ^ tmac[3]}), d.src.meta.mac) == false {
|
||||
tmac, err := bytes_to_a32(mac_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
btmac, err := a32_to_bytes([]uint32{tmac[0] ^ tmac[1], tmac[2] ^ tmac[3]})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if bytes.Equal(btmac, d.src.meta.mac) == false {
|
||||
return EMACMISMATCH
|
||||
}
|
||||
|
||||
|
@ -1188,12 +1292,24 @@ func (m *Mega) NewUpload(parent *Node, name string, fileSize int64) (*Upload, er
|
|||
|
||||
}
|
||||
|
||||
kbytes := a32_to_bytes(ukey[:4])
|
||||
kiv := a32_to_bytes([]uint32{ukey[4], ukey[5], 0, 0})
|
||||
aes_block, _ := aes.NewCipher(kbytes)
|
||||
kbytes, err := a32_to_bytes(ukey[:4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kiv, err := a32_to_bytes([]uint32{ukey[4], ukey[5], 0, 0})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aes_block, err := aes.NewCipher(kbytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mac_enc := cipher.NewCBCEncrypter(aes_block, zero_iv)
|
||||
iv := a32_to_bytes([]uint32{ukey[4], ukey[5], ukey[4], ukey[5]})
|
||||
iv, err := a32_to_bytes([]uint32{ukey[4], ukey[5], ukey[4], ukey[5]})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chunks := getChunkSizes(fileSize)
|
||||
|
||||
|
@ -1243,10 +1359,17 @@ func (u *Upload) UploadChunk(id int, chunk []byte) (err error) {
|
|||
if len(chunk) != chk_size {
|
||||
return errors.New("upload chunk is wrong size")
|
||||
}
|
||||
ctr_iv := bytes_to_a32(u.kiv)
|
||||
ctr_iv, err := bytes_to_a32(u.kiv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctr_iv[2] = uint32(uint64(chk_start) / 0x1000000000)
|
||||
ctr_iv[3] = uint32(chk_start / 0x10)
|
||||
ctr_aes := cipher.NewCTR(u.aes_block, a32_to_bytes(ctr_iv))
|
||||
bctr_iv, err := a32_to_bytes(ctr_iv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctr_aes := cipher.NewCTR(u.aes_block, bctr_iv)
|
||||
|
||||
enc := cipher.NewCBCEncrypter(u.aes_block, u.iv)
|
||||
|
||||
|
@ -1324,7 +1447,10 @@ func (u *Upload) Finish() (node *Node, err error) {
|
|||
u.mac_enc.CryptBlocks(mac_data, v)
|
||||
}
|
||||
|
||||
t := bytes_to_a32(mac_data)
|
||||
t, err := bytes_to_a32(mac_data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta_mac := []uint32{t[0] ^ t[1], t[2] ^ t[3]}
|
||||
|
||||
attr := FileAttr{u.name}
|
||||
|
@ -1338,7 +1464,10 @@ func (u *Upload) Finish() (node *Node, err error) {
|
|||
u.ukey[2] ^ meta_mac[0], u.ukey[3] ^ meta_mac[1],
|
||||
u.ukey[4], u.ukey[5], meta_mac[0], meta_mac[1]}
|
||||
|
||||
buf := a32_to_bytes(key)
|
||||
buf, err := a32_to_bytes(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
master_aes, err := aes.NewCipher(u.m.k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1488,9 +1617,11 @@ func (m *Mega) Move(src *Node, parent *Node) error {
|
|||
return err
|
||||
}
|
||||
|
||||
request, _ := json.Marshal(msg)
|
||||
request, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = m.api_request(request)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1515,11 +1646,17 @@ func (m *Mega) Rename(src *Node, name string) error {
|
|||
}
|
||||
var msg [1]FileAttrMsg
|
||||
|
||||
master_aes, _ := aes.NewCipher(m.k)
|
||||
master_aes, err := aes.NewCipher(m.k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
attr := FileAttr{name}
|
||||
attr_data, _ := encryptAttr(src.meta.key, attr)
|
||||
attr_data, err := encryptAttr(src.meta.key, attr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key := make([]byte, len(src.meta.compkey))
|
||||
err := blockEncrypt(master_aes, key, src.meta.compkey)
|
||||
err = blockEncrypt(master_aes, key, src.meta.compkey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1533,12 +1670,18 @@ func (m *Mega) Rename(src *Node, name string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = m.api_request(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
src.name = name
|
||||
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a directory in the filesystem
|
||||
|
@ -1557,12 +1700,21 @@ func (m *Mega) CreateDir(name string, parent *Node) (*Node, error) {
|
|||
compkey[i] = uint32(mrand.Int31())
|
||||
}
|
||||
|
||||
master_aes, _ := aes.NewCipher(m.k)
|
||||
master_aes, err := aes.NewCipher(m.k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attr := FileAttr{name}
|
||||
ukey := a32_to_bytes(compkey[:4])
|
||||
attr_data, _ := encryptAttr(ukey, attr)
|
||||
ukey, err := a32_to_bytes(compkey[:4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attr_data, err := encryptAttr(ukey, attr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := make([]byte, len(ukey))
|
||||
err := blockEncrypt(master_aes, key, ukey)
|
||||
err = blockEncrypt(master_aes, key, ukey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1578,7 +1730,10 @@ func (m *Mega) CreateDir(name string, parent *Node) (*Node, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := m.api_request(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1614,14 +1769,20 @@ func (m *Mega) Delete(node *Node, destroy bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = m.api_request(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parent := m.FS.lookup[node.hash]
|
||||
parent.removeChild(node)
|
||||
delete(m.FS.lookup, node.hash)
|
||||
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// process an add node event
|
||||
|
@ -1830,9 +1991,11 @@ func (m *Mega) getLink(n *Node) (string, error) {
|
|||
msg[0].Cmd = "l"
|
||||
msg[0].N = n.GetHash()
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
result, err := m.api_request(req)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue