5a25e53a0c4312887f845327aedbe348ec1f7b15
[krb5.git] / src / lib / krb5 / os / kuserok.c
1 /*
2  * lib/krb5/os/kuserok.c
3  *
4  * Copyright 1990,1993 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  * 
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  M.I.T. makes no representations about the suitability of
20  * this software for any purpose.  It is provided "as is" without express
21  * or implied warranty.
22  * 
23  *
24  * krb5_kuserok()
25  */
26
27 #include "k5-int.h"
28 #ifndef _MSDOS    /* Not yet for Windows */
29 #include <stdio.h>
30 #include <pwd.h>
31
32 #if defined(_AIX) && defined(_IBMR2)
33 #include <sys/access.h>
34 /* xlc has a bug with "const" */
35 #define getpwnam(user) getpwnam((char *)user)
36 #endif
37
38 #define MAX_USERNAME 10
39
40 /*
41  * Given a Kerberos principal "principal", and a local username "luser",
42  * determine whether user is authorized to login according to the
43  * authorization file ("~luser/.k5login" by default).  Returns TRUE
44  * if authorized, FALSE if not authorized.
45  *
46  * If there is no account for "luser" on the local machine, returns
47  * FALSE.  If there is no authorization file, and the given Kerberos
48  * name "server" translates to the same name as "luser" (using
49  * krb5_aname_to_lname()), returns TRUE.  Otherwise, if the authorization file
50  * can't be accessed, returns FALSE.  Otherwise, the file is read for
51  * a matching principal name, instance, and realm.  If one is found,
52  * returns TRUE, if none is found, returns FALSE.
53  *
54  * The file entries are in the format produced by krb5_unparse_name(),
55  * one entry per line.
56  *
57  */
58
59 krb5_boolean
60 krb5_kuserok(context, principal, luser)
61     krb5_context context;
62     krb5_principal principal;
63     const char *luser;
64 {
65     struct stat sbuf;
66     struct passwd *pwd;
67     char pbuf[MAXPATHLEN];
68     krb5_boolean isok = FALSE;
69     FILE *fp;
70     char kuser[MAX_USERNAME];
71     char *princname;
72     char linebuf[BUFSIZ];
73     char *newline;
74     int gobble;
75
76     /* no account => no access */
77     if ((pwd = getpwnam(luser)) == NULL) {
78         return(FALSE);
79     }
80     (void) strcpy(pbuf, pwd->pw_dir);
81     (void) strcat(pbuf, "/.k5login");
82
83     if (access(pbuf, F_OK)) {    /* not accessible */
84         /*
85          * if he's trying to log in as himself, and there is no .k5login file,
86          * let him.  To find out, call
87          * krb5_aname_to_localname to convert the principal to a name
88          * which we can string compare. 
89          */
90         if (!(krb5_aname_to_localname(context, principal,
91                                       sizeof(kuser), kuser))
92             && (strcmp(kuser, luser) == 0)) {
93             return(TRUE);
94         }
95     }
96     if (krb5_unparse_name(context, principal, &princname))
97         return(FALSE);                  /* no hope of matching */
98
99     /* open ~/.k5login */
100     if ((fp = fopen(pbuf, "r")) == NULL) {
101         free(princname);
102         return(FALSE);
103     }
104     /*
105      * For security reasons, the .k5login file must be owned either by
106      * the user himself, or by root.  Otherwise, don't grant access.
107      */
108     if (fstat(fileno(fp), &sbuf)) {
109         fclose(fp);
110         free(princname);
111         return(FALSE);
112     }
113     if ((sbuf.st_uid != pwd->pw_uid) && sbuf.st_uid) {
114         fclose(fp);
115         free(princname);
116         return(FALSE);
117     }
118
119     /* check each line */
120     while (!isok && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
121         /* null-terminate the input string */
122         linebuf[BUFSIZ-1] = '\0';
123         newline = NULL;
124         /* nuke the newline if it exists */
125         if (newline = strchr(linebuf, '\n'))
126             *newline = '\0';
127         if (!strcmp(linebuf, princname)) {
128             isok = TRUE;
129             continue;
130         }
131         /* clean up the rest of the line if necessary */
132         if (!newline)
133             while (((gobble = getc(fp)) != EOF) && gobble != '\n');
134     }
135     free(princname);
136     fclose(fp);
137     return(isok);
138 }
139
140 #else /* _MSDOS */
141
142 /*
143  * If the given Kerberos name "server" translates to the same name as "luser"
144  * (using * krb5_aname_to_lname()), returns TRUE.
145  */
146 krb5_boolean INTERFACE
147 krb5_kuserok(context, principal, luser)
148     krb5_context context;
149     krb5_principal principal;
150     const char *luser;
151 {
152     char kuser[50];
153
154     if (! krb5_aname_to_localname(context, principal, sizeof(kuser), kuser))
155         return FALSE;
156
157     if (strcmp(kuser, luser) == 0)
158             return TRUE;
159
160     return FALSE;
161 }
162 #endif /* _MSDOS */