comparison usr/src/cmd/cmd-inet/usr.sbin/in.ftpd/private.c @ 0:c9caec207d52 b86

Initial porting based on b86
author Koji Uno <koji.uno@sun.com>
date Tue, 02 Jun 2009 18:56:50 +0900
parents
children 1a15d5aaf794
comparison
equal deleted inserted replaced
-1:000000000000 0:c9caec207d52
1 /*
2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "@(#)private.c 1.4 04/12/14 SMI"
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 */