1 /*
2 * This file implements the following functions:
3 * pam_modutil_search_key:
4 * lookup a value for key in login.defs file or similar key value format
5 */
6
7 #include "config.h"
8
9 #include "pam_private.h"
10 #include "pam_modutil_private.h"
11 #include <security/pam_ext.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <ctype.h>
16 #ifdef USE_ECONF
17 #include <libeconf.h>
18 #endif
19
20 #define BUF_SIZE 8192
21
22 #ifdef USE_ECONF
23 #define LOGIN_DEFS "/etc/login.defs"
24
25 #ifndef VENDORDIR
26 #define VENDORDIR NULL
27 #endif
28
29 static char *
30 econf_search_key (const char *name, const char *suffix, const char *key)
31 {
32 econf_file *key_file = NULL;
33 char *val;
34
35 if (econf_readDirs (&key_file, VENDORDIR, SYSCONFDIR, name, suffix,
36 " \t", "#"))
37 return NULL;
38
39 if (econf_getStringValue (key_file, NULL, key, &val)) {
40 econf_free (key_file);
41 return NULL;
42 }
43
44 econf_free (key_file);
45
46 return val;
47 }
48
49 #endif
50
51 /* lookup a value for key in login.defs file or similar key value format */
52 char *
53 pam_modutil_search_key(pam_handle_t *pamh UNUSED,
54 const char *file_name,
55 const char *key)
56 {
57 FILE *fp;
58 char *buf = NULL;
59 size_t buflen = 0;
60 char *retval = NULL;
61
62 #ifdef USE_ECONF
63 if (strcmp (file_name, LOGIN_DEFS) == 0)
64 return econf_search_key ("login", ".defs", key);
65 #endif
66
67 fp = fopen(file_name, "r");
68 if (NULL == fp)
69 return NULL;
70
71 while (!feof(fp)) {
72 char *tmp, *cp;
73 #if defined(HAVE_GETLINE)
74 ssize_t n = getline(&buf, &buflen, fp);
75 #elif defined (HAVE_GETDELIM)
76 ssize_t n = getdelim(&buf, &buflen, '\n', fp);
77 #else
78 ssize_t n;
79
80 if (buf == NULL) {
81 buflen = BUF_SIZE;
82 buf = malloc(buflen);
83 if (buf == NULL) {
84 fclose(fp);
85 return NULL;
86 }
87 }
88 buf[0] = '\0';
89 if (fgets(buf, buflen - 1, fp) == NULL)
90 break;
91 else if (buf != NULL)
92 n = strlen(buf);
93 else
94 n = 0;
95 #endif /* HAVE_GETLINE / HAVE_GETDELIM */
96 cp = buf;
97
98 if (n < 1)
99 break;
100 if (cp[n - 1] == '\n')
101 cp[n - 1] = '\0';
102
103 tmp = strchr(cp, '#'); /* remove comments */
104 if (tmp)
105 *tmp = '\0';
106 while (isspace((int)*cp)) /* remove spaces and tabs */
107 ++cp;
108 if (*cp == '\0') /* ignore empty lines */
109 continue;
110
111 tmp = strsep (&cp, " \t=");
112 if (cp != NULL)
113 while (isspace((int)*cp) || *cp == '=')
114 ++cp;
115 else
116 cp = buf + n; /* empty string */
117
118 if (strcasecmp(tmp, key) == 0) {
119 retval = strdup(cp);
120 break;
121 }
122 }
123 fclose(fp);
124
125 free(buf);
126
127 return retval;
128 }