-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathessh.sh
175 lines (143 loc) · 4.95 KB
/
essh.sh
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/bin/bash
# Declare the following two variables before executing essh to let it know what
# to transfer to the remote machine
#
# List all the functions that you want to inject on the remote system.
# essh is usually desireble to be able to hop arround and have your functions with you.
#
# ESSH_FUNCTIONS="essh bin2int int2bin sshrm ts ts2 injection"
#
# List the aliases to inject.
#
# ESSH_ALIASES="chn gtree srsync wget openports"
# ESSH_SCRIPTS=("/home/user/script.sh")
__ESSH_ESCAPE () {
echo -n "$1" | sed 's/\\/\\\\/g;s/\$/\\$/g;s/"/\\"/g'
}
__ESSH_QUOTE () {
echo -n "\""
cat
echo -n "\""
}
__ESSH_ESCAPE_ARGS () {
local res
for i in "$@"; do
res+="${res:+ }"
res+="$(__ESSH_ESCAPE "$i" | __ESSH_QUOTE)"
done
echo "$res";
}
__ESSH_ESCAPE_FILES () {
sed 's/\\/\\\\/g;s/\$/\\$/g;s/"/\\"/g' "$@"
}
__ESSH_GET_CODE_TEXT () {
local scripts functions aliases esshDependencies
# Add all essh and sgo functions to the list
esshDependencies="essh injection __ESSH_PREAMBLE __ESSH_GET_CODE_TEXT __ESSH_ESCAPE_FILES __ESSH_ESCAPE_ARGS __ESSH_QUOTE __ESSH_ESCAPE esudo"
esshDependencies+=" __SGO_PARSE_RULE __SGO_HANDLE sgoInit __SGO_DEBUG __SGO_DEBUG_END sgo"
# Get the function definitions as they are currently known by the running bash.
# This means that we do not read from a file and can perform this step again
# on the remote host to transfer the functions a second time to the next hop.
if [[ -n ${ESSH_FUNCTIONS// } ]]; then
functions="$(declare -f $ESSH_FUNCTIONS $esshDependencies)""$n"
fi
# Get the alias definitions
if [[ -n ${ESSH_ALIASES// } ]]; then
aliases="$(alias $ESSH_ALIASES)""$n"
fi
# for script in "${ESSH_SCRIPTS[@]}"; do
# file=${script##*/}
# escapedFile=${file//./_}
# scripts+="$escapedFile=\"$(__ESSH_ESCAPE_FILES "$script")\"$n"
# scripts+="alias $file='bash -c \"\$$escapedFile\" $file'$n"
# ESSH_ALIASES+=" $file"
# done
echo "ESSH_FUNCTIONS='$ESSH_FUNCTIONS'"
echo "ESSH_ALIASES='$ESSH_ALIASES';"
#echo "$scripts"
echo "$n$functions"
echo "$n$aliases"
}
__ESSH_PREAMBLE () {
# If the version of the remote bash has the pipe sourcing bug, tell the user to manually
# run the script in the $init variable and define the function on that end.
echo "if [[ \$BASH_VERSINFO -lt 4 ]]; then"
echo "echo 'execute: eval \"\$init\" (quotes are important)'"
echo "exec \$SHELL"
echo "fi"
# rcfile option instructs the remote bash to read the initialization script (.bashrc)
# from the pipe instead of from the regular location.
if [[ $1 == "-r" ]]; then
echo -n 'exec $SHELL --rcfile '
elif [[ $1 == "-l" ]]; then
echo -n "$SHELL --rcfile "
fi
# Construct the pipe
echo -n "<("
# Read the original bashrc
echo -n " cat ~/.bashrc;"
# Append the prepared init script
echo -n " echo; echo \"\$init\"; "
echo ");"
}
# Prepare the script to be executed on the remote system.
injection () {
local injection n=$'\n' codeText
if ! [[ $1 =~ ^-(n|l|r)$ ]]; then
return 1
fi
# This part tells the remote end to store the definitions of the functions in a variable
# This is usefull if the remote end has a bash version older than 4 and has the
# pipe sourcing bug.
codeText="$(__ESSH_GET_CODE_TEXT)"
if [[ $1 != "-n" ]]; then
injection+="export init=\"$(__ESSH_ESCAPE "$codeText")\";"$'\n'
injection+="$(__ESSH_PREAMBLE $1)"
else
echo "$codeText"
return 0
fi
echo "$injection"
}
essh () { #DOC: Like ssh but make available some function you have declared. Note that this will suppress the motd.
sgoInit '![1|2|4|6|A|a|C|f|G|g|K|k|M|N|n|q|s|T|t|V|v|X|x|Y|y]
!{b|c|D|E|e|F|I|i|L|l|m|O|o|p|Q|R|S|W|w}';
sgo "$@"
shift $__SGO_SHIFT;
args=("$__SGO_IGNORED")
host="$1"
shift
cmd="$(__ESSH_ESCAPE_ARGS "$@")"
if [[ -n $host && $# -eq 0 ]]; then
# Start an ssh session and run the commands prepared by injection()
if [[ -n $args ]]; then
ssh -t "$args" "$host" "$(injection -r)"
else
ssh -t "$host" "$(injection -r)"
fi
elif [[ -n $host && $# -gt 0 ]]; then
if [[ -n $args ]]; then
ssh "$args" "$host" "$(injection -n) "$'\n'"$cmd"
else
ssh "$host" "$(injection -n) "$'\n'"$cmd"
fi
else
# In case the user did not provide any argument, just run ssh to show the help message.
ssh
fi
}
esudo () {
sgoInit '![A<askpass|preserve-env>|b<background>|E<preserve-env>|e<edit>|H<set-home>|h<help>|i<login>|K<remove-timestamp>|k<reset-timestamp>|l<list>|n<non-interactive>|P<preserve-groups>|S<stdin>|s<shell>|V<version>|v<validate>]
!{p<prompt>|h<host>|r<role>|t<type>|U<other-user>|g<group>|T<command-timeout>|C<close-from>|u<user>}'
sgo "$@"
shift $__SGO_SHIFT;
args=("$__SGO_IGNORED")
cmd="$(__ESSH_ESCAPE_ARGS "$@")"
# local args="$(__ESSH_ESCAPE_ARGS "$@")"
# echo "I am going to execute this:"$'\n'"$(injection -n) "$'\n'"$cmd" > /tmp/esudo
if [[ -n $args ]]; then
sudo "$args" bash -c "$(injection -n) "$'\n'"$cmd"
else
sudo bash -c "$(injection -n) "$'\n'"$cmd"
fi
}