Files
Arquivotheca.Solaris-2.5/lib/libauth/ia_framework.c
seta75D 7c4988eac0 Init
2021-10-11 19:38:01 -03:00

1091 lines
22 KiB
C
Executable File

/*
* Copyright (c) 1992, by Sun Microsystems, Inc.
*/
#ident "@(#)ia_framework.c 1.37 95/02/17 SMI" /* */
#include <syslog.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utmpx.h>
#include <string.h>
#include <malloc.h>
#include <unistd.h>
#include <security/ia_appl.h>
#include <security/ia_schemes.h>
#include <security/ia_switch.h>
#define dlopen _dlopen
#define dlclose _dlclose
#define dlsym _dlsym
#define dlerror _dlerror
/* PAM debugging */
#define PAM_DEBUG "/usr/lib/security/pam_debug"
int pam_debug = 0;
static struct scheme scheme; /* The scheme structure */
/* Function declaration */
/* lint: used by unix scheme */
int sa_getall();
int ia_set_item();
int ia_get_item();
static struct pam_sdata *alloc_pam_buf();
static int istrlen();
static int open_scheme();
static int load_function();
static void clean_up();
/*
* load_scheme - Open and load the specified scheme, storing the
* address of the function at the address of **func.
* This code assumes that func is an address in
* the scheme structure. Note that *func
* also gets cleared. Also note that the code
* performs recovery by copying over the scheme structure
* if a dlopen or dlsym failure occurs.
*/
static int
load_scheme(type)
int type;
{
int error;
int err;
if (pam_debug)
syslog(LOG_DEBUG, "load_scheme(%d)\n", type);
/*
* Check in two places for the scheme (usr/lib/security or /etc/lib)
* (In single user mode /usr might not be mounted) and load all
* scheme functions in, if open scheme succeeds. Use default scheme
* if the scheme failed on dlopen() or if any one of the scheme
* function address cannot be resolved.
*/
err = IA_SUCCESS;
switch (type) {
case AM_SCHEME:
if ((error = open_scheme(AM_SCHEME_LIB)) == 0 ||
(error = open_scheme(AM_SCHEME_ETC)) == 0) {
err = load_function(SA_AUTH_USER,
&scheme.sa_auth_user);
if (err != IA_SUCCESS)
return (err);
err = load_function(SA_SETCRED,
&scheme.sa_setcred);
if (err != IA_SUCCESS)
return (err);
if (pam_debug)
syslog(LOG_DEBUG, "AM_SCHEME load success\n");
return (IA_SUCCESS);
}
if (pam_debug)
syslog(LOG_DEBUG, "AM_SCHEME load failure\n");
break;
case EM_SCHEME:
if ((error = open_scheme(EM_SCHEME_LIB)) == 0 ||
(error = open_scheme(EM_SCHEME_ETC)) == 0) {
err = load_function(SA_AUTH_ACCTMG,
&scheme.sa_auth_acctmg);
if (err != IA_SUCCESS)
return (err);
if (pam_debug)
syslog(LOG_DEBUG, "EM_SCHEME load success\n");
return (IA_SUCCESS);
}
if (pam_debug)
syslog(LOG_DEBUG, "EM_SCHEME load failure\n");
break;
case PM_SCHEME:
if ((error = open_scheme(PM_SCHEME_LIB)) == 0 ||
(error = open_scheme(PM_SCHEME_ETC)) == 0) {
err = load_function(SA_SET_AUTHTOKATTR,
&scheme.sa_set_authtokattr);
if (err != IA_SUCCESS)
return (err);
err = load_function(SA_GET_AUTHTOKATTR,
&scheme.sa_get_authtokattr);
if (err != IA_SUCCESS)
return (err);
err = load_function(SA_CHAUTHTOK,
&scheme.sa_chauthtok);
if (err != IA_SUCCESS)
return (err);
if (pam_debug)
syslog(LOG_DEBUG, "PM_SCHEME load success\n");
return (IA_SUCCESS);
}
if (pam_debug)
syslog(LOG_DEBUG, "PM_SCHEME load failure\n");
break;
case SM_SCHEME:
if ((error = open_scheme(SM_SCHEME_LIB)) == 0 ||
(error = open_scheme(SM_SCHEME_ETC)) == 0) {
err = load_function(SA_OPEN_SESSION,
&scheme.sa_open_session);
if (err != IA_SUCCESS)
return (err);
err = load_function(SA_CLOSE_SESSION,
&scheme.sa_close_session);
if (err != IA_SUCCESS)
return (err);
if (pam_debug)
syslog(LOG_DEBUG, "SM_SCHEME load success\n");
return (IA_SUCCESS);
}
if (pam_debug)
syslog(LOG_DEBUG, "SM_SCHEME load failure\n");
break;
case XM_SCHEME:
if ((error = open_scheme(XM_SCHEME_LIB)) == 0 ||
(error = open_scheme(XM_SCHEME_ETC)) == 0) {
err = load_function(SA_AUTH_NETUSER,
&scheme.sa_auth_netuser);
if (err != IA_SUCCESS)
return (err);
err = load_function(SA_AUTH_PORT,
&scheme.sa_auth_port);
if (err != IA_SUCCESS)
return (err);
if (pam_debug)
syslog(LOG_DEBUG, "XM_SCHEME load success\n");
return (IA_SUCCESS);
}
if (pam_debug)
syslog(LOG_DEBUG, "XM_SCHEME load failure\n");
break;
default:
return (IA_DLFAIL);
}
return (error);
}
/*
* open_scheme - Open the scheme AUTH_SCHEME, first checking for
* propers modes and ownerships on the file.
*/
static int
open_scheme(scheme_so)
char *scheme_so;
{
struct stat stb;
char *errmsg;
if (pam_debug)
syslog(LOG_DEBUG, "open_scheme(%s)", scheme_so);
/*
* Stat the file so we can check modes and ownerships
*/
if (stat(scheme_so, &stb) < 0) {
if (pam_debug)
syslog(LOG_DEBUG, "open_scheme: stat() failed\n");
return (1);
}
/*
* Check the ownership of the file
*/
if (stb.st_uid != (uid_t)0) {
if (pam_debug)
syslog(LOG_DEBUG, "open_scheme: owner not root\n");
return (1);
}
/*
* Check the modes on the file
*/
if (stb.st_mode&S_IWGRP) {
if (pam_debug)
syslog(LOG_DEBUG,
"open_scheme: file writeable by group\n");
return (1);
}
if (stb.st_mode&S_IWOTH) {
if (pam_debug)
syslog(LOG_DEBUG,
"open_scheme: file writeable by others\n");
return (1);
}
/*
* Perform the dlopen()
*/
scheme.handle = (void *) dlopen(scheme_so, RTLD_LAZY);
if (scheme.handle == NULL) {
errmsg = (char *) dlerror();
if (pam_debug)
syslog(LOG_DEBUG, "open_scheme: dlopen() failed\n");
return (1);
}
return (0);
}
/*
* load_function - Call dlsym() to resolve the function address
*/
static int
load_function(name, func)
char *name;
int (**func)();
{
char *errmsg = NULL;
if (pam_debug)
syslog(LOG_DEBUG, "load_function(%s)\n", name);
*func = (int (*)())dlsym(scheme.handle, name);
if (*func == NULL) {
errmsg = (char *) dlerror();
if (pam_debug)
syslog(LOG_DEBUG, "load_function: dlsym() failed, %s\n",
errmsg != NULL ? errmsg : "");
return (IA_SYMFAIL);
}
return (IA_SUCCESS);
}
/*
* ia_XXXXX routines
*
* These are the entry points to the authentication switch
* When adding a new ia_ function add it here.
*/
int
ia_set_authtokattr(iah, sa_setattr, ia_statusp, rep, domain)
void *iah;
char **sa_setattr;
struct ia_status *ia_statusp;
int rep;
char *domain;
{
int error;
if (pam_debug)
syslog(LOG_DEBUG, "ia_set_authtokattr()\n");
ia_statusp->iast_status = 0;
(void) memset((void *) ia_statusp->iast_info, 0, 128);
if (scheme.sa_set_authtokattr == NULL)
if ((error = load_scheme(PM_SCHEME)) != IA_SUCCESS) {
scheme.sa_set_authtokattr = NULL;
return (error);
}
error = (scheme.sa_set_authtokattr(iah, sa_setattr, ia_statusp, rep,
domain));
return (error);
}
int
ia_get_authtokattr(iah, ga_getattr, ia_statusp, rep, domain)
void *iah;
char ***ga_getattr;
struct ia_status *ia_statusp;
int rep;
char *domain;
{
int error;
if (pam_debug)
syslog(LOG_DEBUG, "ia_get_authtokattr()\n");
ia_statusp->iast_status = 0;
(void) memset((void *) ia_statusp->iast_info, 0, 128);
if (scheme.sa_get_authtokattr == NULL)
if ((error = load_scheme(PM_SCHEME)) != IA_SUCCESS) {
scheme.sa_get_authtokattr = NULL;
return (error);
}
error = (scheme.sa_get_authtokattr(iah, ga_getattr, ia_statusp, rep,
domain));
return (error);
}
int
ia_chauthtok(iah, ia_statusp, rep, domain)
void *iah;
struct ia_status *ia_statusp;
int rep;
char *domain;
{
int error;
if (pam_debug)
syslog(LOG_DEBUG, "ia_chauthtok()\n");
ia_statusp->iast_status = 0;
(void) memset((void *) ia_statusp->iast_info, 0, 128);
if (scheme.sa_chauthtok == NULL)
if ((error = load_scheme(PM_SCHEME)) != IA_SUCCESS) {
scheme.sa_chauthtok = NULL;
return (error);
}
error = (scheme.sa_chauthtok(iah, ia_statusp, rep, domain));
return (error);
}
int
ia_auth_netuser(iah, ruser, ia_statusp)
void *iah;
char *ruser;
struct ia_status *ia_statusp;
{
int error;
if (pam_debug)
syslog(LOG_DEBUG, "ia_auth_netuser()\n");
ia_statusp->iast_status = 0;
(void) memset((void *) ia_statusp->iast_info, 0, 128);
if (scheme.sa_auth_netuser == NULL)
if ((error = load_scheme(XM_SCHEME)) != IA_SUCCESS) {
scheme.sa_auth_netuser = NULL;
return (error);
}
error = (scheme.sa_auth_netuser(iah, ruser, ia_statusp));
return (error);
}
int
ia_auth_user(iah, flags, pwd, ia_statusp)
void *iah;
int flags;
struct passwd **pwd;
struct ia_status *ia_statusp;
{
int error;
if (pam_debug)
syslog(LOG_DEBUG, "ia_auth_user(%x, %x, %x, %x)\n",
iah, flags, pwd, ia_statusp);
ia_statusp->iast_status = 0;
(void) memset((void *) ia_statusp->iast_info, 0, 128);
if (scheme.sa_auth_user == NULL)
if ((error = load_scheme(AM_SCHEME)) != IA_SUCCESS) {
scheme.sa_auth_user = NULL;
return (error);
}
error = (scheme.sa_auth_user(iah, flags, pwd, ia_statusp));
if (pam_debug)
syslog(LOG_DEBUG, "ia_auth_user: error %d\n", error);
return (error);
}
int
ia_auth_port(iah, flags, ia_statusp)
void *iah;
int flags;
struct ia_status *ia_statusp;
{
int error;
if (pam_debug)
syslog(LOG_DEBUG, "ia_auth_port()\n");
ia_statusp->iast_status = 0;
(void) memset((void *) ia_statusp->iast_info, 0, 128);
if (scheme.sa_auth_port == NULL)
if ((error = load_scheme(XM_SCHEME)) != IA_SUCCESS) {
scheme.sa_auth_port = NULL;
return (error);
}
error = (scheme.sa_auth_port(iah, flags, ia_statusp));
return (error);
}
int
ia_auth_acctmg(iah, flags, pwd, ia_statusp)
void *iah;
int flags;
struct passwd **pwd;
struct ia_status *ia_statusp;
{
int error;
if (pam_debug)
syslog(LOG_DEBUG, "ia_auth_acctmg()\n");
ia_statusp->iast_status = 0;
(void) memset((void *) ia_statusp->iast_info, 0, 128);
if (scheme.sa_auth_acctmg == NULL)
if ((error = load_scheme(EM_SCHEME)) != IA_SUCCESS) {
scheme.sa_auth_acctmg = NULL;
return (error);
}
error = (scheme.sa_auth_acctmg(iah, flags, pwd, ia_statusp));
return (error);
}
#define INIT_PROC_PID 1
#define SCPYN(a, b) (void) strncpy(a, b, sizeof (a))
#define min(a, b) (((a) < (b)) ? (a) : (b))
int
ia_open_session(iah, flags, type, id, ia_statusp)
void *iah;
int flags;
int type;
char id[];
struct ia_status *ia_statusp;
{
int error;
int tmplen;
struct utmpx *u = (struct utmpx *)0;
struct utmpx utmp;
char *ttyntail;
char *program, *user, *ttyn, *rhost;
struct ia_conv *ia_convp;
int err = 0;
if (pam_debug)
syslog(LOG_DEBUG, "ia_open_session(%d)\n", type);
ia_statusp->iast_status = 0;
(void) memset((void *) ia_statusp->iast_info, 0, 128);
if (scheme.sa_open_session == NULL)
if ((error = load_scheme(SM_SCHEME)) != IA_SUCCESS) {
scheme.sa_open_session = NULL;
return (error);
}
if (error = (scheme.sa_open_session(iah, flags, type, id, ia_statusp)))
return (error);
(void) memset((void *)&utmp, 0, sizeof (utmp));
if ((err = sa_getall(iah, &program, &user, &ttyn, &rhost, &ia_convp))
!= IA_SUCCESS)
return (err);
(void) time(&utmp.ut_tv.tv_sec);
utmp.ut_pid = getpid();
if (rhost != NULL && rhost[0] != '\0') {
(void) strcpy(utmp.ut_host, rhost);
utmp.ut_syslen = (tmplen = strlen(rhost)) ?
min(tmplen + 1, sizeof (utmp.ut_host)) : 0;
} else {
(void) memset(utmp.ut_host, 0, sizeof (utmp.ut_host));
utmp.ut_syslen = 0;
}
(void) strcpy(utmp.ut_user, user);
/*
* Copy in the name of the tty minus the "/dev/" if a /dev/ is
* in the path name.
*/
if (!(flags&IS_LOGIN))
SCPYN(utmp.ut_line, ttyn);
ttyntail = ttyn;
utmp.ut_type = type;
if (id != NULL)
(void) memcpy(utmp.ut_id, id, sizeof (utmp.ut_id));
if (flags == IS_NOLOG) {
updwtmpx(WTMPX_FILE, &utmp);
} else {
/*
* Go through each entry one by one, looking only at INIT,
* LOGIN or USER Processes. Use the entry found if flags == 0
* and the line name matches, or if the process ID matches if
* the UPDATE_ENT flag is set. The UPDATE_ENT flag is mainly
* for login which normally only wants to update an entry if
* the pid fields matches.
*/
if (flags & IS_LOGIN) {
while ((u = getutxent()) != NULL) {
if ((u->ut_type == INIT_PROCESS ||
u->ut_type == LOGIN_PROCESS ||
u->ut_type == USER_PROCESS) &&
((flags == IS_LOGIN && ttyn != NULL &&
strncmp(u->ut_line, ttyntail,
sizeof (u->ut_line)) == 0) ||
u->ut_pid == utmp.ut_pid)) {
if (ttyn)
SCPYN(utmp.ut_line,
(ttyn + sizeof ("/dev/") - 1));
if (id == NULL) {
(void) memcpy(utmp.ut_id, u->ut_id,
sizeof (utmp.ut_id));
}
(void) pututxline(&utmp);
break;
}
} /* end while */
endutxent(); /* Close utmp file */
}
if (u == (struct utmpx *)NULL) {
/* audit_login_main11(); */
if (flags & IS_UPDATE_ENT)
err = IA_NOENTRY;
else
(void) makeutx(&utmp);
}
else
updwtmpx(WTMPX_FILE, &utmp);
}
return (err);
}
int
ia_close_session(iah, flags, pid, status, id, ia_statusp)
void *iah;
int flags;
pid_t pid;
int status;
char id[];
struct ia_status *ia_statusp;
{
int error;
struct utmpx *up;
struct utmpx ut;
int err = 0;
char *ttyn;
if (pam_debug)
syslog(LOG_DEBUG, "ia_close_session()\n");
ia_statusp->iast_status = 0;
(void) memset(ia_statusp->iast_info, 0, 128);
if (scheme.sa_close_session == NULL)
if ((error = load_scheme(SM_SCHEME)) != IA_SUCCESS) {
scheme.sa_close_session = NULL;
return (error);
}
/*
* do we want to do any utmp processing?
*/
if (flags & IS_NOOP) {
if (error = (scheme.sa_close_session(iah, flags, pid, status,
id, ia_statusp))) {
return (error);
}
return (IA_SUCCESS);
}
if (pid == 0)
pid = (int) getpid();
if (flags == IS_NOLOG) { /* only write to wtmp files */
/* clear utmpx entry */
(void) memset((char *)&ut, 0, sizeof (ut));
if (id != NULL)
(void) memcpy(ut.ut_id, id, sizeof (ut.ut_id));
if ((err = ia_get_item(iah, IA_TTYN, (void **) &ttyn)) < 0)
return (-err);
if (ttyn != NULL && *ttyn != '\0') {
if (strstr(ttyn, "/dev/") != NULL)
(void) strncpy(ut.ut_line, (ttyn+sizeof ("/dev/")-1),
sizeof (ut.ut_line));
else
(void) strncpy(ut.ut_line, ttyn,
sizeof (ut.ut_line));
}
ut.ut_pid = pid;
ut.ut_type = DEAD_PROCESS;
ut.ut_exit.e_termination = 0;
ut.ut_exit.e_exit = 0;
ut.ut_syslen = 1;
(void) gettimeofday(&ut.ut_tv, NULL);
updwtmpx(WTMPX_FILE, &ut);
if (error = (scheme.sa_close_session(iah, flags, pid, status,
id, ia_statusp))) {
if (pam_debug)
syslog(LOG_DEBUG,
"ia_close: close session error: %d\n",
error);
return (error);
}
return (IA_SUCCESS);
} else {
setutxent();
while (up = getutxent()) {
if (up->ut_pid == pid) {
if (up->ut_type == DEAD_PROCESS) {
/*
* Cleaned up elsewhere.
*/
endutxent();
return (0);
}
(void) ia_set_item(iah, IA_USER, up->ut_user);
(void) ia_set_item(iah, IA_TTYN, up->ut_line);
(void) ia_set_item(iah, IA_RHOST, up->ut_host);
up->ut_type = DEAD_PROCESS;
up->ut_exit.e_termination = status & 0xff;
up->ut_exit.e_exit = (status >> 8) & 0xff;
if (id != NULL)
(void) memcpy(up->ut_id, id,
sizeof (up->ut_id));
(void) time(&up->ut_tv.tv_sec);
/*
* For init (Process ID 1) we don't write to
* init's pipe, since we are init.
*/
if (getpid() == INIT_PROC_PID) {
(void) pututxline(up);
/*
* Now attempt to add to the end of the
* wtmp and wtmpx files. Do not create
* if they don't already exist.
*/
updwtmpx("wtmpx", up);
} else {
if (modutx(up) == NULL) {
syslog(LOG_INFO,
"\tmodutx failed");
/*
* Since modutx failed we'll
* write out the new entry
* ourselves.
*/
(void) pututxline(up);
updwtmpx("wtmpx", up);
}
}
endutxent();
if (error = (scheme.sa_close_session(iah, flags,
pid, status, id, ia_statusp))) {
if (pam_debug)
syslog(LOG_DEBUG,
"ia_close: close session error: %d\n",
error);
return (error);
}
return (0);
}
}
endutxent();
return (IA_NOENTRY);
}
}
int
ia_setcred(iah, flags, uid, gid, ngroups, grouplist, ia_statusp)
void *iah;
int flags;
uid_t uid;
gid_t gid;
int ngroups;
gid_t *grouplist;
struct ia_status *ia_statusp;
{
int error;
if (pam_debug)
syslog(LOG_DEBUG, "ia_setcred()\n");
ia_statusp->iast_status = 0;
(void) memset(ia_statusp->iast_info, 0, 128);
if (scheme.sa_setcred == NULL)
if ((error = load_scheme(AM_SCHEME)) != IA_SUCCESS) {
scheme.sa_setcred = NULL;
return (error);
}
error = (scheme.sa_setcred(iah, flags, uid, gid, ngroups,
grouplist, ia_statusp));
return (error);
}
/*
* ia_start - initiate an authentication transaction and
* set parameter values to be used during the
* transaction
*/
int
ia_start(program, user, ttyn, rhost, ia_conv, iah)
char *program, *user, *ttyn, *rhost;
struct ia_conv *ia_conv;
void **iah;
{
struct stat statbuf;
int err;
/* turn on PAM debug if "magic" file exists */
if (stat(PAM_DEBUG, &statbuf) == 0) {
pam_debug = 1;
openlog("PAM", LOG_CONS|LOG_NDELAY, LOG_AUTH);
}
if (pam_debug)
syslog(LOG_DEBUG, "ia_start(%s %s %s %s %x %x)\n",
program, (user)?user:"no-user",
(ttyn)?ttyn:"no-ttyn",
(rhost)?rhost:"no-rhost",
ia_conv, iah);
if ((*iah = (void *) alloc_pam_buf()) == NULL)
return (IA_BUFERR);
if (pam_debug)
syslog(LOG_DEBUG, "ia_start: alloc_pam_buf() completed\n");
if ((err = ia_set_item((void *) *iah, IA_PROGRAM, (void *)program))
!= 0) {
clean_up(*iah);
return (err);
}
if ((err = ia_set_item((void *) *iah, IA_USER, (void *) user)) != 0) {
clean_up(*iah);
return (err);
}
if ((err = ia_set_item((void *) *iah, IA_TTYN, (void *) ttyn)) != 0) {
clean_up(*iah);
return (err);
}
if ((err = ia_set_item((void *) *iah, IA_RHOST, (void *) rhost)) != 0) {
clean_up(*iah);
return (err);
}
if ((err = ia_set_item((void *) *iah, IA_CONV, (void *) ia_conv))
!= 0) {
clean_up(*iah);
return (err);
}
return (IA_SUCCESS);
}
/*
* sa_getall - read the value of all parameters specified in
* the initial call to ia_start(), this is
* called only by the scheme
*/
int
sa_getall(iah, program, user, ttyn, rhost, ia_conv)
void * iah;
char **program, **user, **ttyn, **rhost;
struct ia_conv **ia_conv;
{
int err = 0;
if (pam_debug)
syslog(LOG_DEBUG, "sa_getall()\n");
if (program != NULL)
if ((err = ia_get_item(iah, IA_PROGRAM, (void **) program)) < 0)
return (-err);
if (user != NULL)
if ((err = ia_get_item(iah, IA_USER, (void **) user)) < 0)
return (-err);
if (ttyn != NULL)
if ((err = ia_get_item(iah, IA_TTYN, (void **) ttyn)) < 0)
return (-err);
if (rhost != NULL)
if ((err = ia_get_item(iah, IA_RHOST, (void **) rhost)) < 0)
return (-err);
if (ia_conv != NULL)
if ((err = ia_get_item(iah, IA_CONV, (void **) ia_conv)) < 0)
return (-err);
if (err < 0)
return (-err);
else
return (0);
}
/*
* ia_get_item - read the value of a parameter specified in
* the initial call to ia_start()
*/
int
ia_get_item(iahp, item_type, item)
void *iahp;
int item_type;
void **item;
{
struct pam_item *pip;
struct pam_sdata *iah = (struct pam_sdata *) iahp;
if (pam_debug)
syslog(LOG_DEBUG, "ia_get_item(%d)\n", item_type);
/*
* Get the buffer specified by this ia descriptor
*/
if (iah == NULL)
return (-IA_BUFERR);
if (item_type <= 0 || item_type >= IA_MAX_ITEMS)
return (-IA_BUFERR);
pip = &(iah->ps_item[item_type]);
*item = pip->pi_addr;
return (pip->pi_size);
}
/*
* ia_set_item - set the value of a parameter specified in
* the initial call to ia_start()
*/
int
ia_set_item(iahp, item_type, item)
void *iahp;
int item_type;
void *item;
{
struct pam_item *pip;
struct pam_sdata *iah = (struct pam_sdata *) iahp;
int size;
if (pam_debug)
syslog(LOG_DEBUG, "ia_set_item(%d)\n", item_type);
/*
* Check that this iah is in range
*/
if (iah == NULL)
return (IA_BUFERR);
/*
* Check that item_type is within valid range
*/
if (item_type <= 0 || item_type >= IA_MAX_ITEMS)
return (IA_BUFERR);
switch (item_type) {
case IA_PROGRAM:
case IA_USER:
case IA_TTYN:
case IA_RHOST:
case IA_AUTHTOK:
size = istrlen((char *) item);
break;
case IA_CONV:
size = sizeof (struct ia_conv);
break;
default:
return (IA_BUFERR);
}
pip = &(iah->ps_item[item_type]);
/*
* Allocate space if this is the first time we're storing the object
* else call realloc() if space is already allocated
*/
if (pip->pi_addr == NULL) {
if ((pip->pi_addr = (void *) malloc(
(unsigned int) size+1)) == NULL)
return (IA_BUFERR);
} else
if ((pip->pi_addr = (void *)realloc(pip->pi_addr,
(unsigned int) size+1)) == NULL)
return (IA_BUFERR);
if (item != NULL) {
(void) memcpy(pip->pi_addr, item, (unsigned int) size);
((char *) pip->pi_addr)[size] = '\0';
} else
((char *)pip->pi_addr)[0] = '\0';
pip->pi_size = size;
return (IA_SUCCESS);
}
/*
* ia_end - terminate an authentication transaction
*/
int
ia_end(iahp)
void *iahp;
{
int i;
struct pam_sdata *iah = (struct pam_sdata *) iahp;
if (pam_debug)
syslog(LOG_DEBUG, "ia_end()\n");
for (i = 0; i < IA_MAX_ITEMS; i++)
free(iah->ps_item[i].pi_addr);
free(iahp);
/* end syslog reporting */
if (pam_debug)
closelog();
return (IA_SUCCESS);
}
static struct pam_sdata *
alloc_pam_buf()
{
struct pam_sdata *pdp;
if (pam_debug)
syslog(LOG_DEBUG, "alloc_pam_buf()\n");
pdp = (struct pam_sdata *) malloc(sizeof (struct pam_sdata));
if (pdp == NULL)
return (NULL);
if (pam_debug) {
syslog(LOG_DEBUG, "alloc_pam_buf(): almost completed\n");
syslog(LOG_DEBUG, "alloc_pam_buf(): sizeof(pdp) = %d\n",
sizeof (pdp));
}
(void) memset(pdp, 0, sizeof (struct pam_sdata));
return (pdp);
}
static int
istrlen(str)
char *str;
{
if (str == NULL)
return (1);
else
return (strlen(str));
}
/*
* clean_up - free allocated storage before retrun when ia_start() failed
*/
static void
clean_up(iahp)
void *iahp;
{
int i;
struct pam_sdata *iah = (struct pam_sdata *) iahp;
for (i = 0; i < IA_MAX_ITEMS; i++) {
if (iah->ps_item[i].pi_addr != NULL)
free(iah->ps_item[i].pi_addr);
}
free(iahp);
}
/*
* free_resp():
* free storage for responses used in the call back "ia_conv" functions
* Bug fix due to program *_conv() routines calling scheme free_resp().
*/
void
free_resp(num_msg, resp)
int num_msg;
struct ia_response *resp;
{
int i;
struct ia_response *r;
r = resp;
for (i = 0; i < num_msg; i++, r++) {
free(r->resp);
}
free(resp);
}