You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
2.6 KiB
113 lines
2.6 KiB
// Copyright (c) 2021 Proton Technologies AG |
|
// Copyright (c) 2022 Lukasz Janyst <lukasz@jany.st> |
|
// |
|
// This file is part of Peroxide. |
|
// |
|
// Peroxide is free software: you can redistribute it and/or modify |
|
// it under the terms of the GNU General Public License as published by |
|
// the Free Software Foundation, either version 3 of the License, or |
|
// (at your option) any later version. |
|
// |
|
// Peroxide is distributed in the hope that it will be useful, |
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
// GNU General Public License for more details. |
|
// |
|
// You should have received a copy of the GNU General Public License |
|
// along with Peroxide. If not, see <https://www.gnu.org/licenses/>. |
|
|
|
package keychain |
|
|
|
import ( |
|
"fmt" |
|
"sync" |
|
) |
|
|
|
// Version is the keychain data version. |
|
const Version = "k11" |
|
|
|
// NewKeychain creates a new native keychain. |
|
func NewKeychain(keychainName string) (*Keychain, error) { |
|
helper, err := newStaticKeychain() |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
return newKeychain(helper, fmt.Sprintf("protonmail/%v/users", keychainName)), nil |
|
} |
|
|
|
func newKeychain(helper Helper, url string) *Keychain { |
|
return &Keychain{ |
|
helper: helper, |
|
url: url, |
|
locker: &sync.Mutex{}, |
|
} |
|
} |
|
|
|
type Keychain struct { |
|
helper Helper |
|
url string |
|
locker sync.Locker |
|
} |
|
|
|
func (kc *Keychain) List() ([]string, error) { |
|
kc.locker.Lock() |
|
defer kc.locker.Unlock() |
|
|
|
userIDsByURL, err := kc.helper.List() |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
var userIDs []string // nolint[prealloc] |
|
|
|
for url, userID := range userIDsByURL { |
|
if url != kc.secretURL(userID) { |
|
continue |
|
} |
|
|
|
userIDs = append(userIDs, userID) |
|
} |
|
|
|
return userIDs, nil |
|
} |
|
|
|
func (kc *Keychain) Delete(userID string) error { |
|
kc.locker.Lock() |
|
defer kc.locker.Unlock() |
|
|
|
userIDsByURL, err := kc.helper.List() |
|
if err != nil { |
|
return err |
|
} |
|
|
|
if _, ok := userIDsByURL[kc.secretURL(userID)]; !ok { |
|
return nil |
|
} |
|
|
|
return kc.helper.Delete(kc.secretURL(userID)) |
|
} |
|
|
|
// Get returns the username and secret for the given userID. |
|
func (kc *Keychain) Get(userID string) (string, string, error) { |
|
kc.locker.Lock() |
|
defer kc.locker.Unlock() |
|
|
|
return kc.helper.Get(kc.secretURL(userID)) |
|
} |
|
|
|
func (kc *Keychain) Put(userID, secret string) error { |
|
kc.locker.Lock() |
|
defer kc.locker.Unlock() |
|
|
|
return kc.helper.Add(&Credentials{ |
|
ServerURL: kc.secretURL(userID), |
|
Username: userID, |
|
Secret: secret, |
|
}) |
|
} |
|
|
|
// secretURL returns the URL referring to a userID's secrets. |
|
func (kc *Keychain) secretURL(userID string) string { |
|
return fmt.Sprintf("%v/%v", kc.url, userID) |
|
}
|
|
|