...

Source file src/github.com/godbus/dbus/v5/auth_sha1.go

Documentation: github.com/godbus/dbus/v5

     1  package dbus
     2  
     3  import (
     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.
    15  func AuthCookieSha1(user, home string) Auth {
    16  	return authCookieSha1{user, home}
    17  }
    18  
    19  type authCookieSha1 struct {
    20  	user, home string
    21  }
    22  
    23  func (a authCookieSha1) FirstData() ([]byte, []byte, AuthStatus) {
    24  	b := make([]byte, 2*len(a.user))
    25  	hex.Encode(b, []byte(a.user))
    26  	return []byte("DBUS_COOKIE_SHA1"), b, AuthContinue
    27  }
    28  
    29  func (a authCookieSha1) HandleData(data []byte) ([]byte, AuthStatus) {
    30  	challenge := make([]byte, len(data)/2)
    31  	_, err := hex.Decode(challenge, data)
    32  	if err != nil {
    33  		return nil, AuthError
    34  	}
    35  	b := bytes.Split(challenge, []byte{' '})
    36  	if len(b) != 3 {
    37  		return nil, AuthError
    38  	}
    39  	context := b[0]
    40  	id := b[1]
    41  	svchallenge := b[2]
    42  	cookie := a.getCookie(context, id)
    43  	if cookie == nil {
    44  		return nil, AuthError
    45  	}
    46  	clchallenge := a.generateChallenge()
    47  	if clchallenge == nil {
    48  		return nil, AuthError
    49  	}
    50  	hash := sha1.New()
    51  	hash.Write(bytes.Join([][]byte{svchallenge, clchallenge, cookie}, []byte{':'}))
    52  	hexhash := make([]byte, 2*hash.Size())
    53  	hex.Encode(hexhash, hash.Sum(nil))
    54  	data = append(clchallenge, ' ')
    55  	data = append(data, hexhash...)
    56  	resp := make([]byte, 2*len(data))
    57  	hex.Encode(resp, data)
    58  	return resp, AuthOk
    59  }
    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.)
    65  func (a authCookieSha1) getCookie(context, id []byte) []byte {
    66  	file, err := os.Open(a.home + "/.dbus-keyrings/" + string(context))
    67  	if err != nil {
    68  		return nil
    69  	}
    70  	defer file.Close()
    71  	rd := bufio.NewReader(file)
    72  	for {
    73  		line, err := rd.ReadBytes('\n')
    74  		if err != nil {
    75  			return nil
    76  		}
    77  		line = line[:len(line)-1]
    78  		b := bytes.Split(line, []byte{' '})
    79  		if len(b) != 3 {
    80  			return nil
    81  		}
    82  		if bytes.Equal(b[0], id) {
    83  			return b[2]
    84  		}
    85  	}
    86  }
    87  
    88  // generateChallenge returns a random, hex-encoded challenge, or nil on error
    89  // (see above).
    90  func (a authCookieSha1) generateChallenge() []byte {
    91  	b := make([]byte, 16)
    92  	n, err := rand.Read(b)
    93  	if err != nil {
    94  		return nil
    95  	}
    96  	if n != 16 {
    97  		return nil
    98  	}
    99  	enc := make([]byte, 32)
   100  	hex.Encode(enc, b)
   101  	return enc
   102  }
   103  

View as plain text