mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	Add salt for every single user
This commit is contained in:
		@@ -7,7 +7,6 @@ github.com/go-martini/martini =
 | 
				
			|||||||
github.com/Unknwon/com = 
 | 
					github.com/Unknwon/com = 
 | 
				
			||||||
github.com/Unknwon/cae = 
 | 
					github.com/Unknwon/cae = 
 | 
				
			||||||
github.com/Unknwon/goconfig = 
 | 
					github.com/Unknwon/goconfig = 
 | 
				
			||||||
github.com/dchest/scrypt = 
 | 
					 | 
				
			||||||
github.com/nfnt/resize = 
 | 
					github.com/nfnt/resize = 
 | 
				
			||||||
github.com/lunny/xorm = 
 | 
					github.com/lunny/xorm = 
 | 
				
			||||||
github.com/go-sql-driver/mysql = 
 | 
					github.com/go-sql-driver/mysql = 
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,9 +5,9 @@ Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language
 | 
				
			|||||||
 | 
					
 | 
				
			||||||

 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Current version: 0.2.1 Alpha
 | 
					##### Current version: 0.2.2 Alpha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Due to testing purpose, data of [try.gogits.org](http://try.gogits.org) has been reset in March 29, 2014 and will reset multiple times after. Please do NOT put your important data on the site.
 | 
					#### Due to testing purpose, data of [try.gogits.org](http://try.gogits.org) has been reset in April 6, 2014 and will reset multiple times after. Please do NOT put your important data on the site.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Other language version
 | 
					#### Other language version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。
 | 
				
			|||||||
 | 
					
 | 
				
			||||||

 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### 当前版本:0.2.1 Alpha
 | 
					##### 当前版本:0.2.2 Alpha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 开发目的
 | 
					## 开发目的
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							@@ -19,7 +19,7 @@ import (
 | 
				
			|||||||
// Test that go1.2 tag above is included in builds. main.go refers to this definition.
 | 
					// Test that go1.2 tag above is included in builds. main.go refers to this definition.
 | 
				
			||||||
const go12tag = true
 | 
					const go12tag = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const APP_VER = "0.2.1.0406 Alpha"
 | 
					const APP_VER = "0.2.2.0406 Alpha"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	base.AppVer = APP_VER
 | 
						base.AppVer = APP_VER
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@
 | 
				
			|||||||
package models
 | 
					package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/sha256"
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
@@ -13,8 +14,6 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/dchest/scrypt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/gogits/git"
 | 
						"github.com/gogits/git"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
@@ -62,6 +61,7 @@ type User struct {
 | 
				
			|||||||
	IsActive      bool
 | 
						IsActive      bool
 | 
				
			||||||
	IsAdmin       bool
 | 
						IsAdmin       bool
 | 
				
			||||||
	Rands         string    `xorm:"VARCHAR(10)"`
 | 
						Rands         string    `xorm:"VARCHAR(10)"`
 | 
				
			||||||
 | 
						Salt          string    `xorm:"VARCHAR(10)"`
 | 
				
			||||||
	Created       time.Time `xorm:"created"`
 | 
						Created       time.Time `xorm:"created"`
 | 
				
			||||||
	Updated       time.Time `xorm:"updated"`
 | 
						Updated       time.Time `xorm:"updated"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -89,10 +89,9 @@ func (user *User) NewGitSig() *git.Signature {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EncodePasswd encodes password to safe format.
 | 
					// EncodePasswd encodes password to safe format.
 | 
				
			||||||
func (user *User) EncodePasswd() error {
 | 
					func (user *User) EncodePasswd() {
 | 
				
			||||||
	newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(base.SecretKey), 16384, 8, 1, 64)
 | 
						newPasswd := base.PBKDF2([]byte(user.Passwd), []byte(user.Salt), 10000, 50, sha256.New)
 | 
				
			||||||
	user.Passwd = fmt.Sprintf("%x", newPasswd)
 | 
						user.Passwd = fmt.Sprintf("%x", newPasswd)
 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Member represents user is member of organization.
 | 
					// Member represents user is member of organization.
 | 
				
			||||||
@@ -148,9 +147,9 @@ func RegisterUser(user *User) (*User, error) {
 | 
				
			|||||||
	user.Avatar = base.EncodeMd5(user.Email)
 | 
						user.Avatar = base.EncodeMd5(user.Email)
 | 
				
			||||||
	user.AvatarEmail = user.Email
 | 
						user.AvatarEmail = user.Email
 | 
				
			||||||
	user.Rands = GetUserSalt()
 | 
						user.Rands = GetUserSalt()
 | 
				
			||||||
	if err = user.EncodePasswd(); err != nil {
 | 
						user.Salt = GetUserSalt()
 | 
				
			||||||
		return nil, err
 | 
						user.EncodePasswd()
 | 
				
			||||||
	} else if _, err = orm.Insert(user); err != nil {
 | 
						if _, err = orm.Insert(user); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if err = os.MkdirAll(UserPath(user.Name), os.ModePerm); err != nil {
 | 
						} else if err = os.MkdirAll(UserPath(user.Name), os.ModePerm); err != nil {
 | 
				
			||||||
		if _, err := orm.Id(user.Id).Delete(&User{}); err != nil {
 | 
							if _, err := orm.Id(user.Id).Delete(&User{}); err != nil {
 | 
				
			||||||
@@ -384,18 +383,20 @@ func GetUserByEmail(email string) (*User, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// LoginUserPlain validates user by raw user name and password.
 | 
					// LoginUserPlain validates user by raw user name and password.
 | 
				
			||||||
func LoginUserPlain(name, passwd string) (*User, error) {
 | 
					func LoginUserPlain(name, passwd string) (*User, error) {
 | 
				
			||||||
	user := User{LowerName: strings.ToLower(name), Passwd: passwd}
 | 
						user := User{LowerName: strings.ToLower(name)}
 | 
				
			||||||
	if err := user.EncodePasswd(); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	has, err := orm.Get(&user)
 | 
						has, err := orm.Get(&user)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !has {
 | 
				
			||||||
		err = ErrUserNotExist
 | 
							return nil, ErrUserNotExist
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &user, err
 | 
					
 | 
				
			||||||
 | 
						newUser := &User{Passwd: passwd, Salt: user.Salt}
 | 
				
			||||||
 | 
						newUser.EncodePasswd()
 | 
				
			||||||
 | 
						if user.Passwd != newUser.Passwd {
 | 
				
			||||||
 | 
							return nil, ErrUserNotExist
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &user, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Follow is connection request for receiving user notifycation.
 | 
					// Follow is connection request for receiving user notifycation.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,12 +6,14 @@ package base
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 | 
						"crypto/hmac"
 | 
				
			||||||
	"crypto/md5"
 | 
						"crypto/md5"
 | 
				
			||||||
	"crypto/rand"
 | 
						"crypto/rand"
 | 
				
			||||||
	"crypto/sha1"
 | 
						"crypto/sha1"
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"hash"
 | 
				
			||||||
	"math"
 | 
						"math"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
@@ -40,6 +42,44 @@ func GetRandomString(n int, alphabets ...byte) string {
 | 
				
			|||||||
	return string(bytes)
 | 
						return string(bytes)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// http://code.google.com/p/go/source/browse/pbkdf2/pbkdf2.go?repo=crypto
 | 
				
			||||||
 | 
					func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
 | 
				
			||||||
 | 
						prf := hmac.New(h, password)
 | 
				
			||||||
 | 
						hashLen := prf.Size()
 | 
				
			||||||
 | 
						numBlocks := (keyLen + hashLen - 1) / hashLen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var buf [4]byte
 | 
				
			||||||
 | 
						dk := make([]byte, 0, numBlocks*hashLen)
 | 
				
			||||||
 | 
						U := make([]byte, hashLen)
 | 
				
			||||||
 | 
						for block := 1; block <= numBlocks; block++ {
 | 
				
			||||||
 | 
							// N.B.: || means concatenation, ^ means XOR
 | 
				
			||||||
 | 
							// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
 | 
				
			||||||
 | 
							// U_1 = PRF(password, salt || uint(i))
 | 
				
			||||||
 | 
							prf.Reset()
 | 
				
			||||||
 | 
							prf.Write(salt)
 | 
				
			||||||
 | 
							buf[0] = byte(block >> 24)
 | 
				
			||||||
 | 
							buf[1] = byte(block >> 16)
 | 
				
			||||||
 | 
							buf[2] = byte(block >> 8)
 | 
				
			||||||
 | 
							buf[3] = byte(block)
 | 
				
			||||||
 | 
							prf.Write(buf[:4])
 | 
				
			||||||
 | 
							dk = prf.Sum(dk)
 | 
				
			||||||
 | 
							T := dk[len(dk)-hashLen:]
 | 
				
			||||||
 | 
							copy(U, T)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// U_n = PRF(password, U_(n-1))
 | 
				
			||||||
 | 
							for n := 2; n <= iter; n++ {
 | 
				
			||||||
 | 
								prf.Reset()
 | 
				
			||||||
 | 
								prf.Write(U)
 | 
				
			||||||
 | 
								U = U[:0]
 | 
				
			||||||
 | 
								U = prf.Sum(U)
 | 
				
			||||||
 | 
								for x := range U {
 | 
				
			||||||
 | 
									T[x] ^= U[x]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return dk[:keyLen]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// verify time limit code
 | 
					// verify time limit code
 | 
				
			||||||
func VerifyTimeLimitCode(data string, minutes int, code string) bool {
 | 
					func VerifyTimeLimitCode(data string, minutes int, code string) bool {
 | 
				
			||||||
	if len(code) <= 18 {
 | 
						if len(code) <= 18 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,11 +73,7 @@ func SettingPassword(ctx *middleware.Context, form auth.UpdatePasswdForm) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	user := ctx.User
 | 
						user := ctx.User
 | 
				
			||||||
	newUser := &models.User{Passwd: form.NewPasswd}
 | 
						newUser := &models.User{Passwd: form.NewPasswd}
 | 
				
			||||||
	if err := newUser.EncodePasswd(); err != nil {
 | 
						newUser.EncodePasswd()
 | 
				
			||||||
		ctx.Handle(200, "setting.SettingPassword", err)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if user.Passwd != newUser.Passwd {
 | 
						if user.Passwd != newUser.Passwd {
 | 
				
			||||||
		ctx.Data["HasError"] = true
 | 
							ctx.Data["HasError"] = true
 | 
				
			||||||
		ctx.Data["ErrorMsg"] = "Old password is not correct"
 | 
							ctx.Data["ErrorMsg"] = "Old password is not correct"
 | 
				
			||||||
@@ -85,6 +81,7 @@ func SettingPassword(ctx *middleware.Context, form auth.UpdatePasswdForm) {
 | 
				
			|||||||
		ctx.Data["HasError"] = true
 | 
							ctx.Data["HasError"] = true
 | 
				
			||||||
		ctx.Data["ErrorMsg"] = "New password and re-type password are not same"
 | 
							ctx.Data["ErrorMsg"] = "New password and re-type password are not same"
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							newUser.Salt = models.GetUserSalt()
 | 
				
			||||||
		user.Passwd = newUser.Passwd
 | 
							user.Passwd = newUser.Passwd
 | 
				
			||||||
		if err := models.UpdateUser(user); err != nil {
 | 
							if err := models.UpdateUser(user); err != nil {
 | 
				
			||||||
			ctx.Handle(200, "setting.SettingPassword", err)
 | 
								ctx.Handle(200, "setting.SettingPassword", err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -477,12 +477,9 @@ func ResetPasswd(ctx *middleware.Context) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		u.Passwd = passwd
 | 
							u.Passwd = passwd
 | 
				
			||||||
		if err := u.EncodePasswd(); err != nil {
 | 
					 | 
				
			||||||
			ctx.Handle(404, "user.ResetPasswd(EncodePasswd)", err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		u.Rands = models.GetUserSalt()
 | 
							u.Rands = models.GetUserSalt()
 | 
				
			||||||
 | 
							u.Salt = models.GetUserSalt()
 | 
				
			||||||
 | 
							u.EncodePasswd()
 | 
				
			||||||
		if err := models.UpdateUser(u); err != nil {
 | 
							if err := models.UpdateUser(u); err != nil {
 | 
				
			||||||
			ctx.Handle(404, "user.ResetPasswd(UpdateUser)", err)
 | 
								ctx.Handle(404, "user.ResetPasswd(UpdateUser)", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user