xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/in.ftpd/privatepw.c (revision 0:68f95e015346)
1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2 
3 /****************************************************************************
4 
5    Copyright (c) 1999,2000 WU-FTPD Development Group.
6    All rights reserved.
7 
8    Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994
9    The Regents of the University of California.  Portions Copyright (c)
10    1993, 1994 Washington University in Saint Louis.  Portions Copyright
11    (c) 1996, 1998 Berkeley Software Design, Inc.  Portions Copyright (c)
12    1998 Sendmail, Inc.  Portions Copyright (c) 1983, 1995, 1996, 1997 Eric
13    P. Allman.  Portions Copyright (c) 1989 Massachusetts Institute of
14    Technology.  Portions Copyright (c) 1997 by Stan Barber.  Portions
15    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997 Free Software
16    Foundation, Inc.  Portions Copyright (c) 1997 by Kent Landfield.
17 
18    Use and distribution of this software and its source code are governed
19    by the terms and conditions of the WU-FTPD Software License ("LICENSE").
20 
21    $Id: privatepw.c,v 1.10 2000/07/01 18:43:59 wuftpd Exp $
22 
23 ****************************************************************************/
24 /*
25    Subsystem:  WU-FTPD FTP Server
26    Purpose:    Change WU-FTPD Guest Passwords
27    File Name:  privatepw.c
28 
29    usage: privatepw [-c] [-f passwordfile] [-g group] accessgroup
30    privatepw [-d] [-f passwordfile] accessgroup
31    privatepw [-l] [-f passwordfile]
32    -c:           creates a new file.
33    -d:           deletes specified accessgroup.
34    -l:           list contents of ftpgroups file.
35    -f ftpgroups: updates the specified file.
36    -g group:     set real group to the specified group.
37 
38    This software was initially written by Kent Landfield (kent@landfield.com)
39  */
40 
41 #include <sys/types.h>
42 #include <sys/signal.h>
43 #include <sys/stat.h>
44 #include <string.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <time.h>
48 #include <grp.h>
49 #include <unistd.h>
50 #include "config.h"
51 #include "pathnames.h"
52 
53 #define BUFLEN 256
54 #define GROUPLEN 8
55 
56 char *tmp;
57 char line[BUFLEN];
58 FILE *fp;
59 int verbose = 0;
60 
61 static unsigned char itoa64[] =	/* 0 ... 63 => ascii - 64 */
62 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
63 
64 void print_copyright(void);
65 
usage(void)66 static void usage(void)
67 {
68     fprintf(stderr, "usage: privatepw [-c] [-f ftpgroups] [-g group] accessgroup\n");
69     fprintf(stderr, "       privatepw [-d] [-f ftpgroups] accessgroup\n");
70     fprintf(stderr, "       privatepw [-l] [-f ftpgroups]\n");
71     fprintf(stderr, "\t\t-c:           creates a new file.\n");
72     fprintf(stderr, "\t\t-d:           deletes specified accessgroup.\n");
73     fprintf(stderr, "\t\t-l:           list contents of ftpgroups file.\n");
74     fprintf(stderr, "\t\t-f ftpgroups: updates the specified file.\n");
75     fprintf(stderr, "\t\t-g group:     set real group to the specified group.\n");
76     exit(1);
77 }
78 
to64(register char * s,register long v,register int n)79 static void to64(register char *s, register long v, register int n)
80 {
81     while (--n >= 0) {
82 	*s++ = itoa64[v & 0x3f];
83 	v >>= 6;
84     }
85 }
86 
terminate(void)87 static void terminate(void)
88 {
89     if (tmp)
90 	unlink(tmp);
91     exit(1);
92 }
93 
catchintr(void)94 static void catchintr(void)
95 {
96     fprintf(stderr, "Interrupted.\n");
97     terminate();
98 }
99 
savit(char * s)100 static char *savit(char *s)
101 {
102     char *d;
103 
104     if ((d = (char *) malloc(strlen(s) + 1)) == NULL) {
105 	fprintf(stderr, "Whoa... Malloc failed.\n");
106 	terminate();
107     }
108     strcpy(d, s);
109     return (d);
110 }
111 
confirmed(char * accessgroup)112 static int confirmed(char *accessgroup)
113 {
114     register int ch;
115 
116     printf("Delete %s: Are your sure ? (y/n) ", accessgroup);
117     ch = getc(stdin);
118     if (ch == 'y')
119 	return (1);
120     return (0);
121 }
122 
getgroup(char * msg)123 static char *getgroup(char *msg)
124 {
125     register int ch;
126     register char *p;
127     static char buf[GROUPLEN + 1];
128 
129     fputs(msg, stderr);
130     rewind(stderr);		/* implied flush */
131     for (p = buf; (ch = getc(stdin)) != EOF && ch != '\n';)
132 	if (p < buf + GROUPLEN)
133 	    *p++ = ch;
134     *p = '\0';
135 
136     if (getgrnam(buf) == NULL) {
137 	fprintf(stderr, "Invalid group \'%s\' specified\n", buf);
138 	terminate();
139     }
140     return (buf);
141 }
142 
addrecord(char * accessgroup,char * sysgroup,char * msg,FILE * f)143 static void addrecord(char *accessgroup, char *sysgroup, char *msg, FILE *f)
144 {
145     char *pw, *cpw, salt[3];
146 #ifndef NO_CRYPT_PROTO
147     extern char *crypt(const char *, const char *);
148 #endif
149     char *getpass(const char *prompt);
150 
151     printf("%s %s\n", msg, accessgroup);
152 
153     if (sysgroup[0] == '\0')
154 	strcpy(sysgroup, getgroup("Real System Group to use: "));
155 
156     pw = savit((char *) getpass("New password: "));
157     if (strcmp(pw, (char *) getpass("Re-type new password: "))) {
158 	fprintf(stderr, "They don't match, sorry.\n");
159 	if (tmp)
160 	    unlink(tmp);
161 	exit(1);
162     }
163 
164     srand((int) time((time_t *) NULL));
165     to64(&salt[0], rand(), 2);
166     cpw = crypt(pw, salt);
167     free(pw);
168     fprintf(f, "%s:%s:%s\n", accessgroup, cpw, sysgroup);
169 }
170 
list_privatefile(char * privatefile)171 static void list_privatefile(char *privatefile)
172 {
173     if (verbose)
174 	fprintf(stderr, "Private File: %s file.\n", privatefile);
175 
176     if ((fp = fopen(privatefile, "r")) == NULL) {
177 	fprintf(stderr, "Could not open %s file.\n", privatefile);
178 	exit(1);
179     }
180 
181     printf("\nWU-FTPD Private file: %s\n", privatefile);
182     printf("accessgroup : password : system group\n");
183     printf("-------\n");
184 
185     while (fgets(line, BUFLEN, fp) != NULL)
186 	fputs(line, stdout);
187     printf("-------\n");
188 }
189 
main(int argc,char ** argv)190 int main(int argc, char **argv)
191 {
192     extern void (*signal(int sig, void (*disp) (int))) (int);
193     extern int getopt(int argc, char *const *argv, const char *optstring);
194     extern char *optarg;
195     extern int optind;
196     extern int opterr;
197 
198     struct stat stbuf;
199 
200     char realgroup[BUFLEN];
201     char *passwdpath;
202     char *cp;
203 
204     char accessgroup[BUFLEN];
205     char w[BUFLEN];
206     char command[BUFLEN];
207 
208     int create;
209     int delete;
210     int list;
211     int found;
212     int lineno;
213     int c;
214 
215     FILE *tfp;
216 
217 #ifdef HAVE_MKSTEMP
218     char tmpname[BUFLEN];
219     int tfd;
220 #endif
221 
222     opterr = 0;
223     create = 0;
224     delete = 0;
225     list = 0;
226 
227     tmp = NULL;
228     realgroup[0] = '\0';
229 
230     passwdpath = _PATH_PRIVATE;
231 
232     if (argc == 1)
233 	usage();
234 
235     while ((c = getopt(argc, argv, "Vvcdf:g:l")) != EOF) {
236 	switch (c) {
237 	case 'd':
238 	    delete++;
239 	    break;
240 	case 'c':
241 	    create++;
242 	    break;
243 	case 'f':
244 	    passwdpath = optarg;
245 	    break;
246 	case 'g':
247 	    strcpy(realgroup, optarg);
248 	    if (getgrnam(realgroup) == NULL) {
249 		fprintf(stderr, "Invalid group \'%s\' specified\n", realgroup);
250 		return (1);
251 	    }
252 	    break;
253 	case 'l':
254 	    list++;
255 	    break;
256 	case 'v':
257 	    verbose++;
258 	    break;
259 	case 'V':
260 	    print_copyright();
261 	    return (0);
262 	    /* NOTREACHED */
263 	default:
264 	    usage();
265 	}
266     }
267 
268     if (list) {
269 	list_privatefile(passwdpath);
270 	return (0);
271     }
272 
273     if (optind >= argc) {
274 	fprintf(stderr, "Need to specify an accessgroup name.\n");
275 	usage();
276     }
277 
278     signal(SIGINT, (void (*)()) catchintr);
279 
280     strcpy(accessgroup, argv[optind]);
281 
282     if (create) {
283 	if (stat(passwdpath, &stbuf) == 0) {
284 	    fprintf(stderr, "%s exists, cannot create it.\n", passwdpath);
285 	    fprintf(stderr, "Remove -c option or use the -f option to specify another.\n");
286 	    return (1);
287 	}
288 
289 	if ((tfp = fopen(passwdpath, "w")) == NULL) {
290 	    fprintf(stderr, "Could not open \"%s\" for writing.\n", passwdpath);
291 	    perror("fopen");
292 	    return (1);
293 	}
294 
295 	tmp = passwdpath;
296 
297 	printf("Creating WU-FTPD Private file: %s\n", passwdpath);
298 	addrecord(accessgroup, realgroup, "Adding accessgroup", tfp);
299 
300 	fclose(tfp);
301 	return (0);
302     }
303 
304 #ifdef HAVE_MKSTEMP
305     strcpy (tmpname, "/tmp/privatepwXXXXXX");
306     tmp = tmpname;
307     if ((tfd = mkstemp(tmp)) < 0) {
308 	fprintf(stderr, "Could not open temp file.\n");
309 	return (1);
310     }
311 
312     if ((tfp = fdopen(tfd, "w")) == NULL) {
313 	unlink(tmp);
314 	fprintf(stderr, "Could not open temp file.\n");
315 	return (1);
316     }
317 #else
318     tmp = tmpnam(NULL);
319 
320     if ((tfp = fopen(tmp, "w")) == NULL) {
321 	fprintf(stderr, "Could not open temp file.\n");
322 	return (1);
323     }
324 #endif
325 
326     if ((fp = fopen(passwdpath, "r")) == NULL) {
327 	fprintf(stderr, "Could not open %s file.\n", passwdpath);
328 	fprintf(stderr, "Use -c option to create new one.\n");
329 	return (1);
330     }
331 
332     lineno = 0;
333     found = 0;
334 
335     while (fgets(line, BUFLEN, fp) != NULL) {
336 	lineno++;
337 
338 	if (found || (line[0] == '#') || (!line[0])) {
339 	    fputs(line, tfp);
340 	    continue;
341 	}
342 
343 	strcpy(w, line);
344 
345 	if ((cp = strchr(w, ':')) == NULL) {
346 	    fprintf(stderr, "%s: line %d: invalid record format.\n", passwdpath, lineno);
347 	    continue;
348 	}
349 	*cp++ = '\0';
350 
351 	if ((cp = strchr(cp, ':')) == NULL) {
352 	    fprintf(stderr, "%s: line %d: invalid record format.\n", passwdpath, lineno);
353 	    continue;
354 	}
355 	*cp++ = '\0';
356 
357 	if (strcmp(accessgroup, w)) {
358 	    fputs(line, tfp);
359 	    continue;
360 	}
361 	else {
362 	    if (delete) {
363 		if (!confirmed(accessgroup))
364 		    terminate();
365 	    }
366 	    else {
367 		if (realgroup[0] == '\0') {
368 		    strcpy(realgroup, cp);
369 		    if ((cp = strchr(realgroup, '\n')) != NULL)
370 			*cp = '\0';
371 		}
372 		addrecord(accessgroup, realgroup, "Updating accessgroup", tfp);
373 	    }
374 	    found = 1;
375 	}
376     }
377 
378     if (!found && !delete)
379 	addrecord(accessgroup, realgroup, "Adding accessgroup", tfp);
380     else if (!found && delete) {
381 	fprintf(stderr, "%s not found in %s.\n", accessgroup, passwdpath);
382 	terminate();
383     }
384 
385     fclose(fp);
386     fclose(tfp);
387 
388     sprintf(command, "cp %s %s", tmp, passwdpath);
389     system(command);
390     unlink(tmp);
391     return (0);
392 }
393