aboutsummaryrefslogtreecommitdiff
path: root/pam/pam.go
diff options
context:
space:
mode:
Diffstat (limited to 'pam/pam.go')
-rw-r--r--pam/pam.go82
1 files changed, 54 insertions, 28 deletions
diff --git a/pam/pam.go b/pam/pam.go
index 0f20f30..ea1c34e 100644
--- a/pam/pam.go
+++ b/pam/pam.go
@@ -35,16 +35,14 @@ import (
"unsafe"
"github.com/google/fscrypt/security"
- "github.com/google/fscrypt/util"
)
// Handle wraps the C pam_handle_t type. This is used from within modules.
type Handle struct {
- handle *C.pam_handle_t
- status C.int
- // OrigUser is the user who invoked the PAM module (usually root)
- OrigUser *user.User
- // PamUser is the user who the PAM module is for
+ handle *C.pam_handle_t
+ status C.int
+ origPrivs *security.Privileges
+ // PamUser is the user for whom the PAM module is running.
PamUser *user.User
}
@@ -58,17 +56,12 @@ func NewHandle(pamh unsafe.Pointer) (*Handle, error) {
var pamUsername *C.char
h.status = C.pam_get_user(h.handle, &pamUsername, nil)
- if err := h.err(); err != nil {
+ if err = h.err(); err != nil {
return nil, err
}
- if h.PamUser, err = user.Lookup(C.GoString(pamUsername)); err != nil {
- return nil, err
- }
- if h.OrigUser, err = util.EffectiveUser(); err != nil {
- return nil, err
- }
- return h, nil
+ h.PamUser, err = user.Lookup(C.GoString(pamUsername))
+ return h, err
}
func (h *Handle) setData(name string, data unsafe.Pointer, cleanup C.CleanupFunc) error {
@@ -86,7 +79,7 @@ func (h *Handle) getData(name string) (unsafe.Pointer, error) {
return data, h.err()
}
-// ClearData remotes the PAM data with the specified name.
+// ClearData removes the PAM data with the specified name.
func (h *Handle) ClearData(name string) error {
return h.setData(name, unsafe.Pointer(C.CString("")), C.CleanupFunc(C.freeData))
}
@@ -99,8 +92,8 @@ func (h *Handle) SetSecret(name string, secret unsafe.Pointer) error {
}
// GetSecret returns a pointer to the C string PAM data with the specified name.
-// This a pointer directory to the data, so it shouldn't be modified. It should
-// have been previously set with SetSecret().
+// This is a pointer directly to the data, so it shouldn't be modified. It
+// should have been previously set with SetSecret().
func (h *Handle) GetSecret(name string) (unsafe.Pointer, error) {
return h.getData(name)
}
@@ -120,28 +113,54 @@ func (h *Handle) GetString(name string) (string, error) {
return C.GoString((*C.char)(data)), nil
}
-// GetItem retrieves a PAM information item. This a pointer directory to the
+// GetItem retrieves a PAM information item. This is a pointer directly to the
// data, so it shouldn't be modified.
func (h *Handle) GetItem(i Item) (unsafe.Pointer, error) {
var data unsafe.Pointer
h.status = C.pam_get_item(h.handle, C.int(i), &data)
- return data, h.err()
+ if err := h.err(); err != nil {
+ return nil, err
+ }
+ if data == nil {
+ return nil, errors.New("item not found")
+ }
+ return data, nil
+}
+
+// GetServiceName retrieves the name of the application running the PAM transaction.
+func (h *Handle) GetServiceName() string {
+ data, err := h.GetItem(Service)
+ if err != nil {
+ return "[unknown service]"
+ }
+ return C.GoString((*C.char)(data))
}
-// StartAsPamUser sets the effective privileges to that of the PAM user, and
-// configures the PAM user's keyrings to be properly linked.
+// StartAsPamUser sets the effective privileges to that of the PAM user.
func (h *Handle) StartAsPamUser() error {
- if _, err := security.UserKeyringID(h.PamUser, true); err != nil {
- log.Printf("Setting up keyrings in PAM: %v", err)
+ userPrivs, err := security.UserPrivileges(h.PamUser)
+ if err != nil {
+ return err
+ }
+ origPrivs, err := security.ProcessPrivileges()
+ if err != nil {
+ return err
}
- return security.SetThreadPrivileges(h.PamUser)
+ if err = security.SetProcessPrivileges(userPrivs); err != nil {
+ return err
+ }
+ h.origPrivs = origPrivs
+ return nil
}
// StopAsPamUser restores the original privileges that were running the
-// PAM module (this is usually root). As this error is often ignored in a defer
-// statement, any error is also logged.
+// PAM module (this is usually root).
func (h *Handle) StopAsPamUser() error {
- err := security.SetThreadPrivileges(h.OrigUser)
+ if h.origPrivs == nil {
+ return nil
+ }
+ err := security.SetProcessPrivileges(h.origPrivs)
+ h.origPrivs = nil
if err != nil {
log.Print(err)
}
@@ -156,8 +175,15 @@ func (h *Handle) err() error {
return errors.New(s)
}
+// InfoMessage sends a message to the application using pam_info().
+func (h *Handle) InfoMessage(message string) {
+ cMessage := C.CString(message)
+ defer C.free(unsafe.Pointer(cMessage))
+ C.infoMessage(h.handle, cMessage)
+}
+
// Transaction represents a wrapped pam_handle_t type created with pam_start
-// form an application.
+// from an application.
type Transaction Handle
// Start initializes a pam Transaction. End() should be called after the