Initial commit for Tizen
[profile/extras/shadow-utils.git] / lib / getdef.c
1 /*
2  * Copyright (c) 1991 - 1994, Julianne Frances Haugh
3  * Copyright (c) 1996 - 2000, Marek Michałkiewicz
4  * Copyright (c) 2002 - 2006, Tomasz Kłoczko
5  * Copyright (c) 2007 - 2008, Nicolas François
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the copyright holders or contributors may not be used to
17  *    endorse or promote products derived from this software without
18  *    specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <config.h>
34
35 #ident "$Id: getdef.c 2772 2009-04-23 11:46:46Z nekral-guest $"
36
37 #include "prototypes.h"
38 #include "defines.h"
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <ctype.h>
42 #include <errno.h>
43 #include "getdef.h"
44 /*
45  * A configuration item definition.
46  */
47 struct itemdef {
48         /*@null@*/const char *name;     /* name of the item                     */
49         /*@null@*/char *value;          /* value given, or NULL if no value     */
50 };
51
52 #define NUMDEFS (sizeof(def_table)/sizeof(def_table[0]))
53 static struct itemdef def_table[] = {
54         {"CHFN_RESTRICT", NULL},
55         {"CONSOLE_GROUPS", NULL},
56         {"CONSOLE", NULL},
57         {"CREATE_HOME", NULL},
58         {"DEFAULT_HOME", NULL},
59         {"ENCRYPT_METHOD", NULL},
60         {"ENV_PATH", NULL},
61         {"ENV_SUPATH", NULL},
62         {"ERASECHAR", NULL},
63         {"FAIL_DELAY", NULL},
64         {"FAKE_SHELL", NULL},
65         {"GID_MAX", NULL},
66         {"GID_MIN", NULL},
67         {"HUSHLOGIN_FILE", NULL},
68         {"KILLCHAR", NULL},
69         {"LOGIN_RETRIES", NULL},
70         {"LOGIN_TIMEOUT", NULL},
71         {"LOG_OK_LOGINS", NULL},
72         {"LOG_UNKFAIL_ENAB", NULL},
73         {"MAIL_DIR", NULL},
74         {"MAIL_FILE", NULL},
75         {"MAX_MEMBERS_PER_GROUP", NULL},
76         {"MD5_CRYPT_ENAB", NULL},
77         {"PASS_MAX_DAYS", NULL},
78         {"PASS_MIN_DAYS", NULL},
79         {"PASS_WARN_AGE", NULL},
80 #ifdef USE_SHA_CRYPT
81         {"SHA_CRYPT_MAX_ROUNDS", NULL},
82         {"SHA_CRYPT_MIN_ROUNDS", NULL},
83 #endif
84         {"SULOG_FILE", NULL},
85         {"SU_NAME", NULL},
86         {"SYS_GID_MAX", NULL},
87         {"SYS_GID_MIN", NULL},
88         {"SYS_UID_MAX", NULL},
89         {"SYS_UID_MIN", NULL},
90         {"TTYGROUP", NULL},
91         {"TTYPERM", NULL},
92         {"TTYTYPE_FILE", NULL},
93         {"UID_MAX", NULL},
94         {"UID_MIN", NULL},
95         {"UMASK", NULL},
96         {"USERDEL_CMD", NULL},
97         {"USERGROUPS_ENAB", NULL},
98 #ifndef USE_PAM
99         {"CHFN_AUTH", NULL},
100         {"CHSH_AUTH", NULL},
101         {"CRACKLIB_DICTPATH", NULL},
102         {"ENV_HZ", NULL},
103         {"ENVIRON_FILE", NULL},
104         {"ENV_TZ", NULL},
105         {"FAILLOG_ENAB", NULL},
106         {"FTMP_FILE", NULL},
107         {"ISSUE_FILE", NULL},
108         {"LASTLOG_ENAB", NULL},
109         {"LOGIN_STRING", NULL},
110         {"MAIL_CHECK_ENAB", NULL},
111         {"MOTD_FILE", NULL},
112         {"NOLOGINS_FILE", NULL},
113         {"OBSCURE_CHECKS_ENAB", NULL},
114         {"PASS_ALWAYS_WARN", NULL},
115         {"PASS_CHANGE_TRIES", NULL},
116         {"PASS_MAX_LEN", NULL},
117         {"PASS_MIN_LEN", NULL},
118         {"PORTTIME_CHECKS_ENAB", NULL},
119         {"QUOTAS_ENAB", NULL},
120         {"SU_WHEEL_ONLY", NULL},
121         {"ULIMIT", NULL},
122 #endif
123 #ifdef USE_SYSLOG
124         {"SYSLOG_SG_ENAB", NULL},
125         {"SYSLOG_SU_ENAB", NULL},
126 #endif
127         {NULL, NULL}
128 };
129
130 #ifndef LOGINDEFS
131 #define LOGINDEFS "/etc/login.defs"
132 #endif
133
134 static char def_fname[] = LOGINDEFS;    /* login config defs file       */
135 static bool def_loaded = false;         /* are defs already loaded?     */
136
137 /* local function prototypes */
138 static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *);
139 static void def_load (void);
140
141
142 /*
143  * getdef_str - get string value from table of definitions.
144  *
145  * Return point to static data for specified item, or NULL if item is not
146  * defined.  First time invoked, will load definitions from the file.
147  */
148
149 /*@observer@*/ /*@null@*/const char *getdef_str (const char *item)
150 {
151         struct itemdef *d;
152
153         if (!def_loaded) {
154                 def_load ();
155         }
156
157         d = def_find (item);
158         return ((NULL == d)? (const char *) NULL : d->value);
159 }
160
161
162 /*
163  * getdef_bool - get boolean value from table of definitions.
164  *
165  * Return TRUE if specified item is defined as "yes", else FALSE.
166  */
167
168 bool getdef_bool (const char *item)
169 {
170         struct itemdef *d;
171
172         if (!def_loaded) {
173                 def_load ();
174         }
175
176         d = def_find (item);
177         if ((NULL == d) || (NULL == d->value)) {
178                 return false;
179         }
180
181         return (strcasecmp (d->value, "yes") == 0);
182 }
183
184
185 /*
186  * getdef_num - get numerical value from table of definitions
187  *
188  * Returns numeric value of specified item, else the "dflt" value if
189  * the item is not defined.  Octal (leading "0") and hex (leading "0x")
190  * values are handled.
191  */
192
193 int getdef_num (const char *item, int dflt)
194 {
195         struct itemdef *d;
196         long val;
197
198         if (!def_loaded) {
199                 def_load ();
200         }
201
202         d = def_find (item);
203         if ((NULL == d) || (NULL == d->value)) {
204                 return dflt;
205         }
206
207         if (   (getlong (d->value, &val) == 0)
208             || (val > INT_MAX)
209             || (val < INT_MIN)) {
210                 fprintf (stderr,
211                          _("configuration error - cannot parse %s value: '%s'"),
212                          item, d->value);
213                 return dflt;
214         }
215
216         return (int) val;
217 }
218
219
220 /*
221  * getdef_unum - get unsigned numerical value from table of definitions
222  *
223  * Returns numeric value of specified item, else the "dflt" value if
224  * the item is not defined.  Octal (leading "0") and hex (leading "0x")
225  * values are handled.
226  */
227
228 unsigned int getdef_unum (const char *item, unsigned int dflt)
229 {
230         struct itemdef *d;
231         long val;
232
233         if (!def_loaded) {
234                 def_load ();
235         }
236
237         d = def_find (item);
238         if ((NULL == d) || (NULL == d->value)) {
239                 return dflt;
240         }
241
242         if (   (getlong (d->value, &val) == 0)
243             || (val < 0)
244             || (val > INT_MAX)) {
245                 fprintf (stderr,
246                          _("configuration error - cannot parse %s value: '%s'"),
247                          item, d->value);
248                 return dflt;
249         }
250
251         return (unsigned int) val;
252 }
253
254
255 /*
256  * getdef_long - get long integer value from table of definitions
257  *
258  * Returns numeric value of specified item, else the "dflt" value if
259  * the item is not defined.  Octal (leading "0") and hex (leading "0x")
260  * values are handled.
261  */
262
263 long getdef_long (const char *item, long dflt)
264 {
265         struct itemdef *d;
266         long val;
267
268         if (!def_loaded) {
269                 def_load ();
270         }
271
272         d = def_find (item);
273         if ((NULL == d) || (NULL == d->value)) {
274                 return dflt;
275         }
276
277         if (getlong (d->value, &val) == 0) {
278                 fprintf (stderr,
279                          _("configuration error - cannot parse %s value: '%s'"),
280                          item, d->value);
281                 return dflt;
282         }
283
284         return val;
285 }
286
287 /*
288  * getdef_ulong - get unsigned long numerical value from table of definitions
289  *
290  * Returns numeric value of specified item, else the "dflt" value if
291  * the item is not defined.  Octal (leading "0") and hex (leading "0x")
292  * values are handled.
293  */
294
295 unsigned long getdef_ulong (const char *item, unsigned long dflt)
296 {
297         struct itemdef *d;
298         unsigned long val;
299
300         if (!def_loaded) {
301                 def_load ();
302         }
303
304         d = def_find (item);
305         if ((NULL == d) || (NULL == d->value)) {
306                 return dflt;
307         }
308
309         if (getulong (d->value, &val) == 0) {
310                 /* FIXME: we should have a getulong */
311                 fprintf (stderr,
312                          _("configuration error - cannot parse %s value: '%s'"),
313                          item, d->value);
314                 return dflt;
315         }
316
317         return val;
318 }
319
320 /*
321  * putdef_str - override the value read from /etc/login.defs
322  * (also used when loading the initial defaults)
323  */
324
325 int putdef_str (const char *name, const char *value)
326 {
327         struct itemdef *d;
328         char *cp;
329
330         if (!def_loaded) {
331                 def_load ();
332         }
333
334         /*
335          * Locate the slot to save the value.  If this parameter
336          * is unknown then "def_find" will print an err message.
337          */
338         d = def_find (name);
339         if (NULL == d) {
340                 return -1;
341         }
342
343         /*
344          * Save off the value.
345          */
346         cp = strdup (value);
347         if (NULL == cp) {
348                 (void) fputs (_("Could not allocate space for config info.\n"),
349                               stderr);
350                 SYSLOG ((LOG_ERR, "could not allocate space for config info"));
351                 return -1;
352         }
353
354         if (NULL != d->value) {
355                 free (d->value);
356         }
357
358         d->value = cp;
359         return 0;
360 }
361
362
363 /*
364  * def_find - locate named item in table
365  *
366  * Search through a table of configurable items to locate the
367  * specified configuration option.
368  */
369
370 static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
371 {
372         struct itemdef *ptr;
373
374
375         /*
376          * Search into the table.
377          */
378
379         for (ptr = def_table; NULL != ptr->name; ptr++) {
380                 if (strcmp (ptr->name, name) == 0) {
381                         return ptr;
382                 }
383         }
384
385         /*
386          * Item was never found.
387          */
388
389         fprintf (stderr,
390                  _("configuration error - unknown item '%s' (notify administrator)\n"),
391                  name);
392         SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name));
393         return (struct itemdef *) NULL;
394 }
395
396 /*
397  * def_load - load configuration table
398  *
399  * Loads the user-configured options from the default configuration file
400  */
401
402 static void def_load (void)
403 {
404         int i;
405         FILE *fp;
406         char buf[1024], *name, *value, *s;
407
408         /*
409          * Open the configuration definitions file.
410          */
411         fp = fopen (def_fname, "r");
412         if (NULL == fp) {
413                 int err = errno;
414                 SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]",
415                          def_fname, strerror (err)));
416                 exit (EXIT_FAILURE);
417         }
418
419         /*
420          * Set the initialized flag.
421          * (do it early to prevent recursion in putdef_str())
422          */
423         def_loaded = true;
424
425         /*
426          * Go through all of the lines in the file.
427          */
428         while (fgets (buf, (int) sizeof (buf), fp) != NULL) {
429
430                 /*
431                  * Trim trailing whitespace.
432                  */
433                 for (i = (int) strlen (buf) - 1; i >= 0; --i) {
434                         if (!isspace (buf[i])) {
435                                 break;
436                         }
437                 }
438                 i++;
439                 buf[i] = '\0';
440
441                 /*
442                  * Break the line into two fields.
443                  */
444                 name = buf + strspn (buf, " \t");       /* first nonwhite */
445                 if (*name == '\0' || *name == '#')
446                         continue;       /* comment or empty */
447
448                 s = name + strcspn (name, " \t");       /* end of field */
449                 if (*s == '\0')
450                         continue;       /* only 1 field?? */
451
452                 *s++ = '\0';
453                 value = s + strspn (s, " \"\t");        /* next nonwhite */
454                 *(value + strcspn (value, "\"")) = '\0';
455
456                 /*
457                  * Store the value in def_table.
458                  *
459                  * Ignore failures to load the login.defs file.
460                  * The error was already reported to the user and to
461                  * syslog. The tools will just use their default values.
462                  */
463                 (void)putdef_str (name, value);
464         }
465
466         if (ferror (fp) != 0) {
467                 int err = errno;
468                 SYSLOG ((LOG_CRIT, "cannot read login definitions %s [%s]",
469                          def_fname, strerror (err)));
470                 exit (EXIT_FAILURE);
471         }
472
473         (void) fclose (fp);
474 }
475
476
477 #ifdef CKDEFS
478 int main (int argc, char **argv)
479 {
480         int i;
481         char *cp;
482         struct itemdef *d;
483
484         def_load ();
485
486         for (i = 0; i < NUMDEFS; ++i) {
487                 d = def_find (def_table[i].name);
488                 if (NULL == d) {
489                         printf ("error - lookup '%s' failed\n",
490                                 def_table[i].name);
491                 } else {
492                         printf ("%4d %-24s %s\n", i + 1, d->name, d->value);
493                 }
494         }
495         for (i = 1; i < argc; i++) {
496                 cp = getdef_str (argv[1]);
497                 if (NULL != cp) {
498                         printf ("%s `%s'\n", argv[1], cp);
499                 } else {
500                         printf ("%s not found\n", argv[1]);
501                 }
502         }
503         exit (EXIT_SUCCESS);
504 }
505 #endif