2 * compat.c Compatibity routines for fgetpwent(), fgetspent(), and fgetgrent()
4 * The code in here was borrowed from the cache.c module
5 * and adapted to be a standalone set of functions.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * Copyright 2001 The FreeRADIUS server project.
25 static const char rcsid[] = "$Id$";
28 #include "libradius.h"
35 #include <sys/types.h>
48 #ifndef HAVE_FGETPWENT
50 struct passwd *rad_fgetpwent(FILE *pwhandle) {
51 static struct passwd pwbuf;
52 static char username[MAX_STRING_LEN];
53 static char userpwd[64];
54 static char gecostmp[128];
55 static char homedirtmp[128];
56 static char shelltmp[128];
65 #define RAD_EXTRACT_FIELD(txt_field, tmp_buf) \
66 for(bufptr = ptr; (*ptr != '\0') && (*ptr != '\n') && (*ptr != ':'); ptr++); \
68 if((len+1) > sizeof(tmp_buf)) { \
69 radlog(L_ERR, "rlm_unix: %s too long in line: %s", (txt_field), buffer); \
70 return rad_fgetpwent(pwhandle); \
72 strncpy((tmp_buf), bufptr, len); \
73 (tmp_buf)[len] = '\0';
80 if (fgets(buffer, BUFSIZE , pwhandle) == (char *)NULL)
83 memset(&pwbuf, 0, sizeof(struct passwd));
84 memset(username, 0, sizeof(username));
85 memset(userpwd, 0, sizeof(userpwd));
86 memset(gecostmp, 0, sizeof(gecostmp));
87 memset(homedirtmp, 0, sizeof(homedirtmp));
88 memset(shelltmp, 0, sizeof(shelltmp));
89 buffer[BUFSIZE] ='\0';
91 /* Get usernames from the password file */
93 RAD_EXTRACT_FIELD("Username", username);
94 pwbuf.pw_name = username;
96 /* Get (encrypted) password from password file (shadow comes later) */
97 if (*ptr != '\0') ptr++;
98 RAD_EXTRACT_FIELD("Password", userpwd);
99 pwbuf.pw_passwd = userpwd;
101 /* Get uid from the password file */
102 if (*ptr != '\0') ptr++;
103 RAD_EXTRACT_FIELD("UID", uidtmp);
104 pwbuf.pw_uid = atoi(uidtmp);
106 /* Get gid from the password file */
107 if (*ptr != '\0') ptr++;
108 RAD_EXTRACT_FIELD("GID", gidtmp);
109 pwbuf.pw_gid = atoi(gidtmp);
111 /* Get the GECOS (name) field from the password file */
112 if (*ptr != '\0') ptr++;
113 RAD_EXTRACT_FIELD("GECOS", gecostmp);
114 pwbuf.pw_gecos = gecostmp;
116 /* Get the home directory from the password file */
117 if (*ptr != '\0') ptr++;
118 RAD_EXTRACT_FIELD("Home dir", homedirtmp);
119 pwbuf.pw_dir = homedirtmp;
121 /* Get the shell from the password file */
122 if (*ptr != '\0') ptr++;
123 RAD_EXTRACT_FIELD("Shell", shelltmp);
124 pwbuf.pw_shell = shelltmp;
129 #undef RAD_EXTRACT_FIELD
131 #endif /* HAVE_FGETPWENT */
136 #ifndef HAVE_FGETSPENT
138 shadow_pwd_t *rad_fgetspent(FILE *sphandle) {
139 static shadow_pwd_t spbuf;
140 static char username[MAX_STRING_LEN];
141 static char userpwd[64];
149 char buffer[BUFSIZE];
152 #define RAD_EXTRACT_FIELD(txt_field, tmp_buf) \
153 for(bufptr = ptr; (*ptr != '\0') && (*ptr != '\n') && (*ptr != ':'); ptr++); \
154 len = ptr - bufptr; \
155 if((len+1) > sizeof(tmp_buf)) { \
156 radlog(L_ERR, "rlm_unix: %s too long in line: %s", (txt_field), buffer); \
157 return rad_fgetspent(sphandle); \
159 strncpy((tmp_buf), bufptr, len); \
160 (tmp_buf)[len] = '\0';
164 if (sphandle == NULL)
167 if (fgets(buffer, BUFSIZE, sphandle) == (char *)NULL)
170 memset(&spbuf, 0, sizeof(shadow_pwd_t));
171 memset(username, 0, sizeof(username));
172 memset(userpwd, 0, sizeof(userpwd));
173 buffer[BUFSIZE] ='\0';
175 /* Get usernames from the shadow file */
177 RAD_EXTRACT_FIELD("Username", username);
178 GET_SP_NAME(&spbuf) = username;
180 /* Get (encrypted) passwords from the shadow file */
181 if (*ptr != '\0') ptr++;
182 RAD_EXTRACT_FIELD("Password", userpwd);
183 GET_SP_PWD(&spbuf) = userpwd;
185 /* Get the 'last change' field from the shadow file */
187 if (*ptr != '\0') ptr++;
188 RAD_EXTRACT_FIELD("'Last change'", lastchgtmp);
189 GET_SP_LSTCHG(&spbuf) = atoi(lastchgtmp);
192 /* Get the 'minimum time between changes' field from the shadow file */
194 if (*ptr != '\0') ptr++;
195 RAD_EXTRACT_FIELD("'Min change'", mintmp);
196 GET_SP_MIN(&spbuf) = atoi(mintmp);
199 /* Get the 'maximum time between changes' field from the shadow file */
201 if (*ptr != '\0') ptr++;
202 RAD_EXTRACT_FIELD("'Max change'", maxtmp);
203 GET_SP_MAX(&spbuf) = atoi(maxtmp);
206 /* Get the 'expire warning time' field from the shadow file */
208 if (*ptr != '\0') ptr++;
209 RAD_EXTRACT_FIELD("'Warn time'", warntmp);
210 GET_SP_WARN(&spbuf) = atoi(warntmp);
213 /* Get the 'account inactivity time' field from the shadow file */
215 if (*ptr != '\0') ptr++;
216 RAD_EXTRACT_FIELD("'Inactive time'", inactmp);
217 GET_SP_INACT(&spbuf) = atoi(inactmp);
220 /* Get the 'expire time' field from the shadow file */
222 if (*ptr != '\0') ptr++;
223 RAD_EXTRACT_FIELD("'Expire time'", expiretmp);
224 GET_SP_EXPIRE(&spbuf) = atoi(expiretmp);
229 #undef RAD_EXTRACT_FIELD
231 #endif /* HAVE_FGETSPENT */
235 #ifndef HAVE_FGETGRENT
237 #define RAD_MAX_GROUP_MEMBERS 500
239 struct group *rad_fgetgrent(FILE *grhandle) {
240 static struct group grbuf;
241 static char grname[MAX_STRING_LEN];
242 static char grpwd[64];
243 static char *grmem[RAD_MAX_GROUP_MEMBERS];
244 static char grmembuf[2048];
246 char *ptr, *bufptr, *grptr;
247 char buffer[BUFSIZE];
252 #define RAD_EXTRACT_FIELD(txt_field, tmp_buf) \
253 for(bufptr = ptr; (*ptr != '\0') && (*ptr != '\n') && (*ptr != ':'); ptr++); \
254 len = ptr - bufptr; \
255 if((len+1) > sizeof(tmp_buf)) { \
256 radlog(L_ERR, "rlm_unix: %s too long in line: %s", (txt_field), buffer); \
257 return rad_fgetgrent(grhandle); \
259 strncpy((tmp_buf), bufptr, len); \
260 (tmp_buf)[len] = '\0';
264 if (grhandle == NULL)
267 if (fgets(buffer, BUFSIZE, grhandle) == (char *)NULL)
270 memset(&grbuf, 0, sizeof(struct group));
271 memset(grname, 0, sizeof(grname));
272 memset(grpwd, 0, sizeof(grpwd));
273 memset(grmem, 0, sizeof(grmem));
274 memset(grmembuf, 0, sizeof(grmembuf));
275 buffer[BUFSIZE] ='\0';
277 /* Get the group name */
279 RAD_EXTRACT_FIELD("Group name", grname);
280 grbuf.gr_name = grname;
282 /* Get the group password */
283 if (*ptr != '\0') ptr++;
284 RAD_EXTRACT_FIELD("Group password", grpwd);
285 grbuf.gr_passwd = grpwd;
287 /* Get the group id */
288 if (*ptr != '\0') ptr++;
289 RAD_EXTRACT_FIELD("Group ID", gidtmp);
290 grbuf.gr_gid = atoi(gidtmp);
292 /* Collect all of the group members... */
294 grbuf.gr_mem = grmem;
295 grbuf.gr_mem[gidx] = NULL;
297 while (*ptr != '\0') {
298 if (*ptr != '\0') ptr++;
299 for(bufptr = ptr; (*ptr != '\0') && (*ptr != '\n') && (*ptr != ','); ptr++);
302 /* Ignore "NULL" entries... */
303 if (len == 0) continue;
305 if((len+1) > (sizeof(grmembuf) - (grptr - grmembuf))) {
306 radlog(L_ERR, "rlm_unix: Some entries dropped. Group members line too long: %s", buffer);
307 /* Return a partial list */
311 /* Prevent buffer overflows! */
312 if (gidx+1 >= RAD_MAX_GROUP_MEMBERS) {
313 radlog(L_ERR, "rlm_unix: Some entries dropped. Too many group members: %s", buffer);
314 /* Return a partial list */
318 strncpy(grptr, bufptr, len);
320 grbuf.gr_mem[gidx++] = grptr;
321 grbuf.gr_mem[gidx] = NULL;
328 #undef RAD_EXTRACT_FIELD
330 #endif /* HAVE_FGETGRENT */