// ChangePasswd is used to change user password func (u *User) ChangePasswd(passwd string) error { if len(passwd) < 6 { return errors.New("password must be at least 6 chars length") } hashed, err := bcrypt.GenerateFromPassword([]byte(passwd), 10) if err != nil { return err } u.Passwd = string(hashed) if u.HaveMailbox { salt, err := NewUUID() if err != nil { return err } salt = "$6$" + salt[:16] c := sha512_crypt.New() if u.DovePasswd, err = c.Generate([]byte(passwd), []byte(salt)); err != nil { return err } } return DB.Save(u).Error }
// UserAdd add an user func UserAdd(login, passwd, mbQuota string, haveMailbox, authRelay, isCatchall bool) error { login = strings.ToLower(login) // login must be < 257 char l := len(login) if l > 256 { return errors.New("login must have less than 256 chars") } if l < 4 { return errors.New("login must be at least 4 char") } // passwd > 6 char if len(passwd) < 6 { return errors.New("password must be at least 6 chars length") } // no catchall without mailbox if isCatchall && !haveMailbox { return errors.New("only users with mailbox can be defined as catchall") } //OK user := &User{ Login: login, AuthRelay: authRelay, HaveMailbox: haveMailbox, } // if we have to create mailbox, login must be a valid email address if haveMailbox { // check if dovecot is available if !Cfg.GetDovecotSupportEnabled() { return errors.New("you must enable (and install) Dovecot support") } if _, err := mail.ParseAddress(login); err != nil { return errors.New("'login' must be a valid email address") } t := strings.Split(login, "@") if len(t) != 2 { return errors.New("'login' must be a valid email address") } // Quota if mbQuota == "" { // get default mbQuota = Cfg.GetUserMailboxDefaultQuota() } user.MailboxQuota = mbQuota // rcpthost must be in rcpthost && must be local && not an alias rcpthost, err := RcpthostGet(t[1]) if err != nil && err != gorm.ErrRecordNotFound { return err } exists := err == nil if !exists { err = DB.Save(&RcptHost{ Hostname: t[1], IsLocal: true, }).Error if err != nil { return err } } else if !rcpthost.IsLocal { return errors.New("rcpthost " + t[1] + " is already handled by tmail but declared as remote destination") } else if rcpthost.IsAlias { return errors.New("rcpthost " + t[1] + " is an domain alias. You can't add user for this kind of domain") } // home = base/d/domain/u/user user.Home = Cfg.GetUsersHomeBase() + "/" + string(t[1][0]) + "/" + t[1] + "/" + string(t[0][0]) + "/" + t[0] // catchall if isCatchall { // is there another catchall for this domain u, err := UserGetCatchallForDomain(t[1]) if err != nil { return errors.New("unable to check catchall existense for domain " + t[1]) } if u != nil { return errors.New("domain " + t[1] + "already have a catchall: " + u.Login) } } } // hash passwd hashed, err := bcrypt.GenerateFromPassword([]byte(passwd), 10) if err != nil { return err } user.Passwd = string(hashed) // sha512 for dovecot compatibility // {SHA512-CRYPT}$6$iW6KmxlZL56A1raN$4DjgXTUzFZlGQgq61YnBMF2AYWKdY5ZanOUWTDBhuvBYVzkdNjqrmpYnLlQ3M0kU1joUH0Bb2aJcPhUF0xlSq/ salt, err := NewUUID() if err != nil { return err } salt = "$6$" + salt[:16] c := sha512_crypt.New() user.DovePasswd, err = c.Generate([]byte(passwd), []byte(salt)) if err != nil { return err } return DB.Save(user).Error }
func crypt_sha512(pass string) (string, error) { c := sha512_crypt.New() sha, err := c.Generate([]byte(pass), []byte("$6$"+random(16))) if err != nil { return "", fmt.Errorf("Error generating crypt for password: %s\n", err) } return sha, err }