1 /** Fichier db.c
2 **
3 ** Routines de gestion des mots de passe et des fichiers
4 ** de configuration pour calife.
5 **
6 ** Copyright (c) 1991-2010 by Ollivier ROBERT
7 ** A distribuer selon les regles de la GNU GPL General Public Licence
8 ** Voir le fichier COPYING fourni.
9 **
10 **/
11
12 #ifndef lint
13 static const char * rcsid = "@(#) $Id$";
14 #endif
15
16 #include "config.h" /* GNU configure */
17
18 /* fichier de configuration */
19 #include "conf.h"
20
21 static FILE * fp = NULL; /* Moved from calife.c */
22
23 /** On cherche et ouvre la database locale.
24 **
25 ** Dans tous les cas, le fichier log est ouvert (il est local). Si syslogd(8)
26 ** est actif on ouvre le "fichier" pour syslog(3). Le fichier de log devient
27 ** maintenant dependant de NO_SYSLOG: s'il n'y a pas de syslog d'utilisable
28 ** alors on ouvre le fichier de log.
29 **
30 ** Parametres : neant
31 **
32 ** Retourne : int s'il y a un probleme renvoie 1 sinon 0.
33 **/
34
35 int
open_databases(void)36 open_databases (void)
37 {
38 int err;
39
40 MESSAGE ("Opening databases...\n");
41 /*
42 * become root again
43 */
44 GET_ROOT;
45
46 /*
47 * open protected database
48 */
49 fp = fopen (AUTH_CONFIG_FILE, "r");
50 if (fp == NULL)
51 {
52 syslog (LOG_AUTH | LOG_ERR, "No database in `%s', launching su...\n", AUTH_CONFIG_FILE);
53 MESSAGE_1 ("No database in `%s'...\n", AUTH_CONFIG_FILE);
54 return 1;
55 }
56 else
57 {
58 /*
59 * XXX Is this still necessary?
60 */
61 err = fchmod (fileno (fp), 0400);
62 if (err)
63 die(6, "Unable to change '%s' permissions.", AUTH_CONFIG_FILE);
64 /*NOTREACHED*/
65 }
66 /*
67 * stay non root for a time
68 */
69 RELEASE_ROOT;
70 /*
71 * Success
72 */
73 return 0;
74 }
75
76 /** Verifie si l'utilisateur de nom name a le droit d'utiliser
77 ** calife.
78 **
79 ** Line format is :
80 **
81 ** login[:][shell][:user1,user2,user3,...]
82 ** @group[:][shell][:user1,user2,...]
83 **
84 ** Parametres : name char * nom de l'utilisateur
85 ** user_to_be char * futur nom d'utilisateur
86 **
87 ** Retourne : int 1 si l'utilisateur est autorise 0 sinon.
88 **/
89
90 int
verify_auth_info(char * name,char * user_to_be)91 verify_auth_info (char * name, char * user_to_be)
92 {
93 int allowed = 0;
94 char ** user_list = NULL;
95 size_t l_line = 0;
96 int nb_users = 0;
97 char * line, * ptr;
98 char * line_name, * line_shell;
99 char * group_name = NULL, * group = NULL, **p;
100 struct group *gr_group;
101
102 /*
103 * let's search if user allowed or not
104 */
105 #ifdef HAVE_WORKING_SYSCONF
106 l_line = (size_t) sysconf (_SC_LINE_MAX); /* returns long usually */
107 #else
108 l_line = MAX_STRING;
109 #endif /* HAVE_WORKING_SYSCONF */
110
111 line = (char *) xalloc (l_line);
112 while (!feof (fp))
113 {
114 int lastc;
115
116 if (fgets (line, l_line, fp) == NULL)
117 break;
118 /*
119 * remove trailing '\n' if present
120 */
121 lastc = strlen (line) - 1;
122 if (line [lastc] == '\n')
123 line [lastc] = '\0';
124 /*
125 * empty line or comment or null login -- not allowed but ignored
126 */
127 if (!line || (*line) == '#' || (*line) == '\0')
128 continue;
129 MESSAGE_1 ("Line read = |%s|\n", line);
130 line_name = line;
131 /*
132 * Look for a @ or % as first character (for groups)
133 */
134 if (*line == '@' || *line == '%')
135 {
136 group = strdup(line);
137 group_name = strtok(group, ":");
138 group_name++; /* skip '@' */
139 /*
140 * Look into /etc/groups (or its equivalent with get)
141 */
142 gr_group = (struct group *) getgrnam(group_name);
143 if (gr_group == NULL)
144 {
145 die(1, "No such group %s", group_name);
146 allowed = 0;
147 goto end;
148 }
149 for ( p = &gr_group->gr_mem[0]; *p ; p++ )
150 {
151 MESSAGE_3 ("matching %s to %s in %s\n", name, *p, group_name);
152 if (strcmp(name, *p) == 0)
153 {
154 MESSAGE_2 ("User %s Allowed through group %s\n", name, group_name);
155 _group = strdup (group_name);
156 strcpy (_group, group_name);
157 allowed = 2;
158 break;
159 }
160 }
161 }
162 /*
163 * Look for first ':'
164 */
165 ptr = strchr (line, ':');
166 if (ptr == NULL)
167 {
168 /*
169 * No shell and no user list
170 */
171 custom_shell = 0;
172
173 /*
174 * Bypass if already allowed through group
175 */
176 if (group_name != NULL && allowed == 1)
177 goto escape;
178 if (strcmp (line_name, name)) /* not us */
179 continue;
180 goto escape;
181 }
182 /*
183 * I got a ':', put a '\0' instead.
184 */
185 *ptr++ = '\0';
186 /*
187 * Do we have anything behind ?
188 */
189 if (*ptr == '\0')
190 custom_shell = 0;
191
192 MESSAGE_2 ("Current line_name = |%s| / name = |%s|\n", line_name,name);
193
194 /*
195 * Bypass if already allowed through group
196 */
197 if (group_name != NULL && allowed != 0)
198 goto end;
199 if (strcmp (line_name, name)) /* not us */
200 continue;
201
202 line_shell = ptr;
203 /*
204 * Look for another ':', maybe just after the first one
205 */
206 ptr = strchr (line_shell, ':');
207 if (ptr == line_shell)
208 custom_shell = 0;
209 /*
210 * If we got another one, put a '\0' instead
211 */
212 if (ptr)
213 *ptr++ = '\0';
214 /*
215 * Analyze the shell candidate
216 */
217 if (*(line_shell) == '*') /* LOCKED ACCOUNT */
218 {
219 allowed = 0;
220 goto end;
221 }
222 /*
223 * look for pathname
224 */
225 if (*(line_shell) == '/')
226 {
227 /*
228 * Is this a real shell ?
229 */
230 if (access (line_shell, R_OK | X_OK))
231 {
232 MESSAGE_1 (" access of |%s| failed, no custom_shell\n",
233 line_shell);
234 custom_shell = 0;
235 }
236 else
237 {
238 custom_shell = 1;
239 shell = (char *) xalloc (strlen (line_shell) + 1);
240 strncpy (shell, line_shell, strlen (line_shell));
241 shell [strlen (line_shell)] = '\0';
242 MESSAGE_1 (" current line_shell = |%s|\n", line_shell);
243 }
244 }
245 else
246 {
247 custom_shell = 0;
248 }
249 MESSAGE_1 (" custom_shell = |%d|\n", custom_shell);
250
251 /*
252 * Analyze the rest of the line
253 */
254 if (ptr)
255 {
256 MESSAGE_1 ("ptr = %s\n", ptr);
257 /*
258 * we've got a user list
259 */
260 if (*ptr)
261 {
262 char * p, ** q;
263
264 MESSAGE_1 (" current user_list = |%s|\n", ptr);
265 /*
266 * the list should be user1,user2,...,user_n
267 */
268 p = ptr; /* count users # in the list */
269 while (p && *p)
270 if (*p++ == ',')
271 nb_users++;
272 if (*--p != ',') /* last char is not a ',' */
273 nb_users++;
274
275 MESSAGE_1 (" users # = |%d|\n", nb_users);
276
277 /*
278 * two passes to avoid fixed size allocations
279 */
280 user_list = (char **) xalloc((nb_users + 1) * sizeof(char *));
281 /*
282 * put pointers in user_list
283 */
284 p = ptr;
285 q = user_list;
286 /*
287 * 1st user is immediate
288 */
289 (*q++) = p;
290 while (p && *p)
291 {
292 if (*p == ',') /* found a ',' */
293 {
294 *p = '\0';
295 if (*++p == ',')
296 continue;
297 (*q++) = p++; /* next char is user name */
298 }
299 else
300 p++; /* only regular letters */
301 }
302 }
303 }
304 /*
305 * user_list is complete, now compare
306 */
307 escape:
308 if (user_list)
309 {
310 int i;
311
312 for ( i = 0; i < nb_users; i++ )
313 {
314 MESSAGE_2(" comparing |%s| to |%s|\n",
315 user_to_be, user_list [i]);
316 if (!strcmp (user_list [i], user_to_be))
317 {
318 allowed = 1;
319 goto end; /* beuh but too many loops */
320 }
321 }
322 }
323 else
324 {
325 allowed = 1;
326 break;
327 }
328 }
329 end:
330 free (line);
331 if (group)
332 free(group);
333 if (user_list)
334 free (user_list);
335 fclose (fp);
336 if (geteuid() == 0)
337 allowed = 1;
338 MESSAGE_1 ("Exit from verify_auth_info with allowed=%d\n", allowed);
339 return allowed;
340 }
341
342