1#!/bin/sh
2#  -*- tcl -*-
3# Executing wish #\
4exec wish "$0" "$@"
5
6#######################################################################
7#
8# secpanel - Graphical user interface for managing SSH- and
9# SFTP-connections
10#
11# Author: Steffen Leich <steffen.leich _at_ gmail.com>
12# http://secpanel.net
13#
14# This program is free software; you can redistribute it and/or modify
15# it under the terms of the GNU General Public License as published by
16# the Free Software Foundation; either version 2 of the License, or
17# (at your option) any later version.
18#
19# This program is distributed in the hope that it will be useful,
20# but WITHOUT ANY WARRANTY; without even the implied warranty of
21# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22# GNU General Public License for more details.
23#
24# You should have received a copy of the GNU General Public License
25# along with this program; if not, write to the Free Software
26# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27#
28#######################################################################
29
30set spversion 0.6.0
31
32set libdir "/usr/local/share/secpanel"
33# set libdir "$env(HOME)/secpanel_devel/secpanel-0x/lib"
34set sshdir "$env(HOME)/.ssh"
35
36global actdirsel;
37global questres;
38global userres;
39
40proc init {argc argv} {
41    global env configs tk_version launcher defident libdir agent wins platform
42
43    if {! [info exists env(DISPLAY)] || $env(DISPLAY) == ""} {
44		catch {exec "uname -a"} ver
45	if {! [regexp -nocase "macintosh" $ver]} {
46	    puts "No valid Xwindow DISPLAY environment or MacOSX platform -> exiting secpanel"
47	    exit
48	} else {
49	    set platform "macosx"
50	}
51    } else {
52		set platform "linux"
53    }
54
55    set mintcl 8.0
56    set mintk 8.0
57
58    if {[info tclversion]<$mintcl || $tk_version<$mintk} {
59		puts -nonewline stderr "For running secpanel:\nTcl $mintcl/Tk $mintk minimum versions required. "
60		puts stderr "You have Tcl [info tclversion]/Tk $tk_version"
61		exit 1
62    }
63
64    set secpaneldir "$env(HOME)/.secpanel"
65    if {! [file exists $secpaneldir]} {
66		file mkdir $secpaneldir
67		exec chmod 700 $secpaneldir
68		puts "Created config-dir $secpaneldir (chmod 700)..."
69    }
70
71
72    if [file exists $secpaneldir/spdata.lck] {
73		puts "Found protected secpanel data"
74		# exec $libdir/protect.sh $libdir
75		exec $libdir/dppw.tcl "de"
76    }
77
78
79    if {! [file exists $secpaneldir/.runfiles]} {
80		file mkdir $secpaneldir/.runfiles
81    }
82
83    if {! [file exists $secpaneldir/profiles]} {
84		file mkdir $secpaneldir/profiles
85    }
86
87    set configfile "$env(HOME)/.secpanel/config"
88    if {! [file exists $configfile]} {
89		file copy "$libdir/default.config" "$configfile"
90    }
91    source $configfile
92    initconfigs
93
94    array set gshorts {fore foreground back background}
95
96    foreach gcolval [array names gshorts] {
97		if [info exists configs($gcolval)] {
98			option add *$gshorts($gcolval) $configs($gcolval)
99		}
100    }
101
102    array set shorts {entfore Entry.foreground entback Entry.background \
103			  listfore Listbox.foreground listback Listbox.background}
104
105    foreach colval [array names shorts] {
106		if [info exists configs($colval)] {
107			option add *$shorts($colval) $configs($colval)
108			if {$colval == "listfore"} {
109				option add *Text.foreground $configs($colval)
110			}
111			if {$colval == "listback"} {
112				option add *Text.background $configs($colval)
113			}
114		}
115    }
116
117    set fb ""
118    set fi ""
119
120    if {([info exists configs(sysfonts)] && ($configs(sysfonts) != 1)) || ! [info exists configs(sysfonts)]} {
121	    if [info exists configs(fontbold)] {
122			if $configs(fontbold) {
123				set fb "bold"
124			}
125	    }
126
127	    if [info exists configs(fontitalic)] {
128			if $configs(fontitalic) {
129				set fi "italic"
130			}
131	    }
132
133	    if {[info exists configs(fontfam)] && [info exists configs(fontsize)]} {
134			option add *Font "\"$configs(fontfam)\" $configs(fontsize) $fb $fi"
135	    }
136	}
137
138    set agent 0
139}
140
141proc initconfigs {} {
142    global configs
143    foreach {bintag binprog} \
144	{sshbin ssh keygenbin ssh-keygen agentbin ssh-agent \
145	     addbin ssh-add askpassbin ssh-askpass scpbin scp sftpbin Filezilla Thunar thunar termver Xterm browserbin firefox \
146	     } {
147		 if {! [info exists configs($bintag)]} {
148		     set configs($bintag) $binprog
149		 }
150	     }
151
152    if {! [info exists configs(sshver)]} {
153		set configs(sshver) "OpenSSH"
154    }
155
156    if {! [info exists configs(termver)]} {
157		set configs(termver) "Xterm"
158    }
159
160    if {! [info exists configs(protectdata)]} {
161		set configs(protectdata) 0
162    }
163}
164
165init $argc $argv
166
167proc browsebin {which} {
168    global widget
169    choosefile $widget([set which]ent) "actdirsel" "Open" ""
170}
171
172proc manage_remote {mode} {
173    global widget rfts configs libdir env termtype ramhost ramport ramuser
174
175    set usetermver $configs(termver)
176
177    set icontag ""
178
179    set configs(xtermbin) $termtype([set usetermver]_path)
180    set titlepar $termtype([set usetermver]_titlepar)
181    set quotepar $termtype([set usetermver]_quotepar)
182    set execpar $termtype([set usetermver]_execpar)
183    if {[info exists termicon] && $termicon} {
184	set icontag $termtype([set usetermver]_iconpar)
185    }
186    # </xterm selection and params>
187
188    switch -regexp $mode {
189	init {
190	    if {[selection own] == $widget(specsites)} {
191		set actentry [$widget(specsites) get active]
192		set rmprof [retprof $actentry]
193
194		source "$env(HOME)/.secpanel/profiles/$rmprof.profile"
195
196		set ramhost $host
197		set ramport $port
198		set ramuser $user
199	    } else {
200		showmessage "No entry selected" ""
201		return
202	    }
203
204	    if {[winfo exists .top40]} {
205		if [showconfirm\
206			"There is another remote management session. Cancel this former session?"\
207			.top40] {
208		    manage_remote cancel
209		} else {
210		    return
211		}
212	    }
213
214	    set rfts [clock clicks]
215
216	    Window show .top40
217	    .top40.lab51 config -text "Remote Account Manager for $title ($ramuser@$ramhost)"
218
219	    set connstring "$libdir/secpanel_remoteconf.sh $ramhost $ramport $ramuser $configs(scpbin) read $rfts"
220
221	    set runstring "exec $configs(xtermbin) $execpar $quotepar <CONNFILE> $quotepar"
222
223	    provrunfile term nobg $connstring $runstring
224
225	    set shostsfile "$env(HOME)/.secpanel/.runfiles/ram.$rfts/.shosts"
226	    set keysfile "$env(HOME)/.secpanel/.runfiles/ram.$rfts/authorized_keys"
227
228	    if {[file exists $shostsfile]} {
229		$widget(remoteshostsfile) insert end [exec cat $shostsfile]
230	    }
231	    if {[file exists $keysfile]} {
232		$widget(remotekeysfile) insert end [exec cat $keysfile]
233	    }
234
235	    $widget(remotercfile) insert end "Not yet supported, breaks scp..."
236	}
237	cancel {
238	    file delete -force "$env(HOME)/.secpanel/.runfiles/ram.$rfts"
239	    unset rfts
240	    Window destroy .top40
241	}
242	write {
243	    if [showconfirm "Really write back remote configuration?" ".top40"] {
244
245		set shostsfile [open "$env(HOME)/.secpanel/.runfiles/ram.$rfts/.shosts" w]
246		puts -nonewline $shostsfile [$widget(remoteshostsfile) get 1.0 end]
247		close $shostsfile
248
249		set keysfile [open "$env(HOME)/.secpanel/.runfiles/ram.$rfts/authorized_keys" w]
250		puts -nonewline $keysfile [$widget(remotekeysfile) get 1.0 end]
251		close $keysfile
252
253		set connstring "$libdir/secpanel_remoteconf.sh $ramhost $ramport $ramuser $configs(scpbin) write $rfts"
254
255		set runstring "exec $configs(xtermbin) $execpar $quotepar <CONNFILE> $quotepar"
256
257		provrunfile term bg $connstring $runstring
258
259		Window destroy .top40
260	    }
261	}
262    }
263}
264
265proc save_globals {mode} {
266    global widget env configs launcher defident wins
267    set conffile [open "$env(HOME)/.secpanel/config" w]
268    switch -regexp $mode {
269	bins {
270	    array set bindefs { \
271		    ssh ssh keygen ssh-keygen agent ssh-agent add ssh-add \
272		    askpass ssh-askpass scp scp browser firefox }
273
274	    foreach f {ssh keygen agent add askpass scp browser} {
275		if {[$widget([set f]ent) get] == ""} {
276		    $widget([set f]ent) insert 0 $bindefs($f)
277		}
278
279		puts $conffile "set configs([set f]bin) \"[$widget([set f]ent) get]\""
280		set configs([set f]bin) [$widget([set f]ent) get]
281	    }
282	    puts $conffile "set configs(sshver) \"$configs(sshver)\""
283	    puts $conffile "set configs(termver) \"$configs(termver)\""
284	    puts $conffile "set configs(sftpbin) \"$configs(sftpbin)\""
285	    if [info exists defident] {
286		puts $conffile "set defident \"$defident\""
287	    }
288	    puts $conffile "set launcher $launcher"
289	}
290	"geom|startsat|color|fonts|scp|agent|chdef|protectdata" {
291	    foreach f {ssh keygen agent add askpass scp browser} {
292		puts $conffile "set configs([set f]bin) \"$configs([set f]bin)\""
293	    }
294	    puts $conffile "set configs(sshver) \"$configs(sshver)\""
295	    puts $conffile "set configs(termver) \"$configs(termver)\""
296	    puts $conffile "set configs(sftpbin) \"$configs(sftpbin)\""
297	    puts $conffile "set launcher $launcher"
298	    if [info exists defident] {
299		puts $conffile "set defident \"$defident\""
300	    }
301	}
302    }
303
304    foreach col {fore back entfore entback listfore listback} {
305	if [info exists configs($col)] {
306	    puts $conffile "set configs($col) $configs($col)"
307	}
308    }
309
310    foreach font {fontfam fontsize fontbold fontitalic sysfonts} {
311	if [info exists configs($font)] {
312	    puts $conffile "set configs($font) \"$configs($font)\""
313	}
314    }
315
316    if [info exists configs(wingeom)] {
317	puts $conffile "set configs(wingeom) \"$configs(wingeom)\""
318    }
319
320    if [info exists configs(protectdata)] {
321	puts $conffile "set configs(protectdata) \"$configs(protectdata)\""
322    }
323
324    foreach w [array names wins] {
325	puts $conffile "set wins($w) \"$wins($w)\""
326    }
327
328    if [info exists configs(startsat)] {
329	puts $conffile "set configs(startsat) \"$configs(startsat)\""
330    }
331
332    close $conffile
333    showstatus "Global configs saved"
334}
335
336proc chbutton {var but} {
337    global fgdef bgdef
338    if {[set $var]} {
339	$but config -state disabled
340    } else {
341	$but config -state normal
342    }
343}
344
345proc chcol {var button title} {
346    set ret [colorchoose ".top17" $title]
347    if {$ret != ""} {
348	$button config -background $ret
349    }
350}
351
352proc colorchoose {parent title} {
353    set col [tk_chooseColor -parent $parent -title "secpanel - $title"]
354    return $col
355}
356
357proc fontman {mode} {
358    global configs
359
360    set names .top23.fra36.cpd37.01
361    set sizes .top23.fra36.cpd38.01
362
363    switch -exact $mode {
364	show {
365	    Window show .top23
366	    set names .top23.fra36.cpd37.01
367	    set sizes .top23.fra36.cpd38.01
368
369	    foreach f [lsort [font families]] {
370		$names insert end $f
371	    }
372
373	    set fs 6
374	    while {$fs <= 60} {
375		$sizes insert end $fs
376		incr fs
377	    }
378
379	    if $configs(fontbold) {
380		set fb "bold"
381	    } else {
382		set fb ""
383	    }
384
385	    if $configs(fontitalic) {
386		set fi "italic"
387	    } else {
388		set fi ""
389	    }
390
391	    if {! $configs(sysfonts)} {
392
393		if {[info exists configs(fontfam)] && [info exists configs(fontsize)]} {
394		    set label "$configs(fontfam) $configs(fontsize)"
395		    .top23.lab30 config \
396			-font "\"$configs(fontfam)\" $configs(fontsize) $fi $fb"
397		} else {
398		    set label ""
399		}
400
401 		.top23.lab30 config -text "$label"
402	    } else {
403 		.top23.lab30 config -text "Using external sysfonts"
404	    }
405
406	    set fc 0
407	    if [info exists configs(fontfam)] {
408		foreach fn [$names get 0 end] {
409		    if {$fn =="$configs(fontfam)"} {
410			$names activate $fc
411			$names see $fc
412		    }
413		    incr fc
414		}
415	    }
416
417	    set sc 0
418	    if [info exists configs(fontsize)] {
419		foreach fs [$sizes get 0 end] {
420		    if {$fs =="$configs(fontsize)"} {
421			$sizes activate $sc
422			$sizes see $sc
423		    }
424		    incr sc
425		}
426	    }
427
428	    # activate listenelement in fontfam und size mit richtigen Werten
429	    # font-ex.text mit eingestellten werten
430	}
431
432	save {
433	    set configs(fontfam) [$names get active]
434	    set configs(fontsize) [$sizes get active]
435	    save_globals fonts
436	    Window destroy .top23
437	}
438
439	ul {
440
441	    if {! $configs(sysfonts)} {
442		set name [$names get active]
443		set size [$sizes get active]
444
445		if $configs(fontbold) {
446		    set fb "bold"
447		} else {
448		    set fb ""
449		}
450
451		if $configs(fontitalic) {
452		    set fi "italic"
453		} else {
454		    set fi ""
455		}
456		.top23.lab30 config -text "[$names get active] [$sizes get active]" -font "\"$name\" $size $fi $fb"
457	    } else {
458 		.top23.lab30 config -text "Using external sysfonts"
459	    }
460	}
461    }
462}
463
464proc colorman {mode} {
465    global env configs \
466	    foredef backdef entforedef entbackdef listforedef listbackdef
467
468    foreach {name widg} {fore 37 back 38 entfore 39 \
469	    entback 40 listfore 41 listback 42} {
470	set colbut[set name] ".top32.fra33.but[set widg]"
471    }
472
473    set colvals [list fore back entfore entback listfore listback];
474
475    switch -exact $mode {
476	1 {
477	    Window show .top32
478	    foreach colval $colvals {
479		if [info exists configs($colval)] {
480		    [set colbut[set colval]] configure -background $configs($colval)
481		} else {
482		    set [set colval]def 1
483		}
484	    }
485	}
486	save {
487	    foreach colval $colvals {
488		if {! [set [set colval]def]} {
489		    set configs([set colval]) [[set colbut[set colval]] cget -background]
490		} else {
491		    if [info exists configs([set colval])] {
492			unset configs([set colval])
493		    }
494		}
495	    }
496	    Window destroy .top32
497	    save_globals color
498	}
499	default {
500	    set col [colorchoose .top32 "Foreground Color"]
501	    if {$col != ""} {
502		[set colbut[set mode]] config \
503			-background $col -activebackground $col
504		return
505	    } else {
506		return
507	    }
508	}
509    }
510}
511
512proc showmenu {} {
513    if [winfo exists .pm1] {
514	Window destroy .pm1
515    }
516
517    if [winfo exists .pm2] {
518	Window destroy .pm2
519    }
520
521    menu .pm1 -tearoff 0 -borderwidth 1
522    .pm1 add command -label "Connect" -command "connect"
523    .pm1 add command -label "Edit" -command "propconn specsites"
524
525    .pm1 add command -label "Delete" -command "delconn"
526    .pm1 add command -label "Show info" -state "disabled"
527    .pm1 add command -label "Manage remote account" -command "manage_remote init"
528    .pm1 add cascade -label "Export as..." -menu .pm1.pm2
529    .pm1 add separator
530    .pm1 add command -label "New connection" -command "newconn 1"
531
532    menu .pm1.pm2 -tearoff 0 -borderwidth 1
533    .pm1.pm2 add command -label "Shellscript" -command "export sh" -state "disabled"
534    .pm1.pm2 add command -label "SSH configfile" -command "export ssh" -state "disabled"
535    .pm1.pm2 add command -label "GNOME icon" -command "export gnome" -state "disabled"
536    .pm1.pm2 add command -label "KDE icon" -command "export kde" -state "disabled"
537
538    tk_popup .pm1 [winfo pointerx .top17] [winfo pointery .top17]
539}
540
541proc historyman {mode "categ {}" "text {}"} {
542    global env histjob configs wins
543
544    switch -exact $mode {
545	write {
546	    set hf [open "$env(HOME)/.secpanel/history" a]
547	    puts $hf "$categ#[clock seconds]#$text"
548	    close $hf
549	    if [winfo exists .top26] {
550			historyman print
551	    }
552	}
553	show {
554	    Window show .top26
555
556	    if {[info exists configs(wingeom)] && $configs(wingeom)} {
557			if [info exists wins(hist)] {
558				wm geometry ".top26" $wins(hist)
559			}
560	    }
561
562	    set histjob 1
563	    historyman print
564	}
565	report {
566
567	    set repdir "$env(HOME)/.secpanel/reports"
568	    if {! [file exists "$repdir"]} {
569		file mkdir "$repdir"
570	    }
571
572	    set index [open "$repdir/index.html" w]
573	    puts $index "<!-- generated by secpanel [exec date]-->\n<frameset border=0 frameborder=\"no\" rows=\"10%,90%\">\n<frame src=\"header.html\" name=\"header\">\n<frameset border=0 frameborder=\"no\" cols=\"20%,80%\">\n<frame src=\"panel.html\" name=\"panel\">\n<frame src=\"1.html\" name=\"content\">\n</frameset></frameset>"
574	    close $index
575
576	    set header [open "$repdir/header.html" w]
577	    puts $header "<font size=\"+2\">Report of Secure Shell actions</font><br>Generated by secpanel [exec date]"
578	    close $header
579
580	    set panel [open "$repdir/panel.html" w]
581	    puts $panel "<b>Actions</b>\n<HR>\n<a target=\"content\" href=\"1.html\">SSH connect</a><br>\n<a target=\"content\" href=\"2.html\">SFTP connect</a><br>\n<a target=\"content\" href=\"4.html\">Keygen</a><br>\n<a target=\"content\" href=\"5.html\">Keydist</a><br>\n<a target=\"content\" href=\"6.html\">Agent</a><HR>"
582	    close $panel
583
584	    if {! [file exists "$env(HOME)/.secpanel/history"]} {
585		showmessage "No history available" .top26
586		return
587	    }
588
589	    foreach m {1 2 4 5 6} {
590		set modef[set m] [open "$repdir/[set m].html" w]
591		puts [set modef[set m]] "<table border=0 width=\"80%\">\n"
592	    }
593
594	    set hf [open "$env(HOME)/.secpanel/history" r]
595	    while {[gets $hf line] >= 0} {
596		set elems [split $line "#"]
597		set actmode [set modef[lindex $elems 0]]
598		puts $actmode "<tr><td>[clock format [lindex $elems 1]]<hr noshade></td><td>[lindex $elems 2]<hr noshade></td></tr>\n"
599	    }
600
601	    foreach m2 {1 2 4 5 6} {
602		puts [set modef[set m2]] "</table>\n"
603		close [set modef[set m2]]
604	    }
605	    showmessage "Report for actual history generated in ~/.secpanel/reports/index.html" .top26
606
607	    exec $configs(browserbin) "file:$env(HOME)/.secpanel/reports/index.html" &
608	}
609	print {
610	    set text .top26.cpd27.03
611	    $text delete 1.0 end
612	    if {! [file exists "$env(HOME)/.secpanel/history"]} {
613			return
614	    }
615	    set hf [open "$env(HOME)/.secpanel/history" r]
616	    while {[gets $hf line] >= 0} {
617			set elems [split $line "#"]
618			if {[lindex $elems 0] == $histjob} {
619				$text insert end "[clock format [lindex $elems 1]] - [lindex $elems 2]\n"
620			}
621	    }
622	    $text see end
623	    close $hf
624	}
625	clear {
626	    if [showconfirm "Really clear the history?\n(Keeping $categ days)" ".top26"] {
627		if {$categ != "0"} {
628		    set hfile "$env(HOME)/.secpanel/history"
629		    if {! [file exists $hfile]} {
630			showmessage "No history available" .top26
631			return
632		    }
633		    set now [clock seconds]
634		    set hf [open "$hfile" r]
635		    while {[gets $hf line] >= 0} {
636			set elems [split $line "#"]
637
638			if {[lindex $elems 1] >= [expr $now - ($categ * 24 * 60 * 60)]} {
639			    lappend kept $line
640			}
641
642		    }
643		    close $hf
644
645		    set hf [open "$hfile" w]
646		    foreach l $kept {
647			puts $hf $l
648		    }
649		    close $hf
650		} else {
651		    file delete "$env(HOME)/.secpanel/history"
652		}
653		historyman print
654	    } else {
655		return
656	    }
657	}
658    }
659}
660
661proc showcomm {mode} {
662    global widget lfstemp rfstemp
663    set actline [$widget([set mode]forwards) get active]
664    if [regsub { -> } $actline : out] {
665	$widget([set mode]fcomment) config -text [set [set mode]fstemp($out)]
666    }
667}
668
669proc add_forw {mode} {
670    global widget lfstemp rfstemp
671    set fhost [$widget([set mode]fhost) get]
672    set fin [$widget([set mode]fin) get]
673    set fout [$widget([set mode]fout) get]
674    set fcomment [$widget([set mode]fcommentent) get]
675
676    set lhostname "<TARGET-HOST>"
677    set rhostname "<LOCAL-HOST>"
678
679    if {$fhost == ""} {
680	set fht [set [set mode]hostname]
681    } else {
682	set fht $fhost
683    }
684
685    if {$fin != "" && $fout != ""} {
686
687	$widget([set mode]fcomment) config -text ""
688	foreach an [array names [set mode]fstemp] {
689	    if {$an == "$fin:$fht:$fout"} {
690		$widget([set mode]fcomment) config -text "Forward exists"
691		return
692	    }
693	}
694
695	$widget([set mode]forwards) insert end "$fin -> $fht:$fout"
696	set [set mode]fstemp($fin:$fht:$fout) $fcomment
697
698	$widget([set mode]fin) delete 0 end
699	$widget([set mode]fout) delete 0 end
700	$widget([set mode]fhost) delete 0 end
701	$widget([set mode]fcommentent) delete 0 end
702
703	focus $widget([set mode]fin)
704	$widget([set mode]forwards) see end
705    }
706}
707
708proc del_forw {mode} {
709    global widget lfstemp rfstemp
710    set lwin .top43
711    set rwin .top51
712
713    if {[selection own] == $widget([set mode]forwards)} {
714	set actline [$widget([set mode]forwards) get active]
715	if [regsub { -> } $actline : out] {
716	    unset [set mode]fstemp($out)
717	    $widget([set mode]forwards) delete active
718	}
719    } else {
720	showmessage "No forwarding selected" [set [set mode]win]
721    }
722    selection clear
723}
724
725proc save_forwards {mode} {
726    global widget rfs rfstemp lfs lfstemp
727    set lwin .top43
728    set rwin .top51
729
730    if [info exists [set mode]fs] {
731	unset [set mode]fs
732    }
733
734    array set [set mode]fs [array get [set mode]fstemp]
735
736    if [info exists [set mode]fstemp] {
737	unset [set mode]fstemp
738    }
739
740    Window destroy [set [set mode]win]
741}
742
743proc open_forwardings {mode} {
744    global widget lfs rfs lfstemp rfstemp
745    set lwin .top43
746    set rwin .top51
747
748    Window show [set [set mode]win]
749    $widget([set mode]forwards) delete 0 end
750
751    if [info exists [set mode]fstemp] {
752	unset [set mode]fstemp
753    }
754
755    if [info exists [set mode]fs] {
756	array set [set mode]fstemp [array get [set mode]fs]
757    }
758
759    foreach fe [array names [set mode]fstemp] {
760	if [regsub : $fe { -> } out] {
761	    $widget([set mode]forwards) insert end $out
762	}
763    }
764}
765
766proc changetab {mode} {
767    global libdir agent widget wins configs
768    switch -exact $mode {
769	"small" {
770
771	    if {! [$widget(specsites) index end] > 0} {
772		showmessage "No conncections available, please add one..." ""
773		return
774	    }
775
776	    wm withdraw .top17
777	    Window show .top27
778
779	    if {[info exists configs(wingeom)] && $configs(wingeom)} {
780		if [info exists wins(sat)] {
781		    wm geometry ".top27" $wins(sat)
782		}
783	    }
784
785	    .top27.but27 config -image [image create photo -file "$libdir/images/swinback_gr.gif"]
786
787	    if {$agent == 1 || $agent == "ext"} {
788		.top27.but27 config -bg green -fg black
789	    } else {
790		.top27.but27 config -bg red
791	    }
792
793	    specsiteupdate "ss"
794	    bind .top27 <Destroy> {
795		changetab big
796	    }
797	}
798	"big" {
799	    wm withdraw .top27
800	    destroyfilter .top27
801	    Window show .top17
802	}
803	"default" {
804	    foreach f {21 35 44 46} {
805		if {[grid info .top17.fra[set f]] != ""} {
806		    grid remove .top17.fra[set f]
807		}
808	    }
809	    array set frames {connect 46 terminal 44 key 35 ssh 21}
810
811	    grid .top17.fra$frames($mode) -in .top17 \
812		    -column 0 -row 1 -columnspan 1 -rowspan 1 \
813		    -ipadx 2 -ipady 2 -padx 2 -pady 2 -sticky nesw
814	    showstatus ""
815	}
816    }
817}
818
819proc choosefile {{entry ""} {startdir ""} {mode ""} {task ""}} {
820    global actdirsel env widget
821
822    switch -exact $task {
823	"identityent" {
824	    set entry $widget(identityent)
825	    set startdir $env(HOME)/.ssh
826	    set mode "Open"
827	}
828	"cfgfileent" {
829	    set entry $widget(cfgfileent)
830	    set startdir $env(HOME)/.ssh
831	    set mode "Open"
832	}
833	"keygen" {
834	    set entry "$widget(identpath)"
835	    set startdir "$env(HOME)/.ssh"
836	    set mode "Save"
837	}
838	"*" {
839	}
840    }
841
842    if {$startdir == "actdirsel"} {
843	if [info exists actdirsel] {
844	    set startdir $actdirsel
845	} else {
846	    set startdir "/usr/"
847	}
848    }
849
850    set choice [tk_get[set mode]File -initialdir $startdir]
851    if {$choice != ""} {
852	$entry delete 0 end
853	$entry insert 0 $choice
854	set actdirsel [file dirname $choice]
855    } else {
856	return
857    }
858}
859
860proc showmessage_wizard {text} {
861    global widget
862    $widget(messageline) config -text "$text"
863}
864
865proc distwizard {mode direct} {
866    global widget key connectionprofiles
867    switch -exact $mode {
868	"key" {
869	    switchtab_wizard "key"
870	    update_keylist
871	    $widget(contbutton) config -command "distwizard host f" -text "Continue" -state "active"
872	    $widget(backbutton) config -state "disabled" -command ""
873	    showmessage_wizard ""
874	}
875	"host" {
876	    if {$direct == "f"} {
877		set key [$widget(distkeyentry) get]
878		if {$key == ""} {
879		    showmessage_wizard "Please choose key!"
880		    return
881		}
882	    }
883	    switchtab_wizard "host"
884	    $widget(contbutton) config -command "distwizard confirm f" -text "Continue" -state "active"
885	    $widget(backbutton) config -command "distwizard key b" -state "active"
886	    showmessage_wizard ""
887	}
888	"confirm" {
889	    if {$direct == "f"} {
890		if {[selection own] != $widget(distconnlist)} {
891		    showmessage_wizard "Please choose connection!"
892		    return
893		}
894		set connections [$widget(distconnlist) curselection]
895	    }
896
897	    set connectiontitles ""
898	    set connectionprofiles ""
899	    foreach connentry $connections {
900		set connectiontitles [concat $connectiontitles [$widget(distconnlist) get $connentry]]
901		lappend connectionprofiles [retprof [$widget(distconnlist) get $connentry]]
902	    }
903
904	    switchtab_wizard "confirm"
905	    $widget(finishmessage) config -text "Distribute\n$key\nto connection\n[lsort $connectiontitles]"
906	    $widget(contbutton) config -command "distwizard finish f" -text "Distribute key" -state "active"
907	    $widget(backbutton) config -command "distwizard host b" -state "active"
908	    showmessage_wizard ""
909	}
910	"finish" {
911	    Window destroy .top53
912	    distkey "\"$key\"" "$connectionprofiles"
913	}
914    }
915}
916
917
918proc distkey {key connectionprofiles} {
919    global env widget libdir configs termtype
920
921    set connstring ""
922
923    foreach actconn $connectionprofiles {
924
925	source "$env(HOME)/.secpanel/profiles/$actconn.profile"
926
927	if {$user == "<ASKFORUSER>"} {
928	    set user [askforuser]
929	    if {$user == "#####"} {
930		return
931	    }
932	}
933
934	set singleactstring "$libdir/spdistkey $host $port $user $key $configs(sshbin)"
935	set connstring "$connstring $singleactstring"
936	set connstring "$connstring \n\n\necho ==============================================================\n\n"
937
938	historyman write 5 "$key -> $user@$host"
939
940    }
941    set connstring "$connstring echo
942    echo \"Key-Distribution finished\nPress <Return> to continue\"
943    read out
944    exit"
945
946
947    set usetermver $configs(termver)
948
949    set icontag ""
950
951    set configs(xtermbin) $termtype([set usetermver]_path)
952    set titlepar $termtype([set usetermver]_titlepar)
953    set quotepar $termtype([set usetermver]_quotepar)
954    set execpar $termtype([set usetermver]_execpar)
955    if {[info exists termicon] && $termicon} {
956	set icontag $termtype([set usetermver]_iconpar)
957    }
958    # </xterm selection and params>
959
960    set runstring "exec $configs(xtermbin) $titlepar \"secpanel Key-Distribution\" $execpar $quotepar <CONNFILE> $quotepar"
961
962    provrunfile term bg $connstring $runstring
963}
964
965proc command_trace {mode "text {}"} {
966    global env configs wins
967
968    set tracetext ".top24.cpd25.03"
969    set tracefile "$env(HOME)/.secpanel/.runfiles/trace.log"
970
971    switch -exact $mode {
972		"view" {
973			Window show .top24
974
975			if {[info exists configs(wingeom)] && $configs(wingeom)} {
976				if [info exists wins(trace)] {
977					wm geometry ".top24" $wins(trace)
978				}
979			}
980
981			$tracetext delete 1.0 end
982			if [file exists "$tracefile"] {
983				set tf [open "$tracefile" r]
984				while {[gets $tf line] >= 0} {
985					set elems [split $line "#"]
986					$tracetext insert end "[clock format [lindex $elems 0]] - [lindex $elems 1]\n"
987				}
988				close $tf
989			} else {
990				$tracetext insert end "No tracelog available"
991			}
992			$tracetext see end
993		}
994		"save" {
995			set tf [open "$tracefile" a]
996			puts $tf "[clock seconds]#[quote_double_space $text]"
997			close $tf
998			if [winfo exists .top24] {
999				command_trace "view"
1000			}
1001		}
1002    }
1003}
1004
1005proc switchtab_wizard {mode} {
1006	global widget
1007	foreach f {key host confirm} {
1008		if {[grid info $widget([set f]frame)] != ""} {
1009			grid remove $widget([set f]frame)
1010		}
1011	}
1012
1013	grid $widget([set mode]frame) -in .top53  -column 0 -row 1 -columnspan 1 -rowspan 1  -ipadx 2 -ipady 2 -padx 2 -pady 2 -sticky nesw
1014}
1015
1016proc clear_prmenu {} {
1017    global env widget
1018    $widget(profiles) delete 0 end
1019    foreach prof [lsort [glob -nocomplain "$env(HOME)/.secpanel/profiles/*.profile"]] {
1020	$widget(profiles) insert end "[file rootname [file tail $prof]]"
1021    }
1022}
1023
1024proc clear_profiles {} {
1025    global env widget noagentforward x11forward stricthost nopriv lfs rfs \
1026	    verbose quiet fork gateway compress algo compressval \
1027	    connwait termicon sshverconnect ipverconnect askuserspec noexec
1028
1029    foreach b {noagentforward x11forward stricthost nopriv \
1030	    verbose quiet fork gateway compress connwait termicon askuserspec noexec} {
1031	set [set b] 0
1032    }
1033
1034    set algo "default"
1035    set compressval 6
1036
1037    foreach e {profile host command title subsys identity cfgfile user port} {
1038	$widget([set e]ent) delete 0 end
1039    }
1040
1041    if [info exists lfs] {
1042	unset lfs
1043    }
1044
1045    if [info exists rfs] {
1046	unset rfs
1047    }
1048
1049    $widget(userent) insert 0 "$env(USER)"
1050    $widget(portent) insert 0 "22"
1051
1052    set sshverconnect "2"
1053    set ipverconnect "4"
1054
1055    if {[winfo exists .top43]} {
1056	Window destroy .top43
1057	open_forwardings l
1058    }
1059
1060    if {[winfo exists .top51]} {
1061	Window destroy .top51
1062	open_forwardings r
1063    }
1064}
1065
1066proc provrunfile {term bg connstring runstring} {
1067    global env platform libdir
1068
1069    if {$bg=="bg"} {
1070		set bgtag "&"
1071    } else {
1072		set bgtag ""
1073    }
1074
1075    if {$term == "term"} {
1076	set cf "$env(HOME)/.secpanel/.runfiles/runproc.[clock clicks]"
1077	set connfile [open $cf w]
1078
1079	puts $connfile "#!/bin/sh\n"
1080	puts $connfile $connstring
1081
1082	if {$bg == "nobg"} {
1083	    puts $connfile "\necho \"secpanel: Cleaning up handling data for this operation...\";\nrm -f $cf"
1084	}
1085
1086
1087		close $connfile
1088		exec chmod +x $cf
1089
1090		set cfr "$cf-run"
1091		set crfile [open "$cfr" w]
1092
1093		puts $crfile [regsub {<CONNFILE>} $runstring $cf]
1094		close $crfile
1095		exec chmod +x $cfr
1096
1097		exec $cfr $bgtag
1098    } else {
1099		set cfr "$env(HOME)/.secpanel/.runfiles/runproc.[clock clicks]-run"
1100		set crfile [open "$cfr" w]
1101
1102		puts $crfile "$runstring $connstring"
1103		close $crfile
1104		exec chmod +x $cfr
1105
1106		exec $cfr $bgtag
1107    }
1108
1109}
1110
1111proc connect_sftp {} {
1112    global widget env configs libdir
1113
1114    if {! [$widget(specsites) index end] > 0} {
1115		showmessage "No connections available, please use \"New\"" ""
1116		return
1117    }
1118
1119    if {[selection own] != $widget(specsites)} {
1120		showmessage "Please select connection" .top17
1121		return
1122    }
1123
1124    set connsel [$widget(specsites) curselection]
1125
1126    set connstring ""
1127
1128    foreach connselentry $connsel {
1129
1130		set actconn [retprof [$widget(specsites) get $connselentry]]
1131
1132		source "$env(HOME)/.secpanel/profiles/$actconn.profile"
1133
1134		if {$user == "<ASKFORUSER>"} {
1135			set user [askforuser]
1136			if {$user == "#####"} {
1137				return
1138			}
1139		}
1140
1141		switch -exact $configs(sftpbin) {
1142		    "Filezilla" {
1143			set runstring "filezilla -l interactive "
1144		    }
1145		    "Thunar" {
1146			set runstring "thunar "
1147		    }
1148		    "GNOME-Nautilus" {
1149			set runstring "nautilus "
1150		    }
1151		    "KDE-Konqueror" {
1152			set runstring "konqueror "
1153		    }
1154		}
1155
1156		set connstring "sftp://$user@$host:$port"
1157
1158		command_trace save "$runstring$connstring"
1159		provrunfile noterm bg "" $runstring$connstring
1160		historyman write 2 "$connstring"
1161    }
1162}
1163
1164proc multiconnect {mode} {
1165    global widget env configs libdir
1166
1167    if {! [$widget(specsites) index end] > 0} {
1168		showmessage "No connections available, please use \"New\"" ""
1169		return
1170    }
1171
1172    if {[selection own] != $widget(specsites)} {
1173		showmessage "Please select connection" .top17
1174		return
1175    }
1176
1177    set connsel [$widget(specsites) curselection]
1178
1179    set connstring ""
1180
1181    foreach connselentry $connsel {
1182
1183	set actconn [retprof [$widget(specsites) get $connselentry]]
1184
1185	source "$env(HOME)/.secpanel/profiles/$actconn.profile"
1186
1187	if {$user == "<ASKFORUSER>"} {
1188		set user [askforuser]
1189		if {$user == "#####"} {
1190			return
1191		}
1192	}
1193	switch -exact $mode {
1194	    "multixterm" {
1195		set connstring "$connstring $user@$host:$port"
1196	    }
1197	    "cssh" {
1198		set connstring "$connstring $user@$host:$port"
1199	    }
1200	}
1201    }
1202
1203    switch -exact $mode {
1204	"multixterm" {
1205	    set runstring "multixterm -xc \"ssh %n\""
1206	}
1207	"cssh" {
1208	    set runstring "cssh"
1209	}
1210    }
1211
1212    command_trace save "$runstring $connstring"
1213    provrunfile noterm bg $connstring $runstring
1214}
1215
1216proc connect {{cm ""}} {
1217    global widget env configs libdir termtype
1218
1219    set sshverconnect 1
1220
1221    if {$cm == "ss"} {
1222	set connsel 1
1223    } else {
1224
1225	if {! [$widget(specsites) index end] > 0} {
1226	    showmessage "No connections available, please use \"New\"" ""
1227	    return
1228	}
1229
1230	if {[selection own] != $widget(specsites)} {
1231	    showmessage "Please select connection" .top17
1232	    return
1233	}
1234
1235	set connsel [$widget(specsites) curselection]
1236
1237    }
1238
1239
1240    foreach connselentry $connsel {
1241
1242		if {$cm == "ss"} {
1243		    set actconn [retprof [$widget(sspecsites).sspecmenu entrycget active -label]]
1244		} else {
1245		    set actconn [retprof [$widget(specsites) get $connselentry]]
1246		}
1247
1248		source "$env(HOME)/.secpanel/profiles/$actconn.profile"
1249
1250		if {$user == "<ASKFORUSER>"} {
1251			set user [askforuser]
1252			if {$user == "#####"} {
1253			return
1254			}
1255		}
1256
1257		if {[array size lfs] > 0} {
1258			foreach lf [array names lfs] {
1259			if {[regsub {<TARGET-HOST>} [lindex [split $lf :] 1] $host th]} {
1260				append lf_tag " -L [lindex [split $lf :] 0]:$th:[lindex [split $lf :] 2] "
1261			} else {
1262				append lf_tag " -L [lindex [split $lf :] 0]:[lindex [split $lf :] 1]:[lindex [split $lf :] 2] "
1263			}
1264			}
1265		} else {
1266			set lf_tag " "
1267		}
1268
1269		set localhost [info hostname]
1270		if {[array size rfs] > 0} {
1271			foreach rf [array names rfs] {
1272			if {[regsub {<LOCAL-HOST>} [lindex [split $rf :] 1] $localhost lh]} {
1273				append rf_tag " -R [lindex [split $rf :] 0]:$lh:[lindex [split $rf :] 2] "
1274			} else {
1275				append rf_tag " -R [lindex [split $rf :] 0]:[lindex [split $rf :] 1]:[lindex [split $rf :] 2] "
1276			}
1277			}
1278		} else {
1279			set rf_tag " "
1280		}
1281
1282		if {$user != ""} {
1283			set user_tag "-l $user "
1284		} else {
1285			set user_tag " "
1286		}
1287
1288		if {$port == 22 || $port == ""} {
1289			set port_tag " "
1290		} else {
1291			set port_tag "-p $port "
1292		}
1293
1294		if {$algo != "default" || $algo == ""} {
1295			set algo_tag "-c $algo "
1296		} else {
1297			set algo_tag " "
1298		}
1299
1300		if {$identity != ""} {
1301			set ident_tag "-i $identity "
1302		} else {
1303			set ident_tag " "
1304		}
1305
1306		if {[info exists cfgfile] && $cfgfile != ""} {
1307			set cfgfile_tag "-F $cfgfile "
1308		} else {
1309			set cfgfile_tag " "
1310		}
1311
1312		if {[info exists noagentforward] && $noagentforward} {
1313			set noagentforward_tag "-a "
1314		} else {
1315			set noagentforward_tag "-A "
1316		}
1317
1318		if {$command != "" && ([info exists noexec] && ! $noexec) && \
1319			([info exists subsys] && $subsys == "")} {
1320			set command_tag "$command"
1321		} elseif {[info exists subsys] && $subsys != ""} {
1322			set command_tag "-s $subsys"
1323		} else {
1324			set command_tag ""
1325		}
1326
1327		if $compress {
1328			# openssh
1329			if {$configs(sshver) == "OpenSSH"} {
1330			set compressval_tag "-o \'CompressionLevel [set compressval]\' "
1331			} else {
1332			set compressval_tag "-o CompressionLevel=$compressval "
1333			}
1334		} else {
1335			set compressval_tag " "
1336		}
1337
1338		array set bools {
1339			"x11forward" "-x" \
1340			"stricthost" "-o StrictHostKeyChecking=yes" \
1341			"nopriv" "-P" \
1342			"verbose" "-v" \
1343			"quiet" "-q" \
1344			"fork" "-f" \
1345			"gateway" "-g" \
1346			"compress" "-C" \
1347			"noexec" "-N"
1348		}
1349
1350		# foreach f [array names $bools]
1351		foreach f {x11forward stricthost nopriv verbose \
1352				   quiet fork gateway compress noexec} {
1353			if {[info exists $f] && [set $f]} {
1354			set [set f]_tag "$bools($f) "
1355			} else {
1356			set [set f]_tag " "
1357			}
1358		}
1359
1360		if [info exists sshverconnect] {
1361			set sshvertag "-[set sshverconnect] "
1362		}
1363
1364		if [info exists ipverconnect] {
1365			set ipvertag "-[set ipverconnect] "
1366		} else {
1367			set ipvertag " "
1368		}
1369
1370		# openssh
1371		if {$configs(sshver) == "OpenSSH"} {
1372			if {[info exists x11forward] && ! $x11forward} {
1373			set x11forward_tag "-X "
1374			}
1375			if {[info exists noexec] && $noexec} {
1376			set noexec_tag "-N "
1377			}
1378		}
1379
1380		set usetermver $configs(termver)
1381
1382		set icontag ""
1383
1384		set configs(xtermbin) $termtype([set usetermver]_path)
1385		set titlepar $termtype([set usetermver]_titlepar)
1386		set quotepar $termtype([set usetermver]_quotepar)
1387		set execpar $termtype([set usetermver]_execpar)
1388		if {[info exists termicon] && $termicon} {
1389			set icontag $termtype([set usetermver]_iconpar)
1390		}
1391		# </xterm selection and params>
1392
1393
1394		set waittag ""
1395		set woption ""
1396		if {[info exists connwait] && $connwait } {
1397			set waittag "$libdir/secpanel.wait"
1398			set woption "\'"
1399		}
1400
1401		set connstring "$configs(sshbin) $user_tag \
1402			$noagentforward_tag $x11forward_tag $noexec_tag $stricthost_tag $sshvertag \
1403				$ipvertag $port_tag $algo_tag \
1404			$ident_tag $cfgfile_tag $nopriv_tag $verbose_tag $quiet_tag \
1405			$fork_tag $gateway_tag $compress_tag $compressval_tag \
1406			$lf_tag $rf_tag $host $command_tag"
1407
1408		set runstring "exec $configs(xtermbin) $icontag $titlepar \"SSH Connection - $title\" \
1409			$execpar $quotepar $waittag $woption <CONNFILE> $woption $quotepar"
1410
1411		provrunfile term bg $connstring $runstring
1412
1413		historyman write 1 "$title"
1414		command_trace save "$connstring"
1415    }
1416}
1417
1418
1419proc showconfirm {text parent} {
1420    global questres
1421
1422    if {$parent == ""} {
1423	set p .top17
1424    } else {
1425	set p $parent
1426    }
1427
1428    set old [focus]
1429    Window show .top18
1430
1431    set xcoord [expr [winfo rootx $p] + ([winfo width $p] / 2) - ([winfo width .top18] / 2)]
1432    set ycoord [expr [winfo rooty $p] + ([winfo height $p] / 2) - ([winfo height .top18] / 2)]
1433    wm geometry .top18 +$xcoord+$ycoord
1434
1435    .top18.mes19 config -text "$text"
1436    tkwait visibility .top18
1437
1438    focus .top18
1439    grab .top18
1440    tkwait variable questres
1441    grab release .top18
1442    focus $old
1443    Window destroy .top18
1444    if {$questres} {
1445	return 1
1446    } else {
1447	return 0
1448    }
1449}
1450
1451proc getuser {} {
1452    global widget userres
1453    set userres [$widget(askeduser) get]
1454}
1455
1456proc askforuser {"mode c"} {
1457    global userres widget
1458    set old [focus]
1459    Window show .top21
1460
1461    if {$mode == "md"} {
1462	wm title .top21 "secpanel - Make dir"
1463	.top21.fra22.mes23 config -text "Enter name of new directory:"
1464	.top21.but26 config -text "Make dir"
1465    }
1466
1467    if {$mode == "protectdata"} {
1468	wm title .top21 "secpanel - Give password for secpanel data protection"
1469	.top21.fra22.mes23 config -text "Enter name of new directory:"
1470	.top21.but26 config -text "Make dir"
1471    }
1472
1473    tkwait visibility .top21
1474    focus $widget(askeduser)
1475    grab .top21
1476    tkwait variable userres
1477    grab release .top21
1478    focus $old
1479    Window destroy .top21
1480    return $userres
1481}
1482
1483proc quote_space {in} {
1484    regsub -all " " $in "\\ " out
1485    return $out
1486}
1487
1488proc quote_double_space {in} {
1489    regsub -all " +" $in " " out
1490    return $out
1491}
1492
1493proc showmessage {text parent} {
1494    if {$parent == ""} {
1495	set p .top17
1496    } else {
1497	set p $parent
1498    }
1499
1500    Window show .top22
1501    .top22.mes23 config -text $text
1502
1503    set xcoord [expr [winfo rootx $p] + ([winfo width $p] / 2) - ([winfo width .top22] / 2)]
1504    set ycoord [expr [winfo rooty $p] + ([winfo height $p] / 2) - ([winfo height .top22] / 2)]
1505    wm geometry .top22 +$xcoord+$ycoord
1506
1507    focus .top22
1508    grab .top22
1509    tkwait window .top22
1510}
1511
1512
1513proc check_sources {mode} {
1514    global configs
1515    switch -exact $mode {
1516	ssh {
1517	}
1518	sp {
1519	    exec $configs(browserbin) "http://secpanel.net/?sp_check" &
1520	}
1521    }
1522}
1523
1524proc delconn {} {
1525    global widget env
1526    if {[selection own] == $widget(specsites)} {
1527	set actentry [$widget(specsites) get active]
1528	set delprof [retprof $actentry]
1529	if {[showconfirm "Delete $actentry?" ""] == 1} {
1530	    file delete "$env(HOME)/.secpanel/profiles/$delprof.profile"
1531	    specsiteupdate
1532	    clear_prmenu
1533	    selection clear
1534	} else {
1535	    return
1536	}
1537
1538    } else {
1539	showmessage "No entry selected" ""
1540    }
1541}
1542
1543proc delete_profile {} {
1544    global env widget
1545    set act [$widget(profileent) get]
1546    if {$act == ""} {
1547	showmessage "To delete a profile first load it" ""
1548	return
1549    }
1550    if {[showconfirm "Delete $act?" ""] == 1} {
1551	file delete "$env(HOME)/.secpanel/profiles/$act.profile"
1552	clear_prmenu
1553	clear_profiles
1554	specsiteupdate
1555    }
1556}
1557
1558proc hostkey {mode} {
1559    global env widget configs hostkeytype
1560    set khfile "$env(HOME)/.ssh/known_hosts"
1561
1562    catch {exec $configs(keygenbin) -h} ver
1563    if [regexp -nocase "F hostname Find hostname" $ver] {
1564	set hostkeytype "hashed"
1565    } else {
1566	set hostkeytype "clear"
1567    }
1568
1569    switch -exact $mode {
1570	edit {
1571
1572	    Window show .top50
1573	    $widget(knownhosts) delete 0 end
1574
1575	    if { ! [file exists $khfile]} {
1576		showmessage "No $khfile found" ""
1577		return
1578	    }
1579
1580	    if {$hostkeytype=="hashed"} {
1581
1582		# handle new hashed hostkey format
1583		set profiles [glob -nocomplain "$env(HOME)/.secpanel/profiles/*.profile"]
1584
1585		foreach prof [lsort $profiles] {
1586		    source $prof
1587		    catch {exec $configs(keygenbin) -F $host} ver
1588
1589		    if [regexp -nocase "found" $ver] {
1590			$widget(knownhosts) insert end $host
1591		    }
1592		}
1593
1594		return
1595		# end of handling hashed hostkeys
1596
1597	    } else {
1598
1599		set hosts [open $khfile r]
1600		while {[gets $hosts line] >= 0} {
1601		    lappend hl [lindex [split $line] 0]
1602		}
1603
1604		if {[file size $khfile] > 0} {
1605		    foreach h [lsort $hl] {
1606			$widget(knownhosts) insert end $h
1607		    }
1608		}
1609
1610		close $hosts
1611		return
1612	    }
1613	}
1614	view {
1615	    keygen info host
1616	}
1617	export {
1618	    if {[selection own] != $widget(knownhosts)} {
1619		showmessage "No hostkey selected!" ".top50"
1620		return
1621	    }
1622	    set actk [$widget(knownhosts) get active]
1623	    set hkf [tk_getSaveFile -initialdir "$env(HOME)"]
1624	    if {$hkf == ""} {
1625		return
1626	    } else {
1627		set hkfout [open "$hkf" w]
1628
1629		set hosts [open $khfile r]
1630		while {[gets $hosts line] >= 0} {
1631		    set kparts [split $line]
1632		    if {[lindex $kparts 0] == $actk} {
1633			puts $hkfout $line
1634			break
1635		    }
1636		}
1637		close $hosts
1638
1639		close $hkfout
1640		return
1641	    }
1642	}
1643	delete {
1644	    if {[selection own] != $widget(knownhosts)} {
1645		showmessage "No hostkey selected!" ".top50"
1646		return
1647	    }
1648	    set actk [$widget(knownhosts) get active]
1649	    if {[showconfirm "Delete $actk?" ".top50"] == 1} {
1650
1651		if {$hostkeytype=="hashed"} {
1652		    # handle deletion of hashed hostkeys
1653		    if [catch {exec $configs(keygenbin) -R $actk} err] {
1654			showmessage $err ""
1655		    }
1656		    # end handling deletion of hashed hostkeys
1657		} else {
1658
1659		    if [file exists $khfile] {
1660			set hosts [open $khfile r]
1661			# read lines
1662			while {[gets $hosts line] >= 0} {
1663			    lappend klines $line
1664			}
1665			close $hosts
1666			# write lines
1667			set hosts [open $khfile w]
1668			foreach line $klines {
1669			    set kparts [split $line]
1670			    if {[lindex $kparts 0] != $actk} {
1671				puts $hosts $line
1672			    }
1673			}
1674			close $hosts
1675		    }
1676		}
1677		hostkey edit
1678		selection clear
1679	    } else {
1680		return
1681	    }
1682	}
1683    }
1684}
1685
1686proc insprot {nr mode} {
1687    global widget
1688    $widget([set mode]fout) delete 0 end
1689    $widget([set mode]fout) insert 0 $nr
1690}
1691
1692proc keygen {mode "in_keytype {}"} {
1693    global env widget configs pwtextmode libdir nopass passintext kf keytype termtype
1694
1695
1696    set usetermver $configs(termver)
1697
1698    set icontag ""
1699
1700    set configs(xtermbin) $termtype([set usetermver]_path)
1701    set titlepar $termtype([set usetermver]_titlepar)
1702    set quotepar $termtype([set usetermver]_quotepar)
1703    set execpar $termtype([set usetermver]_execpar)
1704    if {[info exists termicon] && $termicon} {
1705	set icontag $termtype([set usetermver]_iconpar)
1706    }
1707    # </xterm selection and params>
1708
1709
1710    switch -exact $mode {
1711	gen {
1712	    # comment
1713	    if {[.top52.fra18.ent24 get] == ""} {
1714		set commtag " "
1715	    } else {
1716		set commtag "-C '[.top52.fra18.ent24 get]' "
1717	    }
1718
1719	    # file
1720	    array set ktfiles {"SSH1 RSA1" "identity" "SSH2 RSA" "id_rsa" "SSH2 DSA" "id_dsa"}
1721	    set ktfile $ktfiles($keytype)
1722
1723	    set identfile "[$widget(identpath) get]"
1724	    if {$identfile == ""} {
1725		set identfile "$env(HOME)/.ssh/$ktfile"
1726	    }
1727	    set filetag "-f $identfile "
1728
1729	    if [file exists $identfile] {
1730		if [showconfirm "$identfile exists. Overwrite?" .top52] {
1731		    file delete $identfile
1732		} else {
1733		    return
1734		}
1735	    }
1736
1737	    # pass
1738	    if {$nopass} {
1739		set passtag "-N \"\""
1740	    } elseif {$passintext} {
1741		set passtag " "
1742	    } elseif {[.top52.fra18.ent29 get] == ""} {
1743		showmessage "Please enter the password for the new key!" .top52
1744		return
1745	    } else {
1746		if {[.top52.fra18.ent29 get] == [.top52.fra18.ent25 get]} {
1747		    set passtag "-N [.top52.fra18.ent29 get] "
1748		} else {
1749		    showmessage "Password and repeated password are not the same!" .top52
1750		    return
1751		}
1752	    }
1753
1754	    # type
1755	    array set ktshorts {"SSH1 RSA1" "rsa1" "SSH2 RSA" "rsa" "SSH2 DSA" "dsa"}
1756	    set typetag "-t $ktshorts($keytype) "
1757
1758	    set connstring "$configs(keygenbin) $filetag $passtag $typetag $commtag"
1759
1760	    if {$passintext} {
1761			set kgstringt "$configs(keygenbin) $filetag $typetag $commtag"
1762	    } else {
1763			set kgstringt "$configs(keygenbin) $filetag -N ***** $typetag $commtag"
1764	    }
1765
1766	    set runstring "exec $configs(xtermbin) $titlepar \"secpanel ssh-keygen\" \
1767		    $execpar $quotepar $libdir/secpanel.wait <CONNFILE> $quotepar"
1768
1769
1770
1771	    command_trace save "$kgstringt"
1772	    historyman write 4 "$identfile"
1773
1774	    provrunfile term nobg $connstring $runstring
1775
1776	    update_keylist
1777	    keygen clear
1778
1779	}
1780	"clear" {
1781	    foreach ke {.top52.fra18.ent24 .top52.fra18.ent29 .top52.fra18.ent29 .top52.fra18.ent25} {
1782		[set ke] delete 0 end
1783	    }
1784	    $widget(identpath) delete 0 end
1785	    set keytype "SSH2 DSA"
1786	    set nopass 0
1787	    set passintext 0
1788	    set pwtextmode 0
1789	}
1790	0 {
1791	    set keytype "SSH2 DSA"
1792	    Window show .top52
1793	    .top52.fra18.but27 configure -image [image create photo -file $libdir/images/folder.gif]
1794	    update_keylist
1795	}
1796	1 {
1797	    if {[selection own] != $widget(keylist)} {
1798		showmessage "No key selected!" .top52
1799		return
1800	    }
1801
1802	    set kf "$env(HOME)/.ssh/[$widget(keylist) get active]"
1803
1804	    if [set pwtextmode] {
1805		set connstring "$configs(keygenbin) -p -f $kf"
1806
1807		set runstring "exec $configs(xtermbin) $titlepar \"secpanel - \
1808			change password for $kf\" \
1809			$execpar $quotepar $libdir/secpanel.wait <CONNFILE> $quotepar"
1810
1811		provrunfile term bg $connstring $runstring
1812	    } else {
1813		Window show .top20
1814		$widget(proplabel) config -text $kf
1815	    }
1816	}
1817	chpwd {
1818	    set oldp [.top20.fra21.ent26 get]
1819	    set newp1 [.top20.fra21.ent30 get]
1820	    set newp2 [.top20.fra21.ent31 get]
1821
1822	    if {$newp1 != $newp2} {
1823		showmessage "New password and repeated new password don't match" ""
1824		return
1825	    }
1826
1827	    set chpwdstr "$configs(keygenbin) -p -f $kf -P ***** -N *****"
1828
1829	    if [catch {exec $configs(keygenbin) -p -f $kf -P $oldp -N $newp1} err] {
1830		showmessage $err ""
1831		return
1832	    }
1833	    Window destroy .top20
1834	    command_trace save "$chpwdstr"
1835	}
1836	info {
1837	    if {$in_keytype != "host"} {
1838
1839		if {[$widget(keylist) index end] == 0} {
1840		    return
1841		}
1842
1843		if {[selection own] != $widget(keylist)} {
1844		    showmessage "No key selected!" .top52
1845		    return
1846		}
1847		set actk [$widget(keylist) get active]
1848		set actkfile "$env(HOME)/.ssh/$actk"
1849		if {! [file exists "$actkfile"]} {
1850		    showmessage "Keyfile not found" .top52
1851		    return
1852		}
1853	    } else {
1854		set khfile "$env(HOME)/.ssh/known_hosts"
1855
1856		if {[$widget(knownhosts) index end] == 0} {
1857		    return
1858		}
1859
1860		set actk [$widget(knownhosts) get active]
1861
1862		if [file exists $khfile] {
1863		    if {[file size $khfile] > 0} {
1864			set hosts [open $khfile r]
1865			while {[gets $hosts line] >= 0} {
1866			    set kparts [split $line]
1867			    if {[lindex $kparts 0] == $actk} {
1868				set fname "$env(HOME)/.secpanel/.runfiles/hkview.[clock clicks]"
1869				set af [open "$fname" w]
1870				puts $af $line
1871				close $af
1872				set actkfile "$fname"
1873			    }
1874			}
1875			close $hosts
1876		    } else {
1877			showmessage "Keyfile empty" .top50
1878			return
1879		    }
1880		} else {
1881		    showmessage "Keyfile not found" .top50
1882		    return
1883		}
1884	    }
1885
1886	    set fptext ".top19.tex17"
1887	    set bbtext ".top19.tex18"
1888
1889	    if [file exists "$actkfile"] {
1890		Window show .top19
1891
1892		if {$in_keytype != "host"} {
1893		    set kt "user key"
1894		} else {
1895		    set kt "host key"
1896		}
1897
1898		.top19.fra22.lab23 config -text "Keyfile: $actkfile"
1899		.top19.fra22.lab24 config -text "Keytype: $kt"
1900
1901		$fptext config -state normal
1902		$bbtext config -state normal
1903
1904		$fptext delete 1.0 end
1905		$bbtext delete 1.0 end
1906
1907		$fptext insert end "[exec $configs(keygenbin) -l -f $actkfile]"
1908		$bbtext insert end "[exec $configs(keygenbin) -B -f $actkfile]"
1909
1910		$fptext config -state disabled
1911		$bbtext config -state disabled
1912		return
1913	    } else {
1914		showmessage "Couldn't find the public key for this identity!" .top52
1915		return
1916	    }
1917	}
1918	del {
1919	    if {[selection own] != $widget(keylist)} {
1920		showmessage "No key selected!" .top52
1921		return
1922	    }
1923
1924	    if [showconfirm "Really delete [$widget(keylist) get active]?" .top52] {
1925		file delete -force "$env(HOME)/.ssh/[$widget(keylist) get active]"
1926		file delete -force "$env(HOME)/.ssh/[$widget(keylist) get active].pub"
1927		update_keylist
1928	    }
1929	}
1930	chpath {
1931	    choosefile "" "" "" keygen
1932	}
1933	dist {
1934	    Window show .top53
1935	    specsiteupdate
1936	    distwizard key f
1937	}
1938    }
1939}
1940
1941proc update_keylist {} {
1942    global widget env
1943    if [winfo exists .top52] {
1944	$widget(keylist) delete 0 end
1945    }
1946    if [winfo exists .top53] {
1947	$widget(distkeylist) delete 0 end
1948    }
1949
1950    set keyfiles [glob -nocomplain "$env(HOME)/.ssh/*.pub"]
1951    foreach kf [lsort $keyfiles] {
1952	if [winfo exists .top52] {
1953	    $widget(keylist) insert end [file rootname [file tail $kf]]
1954	}
1955	if [winfo exists .top53] {
1956	    $widget(distkeylist) insert end [file rootname [file tail $kf]]
1957	}
1958    }
1959}
1960
1961proc load_profile {mode} {
1962    global env widget noagentforward x11forward stricthost nopriv \
1963	verbose quiet fork gateway compress algo \
1964	compressval lfs rfs connwait termicon sshverconnect \
1965	ipverconnect askuserspec noexec
1966
1967    foreach var {noagentforward x11forward stricthost nopriv \
1968		     verbose quiet fork gateway compress algo \
1969		     compressval lfs rfs connwait termicon askuserspec noexec} {
1970	if [info exists [set var]] {
1971	    unset $var
1972	}
1973    }
1974
1975    foreach rvar {sshverconnect ipverconnect} {
1976	if [info exists [set rvar]] {
1977	    unset $rvar
1978	}
1979    }
1980
1981    if {! [info exists sshverconnect]} {
1982	set sshverconnect "2"
1983    }
1984
1985    if {! [info exists ipverconnect]} {
1986	set ipverconnect "4"
1987    }
1988
1989    if {$mode == "ssh"} {
1990	set profile [$widget(profiles) get active]
1991    } elseif {$mode == "specsites"} {
1992	set profile [retprof [$widget(specsites) get active]]
1993    }
1994
1995    source $env(HOME)/.secpanel/profiles/$profile.profile
1996
1997    foreach f {title host user port command subsys identity cfgfile profile} {
1998	$widget([set f]ent) delete 0 end
1999	if [info exists $f] {
2000	    $widget([set f]ent) insert 0 [set $f]
2001	}
2002    }
2003
2004    if {! [array exists lfs] && $lfs != ""} {
2005	set lfsnew [set lfs]
2006	unset lfs
2007	foreach listelem $lfsnew {
2008	    array set lfs \
2009		    "[lindex [split $listelem :] 0]:<TARGET-HOST>:[lindex [split $listelem :] 1] \
2010		    {Local forward vom old Version of secpanel}"
2011	}
2012    }
2013
2014    if {[winfo exists .top43]} {
2015	open_forwardings l
2016    }
2017
2018    if {[winfo exists .top51]} {
2019	open_forwardings r
2020    }
2021}
2022
2023proc manage_agent {mode "m run"} {
2024    global env widget configs launcher defident agent wins
2025    switch -exact $mode {
2026	"launch" {
2027
2028	    if {[info exists env(SSH_AGENT_PID)] && [info exists env(SSH_AUTH_SOCK)]} {
2029		if {[showconfirm "There seems to be another SSH-Agent. Start anyway?" ""] == 0} {
2030		    return
2031		}
2032	    }
2033
2034	    # Start ssh-agent and read envs
2035	    if {! [file exists "$configs(agentbin)"] && [catch {exec which "$configs(agentbin)"}]} {
2036		showmessage "Can't find SSH-Agent ($configs(agentbin))\nCheck configration!" ".top17"
2037		changetab terminal
2038		return error
2039	    }
2040
2041	    set agentout [open "| $configs(agentbin) -c" r]
2042	    while {[gets $agentout line] >= 0} {
2043		if [string match "setenv SSH*" $line] {
2044		    set env([lindex [split $line] 1]) \
2045			    [string trimright [lindex [split $line] 2] \;]
2046		}
2047	    }
2048	    close $agentout
2049	    $widget(statusagent) config -text "Agent active" -bg green -fg black
2050
2051	    $widget(idents) delete 0 end
2052
2053	    wm title .top17 "secpanel - Agent active"
2054	    set agent 1
2055
2056	    command_trace save "$configs(agentbin) -c"
2057	    historyman write 6 "Launching agent"
2058	}
2059	"kill" {
2060	    if {$m == "end" && ! $launcher && $agent == "ext"} {
2061		return
2062	    } elseif {$m == "end" && $launcher && $agent != "ext"} {
2063		catch {exec $configs(agentbin) -k} killerr
2064		unset env(SSH_AGENT_PID)
2065		unset env(SSH_AUTH_SOCK)
2066		historyman write 6 "Stopping agent"
2067	    } elseif {$m == "end" && $launcher && $agent == "ext"} {
2068		return
2069	    } else {
2070		if [info exists env(SSH_AGENT_PID)] {
2071		    if {$agent == "ext"} {
2072			showmessage "Will not kill external agent!" .top17
2073			return
2074		    }
2075		    if {[showconfirm "Kill SSH-agent?" ""] == 1} {
2076			exec $configs(agentbin) -k
2077			unset env(SSH_AGENT_PID)
2078			unset env(SSH_AUTH_SOCK)
2079			$widget(statusagent) config -text "No Agent" -bg red
2080			wm title .top17 "secpanel - No Agent"
2081			$widget(idents) delete 0 end
2082			set agent 0
2083
2084			command_trace save "$configs(agentbin) -k"
2085			historyman write 6 "Stopping agent"
2086			if [winfo exists .top33] {
2087			    destroyfilter .top33
2088			}
2089		    } else {
2090			return
2091		    }
2092		} else {
2093		    showmessage "No agent running" .top17
2094		}
2095	    }
2096	}
2097	"info" {
2098	    if {[info exists env(SSH_AGENT_PID)] && [info exists env(SSH_AUTH_SOCK)]} {
2099		Window show .top33
2100
2101		if {[info exists configs(wingeom)] && $configs(wingeom)} {
2102		    if [info exists wins(agentinfo)] {
2103			wm geometry ".top33" $wins(agentinfo)
2104		    }
2105		}
2106
2107		.top33.fra34.lab38 config -text $env(SSH_AUTH_SOCK)
2108		.top33.fra34.lab39 config -text $env(SSH_AGENT_PID)
2109
2110		catch {exec $configs(addbin) -l} err
2111
2112		command_trace save "$configs(addbin) -l"
2113
2114		set text .top33.cpd36.03
2115		$text delete 1.0 end
2116		$text insert end "Fingerprints of keys contained by the running agent:\n\n"
2117		$text insert end $err
2118	    } else {
2119		showmessage "No agent running or\nagent environment not clean" .top17
2120	    }
2121	}
2122	"chdef" {
2123	    set defident [tk_getOpenFile -initialdir "$env(HOME)/.ssh/"]
2124	    if {$defident != ""} {
2125		save_globals chdef
2126		historyman write 6 "Setting default identity to $defident"
2127	    }
2128	}
2129	"rmdef" {
2130	    set defident ""
2131	    save_globals chdef
2132	    historyman write 6 "Removing default identity"
2133	}
2134	"addident" {
2135	    if {! [info exists env(SSH_AGENT_PID)]} {
2136		showmessage "No agent running" .top17
2137		return
2138	    }
2139
2140	    if {($m == "start")} {
2141		if { $launcher && [info exists defident] && $defident != ""} {
2142		    showstatus "Adding default identity"
2143		    update idletasks
2144		    set fname $defident
2145		} else {
2146		    set fname ""
2147		}
2148	    } else {
2149		showstatus "Adding identity"
2150		update idletasks
2151		set fname [tk_getOpenFile -initialdir "$env(HOME)/.ssh/"]
2152	    }
2153	    if {$fname != ""} {
2154		# openssh
2155		if {$configs(sshver) == "OpenSSH"} {
2156		    set env(SSH_ASKPASS) $configs(askpassbin)
2157		}
2158
2159		catch {exec $configs(addbin) $fname < /dev/null} err
2160		command_trace save "$configs(addbin) $fname < /dev/null"
2161
2162		if [string match "*No such file*" $err] {
2163		    showmessage "Can't find your askpass program-\nCheck configuration!" .top17
2164		    return
2165		}
2166
2167		if [string match "Bad key file*" $err] {
2168		    showmessage "Bad key file" .top17
2169		    return
2170		}
2171		set found 0
2172		foreach ent [$widget(idents) get 0 end] {
2173		    if {$ent == $fname} {
2174			set found 1
2175			break
2176		    }
2177		}
2178		if {! $found} {
2179		    $widget(idents) insert end $fname
2180		}
2181		if [winfo exists .top33] {
2182		    manage_agent "info"
2183		}
2184		showstatus ""
2185		historyman write 6 "Adding identity $fname"
2186	    } else {
2187		showstatus ""
2188		return
2189	    }
2190	}
2191	"remident" {
2192	    if {! [info exists env(SSH_AGENT_PID)]} {
2193		showmessage "No agent running" .top17
2194		return
2195	    }
2196
2197	    if {[selection own] != $widget(idents)} {
2198		showmessage "No Identity selected" ""
2199		return
2200	    } else {
2201		catch {exec $configs(addbin) -d [$widget(idents) get active]}
2202		$widget(idents) delete active
2203		selection clear
2204		command_trace save "$configs(addbin) -d [$widget(idents) get active]"
2205		historyman write 6 "Removing identity [$widget(idents) get active]"
2206		if [winfo exists .top33] {
2207		    manage_agent "info"
2208		}
2209	    }
2210	}
2211    }
2212}
2213
2214proc newconn {state} {
2215    changetab ssh
2216    clear_profiles
2217}
2218
2219proc propconn {mode} {
2220    global widget
2221    if {[selection own] != $widget([set mode])} {
2222	showmessage "Please select connection" .top17
2223	return
2224    }
2225    if {[$widget([set mode]) index end] > 0} {
2226	changetab ssh
2227	load_profile $mode
2228    } else {
2229	showmessage "No conncections available, please use \"New\"" ""
2230	return
2231    }
2232}
2233
2234proc retprof {tit} {
2235    global env
2236    foreach f [glob -nocomplain "$env(HOME)/.secpanel/profiles/*.profile"] {
2237	source $f
2238	if {$title == $tit} {
2239	    return "[file rootname [file tail $f]]"
2240	}
2241	unset lfs
2242    }
2243}
2244
2245proc save_profile {} {
2246    global env widget noagentforward x11forward stricthost nopriv verbose \
2247	    quiet fork gateway compress algo compressval lfs rfs \
2248	    connwait termicon sshverconnect ipverconnect askuserspec noexec
2249
2250    set prname [$widget(profileent) get]
2251    if {$prname == ""} {
2252	showmessage "Enter a name for the profile" ""
2253	return
2254    }
2255
2256    set title [$widget(titleent) get]
2257    set host [$widget(hostent) get]
2258    set user [$widget(userent) get]
2259    if {[info exists askuserspec] && $askuserspec} {
2260	set user "<ASKFORUSER>"
2261    }
2262    set port [$widget(portent) get]
2263    set command [$widget(commandent) get]
2264    set subsys [$widget(subsysent) get]
2265
2266    if {$title == "" || $host == ""} {
2267	showmessage "You must enter at least host and title" ""
2268	return
2269    }
2270
2271    if {$subsys != "" && ($command != "" || $noexec)} {
2272	showmessage "The subsys-entry will be used later (has higher priority)" .top17
2273    }
2274
2275    set identity [$widget(identityent) get]
2276    set cfgfile [$widget(cfgfileent) get]
2277
2278    set prfile [open "$env(HOME)/.secpanel/profiles/$prname.profile" w]
2279
2280    puts $prfile "#\n# secpanel-Profile\n# Do not edit, use secpanel instead\n#"
2281
2282    foreach ent {title host user port command subsys identity cfgfile} {
2283	puts $prfile "set [set ent] \"[set $ent]\""
2284    }
2285    foreach bool {noagentforward x11forward stricthost nopriv verbose \
2286	    quiet fork gateway compress connwait termicon askuserspec noexec} {
2287	if [info exists [set bool]] {
2288	    if [set $bool] {
2289		puts $prfile "set [set bool] \"[set $bool]\""
2290	    } else {
2291		puts $prfile "set [set bool] \"[set $bool]\""
2292	    }
2293	}
2294    }
2295    foreach sel {algo compressval} {
2296	puts $prfile "set [set sel] \"[set $sel]\""
2297    }
2298
2299    puts $prfile "set sshverconnect \"[set sshverconnect]\""
2300
2301    puts $prfile "set ipverconnect \"[set ipverconnect]\""
2302
2303    if [info exists lfs] {
2304	puts $prfile "array set lfs {[array get lfs]}"
2305    } else {
2306	puts $prfile "array set lfs {}"
2307    }
2308
2309    if [info exists rfs] {
2310	puts $prfile "array set rfs {[array get rfs]}"
2311    } else {
2312	puts $prfile "array set rfs {}"
2313    }
2314
2315    close $prfile
2316
2317    specsiteupdate
2318    clear_prmenu
2319    clear_profiles
2320}
2321
2322proc seldistkey {} {
2323    global env widget
2324    set ftypes {
2325	{{Public keys} {.pub}}
2326	{{All files} *}
2327    }
2328    $widget(distkeyentry) delete 0 end
2329    $widget(distkeyentry) insert 0 \
2330	    [tk_getOpenFile -initialdir "$env(HOME)/.ssh"  -filetypes $ftypes]
2331}
2332
2333
2334proc specsiteupdate {{mode ""}} {
2335    global widget env
2336    $widget(specsites) delete 0 end
2337
2338    if [winfo exists $widget(distconnlist)] {
2339		$widget(distconnlist) delete 0 end
2340    }
2341
2342    set profiles [glob -nocomplain "$env(HOME)/.secpanel/profiles/*.profile"]
2343
2344    if {$mode == "ss"} {
2345		if {! [winfo exists $widget(sspecsites).sspecmenu]} {
2346			menu $widget(sspecsites).sspecmenu -tearoff 0 -border 1
2347			$widget(sspecsites) config -menu $widget(sspecsites).sspecmenu
2348		} else {
2349			$widget(sspecsites).sspecmenu delete 0 end
2350		}
2351    }
2352
2353    foreach prof [lsort $profiles] {
2354		source $prof
2355		$widget(specsites) insert end $title
2356		if [winfo exists $widget(distconnlist)] {
2357			$widget(distconnlist) insert end $title
2358		}
2359
2360		if {$mode == "ss"} {
2361			 $widget(sspecsites).sspecmenu add command -label "$title" -command "connect ss"
2362		}
2363
2364		unset lfs
2365    }
2366}
2367
2368proc about {} {
2369    global libdir spversion
2370    Window show .top25
2371    .top25.fra26.lab21 config -text "secpanel $spversion"
2372}
2373
2374proc showstatus {text} {
2375    global widget
2376    $widget(status) config -text $text
2377    update idletasks
2378}
2379
2380proc do_firstinit {lv} {
2381    global libdir spversion env
2382    source $libdir/convert_history.tcl
2383    source $libdir/convert_profile.tcl
2384}
2385
2386proc do_exit {} {
2387    global env wins libdir configs
2388
2389    foreach f [glob -nocomplain "$env(HOME)/.secpanel/.runfiles/*"] {
2390		file delete -force $f
2391    }
2392
2393    if {[info exists env(SSH_AGENT_PID)] && [info exists env(SSH_AUTH_SOCK)]} {
2394		manage_agent kill "end"
2395    }
2396
2397    foreach {winn winnr} {base .top17 trace .top24 sat .top27 agentinfo .top33 hist .top26} {
2398		if [winfo exists $winnr] {
2399			set wins($winn) [wm geometry $winnr]
2400		}
2401    }
2402
2403    save_globals "geom"
2404
2405    # spdata
2406    if [set configs(protectdata)] {
2407		exec $libdir/dppw.tcl "en"
2408    }
2409
2410    destroyfilter .top17
2411
2412    exit
2413}
2414
2415proc destroyfilter {win} {
2416    global wins
2417    foreach {winn winnr} {base .top17 trace .top24 sat .top27 agentinfo .top33 hist .top26} {
2418		if {$win == $winnr} {
2419			set wins($winn) [wm geometry $win]
2420		}
2421    }
2422    Window destroy $win
2423}
2424
2425proc main {argc argv} {
2426    global widget env configs libdir spversion launcher agent termtype
2427
2428    wm protocol .top17 WM_DELETE_WINDOW do_exit
2429
2430#    bind .top17 <Destroy> {
2431#        do_exit
2432#    }
2433
2434    foreach f {ssh keygen agent add askpass scp browser} {
2435		$widget([set f]ent) insert 0 "$configs([set f]bin)"
2436    }
2437    foreach b {connects profiles keys configs sscreen} {
2438		$widget([set b]but) config -border 2 -relief groove -image \
2439			[image create photo -file $libdir/images/[set b]_gr.gif]
2440    }
2441
2442    foreach {sftptag sftpprog} {
2443	"KDE-Konqueror" konqueror
2444	"GNOME-Nautilus" nautilus
2445	"Thunar" thunar
2446	"Filezilla" filezilla
2447    } {
2448	if {! [catch {exec which "$sftpprog"}]} {
2449	    .top17.fra44.fra19.fra30.men34.m add radiobutton \
2450		-value "$sftptag" -variable "configs(sftpbin)" -label "$sftptag"
2451	} else {
2452	    .top17.fra44.fra19.fra30.men34.m add radiobutton \
2453		-value "$sftpprog" -variable "configs(sftpbin)" -label "$sftptag (not found)" \
2454		-state "disabled"
2455	}
2456    }
2457
2458    source "$libdir/termdefs.txt"
2459
2460    foreach k [array names termtype] {
2461	if [string match "*_path" $k] {
2462	    set termname [string replace $k [string first "_" $k] end]
2463	    set termpath $termtype($k)
2464	    if {! [catch {exec which "$termpath"}]} {
2465		.top17.fra44.fra19.fra32.men35.01 add radiobutton \
2466		    -value "$termname" -variable "configs(termver)" -label "$termname"
2467	    } else {
2468		.top17.fra44.fra19.fra32.men35.01 add radiobutton \
2469		    -value "$termname" -variable "configs(termver)" -label "$termname (not found)" \
2470		    -state "disabled"
2471	    }
2472	}
2473    }
2474
2475    set lv 0
2476
2477    if [file exists "$env(HOME)/.secpanel/.init"] {
2478	set vf [open "$env(HOME)/.secpanel/.init" r]
2479	set lv [read $vf]
2480
2481	if {[string equal $spversion $lv] != 1} {
2482	    do_firstinit $lv
2483	    exec echo -n $spversion > $env(HOME)/.secpanel/.init
2484	}
2485	close $vf
2486    } else {
2487	exec echo -n $spversion > $env(HOME)/.secpanel/.init
2488    }
2489
2490    menu .mc1 -tearoff 0 -borderwidth 1
2491
2492
2493    if {! [catch {exec which "cssh"}]} {
2494	.mc1 add command -label "ClusterSSH" -command "multiconnect cssh"
2495    } else {
2496	.mc1 add command -label "ClusterSSH (not found)" -command "multiconnect cssh" -state "disabled"
2497    }
2498
2499    if {! [catch {exec which "multixterm"}]} {
2500	.mc1 add command -label "Multi Xterm" -command "multiconnect multixterm"
2501    } else {
2502	.mc1 add command -label "Multi Xterm (not found)" -command "multiconnect multixterm" -state "disabled"
2503    }
2504
2505    if {[catch {exec which "filezilla"}] && [catch {exec which "thunar"}] && [catch {exec which "nautilus"}] && [catch {exec which "konqueror"}]
2506} {
2507	.top17.fra46.fra26.fra29.fra36.but34 configure -state "disabled"
2508    }
2509
2510    bind .top17.fra46.fra26.fra29.fra36.but38 <Button> {
2511	tk_popup .mc1 [winfo pointerx .top17] [winfo pointery .top17]
2512    }
2513
2514    clear_prmenu
2515    clear_profiles
2516    specsiteupdate
2517
2518    if {[info exists env(SSH_AGENT_PID)] && [info exists env(SSH_AUTH_SOCK)]} {
2519	$widget(statusagent) config -text "Agent active (external)" -bg green -fg black
2520	wm title .top17 "secpanel - Agent active (external)"
2521	historyman write 6 "Accepted external agent"
2522
2523	set initagentout [open "| ssh-add -L" r]
2524	while {[gets $initagentout line] >= 0} {
2525	    if [string match "The agent has no identities*" $line] {
2526		continue
2527	    }
2528	    $widget(idents) insert end [lindex [split $line] 2]
2529	}
2530
2531	set agent "ext"
2532    } else {
2533	$widget(statusagent) config -text "No Agent" -bg red
2534	wm title .top17 "secpanel - No agent"
2535    }
2536
2537
2538    if {$launcher} {
2539	if {[manage_agent launch] != "error"} {
2540	    manage_agent addident "start"
2541	}
2542    }
2543
2544    if {[info exists configs(startsat)] && $configs(startsat)} {
2545	changetab small
2546    }
2547
2548}
2549
2550source $libdir/gui.tcl
2551
2552if {[info exists configs(wingeom)] && $configs(wingeom)} {
2553    if [info exists wins(base)] {
2554	wm geometry ".top17" $wins(base)
2555    }
2556}
2557
2558foreach b {.top17.fra44.fra19.fra20.but23 .top17.fra44.fra19.fra26.03 \
2559	       .top17.fra44.fra19.fra27.03 .top17.fra44.fra19.fra28.03 \
2560	       .top17.fra44.fra19.fra29.03 \
2561	       .top17.fra44.fra19.fra34.but34 .top17.fra21.fra24.but22 \
2562	       .top17.fra21.fra24.but23 .top17.fra44.fra19.fra18.03 \
2563	       } {
2564    $b configure -image [image create photo -file $libdir/images/folder.gif]
2565}
2566
2567main $argc $argv
2568