mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Use fingerprint to check instead content for public key (#911)
* use fingerprint to check instead content for public key * add fingerprint field for ErrKeyAlreadyExist
This commit is contained in:
		| @@ -213,8 +213,9 @@ func (err ErrKeyNotExist) Error() string { | |||||||
|  |  | ||||||
| // ErrKeyAlreadyExist represents a "KeyAlreadyExist" kind of error. | // ErrKeyAlreadyExist represents a "KeyAlreadyExist" kind of error. | ||||||
| type ErrKeyAlreadyExist struct { | type ErrKeyAlreadyExist struct { | ||||||
| 	OwnerID int64 | 	OwnerID     int64 | ||||||
| 	Content string | 	Fingerprint string | ||||||
|  | 	Content     string | ||||||
| } | } | ||||||
|  |  | ||||||
| // IsErrKeyAlreadyExist checks if an error is a ErrKeyAlreadyExist. | // IsErrKeyAlreadyExist checks if an error is a ErrKeyAlreadyExist. | ||||||
| @@ -224,7 +225,8 @@ func IsErrKeyAlreadyExist(err error) bool { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (err ErrKeyAlreadyExist) Error() string { | func (err ErrKeyAlreadyExist) Error() string { | ||||||
| 	return fmt.Sprintf("public key already exists [owner_id: %d, content: %s]", err.OwnerID, err.Content) | 	return fmt.Sprintf("public key already exists [owner_id: %d, finter_print: %s, content: %s]", | ||||||
|  | 		err.OwnerID, err.Fingerprint, err.Content) | ||||||
| } | } | ||||||
|  |  | ||||||
| // ErrKeyNameAlreadyUsed represents a "KeyNameAlreadyUsed" kind of error. | // ErrKeyNameAlreadyUsed represents a "KeyNameAlreadyUsed" kind of error. | ||||||
|   | |||||||
| @@ -354,41 +354,50 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // checkKeyContent only checks if key content has been used as public key, | // checkKeyFingerprint only checks if key fingerprint has been used as public key, | ||||||
| // it is OK to use same key as deploy key for multiple repositories/users. | // it is OK to use same key as deploy key for multiple repositories/users. | ||||||
| func checkKeyContent(content string) error { | func checkKeyFingerprint(e Engine, fingerprint string) error { | ||||||
| 	has, err := x.Get(&PublicKey{ | 	has, err := e.Get(&PublicKey{ | ||||||
| 		Content: content, | 		Fingerprint: fingerprint, | ||||||
| 		Type:    KeyTypeUser, | 		Type:        KeyTypeUser, | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} else if has { | 	} else if has { | ||||||
| 		return ErrKeyAlreadyExist{0, content} | 		return ErrKeyAlreadyExist{0, fingerprint, ""} | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func addKey(e Engine, key *PublicKey) (err error) { | func calcFingerprint(publicKeyContent string) (string, error) { | ||||||
| 	// Calculate fingerprint. | 	// Calculate fingerprint. | ||||||
| 	tmpPath := strings.Replace(path.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()), | 	tmpPath := strings.Replace(path.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()), | ||||||
| 		"id_rsa.pub"), "\\", "/", -1) | 		"id_rsa.pub"), "\\", "/", -1) | ||||||
| 	dir := path.Dir(tmpPath) | 	dir := path.Dir(tmpPath) | ||||||
|  |  | ||||||
| 	if err := os.MkdirAll(dir, os.ModePerm); err != nil { | 	if err := os.MkdirAll(dir, os.ModePerm); err != nil { | ||||||
| 		return fmt.Errorf("Failed to create dir %s: %v", dir, err) | 		return "", fmt.Errorf("Failed to create dir %s: %v", dir, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err = ioutil.WriteFile(tmpPath, []byte(key.Content), 0644); err != nil { | 	if err := ioutil.WriteFile(tmpPath, []byte(publicKeyContent), 0644); err != nil { | ||||||
| 		return err | 		return "", err | ||||||
| 	} | 	} | ||||||
| 	stdout, stderr, err := process.GetManager().Exec("AddPublicKey", "ssh-keygen", "-lf", tmpPath) | 	stdout, stderr, err := process.GetManager().Exec("AddPublicKey", "ssh-keygen", "-lf", tmpPath) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("'ssh-keygen -lf %s' failed with error '%s': %s", tmpPath, err, stderr) | 		return "", fmt.Errorf("'ssh-keygen -lf %s' failed with error '%s': %s", tmpPath, err, stderr) | ||||||
| 	} else if len(stdout) < 2 { | 	} else if len(stdout) < 2 { | ||||||
| 		return errors.New("not enough output for calculating fingerprint: " + stdout) | 		return "", errors.New("not enough output for calculating fingerprint: " + stdout) | ||||||
|  | 	} | ||||||
|  | 	return strings.Split(stdout, " ")[1], nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func addKey(e Engine, key *PublicKey) (err error) { | ||||||
|  | 	if len(key.Fingerprint) <= 0 { | ||||||
|  | 		key.Fingerprint, err = calcFingerprint(key.Content) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	key.Fingerprint = strings.Split(stdout, " ")[1] |  | ||||||
|  |  | ||||||
| 	// Save SSH key. | 	// Save SSH key. | ||||||
| 	if _, err = e.Insert(key); err != nil { | 	if _, err = e.Insert(key); err != nil { | ||||||
| @@ -405,7 +414,13 @@ func addKey(e Engine, key *PublicKey) (err error) { | |||||||
| // AddPublicKey adds new public key to database and authorized_keys file. | // AddPublicKey adds new public key to database and authorized_keys file. | ||||||
| func AddPublicKey(ownerID int64, name, content string) (*PublicKey, error) { | func AddPublicKey(ownerID int64, name, content string) (*PublicKey, error) { | ||||||
| 	log.Trace(content) | 	log.Trace(content) | ||||||
| 	if err := checkKeyContent(content); err != nil { |  | ||||||
|  | 	fingerprint, err := calcFingerprint(content) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := checkKeyFingerprint(x, fingerprint); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -426,11 +441,12 @@ func AddPublicKey(ownerID int64, name, content string) (*PublicKey, error) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	key := &PublicKey{ | 	key := &PublicKey{ | ||||||
| 		OwnerID: ownerID, | 		OwnerID:     ownerID, | ||||||
| 		Name:    name, | 		Name:        name, | ||||||
| 		Content: content, | 		Fingerprint: fingerprint, | ||||||
| 		Mode:    AccessModeWrite, | 		Content:     content, | ||||||
| 		Type:    KeyTypeUser, | 		Mode:        AccessModeWrite, | ||||||
|  | 		Type:        KeyTypeUser, | ||||||
| 	} | 	} | ||||||
| 	if err = addKey(sess, key); err != nil { | 	if err = addKey(sess, key); err != nil { | ||||||
| 		return nil, fmt.Errorf("addKey: %v", err) | 		return nil, fmt.Errorf("addKey: %v", err) | ||||||
| @@ -665,14 +681,15 @@ func HasDeployKey(keyID, repoID int64) bool { | |||||||
|  |  | ||||||
| // AddDeployKey add new deploy key to database and authorized_keys file. | // AddDeployKey add new deploy key to database and authorized_keys file. | ||||||
| func AddDeployKey(repoID int64, name, content string) (*DeployKey, error) { | func AddDeployKey(repoID int64, name, content string) (*DeployKey, error) { | ||||||
| 	if err := checkKeyContent(content); err != nil { | 	fingerprint, err := calcFingerprint(content) | ||||||
|  | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	pkey := &PublicKey{ | 	pkey := &PublicKey{ | ||||||
| 		Content: content, | 		Fingerprint: fingerprint, | ||||||
| 		Mode:    AccessModeRead, | 		Mode:        AccessModeRead, | ||||||
| 		Type:    KeyTypeDeploy, | 		Type:        KeyTypeDeploy, | ||||||
| 	} | 	} | ||||||
| 	has, err := x.Get(pkey) | 	has, err := x.Get(pkey) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -687,6 +704,8 @@ func AddDeployKey(repoID int64, name, content string) (*DeployKey, error) { | |||||||
|  |  | ||||||
| 	// First time use this deploy key. | 	// First time use this deploy key. | ||||||
| 	if !has { | 	if !has { | ||||||
|  | 		pkey.Content = content | ||||||
|  | 		pkey.Name = name | ||||||
| 		if err = addKey(sess, pkey); err != nil { | 		if err = addKey(sess, pkey); err != nil { | ||||||
| 			return nil, fmt.Errorf("addKey: %v", err) | 			return nil, fmt.Errorf("addKey: %v", err) | ||||||
| 		} | 		} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Lunny Xiao
					Lunny Xiao