2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: pam_svc.c /main/5 1997/06/04 16:30:21 samborn $ */
24 /*******************************************************************************
26 ** pam_svc.c 1.10 95/11/25
28 ** Copyright 1993, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
30 ** This file contains procedures specific to dtlogin's use of
31 ** PAM (Pluggable Authentication Module) security library.
33 *******************************************************************************/
35 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
36 * (c) Copyright 1993, 1994 International Business Machines Corp. *
37 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc. *
38 * (c) Copyright 1993, 1994 Novell, Inc. *
50 #include <sys/param.h>
52 #include <security/pam_appl.h>
58 * Local function declarations
61 static int login_conv(int num_msg, struct pam_message **msg,
62 struct pam_response **response, void *appdata_ptr);
64 static char* create_devname(char* short_devname);
69 * Local structures and variables
72 static struct pam_conv pam_conv = {login_conv, NULL};
73 static char *saved_user_passwd;
74 static pam_handle_t *pamh = NULL;
75 static int pam_auth_trys = 0;
77 /****************************************************************************
80 * Initialize or Update PAM datastructures.
82 ****************************************************************************/
85 PamInit(char* prog_name,
90 int status=PAM_SUCCESS;
93 /* Open PAM (Plugable Authentication module ) connection */
94 status = pam_start( prog_name, user, &pam_conv, &pamh );
95 if (status != PAM_SUCCESS) {
96 Debug("PamInit: pam_start error=%d\n", status);
99 Debug("PamInit: pam_start success\n");
102 if (prog_name) pam_set_item(pamh, PAM_SERVICE, prog_name);
103 if (user) pam_set_item(pamh, PAM_USER, user);
106 if (status == PAM_SUCCESS) {
107 if (line_dev) pam_set_item(pamh, PAM_TTY, line_dev);
108 if (display_name) pam_set_item(pamh, PAM_RHOST, display_name);
114 /****************************************************************************
117 * Authenticate that user / password combination is legal for this system
119 ****************************************************************************/
122 PamAuthenticate ( char* prog_name,
129 char* user_str = user ? user : "NULL";
130 char* line_str = line ? line : "NULL";
131 char* line_dev = create_devname(line_str);
133 Debug("PamAuthenticate: prog_name=%s\n", prog_name);
134 Debug("PamAuthenticate: display_name=%s\n", display_name);
135 Debug("PamAuthenticate: user=%s\n", user_str);
136 Debug("PamAuthenticate: line=%s\n", line_str);
137 Debug("PamAuthenticate: line_dev=%s\n", line_dev);
140 if (strlen(user_passwd) == 0) {
141 Debug("PamAuthenticate: user passwd empty\n");
143 Debug("PamAuthenticate: user passwd present\n");
147 Debug("PamAuthenticate: user passwd NULL\n");
149 /* Password challenge required for dtlogin authentication */
150 return(PAM_AUTH_ERR);
154 /* Solaris BSM Audit trail */
156 audit_login_save_host(display_name);
157 audit_login_save_ttyn(line_dev);
158 audit_login_save_port();
161 status = PamInit(prog_name, user, line_dev, display_name);
163 if (status == PAM_SUCCESS) {
166 saved_user_passwd = user_passwd;
167 status = pam_authenticate( pamh, 0 );
171 pwd = getpwnam(user);
172 audit_login_save_pw(pwd);
174 if (status != PAM_SUCCESS) {
175 audit_login_bad_pw();
177 if (status == PAM_MAXTRIES) {
178 pam_auth_trys = PAM_LOGIN_MAXTRIES+1;
181 if (pam_auth_trys > PAM_LOGIN_MAXTRIES) {
182 audit_login_maxtrys();
187 if (status != PAM_SUCCESS) {
188 sleep(PAM_LOGIN_SLEEPTIME);
189 if (pam_auth_trys > PAM_LOGIN_MAXTRIES) {
190 sleep(PAM_LOGIN_DISABLETIME);
195 if (status != PAM_SUCCESS) {
196 Debug("PamAuthenticate: PAM error=%d\n", status);
198 Debug("PamAuthenticate: calling pam_end\n");
199 pam_end(pamh, PAM_ABORT);
210 /****************************************************************************
213 * Work related to open and close of user sessions
214 ****************************************************************************/
217 PamAccounting( char* prog_name,
226 int session_type, status;
227 char *user_str = user ? user : "NULL";
228 char *line_str = line ? line : "NULL";
229 char *line_dev = create_devname(line_str);
232 Debug("PamAccounting: prog_name=%s\n", prog_name);
233 Debug("PamAccounting: display_name=%s\n", display_name);
234 Debug("PamAccounting: entry_id=%c %c %c %c\n", entry_id[0],
235 entry_id[1], entry_id[2], entry_id[3]);
236 Debug("PamAccounting: user=%s\n", user_str);
237 Debug("PamAccounting: line=%s\n", line_str);
238 Debug("PamAccounting: line_dev=%s\n", line_dev);
239 Debug("PamAccounting: pid=%d\n", pid);
240 Debug("PamAccounting: entry_type=%d\n", entry_type);
241 Debug("PamAccounting: exitcode=%d\n", exitcode);
243 /* Open Solaris PAM (Plugable Authentication module ) connection */
245 if (entry_type == ACCOUNTING) {
252 status = PamInit(prog_name, user, tty_line, display_name);
255 /* Session accounting */
257 if (status == PAM_SUCCESS) switch(entry_type) {
259 /* New user session, open session accounting logs */
260 status = pam_open_session(pamh, 0);
261 if (status != PAM_SUCCESS) {
262 Debug("PamAccounting: USER_PROCESS open_session error=%d\n",
266 if (status == PAM_SUCCESS) audit_login_success();
268 session_type = SOLARIS_LOGIN;
269 status = solaris_setutmp_mgmt(user, tty_line, display_name,
270 session_type, entry_type, entry_id);
271 if (status != SOLARIS_SUCCESS) {
272 Debug("PamAccounting: USER_PRCESS set_utmp error=%d\n",
280 * User session has terminated, mark it DEAD and close
281 * the sessions accounting logs.
283 status = pam_open_session(pamh, 0);
284 if (status != PAM_SUCCESS) {
285 Debug("PamAccounting: ACCOUNTING open_session error=%d\n",
288 entry_type = DEAD_PROCESS;
289 session_type = SOLARIS_NOLOG;
290 status = solaris_setutmp_mgmt(user, tty_line, display_name,
291 session_type, entry_type, entry_id);
293 if (status != SOLARIS_SUCCESS) {
294 Debug("PamAccounting: ACCOUNTING set_utmp error=%d\n",
297 /* Intentional fall thru */
301 /* Cleanup account files for dead processes */
302 status = pam_close_session(pamh, 0);
303 if (status != PAM_SUCCESS) {
304 Debug("PamAccounting: DEAD_PROCES close_session error=%d\n",
308 status = solaris_reset_utmp_mgmt(&user, &tty_line,
310 entry_type, entry_id);
312 if (status != SOLARIS_SUCCESS) {
313 Debug("PamAccounting: DEAD_PROCESS reset_utmp error=%d\n",
321 status = pam_open_session(pamh, 0);
322 if (status != PAM_SUCCESS) {
323 Debug("PamAccounting:LOGIN_PROCESS open_session error=%d\n",
327 status = solaris_setutmp_mgmt(user, tty_line, display_name,
328 session_type, entry_type, entry_id);
329 if (status != SOLARIS_SUCCESS) {
330 Debug("PamAccounting: LOGIN_PRCESS set_utmp error=%d\n",
342 /****************************************************************************
345 * Set Users login credentials: uid, gid, and group lists
346 ****************************************************************************/
349 PamSetCred(char* prog_name, char* user, uid_t uid, gid_t gid)
351 int cred_type, status;
352 char* user_str = user ? user : "NULL";
354 Debug("PamSetCred: prog_name=%s\n", prog_name);
355 Debug("PamSetCred: user=%s\n", user_str);
356 Debug("PamSetCred: uid=%d\n", uid);
357 Debug("PamSetCred: gid=%d\n", gid);
359 status = PamInit(prog_name, user, NULL, NULL);
361 /* Set users credentials */
363 if (status == PAM_SUCCESS && setgid(gid) == -1)
364 status = SOLARIS_BAD_GID;
366 if (status == PAM_SUCCESS &&
367 ( !user) || (initgroups(user, gid) == -1) )
368 status = SOLARIS_INITGROUP_FAIL;
370 if (status == PAM_SUCCESS)
371 status = pam_setcred(pamh, PAM_ESTABLISH_CRED);
373 if (status == PAM_SUCCESS && (setuid(uid) == -1))
374 status = SOLARIS_BAD_UID;
376 if (status != PAM_SUCCESS) {
377 Debug("PamSetCred: user=%s, err=%d)\n", user, status);
384 /***************************************************************************
387 * A utility function. Takes short device name like "console" and returns
388 * a long device name like "/dev/console"
389 ***************************************************************************/
392 create_devname(char* short_devname)
396 if (short_devname == NULL)
399 long_devname = (char *) malloc (strlen(short_devname) + 5);
401 if (long_devname == NULL)
404 strcpy(long_devname,"/dev/");
405 strcat(long_devname, short_devname);
407 return(long_devname);
411 /*****************************************************************************
414 * This is a conv (conversation) function called from the PAM
415 * authentication scheme. It returns the user's password when requested by
416 * internal PAM authentication modules and also logs any internal PAM error
418 *****************************************************************************/
421 login_conv(int num_msg, struct pam_message **msg,
422 struct pam_response **response, void *appdata_ptr)
424 struct pam_message *m;
425 struct pam_response *r;
433 return (PAM_CONV_ERR);
435 *response = (struct pam_response*)
436 calloc(num_msg, sizeof (struct pam_response));
437 if (*response == NULL)
438 return (PAM_CONV_ERR);
440 (void) memset(*response, 0, sizeof (struct pam_response));
447 switch (m->msg_style) {
449 case PAM_PROMPT_ECHO_OFF:
450 if (saved_user_passwd != NULL) {
451 r->resp = (char *) malloc(strlen(saved_user_passwd)+1);
452 if (r->resp == NULL) {
453 __pam_free_resp(num_msg, *response);
455 return (PAM_CONV_ERR);
457 (void) strcpy(r->resp, saved_user_passwd);
467 if (m->msg != NULL) {
468 Debug ("login_conv ERROR: %s\n", m->msg);
475 if (m->msg != NULL) {
476 Debug ("login_conv INFO: %s\n", m->msg);
483 Debug ("login_conv: Unexpected case %d\n",
488 return (PAM_SUCCESS);