From efd31890b5ed496a5a00c08a262da240e66a4ddc Mon Sep 17 00:00:00 2001 From: Steve Langasek Date: Thu, 3 Jan 2019 12:44:11 -0800 Subject: New upstream version 0.76 --- libpamc/.cvsignore | 3 - libpamc/License | 42 --- libpamc/Makefile | 107 ------ libpamc/include/security/pam_client.h | 197 ---------- libpamc/libpamc.h | 63 ---- libpamc/pamc_client.c | 189 ---------- libpamc/pamc_converse.c | 211 ----------- libpamc/pamc_load.c | 477 ------------------------ libpamc/test/agents/secret@here | 308 ---------------- libpamc/test/modules/Makefile | 9 - libpamc/test/modules/pam_secret.c | 670 ---------------------------------- libpamc/test/regress/Makefile | 7 - libpamc/test/regress/run_test.sh | 6 - libpamc/test/regress/test.libpamc.c | 342 ----------------- libpamc/test/regress/test.secret@here | 152 -------- 15 files changed, 2783 deletions(-) delete mode 100644 libpamc/.cvsignore delete mode 100644 libpamc/License delete mode 100644 libpamc/Makefile delete mode 100644 libpamc/include/security/pam_client.h delete mode 100644 libpamc/libpamc.h delete mode 100644 libpamc/pamc_client.c delete mode 100644 libpamc/pamc_converse.c delete mode 100644 libpamc/pamc_load.c delete mode 100755 libpamc/test/agents/secret@here delete mode 100644 libpamc/test/modules/Makefile delete mode 100644 libpamc/test/modules/pam_secret.c delete mode 100644 libpamc/test/regress/Makefile delete mode 100755 libpamc/test/regress/run_test.sh delete mode 100644 libpamc/test/regress/test.libpamc.c delete mode 100755 libpamc/test/regress/test.secret@here (limited to 'libpamc') 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 - * - * 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 -#include -#include - -/* 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 -#include -#include - -#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 - * - */ - -#ifndef LIBPAMC_H -#define LIBPAMC_H - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#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; /* 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 - * - * 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 - * - * 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) - || !__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 - * - * 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 = )) { - 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 = ; - ($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 - */ - -/* - * WARNING: AS WRITTEN THIS CODE IS NOT SECURE. THE MD5 IMPLEMENTATION - * NEEDS TO BE INTEGRATED MORE NATIVELY. - */ - -/* #define DEBUG */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * 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 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 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|} */ - 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 {|} */ - 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; icurrent_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[||] */ - 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 {|md5[||]} */ - 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[||]} */ - - { - 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[||] - * - * 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 -#include -#include -#include - -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 = ; - ($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 = )) { - my ($id, $sec) = split /[\s]/, $line; - if ((defined $id) && ($id eq $identifier)) { - $secret = $sec; - last; - } - } - close SECRETS; - } - - return $secret; -} - -- cgit v1.2.3