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