Mercurial > illumos > onarm
annotate usr/src/cmd/cmd-inet/usr.sbin/in.ftpd/private.c @ 4:1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Mon, 31 Aug 2009 14:38:03 +0900 |
parents | c9caec207d52 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. | |
3 * Use is subject to license terms. | |
4 */ | |
5 | |
4
1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
Koji Uno <koji.uno@sun.com>
parents:
0
diff
changeset
|
6 #pragma ident "%Z%%M% %I% %E% SMI" |
0 | 7 |
8 /**************************************************************************** | |
9 Copyright (c) 1999,2000 WU-FTPD Development Group. | |
10 All rights reserved. | |
11 | |
12 Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994 | |
13 The Regents of the University of California. | |
14 Portions Copyright (c) 1993, 1994 Washington University in Saint Louis. | |
15 Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc. | |
16 Portions Copyright (c) 1989 Massachusetts Institute of Technology. | |
17 Portions Copyright (c) 1998 Sendmail, Inc. | |
18 Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P. Allman. | |
19 Portions Copyright (c) 1997 by Stan Barber. | |
20 Portions Copyright (c) 1997 by Kent Landfield. | |
21 Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997 | |
22 Free Software Foundation, Inc. | |
23 | |
24 Use and distribution of this software and its source code are governed | |
25 by the terms and conditions of the WU-FTPD Software License ("LICENSE"). | |
26 | |
27 If you did not receive a copy of the license, it may be obtained online | |
28 at http://www.wu-ftpd.org/license.html. | |
29 | |
30 $Id: private.c,v 1.12 2000/07/01 18:17:39 wuftpd Exp $ | |
31 | |
32 ****************************************************************************/ | |
33 #include "config.h" | |
34 | |
35 #ifndef NO_PRIVATE | |
36 | |
37 #include <stdio.h> | |
38 #include <errno.h> | |
39 | |
40 extern char *strsep(char **, const char *); | |
41 | |
42 #include <string.h> | |
43 #ifdef HAVE_SYS_SYSLOG_H | |
44 #include <sys/syslog.h> | |
45 #endif | |
46 #if defined(HAVE_SYSLOG_H) || (!defined(AUTOCONF) && !defined(HAVE_SYS_SYSLOG_H)) | |
47 #include <syslog.h> | |
48 #endif | |
49 #include <grp.h> | |
50 | |
51 #include <sys/types.h> | |
52 #include <sys/stat.h> | |
53 #include <sys/file.h> | |
54 | |
55 #ifdef HAVE_PATHS_H | |
56 #include <paths.h> | |
57 #endif | |
58 #include "pathnames.h" | |
59 #include "extensions.h" | |
60 #include "proto.h" | |
61 | |
62 #ifdef SECUREOSF | |
63 #define SecureWare /* Does this mean it works for all SecureWare? */ | |
64 #endif | |
65 | |
66 #ifdef HPUX_10_TRUSTED | |
67 #include <hpsecurity.h> | |
68 #endif | |
69 | |
70 #if defined(SecureWare) || defined(HPUX_10_TRUSTED) | |
71 #include <prot.h> | |
72 #endif | |
73 | |
74 #ifndef NO_CRYPT_PROTO | |
75 extern char *crypt(const char *, const char *); | |
76 #endif | |
77 | |
78 static int group_attempts, group_given; | |
79 static char *groupname, *passbuf; | |
80 | |
81 struct acgrp { | |
82 char *gname; /* access group name */ | |
83 char *gpass; /* access group password */ | |
84 gid_t gr_gid; /* group to setegid() to */ | |
85 struct acgrp *next; | |
86 }; | |
87 | |
88 static struct acgrp *privptr, *privtail; | |
89 | |
90 extern int lgi_failure_threshold; | |
91 extern char remoteident[]; | |
92 | |
93 static void add_acgrp(char *gname, char *gpass, gid_t gid) | |
94 { | |
95 struct acgrp *aptr; | |
96 | |
97 aptr = (struct acgrp *) calloc(1, sizeof(struct acgrp)); | |
98 if (aptr == NULL) { | |
99 syslog(LOG_ERR, "calloc error in add_acgrp"); | |
100 dologout(1); | |
101 } | |
102 | |
103 /* add element to end of list */ | |
104 if (privtail) | |
105 privtail->next = aptr; | |
106 privtail = aptr; | |
107 if (!privptr) | |
108 privptr = aptr; | |
109 | |
110 aptr->gname = strdup(gname); | |
111 if (aptr->gname == NULL) { | |
112 syslog(LOG_ERR, "malloc error in add_acgrp"); | |
113 dologout(1); | |
114 } | |
115 if (gpass == NULL) | |
116 aptr->gpass = strdup(""); | |
117 else | |
118 aptr->gpass = strdup(gpass); | |
119 if (aptr->gpass == NULL) { | |
120 syslog(LOG_ERR, "malloc error in add_acgrp"); | |
121 dologout(1); | |
122 } | |
123 aptr->gr_gid = gid; | |
124 } | |
125 | |
126 static void parsepriv(void) | |
127 { | |
128 char *ptr; | |
129 char *acptr = passbuf, *line; | |
130 char *argv[3], *p, *val; | |
131 struct group *gr; | |
132 int n; | |
133 | |
134 if (!passbuf || !(*passbuf)) | |
135 return; | |
136 | |
137 /* read through passbuf, stripping comments. */ | |
138 while (*acptr != '\0') { | |
139 line = acptr; | |
140 while (*acptr && *acptr != '\n') | |
141 acptr++; | |
142 *acptr++ = '\0'; | |
143 | |
144 /* deal with comments */ | |
145 if ((ptr = strchr(line, '#')) != NULL) | |
146 *ptr = '\0'; | |
147 | |
148 if (*line == '\0') | |
149 continue; | |
150 | |
151 /* parse the lines... */ | |
152 for (n = 0, p = line; n < 3 && p != NULL; n++) { | |
153 val = (char *) strsep(&p, ":\n"); | |
154 argv[n] = val; | |
155 if ((argv[n][0] == ' ') || (argv[n][0] == '\0')) | |
156 argv[n] = NULL; | |
157 } | |
158 /* check their were 3 fields, if not skip the line... */ | |
159 if (n != 3 || p != NULL) | |
160 continue; | |
161 | |
162 if (argv[0] && argv[2]) { | |
163 if (argv[2][0] == '%') { | |
164 gid_t gid = atoi(argv[2] + 1); | |
165 if ((gr = getgrgid(gid)) != NULL) | |
166 add_acgrp(argv[0], argv[1], gid); | |
167 } | |
168 else { | |
169 if ((gr = getgrnam((char *) argv[2])) != NULL) | |
170 add_acgrp(argv[0], argv[1], gr->gr_gid); | |
171 } | |
172 endgrent(); | |
173 } | |
174 } | |
175 } | |
176 | |
177 /*************************************************************************/ | |
178 /* FUNCTION : priv_setup */ | |
179 /* PURPOSE : Set things up to use the private access password file. */ | |
180 /* ARGUMENTS : path, the path to the private access password file */ | |
181 /*************************************************************************/ | |
182 | |
183 void priv_setup(char *path) | |
184 { | |
185 FILE *prvfile; | |
186 struct stat finfo; | |
187 struct acgrp *aptr; | |
188 | |
189 while (privptr) { | |
190 aptr = privptr->next; | |
191 free(privptr->gname); | |
192 free(privptr->gpass); | |
193 free(privptr); | |
194 privptr = aptr; | |
195 } | |
196 privtail = NULL; | |
197 | |
198 if (passbuf) { | |
199 free(passbuf); | |
200 passbuf = NULL; | |
201 } | |
202 | |
203 if ((prvfile = fopen(path, "r")) == NULL) { | |
204 if (errno != ENOENT) | |
205 syslog(LOG_ERR, "cannot open private access file %s: %s", | |
206 path, strerror(errno)); | |
207 return; | |
208 } | |
209 if (fstat(fileno(prvfile), &finfo) != 0) { | |
210 syslog(LOG_ERR, "cannot fstat private access file %s: %s", path, | |
211 strerror(errno)); | |
212 (void) fclose(prvfile); | |
213 return; | |
214 } | |
215 if (finfo.st_size == 0) { | |
216 passbuf = (char *) calloc(1, 1); | |
217 } | |
218 else { | |
219 if (!(passbuf = (char *) malloc((size_t) finfo.st_size + 1))) { | |
220 (void) syslog(LOG_ERR, "could not malloc passbuf (%d bytes)", | |
221 (size_t) finfo.st_size + 1); | |
222 (void) fclose(prvfile); | |
223 return; | |
224 } | |
225 if (!fread(passbuf, (size_t) finfo.st_size, 1, prvfile)) { | |
226 (void) syslog(LOG_ERR, "error reading private access file %s: %s", | |
227 path, strerror(errno)); | |
228 (void) fclose(prvfile); | |
229 return; | |
230 } | |
231 *(passbuf + finfo.st_size) = '\0'; | |
232 } | |
233 (void) fclose(prvfile); | |
234 (void) parsepriv(); | |
235 } | |
236 | |
237 /*************************************************************************/ | |
238 /* FUNCTION : priv_getent */ | |
239 /* PURPOSE : Retrieve an entry from the in-memory copy of the group */ | |
240 /* access file. */ | |
241 /* ARGUMENTS : pointer to group name */ | |
242 /*************************************************************************/ | |
243 | |
244 static struct acgrp *priv_getent(char *group) | |
245 { | |
246 struct acgrp *ptr; | |
247 | |
248 for (ptr = privptr; ptr; ptr = ptr->next) | |
249 if (!strcasecmp(group, ptr->gname)) | |
250 return (ptr); | |
251 | |
252 return (NULL); | |
253 } | |
254 | |
255 /*************************************************************************/ | |
256 /* FUNCTION : priv_group */ | |
257 /* PURPOSE : */ | |
258 /* ARGUMENTS : */ | |
259 /*************************************************************************/ | |
260 | |
261 void priv_group(char *group) | |
262 { | |
263 if (groupname) | |
264 free(groupname); | |
265 | |
266 groupname = strdup(group); | |
267 if (groupname == NULL) { | |
268 reply(421, "Local resource failure: malloc"); | |
269 syslog(LOG_ERR, "malloc error in priv_group"); | |
270 dologout(1); | |
271 } | |
272 group_given = 1; | |
273 reply(200, "Request for access to group %s accepted.", group); | |
274 } | |
275 | |
276 /*************************************************************************/ | |
277 /* FUNCTION : priv_gpass */ | |
278 /* PURPOSE : validate the group access request, and if OK place user */ | |
279 /* in the proper group. */ | |
280 /* ARGUMENTS : group access password */ | |
281 /*************************************************************************/ | |
282 | |
283 void priv_gpass(char *gpass) | |
284 { | |
285 char *xgpass = NULL; | |
286 struct acgrp *grp; | |
287 uid_t uid; | |
288 | |
289 if (group_given == 0) { | |
290 reply(503, "Give group name with SITE GROUP first."); | |
291 return; | |
292 } | |
293 /* OK, now they're getting a chance to specify a password. Make them | |
294 * give the group name again if they fail... */ | |
295 group_given = 0; | |
296 | |
297 grp = priv_getent(groupname); | |
298 if (passbuf && gpass && *gpass != '\0' && grp && *grp->gpass != '\0') | |
299 #if defined(SecureWare) || defined(HPUX_10_TRUSTED) | |
300 xgpass = bigcrypt(gpass, grp->gpass); | |
301 #else | |
302 xgpass = crypt(gpass, grp->gpass); | |
303 #endif | |
304 | |
305 if (!(((gpass != NULL) | |
306 && (*gpass != '\0') | |
307 && (grp != NULL) | |
308 && (*grp->gpass != '\0') | |
309 && (strcmp(xgpass, grp->gpass) == 0)) | |
310 || (((gpass == NULL) | |
311 || (*gpass == '\0')) | |
312 && (grp != NULL) | |
313 && (*grp->gpass == '\0')) | |
314 )) { | |
315 reply(530, "Group access request incorrect."); | |
316 grp = NULL; | |
317 if (++group_attempts >= lgi_failure_threshold) { | |
318 syslog(LOG_NOTICE, | |
319 "repeated group access failures from %s, group %s", | |
320 remoteident, groupname); | |
321 dologout(0); | |
322 } | |
323 sleep(group_attempts); /* slow down password crackers */ | |
324 return; | |
325 } | |
326 | |
327 uid = geteuid(); | |
328 setid_priv_on(0); | |
329 setegid(grp->gr_gid); | |
330 setid_priv_off(uid); | |
331 | |
332 reply(200, "Group access enabled."); | |
333 group_attempts = 0; | |
334 } | |
335 #endif /* !NO_PRIVATE */ |