]> git.sesse.net Git - betaftpd/blob - nonroot.c
Fixed a security problem where the custom snprintf() would always be used. Thanks...
[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 of 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_UNISTD_H
47 #include <unistd.h>
48 #endif
49
50 #if HAVE_STDLIB_H
51 #include <stdlib.h>
52 #endif
53
54 #if HAVE_CRYPT_H
55 #include <crypt.h>
56 #endif
57
58 #include <nonroot.h>
59
60 struct users {
61         char username[24];
62         char password[14];
63         char homedir[128];
64         uid_t uid;
65         gid_t gid;
66 };
67
68 /* we will add cacheing of both users and rights LATER :-) */
69
70 int nr_userinfo(const char * const username, int * const uid,
71                 char * const homedir, char * const rootdir,
72                 const char * const password) 
73 {
74         FILE *users_file = fopen(USERS_FILE, "r");
75         char this_username[256];
76         char real_password[256];
77
78         if (users_file == NULL) return 0; /* panic, reject all users */
79
80         /* 
81          * ignores gids atm, we may want to change that in the future
82          */
83         while (!feof(users_file)) {
84                 fscanf(users_file, "%d %s %s %s %s %*[^\n]\n", 
85                         uid, this_username, real_password, homedir, rootdir);
86                 if (strcmp(this_username, username) != 0) continue;
87
88                 fclose(users_file);
89
90                 printf("pw = %s\n", real_password);
91                 printf("uid = %u\n", *uid);
92                 printf("hdir = %s\n", homedir);
93                 printf("rdir = %s\nEND\n", rootdir);
94
95                 if (strcmp(real_password, crypt(password, real_password)) == 0) {
96                         return 3;
97                 } else {
98                         return 0;
99                 }
100         }
101         
102         fclose(users_file);
103         return 0;               /* no such user */
104 }
105
106 /*
107  * Thank goodness for the Unix inventors, who invented all those nice flags! :-)
108  * Reduces my code size a lot :-)
109  */
110 int nr_check_permission(const uid_t uid, const char * const object,
111                         const int perm, const int is_dir,
112                         char * const ret_rights)
113 {
114         char temp[256];
115
116         if (is_dir) {
117                 snprintf(temp, 256, "%s/.rights", object);
118                 return nr_intperm(uid, temp, ".", perm, ret_rights);
119         } else {
120                 char *ptr;
121
122                 snprintf(temp, 256, "%s", object);      /* non-overflow */
123
124                 ptr = strrchr(temp, '/');
125                 if (ptr == NULL) {
126                         return nr_intperm(uid, "./.rights", temp, perm, ret_rights);
127                 } else {
128                         char temp2[256];
129                         ptr[0] = 0;
130
131                         snprintf(temp2, 256, "%s/.rights", temp);
132                         return nr_intperm(uid, temp2, ptr + 1, perm, ret_rights);
133                 }
134         }
135 }
136
137 int nr_intperm(const uid_t uid, const char * const rightfile,
138                 const char * const entry, const int perm,
139                 char * const ret_rights)
140 {
141         FILE *rights = fopen(rightfile, "r");
142         char default_rights[] = "---------";
143         char this_entry[256], these_rights[16], check_rights[16], *ptr;
144         int rights_assigned = 0;
145         uid_t this_uid, check_uid;
146         gid_t this_gid, check_gid;
147
148         printf("Checking permission %u for uid %d, file `%s', entry `%s'\n",
149                 perm, uid, rightfile, entry);
150
151         {
152                 char buf[256];
153                 getcwd(buf, 256);
154                 printf("cwd is `%s'\n", buf);
155         }
156
157         if (rights == NULL) perror(rightfile);
158
159         if (ret_rights != NULL) strcpy(ret_rights, default_rights);
160         if (rights == NULL) return -1;  /* no rights file -- no permission */
161
162         while (!feof(rights)) {
163                 fscanf(rights, "%s %s %d %d\n", this_entry, these_rights,
164                         &this_uid, &this_gid);
165
166                 if (strcmp(this_entry, entry) == 0) rights_assigned = 1;
167                 if (strcmp(this_entry, ".default") == 0) rights_assigned = 2;
168
169                 if (rights_assigned != 0) {
170                         if (ret_rights != NULL) strcpy(ret_rights, these_rights);
171
172                         strcpy(check_rights, these_rights);
173                         check_uid = this_uid;
174                         check_gid = this_gid;
175
176                         /* if we found a `real' (non-default) match, break right away */
177                         if (rights_assigned == 1) break;
178                 }
179         }
180
181         if (rights_assigned == 0) {
182                 puts("no entry! denying...\n");
183                 return -1;      /* no entry, no access */
184         }
185
186         /* if we're only looking for at entry, return OK now */
187         if (perm == 0) {
188                 puts("Only peeking; OK\n");
189                 return 0;
190         }
191
192         /* now on to the actual checking... */
193         ptr = check_rights;
194         if (perm != 4) ptr++;           /* check the right bits */
195         if (perm == 1) ptr++;
196
197         printf("Actual rights are `%s', filtered: `%s'\n", check_rights, ptr);
198
199         if (ptr[6] != '-') return 0;                      /* all users */
200         if (uid == check_uid && ptr[0] != '-') return 0;  /* user owner */
201         if (member_of_group(uid, check_gid) && ptr[3] != '-') return 0;
202                                                           /* member of group */
203
204         return -1;              /* no access */
205 }
206
207 int member_of_group(const uid_t uid, const gid_t gid)
208 {
209         printf("For now, `%s' is not member of `%s'\n", 
210                 nr_get_uname(uid), nr_get_gname(gid));
211         return 0;
212 }
213
214 char username[256], groupname[256];     /* static buffer to return */
215
216 char *nr_get_uname(const uid_t uid)
217 {
218         FILE *users = fopen(USERS_FILE, "r");
219         uid_t uid_this;
220
221         if (users == NULL) return "error";      /* panic */
222
223         while (!feof(users)) {
224                 if (fscanf(users, "%d %s %*[^\n]\n", &uid_this, username) < 2) continue;
225                 if (uid_this == uid) return username;
226         }
227         snprintf(username, 256, "%d", uid);
228         return username;
229 }
230
231 char *nr_get_gname(const uid_t gid)
232 {
233         FILE *group = fopen(GROUP_FILE, "r");
234         gid_t gid_this;
235
236         if (group == NULL) return "error";      /* panic */
237
238         while (!feof(group)) {
239                 if (fscanf(group, "%d %s\n", &gid_this, groupname) < 2) continue;
240                 if (gid_this == gid) return groupname;
241         }
242         snprintf(groupname, 256, "%d", gid);
243         return groupname;
244 }
245
246 #endif /* !WANT_NONROOT */