go-tg-screenshot-bot
102 строки · 2.4 Кб
1package dbus2
3import (4"bufio"5"bytes"6"crypto/rand"7"crypto/sha1"8"encoding/hex"9"os"10)
11
12// AuthCookieSha1 returns an Auth that authenticates as the given user with the
13// DBUS_COOKIE_SHA1 mechanism. The home parameter should specify the home
14// directory of the user.
15func AuthCookieSha1(user, home string) Auth {16return authCookieSha1{user, home}17}
18
19type authCookieSha1 struct {20user, home string21}
22
23func (a authCookieSha1) FirstData() ([]byte, []byte, AuthStatus) {24b := make([]byte, 2*len(a.user))25hex.Encode(b, []byte(a.user))26return []byte("DBUS_COOKIE_SHA1"), b, AuthContinue27}
28
29func (a authCookieSha1) HandleData(data []byte) ([]byte, AuthStatus) {30challenge := make([]byte, len(data)/2)31_, err := hex.Decode(challenge, data)32if err != nil {33return nil, AuthError34}35b := bytes.Split(challenge, []byte{' '})36if len(b) != 3 {37return nil, AuthError38}39context := b[0]40id := b[1]41svchallenge := b[2]42cookie := a.getCookie(context, id)43if cookie == nil {44return nil, AuthError45}46clchallenge := a.generateChallenge()47if clchallenge == nil {48return nil, AuthError49}50hash := sha1.New()51hash.Write(bytes.Join([][]byte{svchallenge, clchallenge, cookie}, []byte{':'}))52hexhash := make([]byte, 2*hash.Size())53hex.Encode(hexhash, hash.Sum(nil))54data = append(clchallenge, ' ')55data = append(data, hexhash...)56resp := make([]byte, 2*len(data))57hex.Encode(resp, data)58return resp, AuthOk59}
60
61// getCookie searches for the cookie identified by id in context and returns
62// the cookie content or nil. (Since HandleData can't return a specific error,
63// but only whether an error occurred, this function also doesn't bother to
64// return an error.)
65func (a authCookieSha1) getCookie(context, id []byte) []byte {66file, err := os.Open(a.home + "/.dbus-keyrings/" + string(context))67if err != nil {68return nil69}70defer file.Close()71rd := bufio.NewReader(file)72for {73line, err := rd.ReadBytes('\n')74if err != nil {75return nil76}77line = line[:len(line)-1]78b := bytes.Split(line, []byte{' '})79if len(b) != 3 {80return nil81}82if bytes.Equal(b[0], id) {83return b[2]84}85}86}
87
88// generateChallenge returns a random, hex-encoded challenge, or nil on error
89// (see above).
90func (a authCookieSha1) generateChallenge() []byte {91b := make([]byte, 16)92n, err := rand.Read(b)93if err != nil {94return nil95}96if n != 16 {97return nil98}99enc := make([]byte, 32)100hex.Encode(enc, b)101return enc102}
103