]> git.sesse.net Git - betaftpd/blob - nonroot.c
Updated documentation to tell that root can't FTP anymore.
[betaftpd] / nonroot.c
1 /*  nonroot.c: Various database functions for rights and users
2     Copyright (C) 1999-2000 Steinar H. Gunderson
3
4     This program is is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License, version 2 if the
6     License as published by the Free Software Foundation.
7
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12
13     You should have received a copy of the GNU General Public License
14     along with this program; if not, write to the Free Software
15     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 */
17
18 /*
19  * make autoconf changeable!!!
20  */
21 #define USERS_FILE "/home/betaftpd/betaftpd.users"
22 #define GROUP_FILE "/home/betaftpd/betaftpd.groups"
23
24 #if HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #if WANT_NONROOT
29
30 #if HAVE_SYS_TYPES_H
31 #include <sys/types.h>
32 #endif
33
34 #if HAVE_STDIO_H
35 #include <stdio.h>
36 #endif
37
38 #if HAVE_STRING_H
39 #include <string.h>
40 #endif
41
42 #if HAVE_STRINGS_H
43 #include <strings.h>
44 #endif
45
46 #if HAVE_CONFIG_H
47 #include <config.h>
48 #endif
49
50 #if HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif
53
54 #if HAVE_STDLIB_H
55 #include <stdlib.h>
56 #endif
57
58 #if HAVE_CRYPT_H
59 #include <crypt.h>
60 #endif
61
62 #include <nonroot.h>
63
64 struct users {
65         char username[24];
66         char password[14];
67         char homedir[128];
68         uid_t uid;
69         gid_t gid;
70 };
71
72 /* we will add cacheing of both users and rights LATER :-) */
73
74 int nr_userinfo(const char * const username, int * const uid,
75                 char * const homedir, char * const rootdir,
76                 const char * const password) 
77 {
78         FILE *users_file = fopen(USERS_FILE, "r");
79         char this_username[256];
80         char real_password[256];
81
82         if (users_file == NULL) return 0; /* panic, reject all users */
83
84         /* 
85          * ignores gids atm, we may want to change that in the future
86          */
87         while (!feof(users_file)) {
88                 fscanf(users_file, "%d %s %s %s %s %*[^\n]\n", 
89                         uid, this_username, real_password, homedir, rootdir);
90                 if (strcmp(this_username, username) != 0) continue;
91
92                 fclose(users_file);
93
94                 printf("pw = %s\n", real_password);
95                 printf("uid = %u\n", *uid);
96                 printf("hdir = %s\n", homedir);
97                 printf("rdir = %s\nEND\n", rootdir);
98
99                 if (strcmp(real_password, crypt(password, real_password)) == 0) {
100                         return 3;
101                 } else {
102                         return 0;
103                 }
104         }
105         
106         fclose(users_file);
107         return 0;               /* no such user */
108 }
109
110 /*
111  * Thank goodness for the Unix inventors, who invented all those nice flags! :-)
112  * Reduces my code size a lot :-)
113  */
114 int nr_check_permission(const uid_t uid, const char * const object,
115                         const int perm, const int is_dir,
116                         char * const ret_rights)
117 {
118         char temp[256];
119
120         if (is_dir) {
121                 snprintf(temp, 256, "%s/.rights", object);
122                 return nr_intperm(uid, temp, ".", perm, ret_rights);
123         } else {
124                 char *ptr;
125
126                 snprintf(temp, 256, "%s", object);      /* non-overflow */
127
128                 ptr = strrchr(temp, '/');
129                 if (ptr == NULL) {
130                         return nr_intperm(uid, "./.rights", temp, perm, ret_rights);
131                 } else {
132                         char temp2[256];
133                         ptr[0] = 0;
134
135                         snprintf(temp2, 256, "%s/.rights", temp);
136                         return nr_intperm(uid, temp2, ptr + 1, perm, ret_rights);
137                 }
138         }
139 }
140
141 int nr_intperm(const uid_t uid, const char * const rightfile,
142                 const char * const entry, const int perm,
143                 char * const ret_rights)
144 {
145         FILE *rights = fopen(rightfile, "r");
146         char default_rights[] = "---------";
147         char this_entry[256], these_rights[16], check_rights[16], *ptr;
148         int rights_assigned = 0;
149         uid_t this_uid, check_uid;
150         gid_t this_gid, check_gid;
151
152         printf("Checking permission %u for uid %d, file `%s', entry `%s'\n",
153                 perm, uid, rightfile, entry);
154
155         {
156                 char buf[256];
157                 getcwd(buf, 256);
158                 printf("cwd is `%s'\n", buf);
159         }
160
161         if (rights == NULL) perror(rightfile);
162
163         if (ret_rights != NULL) strcpy(ret_rights, default_rights);
164         if (rights == NULL) return -1;  /* no rights file -- no permission */
165
166         while (!feof(rights)) {
167                 fscanf(rights, "%s %s %d %d\n", this_entry, these_rights,
168                         &this_uid, &this_gid);
169
170                 /*
171                  * a bit (a BIT?) ugly, perhaps (PERHAPS?)
172                  * note: no typo, it's supposed to be a single `=' sign
173                  */
174                 if ((strcmp(this_entry, entry) == 0 && (rights_assigned = 1)) ||
175                     (strcmp(this_entry, ".default") == 0 &&
176                       strcmp(this_entry, ".rights")  != 0 &&
177                       rights_assigned == 0)) {
178                         if (ret_rights != NULL) strcpy(ret_rights, these_rights);
179
180                         strcpy(check_rights, these_rights);
181                         check_uid = this_uid;
182                         check_gid = this_gid;
183                         if (rights_assigned == 1) break;
184                         rights_assigned = 1;
185                 }
186         }
187
188         if (rights_assigned == 0) puts("no entry! denying...\n");
189         if (rights_assigned == 0) return -1;    /* no entry, no access */
190
191         /* if we're only looking for at entry, return OK now */
192         if (perm == 0) {
193                 puts("Only peeking; OK\n");
194                 return 0;
195         }
196
197         /* now on to the actual checking... */
198         ptr = check_rights;
199         if (perm != 4) ptr++;           /* check the right bits */
200         if (perm == 1) ptr++;
201
202         printf("Actual rights are `%s', filtered: `%s'\n", check_rights, ptr);
203
204         if (ptr[6] != '-') return 0;                      /* all users */
205         if (uid == check_uid && ptr[0] != '-') return 0;  /* user owner */
206         if (member_of_group(uid, check_gid) && ptr[3] != '-') return 0;
207                                                           /* member of group */
208
209         return -1;              /* no access */
210 }
211
212 int member_of_group(const uid_t uid, const gid_t gid)
213 {
214         printf("For now, `%s' is not member of `%s'\n", 
215                 nr_get_uname(uid), nr_get_gname(gid));
216         return 0;
217 }
218
219 char username[256], groupname[256];     /* static buffer to return */
220
221 char *nr_get_uname(const uid_t uid)
222 {
223         FILE *users = fopen(USERS_FILE, "r");
224         uid_t uid_this;
225
226         if (users == NULL) return "error";      /* panic */
227
228         while (!feof(users)) {
229                 if (fscanf(users, "%d %s %*[^\n]\n", &uid_this, username) < 2) continue;
230                 if (uid_this == uid) return username;
231         }
232         snprintf(username, 256, "%d", uid);
233         return username;
234 }
235
236 char *nr_get_gname(const uid_t gid)
237 {
238         FILE *group = fopen(GROUP_FILE, "r");
239         gid_t gid_this;
240
241         if (group == NULL) return "error";      /* panic */
242
243         while (!feof(group)) {
244                 if (fscanf(group, "%d %s\n", &gid_this, groupname) < 2) continue;
245                 if (gid_this == gid) return groupname;
246         }
247         snprintf(groupname, 256, "%d", gid);
248         return groupname;
249 }
250
251 #endif /* !WANT_NONROOT */