(Fix): fixed unsafe.Slice using &r (pointer-to-pointer) as the backing array instead of r (the calloc'd response array), which wrote password bytes into random

This commit is contained in:
2026-07-18 21:42:05 +05:30
parent 863ed82298
commit eedde29e03
5 changed files with 25 additions and 22 deletions

View File

@@ -67,6 +67,8 @@ type Credentials struct {
HomeDir string
Shell string
pamHandle *C.pam_handle_t
pamData unsafe.Pointer
pamCB cgo.Handle
}
//export latchd_pam_conv
@@ -110,16 +112,16 @@ func Validate(user, pass, service string) (*Credentials, error) {
defer C.free(unsafe.Pointer(cUser))
h := cgo.NewHandle(pass)
defer h.Delete()
cData := C.storeHandle(C.uintptr_t(h))
defer C.free(cData)
conv := C.makePAMConv(cData)
var pamh *C.pam_handle_t
ret := C.pam_start(cSvc, cUser, &conv, &pamh)
if ret != C.PAM_SUCCESS {
h.Delete()
C.free(cData)
return nil, &AuthError{ErrPAMService, fmt.Sprintf("pam_start: %s", pamErr(pamh, ret))}
}
@@ -127,6 +129,8 @@ func Validate(user, pass, service string) (*Credentials, error) {
if ret != C.PAM_SUCCESS {
msg := fmt.Sprintf("auth failed: %s", pamErr(pamh, ret))
C.pam_end(pamh, ret)
h.Delete()
C.free(cData)
return nil, &AuthError{ErrAccountValidation, msg}
}
@@ -134,12 +138,16 @@ func Validate(user, pass, service string) (*Credentials, error) {
if ret != C.PAM_SUCCESS {
msg := fmt.Sprintf("account: %s", pamErr(pamh, ret))
C.pam_end(pamh, ret)
h.Delete()
C.free(cData)
return nil, &AuthError{ErrAccountValidation, msg}
}
u, err := ouser.Lookup(user)
if err != nil {
C.pam_end(pamh, ret)
h.Delete()
C.free(cData)
return nil, &AuthError{ErrUsernameNotFound, fmt.Sprintf("lookup %s: %v", user, err)}
}
@@ -163,6 +171,8 @@ func Validate(user, pass, service string) (*Credentials, error) {
HomeDir: u.HomeDir,
Shell: "/bin/sh",
pamHandle: pamh,
pamData: cData,
pamCB: h,
}, nil
}
@@ -180,6 +190,11 @@ func (c *Credentials) CloseSession() {
C.pam_end(c.pamHandle, 0)
c.pamHandle = nil
}
if c.pamData != nil {
C.free(c.pamData)
c.pamData = nil
}
c.pamCB.Delete()
}
func pamErr(h *C.pam_handle_t, e C.int) string {