]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - release/sysinstall/anonFTP.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / release / sysinstall / anonFTP.c
1 /*
2  * The new sysinstall program.
3  *
4  * This is probably the last program in the `sysinstall' line - the next
5  * generation being essentially a complete rewrite.
6  *
7  * $FreeBSD$
8  *
9  * Copyright (c) 1995
10  *      Coranth Gryphon.  All rights reserved.
11  * Copyright (c) 1996
12  *      Jordan K. Hubbard.  All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer,
19  *    verbatim and that no modifications are made prior to this
20  *    point in the file.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR THEIR PETS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  */
38
39 #include "sysinstall.h"
40 #include <sys/param.h>
41 #include <pwd.h>
42 #include <grp.h>
43
44 /* This doesn't change until FTP itself changes */
45
46 #define FTP_NAME        "ftp"
47 #define MOTD_FILE       "ftpmotd"
48
49 /* These change if we want to use different defaults */
50
51 #define FTP_UID         14
52 #define FTP_GID         5
53 #define FTP_GROUP       "operator"
54 #define FTP_UPLOAD      "incoming"
55 #define FTP_COMMENT     "Anonymous FTP Admin"
56 #define FTP_HOMEDIR     "/var/ftp"
57
58 #define ANONFTP_HELPFILE "anonftp"
59
60 /* Set up the structure to hold configuration information */
61 /* Note that this is only what we could fit onto the one screen */
62
63 typedef struct
64 {
65     char homedir[64];             /* Home Dir for Anon FTP */
66     char group[32];               /* Group */
67     char uid[8];                  /* UID */
68     char comment[64];             /* PWD Comment */
69     char upload[32];              /* Upload Dir */
70 } FTPConf;
71
72 static FTPConf tconf;
73
74 #define ANONFTP_HOMEDIR_LEN       64
75 #define ANONFTP_COMMENT_LEN       64
76 #define ANONFTP_UPLOAD_LEN        32
77 #define ANONFTP_GROUP_LEN         32
78 #define ANONFTP_UID_LEN           8
79
80 static int      okbutton, cancelbutton;
81
82 /* What the screen size is meant to be */
83 #define ANONFTP_DIALOG_Y         0
84 #define ANONFTP_DIALOG_X         8
85 #define ANONFTP_DIALOG_WIDTH     COLS - 16
86 #define ANONFTP_DIALOG_HEIGHT    LINES - 2
87
88 static Layout layout[] = {
89 #define LAYOUT_UID              0
90     { 2, 3, 8, ANONFTP_UID_LEN - 1,
91       "UID:", "What user ID to assign to FTP Admin",
92       tconf.uid, STRINGOBJ, NULL },
93 #define LAYOUT_GROUP            1
94     { 2, 15, 15, ANONFTP_GROUP_LEN - 1,
95       "Group:",  "Group name that ftp process belongs to",
96       tconf.group, STRINGOBJ, NULL },
97 #define LAYOUT_COMMENT          2
98     { 2, 35, 24, ANONFTP_COMMENT_LEN - 1,
99       "Comment:", "Password file comment for FTP Admin",
100       tconf.comment, STRINGOBJ, NULL },
101 #define LAYOUT_HOMEDIR          3
102     { 9, 10, 43, ANONFTP_HOMEDIR_LEN - 1,
103       "FTP Root Directory:",
104       "The top directory to chroot to when doing anonymous ftp",
105       tconf.homedir, STRINGOBJ, NULL },
106 #define LAYOUT_UPLOAD           4
107     { 14, 20, 22, ANONFTP_UPLOAD_LEN - 1,
108       "Upload Subdirectory:", "Designated sub-directory that holds uploads",
109       tconf.upload, STRINGOBJ, NULL },
110 #define LAYOUT_OKBUTTON         5
111     { 19, 15, 0, 0,
112       "OK", "Select this if you are happy with these settings",
113       &okbutton, BUTTONOBJ, NULL },
114 #define LAYOUT_CANCELBUTTON     6
115     { 19, 35, 0, 0,
116       "CANCEL", "Select this if you wish to cancel this screen",
117       &cancelbutton, BUTTONOBJ, NULL },
118     { NULL },
119 };
120
121 int
122 createFtpUser(void)
123 {
124     struct passwd *tpw;
125     struct group  *tgrp;
126     char pwline[256];
127     char *tptr;
128     int gid;
129     FILE *fptr;
130     
131     if ((gid = atoi(tconf.group)) <= 0) {
132         if (!(tgrp = getgrnam(tconf.group))) {
133             /* group does not exist, create it by name */
134             
135             tptr = msgGetInput("14", "What group ID to use for group %s ?", tconf.group);
136             if (tptr && *tptr && ((gid = atoi(tptr)) > 0)) {
137                 if ((fptr = fopen(_PATH_GROUP,"a"))) {
138                     fprintf(fptr,"%s:*:%d:%s\n",tconf.group,gid,FTP_NAME);
139                     fclose(fptr);
140                 }
141             }
142             else
143                 gid = FTP_GID;
144         }
145         else
146             gid = tgrp->gr_gid;
147     }
148     else if (!getgrgid(gid)) {
149         /* group does not exist, create it by number */
150         
151         tptr = msgGetInput("14", "What group name to use for gid %d ?", gid);
152         if (tptr && *tptr) {
153             SAFE_STRCPY(tconf.group, tptr);
154             if ((tgrp = getgrnam(tconf.group))) {
155                 gid = tgrp->gr_gid;
156             }
157             else if ((fptr = fopen(_PATH_GROUP,"a"))) {
158                 fprintf(fptr,"%s:*:%d:%s\n",tconf.group,gid,FTP_NAME);
159                 fclose(fptr);
160             }
161         }
162     }
163     
164     if ((tpw = getpwnam(FTP_NAME))) {
165         if (tpw->pw_uid != FTP_UID)
166             msgConfirm("FTP user already exists with a different uid.");
167         
168         return DITEM_SUCCESS;   /* succeeds if already exists */
169     }
170     
171     sprintf(pwline, "%s:*:%s:%d::0:0:%s:%s:/nonexistent\n", FTP_NAME, tconf.uid, gid, tconf.comment, tconf.homedir);
172     
173     fptr = fopen(_PATH_MASTERPASSWD,"a");
174     if (! fptr) {
175         msgConfirm("Could not open master password file.");
176         return DITEM_FAILURE;
177     }
178     fprintf(fptr, pwline);
179     fclose(fptr);
180     msgNotify("Remaking password file: %s", _PATH_MASTERPASSWD);
181     vsystem("pwd_mkdb -p %s", _PATH_MASTERPASSWD);
182     return DITEM_SUCCESS | DITEM_RESTORE;
183 }
184
185 /* This is it - how to get the setup values */
186 static int
187 anonftpOpenDialog(void)
188 {
189     WINDOW              *ds_win;
190     ComposeObj          *obj = NULL;
191     int                 n = 0, cancel = FALSE;
192     int                 max;
193     char                title[80];
194     WINDOW              *w = savescr();
195
196     /* We need a curses window */
197     if (!(ds_win = openLayoutDialog(ANONFTP_HELPFILE, " Anonymous FTP Configuration ",
198                               ANONFTP_DIALOG_X, ANONFTP_DIALOG_Y, ANONFTP_DIALOG_WIDTH, ANONFTP_DIALOG_HEIGHT))) {
199         beep();
200         msgConfirm("Cannot open anonymous ftp dialog window!!");
201         restorescr(w);
202         return DITEM_FAILURE;
203     }
204     
205     /* Draw a sub-box for the path configuration */
206     draw_box(ds_win, ANONFTP_DIALOG_Y + 7, ANONFTP_DIALOG_X + 8,
207              ANONFTP_DIALOG_HEIGHT - 11, ANONFTP_DIALOG_WIDTH - 17,
208              dialog_attr, border_attr);
209     wattrset(ds_win, dialog_attr);
210     sprintf(title, " Path Configuration ");
211     mvwaddstr(ds_win, ANONFTP_DIALOG_Y + 7, ANONFTP_DIALOG_X + 22, title);
212     
213     /** Initialize the config Data Structure **/
214     bzero(&tconf, sizeof(tconf));
215     
216     SAFE_STRCPY(tconf.group, FTP_GROUP);
217     SAFE_STRCPY(tconf.upload, FTP_UPLOAD);
218     SAFE_STRCPY(tconf.comment, FTP_COMMENT);
219     SAFE_STRCPY(tconf.homedir, FTP_HOMEDIR);
220     sprintf(tconf.uid, "%d", FTP_UID);
221     
222     /* Some more initialisation before we go into the main input loop */
223     obj = initLayoutDialog(ds_win, layout, ANONFTP_DIALOG_X, ANONFTP_DIALOG_Y, &max);
224
225     cancelbutton = okbutton = 0;
226     while (layoutDialogLoop(ds_win, layout, &obj, &n, max, &cancelbutton, &cancel));
227
228     /* Clear this crap off the screen */
229     delwin(ds_win);
230     use_helpfile(NULL);
231     restorescr(w);
232     if (cancel)
233         return DITEM_FAILURE;
234     return DITEM_SUCCESS;
235 }
236
237 int
238 configAnonFTP(dialogMenuItem *self)
239 {
240     int i;
241     
242     /* Be optimistic */
243     i = DITEM_SUCCESS;
244     
245     i = anonftpOpenDialog();
246     if (DITEM_STATUS(i) != DITEM_SUCCESS) {
247         msgConfirm("Configuration of Anonymous FTP cancelled per user request.");
248         return i;
249     }
250     
251     /*** Use defaults for any invalid values ***/
252     if (atoi(tconf.uid) <= 0)
253         sprintf(tconf.uid, "%d", FTP_UID);
254     
255     if (!tconf.group[0])
256         SAFE_STRCPY(tconf.group, FTP_GROUP);
257     
258     if (!tconf.upload[0])
259         SAFE_STRCPY(tconf.upload, FTP_UPLOAD);
260     
261     /*** If the user did not specify a directory, use default ***/
262     
263     if (tconf.homedir[strlen(tconf.homedir) - 1] == '/')
264         tconf.homedir[strlen(tconf.homedir) - 1] = '\0';
265     
266     if (!tconf.homedir[0])
267         SAFE_STRCPY(tconf.homedir, FTP_HOMEDIR);
268     
269     /*** If HomeDir does not exist, create it ***/
270     
271     if (!directory_exists(tconf.homedir))
272         vsystem("mkdir -p %s", tconf.homedir);
273     
274     if (directory_exists(tconf.homedir)) {
275         msgNotify("Configuring %s for use by anon FTP.", tconf.homedir);
276         vsystem("chmod 555 %s && chown root.%s %s", tconf.homedir, tconf.group, tconf.homedir);
277         vsystem("mkdir %s/bin && chmod 555 %s/bin", tconf.homedir, tconf.homedir);
278         vsystem("cp /bin/ls %s/bin && chmod 111 %s/bin/ls", tconf.homedir, tconf.homedir);
279         vsystem("cp /bin/date %s/bin && chmod 111 %s/bin/date", tconf.homedir, tconf.homedir);
280         vsystem("mkdir %s/etc && chmod 555 %s/etc", tconf.homedir, tconf.homedir);
281         vsystem("mkdir -p %s/pub", tconf.homedir);
282         vsystem("mkdir -p %s/%s", tconf.homedir, tconf.upload);
283         vsystem("chmod 1777 %s/%s", tconf.homedir, tconf.upload);
284         
285         if (DITEM_STATUS(createFtpUser()) == DITEM_SUCCESS) {
286             msgNotify("Copying password information for anon FTP.");
287             vsystem("awk -F: '{if ($3 < 10 || $1 == \"ftp\") print $0}' /etc/passwd > %s/etc/passwd && chmod 444 %s/etc/passwd", tconf.homedir, tconf.homedir);
288             vsystem("awk -F: '{if ($3 < 100) print $0}' /etc/group > %s/etc/group && chmod 444 %s/etc/group", tconf.homedir, tconf.homedir);
289             vsystem("chown -R root.%s %s/pub", tconf.group, tconf.homedir);
290         }
291         else {
292             msgConfirm("Unable to create FTP user!  Anonymous FTP setup failed.");
293             i = DITEM_FAILURE;
294         }
295         
296         if (!msgYesNo("Create a welcome message file for anonymous FTP users?")) {
297             char cmd[256];
298             vsystem("echo Your welcome message here. > %s/etc/%s", tconf.homedir, MOTD_FILE);
299             sprintf(cmd, "%s %s/etc/%s", variable_get(VAR_EDITOR), tconf.homedir, MOTD_FILE);
300             if (!systemExecute(cmd))
301                 i = DITEM_SUCCESS;
302             else
303                 i = DITEM_FAILURE;
304         }
305     }
306     else {
307         msgConfirm("Invalid Directory: %s\n"
308                    "Anonymous FTP will not be set up.", tconf.homedir);
309         i = DITEM_FAILURE;
310     }
311     if (DITEM_STATUS(i) == DITEM_SUCCESS)
312         variable_set2("anon_ftp", "YES", 0);
313     return i | DITEM_RESTORE;
314 }