1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2  *
3  * Copyright (c) 2007 William Jon McCann <mccann@jhu.edu>
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation
7  * files (the "Software"), to deal in the Software without
8  * restriction, including without limitation the rights to use,
9  * copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following
12  * conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24  * OTHER DEALINGS IN THE SOFTWARE.
25  */
26 
27 #include "config.h"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 
33 #include <security/pam_appl.h>
34 #include <security/pam_misc.h>
35 
36 #ifdef HAVE_PATHS_H
37 #include <paths.h>
38 #endif /* HAVE_PATHS_H */
39 
40 #define PAM_MAX_LOGIN_TRIES	3
41 #define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \
42        fprintf (stderr, "\n%s\n", pam_strerror (pamh, retcode)); \
43        pam_end (pamh, retcode); exit (1); \
44    }
45 #define PAM_END { \
46 	pam_setcred (pamh, PAM_DELETE_CRED); \
47 	retcode = pam_close_session (pamh, 0); \
48 	pam_end (pamh, retcode); \
49 }
50 
51 int
main(int argc,char * argv[])52 main (int argc, char *argv[])
53 {
54         int             retcode;
55         int             ret;
56         pam_handle_t   *pamh;
57         char           *username;
58         char           *hostname;
59         char           *tty_name;
60         char           *ttyn;
61         struct pam_conv conv = { misc_conv, NULL };
62         int             failcount;
63 
64         ret = 1;
65         username = NULL;
66         hostname = NULL;
67         tty_name = NULL;
68 
69         retcode = pam_start ("login", username, &conv, &pamh);
70         if (retcode != PAM_SUCCESS) {
71                 fprintf (stderr, "login: PAM Failure, aborting: %s\n",
72                          pam_strerror (pamh, retcode));
73                 exit (99);
74         }
75 
76         ttyn = ttyname (0);
77 
78         if (strncmp (ttyn, _PATH_DEV, 5) == 0) {
79                 tty_name = ttyn + 5;
80         } else {
81                 tty_name = ttyn;
82         }
83 
84         retcode = pam_set_item (pamh, PAM_RHOST, hostname);
85         PAM_FAIL_CHECK;
86         retcode = pam_set_item (pamh, PAM_TTY, tty_name);
87         PAM_FAIL_CHECK;
88         pam_set_item (pamh, PAM_USER, NULL);
89 
90         retcode = pam_set_item (pamh, PAM_USER_PROMPT, "Username: ");
91         PAM_FAIL_CHECK;
92 
93         failcount = 0;
94         retcode = pam_authenticate (pamh, 0);
95         while ((failcount++ < PAM_MAX_LOGIN_TRIES) &&
96                ((retcode == PAM_AUTH_ERR) ||
97                 (retcode == PAM_USER_UNKNOWN) ||
98                 (retcode == PAM_CRED_INSUFFICIENT) ||
99                 (retcode == PAM_AUTHINFO_UNAVAIL))) {
100                 pam_get_item (pamh, PAM_USER, (const void **) &username);
101 
102                 fprintf (stderr, "Login incorrect\n\n");
103                 pam_set_item (pamh, PAM_USER, NULL);
104                 retcode = pam_authenticate (pamh, 0);
105         }
106 
107         if (retcode != PAM_SUCCESS) {
108                 fprintf (stderr, "\nLogin incorrect\n");
109                 pam_end (pamh, retcode);
110                 exit (0);
111         }
112 
113         retcode = pam_acct_mgmt (pamh, 0);
114         if (retcode == PAM_NEW_AUTHTOK_REQD) {
115                 retcode = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
116         }
117 
118         PAM_FAIL_CHECK;
119 
120         pam_putenv (pamh, "CKCON_TTY=/dev/tty55");
121         pam_putenv (pamh, "CKCON_X11_DISPLAY=:50");
122 
123         retcode = pam_open_session (pamh, 0);
124         PAM_FAIL_CHECK;
125 
126         retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED);
127         PAM_FAIL_CHECK;
128 
129         pam_get_item (pamh, PAM_USER, (const void **) &username);
130 
131         printf ("Session opened for %s\n", username);
132 
133         printf ("sleeping for 20 seconds...");
134         sleep (20);
135 
136         PAM_END;
137 
138         printf ("\nSession closed\n");
139 
140         return ret;
141 }
142