/
user.go
128 lines (104 loc) · 2.67 KB
/
user.go
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
package etcdsshd
// #include <pwd.h>
// #include <errno.h>
import "C"
import (
"bytes"
"syscall"
"unsafe"
)
type UID uint
type GID uint
type Passwd struct {
Name string
Passwd string
UID UID
GID GID
Gecos string
Dir string
Shell string
}
type PasswdInterface interface {
Setpwent() error
Endpwent() error
Getpwent() (*Passwd, error)
Getpwnam(name string) (*Passwd, error)
Getpwuid(uid UID) (*Passwd, error)
}
var impl PasswdInterface
func RegisterPasswd(pwd PasswdInterface) {
impl = pwd
}
func setCPasswd(p *Passwd, passwd *C.struct_passwd, buf *C.char, buflen C.size_t, errnop *C.int) nssStatus {
if len(p.Name)+len(p.Passwd)+len(p.Gecos)+len(p.Dir)+len(p.Shell)+5 > int(buflen) {
*errnop = C.int(syscall.EAGAIN)
return nssStatusTryagain
}
gobuf := C.GoBytes(unsafe.Pointer(buf), C.int(buflen))
b := bytes.NewBuffer(gobuf)
b.Reset()
passwd.pw_name = (*C.char)(unsafe.Pointer(&gobuf[b.Len()]))
b.WriteString(p.Name)
b.WriteByte(0)
passwd.pw_passwd = (*C.char)(unsafe.Pointer(&gobuf[b.Len()]))
b.WriteString(p.Passwd)
b.WriteByte(0)
passwd.pw_gecos = (*C.char)(unsafe.Pointer(&gobuf[b.Len()]))
b.WriteString(p.Gecos)
b.WriteByte(0)
passwd.pw_dir = (*C.char)(unsafe.Pointer(&gobuf[b.Len()]))
b.WriteString(p.Dir)
b.WriteByte(0)
passwd.pw_shell = (*C.char)(unsafe.Pointer(&gobuf[b.Len()]))
b.WriteString(p.Shell)
b.WriteByte(0)
passwd.pw_uid = C.uint(p.UID)
passwd.pw_gid = C.uint(p.GID)
return nssStatusSuccess
}
//export go_setpwent
func go_setpwent() nssStatus {
err := impl.Setpwent()
if err != nil {
return nssStatusUnavail
}
return nssStatusSuccess
}
//export go_endpwent
func go_endpwent() nssStatus {
err := impl.Endpwent()
if err != nil {
return nssStatusUnavail
}
return nssStatusSuccess
}
//export go_getpwent
func go_getpwent(passwd *C.struct_passwd, buf *C.char, buflen C.size_t, errnop *C.int) nssStatus {
p, err := impl.Getpwent()
if err == ErrNotFound {
return nssStatusNotfound
} else if err != nil {
return nssStatusUnavail
}
return setCPasswd(p, passwd, buf, buflen, errnop)
}
//export go_getpwnam
func go_getpwnam(name string, passwd *C.struct_passwd, buf *C.char, buflen C.size_t, errnop *C.int) nssStatus {
p, err := impl.Getpwnam(name)
if err == ErrNotFound {
return nssStatusNotfound
} else if err != nil {
return nssStatusUnavail
}
return setCPasswd(p, passwd, buf, buflen, errnop)
}
//export go_getpwuid
func go_getpwuid(uid UID, passwd *C.struct_passwd, buf *C.char, buflen C.size_t, errnop *C.int) nssStatus {
p, err := impl.Getpwuid(uid)
if err == ErrNotFound {
return nssStatusNotfound
} else if err != nil {
return nssStatusUnavail
}
return setCPasswd(p, passwd, buf, buflen, errnop)
}