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 libraries 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);
153 status = PamInit(prog_name, user, line_dev, display_name);
155 if (status == PAM_SUCCESS) {
158 saved_user_passwd = user_passwd;
159 status = pam_authenticate( pamh, 0 );
162 if (status != PAM_SUCCESS) {
163 sleep(PAM_LOGIN_SLEEPTIME);
164 if (pam_auth_trys > PAM_LOGIN_MAXTRIES) {
165 sleep(PAM_LOGIN_DISABLETIME);
170 if (status != PAM_SUCCESS) {
171 Debug("PamAuthenticate: PAM error=%d\n", status);
173 Debug("PamAuthenticate: calling pam_end\n");
174 pam_end(pamh, PAM_ABORT);
185 /****************************************************************************
188 * Work related to open and close of user sessions
189 ****************************************************************************/
192 PamAccounting( char* prog_name,
201 int session_type, status;
202 char *user_str = user ? user : "NULL";
203 char *line_str = line ? line : "NULL";
204 char *line_dev = create_devname(line_str);
207 Debug("PamAccounting: prog_name=%s\n", prog_name);
208 Debug("PamAccounting: display_name=%s\n", display_name);
209 Debug("PamAccounting: entry_id=%c %c %c %c\n", entry_id[0],
210 entry_id[1], entry_id[2], entry_id[3]);
211 Debug("PamAccounting: user=%s\n", user_str);
212 Debug("PamAccounting: line=%s\n", line_str);
213 Debug("PamAccounting: line_dev=%s\n", line_dev);
214 Debug("PamAccounting: pid=%d\n", pid);
215 Debug("PamAccounting: entry_type=%d\n", entry_type);
216 Debug("PamAccounting: exitcode=%d\n", exitcode);
218 /* Open Solaris PAM (Plugable Authentication module ) connection */
220 if (entry_type == ACCOUNTING) {
227 status = PamInit(prog_name, user, tty_line, display_name);
230 /* Session accounting */
232 if (status == PAM_SUCCESS) switch(entry_type) {
234 /* New user session, open session accounting logs */
235 status = pam_open_session(pamh, 0);
236 if (status != PAM_SUCCESS) {
237 Debug("PamAccounting: USER_PROCESS open_session error=%d\n",
240 session_type = SOLARIS_LOGIN;
241 status = solaris_setutmp_mgmt(user, tty_line, display_name,
242 session_type, entry_type, entry_id);
243 if (status != SOLARIS_SUCCESS) {
244 Debug("PamAccounting: USER_PRCESS set_utmp error=%d\n",
252 * User session has terminated, mark it DEAD and close
253 * the sessions accounting logs.
255 status = pam_open_session(pamh, 0);
256 if (status != PAM_SUCCESS) {
257 Debug("PamAccounting: ACCOUNTING open_session error=%d\n",
260 entry_type = DEAD_PROCESS;
261 session_type = SOLARIS_NOLOG;
262 status = solaris_setutmp_mgmt(user, tty_line, display_name,
263 session_type, entry_type, entry_id);
265 if (status != SOLARIS_SUCCESS) {
266 Debug("PamAccounting: ACCOUNTING set_utmp error=%d\n",
269 /* Intentional fall thru */
273 /* Cleanup account files for dead processes */
274 status = pam_close_session(pamh, 0);
275 if (status != PAM_SUCCESS) {
276 Debug("PamAccounting: DEAD_PROCES close_session error=%d\n",
280 status = solaris_reset_utmp_mgmt(&user, &tty_line,
282 entry_type, entry_id);
284 if (status != SOLARIS_SUCCESS) {
285 Debug("PamAccounting: DEAD_PROCESS reset_utmp error=%d\n",
293 status = pam_open_session(pamh, 0);
294 if (status != PAM_SUCCESS) {
295 Debug("PamAccounting:LOGIN_PROCESS open_session error=%d\n",
299 status = solaris_setutmp_mgmt(user, tty_line, display_name,
300 session_type, entry_type, entry_id);
301 if (status != SOLARIS_SUCCESS) {
302 Debug("PamAccounting: LOGIN_PROCESS set_utmp error=%d\n",
314 /****************************************************************************
317 * Set Users login credentials: uid, gid, and group lists
318 ****************************************************************************/
321 PamSetCred(char* prog_name, char* user, uid_t uid, gid_t gid)
323 int cred_type, status;
324 char* user_str = user ? user : "NULL";
326 Debug("PamSetCred: prog_name=%s\n", prog_name);
327 Debug("PamSetCred: user=%s\n", user_str);
328 Debug("PamSetCred: uid=%d\n", uid);
329 Debug("PamSetCred: gid=%d\n", gid);
331 status = PamInit(prog_name, user, NULL, NULL);
333 /* Set users credentials */
335 if (status == PAM_SUCCESS && setgid(gid) == -1)
336 status = SOLARIS_BAD_GID;
338 if (status == PAM_SUCCESS &&
339 ( !user) || (initgroups(user, gid) == -1) )
340 status = SOLARIS_INITGROUP_FAIL;
342 if (status == PAM_SUCCESS)
343 status = pam_setcred(pamh, PAM_ESTABLISH_CRED);
345 if (status == PAM_SUCCESS && (setuid(uid) == -1))
346 status = SOLARIS_BAD_UID;
348 if (status != PAM_SUCCESS) {
349 Debug("PamSetCred: user=%s, err=%d)\n", user, status);
356 /***************************************************************************
359 * A utility function. Takes short device name like "console" and returns
360 * a long device name like "/dev/console"
361 ***************************************************************************/
364 create_devname(char* short_devname)
368 if (short_devname == NULL)
371 long_devname = (char *) malloc (strlen(short_devname) + 5);
373 if (long_devname == NULL)
376 strcpy(long_devname,"/dev/");
377 strcat(long_devname, short_devname);
379 return(long_devname);
383 /*****************************************************************************
386 * This is a conv (conversation) function called from the PAM
387 * authentication scheme. It returns the user's password when requested by
388 * internal PAM authentication modules and also logs any internal PAM error
390 *****************************************************************************/
393 login_conv(int num_msg, struct pam_message **msg,
394 struct pam_response **response, void *appdata_ptr)
396 struct pam_message *m;
397 struct pam_response *r;
405 return (PAM_CONV_ERR);
407 *response = (struct pam_response*)
408 calloc(num_msg, sizeof (struct pam_response));
409 if (*response == NULL)
410 return (PAM_CONV_ERR);
412 (void) memset(*response, 0, sizeof (struct pam_response));
419 switch (m->msg_style) {
421 case PAM_PROMPT_ECHO_OFF:
422 if (saved_user_passwd != NULL) {
423 r->resp = (char *) malloc(strlen(saved_user_passwd)+1);
424 if (r->resp == NULL) {
425 /* __pam_free_resp(num_msg, *response); */
427 return (PAM_CONV_ERR);
429 (void) strcpy(r->resp, saved_user_passwd);
439 if (m->msg != NULL) {
440 Debug ("login_conv ERROR: %s\n", m->msg);
447 if (m->msg != NULL) {
448 Debug ("login_conv INFO: %s\n", m->msg);
455 Debug ("login_conv: Unexpected case %d\n",
460 return (PAM_SUCCESS);