summaryrefslogtreecommitdiff
path: root/modules/pam_motd/pam_motd.c
blob: 291d76d950d69294f4946f6a3937d876240f0bc5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* pam_motd module */

/*
 * Modified for pam_motd by Ben Collins <bcollins@debian.org>
 *
 * Based off of:
 * $Id$
 *
 * Written by Michael K. Johnson <johnsonm@redhat.com> 1996/10/24
 *
 */

#include "config.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>

#include <security/_pam_macros.h>
/*
 * here, we make a definition for the externally accessible function
 * in this file (this definition is required for static a module
 * but strongly encouraged generally) it is used to instruct the
 * modules include file to define the function prototypes.
 */

#define PAM_SM_SESSION
#define DEFAULT_MOTD	"/etc/motd"

#include <security/pam_modules.h>
#include <security/_pam_modutil.h>

/* --- session management functions (only) --- */

PAM_EXTERN int
pam_sm_close_session (pam_handle_t *pamh UNUSED, int flags UNUSED,
		      int argc UNUSED, const char **argv UNUSED)
{
     return PAM_IGNORE;
}

static char default_motd[] = DEFAULT_MOTD;

PAM_EXTERN
int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
                   const char **argv)
{
     int retval = PAM_IGNORE;
     int fd;
     char *mtmp=NULL;
     char *motd_path=NULL;
     const void *void_conv;
     const struct pam_conv *conversation;
     struct pam_message message;
     struct pam_message *pmessage = &message;
     struct pam_response *resp = NULL;
     struct stat st;

     if (flags & PAM_SILENT) {
	return retval;
     }

    for (; argc-- > 0; ++argv) {
        if (!strncmp(*argv,"motd=",5)) {

            motd_path = (char *) strdup(5+*argv);
            if (motd_path != NULL) {
                D(("set motd path: %s", motd_path));
            } else {
                D(("failed to duplicate motd path - ignored"));
            }
	}
     }

     if (motd_path == NULL)
	motd_path = default_motd;

     message.msg_style = PAM_TEXT_INFO;

     if ((fd = open(motd_path, O_RDONLY, 0)) >= 0) {
       if (motd_path != default_motd)
         free(motd_path);
       /* fill in message buffer with contents of motd */
       if ((fstat(fd, &st) < 0) || !st.st_size) {
         close(fd);
         return retval;
       }
       message.msg = mtmp = malloc(st.st_size+1);
       /* if malloc failed... */
       if (!message.msg) {
           close(fd);
           return retval;
       }
       if (_pammodutil_read(fd, mtmp, st.st_size) == st.st_size) {
	   if (mtmp[st.st_size-1] == '\n')
		mtmp[st.st_size-1] = '\0';
	   else
		mtmp[st.st_size] = '\0';
	   close(fd);

 	   /* Use conversation function to give user contents of motd */
	   if (pam_get_item(pamh, PAM_CONV, &void_conv) ==
	               PAM_SUCCESS && void_conv) {
	       conversation = void_conv;
	       conversation->conv(1, (const struct pam_message **)&pmessage,
	            &resp, conversation->appdata_ptr);
	       if (resp)
	           _pam_drop_reply(resp, 1);
           }
       }
       free(mtmp);
     } else {
       if (motd_path != default_motd)
         free(motd_path);
     }

     return retval;
}


#ifdef PAM_STATIC

/* static module data */

struct pam_module _pam_motd_modstruct = {
     "pam_motd",
     NULL,
     NULL,
     NULL,
     pam_sm_open_session,
     pam_sm_close_session,
     NULL,
};

#endif

/* end of module definition */