source: trunk/athena/lib/al/allowed.c @ 11483

Revision 11483, 6.0 KB checked in by ghudson, 26 years ago (diff)
Use al_get_access() now that it exists, instead of parsing the access file ourselves.
Line 
1/* Copyright 1997, 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16/* This file is part of the Athena login library.  It implements the
17 * function to check if a user is allowed to log in.
18 */
19
20static const char rcsid[] = "$Id: allowed.c,v 1.8 1998-05-07 17:11:01 ghudson Exp $";
21
22#include <errno.h>
23#include <hesiod.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <ctype.h>
28#include <unistd.h>
29#include <pwd.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include "al.h"
33#include "al_private.h"
34
35static int try_access(const char *username, int isremote, int *local_acct,
36                      char **text, int *retval);
37static int good_hesiod(const char *username, int *retval);
38
39/* The al_login_allowed() function determines whether a user is allowed
40 * to log in.  The calling process provides an indication of whether the
41 * login session is from a remote host.  The al_login_allowed() function
42 * has no side-effects.
43 *
44 * The al_login_allowed() function may return the following values:
45 *
46 *      AL_SUCCESS      The user may log in
47 *      AL_ENOUSER      Unknown user
48 *      AL_EBADHES      Illegal hesiod entry for user
49 *      AL_ENOLOGIN     Login denied because logins are disabled
50 *      AL_ENOREMOTE    Login denied because this user is not allowed
51 *                      to log in remotely
52 *      AL_ENOCREATE    Login denied because this user is not allowed
53 *                      to log in
54 *      AL_ENOMEM       Ran out of memory
55 *
56 * If al_login_allowed() returns AL_ENOLOGIN, AL_ENOREMOTE, or
57 * AL_ENOCREATE and text is not NULL, then *text is set to a malloc()'d
58 * string (which the caller must free) containing the text of the file
59 * which caused the login to be denied.  Otherwise, *text is set to NULL.
60 */
61
62int al_login_allowed(const char *username, int isremote, int *local_acct,
63                     char **text)
64{
65  struct passwd *local_pwd;
66  int retval = AL_SUCCESS;
67  char *retfname = NULL;
68  FILE *retfile;
69
70  /* Make sure *text gets set to NULL if we don't give it a value
71   * later.  Also, assume account is non-local for now.
72   */
73  if (text)
74    *text = NULL;
75  *local_acct = 0;
76
77  if (!al__username_valid(username))
78    return AL_ENOUSER;
79
80  /* root is always authorized to log in and is always a local account. */
81  local_pwd = al__getpwnam(username);
82  if (local_pwd && local_pwd->pw_uid == 0)
83    {
84      *local_acct = 1;
85      goto cleanup;
86    }
87
88  /* For all non-root users, honor the /etc/nologin file. */
89  if (!access(PATH_NOLOGIN, F_OK))
90    {
91      retval = AL_ENOLOGIN;
92      retfname = PATH_NOLOGIN;
93      goto cleanup;
94    }
95
96  /* Those without local passwd information must have Hesiod passwd
97   * information or they don't exist.
98   */
99  if (!local_pwd && !good_hesiod(username, &retval))
100    goto cleanup;
101
102  /* Try the access control file. */
103  if (try_access(username, isremote, local_acct, text, &retval))
104    goto cleanup;
105
106  /* There is no access control file.  Look at the nocreate and noremote
107   * files if the user has no local passwd information.
108   */
109  if (!local_pwd)
110    {
111      if (!access(PATH_NOCREATE, F_OK))
112        {
113          retval = AL_ENOCREATE;
114          retfname = PATH_NOCREATE;
115          goto cleanup;
116        }
117      if (isremote && !access(PATH_NOREMOTE, F_OK))
118        {
119          retval = AL_ENOREMOTE;
120          retfname = PATH_NOREMOTE;
121          goto cleanup;
122        }
123    }
124
125cleanup:
126  if (local_pwd)
127    al__free_passwd(local_pwd);
128  if (retfname && text)
129    {
130      retfile = fopen(retfname, "r");
131      if (retfile)
132        {
133          struct stat st;
134
135          if (!fstat(fileno(retfile), &st) && st.st_size > 0)
136            {
137              *text = malloc(1 + st.st_size);
138              if (*text)
139                {
140                  /* Zero all in case fewer chars read than expected. */
141                  memset(*text, 0, 1 + st.st_size);
142                  fread(*text, sizeof(char), st.st_size, retfile);
143                }
144            }
145          fclose(retfile);
146        }
147    }
148  return retval;
149}
150
151/* Using the access file, determine whether username has permission to
152 * log in and whether username has a local account.  On unsuccessful
153 * return, *text may be set to contain explanatory information from the
154 * access file. */
155static int try_access(const char *username, int isremote, int *local_acct,
156                      char **text, int *retval)
157{
158  char *bits, *accesstext;
159  const char *p;
160  int status;
161
162  status = al_get_access(username, &bits, &accesstext);
163  if (status == AL_ENOENT)
164    return 0;
165
166  *retval = AL_ENOCREATE;
167  if (status == AL_ENOUSER)
168    return 1;
169  for (p = bits; *p; p++)
170    {
171      if ((*p == 'l' && !isremote) || (*p == 'r' && isremote))
172        *retval = AL_SUCCESS;
173      if (*p == 'l' && isremote && *retval == AL_ENOCREATE)
174        *retval = AL_ENOREMOTE;
175      if (*p == 'L')
176        *local_acct = 1;
177    }
178  free(bits);
179  if (*retval != AL_SUCCESS && accesstext && text)
180    {
181      *text = malloc(strlen(accesstext) + 2);
182      if (*text)
183        {
184          strcpy(*text, accesstext);
185          strcat(*text, "\n");
186        }
187    }
188  if (accesstext)
189    free(accesstext);
190  return 1;
191}
192
193/* Check whether a user has Hesiod information which doesn't conflict
194 * with a local uid.
195 */
196static int good_hesiod(const char *username, int *retval)
197{
198  void *hescontext = NULL;
199  struct passwd *local_pwd, *hes_pwd;
200  int ok = 0;
201
202  if (hesiod_init(&hescontext) == 0)
203    {
204      hes_pwd = hesiod_getpwnam(hescontext, username);
205      if (hes_pwd)
206        {
207          local_pwd = al__getpwuid(hes_pwd->pw_uid);
208          if (local_pwd)
209            {
210              al__free_passwd(local_pwd);
211              *retval = AL_EBADHES;
212            }
213          else
214            ok = 1;
215          hesiod_free_passwd(hescontext, hes_pwd);
216        }
217      else
218        *retval = AL_ENOUSER;
219      hesiod_end(hescontext);
220    }
221  else
222    *retval = (errno == ENOMEM) ? AL_ENOMEM : AL_ENOUSER;
223  return ok;
224}
Note: See TracBrowser for help on using the repository browser.