1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
// Copyright 2013 Jonas mg
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Passwords
//
// If the passwd field contains some string that is not a valid result of
// hashing, for instance "!" or "*", the user will not be able to use a unix
// passwd to log in (but the user may log in the system by other means).
//
// A passwd field which starts with a exclamation mark means that the passwd is
// locked. The remaining characters on the line represent the passwd field before
// the passwd was locked.
package user
import (
"bufio"
"errors"
"io"
"log"
"os"
"github.com/tredoe/osutil/user/crypt"
_ "github.com/tredoe/osutil/user/crypt/md5_crypt"
_ "github.com/tredoe/osutil/user/crypt/sha256_crypt"
_ "github.com/tredoe/osutil/user/crypt/sha512_crypt"
//_ "github.com/tredoe/osutil/user/crypt/bcrypt"
)
const lockChar = '!' // Character added at the beginning of the passwd to lock it.
var ErrShadowPasswd = errors.New("no found user with shadowed passwd")
// lookupCrypter returns the first crypt function found in shadowed passwd file.
func lookupCrypter() (crypt.Crypter, error) {
f, err := os.Open(fileShadow)
if err != nil {
return nil, err
}
defer f.Close()
buf := bufio.NewReader(f)
for {
line, _, err := buf.ReadLine()
if err != nil {
if err == io.EOF {
return nil, ErrShadowPasswd
}
log.Print(err)
continue
}
shadow, err := parseShadow(string(line))
if err != nil {
log.Print(err)
continue
}
if shadow.password[0] == '$' {
return crypt.NewFromHash(shadow.password), nil
}
}
//return nil, ErrShadowPasswd
}
// SetCrypter sets the crypt function to can hash the passwords.
// The type "crypt.Crypt" comes from package "github.com/tredoe/osutil/user/crypt".
func SetCrypter(c crypt.Crypt) {
loadConfig()
config.crypter = crypt.New(c)
}
// Passwd sets a hashed passwd for the actual user.
// The passwd must be supplied in clear-text.
func (s *Shadow) Passwd(key []byte) {
loadConfig()
s.password, _ = config.crypter.Generate(key, nil)
s.setChange()
}
// Passwd sets a hashed passwd for the actual group.
// The passwd must be supplied in clear-text.
func (gs *GShadow) Passwd(key []byte) {
loadConfig()
gs.password, _ = config.crypter.Generate(key, nil)
}
// == Change passwd
// ChPasswd updates passwd.
// The passwd must be supplied in clear-text.
func ChPasswd(user string, key []byte) error {
shadow, err := LookupShadow(user)
if err != nil {
return err
}
shadow.Passwd(key)
return edit(user, shadow)
}
// ChGPasswd updates group passwd.
// The passwd must be supplied in clear-text.
func ChGPasswd(group string, key []byte) error {
gshadow, err := LookupGShadow(group)
if err != nil {
return err
}
gshadow.Passwd(key)
return edit(group, gshadow)
}
// == Locking
// LockUser locks the passwd of the given user.
func LockUser(name string) error {
shadow, err := LookupShadow(name)
if err != nil {
return err
}
if shadow.password[0] != lockChar {
shadow.password = string(lockChar) + shadow.password
return edit(name, shadow)
}
return nil
}
// UnlockUser unlocks the passwd of the given user.
func UnlockUser(name string) error {
shadow, err := LookupShadow(name)
if err != nil {
return err
}
if shadow.password[0] == lockChar {
shadow.password = shadow.password[1:]
return edit(name, shadow)
}
return nil
}
|