1 /* pam_issue module - a simple /etc/issue parser to set PAM_USER_PROMPT
3 * Copyright 1999 by Ben Collins <bcollins@debian.org>
5 * Needs to be called before any other auth modules so we can setup the
6 * user prompt before it's first used. Allows one argument option, which
7 * is the full path to a file to be used for issue (uses /etc/issue as a
8 * default) such as "issue=/etc/issue.telnet".
10 * We can also parse escapes within the the issue file (enabled by
11 * default, but can be disabled with the "noesc" option). It's the exact
12 * same parsing as util-linux's agetty program performs.
14 * Released under the GNU LGPL version 2 or later
15 * $FreeBSD: src/contrib/libpam/modules/pam_issue/pam_issue.c,v 1.1.1.1.2.2 2001/06/11 15:28:18 markm Exp $
24 #include <sys/types.h>
30 #include <sys/utsname.h>
34 #include <security/_pam_macros.h>
38 #include <security/pam_modules.h>
40 static int _user_prompt_set = 0;
42 char *do_prompt (FILE *);
44 /* --- authentication management functions (only) --- */
47 int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
50 int retval = PAM_SUCCESS;
53 char *prompt_tmp = NULL, *cur_prompt = NULL;
55 char *issue_file = NULL;
57 /* If we've already set the prompt, don't set it again */
61 /* we set this here so if we fail below, we wont get further
62 than this next time around (only one real failure) */
65 for ( ; argc-- > 0 ; ++argv ) {
66 if (!strncmp(*argv,"issue=",6)) {
67 issue_file = (char *) strdup(6+*argv);
68 if (issue_file != NULL) {
69 D(("set issue_file to: %s", issue_file));
71 D(("failed to strdup issue_file - ignored"));
74 } else if (!strcmp(*argv,"noesc")) {
76 D(("turning off escape parsing by request"));
78 D(("unknown option passed: %s", *argv));
81 if (issue_file == NULL)
82 issue_file = strdup("/etc/issue");
84 if ((fd = fopen(issue_file, "r")) != NULL) {
87 if (stat(issue_file, &st) < 0)
90 retval = pam_get_item(pamh, PAM_USER_PROMPT, (const void **) &cur_prompt);
91 if (retval != PAM_SUCCESS)
94 /* first read in the issue file */
97 prompt_tmp = do_prompt(fd);
100 prompt_tmp = malloc(st.st_size + 1);
101 if (prompt_tmp == NULL) return PAM_IGNORE;
102 memset (prompt_tmp, '\0', st.st_size + 1);
103 count = fread(prompt_tmp, sizeof(char *), st.st_size, fd);
104 prompt_tmp[st.st_size] = '\0';
109 tot_size = strlen(prompt_tmp) + strlen(cur_prompt) + 1;
112 * alloc some extra space for the original prompt
113 * and postpend it to the buffer
115 prompt_tmp = realloc(prompt_tmp, tot_size);
116 strcpy(prompt_tmp+strlen(prompt_tmp), cur_prompt);
118 prompt_tmp[tot_size] = '\0';
120 retval = pam_set_item(pamh, PAM_USER_PROMPT, (const char *) prompt_tmp);
125 D(("could not open issue_file: %s", issue_file));
133 int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
139 char *do_prompt(FILE *fd)
142 char *issue = (char *)malloc(size);
146 if (issue == NULL || fd == NULL)
149 issue[0] = '\0'; /* zero this, for strcat to work on first buf */
152 while ((c = getc(fd)) != EOF) {
157 snprintf (buf, 1024, "%s", uts.sysname);
160 snprintf (buf, 1024, "%s", uts.nodename);
163 snprintf (buf, 1024, "%s", uts.release);
166 snprintf (buf, 1024, "%s", uts.version);
169 snprintf (buf, 1024, "%s", uts.machine);
173 char domainname[256];
175 getdomainname(domainname, sizeof(domainname));
176 domainname[sizeof(domainname)-1] = '\0';
177 snprintf (buf, 1024, "%s", domainname);
184 const char *weekday[] = {
185 "Sun", "Mon", "Tue", "Wed", "Thu",
187 const char *month[] = {
188 "Jan", "Feb", "Mar", "Apr", "May",
189 "Jun", "Jul", "Aug", "Sep", "Oct",
195 tm = localtime(&now);
198 snprintf (buf, 1024, "%s %s %d %d",
199 weekday[tm->tm_wday], month[tm->tm_mon],
203 snprintf (buf, 1024, "%02d:%02d:%02d",
204 tm->tm_hour, tm->tm_min, tm->tm_sec);
209 char *ttyn = ttyname(1);
210 if (!strncmp(ttyn, "/dev/", 5))
212 snprintf (buf, 1024, "%s", ttyn);
221 while ((ut = getutent()))
222 if (ut->ut_type == USER_PROCESS)
225 printf ("%d ", users);
227 snprintf (buf, 1024, "%s", (users == 1) ?
232 buf[0] = c; buf[1] = '\0';
234 if ((strlen(issue) + strlen(buf)) < size + 1) {
235 size += strlen(buf) + 1;
236 issue = (char *) realloc (issue, size);
240 buf[0] = c; buf[1] = '\0';
241 if ((strlen(issue) + strlen(buf)) < size + 1) {
242 size += strlen(buf) + 1;
243 issue = (char *) realloc (issue, size);
253 /* static module data */
255 struct pam_module _pam_issue_modstruct = {
267 /* end of module definition */