add .gpg url (match github behaviour) (#6610)

* add .gpg url (match github behaviour)

* wildcard

* test to export maximum data

* working POC

* add comment for old imported keys

* cleaning

* Update routers/user/profile.go

Co-Authored-By: sapk <sapk@users.noreply.github.com>

* add migration script

* add integration tests
This commit is contained in:
Antoine GIRARD 2019-04-14 18:43:56 +02:00 committed by techknowlogick
parent 38889f09cb
commit d699de32f2
10 changed files with 259 additions and 20 deletions

View file

@ -43,6 +43,12 @@ type GPGKey struct {
CanCertify bool
}
//GPGKeyImport the original import of key
type GPGKeyImport struct {
KeyID string `xorm:"pk CHAR(16) NOT NULL"`
Content string `xorm:"TEXT NOT NULL"`
}
// BeforeInsert will be invoked by XORM before inserting a record
func (key *GPGKey) BeforeInsert() {
key.AddedUnix = util.TimeStampNow()
@ -74,6 +80,18 @@ func GetGPGKeyByID(keyID int64) (*GPGKey, error) {
return key, nil
}
// GetGPGImportByKeyID returns the import public armored key by given KeyID.
func GetGPGImportByKeyID(keyID string) (*GPGKeyImport, error) {
key := new(GPGKeyImport)
has, err := x.ID(keyID).Get(key)
if err != nil {
return nil, err
} else if !has {
return nil, ErrGPGKeyImportNotExist{keyID}
}
return key, nil
}
// checkArmoredGPGKeyString checks if the given key string is a valid GPG armored key.
// The function returns the actual public key on success
func checkArmoredGPGKeyString(content string) (*openpgp.Entity, error) {
@ -84,15 +102,37 @@ func checkArmoredGPGKeyString(content string) (*openpgp.Entity, error) {
return list[0], nil
}
//addGPGKey add key and subkeys to database
func addGPGKey(e Engine, key *GPGKey) (err error) {
//addGPGKey add key, import and subkeys to database
func addGPGKey(e Engine, key *GPGKey, content string) (err error) {
//Add GPGKeyImport
if _, err = e.Insert(GPGKeyImport{
KeyID: key.KeyID,
Content: content,
}); err != nil {
return err
}
// Save GPG primary key.
if _, err = e.Insert(key); err != nil {
return err
}
// Save GPG subs key.
for _, subkey := range key.SubsKey {
if err := addGPGKey(e, subkey); err != nil {
if err := addGPGSubKey(e, subkey); err != nil {
return err
}
}
return nil
}
//addGPGSubKey add subkeys to database
func addGPGSubKey(e Engine, key *GPGKey) (err error) {
// Save GPG primary key.
if _, err = e.Insert(key); err != nil {
return err
}
// Save GPG subs key.
for _, subkey := range key.SubsKey {
if err := addGPGSubKey(e, subkey); err != nil {
return err
}
}
@ -127,14 +167,14 @@ func AddGPGKey(ownerID int64, content string) (*GPGKey, error) {
return nil, err
}
if err = addGPGKey(sess, key); err != nil {
if err = addGPGKey(sess, key, content); err != nil {
return nil, err
}
return key, sess.Commit()
}
//base64EncPubKey encode public kay content to base 64
//base64EncPubKey encode public key content to base 64
func base64EncPubKey(pubkey *packet.PublicKey) (string, error) {
var w bytes.Buffer
err := pubkey.Serialize(&w)
@ -144,6 +184,34 @@ func base64EncPubKey(pubkey *packet.PublicKey) (string, error) {
return base64.StdEncoding.EncodeToString(w.Bytes()), nil
}
//base64DecPubKey decode public key content from base 64
func base64DecPubKey(content string) (*packet.PublicKey, error) {
b, err := readerFromBase64(content)
if err != nil {
return nil, err
}
//Read key
p, err := packet.Read(b)
if err != nil {
return nil, err
}
//Check type
pkey, ok := p.(*packet.PublicKey)
if !ok {
return nil, fmt.Errorf("key is not a public key")
}
return pkey, nil
}
//GPGKeyToEntity retrieve the imported key and the traducted entity
func GPGKeyToEntity(k *GPGKey) (*openpgp.Entity, error) {
impKey, err := GetGPGImportByKeyID(k.KeyID)
if err != nil {
return nil, err
}
return checkArmoredGPGKeyString(impKey.Content)
}
//parseSubGPGKey parse a sub Key
func parseSubGPGKey(ownerID int64, primaryID string, pubkey *packet.PublicKey, expiry time.Time) (*GPGKey, error) {
content, err := base64EncPubKey(pubkey)
@ -244,6 +312,11 @@ func deleteGPGKey(e *xorm.Session, keyID string) (int64, error) {
if keyID == "" {
return 0, fmt.Errorf("empty KeyId forbidden") //Should never happen but just to be sure
}
//Delete imported key
n, err := e.Where("key_id=?", keyID).Delete(new(GPGKeyImport))
if err != nil {
return n, err
}
return e.Where("key_id=?", keyID).Or("primary_key_id=?", keyID).Delete(new(GPGKey))
}
@ -339,22 +412,10 @@ func verifySign(s *packet.Signature, h hash.Hash, k *GPGKey) error {
return fmt.Errorf("key can not sign")
}
//Decode key
b, err := readerFromBase64(k.Content)
pkey, err := base64DecPubKey(k.Content)
if err != nil {
return err
}
//Read key
p, err := packet.Read(b)
if err != nil {
return err
}
//Check type
pkey, ok := p.(*packet.PublicKey)
if !ok {
return fmt.Errorf("key is not a public key")
}
return pkey.VerifySignature(h, s)
}