summaryrefslogtreecommitdiff
path: root/libpamc
diff options
context:
space:
mode:
Diffstat (limited to 'libpamc')
-rw-r--r--libpamc/.cvsignore3
-rw-r--r--libpamc/License42
-rw-r--r--libpamc/Makefile107
-rw-r--r--libpamc/include/security/pam_client.h197
-rw-r--r--libpamc/libpamc.h63
-rw-r--r--libpamc/pamc_client.c189
-rw-r--r--libpamc/pamc_converse.c211
-rw-r--r--libpamc/pamc_load.c477
-rwxr-xr-xlibpamc/test/agents/secret@here308
-rw-r--r--libpamc/test/modules/Makefile9
-rw-r--r--libpamc/test/modules/pam_secret.c670
-rw-r--r--libpamc/test/regress/Makefile7
-rwxr-xr-xlibpamc/test/regress/run_test.sh6
-rw-r--r--libpamc/test/regress/test.libpamc.c342
-rwxr-xr-xlibpamc/test/regress/test.secret@here152
15 files changed, 0 insertions, 2783 deletions
diff --git a/libpamc/.cvsignore b/libpamc/.cvsignore
deleted file mode 100644
index ce01b11d..00000000
--- a/libpamc/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-libpamc.so*
-static
-dynamic
diff --git a/libpamc/License b/libpamc/License
deleted file mode 100644
index 90106954..00000000
--- a/libpamc/License
+++ /dev/null
@@ -1,42 +0,0 @@
-Unless otherwise *explicitly* stated the following text describes the
-licensed conditions under which the contents of this libpamc release
-may be distributed:
-
--------------------------------------------------------------------------
-Redistribution and use in source and binary forms of libpamc,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-1. Redistributions of source code must retain any existing copyright
- notice, and this entire permission notice in its entirety,
- including the disclaimer of warranties.
-
-2. Redistributions in binary form must reproduce all prior and current
- copyright notices, this list of conditions, and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
-
-3. The name of any author may not be used to endorse or promote
- products derived from this software without their specific prior
- written permission.
-
-ALTERNATIVELY, this product may be distributed under the terms of the
-GNU Library General Public License (LGPL), in which case the
-provisions of the GNU LGPL are required INSTEAD OF the above
-restrictions. (This clause is necessary due to a potential conflict
-between the GNU LGPL and the restrictions contained in a BSD-style
-copyright.)
-
-THIS SOFTWARE IS PROVIDED ``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 AUTHOR(S) 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/libpamc/Makefile b/libpamc/Makefile
deleted file mode 100644
index 45d42051..00000000
--- a/libpamc/Makefile
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# $Id$
-#
-
-# lots of debugging information goes to /tmp/pam-debug.log
-#MOREFLAGS += -D"DEBUG"
-
-include ../Make.Rules
-
-ifeq ($(DEBUG_REL),yes)
- LIBNAME=libpamcd
-else
- LIBNAME=libpamc
-endif
-VERSION=.$(MAJOR_REL)
-MODIFICATION=.$(MINOR_REL)
-
-CFLAGS += $(MOREFLAGS) $(DYNAMIC) $(STATIC)
-
-# dynamic library names
-
-LIBNAMED = $(LIBNAME).$(DYNTYPE)
-LIBNAMEDNAME = $(LIBNAMED)$(VERSION)
-LIBNAMEDFULL = $(LIBNAMEDNAME)$(MODIFICATION)
-
-# static library name
-
-LIBNAMEDSTATIC = $(LIBNAME).a
-
-LIBOBJECTS = pamc_client.o pamc_converse.o pamc_load.o
-
-ifeq ($(DYNAMIC_LIBPAM),yes)
-DLIBOBJECTS = $(addprefix dynamic/,$(LIBOBJECTS))
-endif
-
-ifeq ($(STATIC_LIBPAM),yes)
-SLIBOBJECTS = $(addprefix static/,$(LIBOBJECTS))
-endif
-
-# ---------------------------------------------
-## rules
-
-all: dirs $(LIBNAMED) $(LIBNAMEDSTATIC)
-
-dirs:
-ifeq ($(DYNAMIC_LIBPAM),yes)
- $(MKDIR) dynamic
-endif
-ifeq ($(STATIC_LIBPAM),yes)
- $(MKDIR) static
-endif
-
-dynamic/%.o : %.c
- $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
-
-static/%.o : %.c
- $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
-
-$(LIBNAMED): $(DLIBOBJECTS)
-ifeq ($(DYNAMIC_LIBPAM),yes)
- ifeq ($(USESONAME),yes)
- $(LD_L) $(SOSWITCH) $(LIBNAMEDNAME) -o $@ $(DLIBOBJECTS) $(MODULES) $(LINKLIBS)
- else
- $(LD_L) -o $@ $(DLIBOBJECTS) $(MODULES)
- endif
- ifeq ($(NEEDSONAME),yes)
- rm -f $(LIBNAMEDFULL)
- ln -s $(LIBNAMED) $(LIBNAMEDFULL)
- rm -f $(LIBNAMEDNAME)
- ln -s $(LIBNAMED) $(LIBNAMEDNAME)
- endif
-endif
-
-$(LIBNAMEDSTATIC): $(SLIBOBJECTS)
-ifeq ($(STATIC_LIBPAM),yes)
- $(AR) rc $@ $(SLIBOBJECTS) $(MODULES)
- $(RANLIB) $@
-endif
-
-install: all
- $(MKDIR) $(FAKEROOT)$(INCLUDED)
- $(INSTALL) -m 644 include/security/pam_client.h $(FAKEROOT)$(INCLUDED)
-ifeq ($(DYNAMIC_LIBPAM),yes)
- $(MKDIR) $(FAKEROOT)$(libdir)
- $(INSTALL) -m $(SHLIBMODE) $(LIBNAMED) $(FAKEROOT)$(libdir)/$(LIBNAMEDFULL)
- $(LDCONFIG)
- ifneq ($(DYNTYPE),"sl")
- ( cd $(FAKEROOT)$(libdir) ; rm -f $(LIBNAMED) ; ln -s $(LIBNAMEDNAME) $(LIBNAMED) )
- endif
-endif
-ifeq ($(STATIC_LIBPAM),yes)
- $(INSTALL) -m 644 $(LIBNAMEDSTATIC) $(FAKEROOT)$(libdir)
-endif
-
-remove:
- rm -f $(FAKEROOT)$(INCLUDED)/pam_client.h
- rm -f $(FAKEROOT)$(libdir)/$(LIBNAMEDFULL)
- rm -f $(FAKEROOT)$(libdir)/$(LIBNAMED)
- $(LDCONFIG)
- rm -f $(FAKEROOT)$(libdir)/$(LIBNAMEDSTATIC)
-
-clean:
- rm -f a.out core *~ static/*.o dynamic/*.o
- rm -f *.a *.out *.o *.so ./include/security/*~
- if [ -d dynamic ]; then rmdir dynamic ; fi
- if [ -d static ]; then rmdir static ; fi
-
diff --git a/libpamc/include/security/pam_client.h b/libpamc/include/security/pam_client.h
deleted file mode 100644
index 2afddd77..00000000
--- a/libpamc/include/security/pam_client.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (c) 1999 Andrew G. Morgan <morgan@linux.kernel.org>
- *
- * This header file provides the prototypes for the PAM client API
- */
-
-#ifndef PAM_CLIENT_H
-#define PAM_CLIENT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* def __cplusplus */
-
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-
-/* opaque agent handling structure */
-
-typedef struct pamc_handle_s *pamc_handle_t;
-
-/* binary prompt structure pointer */
-#ifndef __u32
-# define __u32 unsigned int
-#endif
-#ifndef __u8
-# define __u8 unsigned char
-#endif
-typedef struct { __u32 length; __u8 control; } *pamc_bp_t;
-
-/*
- * functions provided by libpamc
- */
-
-/*
- * Initialize the agent abstraction library
- */
-
-pamc_handle_t pamc_start(void);
-
-/*
- * Terminate the authentication process
- */
-
-int pamc_end(pamc_handle_t *pch);
-
-/*
- * force the loading of a specified agent
- */
-
-int pamc_load(pamc_handle_t pch, const char *agent_id);
-
-/*
- * Single conversation interface for binary prompts
- */
-
-int pamc_converse(pamc_handle_t pch, pamc_bp_t *prompt_p);
-
-/*
- * disable an agent
- */
-
-int pamc_disable(pamc_handle_t pch, const char *agent_id);
-
-/*
- * obtain a list of available agents
- */
-
-char **pamc_list_agents(pamc_handle_t pch);
-
-/*
- * PAM_BP_ MACROS for creating, destroying and manipulating binary prompts
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#ifndef PAM_BP_ASSERT
-# define PAM_BP_ASSERT(x) do { printf(__FILE__ "(%d): %s\n", \
- __LINE__, x) ; exit(1); } while (0)
-#endif /* PAM_BP_ASSERT */
-
-#ifndef PAM_BP_CALLOC
-# define PAM_BP_CALLOC calloc
-#endif /* PAM_BP_CALLOC */
-
-#ifndef PAM_BP_FREE
-# define PAM_BP_FREE free
-#endif /* PAM_BP_FREE */
-
-#define __PAM_BP_WOCTET(x,y) (*((y) + (__u8 *)(x)))
-#define __PAM_BP_ROCTET(x,y) (*((y) + (const __u8 *)(x)))
-
-#define PAM_BP_MIN_SIZE (sizeof(__u32) + sizeof(__u8))
-#define PAM_BP_MAX_LENGTH 0x20000 /* an advisory limit */
-#define PAM_BP_WCONTROL(x) (__PAM_BP_WOCTET(x,4))
-#define PAM_BP_RCONTROL(x) (__PAM_BP_ROCTET(x,4))
-#define PAM_BP_SIZE(x) ((__PAM_BP_ROCTET(x,0)<<24)+ \
- (__PAM_BP_ROCTET(x,1)<<16)+ \
- (__PAM_BP_ROCTET(x,2)<< 8)+ \
- (__PAM_BP_ROCTET(x,3) ))
-#define PAM_BP_LENGTH(x) (PAM_BP_SIZE(x) - PAM_BP_MIN_SIZE)
-#define PAM_BP_WDATA(x) (PAM_BP_MIN_SIZE + (__u8 *) (x))
-#define PAM_BP_RDATA(x) (PAM_BP_MIN_SIZE + (const __u8 *) (x))
-
-/* Note, this macro always '\0' terminates renewed packets */
-
-#define PAM_BP_RENEW(old_p, cntrl, data_length) \
-do { \
- if (old_p) { \
- if (*(old_p)) { \
- __u32 __size; \
- __size = PAM_BP_SIZE(*(old_p)); \
- memset(*(old_p), 0, __size); \
- PAM_BP_FREE(*(old_p)); \
- } \
- if (cntrl) { \
- __u32 __size; \
- \
- __size = PAM_BP_MIN_SIZE + data_length; \
- if ((*(old_p) = PAM_BP_CALLOC(1, 1+__size))) { \
- __PAM_BP_WOCTET(*(old_p), 3) = __size & 0xFF; \
- __PAM_BP_WOCTET(*(old_p), 2) = (__size>>=8) & 0xFF; \
- __PAM_BP_WOCTET(*(old_p), 1) = (__size>>=8) & 0xFF; \
- __PAM_BP_WOCTET(*(old_p), 0) = (__size>>=8) & 0xFF; \
- (*(old_p))->control = cntrl; \
- } else { \
- PAM_BP_ASSERT("out of memory for binary prompt"); \
- } \
- } else { \
- *old_p = NULL; \
- } \
- } else { \
- PAM_BP_ASSERT("programming error, invalid binary prompt pointer"); \
- } \
-} while (0)
-
-#define PAM_BP_FILL(prmpt, offset, length, data) \
-do { \
- size_t bp_length; \
- __u8 *prompt = (__u8 *) (prmpt); \
- bp_length = PAM_BP_LENGTH(prompt); \
- if (bp_length < ((length)+(offset))) { \
- PAM_BP_ASSERT("attempt to write over end of prompt"); \
- } \
- memcpy((offset) + PAM_BP_WDATA(prompt), (data), (length)); \
-} while (0)
-
-#define PAM_BP_EXTRACT(prmpt, offset, length, data) \
-do { \
- size_t __bp_length; \
- const __u8 *__prompt = (const __u8 *) (prmpt); \
- __bp_length = PAM_BP_LENGTH(__prompt); \
- if (((offset) < 0) || (__bp_length < ((length)+(offset))) \
- || ((length) < 0)) { \
- PAM_BP_ASSERT("invalid extraction from prompt"); \
- } \
- memcpy((data), (offset) + PAM_BP_RDATA(__prompt), (length)); \
-} while (0)
-
-
-/* Control types */
-
-#define PAM_BPC_FALSE 0
-#define PAM_BPC_TRUE 1
-
-#define PAM_BPC_OK 0x01 /* continuation packet */
-#define PAM_BPC_SELECT 0x02 /* initialization packet */
-#define PAM_BPC_DONE 0x03 /* termination packet */
-#define PAM_BPC_FAIL 0x04 /* unable to execute */
-
-/* The following control characters are only legal for echanges
- between an agent and a client (it is the responsibility of the
- client to enforce this rule in the face of a rogue server): */
-
-#define PAM_BPC_GETENV 0x41 /* obtain client env.var */
-#define PAM_BPC_PUTENV 0x42 /* set client env.var */
-#define PAM_BPC_TEXT 0x43 /* display message */
-#define PAM_BPC_ERROR 0x44 /* display error message */
-#define PAM_BPC_PROMPT 0x45 /* echo'd text prompt */
-#define PAM_BPC_PASS 0x46 /* non-echo'd text prompt*/
-
-/* quick check for prompts that are legal for the client (by
- implication the server too) to send to libpamc */
-
-#define PAM_BPC_FOR_CLIENT(/* pamc_bp_t */ prompt) \
- (((prompt)->control <= PAM_BPC_FAIL && (prompt)->control >= PAM_BPC_OK) \
- ? PAM_BPC_TRUE:PAM_BPC_FALSE)
-
-#ifdef __cplusplus
-}
-#endif /* def __cplusplus */
-
-#endif /* PAM_CLIENT_H */
diff --git a/libpamc/libpamc.h b/libpamc/libpamc.h
deleted file mode 100644
index 93c833c6..00000000
--- a/libpamc/libpamc.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (c) Andrew G. Morgan <morgan@ftp.kernel.org>
- *
- */
-
-#ifndef LIBPAMC_H
-#define LIBPAMC_H
-
-#include <security/pam_client.h>
-#include <security/_pam_macros.h>
-
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/wait.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-
-#define _PAMC_DEFAULT_TOP_FD 10
-
-struct pamc_handle_s {
- struct pamc_agent_s *current;
- struct pamc_agent_s *chain;
- struct pamc_blocked_s *blocked_agents;
- int max_path;
- char **agent_paths;
- int combined_status;
- int highest_fd_to_close;
-};
-
-typedef struct pamc_blocked_s {
- char *id; /* <NUL> terminated */
- struct pamc_blocked_s *next;
-} pamc_blocked_t;
-
-typedef struct pamc_agent_s {
- char *id;
- int id_length;
- struct pamc_agent_s *next;
- int writer; /* write to agent */
- int reader; /* read from agent */
- pid_t pid; /* agent process id */
-} pamc_agent_t;
-
-/* used to build a tree of unique, sorted agent ids */
-
-typedef struct pamc_id_node {
- struct pamc_id_node *left, *right;
- int child_count;
- char *agent_id;
-} pamc_id_node_t;
-
-/* internal function */
-int __pamc_valid_agent_id(int id_length, const char *id);
-
-#define PAMC_SYSTEM_AGENT_PATH "/lib/pamc:/usr/lib/pamc"
-#define PAMC_SYSTEM_AGENT_SEPARATOR ':'
-
-#endif /* LIBPAMC_H */
diff --git a/libpamc/pamc_client.c b/libpamc/pamc_client.c
deleted file mode 100644
index 9d2bc671..00000000
--- a/libpamc/pamc_client.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (c) Andrew G. Morgan <morgan@ftp.kernel.org>
- *
- * pamc_start and pamc_end
- */
-
-#include "libpamc.h"
-
-/*
- * liberate path list
- */
-
-static void __pamc_delete_path_list(pamc_handle_t pch)
-{
- int i;
-
- for (i=0; pch->agent_paths[i]; ++i) {
- free(pch->agent_paths[i]);
- pch->agent_paths[i] = NULL;
- }
-
- free(pch->agent_paths);
- pch->agent_paths = NULL;
-}
-
-/*
- * open the pamc library
- */
-
-pamc_handle_t pamc_start(void)
-{
- int i, count, last, this;
- const char *default_path;
- pamc_handle_t pch;
-
- pch = calloc(1, sizeof(struct pamc_handle_s));
- if (pch == NULL) {
- D(("no memory for *pch"));
- return NULL;
- }
-
- pch->highest_fd_to_close = _PAMC_DEFAULT_TOP_FD;
-
- default_path = getenv("PAMC_AGENT_PATH");
- if (default_path == NULL) {
- default_path = PAMC_SYSTEM_AGENT_PATH;
- }
-
- /* number of individual paths */
- for (count=1, i=0; default_path[i]; ++i) {
- if (default_path[i] == PAMC_SYSTEM_AGENT_SEPARATOR) {
- ++count;
- }
- }
-
- pch->agent_paths = calloc(count+1, sizeof(char *));
- if (pch->agent_paths == NULL) {
- D(("no memory for path list"));
- goto drop_pch;
- }
-
- this = last = i = 0;
- while ( default_path[i] || (i != last) ) {
- if ( default_path[i] == PAMC_SYSTEM_AGENT_SEPARATOR
- || !default_path[i] ) {
- int length;
-
- pch->agent_paths[this] = malloc(length = 1+i-last);
-
- if (pch->agent_paths[this] == NULL) {
- D(("no memory for next path"));
- goto drop_list;
- }
-
- memcpy(pch->agent_paths[this], default_path + last, i-last);
- pch->agent_paths[this][i-last] = '\0';
- if (length > pch->max_path) {
- pch->max_path = length;
- }
-
- if (++this == count) {
- break;
- }
-
- last = ++i;
- } else {
- ++i;
- }
- }
-
- return pch;
-
-drop_list:
- __pamc_delete_path_list(pch);
-
-drop_pch:
- free(pch);
-
- return NULL;
-}
-
-/*
- * shutdown each of the loaded agents and
- */
-
-static int __pamc_shutdown_agents(pamc_handle_t pch)
-{
- int retval = PAM_BPC_TRUE;
-
- D(("called"));
-
- while (pch->chain) {
- pid_t pid;
- int status;
- pamc_agent_t *this;
-
- this = pch->chain;
- D(("cleaning up agent %p", this));
- pch->chain = pch->chain->next;
- this->next = NULL;
- D(("cleaning up agent: %s", this->id));
-
- /* close off contact with agent and wait for it to shutdown */
-
- close(this->writer);
- this->writer = -1;
- close(this->reader);
- this->reader = -1;
-
- pid = waitpid(this->pid, &status, 0);
- if (pid == this->pid) {
-
- D(("is exit:%d, exit val:%d",
- WIFEXITED(status), WEXITSTATUS(status)));
-
- if (!(WIFEXITED(status) && (WEXITSTATUS(status) == 0))) {
- retval = PAM_BPC_FALSE;
- }
- } else {
- D(("problem shutting down agent (%s): pid(%d) != waitpid(%d)!?",
- this->id, this->pid, pid));
- retval = PAM_BPC_FALSE;
- }
- pid = this->pid = 0;
-
- memset(this->id, 0, this->id_length);
- free(this->id);
- this->id = NULL;
- this->id_length = 0;
-
- free(this);
- this = NULL;
- }
-
- return retval;
-}
-
-/*
- * close the pamc library
- */
-
-int pamc_end(pamc_handle_t *pch_p)
-{
- int retval;
-
- if (pch_p == NULL) {
- D(("called with no pch_p"));
- return PAM_BPC_FALSE;
- }
-
- if (*pch_p == NULL) {
- D(("called with no *pch_p"));
- return PAM_BPC_FALSE;
- }
-
- D(("removing path_list"));
- __pamc_delete_path_list(*pch_p);
-
- D(("shutting down agents"));
- retval = __pamc_shutdown_agents(*pch_p);
-
- D(("freeing *pch_p"));
- free(*pch_p);
- *pch_p = NULL;
-
- return retval;
-}
diff --git a/libpamc/pamc_converse.c b/libpamc/pamc_converse.c
deleted file mode 100644
index 540a7d86..00000000
--- a/libpamc/pamc_converse.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (c) Andrew G. Morgan <morgan@ftp.kernel.org>
- *
- * pamc_converse
- */
-
-#include "libpamc.h"
-
-/*
- * select agent
- */
-
-static int __pamc_select_agent(pamc_handle_t pch, char *agent_id)
-{
- pamc_agent_t *agent;
-
- for (agent = pch->chain; agent; agent = agent->next) {
- if (!strcmp(agent->id, agent_id)) {
- pch->current = agent;
- return PAM_BPC_TRUE;
- }
- }
-
- D(("failed to locate agent"));
- pch->current = NULL;
- return PAM_BPC_FALSE;
-}
-
-/*
- * pass a binary prompt to the active agent and wait for a reply prompt
- */
-
-int pamc_converse(pamc_handle_t pch, pamc_bp_t *prompt_p)
-{
- __u32 size, offset=0;
- __u8 control, raw[PAM_BP_MIN_SIZE];
-
- D(("called"));
-
- if (pch == NULL) {
- D(("null pch"));
- goto pamc_converse_failure;
- }
-
- if (prompt_p == NULL) {
- D(("null prompt_p"));
- goto pamc_converse_failure;
- }
-
- if (*prompt_p == NULL) {
- D(("null *prompt_p"));
- goto pamc_converse_failure;
- }
-
- /* from here on, failures are interoperability problems.. */
-
- size = PAM_BP_SIZE(*prompt_p);
- if (size < PAM_BP_MIN_SIZE) {
- D(("problem with size being too short (%u)", size));
- goto pamc_unknown_prompt;
- }
-
- if (PAM_BPC_FOR_CLIENT(*prompt_p) != PAM_BPC_TRUE) {
- D(("*prompt_p is not legal for the client to use"));
- goto pamc_unknown_prompt;
- }
-
- /* do we need to select the agent? */
- if ((*prompt_p)->control == PAM_BPC_SELECT) {
- char *rawh;
- int i, retval;
-
- D(("selecting a specified agent"));
-
- rawh = (char *) *prompt_p;
- for (i = PAM_BP_MIN_SIZE; i<size; ++i) {
- if (rawh[i] == '/') {
- break;
- }
- }
-
- if ( (i >= size)
- || !__pamc_valid_agent_id(i-PAM_BP_MIN_SIZE,
- rawh + PAM_BP_MIN_SIZE) ) {
- goto pamc_unknown_prompt;
- }
-
- rawh[i] = '\0';
- retval = pamc_load(pch, PAM_BP_MIN_SIZE + rawh);
- if (retval == PAM_BPC_TRUE) {
- retval = __pamc_select_agent(pch, PAM_BP_MIN_SIZE + rawh);
- }
- rawh[i] = '/';
-
- if (retval != PAM_BPC_TRUE) {
- goto pamc_unknown_prompt;
- }
-
- D(("agent is loaded"));
- }
-
- if (pch->current == NULL) {
- D(("unable to address agent"));
- goto pamc_unknown_prompt;
- }
-
- /* pump all of the prompt into the agent */
- do {
- int rval = write(pch->current->writer,
- offset + (const __u8 *) (*prompt_p),
- size - offset);
- if (rval == -1) {
- switch (errno) {
- case EINTR:
- break;
- default:
- D(("problem writing to agent: %s", strerror(errno)));
- goto pamc_unknown_prompt;
- }
- } else {
- offset += rval;
- }
- } while (offset < size);
-
- D(("whole prompt sent to agent"));
-
- /* read size and control for response prompt */
-
- offset = 0;
- memset(raw, 0, sizeof(raw));
- do {
- int rval;
-
- rval = read(pch->current->reader, raw + offset,
- PAM_BP_MIN_SIZE - offset);
-
- if (rval == -1) {
- switch (errno) {
- case EINTR:
- break;
- default:
- D(("problem reading from agent: %s", strerror(errno)));
- goto pamc_unknown_prompt;
- }
- } else if (rval) {
- offset += rval;
- } else {
- D(("agent has closed its output pipe - nothing more to read"));
- goto pamc_converse_failure;
- }
- } while (offset < PAM_BP_MIN_SIZE);
-
- /* construct the whole reply prompt */
-
- size = PAM_BP_SIZE(raw);
- control = PAM_BP_RCONTROL(raw);
- memset(raw, 0, sizeof(raw));
-
- D(("agent replied with prompt of size %d and control %u",
- size, control));
-
- PAM_BP_RENEW(prompt_p, control, size - PAM_BP_MIN_SIZE);
- if (*prompt_p == NULL) {
- D(("problem making a new prompt for reply"));
- goto pamc_unknown_prompt;
- }
-
- /* read the rest of the reply prompt -- note offset has the correct
- value from the previous loop */
-
- while (offset < size) {
- int rval = read(pch->current->reader, offset + (__u8 *) *prompt_p,
- size-offset);
-
- if (rval == -1) {
- switch (errno) {
- case EINTR:
- break;
- default:
- D(("problem reading from agent: %s", strerror(errno)));
- goto pamc_unknown_prompt;
- }
- } else if (rval) {
- offset += rval;
- } else {
- D(("problem reading prompt (%d) with %d to go",
- size, size-offset));
- goto pamc_converse_failure;
- }
- }
-
- D(("returning success"));
-
- return PAM_BPC_TRUE;
-
-pamc_converse_failure:
-
- D(("conversation failure"));
- PAM_BP_RENEW(prompt_p, 0, 0);
- return PAM_BPC_FALSE;
-
-pamc_unknown_prompt:
-
- /* the server is trying something that the client does not support */
- D(("unknown prompt"));
- PAM_BP_RENEW(prompt_p, PAM_BPC_FAIL, 0);
- return PAM_BPC_TRUE;
-}
-
diff --git a/libpamc/pamc_load.c b/libpamc/pamc_load.c
deleted file mode 100644
index b3c0b5d5..00000000
--- a/libpamc/pamc_load.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (c) 1999 Andrew G. Morgan <morgan@ftp.kernel.org>
- *
- * pamc_load
- */
-
-#include "libpamc.h"
-
-static int __pamc_exec_agent(pamc_handle_t pch, pamc_agent_t *agent)
-{
- char *full_path;
- int found_agent, length, reset_length, to_agent[2], from_agent[2];
- int return_code = PAM_BPC_FAIL;
-
- if (agent->id[agent->id_length] != '\0') {
- PAM_BP_ASSERT("libpamc: internal error agent_id not terminated");
- }
-
- for (length=0; (length < agent->id_length); ++length) {
- switch (agent->id[length]) {
- case '/':
- D(("ill formed agent id"));
- return PAM_BPC_FAIL;
- }
- }
-
- /* enough memory for any path + this agent */
- reset_length = 3 + pch->max_path + agent->id_length;
- D(("reset_length = %d (3+%d+%d)",
- reset_length, pch->max_path, agent->id_length));
- full_path = malloc(reset_length);
- if (full_path == NULL) {
- D(("no memory for agent path"));
- return PAM_BPC_FAIL;
- }
-
- found_agent = 0;
- for (length=0; pch->agent_paths[length]; ++length) {
- struct stat buf;
-
- D(("path: [%s]", pch->agent_paths[length]));
- D(("agent id: [%s]", agent->id));
-
- sprintf(full_path, "%s/%s", pch->agent_paths[length], agent->id);
-
- D(("looking for agent here: [%s]\n", full_path));
- if (stat(full_path, &buf) == 0) {
- D(("file existis"));
- found_agent = 1;
- break;
- }
- }
-
- if (! found_agent) {
- D(("no agent was found"));
- goto free_and_return;
- }
-
- if (pipe(to_agent)) {
- D(("failed to open pipe to agent"));
- goto free_and_return;
- }
-
- if (pipe(from_agent)) {
- D(("failed to open pipe from agent"));
- goto close_the_agent;
- }
-
- agent->pid = fork();
- if (agent->pid == -1) {
-
- D(("failed to fork for agent"));
- goto close_both_pipes;
-
- } else if (agent->pid == 0) {
-
- int i;
-
- dup2(from_agent[1], STDOUT_FILENO);
- dup2(to_agent[0], STDIN_FILENO);
-
- /* we close all of the files that have filedescriptors lower
- and equal to twice the highest we have seen, The idea is
- that we don't want to leak filedescriptors to agents from a
- privileged client application.
-
- XXX - this is a heuristic at this point. There is a growing
- need for an extra 'set param' libpamc function, that could
- be used to supply info like the highest fd to close etc..
- */
-
- if (from_agent[1] > pch->highest_fd_to_close) {
- pch->highest_fd_to_close = 2*from_agent[1];
- }
-
- for (i=0; i <= pch->highest_fd_to_close; ++i) {
- switch (i) {
- case STDOUT_FILENO:
- case STDERR_FILENO:
- case STDIN_FILENO:
- /* only these three remain open */
- break;
- default:
- (void) close(i); /* don't care if its not open */
- }
- }
-
- /* we make no attempt to drop other privileges - this library
- has no idea how that would be done in the general case. It
- is up to the client application (when calling
- pamc_converse) to make sure no privilege will leak into an
- (untrusted) agent. */
-
- /* we propogate no environment - future versions of this
- library may have the ability to audit all agent
- transactions. */
-
- D(("exec'ing agent %s", full_path));
- execle(full_path, "pam-agent", NULL, NULL);
-
- D(("exec failed"));
- exit(1);
-
- }
-
- close(to_agent[0]);
- close(from_agent[1]);
-
- agent->writer = to_agent[1];
- agent->reader = from_agent[0];
-
- return_code = PAM_BPC_TRUE;
- goto free_and_return;
-
-close_both_pipes:
- close(from_agent[0]);
- close(from_agent[1]);
-
-close_the_agent:
- close(to_agent[0]);
- close(to_agent[1]);
-
-free_and_return:
- memset(full_path, 0, reset_length);
- free(full_path);
-
- D(("returning %d", return_code));
-
- return return_code;
-}
-
-/*
- * has the named agent been loaded?
- */
-
-static int __pamc_agent_is_enabled(pamc_handle_t pch, const char *agent_id)
-{
- pamc_agent_t *agent;
-
- for (agent = pch->chain; agent; agent = agent->next) {
- if (!strcmp(agent->id, agent_id)) {
- D(("agent already loaded"));
- return PAM_BPC_TRUE;
- }
- }
-
- D(("agent is not loaded"));
- return PAM_BPC_FALSE;
-}
-
-/*
- * has the named agent been disabled?
- */
-
-static int __pamc_agent_is_disabled(pamc_handle_t pch, const char *agent_id)
-{
- pamc_blocked_t *blocked;
-
- for (blocked=pch->blocked_agents; blocked; blocked = blocked->next) {
- if (!strcmp(agent_id, blocked->id)) {
- D(("agent is disabled"));
- return PAM_BPC_TRUE;
- }
- }
-
- D(("agent is not disabled"));
- return PAM_BPC_FALSE;
-}
-
-/*
- * disable an agent
- */
-
-int pamc_disable(pamc_handle_t pch, const char *agent_id)
-{
- pamc_blocked_t *block;
-
- if (pch == NULL) {
- D(("pch is NULL"));
- return PAM_BPC_FALSE;
- }
-
- if (agent_id == NULL) {
- D(("agent_id is NULL"));
- return PAM_BPC_FALSE;
- }
-
- if (__pamc_agent_is_enabled(pch, agent_id) != PAM_BPC_FALSE) {
- D(("agent is already loaded"));
- return PAM_BPC_FALSE;
- }
-
- if (__pamc_agent_is_disabled(pch, agent_id) != PAM_BPC_FALSE) {
- D(("agent is already disabled"));
- return PAM_BPC_TRUE;
- }
-
- block = calloc(1, sizeof(pamc_blocked_t));
- if (block == NULL) {
- D(("no memory for new blocking structure"));
- return PAM_BPC_FALSE;
- }
-
- block->id = malloc(1 + strlen(agent_id));
- if (block->id == NULL) {
- D(("no memory for agent id"));
- free(block);
- return PAM_BPC_FALSE;
- }
-
- strcpy(block->id, agent_id);
- block->next = pch->blocked_agents;
- pch->blocked_agents = block;
-
- return PAM_BPC_TRUE;
-}
-
-/*
- * force the loading of a particular agent
- */
-
-int pamc_load(pamc_handle_t pch, const char *agent_id)
-{
- pamc_agent_t *agent;
- int length;
-
- /* santity checking */
-
- if (pch == NULL) {
- D(("pch is NULL"));
- return PAM_BPC_FALSE;
- }
-
- if (agent_id == NULL) {
- D(("agent_id is NULL"));
- return PAM_BPC_FALSE;
- }
-
- if (__pamc_agent_is_disabled(pch, agent_id) != PAM_BPC_FALSE) {
- D(("sorry agent is disabled"));
- return PAM_BPC_FALSE;
- }
-
- length = strlen(agent_id);
-
- /* scan list to see if agent is loaded */
-
- if (__pamc_agent_is_enabled(pch, agent_id) == PAM_BPC_TRUE) {
- D(("no need to load an already loaded agent (%s)", agent_id));
- return PAM_BPC_TRUE;
- }
-
- /* not in the list, so we need to load it and add it to the head
- of the chain */
-
- agent = calloc(1, sizeof(pamc_agent_t));
- if (agent == NULL) {
- D(("no memory for new agent"));
- return PAM_BPC_FALSE;
- }
- agent->id = calloc(1, 1+length);
- if (agent->id == NULL) {
- D(("no memory for new agent's id"));
- goto fail_free_agent;
- }
- memcpy(agent->id, agent_id, length);
- agent->id[length] = '\0';
- agent->id_length = length;
-
- if (__pamc_exec_agent(pch, agent) != PAM_BPC_TRUE) {
- D(("unable to exec agent"));
- goto fail_free_agent_id;
- }
-
- agent->next = pch->chain;
- pch->chain = agent;
-
- return PAM_BPC_TRUE;
-
-fail_free_agent_id:
-
- memset(agent->id, 0, agent->id_length);
- free(agent->id);
-
- memset(agent, 0, sizeof(*agent));
-
-fail_free_agent:
-
- free(agent);
- return PAM_BPC_FALSE;
-}
-
-/*
- * what's a valid agent name?
- */
-
-int __pamc_valid_agent_id(int id_length, const char *id)
-{
- int post, i;
-
- for (i=post=0 ; i < id_length; ++i) {
- int ch = id[i++];
-
- if (isalpha(ch) || isdigit(ch) || (ch == '_')) {
- continue;
- } else if (post && (ch == '.')) {
- continue;
- } else if ((i > 1) && (!post) && (ch == '@')) {
- post = 1;
- } else {
- D(("id=%s contains '%c' which is illegal", id, ch));
- return 0;
- }
- }
-
- if (!i) {
- D(("length of id is 0"));
- return 0;
- } else {
- return 1; /* id is valid */
- }
-}
-
-/*
- * building a tree of available agent names
- */
-
-static pamc_id_node_t *__pamc_add_node(pamc_id_node_t *root, const char *id,
- int *counter)
-{
- if (root) {
-
- int cmp;
-
- if ((cmp = strcmp(id, root->agent_id))) {
- if (cmp > 0) {
- root->right = __pamc_add_node(root->right, id,
- &(root->child_count));
- } else {
- root->left = __pamc_add_node(root->left, id,
- &(root->child_count));
- }
- }
-
- return root;
-
- } else {
-
- pamc_id_node_t *node = calloc(1, sizeof(pamc_id_node_t));
-
- if (node) {
- node->agent_id = malloc(1+strlen(id));
- if (node->agent_id) {
- strcpy(node->agent_id, id);
- } else {
- free(node);
- node = NULL;
- }
- }
-
- (*counter)++;
- return node;
- }
-}
-
-/*
- * drop all of the tree and any remaining ids
- */
-
-static pamc_id_node_t *__pamc_liberate_nodes(pamc_id_node_t *tree)
-{
- if (tree) {
- if (tree->agent_id) {
- free(tree->agent_id);
- tree->agent_id = NULL;
- }
-
- tree->left = __pamc_liberate_nodes(tree->left);
- tree->right = __pamc_liberate_nodes(tree->right);
-
- tree->child_count = 0;
- free(tree);
- }
-
- return NULL;
-}
-
-/*
- * fill a list with the contents of the tree (in ascii order)
- */
-
-static void __pamc_fill_list_from_tree(pamc_id_node_t *tree, char **agent_list,
- int *counter)
-{
- if (tree) {
- __pamc_fill_list_from_tree(tree->left, agent_list, counter);
- agent_list[(*counter)++] = tree->agent_id;
- tree->agent_id = NULL;
- __pamc_fill_list_from_tree(tree->right, agent_list, counter);
- }
-}
-
-/*
- * get a list of the available agents
- */
-
-char **pamc_list_agents(pamc_handle_t pch)
-{
- int i, total_agent_count=0;
- pamc_id_node_t *tree = NULL;
- char **agent_list;
-
- /* loop over agent paths */
-
- for (i=0; pch->agent_paths[i]; ++i) {
- DIR *dir;
-
- dir = opendir(pch->agent_paths[i]);
- if (dir) {
- struct dirent *item;
-
- while ((item = readdir(dir))) {
-
- /* this is a cheat on recognizing agent_ids */
- if (!__pamc_valid_agent_id(strlen(item->d_name),
- item->d_name)) {
- continue;
- }
-
- tree = __pamc_add_node(tree, item->d_name, &total_agent_count);
- }
-
- closedir(dir);
- }
- }
-
- /* now, we build a list of ids */
- D(("total of %d available agents\n", total_agent_count));
-
- agent_list = calloc(total_agent_count+1, sizeof(char *));
- if (agent_list) {
- int counter=0;
-
- __pamc_fill_list_from_tree(tree, agent_list, &counter);
- if (counter != total_agent_count) {
- PAM_BP_ASSERT("libpamc: internal error transcribing tree");
- }
- } else {
- D(("no memory for agent list"));
- }
-
- __pamc_liberate_nodes(tree);
-
- return agent_list;
-}
diff --git a/libpamc/test/agents/secret@here b/libpamc/test/agents/secret@here
deleted file mode 100755
index afdcbaa8..00000000
--- a/libpamc/test/agents/secret@here
+++ /dev/null
@@ -1,308 +0,0 @@
-#!/usr/bin/perl
-#
-# This is a simple example PAM authentication agent, it implements a
-# simple shared secret authentication scheme. The PAM module pam_secret.so
-# is its counter part. Both the agent and the remote server are able to
-# authenticate one another, but the server is given the opportunity to
-# ignore a failed authentication.
-#
-
-$^W = 1;
-use strict;
-use IPC::Open2;
-$| = 1;
-
-# display extra information to STDERR
-my $debug = 0;
-if (scalar @ARGV) {
- $debug = 1;
-}
-
-# Globals
-
-my %state;
-my $default_key;
-
-my $next_key = $$;
-
-# loop over binary prompts
-for (;;) {
- my ($control, $data) = ReadBinaryPrompt();
- my ($reply_control, $reply_data);
-
- if ($control == 0) {
- if ($debug) {
- print STDERR "agent: no packet to read\n";
- }
- last;
- } elsif ($control == 0x02) {
- ($reply_control, $reply_data) = HandleAgentSelection($data);
- } elsif ($control == 0x01) {
- ($reply_control, $reply_data) = HandleContinuation($data);
- } else {
- if ($debug) {
- print STDERR
- "agent: unrecognized packet $control {$data} to read\n";
- }
- ($reply_control, $reply_data) = (0x04, "");
- }
-
- WriteBinaryPrompt($reply_control, $reply_data);
-}
-
-# Only willing to exit well if we've completed our authentication exchange
-
-if (scalar keys %state) {
- if ($debug) {
- print STDERR "The following sessions are still active:\n ";
- print STDERR join ', ', keys %state;
- print STDERR "\n";
- }
- exit 1;
-} else {
- exit 0;
-}
-
-sub HandleAgentSelection ($) {
- my ($data) = @_;
-
- unless ( $data =~ /^([a-zA-Z0-9_]+\@?[a-zA-Z0-9_.]*)\/(.*)$/ ) {
- return (0x04, "");
- }
-
- my ($agent_name, $payload) = ($1, $2);
- if ($debug) {
- print STDERR "agent: ". "agent=$agent_name, payload=$payload\n";
- }
-
- # this agent has a defined name
- if ($agent_name ne "secret\@here") {
- if ($debug) {
- print STDERR "bad agent name: [$agent_name]\n";
- }
- return (0x04, "");
- }
-
- # the selection request is acompanied with a hexadecimal cookie
- my @tokens = split '\|', $payload;
-
- unless ((scalar @tokens) == 2) {
- if ($debug) {
- print STDERR "bad payload\n";
- }
- return (0x04, "");
- }
-
- unless ($tokens[1] =~ /^[a-z0-9]+$/) {
- if ($debug) {
- print STDERR "bad server cookie\n";
- }
- return (0x04, "");
- }
-
- my $shared_secret = IdentifyLocalSecret($tokens[0]);
-
- unless (defined $shared_secret) {
- # make a secret up
- if ($debug) {
- print STDERR "agent: cannot authenticate user\n";
- }
- $shared_secret = GetRandom();
- }
-
- my $local_cookie = GetRandom();
- $default_key = $next_key++;
-
- $state{$default_key} = $local_cookie ."|". $tokens[1] ."|". $shared_secret;
-
- if ($debug) {
- print STDERR "agent: \$state{$default_key} = $state{$default_key}\n";
- }
-
- return (0x01, $default_key ."|". $local_cookie);
-}
-
-sub HandleContinuation ($) {
- my ($data) = @_;
-
- my ($key, $server_digest) = split '\|', $data;
-
- unless (defined $state{$key}) {
- # retries and out of sequence prompts are not permitted
- return (0x04, "");
- }
-
- my $expected_digest = CreateDigest($state{$key});
- my ($local_cookie, $remote_cookie, $shared_secret)
- = split '\|', $state{$key};
- delete $state{$key};
-
- unless ($expected_digest eq $server_digest) {
- if ($debug) {
- print STDERR "agent: don't trust server - faking reply\n";
- print STDERR "agent: got ($server_digest)\n";
- print STDERR "agent: expected ($expected_digest)\n";
- }
-
- ## FIXME: Agent should exchange a prompt with the client warning
- ## that the server is faking us out.
-
- return (0x03, CreateDigest($expected_digest . $data . GetRandom()));
- }
-
- if ($debug) {
- print STDERR "agent: server appears to know the secret\n";
- }
-
- my $session_authenticated_ticket =
- CreateDigest($remote_cookie."|".$shared_secret."|".$local_cookie);
-
- # FIXME: Agent should set a derived session key environment
- # variable (available for the client (and its children) to sign
- # future data exchanges.
-
- if ($debug) {
- print STDERR "agent: should putenv("
- ."\"AUTH_SESSION_TICKET=$session_authenticated_ticket\")\n";
- }
-
- # return agent's authenticating digest
- return (0x03, CreateDigest($shared_secret."|".$remote_cookie
- ."|".$local_cookie));
-}
-
-sub ReadBinaryPrompt {
- my $buffer = " ";
- my $count = read(STDIN, $buffer, 5);
- if ($count == 0) {
- # no more packets to read
- return (0, "");
- }
-
- if ($count != 5) {
- # broken packet header
- return (-1, "");
- }
-
- my ($length, $control) = unpack("N C", $buffer);
- if ($length < 5) {
- # broken packet length
- return (-1, "");
- }
-
- my $data = "";
- $length -= 5;
- while ($count = read(STDIN, $buffer, $length)) {
- $data .= $buffer;
- if ($count != $length) {
- $length -= $count;
- next;
- }
-
- if ($debug) {
- print STDERR "agent: ". "data is [$data]\n";
- }
-
- return ($control, $data);
- }
-
- # broken packet data
- return (-1, "");
-}
-
-sub WriteBinaryPrompt ($$) {
- my ($control, $data) = @_;
-
- my $length = 5 + length($data);
- if ($debug) {
- printf STDERR "agent: ". "{%d|0x%.2x|%s}\n", $length, $control, $data;
- }
- my $bp = pack("N C a*", $length, $control, $data);
- print STDOUT $bp;
- if ($debug) {
- printf STDERR "agent: ". "agent has replied\n";
- }
-}
-
-##
-## Here is where we parse the simple secret file
-## The format of this file is a list of lines of the following form:
-##
-## user@client0.host.name secret_string1
-## user@client1.host.name secret_string2
-## user@client2.host.name secret_string3
-##
-
-sub IdentifyLocalSecret ($) {
- my ($identifier) = @_;
- my $secret;
-
- if (open SECRETS, "< ". (getpwuid($<))[7] ."/.secret\@here") {
- my $line;
- while (defined ($line = <SECRETS>)) {
- my ($id, $sec) = split /[\s]+/, $line;
- if ((defined $id) && ($id eq $identifier)) {
- $secret = $sec;
- last;
- }
- }
- close SECRETS;
- }
-
- return $secret;
-}
-
-## Here is where we generate a message digest
-
-sub CreateDigest ($) {
- my ($data) = @_;
-
- my $pid = open2(\*MD5out, \*MD5in, "/usr/bin/md5sum -")
- or die "you'll need /usr/bin/md5sum installed";
-
- my $oldfd = select MD5in; $|=1; select $oldfd;
- if ($debug) {
- print STDERR "agent: ". "telling md5: <$data>\n";
- }
- print MD5in "$data";
- close MD5in;
- my $reply = <MD5out>;
- ($reply) = split /\s/, $reply;
- if ($debug) {
- print STDERR "agent: ". "md5 said: <$reply>\n";
- }
- close MD5out;
-
- return $reply;
-}
-
-## get a random number
-
-sub GetRandom {
-
- if ( -r "/dev/urandom" ) {
- open RANDOM, "< /dev/urandom" or die "crazy";
-
- my $i;
- my $reply = "";
-
- for ($i=0; $i<4; ++$i) {
- my $buffer = " ";
- while (read(RANDOM, $buffer, 4) != 4) {
- ;
- }
- $reply .= sprintf "%.8x", unpack("N", $buffer);
- if ($debug) {
- print STDERR "growing reply: [$reply]\n";
- }
- }
- close RANDOM;
-
- return $reply;
- } else {
- print STDERR "agent: ". "[got linux?]\n";
- return "%.8x%.8x%.8x%.8x", time, time, time, time;
- }
-
-}
-
diff --git a/libpamc/test/modules/Makefile b/libpamc/test/modules/Makefile
deleted file mode 100644
index 48065462..00000000
--- a/libpamc/test/modules/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-CFLAGS = -g -fPIC -I"../../include"
-
-pam_secret.so: pam_secret.o
- ld -x --shared -o pam_secret.so pam_secret.o -lc
-
-.o.c:
-
-clean:
- rm -f *.so *.o
diff --git a/libpamc/test/modules/pam_secret.c b/libpamc/test/modules/pam_secret.c
deleted file mode 100644
index 7efa8c23..00000000
--- a/libpamc/test/modules/pam_secret.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (c) 1999 Andrew G. Morgan <morgan@linux.kernel.org>
- */
-
-/*
- * WARNING: AS WRITTEN THIS CODE IS NOT SECURE. THE MD5 IMPLEMENTATION
- * NEEDS TO BE INTEGRATED MORE NATIVELY.
- */
-
-/* #define DEBUG */
-
-#include <fcntl.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <security/pam_modules.h>
-#include <security/pam_client.h>
-#include <security/_pam_macros.h>
-
-/*
- * This is a sample module that demonstrates the use of binary prompts
- * and how they can be used to implement sophisticated authentication
- * schemes.
- */
-
-struct ps_state_s {
- int retval; /* last retval returned by the authentication fn */
- int state; /* what state the module was in when it
- returned incomplete */
-
- char *username; /* the name of the local user */
-
- char server_cookie[33]; /* storage for 32 bytes of server cookie */
- char client_cookie[33]; /* storage for 32 bytes of client cookie */
-
- char *secret_data; /* pointer to <NUL> terminated secret_data */
- int invalid_secret; /* indication of whether the secret is valid */
-
- pamc_bp_t current_prompt; /* place to store the current prompt */
- pamc_bp_t current_reply; /* place to receive the reply prompt */
-};
-
-#define PS_STATE_ID "PAM_SECRET__STATE"
-#define PS_AGENT_ID "secret@here"
-#define PS_STATE_DEAD 0
-#define PS_STATE_INIT 1
-#define PS_STATE_PROMPT1 2
-#define PS_STATE_PROMPT2 3
-
-#define MAX_LEN_HOSTNAME 512
-#define MAX_FILE_LINE_LEN 1024
-
-/*
- * Routine for generating 16*8 bits of random data represented in ASCII hex
- */
-
-static int generate_cookie(unsigned char *buffer_33)
-{
- static const char hexarray[] = "0123456789abcdef";
- int i, fd;
-
- /* fill buffer_33 with 32 hex characters (lower case) + '\0' */
- fd = open("/dev/urandom", O_RDONLY);
- if (fd < 0) {
- D(("failed to open /dev/urandom"));
- return 0;
- }
- read(fd, buffer_33 + 16, 16);
- close(fd);
-
- /* expand top 16 bytes into 32 nibbles */
- for (i=0; i<16; ++i) {
- buffer_33[2*i ] = hexarray[(buffer_33[16+i] & 0xf0)>>4];
- buffer_33[2*i+1] = hexarray[(buffer_33[16+i] & 0x0f)];
- }
-
- buffer_33[32] = '\0';
-
- return 1;
-}
-
-/*
- * XXX - This is a hack, and is fundamentally insecure. Its subject to
- * all sorts of attacks not to mention the fact that all our secrets
- * will be displayed on the command line for someone doing 'ps' to
- * see. This is just for programming convenience in this instance, it
- * needs to be replaced with the md5 code. Although I am loath to
- * add yet another instance of md5 code to the Linux-PAM source code.
- * [Need to think of a cleaner way to do this for the distribution as
- * a whole...]
- */
-
-#define COMMAND_FORMAT "/bin/echo -n '%s|%s|%s'|/usr/bin/md5sum -"
-
-int create_digest(const char *d1, const char *d2, const char *d3,
- char *buffer_33)
-{
- int length;
- char *buffer;
- FILE *pipe;
-
- length = strlen(d1)+strlen(d2)+strlen(d3)+sizeof(COMMAND_FORMAT);
- buffer = malloc(length);
- if (buffer == NULL) {
- D(("out of memory"));
- return 0;
- }
-
- sprintf(buffer, COMMAND_FORMAT, d1,d2,d3);
-
- D(("executing pipe [%s]", buffer));
- pipe = popen(buffer, "r");
- memset(buffer, 0, length);
- free(buffer);
-
- if (pipe == NULL) {
- D(("failed to launch pipe"));
- return 0;
- }
-
- if (fgets(buffer_33, 33, pipe) == NULL) {
- D(("failed to read digest"));
- return 0;
- }
-
- if (strlen(buffer_33) != 32) {
- D(("digest was not 32 chars"));
- return 0;
- }
-
- fclose(pipe);
-
- D(("done [%s]", buffer_33));
-
- return 1;
-}
-
-/*
- * method to attempt to instruct the application's conversation function
- */
-
-static int converse(pam_handle_t *pamh, struct ps_state_s *new)
-{
- int retval;
- struct pam_conv *conv;
-
- D(("called"));
-
- retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
- if (retval == PAM_SUCCESS) {
- struct pam_message msg;
- struct pam_response *single_reply;
- const struct pam_message *msg_ptr;
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_style = PAM_BINARY_PROMPT;
- msg.msg = (const char *) new->current_prompt;
- msg_ptr = &msg;
-
- single_reply = NULL;
- retval = conv->conv(1, &msg_ptr, &single_reply, conv->appdata_ptr);
- if (retval == PAM_SUCCESS) {
- if ((single_reply == NULL) || (single_reply->resp == NULL)) {
- retval == PAM_CONV_ERR;
- } else {
- new->current_reply = (pamc_bp_t) single_reply->resp;
- single_reply->resp = NULL;
- }
- }
-
- if (single_reply) {
- free(single_reply);
- }
- }
-
-#ifdef DEBUG
- if (retval == PAM_SUCCESS) {
- D(("reply has length=%d and control=%u",
- PAM_BP_LENGTH(new->current_reply),
- PAM_BP_CONTROL(new->current_reply)));
- }
- D(("returning %s", pam_strerror(pamh, retval)));
-#endif
-
- return retval;
-}
-
-/*
- * identify the secret in question
- */
-
-#define SECRET_FILE_FORMAT "%s/.secret@here"
-
-char *identify_secret(char *identity, const char *user)
-{
- struct passwd *pwd;
- char *temp;
- FILE *secrets;
- int length_id;
-
- pwd = getpwnam(user);
- if ((pwd == NULL) || (pwd->pw_dir == NULL)) {
- D(("user [%s] is not known", user));
- }
-
- length_id = strlen(pwd->pw_dir) + sizeof(SECRET_FILE_FORMAT);
- temp = malloc(length_id);
- if (temp == NULL) {
- D(("out of memory"));
- pwd = NULL;
- return NULL;
- }
-
- sprintf(temp, SECRET_FILE_FORMAT, pwd->pw_dir);
- pwd = NULL;
-
- D(("opening key file [%s]", temp));
- secrets = fopen(temp, "r");
- memset(temp, 0, length_id);
-
- if (secrets == NULL) {
- D(("failed to open key file"));
- return NULL;
- }
-
- length_id = strlen(identity);
- temp = malloc(MAX_FILE_LINE_LEN);
-
- for (;;) {
- char *secret = NULL;
-
- if (fgets(temp, MAX_FILE_LINE_LEN, secrets) == NULL) {
- fclose(secrets);
- return NULL;
- }
-
- D(("cf[%s][%s]", identity, temp));
- if (memcmp(temp, identity, length_id)) {
- continue;
- }
-
- D(("found entry"));
- fclose(secrets);
-
- for (secret=temp+length_id; *secret; ++secret) {
- if (!(*secret == ' ' || *secret == '\n' || *secret == '\t')) {
- break;
- }
- }
-
- memmove(temp, secret, MAX_FILE_LINE_LEN-(secret-(temp+length_id)));
- secret = temp;
-
- for (; *secret; ++secret) {
- if (*secret == ' ' || *secret == '\n' || *secret == '\t') {
- break;
- }
- }
-
- if (*secret) {
- *secret = '\0';
- }
-
- D(("secret found [%s]", temp));
-
- return temp;
- }
-
- /* NOT REACHED */
-}
-
-/*
- * function to perform the two message authentication process
- * (with support for event driven conversation functions)
- */
-
-static int auth_sequence(pam_handle_t *pamh,
- const struct ps_state_s *old, struct ps_state_s *new)
-{
- const char *rhostname;
- const char *rusername;
- int retval;
-
- retval = pam_get_item(pamh, PAM_RUSER, (const void **) &rusername);
- if ((retval != PAM_SUCCESS) || (rusername == NULL)) {
- D(("failed to obtain an rusername"));
- new->state = PS_STATE_DEAD;
- return PAM_AUTH_ERR;
- }
-
- retval = pam_get_item(pamh, PAM_RHOST, (const void **) &rhostname);
- if ((retval != PAM_SUCCESS) || (rhostname == NULL)) {
- D(("failed to identify local hostname: ", pam_strerror(pamh, retval)));
- new->state = PS_STATE_DEAD;
- return PAM_AUTH_ERR;
- }
-
- D(("switch on new->state=%d [%s@%s]", new->state, rusername, rhostname));
- switch (new->state) {
-
- case PS_STATE_INIT:
- {
- const char *user = NULL;
-
- retval = pam_get_user(pamh, &user, NULL);
-
- if ((retval == PAM_SUCCESS) && (user == NULL)) {
- D(("success but no username?"));
- new->state = PS_STATE_DEAD;
- retval = PAM_USER_UNKNOWN;
- }
-
- if (retval != PAM_SUCCESS) {
- if (retval == PAM_CONV_AGAIN) {
- retval = PAM_INCOMPLETE;
- } else {
- new->state = PS_STATE_DEAD;
- }
- D(("state init failed: %s", pam_strerror(pamh, retval)));
- return retval;
- }
-
- /* nothing else in this 'case' can be retried */
-
- new->username = strdup(user);
- if (new->username == NULL) {
- D(("out of memory"));
- new->state = PS_STATE_DEAD;
- return PAM_BUF_ERR;
- }
-
- if (! generate_cookie(new->server_cookie)) {
- D(("problem generating server cookie"));
- new->state = PS_STATE_DEAD;
- return PAM_ABORT;
- }
-
- new->current_prompt = NULL;
- PAM_BP_RENEW(&new->current_prompt, PAM_BPC_SELECT,
- sizeof(PS_AGENT_ID) + strlen(rusername) + 1
- + strlen(rhostname) + 1 + 32);
- sprintf(PAM_BP_WDATA(new->current_prompt),
- PS_AGENT_ID "/%s@%s|%.32s", rusername, rhostname,
- new->server_cookie);
-
- /* note, the BP is guaranteed by the spec to be <NUL> terminated */
- D(("initialization packet [%s]", PAM_BP_DATA(new->current_prompt)));
-
- /* fall through */
- new->state = PS_STATE_PROMPT1;
-
- D(("fall through to state_prompt1"));
- }
-
- case PS_STATE_PROMPT1:
- {
- int i, length;
-
- /* send {secret@here/jdoe@client.host|<s_cookie>} */
- retval = converse(pamh, new);
- if (retval != PAM_SUCCESS) {
- if (retval == PAM_CONV_AGAIN) {
- D(("conversation failed to complete"));
- return PAM_INCOMPLETE;
- } else {
- new->state = PS_STATE_DEAD;
- return retval;
- }
- }
-
- if (retval != PAM_SUCCESS) {
- D(("failed to read ruser@rhost"));
- new->state = PS_STATE_DEAD;
- return PAM_AUTH_ERR;
- }
-
- /* expect to receive the following {<seqid>|<a_cookie>} */
- if (new->current_reply == NULL) {
- D(("converstation returned [%s] but gave no reply",
- pam_strerror(pamh, retval)));
- new->state = PS_STATE_DEAD;
- return PAM_CONV_ERR;
- }
-
- /* find | */
- length = PAM_BP_LENGTH(new->current_reply);
- for (i=0; i<length; ++i) {
- if (PAM_BP_RDATA(new->current_reply)[i] == '|') {
- break;
- }
- }
- if (i >= length) {
- D(("malformed response (no |) of length %d", length));
- new->state = PS_STATE_DEAD;
- return PAM_CONV_ERR;
- }
- if ((length - ++i) != 32) {
- D(("cookie is incorrect length (%d,%d) %d != 32",
- length, i, length-i));
- new->state = PS_STATE_DEAD;
- return PAM_CONV_ERR;
- }
-
- /* copy client cookie */
- memcpy(new->client_cookie, PAM_BP_RDATA(new->current_reply)+i, 32);
-
- /* generate a prompt that is length(seqid) + length(|) + 32 long */
- PAM_BP_RENEW(&new->current_prompt, PAM_BPC_OK, i+32);
- /* copy the head of the response prompt */
- memcpy(PAM_BP_WDATA(new->current_prompt),
- PAM_BP_RDATA(new->current_reply), i);
- PAM_BP_RENEW(&new->current_reply, 0, 0);
-
- /* look up the secret */
- new->invalid_secret = 0;
-
- if (new->secret_data == NULL) {
- char *ruser_rhost;
-
- ruser_rhost = malloc(strlen(rusername)+2+strlen(rhostname));
- if (ruser_rhost == NULL) {
- D(("out of memory"));
- new->state = PS_STATE_DEAD;
- return PAM_BUF_ERR;
- }
- sprintf(ruser_rhost, "%s@%s", rusername, rhostname);
- new->secret_data = identify_secret(ruser_rhost, new->username);
-
- memset(ruser_rhost, 0, strlen(ruser_rhost));
- free(ruser_rhost);
- }
-
- if (new->secret_data == NULL) {
- D(("secret not found for user"));
- new->invalid_secret = 1;
-
- /* need to make up a secret */
- new->secret_data = malloc(32 + 1);
- if (new->secret_data == NULL) {
- D(("out of memory"));
- new->state = PS_STATE_DEAD;
- return PAM_BUF_ERR;
- }
- if (! generate_cookie(new->secret_data)) {
- D(("what's up - no fake cookie generated?"));
- new->state = PS_STATE_DEAD;
- return PAM_ABORT;
- }
- }
-
- /* construct md5[<client_cookie>|<server_cookie>|<secret_data>] */
- if (! create_digest(new->client_cookie, new->server_cookie,
- new->secret_data,
- PAM_BP_WDATA(new->current_prompt)+i)) {
- D(("md5 digesting failed"));
- new->state = PS_STATE_DEAD;
- return PAM_ABORT;
- }
-
- /* prompt2 is now constructed - fall through to send it */
- }
-
- case PS_STATE_PROMPT2:
- {
- /* send {<seqid>|md5[<client_cookie>|<server_cookie>|<secret_data>]} */
- retval = converse(pamh, new);
- if (retval != PAM_SUCCESS) {
- if (retval == PAM_CONV_AGAIN) {
- D(("conversation failed to complete"));
- return PAM_INCOMPLETE;
- } else {
- new->state = PS_STATE_DEAD;
- return retval;
- }
- }
-
- /* After we complete this section, we should not be able to
- recall this authentication function. So, we force all
- future calls into the weeds. */
-
- new->state = PS_STATE_DEAD;
-
- /* expect reply:{md5[<secret_data>|<server_cookie>|<client_cookie>]} */
-
- {
- int cf;
- char expectation[33];
-
- if (!create_digest(new->secret_data, new->server_cookie,
- new->client_cookie, expectation)) {
- new->state = PS_STATE_DEAD;
- return PAM_ABORT;
- }
-
- cf = strcmp(expectation, PAM_BP_RDATA(new->current_reply));
- memset(expectation, 0, sizeof(expectation));
- if (cf || new->invalid_secret) {
- D(("failed to authenticate"));
- return PAM_AUTH_ERR;
- }
- }
-
- D(("correctly authenticated :)"));
- return PAM_SUCCESS;
- }
-
- default:
- new->state = PS_STATE_DEAD;
-
- case PS_STATE_DEAD:
-
- D(("state is currently dead/unknown"));
- return PAM_AUTH_ERR;
- }
-
- fprintf(stderr, "pam_secret: this should not be reached\n");
- return PAM_ABORT;
-}
-
-static void clean_data(pam_handle_t *pamh, void *datum, int error_status)
-{
- struct ps_state_s *data = datum;
-
- D(("liberating datum=%p", datum));
-
- if (data) {
- D(("renew prompt"));
- PAM_BP_RENEW(&data->current_prompt, 0, 0);
- D(("renew reply"));
- PAM_BP_RENEW(&data->current_reply, 0, 0);
- D(("overwrite datum"));
- memset(data, 0, sizeof(struct ps_state_s));
- D(("liberate datum"));
- free(data);
- }
-
- D(("done."));
-}
-
-/*
- * front end for the authentication function
- */
-
-int pam_sm_authenticate(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
-{
- int retval;
- struct ps_state_s *new_data;
- const struct ps_state_s *old_data;
-
- D(("called"));
-
- new_data = calloc(1, sizeof(struct ps_state_s));
- if (new_data == NULL) {
- D(("out of memory"));
- return PAM_BUF_ERR;
- }
- new_data->retval = PAM_SUCCESS;
-
- retval = pam_get_data(pamh, PS_STATE_ID, (const void **) &old_data);
- if (retval == PAM_SUCCESS) {
- new_data->state = old_data->state;
- memcpy(new_data->server_cookie, old_data->server_cookie, 32);
- memcpy(new_data->client_cookie, old_data->client_cookie, 32);
- if (old_data->username) {
- new_data->username = strdup(old_data->username);
- }
- if (old_data->secret_data) {
- new_data->secret_data = strdup(old_data->secret_data);
- }
- if (old_data->current_prompt) {
- int length;
-
- length = PAM_BP_LENGTH(old_data->current_prompt);
- PAM_BP_RENEW(&new_data->current_prompt,
- PAM_BP_CONTROL(old_data->current_prompt), length);
- PAM_BP_FILL(new_data->current_prompt, 0, length,
- PAM_BP_RDATA(old_data->current_prompt));
- }
- /* don't need to duplicate current_reply */
- } else {
- old_data = NULL;
- new_data->state = PS_STATE_INIT;
- }
-
- D(("call auth_sequence"));
- new_data->retval = auth_sequence(pamh, old_data, new_data);
- D(("returned from auth_sequence"));
-
- retval = pam_set_data(pamh, PS_STATE_ID, new_data, clean_data);
- if (retval != PAM_SUCCESS) {
- D(("unable to store new_data"));
- } else {
- retval = new_data->retval;
- }
-
- old_data = new_data = NULL;
-
- D(("done (%d)", retval));
- return retval;
-}
-
-/*
- * front end for the credential setting function
- */
-
-#define AUTH_SESSION_TICKET_ENV_FORMAT "AUTH_SESSION_TICKET="
-
-int pam_sm_setcred(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
-{
- int retval;
- const struct ps_state_s *old_data;
-
- D(("called"));
-
- /* XXX - need to pay attention to the various flavors of call */
-
- /* XXX - need provide an option to turn this feature on/off: if
- other modules want to supply an AUTH_SESSION_TICKET, we should
- leave it up to the admin which module dominiates. */
-
- retval = pam_get_data(pamh, PS_STATE_ID, (const void **) &old_data);
- if (retval != PAM_SUCCESS) {
- D(("no data to base decision on"));
- return PAM_AUTH_ERR;
- }
-
- /*
- * If ok, export a derived shared secret session ticket to the
- * client's PAM environment - the ticket has the form
- *
- * AUTH_SESSION_TICKET =
- * md5[<server_cookie>|<secret_data>|<client_cookie>]
- *
- * This is a precursor to supporting a spoof resistant trusted
- * path mechanism. This shared secret ticket can be used to add
- * a hard-to-guess checksum to further authentication data.
- */
-
- retval = old_data->retval;
- if (retval == PAM_SUCCESS) {
- char envticket[sizeof(AUTH_SESSION_TICKET_ENV_FORMAT)+32];
-
- memcpy(envticket, AUTH_SESSION_TICKET_ENV_FORMAT,
- sizeof(AUTH_SESSION_TICKET_ENV_FORMAT));
-
- if (! create_digest(old_data->server_cookie, old_data->secret_data,
- old_data->client_cookie,
- envticket+sizeof(AUTH_SESSION_TICKET_ENV_FORMAT)-1
- )) {
- D(("unable to generate a digest for session ticket"));
- return PAM_ABORT;
- }
-
- D(("putenv[%s]", envticket));
- retval = pam_putenv(pamh, envticket);
- memset(envticket, 0, sizeof(envticket));
- }
-
- old_data = NULL;
- D(("done (%d)", retval));
-
- return retval;
-}
diff --git a/libpamc/test/regress/Makefile b/libpamc/test/regress/Makefile
deleted file mode 100644
index ff63e5f0..00000000
--- a/libpamc/test/regress/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-CFLAGS = -g -I ../../include
-
-test.libpamc: test.libpamc.o
- $(CC) -o $@ $< -L ../.. -lpamc
-
-clean:
- rm -f test.libpamc test.libpamc.o
diff --git a/libpamc/test/regress/run_test.sh b/libpamc/test/regress/run_test.sh
deleted file mode 100755
index 6922f03d..00000000
--- a/libpamc/test/regress/run_test.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-LD_LIBRARY_PATH=../.. ; export LD_LIBRARY_PATH
-PAMC_AGENT_PATH="../agents" ; export PAMC_AGENT_PATH
-
-./test.libpamc
diff --git a/libpamc/test/regress/test.libpamc.c b/libpamc/test/regress/test.libpamc.c
deleted file mode 100644
index b7bc4e4b..00000000
--- a/libpamc/test/regress/test.libpamc.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * This is a small test program for testing libpamc against the
- * secret@here agent. It does the same as the test.secret@here perl
- * script in this directory, but via the libpamc API.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <security/pam_client.h>
-#include <ctype.h>
-
-struct internal_packet {
- int length;
- int at;
- char *buffer;
-};
-
-
-void append_data(struct internal_packet *packet, int extra, const char *data)
-{
- if ((extra + packet->at) >= packet->length) {
- if (packet->length == 0) {
- packet->length = 1000;
- }
- /* make sure we have at least a char extra space available */
- while (packet->length <= (extra + packet->at)) {
- packet->length <<= 1;
- }
- packet->buffer = realloc(packet->buffer, packet->length);
- if (packet->buffer == NULL) {
- fprintf(stderr, "out of memory\n");
- exit(1);
- }
- }
-
- if (data != NULL) {
- memcpy(packet->at + packet->buffer, data, extra);
- }
- packet->at += extra;
-
- /* assisting string manipulation */
- packet->buffer[packet->at] = '\0';
-}
-
-void append_string(struct internal_packet *packet, const char *string,
- int with_nul)
-{
- append_data(packet, strlen(string) + (with_nul ? 1:0), string);
-}
-
-char *identify_secret(char *identity)
-{
- struct internal_packet temp_packet;
- FILE *secrets;
- int length_id;
-
- temp_packet.length = temp_packet.at = 0;
- temp_packet.buffer = NULL;
-
- append_string(&temp_packet, "/home/", 0);
- append_string(&temp_packet, getlogin(), 0);
- append_string(&temp_packet, "/.secret@here", 1);
-
- secrets = fopen(temp_packet.buffer, "r");
- if (secrets == NULL) {
- fprintf(stderr, "server: failed to open\n [%s]\n",
- temp_packet.buffer);
- exit(1);
- }
-
- length_id = strlen(identity);
- for (;;) {
- char *secret = NULL;
- temp_packet.at = 0;
-
- if (fgets(temp_packet.buffer, temp_packet.length, secrets) == NULL) {
- fclose(secrets);
- return NULL;
- }
-
- if (memcmp(temp_packet.buffer, identity, length_id)) {
- continue;
- }
-
- fclose(secrets);
- for (secret=temp_packet.buffer; *secret; ++secret) {
- if (*secret == ' ' || *secret == '\n' || *secret == '\t') {
- break;
- }
- }
- for (; *secret; ++secret) {
- if (!(*secret == ' ' || *secret == '\n' || *secret == '\t')) {
- break;
- }
- }
-
- for (temp_packet.buffer=secret; *temp_packet.buffer;
- ++temp_packet.buffer) {
- if (*temp_packet.buffer == ' ' || *temp_packet.buffer == '\n'
- || *temp_packet.buffer == '\t') {
- break;
- }
- }
- if (*temp_packet.buffer) {
- *temp_packet.buffer = '\0';
- }
-
- return secret;
- }
-
- /* NOT REACHED */
-}
-
-/*
- * This is a hack, and is fundamentally insecure. All our secrets will be
- * displayed on the command line for someone doing 'ps' to see. This
- * is just for programming convenience in this instance, since this
- * program is simply a regression test. The pam_secret module should
- * not do this, but make use of md5 routines directly.
- */
-
-char *create_digest(int length, const char *raw)
-{
- struct internal_packet temp_packet;
- FILE *pipe;
-
- temp_packet.length = temp_packet.at = 0;
- temp_packet.buffer = NULL;
-
- append_string(&temp_packet, "echo -n '", 0);
- append_string(&temp_packet, raw, 0);
- append_string(&temp_packet, "'|/usr/bin/md5sum -", 1);
-
- fprintf(stderr, "am attempting to run [%s]\n", temp_packet.buffer);
-
- pipe = popen(temp_packet.buffer, "r");
- if (pipe == NULL) {
- fprintf(stderr, "server: failed to run\n [%s]\n", temp_packet.buffer);
- exit(1);
- }
-
- temp_packet.at = 0;
- append_data(&temp_packet, 32, NULL);
-
- if (fgets(temp_packet.buffer, 33, pipe) == NULL) {
- fprintf(stderr, "server: failed to read digest\n");
- exit(1);
- }
- if (strlen(temp_packet.buffer) != 32) {
- fprintf(stderr, "server: digest was not 32 chars?? [%s]\n",
- temp_packet.buffer);
- exit(1);
- }
-
- fclose(pipe);
-
- return temp_packet.buffer;
-}
-
-void packet_to_prompt(pamc_bp_t *prompt_p, __u8 control,
- struct internal_packet *packet)
-{
- PAM_BP_RENEW(prompt_p, control, packet->at);
- PAM_BP_FILL(*prompt_p, 0, packet->at, packet->buffer);
- packet->at = 0;
-}
-
-void prompt_to_packet(pamc_bp_t prompt, struct internal_packet *packet)
-{
- int data_length;
-
- data_length = PAM_BP_LENGTH(prompt);
- packet->at = 0;
- append_data(packet, data_length, NULL);
-
- PAM_BP_EXTRACT(prompt, 0, data_length, packet->buffer);
-
- fprintf(stderr, "server received[%d]: {%d|0x%.2x|%s}\n",
- data_length,
- PAM_BP_SIZE(prompt), PAM_BP_RCONTROL(prompt),
- PAM_BP_RDATA(prompt));
-}
-
-int main(int argc, char **argv)
-{
- pamc_handle_t pch;
- pamc_bp_t prompt = NULL;
- struct internal_packet packet_data, *packet;
- char *temp_string, *secret, *user, *a_cookie, *seqid, *digest;
- const char *cookie = "123451234512345";
- int retval;
-
- packet = &packet_data;
- packet->length = 0;
- packet->at = 0;
- packet->buffer = NULL;
-
- pch = pamc_start();
- if (pch == NULL) {
- fprintf(stderr, "server: unable to get a handle from libpamc\n");
- exit(1);
- }
-
- temp_string = getlogin();
- if (temp_string == NULL) {
- fprintf(stderr, "server: who are you?\n");
- exit(1);
- }
-#define DOMAIN "@local.host"
- user = malloc(1+strlen(temp_string)+strlen(DOMAIN));
- if (user == NULL) {
- fprintf(stderr, "server: out of memory for user id\n");
- exit(1);
- }
- sprintf(user, "%s%s", temp_string, DOMAIN);
-
- append_string(packet, "secret@here/", 0);
- append_string(packet, user, 0);
- append_string(packet, "|", 0);
- append_string(packet, cookie, 0);
- packet_to_prompt(&prompt, PAM_BPC_SELECT, packet);
-
- /* get the library to accept the first packet (which should load
- the secret@here agent) */
-
- retval = pamc_converse(pch, &prompt);
- fprintf(stderr, "server: after conversation\n");
- if (PAM_BP_RCONTROL(prompt) != PAM_BPC_OK) {
- fprintf(stderr, "server: prompt had unexpected control type: %u\n",
- PAM_BP_RCONTROL(prompt));
- exit(1);
- }
-
- fprintf(stderr, "server: got a prompt back\n");
-
- prompt_to_packet(prompt, packet);
-
- temp_string = strtok(packet->buffer, "|");
- if (temp_string == NULL) {
- fprintf(stderr, "server: prompt does not contain anything");
- exit(1);
- }
- seqid = strdup(temp_string);
- if (seqid == NULL) {
- fprintf(stderr, "server: unable to store sequence id\n");
- }
-
- temp_string = strtok(NULL, "|");
- if (temp_string == NULL) {
- fprintf(stderr, "server: no cookie from agent\n");
- exit(1);
- }
- a_cookie = strdup(temp_string);
- if (a_cookie == NULL) {
- fprintf(stderr, "server: no memory to store agent cookie\n");
- exit(1);
- }
-
- fprintf(stderr, "server: agent responded with {%s|%s}\n", seqid, a_cookie);
- secret = identify_secret(user);
- fprintf(stderr, "server: secret=%s\n", secret);
-
- /* now, we construct the response */
- packet->at = 0;
- append_string(packet, a_cookie, 0);
- append_string(packet, "|", 0);
- append_string(packet, cookie, 0);
- append_string(packet, "|", 0);
- append_string(packet, secret, 0);
-
- fprintf(stderr, "server: get digest of %s\n", packet->buffer);
-
- digest = create_digest(packet->at, packet->buffer);
-
- fprintf(stderr, "server: secret=%s, digest=%s\n", secret, digest);
-
- packet->at = 0;
- append_string(packet, seqid, 0);
- append_string(packet, "|", 0);
- append_string(packet, digest, 0);
- packet_to_prompt(&prompt, PAM_BPC_OK, packet);
-
- retval = pamc_converse(pch, &prompt);
- fprintf(stderr, "server: after 2nd conversation\n");
- if (PAM_BP_RCONTROL(prompt) != PAM_BPC_DONE) {
- fprintf(stderr, "server: 2nd prompt had unexpected control type: %u\n",
- PAM_BP_RCONTROL(prompt));
- exit(1);
- }
-
- prompt_to_packet(prompt, packet);
- PAM_BP_RENEW(&prompt, 0, 0);
-
- temp_string = strtok(packet->buffer, "|");
- if (temp_string == NULL) {
- fprintf(stderr, "no digest from agent\n");
- exit(1);
- }
- temp_string = strdup(temp_string);
-
- packet->at = 0;
- append_string(packet, secret, 0);
- append_string(packet, "|", 0);
- append_string(packet, cookie, 0);
- append_string(packet, "|", 0);
- append_string(packet, a_cookie, 0);
-
- fprintf(stderr, "server: get digest of %s\n", packet->buffer);
-
- digest = create_digest(packet->at, packet->buffer);
-
- fprintf(stderr, "server: digest=%s\n", digest);
-
- if (strcmp(digest, temp_string)) {
- fprintf(stderr, "server: agent doesn't know the secret\n");
- fprintf(stderr, "server: agent says: [%s]\n"
- "server: server says: [%s]\n", temp_string, digest);
- exit(1);
- } else {
- fprintf(stderr, "server: agent seems to know the secret\n");
-
- packet->at = 0;
- append_string(packet, cookie, 0);
- append_string(packet, "|", 0);
- append_string(packet, secret, 0);
- append_string(packet, "|", 0);
- append_string(packet, a_cookie, 0);
-
- digest = create_digest(packet->at, packet->buffer);
-
- fprintf(stderr, "server: putenv(\"AUTH_SESSION_TICKET=%s\")\n",
- digest);
- }
-
-
- retval = pamc_end(&pch);
-
- fprintf(stderr, "server: agent(s) were %shappy to terminate\n",
- retval == PAM_BPC_TRUE ? "":"un");
-
- exit(!retval);
-}
diff --git a/libpamc/test/regress/test.secret@here b/libpamc/test/regress/test.secret@here
deleted file mode 100755
index 2e0b9b94..00000000
--- a/libpamc/test/regress/test.secret@here
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/bin/perl
-
-##
-## this is a test script for regressing changes to the secret@here PAM
-## agent
-##
-
-$^W = 1;
-use strict;
-use IPC::Open2;
-
-$| = 1;
-
-my $whoami = `/usr/bin/whoami`; chomp $whoami;
-my $cookie = "12345";
-my $user_domain = "$whoami\@local.host";
-
-my $pid = open2(\*Reader, \*Writer, "../agents/secret\@here blah")
- or die "failed to load secret\@here agent";
-
-unless (-f (getpwuid($<))[7]."/.secret\@here") {
- print STDERR "server: ". "no " .(getpwuid($<))[7]. "/.secret\@here file\n";
- die "no config file";
-}
-
-WriteBinaryPrompt(\*Writer, 0x02, "secret\@here/$user_domain|$cookie");
-
-my ($control, $data) = ReadBinaryPrompt(\*Reader);
-
-print STDERR "server: ". "reply: control=$control, data=$data\n";
-if ($control != 1) {
- die "expected 1 (OK) for the first agent reply; got $control";
-}
-my ($seqid, $a_cookie) = split '\|', $data;
-
-# server needs to convince agent that it knows the secret before
-# agent will give a valid response
-my $secret = IdentifyLocalSecret($user_domain);
-my $digest = CreateDigest($a_cookie."|".$cookie."|".$secret);
-
-print STDERR "server: ". "digest = $digest\n";
-WriteBinaryPrompt(\*Writer, 0x01, "$seqid|$digest");
-
-# The agent will authenticate us and then reply with its
-# authenticating digest. we check that before we're done.
-
-($control, $data) = ReadBinaryPrompt(\*Reader);
-if ($control != 0x03) {
- die "server: agent did not reply with a 'done' prompt ($control)\n";
-}
-
-unless ($data eq CreateDigest($secret."|".$cookie."|".$a_cookie)) {
- die "server: agent is not authenticated\n";
-}
-
-print STDERR "server: agent appears to know secret\n";
-
-my $session_authenticated_ticket
- = CreateDigest($cookie."|".$secret."|".$a_cookie);
-
-print STDERR "server: should putenv("
- ."\"AUTH_SESSION_TICKET=$session_authenticated_ticket\")\n";
-
-exit 0;
-
-sub CreateDigest ($) {
- my ($data) = @_;
-
- my $pid = open2(\*MD5out, \*MD5in, "/usr/bin/md5sum -")
- or die "you'll need /usr/bin/md5sum installed";
-
- my $oldfd = select MD5in; $|=1; select $oldfd;
- print MD5in "$data";
- close MD5in;
- my $reply = <MD5out>;
- ($reply) = split /\s/, $reply;
- print STDERR "server: ". "md5 said: <$reply>\n";
- close MD5out;
-
- return $reply;
-}
-
-sub ReadBinaryPrompt ($) {
- my ($fd) = @_;
-
- my $buffer = " ";
- my $count = read($fd, $buffer, 5);
- if ($count == 0) {
- # no more packets to read
- return (0, "");
- }
-
- if ($count != 5) {
- # broken packet header
- return (-1, "");
- }
-
- my ($length, $control) = unpack("N C", $buffer);
- if ($length < 5) {
- # broken packet length
- return (-1, "");
- }
-
- my $data = "";
- $length -= 5;
- while ($count = read($fd, $buffer, $length)) {
- $data .= $buffer;
- if ($count != $length) {
- $length -= $count;
- next;
- }
-
- print STDERR "server: ". "data is [$data]\n";
-
- return ($control, $data);
- }
-
- # broken packet data
- return (-1, "");
-}
-
-sub WriteBinaryPrompt ($$$) {
- my ($fd, $control, $data) = @_;
-
- my $length = 5 + length($data);
- printf STDERR "server: ". "{%d|0x%.2x|%s}\n", $length, $control, $data;
- my $bp = pack("N C a*", $length, $control, $data);
- print $fd $bp;
-
- print STDERR "server: ". "control passed to agent\@here\n";
-}
-
-sub IdentifyLocalSecret ($) {
- my ($identifier) = @_;
- my $secret;
-
- my $whoami = `/usr/bin/whoami` ; chomp $whoami;
- if (open SECRETS, "< " .(getpwuid($<))[7]. "/.secret\@here") {
- my $line;
- while (defined ($line = <SECRETS>)) {
- my ($id, $sec) = split /[\s]/, $line;
- if ((defined $id) && ($id eq $identifier)) {
- $secret = $sec;
- last;
- }
- }
- close SECRETS;
- }
-
- return $secret;
-}
-