File: crypt.go

package info (click to toggle)
golang-github-tredoe-osutil 1.5.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 476 kB
  • sloc: makefile: 4
file content (145 lines) | stat: -rw-r--r-- 3,505 bytes parent folder | download
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
}