aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/msteinert
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/msteinert')
-rw-r--r--vendor/github.com/msteinert/pam/LICENSE24
-rw-r--r--vendor/github.com/msteinert/pam/README.md36
-rw-r--r--vendor/github.com/msteinert/pam/transaction.c51
-rw-r--r--vendor/github.com/msteinert/pam/transaction.go319
4 files changed, 430 insertions, 0 deletions
diff --git a/vendor/github.com/msteinert/pam/LICENSE b/vendor/github.com/msteinert/pam/LICENSE
new file mode 100644
index 00000000..e3adca07
--- /dev/null
+++ b/vendor/github.com/msteinert/pam/LICENSE
@@ -0,0 +1,24 @@
+Copyright 2011, krockot
+Copyright 2015, Michael Steinert <mike.steinert@gmail.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/msteinert/pam/README.md b/vendor/github.com/msteinert/pam/README.md
new file mode 100644
index 00000000..21851ed8
--- /dev/null
+++ b/vendor/github.com/msteinert/pam/README.md
@@ -0,0 +1,36 @@
+[![Build Status](https://travis-ci.org/msteinert/pam.svg?branch=master)](https://travis-ci.org/msteinert/pam)
+[![GoDoc](https://godoc.org/github.com/msteinert/pam?status.svg)](http://godoc.org/github.com/msteinert/pam)
+[![Coverage Status](https://coveralls.io/repos/msteinert/pam/badge.svg?branch=master)](https://coveralls.io/r/msteinert/pam?branch=master)
+[![Go Report Card](http://goreportcard.com/badge/msteinert/pam)](http://goreportcard.com/report/msteinert/pam)
+
+# Go PAM
+
+This is a Go wrapper for the PAM application API. There's not much
+else to be said. PAM is a simple API and now it's available for use in Go
+applications.
+
+There's an example of a "fake login" program in the examples directory.
+Look at the pam module's [godocs][1] for details about the Go API, or refer
+to the official [PAM documentation][2].
+
+## Testing
+
+To run the full suite, the tests must be run as the root user. To setup your
+system for testing, create a user named "test" with the password "secret". For
+example:
+
+```
+$ sudo useradd test \
+ -d /tmp/test \
+ -p '$1$Qd8H95T5$RYSZQeoFbEB.gS19zS99A0' \
+ -s /bin/false
+```
+
+Then execute the tests:
+
+```
+$ sudo GOPATH=$GOPATH $(which go) test -v
+```
+
+[1]: http://godoc.org/github.com/msteinert/pam
+[2]: http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_ADG.html
diff --git a/vendor/github.com/msteinert/pam/transaction.c b/vendor/github.com/msteinert/pam/transaction.c
new file mode 100644
index 00000000..4ff649b1
--- /dev/null
+++ b/vendor/github.com/msteinert/pam/transaction.c
@@ -0,0 +1,51 @@
+#include "_cgo_export.h"
+#include <security/pam_appl.h>
+#include <string.h>
+
+int cb_pam_conv(
+ int num_msg,
+ const struct pam_message **msg,
+ struct pam_response **resp,
+ void *appdata_ptr)
+{
+ *resp = calloc(num_msg, sizeof **resp);
+ if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG) {
+ return PAM_CONV_ERR;
+ }
+ if (!*resp) {
+ return PAM_BUF_ERR;
+ }
+ for (size_t i = 0; i < num_msg; ++i) {
+ struct cbPAMConv_return result = cbPAMConv(
+ msg[i]->msg_style,
+ (char *)msg[i]->msg,
+ appdata_ptr);
+ if (result.r1 != PAM_SUCCESS) {
+ goto error;
+ }
+ (*resp)[i].resp = result.r0;
+ }
+ return PAM_SUCCESS;
+error:
+ for (size_t i = 0; i < num_msg; ++i) {
+ if ((*resp)[i].resp) {
+ memset((*resp)[i].resp, 0, strlen((*resp)[i].resp));
+ free((*resp)[i].resp);
+ }
+ }
+ memset(*resp, 0, num_msg * sizeof *resp);
+ free(*resp);
+ *resp = NULL;
+ return PAM_CONV_ERR;
+}
+
+struct pam_conv *make_pam_conv(void *appdata_ptr)
+{
+ struct pam_conv* conv = malloc(sizeof *conv);
+ if (!conv) {
+ return NULL;
+ }
+ conv->conv = cb_pam_conv;
+ conv->appdata_ptr = appdata_ptr;
+ return conv;
+}
diff --git a/vendor/github.com/msteinert/pam/transaction.go b/vendor/github.com/msteinert/pam/transaction.go
new file mode 100644
index 00000000..360d89a6
--- /dev/null
+++ b/vendor/github.com/msteinert/pam/transaction.go
@@ -0,0 +1,319 @@
+package pam
+
+//#include <security/pam_appl.h>
+//#include <stdlib.h>
+//#cgo CFLAGS: -Wall -std=c99
+//#cgo LDFLAGS: -lpam
+//struct pam_conv *make_pam_conv(void *);
+import "C"
+
+import (
+ "runtime"
+ "strings"
+ "unsafe"
+)
+
+// Style is the type of message that the conversation handler should display.
+type Style int
+
+// Coversation handler style types.
+const (
+ // PromptEchoOff indicates the conversation handler should obtain a
+ // string without echoing any text.
+ PromptEchoOff Style = C.PAM_PROMPT_ECHO_OFF
+ // PromptEchoOn indicates the conversation handler should obtain a
+ // string while echoing text.
+ PromptEchoOn = C.PAM_PROMPT_ECHO_ON
+ // ErrorMsg indicates the conversation handler should display an
+ // error message.
+ ErrorMsg = C.PAM_ERROR_MSG
+ // TextInfo indicates the conversation handler should display some
+ // text.
+ TextInfo = C.PAM_TEXT_INFO
+)
+
+// ConversationHandler is an interface for objects that can be used as
+// conversation callbacks during PAM authentication.
+type ConversationHandler interface {
+ // RespondPAM receives a message style and a message string. If the
+ // message Style is PromptEchoOff or PromptEchoOn then the function
+ // should return a response string.
+ RespondPAM(Style, string) (string, error)
+}
+
+// ConversationFunc is an adapter to allow the use of ordinary functions as
+// conversation callbacks.
+type ConversationFunc func(Style, string) (string, error)
+
+// RespondPAM is a conversation callback adapter.
+func (f ConversationFunc) RespondPAM(s Style, msg string) (string, error) {
+ return f(s, msg)
+}
+
+// Internal conversation structure
+type conversation struct {
+ handler ConversationHandler
+ conv *C.struct_pam_conv
+}
+
+// Constructs a new conversation object with a given handler and a newly
+// allocated pam_conv struct that uses this object as its appdata_ptr.
+func newConversation(handler ConversationHandler) (*conversation, C.int) {
+ c := &conversation{}
+ c.handler = handler
+ c.conv = C.make_pam_conv(unsafe.Pointer(c))
+ if c.conv == nil {
+ return nil, C.PAM_BUF_ERR
+ }
+ return c, C.PAM_SUCCESS
+}
+
+// Go-side function for processing a single conversational message. Ultimately
+// this calls the associated ConversationHandler's ResponsePAM callback with data
+// coming in from a C-side call.
+//export cbPAMConv
+func cbPAMConv(s C.int, msg *C.char, appdata unsafe.Pointer) (*C.char, C.int) {
+ c := (*conversation)(appdata)
+ r, err := c.handler.RespondPAM(Style(s), C.GoString(msg))
+ if err != nil {
+ return nil, C.PAM_CONV_ERR
+ }
+ return C.CString(r), C.PAM_SUCCESS
+}
+
+// Transaction is the application's handle for a PAM transaction.
+type Transaction struct {
+ handle *C.pam_handle_t
+ conv *conversation
+ status C.int
+}
+
+// Finalize a PAM transaction.
+func transactionFinalizer(t *Transaction) {
+ C.pam_end(t.handle, t.status)
+ C.free(unsafe.Pointer(t.conv.conv))
+}
+
+// Start initiates a new PAM transaction. Service is treated identically to
+// how pam_start treats it internally.
+//
+// All application calls to PAM begin with Start (or StartFunc). The returned
+// transaction provides an interface to the remainder of the API.
+func Start(service, user string, handler ConversationHandler) (*Transaction, error) {
+ t := &Transaction{}
+ t.conv, t.status = newConversation(handler)
+ if t.status != C.PAM_SUCCESS {
+ return nil, t
+ }
+ s := C.CString(service)
+ defer C.free(unsafe.Pointer(s))
+ var u *C.char
+ if len(user) != 0 {
+ u = C.CString(user)
+ defer C.free(unsafe.Pointer(u))
+ }
+ t.status = C.pam_start(s, u, t.conv.conv, &t.handle)
+ if t.status != C.PAM_SUCCESS {
+ C.free(unsafe.Pointer(t.conv.conv))
+ return nil, t
+ }
+ runtime.SetFinalizer(t, transactionFinalizer)
+ return t, nil
+}
+
+// StartFunc registers the handler func as a conversation handler.
+func StartFunc(service, user string, handler func(Style, string) (string, error)) (*Transaction, error) {
+ return Start(service, user, ConversationFunc(handler))
+}
+
+func (t *Transaction) Error() string {
+ return C.GoString(C.pam_strerror(t.handle, C.int(t.status)))
+}
+
+// Item is a an PAM information type.
+type Item int
+
+// PAM Item types.
+const (
+ // Service is the name which identifies the PAM stack.
+ Service Item = C.PAM_SERVICE
+ // User identifies the username identity used by a service.
+ User = C.PAM_USER
+ // Tty is the terminal name.
+ Tty = C.PAM_TTY
+ // Rhost is the requesting host name.
+ Rhost = C.PAM_RHOST
+ // Authtok is the currently active authentication token.
+ Authtok = C.PAM_AUTHTOK
+ // Oldauthtok is the old authentication token.
+ Oldauthtok = C.PAM_OLDAUTHTOK
+ // Ruser is the requesting user name.
+ Ruser = C.PAM_RUSER
+ // UserPrompt is the string use to prompt for a username.
+ UserPrompt = C.PAM_USER_PROMPT
+)
+
+// SetItem sets a PAM information item.
+func (t *Transaction) SetItem(i Item, item string) error {
+ cs := unsafe.Pointer(C.CString(item))
+ defer C.free(cs)
+ t.status = C.pam_set_item(t.handle, C.int(i), cs)
+ if t.status != C.PAM_SUCCESS {
+ return t
+ }
+ return nil
+}
+
+// GetItem retrieves a PAM information item.
+func (t *Transaction) GetItem(i Item) (string, error) {
+ var s unsafe.Pointer
+ t.status = C.pam_get_item(t.handle, C.int(i), &s)
+ if t.status != C.PAM_SUCCESS {
+ return "", t
+ }
+ return C.GoString((*C.char)(s)), nil
+}
+
+// Flags are inputs to various PAM functions than be combined with a bitwise
+// or. Refer to the official PAM documentation for which flags are accepted
+// by which functions.
+type Flags int
+
+// PAM Flag types.
+const (
+ // Silent indicates that no messages should be emitted.
+ Silent Flags = C.PAM_SILENT
+ // DisallowNullAuthtok indicates that authorization should fail
+ // if the user does not have a registered authentication token.
+ DisallowNullAuthtok = C.PAM_DISALLOW_NULL_AUTHTOK
+ // EstablishCred indicates that credentials should be established
+ // for the user.
+ EstablishCred = C.PAM_ESTABLISH_CRED
+ // DeleteCred inidicates that credentials should be deleted.
+ DeleteCred = C.PAM_DELETE_CRED
+ // ReinitializeCred indicates that credentials should be fully
+ // reinitialized.
+ ReinitializeCred = C.PAM_REINITIALIZE_CRED
+ // RefreshCred indicates that the lifetime of existing credentials
+ // should be extended.
+ RefreshCred = C.PAM_REFRESH_CRED
+ // ChangeExpiredAuthtok indicates that the authentication token
+ // should be changed if it has expired.
+ ChangeExpiredAuthtok = C.PAM_CHANGE_EXPIRED_AUTHTOK
+)
+
+// Authenticate is used to authenticate the user.
+//
+// Valid flags: Silent, DisallowNullAuthtok
+func (t *Transaction) Authenticate(f Flags) error {
+ t.status = C.pam_authenticate(t.handle, C.int(f))
+ if t.status != C.PAM_SUCCESS {
+ return t
+ }
+ return nil
+}
+
+// SetCred is used to establish, maintain and delete the credentials of a
+// user.
+//
+// Valid flags: EstablishCred, DeleteCred, ReinitializeCred, RefreshCred
+func (t *Transaction) SetCred(f Flags) error {
+ t.status = C.pam_setcred(t.handle, C.int(f))
+ if t.status != C.PAM_SUCCESS {
+ return t
+ }
+ return nil
+}
+
+// AcctMgmt is used to determine if the user's account is valid.
+//
+// Valid flags: Silent, DisallowNullAuthtok
+func (t *Transaction) AcctMgmt(f Flags) error {
+ t.status = C.pam_acct_mgmt(t.handle, C.int(f))
+ if t.status != C.PAM_SUCCESS {
+ return t
+ }
+ return nil
+}
+
+// ChangeAuthTok is used to change the authentication token.
+//
+// Valid flags: Silent, ChangeExpiredAuthtok
+func (t *Transaction) ChangeAuthTok(f Flags) error {
+ t.status = C.pam_chauthtok(t.handle, C.int(f))
+ if t.status != C.PAM_SUCCESS {
+ return t
+ }
+ return nil
+}
+
+// OpenSession sets up a user session for an authenticated user.
+//
+// Valid flags: Slient
+func (t *Transaction) OpenSession(f Flags) error {
+ t.status = C.pam_open_session(t.handle, C.int(f))
+ if t.status != C.PAM_SUCCESS {
+ return t
+ }
+ return nil
+}
+
+// CloseSession closes a previously opened session.
+//
+// Valid flags: Silent
+func (t *Transaction) CloseSession(f Flags) error {
+ t.status = C.pam_close_session(t.handle, C.int(f))
+ if t.status != C.PAM_SUCCESS {
+ return t
+ }
+ return nil
+}
+
+// PutEnv adds or changes the value of PAM environment variables.
+//
+// NAME=value will set a variable to a value.
+// NAME= will set a variable to an empty value.
+// NAME (without an "=") will delete a variable.
+func (t *Transaction) PutEnv(nameval string) error {
+ cs := C.CString(nameval)
+ defer C.free(unsafe.Pointer(cs))
+ t.status = C.pam_putenv(t.handle, cs)
+ if t.status != C.PAM_SUCCESS {
+ return t
+ }
+ return nil
+}
+
+// GetEnv is used to retrieve a PAM environment variable.
+func (t *Transaction) GetEnv(name string) string {
+ cs := C.CString(name)
+ defer C.free(unsafe.Pointer(cs))
+ value := C.pam_getenv(t.handle, cs)
+ if value == nil {
+ return ""
+ }
+ return C.GoString(value)
+}
+
+func next(p **C.char) **C.char {
+ return (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(p)))
+}
+
+// GetEnvList returns a copy of the PAM environment as a map.
+func (t *Transaction) GetEnvList() (map[string]string, error) {
+ env := make(map[string]string)
+ p := C.pam_getenvlist(t.handle)
+ if p == nil {
+ t.status = C.PAM_BUF_ERR
+ return nil, t
+ }
+ for q := p; *q != nil; q = next(q) {
+ chunks := strings.SplitN(C.GoString(*q), "=", 2)
+ if len(chunks) == 2 {
+ env[chunks[0]] = chunks[1]
+ }
+ C.free(unsafe.Pointer(*q))
+ }
+ C.free(unsafe.Pointer(p))
+ return env, nil
+}