462 lines
12 KiB
C
462 lines
12 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $TOG: pam_svc.c /main/5 1997/06/04 16:30:21 samborn $ */
|
|
/*******************************************************************************
|
|
**
|
|
** pam_svc.c 1.10 95/11/25
|
|
**
|
|
** Copyright 1993, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
|
|
**
|
|
** This file contains procedures specific to dtlogin's use of
|
|
** PAM (Pluggable Authentication Module) security library.
|
|
**
|
|
*******************************************************************************/
|
|
/* *
|
|
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
|
|
* (c) Copyright 1993, 1994 International Business Machines Corp. *
|
|
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc. *
|
|
* (c) Copyright 1993, 1994 Novell, Inc. *
|
|
*/
|
|
|
|
/*
|
|
* Header Files
|
|
*/
|
|
|
|
#include <utmpx.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <dirent.h>
|
|
#include <sys/param.h>
|
|
#include <pwd.h>
|
|
#include <security/pam_appl.h>
|
|
#include "pam_svc.h"
|
|
#include "dm.h"
|
|
#include "solaris.h"
|
|
|
|
/*
|
|
* Local function declarations
|
|
*/
|
|
|
|
static int login_conv(int num_msg, struct pam_message **msg,
|
|
struct pam_response **response, void *appdata_ptr);
|
|
|
|
static char* create_devname(char* short_devname);
|
|
|
|
|
|
|
|
/*
|
|
* Local structures and variables
|
|
*/
|
|
|
|
static struct pam_conv pam_conv = {login_conv, NULL};
|
|
static char *saved_user_passwd;
|
|
static pam_handle_t *pamh = NULL;
|
|
static int pam_auth_trys = 0;
|
|
|
|
/****************************************************************************
|
|
* PamInit
|
|
*
|
|
* Initialize or Update PAM datastructures.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
PamInit(char* prog_name,
|
|
char* user,
|
|
char* line_dev,
|
|
char* display_name)
|
|
{
|
|
int status=PAM_SUCCESS;
|
|
|
|
if (!pamh) {
|
|
/* Open PAM (Plugable Authentication module ) connection */
|
|
status = pam_start( prog_name, user, &pam_conv, &pamh );
|
|
if (status != PAM_SUCCESS) {
|
|
Debug("PamInit: pam_start error=%d\n", status);
|
|
pamh = NULL;
|
|
} else {
|
|
Debug("PamInit: pam_start success\n");
|
|
}
|
|
} else {
|
|
if (prog_name) pam_set_item(pamh, PAM_SERVICE, prog_name);
|
|
if (user) pam_set_item(pamh, PAM_USER, user);
|
|
}
|
|
|
|
if (status == PAM_SUCCESS) {
|
|
if (line_dev) pam_set_item(pamh, PAM_TTY, line_dev);
|
|
if (display_name) pam_set_item(pamh, PAM_RHOST, display_name);
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* PamAuthenticate
|
|
*
|
|
* Authenticate that user / password combination is legal for this system
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
PamAuthenticate ( char* prog_name,
|
|
char* display_name,
|
|
char* user_passwd,
|
|
char* user,
|
|
char* line )
|
|
{
|
|
int status;
|
|
char* user_str = user ? user : "NULL";
|
|
char* line_str = line ? line : "NULL";
|
|
char* line_dev = create_devname(line_str);
|
|
|
|
Debug("PamAuthenticate: prog_name=%s\n", prog_name);
|
|
Debug("PamAuthenticate: display_name=%s\n", display_name);
|
|
Debug("PamAuthenticate: user=%s\n", user_str);
|
|
Debug("PamAuthenticate: line=%s\n", line_str);
|
|
Debug("PamAuthenticate: line_dev=%s\n", line_dev);
|
|
|
|
if (user_passwd) {
|
|
if (strlen(user_passwd) == 0) {
|
|
Debug("PamAuthenticate: user passwd empty\n");
|
|
} else {
|
|
Debug("PamAuthenticate: user passwd present\n");
|
|
}
|
|
}
|
|
else {
|
|
Debug("PamAuthenticate: user passwd NULL\n");
|
|
|
|
/* Password challenge required for dtlogin authentication */
|
|
return(PAM_AUTH_ERR);
|
|
}
|
|
|
|
status = PamInit(prog_name, user, line_dev, display_name);
|
|
|
|
if (status == PAM_SUCCESS) {
|
|
struct passwd *pwd;
|
|
|
|
saved_user_passwd = user_passwd;
|
|
status = pam_authenticate( pamh, 0 );
|
|
pam_auth_trys++;
|
|
|
|
if (status != PAM_SUCCESS) {
|
|
sleep(PAM_LOGIN_SLEEPTIME);
|
|
if (pam_auth_trys > PAM_LOGIN_MAXTRIES) {
|
|
sleep(PAM_LOGIN_DISABLETIME);
|
|
}
|
|
}
|
|
};
|
|
|
|
if (status != PAM_SUCCESS) {
|
|
Debug("PamAuthenticate: PAM error=%d\n", status);
|
|
if (pamh) {
|
|
Debug("PamAuthenticate: calling pam_end\n");
|
|
pam_end(pamh, PAM_ABORT);
|
|
pamh=NULL;
|
|
}
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* PamAccounting
|
|
*
|
|
* Work related to open and close of user sessions
|
|
****************************************************************************/
|
|
|
|
int
|
|
PamAccounting( char* prog_name,
|
|
char* display_name,
|
|
char* entry_id,
|
|
char* user,
|
|
char* line,
|
|
pid_t pid,
|
|
int entry_type,
|
|
int exitcode )
|
|
{
|
|
int session_type, status;
|
|
char *user_str = user ? user : "NULL";
|
|
char *line_str = line ? line : "NULL";
|
|
char *line_dev = create_devname(line_str);
|
|
char *tty_line;
|
|
|
|
Debug("PamAccounting: prog_name=%s\n", prog_name);
|
|
Debug("PamAccounting: display_name=%s\n", display_name);
|
|
Debug("PamAccounting: entry_id=%c %c %c %c\n", entry_id[0],
|
|
entry_id[1], entry_id[2], entry_id[3]);
|
|
Debug("PamAccounting: user=%s\n", user_str);
|
|
Debug("PamAccounting: line=%s\n", line_str);
|
|
Debug("PamAccounting: line_dev=%s\n", line_dev);
|
|
Debug("PamAccounting: pid=%d\n", pid);
|
|
Debug("PamAccounting: entry_type=%d\n", entry_type);
|
|
Debug("PamAccounting: exitcode=%d\n", exitcode);
|
|
|
|
/* Open Solaris PAM (Plugable Authentication module ) connection */
|
|
|
|
if (entry_type == ACCOUNTING) {
|
|
tty_line = line;
|
|
}
|
|
else {
|
|
tty_line = line_dev;
|
|
}
|
|
|
|
status = PamInit(prog_name, user, tty_line, display_name);
|
|
|
|
|
|
/* Session accounting */
|
|
|
|
if (status == PAM_SUCCESS) switch(entry_type) {
|
|
case USER_PROCESS:
|
|
/* New user session, open session accounting logs */
|
|
status = pam_open_session(pamh, 0);
|
|
if (status != PAM_SUCCESS) {
|
|
Debug("PamAccounting: USER_PROCESS open_session error=%d\n",
|
|
status);
|
|
}
|
|
session_type = SOLARIS_LOGIN;
|
|
status = solaris_setutmp_mgmt(user, tty_line, display_name,
|
|
session_type, entry_type, entry_id);
|
|
if (status != SOLARIS_SUCCESS) {
|
|
Debug("PamAccounting: USER_PRCESS set_utmp error=%d\n",
|
|
status);
|
|
}
|
|
break;
|
|
|
|
|
|
case ACCOUNTING:
|
|
/*
|
|
* User session has terminated, mark it DEAD and close
|
|
* the sessions accounting logs.
|
|
*/
|
|
status = pam_open_session(pamh, 0);
|
|
if (status != PAM_SUCCESS) {
|
|
Debug("PamAccounting: ACCOUNTING open_session error=%d\n",
|
|
status);
|
|
}
|
|
entry_type = DEAD_PROCESS;
|
|
session_type = SOLARIS_NOLOG;
|
|
status = solaris_setutmp_mgmt(user, tty_line, display_name,
|
|
session_type, entry_type, entry_id);
|
|
|
|
if (status != SOLARIS_SUCCESS) {
|
|
Debug("PamAccounting: ACCOUNTING set_utmp error=%d\n",
|
|
status);
|
|
}
|
|
/* Intentional fall thru */
|
|
|
|
|
|
case DEAD_PROCESS:
|
|
/* Cleanup account files for dead processes */
|
|
status = pam_close_session(pamh, 0);
|
|
if (status != PAM_SUCCESS) {
|
|
Debug("PamAccounting: DEAD_PROCES close_session error=%d\n",
|
|
status);
|
|
}
|
|
|
|
status = solaris_reset_utmp_mgmt(&user, &tty_line,
|
|
&display_name, 0,
|
|
entry_type, entry_id);
|
|
|
|
if (status != SOLARIS_SUCCESS) {
|
|
Debug("PamAccounting: DEAD_PROCESS reset_utmp error=%d\n",
|
|
status);
|
|
}
|
|
break;
|
|
|
|
|
|
case LOGIN_PROCESS:
|
|
default:
|
|
status = pam_open_session(pamh, 0);
|
|
if (status != PAM_SUCCESS) {
|
|
Debug("PamAccounting:LOGIN_PROCESS open_session error=%d\n",
|
|
status);
|
|
}
|
|
session_type = 0;
|
|
status = solaris_setutmp_mgmt(user, tty_line, display_name,
|
|
session_type, entry_type, entry_id);
|
|
if (status != SOLARIS_SUCCESS) {
|
|
Debug("PamAccounting: LOGIN_PROCESS set_utmp error=%d\n",
|
|
status);
|
|
}
|
|
break;
|
|
}
|
|
|
|
free(line_dev);
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* PamSetCred
|
|
*
|
|
* Set Users login credentials: uid, gid, and group lists
|
|
****************************************************************************/
|
|
|
|
int
|
|
PamSetCred(char* prog_name, char* user, uid_t uid, gid_t gid)
|
|
{
|
|
int cred_type, status;
|
|
char* user_str = user ? user : "NULL";
|
|
|
|
Debug("PamSetCred: prog_name=%s\n", prog_name);
|
|
Debug("PamSetCred: user=%s\n", user_str);
|
|
Debug("PamSetCred: uid=%d\n", uid);
|
|
Debug("PamSetCred: gid=%d\n", gid);
|
|
|
|
status = PamInit(prog_name, user, NULL, NULL);
|
|
|
|
/* Set users credentials */
|
|
|
|
if (status == PAM_SUCCESS && setgid(gid) == -1)
|
|
status = SOLARIS_BAD_GID;
|
|
|
|
if (status == PAM_SUCCESS &&
|
|
( !user) || (initgroups(user, gid) == -1) )
|
|
status = SOLARIS_INITGROUP_FAIL;
|
|
|
|
if (status == PAM_SUCCESS)
|
|
status = pam_setcred(pamh, PAM_ESTABLISH_CRED);
|
|
|
|
if (status == PAM_SUCCESS && (setuid(uid) == -1))
|
|
status = SOLARIS_BAD_UID;
|
|
|
|
if (status != PAM_SUCCESS) {
|
|
Debug("PamSetCred: user=%s, err=%d)\n", user, status);
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* create_devname
|
|
*
|
|
* A utility function. Takes short device name like "console" and returns
|
|
* a long device name like "/dev/console"
|
|
***************************************************************************/
|
|
|
|
static char*
|
|
create_devname(char* short_devname)
|
|
{
|
|
char* long_devname;
|
|
|
|
if (short_devname == NULL)
|
|
short_devname = "";
|
|
|
|
long_devname = (char *) malloc (strlen(short_devname) + 5);
|
|
|
|
if (long_devname == NULL)
|
|
return(NULL);
|
|
|
|
strcpy(long_devname,"/dev/");
|
|
strcat(long_devname, short_devname);
|
|
|
|
return(long_devname);
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* login_conv():
|
|
*
|
|
* This is a conv (conversation) function called from the PAM
|
|
* authentication scheme. It returns the user's password when requested by
|
|
* internal PAM authentication modules and also logs any internal PAM error
|
|
* messages.
|
|
*****************************************************************************/
|
|
|
|
static int
|
|
login_conv(int num_msg, struct pam_message **msg,
|
|
struct pam_response **response, void *appdata_ptr)
|
|
{
|
|
struct pam_message *m;
|
|
struct pam_response *r;
|
|
char *temp;
|
|
int k;
|
|
|
|
#ifdef lint
|
|
conv_id = conv_id;
|
|
#endif
|
|
if (num_msg <= 0)
|
|
return (PAM_CONV_ERR);
|
|
|
|
*response = (struct pam_response*)
|
|
calloc(num_msg, sizeof (struct pam_response));
|
|
if (*response == NULL)
|
|
return (PAM_CONV_ERR);
|
|
|
|
(void) memset(*response, 0, sizeof (struct pam_response));
|
|
|
|
k = num_msg;
|
|
m = *msg;
|
|
r = *response;
|
|
while (k--) {
|
|
|
|
switch (m->msg_style) {
|
|
|
|
case PAM_PROMPT_ECHO_OFF:
|
|
if (saved_user_passwd != NULL) {
|
|
r->resp = (char *) malloc(strlen(saved_user_passwd)+1);
|
|
if (r->resp == NULL) {
|
|
/* __pam_free_resp(num_msg, *response); */
|
|
*response = NULL;
|
|
return (PAM_CONV_ERR);
|
|
}
|
|
(void) strcpy(r->resp, saved_user_passwd);
|
|
r->resp_retcode=0;
|
|
}
|
|
|
|
m++;
|
|
r++;
|
|
break;
|
|
|
|
|
|
case PAM_ERROR_MSG:
|
|
if (m->msg != NULL) {
|
|
Debug ("login_conv ERROR: %s\n", m->msg);
|
|
}
|
|
m++;
|
|
r++;
|
|
break;
|
|
|
|
case PAM_TEXT_INFO:
|
|
if (m->msg != NULL) {
|
|
Debug ("login_conv INFO: %s\n", m->msg);
|
|
}
|
|
m++;
|
|
r++;
|
|
break;
|
|
|
|
default:
|
|
Debug ("login_conv: Unexpected case %d\n",
|
|
m->msg_style);
|
|
break;
|
|
}
|
|
}
|
|
return (PAM_SUCCESS);
|
|
}
|