969 lines
26 KiB
C
969 lines
26 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
|
|
*/
|
|
/* $XConsortium: solaris.c /main/4 1995/10/27 16:15:38 rswiston $ */
|
|
/*******************************************************************************
|
|
**
|
|
** solaris.c 1.15 95/09/10
|
|
**
|
|
** Copyright 1993, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
|
|
**
|
|
** This file contains procedures specific to Sun Solaris login
|
|
**
|
|
*******************************************************************************/
|
|
/* *
|
|
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
|
|
* (c) Copyright 1993, 1994 International Business Machines Corp. *
|
|
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
|
|
* (c) Copyright 1993, 1994 Novell, Inc. *
|
|
*/
|
|
/*******************************************************************************
|
|
**
|
|
** RESTRICTED CONFIDENTIAL INFORMATION:
|
|
**
|
|
** The information in this document is subject to special
|
|
** restrictions in a confidential disclosure agreement between
|
|
** HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
|
|
** document outside HP, IBM, Sun, USL, SCO, or Univel without
|
|
** Sun's specific written approval. This document and all copies
|
|
** and derivative works thereof must be returned or destroyed at
|
|
** Sun's request.
|
|
**
|
|
** Copyright 1994 Sun Microsystems, Inc. All rights reserved.
|
|
**
|
|
*******************************************************************************/
|
|
|
|
|
|
/*
|
|
* Header Files
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <utmpx.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <dirent.h>
|
|
#include <sys/param.h>
|
|
#include <pwd.h>
|
|
#include "solaris.h"
|
|
|
|
#ifdef SUNAUTH
|
|
#include <security/ia_appl.h>
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Local function declarations, structures, and variables
|
|
*/
|
|
|
|
static char* create_devname(char* short_devname);
|
|
static void dir_dev_acc(char *, uid_t, gid_t, mode_t, char *);
|
|
static void logindevperm(char *, uid_t, gid_t);
|
|
static void resetdevperm(char *);
|
|
|
|
#ifdef SUNAUTH
|
|
static int login_conv(int conv_id, int num_msg, struct ia_message **msg,
|
|
struct ia_response **response, void *appdata_ptr);
|
|
static void end_conv();
|
|
|
|
static struct ia_conv ia_conv = {login_conv, login_conv, end_conv, NULL};
|
|
static char *saved_user_passwd;
|
|
#endif SUNAUTH
|
|
|
|
|
|
/****************************************************************************
|
|
* solaris_setdevperm
|
|
*
|
|
* Modify permission of devices as specified in Solaris /etc/logindevperm file
|
|
****************************************************************************/
|
|
|
|
int
|
|
solaris_setdevperm(char* gettyLine, uid_t uid, gid_t gid)
|
|
{
|
|
char *devname = create_devname(gettyLine);
|
|
|
|
if (devname == NULL) {
|
|
Debug ("solaris_setdevperm: NULL devname\n");
|
|
return(0);
|
|
};
|
|
|
|
logindevperm(devname, uid, gid);
|
|
free(devname);
|
|
return(1);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* solaris_resetdevperm
|
|
*
|
|
* Reset permission on devices specified in /etc/logindevperm file
|
|
****************************************************************************/
|
|
|
|
int
|
|
solaris_resetdevperm(char* gettyLine)
|
|
{
|
|
char *devname = create_devname(gettyLine);
|
|
|
|
if (devname == NULL) {
|
|
Debug ("solaris_resetdevperm: NULL devname\n");
|
|
return(0);
|
|
}
|
|
|
|
resetdevperm(devname);
|
|
free(devname);
|
|
return(1);
|
|
}
|
|
|
|
|
|
#ifdef SUNAUTH
|
|
/****************************************************************************
|
|
* solaris_authentication
|
|
*
|
|
* Authenticate that user / password combination is legal for this system
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
solaris_authenticate ( char* prog_name,
|
|
char* display_name,
|
|
char* user_passwd,
|
|
char* user,
|
|
char* line )
|
|
{
|
|
int status;
|
|
struct ia_status out;
|
|
void *iah; /* PAM authentication handle */
|
|
char* user_str = user ? user : "NULL";
|
|
char* line_str = line ? line : "NULL";
|
|
char *line_dev = create_devname(line_str);
|
|
|
|
Debug("solaris_authenticate: prog_name=%s\n", prog_name);
|
|
Debug("solaris_authenticate: display_name=%s\n", display_name);
|
|
Debug("solaris_authenticate: user=%s\n", user_str);
|
|
Debug("solaris_authenticate: line=%s\n", line_str);
|
|
Debug("solaris_authenticate: line_dev=%s\n", line_dev);
|
|
|
|
if (user_passwd) {
|
|
if (strlen(user_passwd) == 0) {
|
|
Debug("solaris_authenticate: user passwd empty\n");
|
|
} else {
|
|
Debug("solaris_authenticate: user passwd present\n");
|
|
}
|
|
}
|
|
else {
|
|
Debug("solaris_authenticate: user passwd NULL\n");
|
|
|
|
/* Password challenge required for solaris authentication */
|
|
return(IA_AUTHTEST_FAIL);
|
|
}
|
|
|
|
/* Solaris BSM Audit trail */
|
|
|
|
audit_login_save_host(display_name);
|
|
audit_login_save_ttyn(line_dev);
|
|
audit_login_save_port();
|
|
|
|
/* Open Solaris PAM (Plugable Authentication module ) connection */
|
|
|
|
status = ia_start( prog_name, user, line_dev,
|
|
display_name, &ia_conv, &iah );
|
|
|
|
if (status == 0) {
|
|
int flags = AU_CHECK_PASSWD | AU_CONTINUE;
|
|
struct passwd *pwd;
|
|
|
|
saved_user_passwd = user_passwd;
|
|
status = ia_auth_user( iah, flags, &pwd, &out );
|
|
|
|
audit_login_save_pw(pwd);
|
|
|
|
if (status != 0) {
|
|
audit_login_bad_pw();
|
|
if (status == IA_MAXTRYS) {
|
|
audit_login_maxtrys();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (status != 0) {
|
|
Debug("solaris_authenticate: PAM error=%d\n", status);
|
|
}
|
|
|
|
ia_end(iah);
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* solaris_accounting
|
|
*
|
|
* Updates "utmp/utmpx: and "wtmp/wtmpx" system accounting entries
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
solaris_accounting( 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;
|
|
struct ia_status out;
|
|
void *iah; /* PAM authentication handle */
|
|
char* user_str = user ? user : "NULL";
|
|
char* line_str = line ? line : "NULL";
|
|
char *line_dev = create_devname(line_str);
|
|
|
|
Debug("solaris_accounting: prog_name=%s\n", prog_name);
|
|
Debug("solaris_accounting: display_name=%s\n", display_name);
|
|
Debug("solaris_accounting: entry_id=%c %c %c %c\n", entry_id[0],
|
|
entry_id[1], entry_id[2], entry_id[3]);
|
|
Debug("solaris_accounting: user=%s\n", user_str);
|
|
Debug("solaris_accounting: line=%s\n", line_str);
|
|
Debug("solaris_accounting: line_dev=%s\n", line_dev);
|
|
Debug("solaris_accounting: pid=%d\n", pid);
|
|
Debug("solaris_accounting: entry_type=%d\n", entry_type);
|
|
Debug("solaris_accounting: exitcode=%d\n", exitcode);
|
|
|
|
|
|
/* Open Solaris PAM (Plugable Authentication module ) connection */
|
|
|
|
if (entry_type == ACCOUNTING) {
|
|
status = ia_start(prog_name, user, line,
|
|
display_name, &ia_conv, &iah);
|
|
}
|
|
else {
|
|
status = ia_start(prog_name, user, line_dev,
|
|
display_name, &ia_conv, &iah);
|
|
}
|
|
|
|
|
|
/* Session accounting */
|
|
|
|
if (status != IA_SUCCESS) {
|
|
Debug("solaris_accounting: PAM error=%d)\n", status);
|
|
}
|
|
else {
|
|
switch(entry_type) {
|
|
|
|
case USER_PROCESS:
|
|
/* New user session, open session accounting logs */
|
|
session_type = IS_LOGIN;
|
|
status = ia_open_session(iah, session_type,
|
|
entry_type, entry_id, &out);
|
|
if (status == IA_SUCCESS) audit_login_success();
|
|
break;
|
|
|
|
|
|
case ACCOUNTING:
|
|
/*
|
|
* User session has terminated, mark it DEAD and close
|
|
* the sessions accounting logs.
|
|
*/
|
|
entry_type = DEAD_PROCESS;
|
|
session_type = IS_NOLOG;
|
|
status = ia_open_session(iah, session_type,
|
|
entry_type, entry_id, &out);
|
|
if (status != IA_SUCCESS) {
|
|
Debug("solaris_accounting: PAM check seuser error=%d\n",
|
|
status);
|
|
}
|
|
/* Intentional fall thru */
|
|
|
|
|
|
case DEAD_PROCESS:
|
|
/* Cleanup account files for dead processes */
|
|
status = ia_close_session(iah, 0, pid,
|
|
exitcode, entry_id, &out);
|
|
break;
|
|
|
|
|
|
case LOGIN_PROCESS:
|
|
default:
|
|
session_type = 0;
|
|
status = ia_open_session(iah, session_type,
|
|
entry_type, entry_id, &out);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (status != IA_SUCCESS) {
|
|
Debug("solaris_accounting: PAM session error=%d\n", status);
|
|
}
|
|
|
|
ia_end(iah);
|
|
free(line_dev);
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* solaris_setcred
|
|
*
|
|
* Set Users login credentials: uid, gid, and group lists
|
|
****************************************************************************/
|
|
|
|
int
|
|
solaris_setcred(char* prog_name, char* user, uid_t uid, gid_t gid)
|
|
{
|
|
int cred_type, status;
|
|
struct ia_status out;
|
|
void *iah; /* PAM authentication handle */
|
|
char* user_str = user ? user : "NULL";
|
|
|
|
Debug("solaris_setcred: prog_name=%s\n", prog_name);
|
|
Debug("solaris_setcred: user=%s\n", user_str);
|
|
Debug("solaris_setcred: uid=%d\n", uid);
|
|
Debug("solaris_setcred: gid=%d\n", gid);
|
|
|
|
|
|
/* Open PAM connection */
|
|
|
|
status = ia_start(prog_name, user, NULL, NULL, &ia_conv, &iah);
|
|
if (status != 0) {
|
|
Debug("solaris_setcred: PAM start error=%d\n", status);
|
|
return(status);
|
|
}
|
|
|
|
/* Set users credentials */
|
|
|
|
ia_set_item(iah, IA_AUTHTOK, saved_user_passwd);
|
|
|
|
cred_type = SC_INITGPS|SC_SETRID;
|
|
status = ia_setcred(iah, cred_type, uid, gid, 0, NULL, &out);
|
|
|
|
if (status != 0) {
|
|
Debug("solaris_setcred: user=%s, err=%d)\n", user, status);
|
|
}
|
|
|
|
ia_end(iah);
|
|
|
|
Debug("solaris_setcred: return status =%d\n", status);
|
|
|
|
return(status);
|
|
}
|
|
#endif SUNAUTH
|
|
|
|
|
|
/***************************************************************************
|
|
* 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);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* logindevperm
|
|
*
|
|
* change owner/group/permissions of devices list in /etc/logindevperm.
|
|
*
|
|
* This code is directly from Sun Solaris 5.3 login. Eventually this will
|
|
* be a fuction in a Solaris library. Till then, this is duplicate copy.
|
|
***************************************************************************/
|
|
|
|
#define LOGINDEVPERM "/etc/logindevperm"
|
|
#define DIRWILD "/*" /* directory wildcard */
|
|
#define DIRWLDLEN 2 /* strlen(DIRWILD) */
|
|
|
|
|
|
static void
|
|
logindevperm(char *ttyn, uid_t uid, gid_t gid)
|
|
{
|
|
char *field_delims = " \t\n";
|
|
char *permfile = LOGINDEVPERM;
|
|
char line[MAXPATHLEN];
|
|
char *console;
|
|
char *mode_str;
|
|
char *dev_list;
|
|
char *device;
|
|
char *ptr;
|
|
int mode;
|
|
FILE *fp;
|
|
size_t l;
|
|
int lineno;
|
|
|
|
if ((fp = fopen(permfile, "r")) == NULL)
|
|
return;
|
|
|
|
lineno = 0;
|
|
while (fgets(line, MAXPATHLEN, fp) != NULL) {
|
|
lineno++;
|
|
|
|
if ((ptr = strchr(line, '#')) != NULL)
|
|
*ptr = '\0'; /* handle comments */
|
|
|
|
if ((console = strtok(line, field_delims)) == NULL)
|
|
continue; /* ignore blank lines */
|
|
|
|
if (strcmp(console, ttyn) != 0)
|
|
continue; /* not our tty, skip */
|
|
|
|
mode_str = strtok((char *)NULL, field_delims);
|
|
if (mode_str == NULL) {
|
|
(void) fprintf(stderr,
|
|
"%s: line %d, invalid entry -- %s\n", permfile,
|
|
lineno, line);
|
|
continue;
|
|
}
|
|
|
|
/* convert string to octal value */
|
|
mode = strtol(mode_str, &ptr, 8);
|
|
if (mode < 0 || mode > 0777 || *ptr != '\0') {
|
|
(void) fprintf(stderr,
|
|
"%s: line %d, invalid mode -- %s\n", permfile,
|
|
lineno, mode_str);
|
|
continue;
|
|
}
|
|
|
|
dev_list = strtok((char *)NULL, field_delims);
|
|
if (dev_list == NULL) {
|
|
(void) fprintf(stderr,
|
|
"%s: line %d, %s -- empty device list\n",
|
|
permfile, lineno, console);
|
|
continue;
|
|
}
|
|
|
|
device = strtok(dev_list, ":");
|
|
while (device != NULL) {
|
|
l = strlen(device);
|
|
ptr = &device[l - DIRWLDLEN];
|
|
if ((l > DIRWLDLEN) && (strcmp(ptr, DIRWILD) == 0)) {
|
|
*ptr = '\0'; /* chop off wildcard */
|
|
dir_dev_acc(device, uid, gid, mode, permfile);
|
|
} else {
|
|
/*
|
|
* change the owner/group/permission;
|
|
* nonexistent devices are ignored
|
|
*/
|
|
if (chown(device, uid, gid) == -1) {
|
|
if (errno != ENOENT) {
|
|
(void) fprintf(stderr, "%s: ",
|
|
permfile);
|
|
perror(device);
|
|
}
|
|
} else {
|
|
if ((chmod(device, mode) == -1) &&
|
|
(errno != ENOENT)) {
|
|
(void) fprintf(stderr, "%s: ",
|
|
permfile);
|
|
perror(device);
|
|
}
|
|
}
|
|
}
|
|
device = strtok((char *)NULL, ":");
|
|
}
|
|
}
|
|
(void) fclose(fp);
|
|
}
|
|
|
|
/***************************************************************************
|
|
* dir_dev_acc
|
|
*
|
|
* Apply owner/group/perms to all files (except "." and "..") in a directory.
|
|
*
|
|
* This code is directly Sun Solaris 5.3 login. Eventually this will
|
|
* be internal to a Solaris library. Till then, this is a duplicate copy.
|
|
***************************************************************************/
|
|
|
|
static void
|
|
dir_dev_acc(char *dir, uid_t uid, gid_t gid, mode_t mode, char *permfile)
|
|
{
|
|
DIR *dirp;
|
|
struct dirent *direntp;
|
|
char *name, path[MAXPATHLEN];
|
|
|
|
dirp = opendir(dir);
|
|
if (dirp == NULL)
|
|
return;
|
|
|
|
while ((direntp = readdir(dirp)) != NULL) {
|
|
name = direntp->d_name;
|
|
if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0))
|
|
continue;
|
|
|
|
(void) sprintf(path, "%s/%s", dir, name);
|
|
if (chown(path, uid, gid) == -1) {
|
|
if (errno != ENOENT) {
|
|
(void) fprintf(stderr, "%s: ", permfile);
|
|
perror(path);
|
|
}
|
|
} else {
|
|
if ((chmod(path, mode) == -1) && (errno != ENOENT)) {
|
|
(void) fprintf(stderr, "%s: ", permfile);
|
|
perror(path);
|
|
}
|
|
}
|
|
}
|
|
(void) closedir(dirp);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* resetdevperm
|
|
*
|
|
* Clean up access of devices in /etc/logindevperm by resetting the
|
|
* owner/group/permissions back to the login pseudo user.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
extern struct passwd puser; /* pseudo_user password entry */
|
|
|
|
static void
|
|
resetdevperm(char *ttyn)
|
|
{
|
|
logindevperm(ttyn, puser.pw_uid, puser.pw_gid);
|
|
}
|
|
|
|
#ifdef SUNAUTH
|
|
/*****************************************************************************
|
|
* 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 conv_id, int num_msg, struct ia_message **msg,
|
|
struct ia_response **response, void *appdata_ptr)
|
|
{
|
|
struct ia_message *m;
|
|
struct ia_response *r;
|
|
char *temp;
|
|
int k;
|
|
|
|
#ifdef lint
|
|
conv_id = conv_id;
|
|
#endif
|
|
if (num_msg <= 0)
|
|
return (IA_CONV_FAILURE);
|
|
|
|
*response = (struct ia_response*)
|
|
calloc(num_msg, sizeof (struct ia_response));
|
|
if (*response == NULL)
|
|
return (IA_CONV_FAILURE);
|
|
|
|
(void) memset(*response, 0, sizeof (struct ia_response));
|
|
|
|
k = num_msg;
|
|
m = *msg;
|
|
r = *response;
|
|
while (k--) {
|
|
|
|
switch (m->msg_style) {
|
|
|
|
case IA_PROMPT_ECHO_OFF:
|
|
if (saved_user_passwd != NULL) {
|
|
r->resp = (char *) malloc(strlen(saved_user_passwd)+1);
|
|
if (r->resp == NULL) {
|
|
free_resp(num_msg, *response);
|
|
*response = NULL;
|
|
return (IA_CONV_FAILURE);
|
|
}
|
|
(void) strcpy(r->resp, saved_user_passwd);
|
|
r->resp_len = strlen(r->resp);
|
|
}
|
|
|
|
m++;
|
|
r++;
|
|
break;
|
|
|
|
|
|
case IA_ERROR_MSG:
|
|
if (m->msg != NULL) {
|
|
Debug ("login_conv: %s\n", m->msg);
|
|
}
|
|
m++;
|
|
r++;
|
|
break;
|
|
|
|
default:
|
|
Debug ("login_conv: Unexpected case %d\n",
|
|
m->msg_style);
|
|
break;
|
|
}
|
|
}
|
|
return (IA_SUCCESS);
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* end_conv():
|
|
*
|
|
* End of conversation function. Called from PAM.
|
|
* Currently a noop for dtlogin.
|
|
*****************************************************************************/
|
|
|
|
static void
|
|
end_conv()
|
|
{}
|
|
#endif SUNAUTH
|
|
|
|
#ifdef PAM
|
|
/****************************************************************************
|
|
* Following Solaris utmp management code was taken from portions of the
|
|
* private libauth open and close session code. There are no equivalent calls
|
|
* in libpam that replaces it, so the code is copied to here. Eventually this
|
|
* code may become functions in either PAM or other appropriate libraries.
|
|
***************************************************************************/
|
|
|
|
#define INIT_PROC_PID 1
|
|
#define PAMTXD "SUNW_OST_SYSOSPAM"
|
|
#define SCPYN(a, b) (void) strncpy(a, b, sizeof (a))
|
|
|
|
/* utility function to do UTMP/WTMP management */
|
|
int
|
|
solaris_setutmp_mgmt(
|
|
char *user, /* user */
|
|
char *ttyn, /* ttyn */
|
|
char *rhost, /* remote hostname */
|
|
int flags, /* Flags - see below */
|
|
int type, /* type of utmp/wtmp entry */
|
|
char id[] /* 4 byte id field for utmp */
|
|
);
|
|
|
|
/*
|
|
* solaris_reset_utmp_mgmt
|
|
* a utility function which terminates UTMP/WTMP mgmt
|
|
*/
|
|
int
|
|
solaris_reset_utmp_mgmt(
|
|
char **user, /* user */
|
|
char **ttyn, /* tty name */
|
|
char **rhost, /* remote host */
|
|
int flags, /* flags - see below */
|
|
int status, /* logout process status */
|
|
char id[] /* logout ut_id (/etc/inittab id) */
|
|
);
|
|
|
|
/* flags for the flags field */
|
|
#define __NOOP 8 /* No utmp action desired */
|
|
|
|
/* __setproc_cred is a utility function to set process credentials */
|
|
int
|
|
__setproc_cred(
|
|
char *user, /* user */
|
|
int flags, /* flags - see below */
|
|
uid_t uid, /* User ID to set for this process */
|
|
gid_t gid, /* Group ID */
|
|
int ngroups, /* Number of groups */
|
|
gid_t *grouplist /* Group list */
|
|
);
|
|
|
|
/* flags indicates specific set credential actions */
|
|
|
|
#define __INITGROUPS 0x00000001 /* Request to initgroups() */
|
|
#define __SETGROUPS 0x00000002 /* Request to setgroups() */
|
|
#define __SETEGID 0x00000004 /* Set effective gid only */
|
|
#define __SETGID 0x00000008 /* Set real gid */
|
|
#define __SETEUID 0x00000010 /* Set effective uid only */
|
|
#define __SETUID 0x00000020 /* Set real uid */
|
|
#define __SETEID (__SETEGID|__SETEUID) /* Set effective ids only */
|
|
#define __SETRID (__SETGID|__SETUID) /* Set real ids */
|
|
|
|
/*
|
|
* solaris_setutmp_mgmt - A utility function used to do UTMP/WTMP management.
|
|
*
|
|
* "user" is the current username.
|
|
* "ttyn" is the tty name.
|
|
* "rhost" is the remote hostname.
|
|
* The following flags may be set in the "flags" field:
|
|
*
|
|
* SOLARIS_UPDATE_ENTRY No new entry will be created if utmp
|
|
* entry not found - return __NOENTRY
|
|
* SOLARIS_NOLOG Generate a wtmp/wtmpx entry only
|
|
* SOLARIS_LOGIN Caller is a login application - update
|
|
* utmp entry accordingly
|
|
*
|
|
* "type" is used to indicate the type of utmp/wtmp entry written
|
|
* (see also utmp.h and utmpx.h)
|
|
* "id is an optional application-defined 4 byte array that represents
|
|
* the /sbin/inittab id (created by the process that puts an entry in
|
|
* utmp).
|
|
*
|
|
* Upon successful completion, SOLARIS_SUCCESS is returned.
|
|
* Error values may include:
|
|
*
|
|
* SOLARIS_NOENTRY An entry for the specified process was not found
|
|
* SOLARIS_ENTRYFAIL Could not make/remove entry for specified process
|
|
*/
|
|
|
|
int
|
|
solaris_setutmp_mgmt(
|
|
char *user,
|
|
char *ttyn,
|
|
char *rhost,
|
|
int flags,
|
|
int type,
|
|
char id[])
|
|
{
|
|
int tmplen;
|
|
struct utmpx *u = (struct utmpx *)0;
|
|
struct utmpx utmp;
|
|
char *ttyntail;
|
|
int err = PAM_SUCCESS;
|
|
|
|
Debug("Enter: solaris_setutmp_mgmt()\n");
|
|
|
|
(void) memset((void *)&utmp, 0, sizeof (utmp));
|
|
|
|
(void) time(&utmp.ut_tv.tv_sec);
|
|
utmp.ut_pid = getpid();
|
|
if (rhost != NULL && rhost[0] != '\0') {
|
|
(void) strcpy(utmp.ut_host, rhost);
|
|
tmplen = strlen(rhost) + 1;
|
|
if (tmplen < sizeof (utmp.ut_host))
|
|
utmp.ut_syslen = tmplen;
|
|
else
|
|
utmp.ut_syslen = sizeof (utmp.ut_host);
|
|
} 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&SOLARIS_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 & SOLARIS_NOLOG) == SOLARIS_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_ENTRY flag is set. The UPDATE_ENTRY flag is
|
|
* mainly for login which normally only wants to update an
|
|
* entry if the pid fields matches.
|
|
*/
|
|
|
|
if (flags & SOLARIS_LOGIN) {
|
|
while ((u = getutxent()) != NULL) {
|
|
if ((u->ut_type == INIT_PROCESS ||
|
|
u->ut_type == LOGIN_PROCESS ||
|
|
u->ut_type == USER_PROCESS) &&
|
|
((flags == SOLARIS_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 & SOLARIS_UPDATE_ENTRY)
|
|
err = SOLARIS_NOENTRY;
|
|
else
|
|
(void) makeutx(&utmp);
|
|
}
|
|
else
|
|
updwtmpx(WTMPX_FILE, &utmp);
|
|
}
|
|
return (err);
|
|
}
|
|
|
|
/*
|
|
* solaris_reset_utmp_mgmt
|
|
* A utility function used to terminate UTMP/WTMP mgmt.
|
|
*
|
|
* "user" is the current username.
|
|
* "ttyn" is the tty name.
|
|
* "rhost" is the remote hostname.
|
|
* The following flags may be set in the "flags" field:
|
|
*
|
|
* SOLARIS_NOLOG Write a wtmp/wtmpx entry only
|
|
* SOLARIS_NOOP Ignore utmp/wtmp processing
|
|
*
|
|
* "status" is the logout process status.
|
|
* "id is an optional application-defined 4 byte array that represents
|
|
* the /sbin/inittab id (created by the process that puts an entry in
|
|
* utmp).
|
|
*
|
|
* Upon successful completion, PAM_SUCCESS is returned.
|
|
* Error values may include:
|
|
*
|
|
* SOLARIS_NOENTRY An entry for the specified process was not found
|
|
* SOLARIS_ENTRYFAIL Could not make/remove entry for specified process
|
|
*/
|
|
|
|
int
|
|
solaris_reset_utmp_mgmt(
|
|
char **user,
|
|
char **ttyn,
|
|
char **rhost,
|
|
int flags,
|
|
int status,
|
|
char id[])
|
|
{
|
|
struct utmpx *up;
|
|
struct utmpx ut;
|
|
int err = 0;
|
|
int pid;
|
|
|
|
Debug("Enter: solaris_reset_utmp_mgmt()\n");
|
|
|
|
|
|
pid = (int) getpid();
|
|
|
|
if ((flags & SOLARIS_NOLOG) == SOLARIS_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 (*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);
|
|
|
|
return (PAM_SUCCESS);
|
|
} else {
|
|
setutxent();
|
|
while (up = getutxent()) {
|
|
if (up->ut_pid == pid) {
|
|
if (up->ut_type == DEAD_PROCESS) {
|
|
/*
|
|
* Cleaned up elsewhere.
|
|
*/
|
|
endutxent();
|
|
return (0);
|
|
}
|
|
if ((*user = (char *) strdup (up->ut_user))
|
|
== NULL ||
|
|
(*ttyn = (char *) strdup (up->ut_line))
|
|
== NULL ||
|
|
(*rhost = (char *) strdup (up->ut_host))
|
|
== NULL)
|
|
return (PAM_BUF_ERR);
|
|
|
|
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) {
|
|
Debug("modutx failed\n");
|
|
/*
|
|
* Since modutx failed we'll
|
|
* write out the new entry
|
|
* ourselves.
|
|
*/
|
|
(void) pututxline(up);
|
|
updwtmpx("wtmpx", up);
|
|
}
|
|
}
|
|
|
|
endutxent();
|
|
|
|
return (PAM_SUCCESS);
|
|
}
|
|
}
|
|
|
|
endutxent();
|
|
return (SOLARIS_NOENTRY);
|
|
}
|
|
|
|
}
|
|
|
|
#endif PAM
|