/* * 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 #include #include #include #include #include #include #include #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); }