1/* pam_nologin module */
2
3/*
4 * $Id: pam_nologin.c,v 1.5 2002/03/27 19:20:24 bbraun Exp $
5 *
6 * Written by Michael K. Johnson <johnsonm@redhat.com> 1996/10/24
7 *
8 * Portions Copyright (C) 2002-2009 Apple Inc.  All rights reserved.
9 *
10 * Redistribution and use in source and binary forms of Linux-PAM, with
11 * or without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * 1. Redistributions of source code must retain any existing copyright
15 * notice, and this entire permission notice in its entirety,
16 * including the disclaimer of warranties.
17 *
18 * 2. Redistributions in binary form must reproduce all prior and current
19 * copyright notices, this list of conditions, and the following
20 * disclaimer in the documentation and/or other materials provided
21 * with the distribution.
22 *
23 * 3. The name of any author may not be used to endorse or promote
24 * products derived from this software without their specific prior
25 * written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
33 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
37 * DAMAGE.
38 */
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <unistd.h>
43#include <fcntl.h>
44#include <sys/types.h>
45#include <sys/stat.h>
46#include <sys/syslimits.h>
47#include <pwd.h>
48#include <string.h>
49
50/*
51 * here, we make a definition for the externally accessible function
52 * in this file (this definition is required for static a module
53 * but strongly encouraged generally) it is used to instruct the
54 * modules include file to define the function prototypes.
55 */
56
57#define PAM_SM_ACCOUNT
58
59#include <security/pam_modules.h>
60#include <security/pam_appl.h>
61
62
63/* --- account management function (only) --- */
64
65PAM_EXTERN
66int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
67                        const char **argv)
68{
69     int retval = PAM_SUCCESS;
70     int fd;
71     const char *username;
72     char *mtmp=NULL;
73     struct passwd *user_pwd;
74     struct passwd pwdbuf;
75     char pwbuffer[2 * PATH_MAX];
76     struct pam_conv *conversation;
77     struct pam_message message;
78     struct pam_message *pmessage = &message;
79     struct pam_response *resp = NULL;
80     struct stat st;
81
82     if ((fd = open("/etc/nologin", O_RDONLY, 0)) >= 0) {
83       /* root can still log in; lusers cannot */
84       if ((pam_get_user(pamh, &username, NULL) != PAM_SUCCESS)
85           || !username) {
86		   openpam_log(PAM_LOG_ERROR, "Failed to obtain the username.");
87         return PAM_SERVICE_ERR;
88       }
89       if (getpwnam_r(username, &pwdbuf, pwbuffer, sizeof(pwbuffer), &user_pwd) != 0) {
90         openpam_log(PAM_LOG_ERROR, "The getpwnam_r call failed.");
91         user_pwd = NULL;
92       }
93       if (user_pwd && user_pwd->pw_uid == 0) {
94         message.msg_style = PAM_TEXT_INFO;
95       } else {
96	   if (!user_pwd) {
97		   openpam_log(PAM_LOG_ERROR, "The user is invalid.");
98	       retval = PAM_USER_UNKNOWN;
99	   } else {
100		   openpam_log(PAM_LOG_ERROR, "Denying non-root login.");
101	       retval = PAM_AUTH_ERR;
102	   }
103	   message.msg_style = PAM_ERROR_MSG;
104       }
105
106       /* fill in message buffer with contents of /etc/nologin */
107	   if (fstat(fd, &st) < 0) {/* give up trying to display message */
108		   openpam_log(PAM_LOG_DEBUG, "Failure displaying the message.");
109		   return retval;
110	   }
111       message.msg = mtmp = malloc(st.st_size+1);
112       /* if malloc failed... */
113	   if (!message.msg){
114		   openpam_log(PAM_LOG_DEBUG, "The message is empty.");
115		   return retval;
116	   }
117       read(fd, mtmp, st.st_size);
118       mtmp[st.st_size] = '\000';
119
120       /* Use conversation function to give user contents of /etc/nologin */
121       pam_get_item(pamh, PAM_CONV, (const void **)&conversation);
122       conversation->conv(1, (const struct pam_message **)&pmessage,
123			  &resp, conversation->appdata_ptr);
124       free(mtmp);
125       if (NULL != resp && NULL != resp->resp) {
126         memset(resp->resp, 0, strlen(resp->resp));
127       }
128     }
129
130     return retval;
131}
132
133
134#ifdef PAM_STATIC
135
136/* static module data */
137
138struct pam_module _pam_nologin_modstruct = {
139     "pam_nologin",
140     pam_sm_authenticate,
141     pam_sm_setcred,
142     NULL,
143     NULL,
144     NULL,
145     NULL,
146};
147
148#endif
149
150/* end of module definition */
151