Remove extra whitespace at the end of some lines.
[dragonfly.git] / contrib / libpam / modules / pam_wheel / pam_wheel.c
1 /* pam_wheel module */
2
3 /*
4  * Written by Cristian Gafton <gafton@redhat.com> 1996/09/10
5  * See the end of the file for Copyright Information
6  *
7  *
8  * 1.2 - added 'deny' and 'group=' options
9  * 1.1 - added 'trust' option
10  * 1.0 - the code is working for at least another person, so... :-)
11  * 0.1 - use vsyslog instead of vfprintf/syslog in _pam_log
12  *     - return PAM_IGNORE on success (take care of sloppy sysadmins..)
13  *     - use pam_get_user instead of pam_get_item(...,PAM_USER,...)
14  *     - a new arg use_uid to auth the current uid instead of the
15  *       initial (logged in) one.
16  * 0.0 - first release
17  *
18  * TODO:
19  *  - try to use make_remark from pam_unix/support.c
20  *  - consider returning on failure PAM_FAIL_NOW if the user is not
21  *    a wheel member.
22  *
23  * $FreeBSD: src/contrib/libpam/modules/pam_wheel/pam_wheel.c,v 1.3.2.2 2001/06/11 15:28:35 markm Exp $
24  * $DragonFly: src/contrib/libpam/modules/pam_wheel/Attic/pam_wheel.c,v 1.2 2003/06/17 04:24:03 dillon Exp $
25  */
26
27 #define _BSD_SOURCE
28
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <syslog.h>
33 #include <stdarg.h>
34 #include <sys/types.h>
35 #include <pwd.h>
36 #include <grp.h>
37
38 /*
39  * here, we make a definition for the externally accessible function
40  * in this file (this definition is required for static a module
41  * but strongly encouraged generally) it is used to instruct the
42  * modules include file to define the function prototypes.
43  */
44
45 #define PAM_SM_AUTH
46
47 #include <security/pam_modules.h>
48
49 /* some syslogging */
50
51 static void _pam_log(int err, const char *format, ...)
52 {
53     va_list args;
54
55     va_start(args, format);
56     openlog("PAM-Wheel", LOG_CONS|LOG_PID, LOG_AUTH);
57     vsyslog(err, format, args);
58     va_end(args);
59     closelog();
60 }
61
62 /* checks if a user is on a list of members of the GID 0 group */
63
64 static int is_on_list(char * const *list, const char *member)
65 {
66     while (*list) {
67         if (strcmp(*list, member) == 0)
68             return 1;
69         list++;
70     }
71     return 0;
72 }
73
74 /* argument parsing */
75
76 #define PAM_DEBUG_ARG       0x0001
77 #define PAM_USE_UID_ARG     0x0002
78 #define PAM_TRUST_ARG       0x0004
79 #define PAM_DENY_ARG        0x0010  
80
81 static int _pam_parse(int argc, const char **argv, char *use_group)
82 {
83      int ctrl=0;
84
85      /* step through arguments */
86      for (ctrl=0; argc-- > 0; ++argv) {
87
88           /* generic options */
89
90           if (!strcmp(*argv,"debug"))
91                ctrl |= PAM_DEBUG_ARG;
92           else if (!strcmp(*argv,"use_uid"))
93                ctrl |= PAM_USE_UID_ARG;
94           else if (!strcmp(*argv,"trust"))
95                ctrl |= PAM_TRUST_ARG;
96           else if (!strcmp(*argv,"deny"))
97                ctrl |= PAM_DENY_ARG;
98           else if (!strncmp(*argv,"group=",6))
99                 strcpy(use_group,*argv+6);
100           else {
101                _pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv);
102           }
103      }
104
105      return ctrl;
106 }
107
108
109 /* --- authentication management functions (only) --- */
110
111 PAM_EXTERN
112 int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
113                         ,const char **argv)
114 {
115      int ctrl;
116      const char *username;
117      char *fromsu;
118      struct passwd *pwd, *tpwd;
119      struct group *grp;
120      int retval = PAM_AUTH_ERR;
121      char use_group[BUFSIZ];
122     
123      /* Init the optional group */
124      bzero(use_group,BUFSIZ);
125      
126      ctrl = _pam_parse(argc, argv, use_group);
127      retval = pam_get_user(pamh,&username,NULL);
128      if ((retval != PAM_SUCCESS) || (!username)) {
129         if (ctrl & PAM_DEBUG_ARG)
130             _pam_log(LOG_DEBUG,"can not get the username");
131         return PAM_SERVICE_ERR;
132      }
133
134      /* su to a uid 0 account ? */
135      pwd = getpwnam(username);
136      if (!pwd) {
137         if (ctrl & PAM_DEBUG_ARG)
138             _pam_log(LOG_NOTICE,"unknown user %s",username);
139         return PAM_USER_UNKNOWN;
140      }
141      
142      /* Now we know that the username exists, pass on to other modules...
143       * the call to pam_get_user made this obsolete, so is commented out
144       *
145       * pam_set_item(pamh,PAM_USER,(const void *)username);
146       */
147
148      /* is this user an UID 0 account ? */
149      if(pwd->pw_uid) {
150         /* no need to check for wheel */
151         return PAM_IGNORE;
152      }
153      
154      if (ctrl & PAM_USE_UID_ARG) {
155          tpwd = getpwuid(getuid());
156          if (!tpwd) {
157             if (ctrl & PAM_DEBUG_ARG)
158                 _pam_log(LOG_NOTICE,"who is running me ?!");
159             return PAM_SERVICE_ERR;
160          }
161          fromsu = tpwd->pw_name;
162      } else {
163          fromsu = getlogin();
164          if (!fromsu) {
165              if (ctrl & PAM_DEBUG_ARG)
166                 _pam_log(LOG_NOTICE,"who is running me ?!");
167              return PAM_SERVICE_ERR;
168          }
169      }
170      
171      if (!use_group[0]) {
172          if ((grp = getgrnam("wheel")) == NULL) {
173              grp = getgrgid(0);
174          }
175      } else
176          grp = getgrnam(use_group);
177         
178      if (!grp || !grp->gr_mem) {
179         if (ctrl & PAM_DEBUG_ARG) {
180             if (!use_group[0])
181                 _pam_log(LOG_NOTICE,"no members in a GID 0 group");
182             else
183                 _pam_log(LOG_NOTICE,"no members in '%s' group",use_group);
184         }
185         if (ctrl & PAM_DENY_ARG)
186             /* if this was meant to deny access to the members
187              * of this group and the group does not exist, allow
188              * access
189              */
190             return PAM_IGNORE;
191         else
192             return PAM_AUTH_ERR;
193      }
194         
195      if (is_on_list(grp->gr_mem, fromsu)) {
196         if (ctrl & PAM_DEBUG_ARG)
197             _pam_log(LOG_NOTICE,"Access %s to '%s' for '%s'",
198                      (ctrl & PAM_DENY_ARG)?"denied":"granted",
199                      fromsu,username);
200         if (ctrl & PAM_DENY_ARG)
201             return PAM_PERM_DENIED;
202         else
203             if (ctrl & PAM_TRUST_ARG)
204                 return PAM_SUCCESS;
205             else
206                 return PAM_IGNORE;
207      }
208
209      if (ctrl & PAM_DEBUG_ARG)
210         _pam_log(LOG_NOTICE,"Access %s for '%s' to '%s'",
211         (ctrl & PAM_DENY_ARG)?"granted":"denied",fromsu,username);
212      if (ctrl & PAM_DENY_ARG)
213         return PAM_SUCCESS;
214      else
215         return PAM_PERM_DENIED;
216 }
217
218 PAM_EXTERN
219 int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
220                    ,const char **argv)
221 {
222      return PAM_SUCCESS;
223 }
224
225
226 /* end of module definition */
227
228 PAM_MODULE_ENTRY("pam_wheel");
229
230 /*
231  * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1996, 1997
232  *                                              All rights reserved
233  *
234  * Redistribution and use in source and binary forms, with or without
235  * modification, are permitted provided that the following conditions
236  * are met:
237  * 1. Redistributions of source code must retain the above copyright
238  *    notice, and the entire permission notice in its entirety,
239  *    including the disclaimer of warranties.
240  * 2. Redistributions in binary form must reproduce the above copyright
241  *    notice, this list of conditions and the following disclaimer in the
242  *    documentation and/or other materials provided with the distribution.
243  * 3. The name of the author may not be used to endorse or promote
244  *    products derived from this software without specific prior
245  *    written permission.
246  *
247  * ALTERNATIVELY, this product may be distributed under the terms of
248  * the GNU Public License, in which case the provisions of the GPL are
249  * required INSTEAD OF the above restrictions.  (This clause is
250  * necessary due to a potential bad interaction between the GPL and
251  * the restrictions contained in a BSD-style copyright.)
252  *
253  * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
254  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
255  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
256  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
257  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
258  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
259  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
260  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
261  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
262  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
263  * OF THE POSSIBILITY OF SUCH DAMAGE.
264  */