2 * The new sysinstall program.
4 * This is probably the last program in the `sysinstall' line - the next
5 * generation being essentially a complete rewrite.
10 * Coranth Gryphon. All rights reserved.
12 * Jordan K. Hubbard. All rights reserved.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
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
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.
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
39 #include "sysinstall.h"
40 #include <sys/param.h>
44 /* This doesn't change until FTP itself changes */
46 #define FTP_NAME "ftp"
47 #define MOTD_FILE "ftpmotd"
49 /* These change if we want to use different defaults */
53 #define FTP_GROUP "operator"
54 #define FTP_UPLOAD "incoming"
55 #define FTP_COMMENT "Anonymous FTP Admin"
56 #define FTP_HOMEDIR "/var/ftp"
58 #define ANONFTP_HELPFILE "anonftp"
60 /* Set up the structure to hold configuration information */
61 /* Note that this is only what we could fit onto the one screen */
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 */
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
80 static int okbutton, cancelbutton;
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
88 static Layout layout[] = {
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
112 "OK", "Select this if you are happy with these settings",
113 &okbutton, BUTTONOBJ, NULL },
114 #define LAYOUT_CANCELBUTTON 6
116 "CANCEL", "Select this if you wish to cancel this screen",
117 &cancelbutton, BUTTONOBJ, NULL },
131 if ((gid = atoi(tconf.group)) <= 0) {
132 if (!(tgrp = getgrnam(tconf.group))) {
133 /* group does not exist, create it by name */
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);
148 else if (!getgrgid(gid)) {
149 /* group does not exist, create it by number */
151 tptr = msgGetInput("14", "What group name to use for gid %d ?", gid);
153 SAFE_STRCPY(tconf.group, tptr);
154 if ((tgrp = getgrnam(tconf.group))) {
157 else if ((fptr = fopen(_PATH_GROUP,"a"))) {
158 fprintf(fptr,"%s:*:%d:%s\n",tconf.group,gid,FTP_NAME);
164 if ((tpw = getpwnam(FTP_NAME))) {
165 if (tpw->pw_uid != FTP_UID)
166 msgConfirm("FTP user already exists with a different uid.");
168 return DITEM_SUCCESS; /* succeeds if already exists */
171 sprintf(pwline, "%s:*:%s:%d::0:0:%s:%s:/nonexistent\n", FTP_NAME, tconf.uid, gid, tconf.comment, tconf.homedir);
173 fptr = fopen(_PATH_MASTERPASSWD,"a");
175 msgConfirm("Could not open master password file.");
176 return DITEM_FAILURE;
178 fprintf(fptr, pwline);
180 msgNotify("Remaking password file: %s", _PATH_MASTERPASSWD);
181 vsystem("pwd_mkdb -p %s", _PATH_MASTERPASSWD);
182 return DITEM_SUCCESS | DITEM_RESTORE;
185 /* This is it - how to get the setup values */
187 anonftpOpenDialog(void)
190 ComposeObj *obj = NULL;
191 int n = 0, cancel = FALSE;
194 WINDOW *w = savescr();
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))) {
200 msgConfirm("Cannot open anonymous ftp dialog window!!");
202 return DITEM_FAILURE;
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);
213 /** Initialize the config Data Structure **/
214 bzero(&tconf, sizeof(tconf));
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);
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);
225 cancelbutton = okbutton = 0;
226 while (layoutDialogLoop(ds_win, layout, &obj, &n, max, &cancelbutton, &cancel));
228 /* Clear this crap off the screen */
233 return DITEM_FAILURE;
234 return DITEM_SUCCESS;
238 configAnonFTP(dialogMenuItem *self)
245 i = anonftpOpenDialog();
246 if (DITEM_STATUS(i) != DITEM_SUCCESS) {
247 msgConfirm("Configuration of Anonymous FTP cancelled per user request.");
251 /*** Use defaults for any invalid values ***/
252 if (atoi(tconf.uid) <= 0)
253 sprintf(tconf.uid, "%d", FTP_UID);
256 SAFE_STRCPY(tconf.group, FTP_GROUP);
258 if (!tconf.upload[0])
259 SAFE_STRCPY(tconf.upload, FTP_UPLOAD);
261 /*** If the user did not specify a directory, use default ***/
263 if (tconf.homedir[strlen(tconf.homedir) - 1] == '/')
264 tconf.homedir[strlen(tconf.homedir) - 1] = '\0';
266 if (!tconf.homedir[0])
267 SAFE_STRCPY(tconf.homedir, FTP_HOMEDIR);
269 /*** If HomeDir does not exist, create it ***/
271 if (!directory_exists(tconf.homedir))
272 vsystem("mkdir -p %s", tconf.homedir);
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);
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);
292 msgConfirm("Unable to create FTP user! Anonymous FTP setup failed.");
296 if (!msgYesNo("Create a welcome message file for anonymous FTP users?")) {
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))
307 msgConfirm("Invalid Directory: %s\n"
308 "Anonymous FTP will not be set up.", tconf.homedir);
311 if (DITEM_STATUS(i) == DITEM_SUCCESS)
312 variable_set2("anon_ftp", "YES", 0);
313 return i | DITEM_RESTORE;