Handle hostnames with upper-case letters
[webmin.git] / exports-nfs4 / edit_export.cgi
1 #!/usr/bin/perl
2 # edit_export.cgi
3 # Allow editing of one export to a client
4
5 require './exports-lib.pl';
6 &ReadParse();
7 local $via_pfs = 0;
8 local $nfsv = nfs_max_version("localhost");
9 my $is_new=$in{'new'} ? 1 : 0;
10
11 if ($in{'new'}) {
12         &ui_print_header(undef, $text{'create_title'}, "", "create_export");
13         $via_pfs = ($nfsv == 4) ? 1 : 0;
14         &list_exports(); # only to retrieve nfsv4_root
15         $exp->{"pfs"} = $nfsv4_root;
16     }
17 else {
18         &ui_print_header(undef, $text{'edit_title'}, "", "edit_export");
19         @exps = &list_exports();
20         $exp = $exps[$in{'idx'}];
21         %opts = %{$exp->{'options'}};
22         }
23
24 # WebNFS doesn't exist on Linux
25 local $linux = ($gconfig{'os_type'} =~ /linux/i) ? 1 : 0;
26
27 print qq*
28 <SCRIPT language="JavaScript">
29 <!--
30 function virtual_root(){
31     if(document.forms[0].is_pfs.checked==1)
32         document.forms[0].pfs_dir.disabled=1;
33     else
34         document.forms[0].pfs_dir.disabled=0;
35 }
36 function selectv4(selected){
37     if(selected){
38         document.forms[0].pfs_dir.disabled=0;
39         document.forms[0].is_pfs.disabled=0;
40     }
41     else{
42         document.forms[0].pfs_dir.disabled=1;
43         document.forms[0].is_pfs.disabled=1;
44     }
45 }
46 function enterbindto(){
47     if(document.forms[0].pfs_dir.value==""){
48         if('$nfsv4_root' == "")
49             alert('$text{'alert_no_nfsv4root'}');
50         else
51             document.forms[0].pfs_dir.value="$nfsv4_root";
52     }
53 }
54 window.onload = function() {
55    if ($is_new)
56         virtual_root();
57    maj_flav();
58 }
59 function disable_all(){
60     document.forms[0].host.disabled=1;
61     document.forms[0].netgroup.disabled=1;
62     document.forms[0].network.disabled=1;
63     document.forms[0].netmask.disabled=1;
64     document.forms[0].address.disabled=1;
65     document.forms[0].prefix.disabled=1;
66 }
67 function everybody_select(){
68     disable_all();
69 }
70 function hostname_select(){
71     disable_all();
72     document.forms[0].host.disabled=0;
73 }
74 function public_select(){
75     disable_all();
76 }
77 function netgroup_select(){
78     disable_all();
79     document.forms[0].netgroup.disabled=0;
80 }
81 function network_select(){
82     disable_all();
83     document.forms[0].network.disabled=0;
84     document.forms[0].netmask.disabled=0;
85     // Autofill
86     if(document.forms[0].network.value==""){
87         document.forms[0].network.value="192.168.0.1";
88         document.forms[0].netmask.value="255.255.255.0";
89     }
90 }
91 function ipv6_select(){
92     disable_all();
93     document.forms[0].address.disabled=0;
94     document.forms[0].prefix.disabled=0;
95 }
96 function maj_flav(){
97    lgthR = document.forms[0].selectRight.options.length;
98    var str="";
99    for(var i=0;i<lgthR;i++){
100             text=document.forms[0].selectRight.options[i].value;
101             str+=(text+",");
102    }
103    document.forms[0].the_flav.value=str;
104 }
105 function clickLtoR(){
106    lgthL = document.forms[0].selectLeft.options.length;
107    for(var i=0;i<lgthL;i++){
108         if(document.forms[0].selectLeft.options[i].selected){
109             text=document.forms[0].selectLeft.options[i].text;
110             value=document.forms[0].selectLeft.options[i].value;
111             lgth = document.forms[0].selectRight.options.length;
112             document.forms[0].selectRight.options[lgth] = new Option(text,value);
113         }
114    }
115    maj_flav();
116 }
117 function clickRtoL(){ 
118      lgth = document.forms[0].selectRight.options.length;
119      for(var i=0;i<lgth;i++){
120         if(document.forms[0].selectRight.options[i].selected){
121             document.forms[0].selectRight.options[i] = null;
122             i--; lgth = document.forms[0].selectRight.options.length;
123         }
124      }
125      maj_flav();
126 }
127 function clickUp(){
128     idx=document.forms[0].selectRight.selectedIndex;
129     if(idx==0) return;
130     
131     tmpText=document.forms[0].selectRight.options[idx-1].text;
132     tmpValue=document.forms[0].selectRight.options[idx-1].value;
133     document.forms[0].selectRight.options[idx-1]=new Option(document.forms[0].selectRight.options[idx].text,document.forms[0].selectRight.options[idx].value);
134     document.forms[0].selectRight.options[idx]=new Option(tmpText,tmpValue);
135     document.forms[0].selectRight.selectedIndex=idx-1;
136     maj_flav();
137 }
138 function clickDown(){
139     lgth = document.forms[0].selectRight.options.length;
140     idx=document.forms[0].selectRight.selectedIndex;
141     if(idx>=lgth-1) return;
142     
143     tmpText=document.forms[0].selectRight.options[idx+1].text;
144     tmpValue=document.forms[0].selectRight.options[idx+1].value;
145     document.forms[0].selectRight.options[idx+1]=new Option(document.forms[0].selectRight.options[idx].text,document.forms[0].selectRight.options[idx].value);
146     document.forms[0].selectRight.options[idx]=new Option(tmpText,tmpValue);
147     document.forms[0].selectRight.selectedIndex=idx+1;
148     maj_flav();
149 }
150 -->
151 </SCRIPT>*;
152
153 #--------------------------------------------------------------------
154 # Get values for export to
155 # Mode : 0 = public, 1 = netgroup NIS, 2= IPv4 network, 3= everybody, 
156 # 4=hostname, 5 = gss, 6= IPv6 address
157 #---------------------------------------------------------------------
158
159 my $h = $exp->{'host'};
160 # and value for authentication 
161 local $auth = "", $sec = "";
162 my $html="";
163
164 # parse security flavors list and build html code for "select" component
165
166 while ($h =~/^(((gss\/)?(krb5|spkm-3|lipkey))|\sys)([ip]?)(([,:](\S+))|$)/ || $h =~/^gss\/(krb5|spkm-3|lipkey)([ip]?)$/) {
167     $auth = $1; # sys, krb5, spkm-3 or lipkey
168     $sec=$5; # authentication(""), integrity("i"), privacy("p")
169     
170     my $to_add=0;
171     my $suffix="";
172     if($sec eq "i"){ $to_add=1; $suffix=" (i)" }
173     elsif($sec eq "p"){ $to_add=2; $suffix=" (p)" }
174     if($auth eq "sys"){
175         $html.=qq*<OPTION VALUE="0">sys\n*;
176     }
177     elsif($auth eq "gss/krb5" || $auth eq "krb5"){
178        $val=1+$to_add;
179        $html.=qq*<OPTION VALUE="$val">kerberos 5$suffix\n*;
180     }
181     elsif($auth eq "gss/spkm-3" || $auth eq "spkm-3"){
182        $val=4+$to_add;
183        $html.=qq*<OPTION VALUE="$val">spkm-3$suffix\n*;       
184     }
185     elsif($auth eq "gss/lipkey" || $auth eq "lipkey"){
186        $val=7+$to_add;
187        $html.=qq*<OPTION VALUE="$val">lipkey$suffix\n*;       
188     }
189     $h=$8;
190 }
191 if($html eq ""){ # Default is sys
192     $html=qq*<OPTION VALUE="0">sys\n*;
193 }
194
195 # parse hosts
196
197 if ($h eq "=public") { $mode = 0; }
198 elsif ($h =~ /^\@(.*)/) { $mode = 1; $netgroup = $1; }
199 elsif ($h =~ /^(\S+)\/(\S+)$/ && check_ip6address($1)) { $mode = 6; $address = $1; $prefix = $2; }
200 elsif ($h =~ /^(\S+)\/(\S+)$/) {$mode = 2; $network = $1; $netmask = $2; }
201 elsif ($h eq "" or $h eq "*") { $mode = 3; }
202 else { $mode = 4; $host = $h; }
203
204
205 print "<form action=save_export.cgi>\n";
206 print "<input type=hidden name=new value='$in{'new'}'>\n";
207 print "<input type=hidden name=idx value='$in{'idx'}'>\n";
208 print "<input type=hidden name=the_flav value='sys'>\n";
209
210 #-----------------------------------------------------------------
211 # Exports details
212 #-----------------------------------------------------------------
213 print "<table border width=100%>\n";
214 print "<tr $tb> <td><b>$text{'edit_details'}</b></td> </tr>\n";
215 print "<tr $cb> <td><table>\n";
216
217 # Choice between NFSv3 or NFSv4 (if system supports NFSv4, else default to NFSv3).
218 if ($nfsv == 4) {
219     print "<tr> <td>",&hlink("<b>$text{'edit_nfs_vers'}</b>","vers"),"</td>\n";
220     printf qq*<td colspan=3><input type=radio name=via_pfs value=1 checked onClick="selectv4(true)"> 4\n*;
221     printf qq*<input type=radio name=via_pfs value=0 %s onClick="selectv4(false)"> 3 (or lower)</td> </tr>\n*;
222 } else {
223     printf "<tr><td><input type=hidden name=via_pfs value=0></td></tr>\n";
224 }
225
226 # Show 'directory to export' input
227 print "<tr> <td>",&hlink("<b>$text{'edit_dir'}</b>","dir"),"</td>\n";
228 print "<td colspan=3><input name=dir size=30 value=\"$exp->{'dir'}\">",
229     &file_chooser_button("dir", 1);
230     
231 # Show 'NFSv4 root' checkbox
232 if ($nfsv == 4) {
233    printf qq*<td> <input type=checkbox name=is_pfs %s onClick="virtual_root()"> $text{'edit_ispfs'} </td></tr>\n*,defined($opts{'fsid'}) ? "checked" : "";
234 }
235
236 # Show 'bind to' input only for new export (else, bind is already done...)
237 if ($in{'new'} && $nfsv==4) {
238     print "<tr> <td>",&hlink("<b>$text{'edit_in'}</b>","in"),"</td>\n";
239     print qq*<td $text{'edit_in'} <input name=pfs_dir size=30 onclick="enterbindto()"></td> </tr>\n*;
240 }
241
242 # Show active input
243 print "<tr> <td>",&hlink("<b>$text{'edit_active'}</b>","active"),"</td>\n";
244 printf "<td colspan=3><input type=checkbox name=active value=1 %s> $text{'yes'}\n",
245     $in{'new'} || $exp->{'active'} ? 'checked' : '';
246
247 #----------------------------------------------------------------
248 # Host selection
249 #----------------------------------------------------------------
250 print &ui_table_end();
251 print &ui_table_start($text{'hostsec_host'},'width=100%');
252
253 # Everybody (3)
254 printf "<tr><td><input type=radio name=mode value=3 %s onClick=\"everybody_select()\"> $text{'edit_all'} </td>\n",
255         $mode == 3 ? "checked" : "";
256
257 # Hostname (4)
258 printf "<td colspan=2><input type=radio name=mode value=4 %s onClick=\"hostname_select()\"> $text{'edit_host'}\n",
259         $mode == 4 ? "checked" : "";
260 print "<input name=host size=31 value='$host'></td> </tr>\n";
261
262 # Public (0)
263 printf "<tr><td><input type=radio name=mode value=0 %s %s onClick=\"public_select()\"> $text{'edit_webnfs'}</td>\n",
264         $mode == 0 ? "checked" : "", $linux ? "disabled" : "";
265
266 # Netgroup (1)
267 printf "<td colspan=2><input type=radio name=mode value=1 %s onClick=\"netgroup_select()\"> $text{'edit_netgroup'}\n",
268         $mode == 1 ? "checked" : "";
269 print "<input name=netgroup size=25 value='$netgroup'></td> </tr>\n";
270
271 # IPV4 Network (2)
272 printf "<tr><td colspan=3><input type=radio name=mode value=2 %s onClick=\"network_select()\"> IPv4 $text{'edit_network'}\n",
273         $mode == 2 ? "checked" : "";
274 print qq*<input name=network size=15 value='$network'>\n*;
275 print "$text{'edit_netmask'} <input name=netmask size=15 value='$netmask'></td> </tr>\n"; 
276
277 # IPV6 Network (6)
278 printf "<tr><td colspan=3><input type=radio name=mode value=6 %s onClick=\"ipv6_select()\"> IPv6 $text{'edit_address'}\n",
279     $mode == 6 ? "checked" : "";
280 print "<input name=address size=39 value='$address'>\n";
281 print "$text{'edit_prefix'}<input name=prefix size=2 value='$prefix'></td> </tr>\n";
282
283 #----------------------------------------------------------------
284 # Flavors selection
285 #----------------------------------------------------------------
286 print &ui_table_end();
287     print qq*<table border width=100% valign="TOP">\n*;
288     print "<tr $tb> <td><b>$text{'hostsec_flavors'}</b></td> </tr>\n";
289     print "<tr $cb> <td><table>\n";
290     
291     # Lists and buttons for security flavors selection
292     print qq*
293     <tr> <td>
294     $text{'hostsec_supported'}
295     <SELECT NAME="selectLeft" SIZE=4 MULTIPLE>
296             <OPTION VALUE="0">sys
297             <OPTION VALUE="1">kerberos 5
298             <OPTION VALUE="2">kerberos 5 (i)
299             <OPTION VALUE="3">kerberos 5 (p)
300             <OPTION VALUE="4">spkm-3
301             <OPTION VALUE="5">spkm-3 (i)
302             <OPTION VALUE="6">spkm-3 (p)
303             <OPTION VALUE="7">lipkey
304             <OPTION VALUE="8">lipkey (i)
305             <OPTION VALUE="9">lipkey (p)
306     </SELECT>
307     </td>
308     <td> <INPUT TYPE="button" NAME="buttonLtoR" VALUE=">>" onClick="clickLtoR()">
309     <INPUT TYPE="button" NAME="buttonRtoL" VALUE="<<" onClick="clickRtoL()"> </td>
310     <td>$text{'hostsec_enabled'} 
311     <SELECT NAME="selectRight" SIZE=4 MULTIPLE>
312             $html
313     </SELECT>
314     </td>
315     <td> <INPUT TYPE="button" NAME="buttonUp" VALUE="$text{'hostsec_up'}" onClick="clickUp()">
316     <INPUT TYPE="button" NAME="buttonDown" VALUE="$text{'hostsec_down'}" onClick="clickDown()"></td>
317     <tr>
318     *;
319     print &ui_table_end();
320
321 #-----------------------------------------------------------------
322 # Exports options
323 #-----------------------------------------------------------------
324
325 print &ui_table_start($text{'edit_security'},'width=100%');
326
327 # Show read-only input
328 print "<tr> <td>",&hlink("<b>$text{'edit_ro'}</b>","ro"),"</td>\n";
329 printf "<td><input type=checkbox name=ro %s> $text{'yes'}\n",
330         defined($opts{'rw'}) ? "" : "checked";
331
332 # Show input for secure port
333 print "<td>",&hlink("<b>$text{'edit_insecure'}</b>","insecure"),"</td>\n";
334 printf "<td><input type=checkbox name=insecure %s> $text{'yes'}\n",
335         defined($opts{'insecure'}) ? "" : "checked";
336
337 # Show subtree check input
338 print "<tr> <td>",&hlink("<b>$text{'edit_subtree_check'}</b>","subtree_check"),"</td>\n";
339 printf "<td><input type=checkbox name=no_subtree_check%s> $text{'yes'}\n",
340     defined($opts{'no_subtree_check'}) ? "checked" : "";
341
342 # Show nohide check input
343 print "<td>",&hlink("<b>$text{'edit_hide'}</b>","hide"),"</td>\n";
344 printf "<td><input type=checkbox name=nohide %s> $text{'yes'}\n",
345         defined($opts{'nohide'}) ? "" : "checked";
346
347 # Show sync input
348 print "<tr> <td>",&hlink("<b>$text{'edit_sync'}</b>","sync"),"</td>\n<td colspan=3>";
349 printf "<input type=checkbox name=sync %s> %s\n",defined($opts{'async'}) ? "" : "checked", $text{'yes'};
350 print "</td> </tr>\n";
351
352 # Show root trust input
353 print "<tr> <td>",&hlink("<b>$text{'edit_squash'}</b>","squash"),"</td> <td colspan=3>\n";
354 printf "<input type=radio name=squash value=0 %s> $text{'edit_everyone'}\n",
355         defined($opts{'no_root_squash'}) ? "checked" : "";
356 printf "<input type=radio name=squash value=1 %s> $text{'edit_except'}\n",
357         !defined($opts{'no_root_squash'}) &&
358         !defined($opts{'all_squash'}) ? "checked" : "";
359 printf "<input type=radio name=squash value=2 %s> $text{'edit_nobody'}\n";
360         defined($opts{'all_squash'}) ? "checked" : "";
361 print "</td> </tr>\n";
362
363 # Show untrusted user input
364 print "<tr> <td>",&hlink("<b>$text{'edit_anonuid'}</b>","anonuid"),"</td> <td>\n";
365 printf "<input type=radio name=anonuid_def value=1 %s> $text{'edit_default'}\n",
366     defined($opts{'anonuid'}) ? "" : "checked";
367 printf "<input type=radio name=anonuid_def value=0 %s>\n",
368     defined($opts{'anonuid'}) ? "checked" : "";
369 printf "<input name=anonuid size=8 value=\"%s\">\n",
370     $opts{'anonuid'} ? getpwuid($opts{'anonuid'}) : "";
371 print &user_chooser_button("anonuid", 0),"</td>\n";
372
373 # Show untrusted group input
374 print "<td>",&hlink("<b>$text{'edit_anongid'}</b>","anongid"),"</td> <td>\n";
375 printf "<input type=radio name=anongid_def value=1 %s> $text{'edit_default'}\n",
376     defined($opts{'anongid'}) ? "" : "checked";
377 printf "<input type=radio name=anongid_def value=0 %s>\n",
378     defined($opts{'anongid'}) ? "checked" : "";
379 printf "<input name=anongid size=8 value=\"%s\">\n",
380     $opts{'anongid'} ? getgrgid($opts{'anongid'}) : "";
381 print &group_chooser_button("anongid", 0),"</td> </tr>\n";
382
383 #-----------------------------------------------------------------
384 # NFSv2 specific options
385 #-----------------------------------------------------------------
386 if ($nfsv < 4) {
387     print "<tr $tb> <td colspan=4><b>$text{'edit_v2opts'}</b></td> </tr>\n";
388     # Show input for relative symlinks
389     print "<tr> <td>",&hlink("<b>$text{'edit_relative'}</b>","link_relative"),"</td>\n";
390     printf "<td><input type=radio name=link_relative value=1 %s> $text{'yes'}\n",
391         defined($opts{'link_relative'}) ? "checked" : "";
392     printf "<input type=radio name=link_relative value=0 %s> $text{'no'}</td>\n",
393         defined($opts{'link_relative'}) ? "" : "checked";
394     
395     # Show deny access input
396     print "<td>",&hlink("<b>$text{'edit_noaccess'}</b>","noaccess"),"</td>\n";
397     printf "<td><input type=radio name=noaccess value=1 %s> $text{'yes'}\n",
398         defined($opts{'noaccess'}) ? "checked" : "";
399     printf "<input type=radio name=noaccess value=0 %s> $text{'no'}</td> </tr>\n",
400         defined($opts{'noaccess'}) ? "" : "checked";
401     
402     # Show untrusted UIDs input
403     print "<tr> <td>",&hlink("<b>$text{'edit_uids'}</b>","squash_uids"),"</td> <td>\n";
404     printf "<input type=radio name=squash_uids_def value=1 %s> $text{'edit_none'}\n",
405         $opts{'squash_uids'} ? "" : "checked";
406     printf "<input type=radio name=squash_uids_def value=0 %s>\n",
407         $opts{'squash_uids'} ? "checked" : "";
408     printf "<input name=squash_uids size=15 value=\"%s\"></td>\n",
409         $opts{'squash_uids'};
410     
411     # Show untrusted GIDs input
412     print "<td>",&hlink("<b>$text{'edit_gids'}</b>","squash_gids"),"</td> <td>\n";
413     printf "<input type=radio name=squash_gids_def value=1 %s> $text{'edit_none'}\n",
414         $opts{'squash_gids'} ? "" : "checked";
415     printf "<input type=radio name=squash_gids_def value=0 %s>\n",
416         $opts{'squash_gids'} ? "checked" : "";
417     printf "<input name=squash_gids size=15 value=\"%s\"></td> </tr>\n",
418         $opts{'squash_gids'};
419 }
420
421 print &ui_table_end();
422 if (!$in{'new'}) {
423         print "<table width=100%><tr>\n";
424         print "<td><input type=submit value=\"$text{'save'}\"></td>\n";
425         print "<td align=right><input type=submit name=delete ",
426               "value=\"$text{'delete'}\"></td>\n";
427         print "</tr></table>\n";
428         }
429 else {
430         print "<input type=hidden name=new value=1>\n";
431         print "<input type=submit value=\"$text{'create'}\">\n";
432         }
433
434 &ui_print_footer("", $text{'index_return'});