summaryrefslogtreecommitdiff
path: root/lib/sshkey.tcl
blob: 589ff8f78aba8273651b33005c6f6abd1db2fa27 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# git-gui about git-gui dialog
# Copyright (C) 2006, 2007 Shawn Pearce

proc find_ssh_key {} {
	foreach name {
		~/.ssh/id_dsa.pub ~/.ssh/id_ecdsa.pub ~/.ssh/id_ed25519.pub
		~/.ssh/id_rsa.pub ~/.ssh/identity.pub
	} {
		if {[file exists $name]} {
			set fh    [open $name r]
			set cont  [read $fh]
			close $fh
			return [list $name $cont]
		}
	}

	return {}
}

proc do_ssh_key {} {
	global sshkey_title have_tk85 sshkey_fd use_ttk NS

	set w .sshkey_dialog
	if {[winfo exists $w]} {
		raise $w
		return
	}

	Dialog $w
	wm transient $w .

	set finfo [find_ssh_key]
	if {$finfo eq {}} {
		set sshkey_title [mc "No keys found."]
		set gen_state   normal
	} else {
		set sshkey_title [mc "Found a public key in: %s" [lindex $finfo 0]]
		set gen_state   disabled
	}

	${NS}::frame $w.header
	${NS}::label $w.header.lbl -textvariable sshkey_title -anchor w
	${NS}::button $w.header.gen -text [mc "Generate Key"] \
		-command [list make_ssh_key $w] -state $gen_state
	pack $w.header.lbl -side left -expand 1 -fill x
	pack $w.header.gen -side right
	pack $w.header -fill x -pady 5 -padx 5

	text $w.contents -width 60 -height 10 -wrap char -relief sunken
	pack $w.contents -fill both -expand 1
	if {$have_tk85} {
		set clr darkblue
		if {$use_ttk} { set clr [ttk::style lookup . -selectbackground] }
		$w.contents configure -inactiveselectbackground $clr
	}

	${NS}::frame $w.buttons
	${NS}::button $w.buttons.close -text [mc Close] \
		-default active -command [list destroy $w]
	pack $w.buttons.close -side right
	${NS}::button $w.buttons.copy -text [mc "Copy To Clipboard"] \
		-command [list tk_textCopy $w.contents]
	pack $w.buttons.copy -side left
	pack $w.buttons -side bottom -fill x -pady 5 -padx 5

	if {$finfo ne {}} {
		$w.contents insert end [lindex $finfo 1] sel
	}
	$w.contents configure -state disabled

	bind $w <Visibility> "grab $w; focus $w.buttons.close"
	bind $w <Key-Escape> "destroy $w"
	bind $w <Key-Return> "destroy $w"
	bind $w <Destroy> kill_sshkey
	wm title $w [mc "Your OpenSSH Public Key"]
	tk::PlaceWindow $w widget .
	tkwait window $w
}

proc make_ssh_key {w} {
	global sshkey_title sshkey_output sshkey_fd

	set sshkey_title [mc "Generating..."]
	$w.header.gen configure -state disabled

	set cmdline [list sh -c {echo | ssh-keygen -q -t rsa -f ~/.ssh/id_rsa 2>&1}]

	if {[catch { set sshkey_fd [_open_stdout_stderr $cmdline] } err]} {
		error_popup [mc "Could not start ssh-keygen:\n\n%s" $err]
		return
	}

	set sshkey_output {}
	fconfigure $sshkey_fd -blocking 0
	fileevent $sshkey_fd readable [list read_sshkey_output $sshkey_fd $w]
}

proc kill_sshkey {} {
	global sshkey_fd
	if {![info exists sshkey_fd]} return
	catch { kill_file_process $sshkey_fd }
	catch { close $sshkey_fd }
}

proc read_sshkey_output {fd w} {
	global sshkey_fd sshkey_output sshkey_title

	set sshkey_output "$sshkey_output[read $fd]"
	if {![eof $fd]} return

	fconfigure $fd -blocking 1
	unset sshkey_fd

	$w.contents configure -state normal
	if {[catch {close $fd} err]} {
		set sshkey_title [mc "Generation failed."]
		$w.contents insert end $err
		$w.contents insert end "\n"
		$w.contents insert end $sshkey_output
	} else {
		set finfo [find_ssh_key]
		if {$finfo eq {}} {
			set sshkey_title [mc "Generation succeeded, but no keys found."]
			$w.contents insert end $sshkey_output
		} else {
			set sshkey_title [mc "Your key is in: %s" [lindex $finfo 0]]
			$w.contents insert end [lindex $finfo 1] sel
		}
	}
	$w.contents configure -state disable
}