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 $
16 * $DragonFly: src/contrib/libpam/modules/pam_issue/Attic/pam_issue.c,v 1.2 2003/06/17 04:24:03 dillon Exp $
25 #include <sys/types.h>
31 #include <sys/utsname.h>
35 #include <security/_pam_macros.h>
39 #include <security/pam_modules.h>
41 static int _user_prompt_set = 0;
43 char *do_prompt (FILE *);
45 /* --- authentication management functions (only) --- */
48 int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
51 int retval = PAM_SUCCESS;
54 char *prompt_tmp = NULL, *cur_prompt = NULL;
56 char *issue_file = NULL;
58 /* If we've already set the prompt, don't set it again */
62 /* we set this here so if we fail below, we wont get further
63 than this next time around (only one real failure) */
66 for ( ; argc-- > 0 ; ++argv ) {
67 if (!strncmp(*argv,"issue=",6)) {
68 issue_file = (char *) strdup(6+*argv);
69 if (issue_file != NULL) {
70 D(("set issue_file to: %s", issue_file));
72 D(("failed to strdup issue_file - ignored"));
75 } else if (!strcmp(*argv,"noesc")) {
77 D(("turning off escape parsing by request"));
79 D(("unknown option passed: %s", *argv));
82 if (issue_file == NULL)
83 issue_file = strdup("/etc/issue");
85 if ((fd = fopen(issue_file, "r")) != NULL) {
88 if (stat(issue_file, &st) < 0)
91 retval = pam_get_item(pamh, PAM_USER_PROMPT, (const void **) &cur_prompt);
92 if (retval != PAM_SUCCESS)
95 /* first read in the issue file */
98 prompt_tmp = do_prompt(fd);
101 prompt_tmp = malloc(st.st_size + 1);
102 if (prompt_tmp == NULL) return PAM_IGNORE;
103 memset (prompt_tmp, '\0', st.st_size + 1);
104 count = fread(prompt_tmp, sizeof(char *), st.st_size, fd);
105 prompt_tmp[st.st_size] = '\0';
110 tot_size = strlen(prompt_tmp) + strlen(cur_prompt) + 1;
113 * alloc some extra space for the original prompt
114 * and postpend it to the buffer
116 prompt_tmp = realloc(prompt_tmp, tot_size);
117 strcpy(prompt_tmp+strlen(prompt_tmp), cur_prompt);
119 prompt_tmp[tot_size] = '\0';
121 retval = pam_set_item(pamh, PAM_USER_PROMPT, (const char *) prompt_tmp);
126 D(("could not open issue_file: %s", issue_file));
134 int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
140 char *do_prompt(FILE *fd)
143 char *issue = (char *)malloc(size);
147 if (issue == NULL || fd == NULL)
150 issue[0] = '\0'; /* zero this, for strcat to work on first buf */
153 while ((c = getc(fd)) != EOF) {
158 snprintf (buf, 1024, "%s", uts.sysname);
161 snprintf (buf, 1024, "%s", uts.nodename);
164 snprintf (buf, 1024, "%s", uts.release);
167 snprintf (buf, 1024, "%s", uts.version);
170 snprintf (buf, 1024, "%s", uts.machine);
174 char domainname[256];
176 getdomainname(domainname, sizeof(domainname));
177 domainname[sizeof(domainname)-1] = '\0';
178 snprintf (buf, 1024, "%s", domainname);
185 const char *weekday[] = {
186 "Sun", "Mon", "Tue", "Wed", "Thu",
188 const char *month[] = {
189 "Jan", "Feb", "Mar", "Apr", "May",
190 "Jun", "Jul", "Aug", "Sep", "Oct",
196 tm = localtime(&now);
199 snprintf (buf, 1024, "%s %s %d %d",
200 weekday[tm->tm_wday], month[tm->tm_mon],
204 snprintf (buf, 1024, "%02d:%02d:%02d",
205 tm->tm_hour, tm->tm_min, tm->tm_sec);
210 char *ttyn = ttyname(1);
211 if (!strncmp(ttyn, "/dev/", 5))
213 snprintf (buf, 1024, "%s", ttyn);
222 while ((ut = getutent()))
223 if (ut->ut_type == USER_PROCESS)
226 printf ("%d ", users);
228 snprintf (buf, 1024, "%s", (users == 1) ?
233 buf[0] = c; buf[1] = '\0';
235 if ((strlen(issue) + strlen(buf)) < size + 1) {
236 size += strlen(buf) + 1;
237 issue = (char *) realloc (issue, size);
241 buf[0] = c; buf[1] = '\0';
242 if ((strlen(issue) + strlen(buf)) < size + 1) {
243 size += strlen(buf) + 1;
244 issue = (char *) realloc (issue, size);
254 /* static module data */
256 struct pam_module _pam_issue_modstruct = {
268 /* end of module definition */