From ed280d5ac360e2af796e9bd973d7b4df89f0c449 Mon Sep 17 00:00:00 2001 From: "Jeremy T. Bouse" Date: Fri, 27 Nov 2009 16:20:12 -0500 Subject: Imported Upstream version 1.7.4 --- docs/paramiko.kex_gex-pysrc.html | 483 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 483 insertions(+) create mode 100644 docs/paramiko.kex_gex-pysrc.html (limited to 'docs/paramiko.kex_gex-pysrc.html') diff --git a/docs/paramiko.kex_gex-pysrc.html b/docs/paramiko.kex_gex-pysrc.html new file mode 100644 index 0000000..2bc411e --- /dev/null +++ b/docs/paramiko.kex_gex-pysrc.html @@ -0,0 +1,483 @@ + + + + + paramiko.kex_gex + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Package paramiko :: + Module kex_gex + + + + + +
[frames] | no frames]
+
+

Source Code for Module paramiko.kex_gex

+
+  1  # Copyright (C) 2003-2007  Robey Pointer <robey@lag.net> 
+  2  # 
+  3  # This file is part of paramiko. 
+  4  # 
+  5  # Paramiko is free software; you can redistribute it and/or modify it under the 
+  6  # terms of the GNU Lesser General Public License as published by the Free 
+  7  # Software Foundation; either version 2.1 of the License, or (at your option) 
+  8  # any later version. 
+  9  # 
+ 10  # Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY 
+ 11  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
+ 12  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
+ 13  # details. 
+ 14  # 
+ 15  # You should have received a copy of the GNU Lesser General Public License 
+ 16  # along with Paramiko; if not, write to the Free Software Foundation, Inc., 
+ 17  # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. 
+ 18   
+ 19  """ 
+ 20  Variant on L{KexGroup1 <paramiko.kex_group1.KexGroup1>} where the prime "p" and 
+ 21  generator "g" are provided by the server.  A bit more work is required on the 
+ 22  client side, and a B{lot} more on the server side. 
+ 23  """ 
+ 24   
+ 25  from Crypto.Hash import SHA 
+ 26  from Crypto.Util import number 
+ 27   
+ 28  from paramiko.common import * 
+ 29  from paramiko import util 
+ 30  from paramiko.message import Message 
+ 31  from paramiko.ssh_exception import SSHException 
+ 32   
+ 33   
+ 34  _MSG_KEXDH_GEX_REQUEST_OLD, _MSG_KEXDH_GEX_GROUP, _MSG_KEXDH_GEX_INIT, \ 
+ 35      _MSG_KEXDH_GEX_REPLY, _MSG_KEXDH_GEX_REQUEST = range(30, 35) 
+ 36   
+ 37   
+
38 -class KexGex (object): +
39 + 40 name = 'diffie-hellman-group-exchange-sha1' + 41 min_bits = 1024 + 42 max_bits = 8192 + 43 preferred_bits = 2048 + 44 +
45 - def __init__(self, transport): +
46 self.transport = transport + 47 self.p = None + 48 self.q = None + 49 self.g = None + 50 self.x = None + 51 self.e = None + 52 self.f = None + 53 self.old_style = False +
54 +
55 - def start_kex(self, _test_old_style=False): +
56 if self.transport.server_mode: + 57 self.transport._expect_packet(_MSG_KEXDH_GEX_REQUEST, _MSG_KEXDH_GEX_REQUEST_OLD) + 58 return + 59 # request a bit range: we accept (min_bits) to (max_bits), but prefer + 60 # (preferred_bits). according to the spec, we shouldn't pull the + 61 # minimum up above 1024. + 62 m = Message() + 63 if _test_old_style: + 64 # only used for unit tests: we shouldn't ever send this + 65 m.add_byte(chr(_MSG_KEXDH_GEX_REQUEST_OLD)) + 66 m.add_int(self.preferred_bits) + 67 self.old_style = True + 68 else: + 69 m.add_byte(chr(_MSG_KEXDH_GEX_REQUEST)) + 70 m.add_int(self.min_bits) + 71 m.add_int(self.preferred_bits) + 72 m.add_int(self.max_bits) + 73 self.transport._send_message(m) + 74 self.transport._expect_packet(_MSG_KEXDH_GEX_GROUP) +
75 +
76 - def parse_next(self, ptype, m): +
77 if ptype == _MSG_KEXDH_GEX_REQUEST: + 78 return self._parse_kexdh_gex_request(m) + 79 elif ptype == _MSG_KEXDH_GEX_GROUP: + 80 return self._parse_kexdh_gex_group(m) + 81 elif ptype == _MSG_KEXDH_GEX_INIT: + 82 return self._parse_kexdh_gex_init(m) + 83 elif ptype == _MSG_KEXDH_GEX_REPLY: + 84 return self._parse_kexdh_gex_reply(m) + 85 elif ptype == _MSG_KEXDH_GEX_REQUEST_OLD: + 86 return self._parse_kexdh_gex_request_old(m) + 87 raise SSHException('KexGex asked to handle packet type %d' % ptype) +
88 + 89 + 90 ### internals... + 91 + 92 +
93 - def _generate_x(self): +
94 # generate an "x" (1 < x < (p-1)/2). + 95 q = (self.p - 1) // 2 + 96 qnorm = util.deflate_long(q, 0) + 97 qhbyte = ord(qnorm[0]) + 98 bytes = len(qnorm) + 99 qmask = 0xff +100 while not (qhbyte & 0x80): +101 qhbyte <<= 1 +102 qmask >>= 1 +103 while True: +104 self.transport.randpool.stir() +105 x_bytes = self.transport.randpool.get_bytes(bytes) +106 x_bytes = chr(ord(x_bytes[0]) & qmask) + x_bytes[1:] +107 x = util.inflate_long(x_bytes, 1) +108 if (x > 1) and (x < q): +109 break +110 self.x = x +
111 +
112 - def _parse_kexdh_gex_request(self, m): +
113 minbits = m.get_int() +114 preferredbits = m.get_int() +115 maxbits = m.get_int() +116 # smoosh the user's preferred size into our own limits +117 if preferredbits > self.max_bits: +118 preferredbits = self.max_bits +119 if preferredbits < self.min_bits: +120 preferredbits = self.min_bits +121 # fix min/max if they're inconsistent. technically, we could just pout +122 # and hang up, but there's no harm in giving them the benefit of the +123 # doubt and just picking a bitsize for them. +124 if minbits > preferredbits: +125 minbits = preferredbits +126 if maxbits < preferredbits: +127 maxbits = preferredbits +128 # now save a copy +129 self.min_bits = minbits +130 self.preferred_bits = preferredbits +131 self.max_bits = maxbits +132 # generate prime +133 pack = self.transport._get_modulus_pack() +134 if pack is None: +135 raise SSHException('Can\'t do server-side gex with no modulus pack') +136 self.transport._log(DEBUG, 'Picking p (%d <= %d <= %d bits)' % (minbits, preferredbits, maxbits)) +137 self.g, self.p = pack.get_modulus(minbits, preferredbits, maxbits) +138 m = Message() +139 m.add_byte(chr(_MSG_KEXDH_GEX_GROUP)) +140 m.add_mpint(self.p) +141 m.add_mpint(self.g) +142 self.transport._send_message(m) +143 self.transport._expect_packet(_MSG_KEXDH_GEX_INIT) +
144 +
145 - def _parse_kexdh_gex_request_old(self, m): +
146 # same as above, but without min_bits or max_bits (used by older clients like putty) +147 self.preferred_bits = m.get_int() +148 # smoosh the user's preferred size into our own limits +149 if self.preferred_bits > self.max_bits: +150 self.preferred_bits = self.max_bits +151 if self.preferred_bits < self.min_bits: +152 self.preferred_bits = self.min_bits +153 # generate prime +154 pack = self.transport._get_modulus_pack() +155 if pack is None: +156 raise SSHException('Can\'t do server-side gex with no modulus pack') +157 self.transport._log(DEBUG, 'Picking p (~ %d bits)' % (self.preferred_bits,)) +158 self.g, self.p = pack.get_modulus(self.min_bits, self.preferred_bits, self.max_bits) +159 m = Message() +160 m.add_byte(chr(_MSG_KEXDH_GEX_GROUP)) +161 m.add_mpint(self.p) +162 m.add_mpint(self.g) +163 self.transport._send_message(m) +164 self.transport._expect_packet(_MSG_KEXDH_GEX_INIT) +165 self.old_style = True +
166 +
167 - def _parse_kexdh_gex_group(self, m): +
168 self.p = m.get_mpint() +169 self.g = m.get_mpint() +170 # reject if p's bit length < 1024 or > 8192 +171 bitlen = util.bit_length(self.p) +172 if (bitlen < 1024) or (bitlen > 8192): +173 raise SSHException('Server-generated gex p (don\'t ask) is out of range (%d bits)' % bitlen) +174 self.transport._log(DEBUG, 'Got server p (%d bits)' % bitlen) +175 self._generate_x() +176 # now compute e = g^x mod p +177 self.e = pow(self.g, self.x, self.p) +178 m = Message() +179 m.add_byte(chr(_MSG_KEXDH_GEX_INIT)) +180 m.add_mpint(self.e) +181 self.transport._send_message(m) +182 self.transport._expect_packet(_MSG_KEXDH_GEX_REPLY) +
183 +
184 - def _parse_kexdh_gex_init(self, m): +
185 self.e = m.get_mpint() +186 if (self.e < 1) or (self.e > self.p - 1): +187 raise SSHException('Client kex "e" is out of range') +188 self._generate_x() +189 self.f = pow(self.g, self.x, self.p) +190 K = pow(self.e, self.x, self.p) +191 key = str(self.transport.get_server_key()) +192 # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) +193 hm = Message() +194 hm.add(self.transport.remote_version, self.transport.local_version, +195 self.transport.remote_kex_init, self.transport.local_kex_init, +196 key) +197 if not self.old_style: +198 hm.add_int(self.min_bits) +199 hm.add_int(self.preferred_bits) +200 if not self.old_style: +201 hm.add_int(self.max_bits) +202 hm.add_mpint(self.p) +203 hm.add_mpint(self.g) +204 hm.add_mpint(self.e) +205 hm.add_mpint(self.f) +206 hm.add_mpint(K) +207 H = SHA.new(str(hm)).digest() +208 self.transport._set_K_H(K, H) +209 # sign it +210 sig = self.transport.get_server_key().sign_ssh_data(self.transport.randpool, H) +211 # send reply +212 m = Message() +213 m.add_byte(chr(_MSG_KEXDH_GEX_REPLY)) +214 m.add_string(key) +215 m.add_mpint(self.f) +216 m.add_string(str(sig)) +217 self.transport._send_message(m) +218 self.transport._activate_outbound() +
219 +
220 - def _parse_kexdh_gex_reply(self, m): +
221 host_key = m.get_string() +222 self.f = m.get_mpint() +223 sig = m.get_string() +224 if (self.f < 1) or (self.f > self.p - 1): +225 raise SSHException('Server kex "f" is out of range') +226 K = pow(self.f, self.x, self.p) +227 # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) +228 hm = Message() +229 hm.add(self.transport.local_version, self.transport.remote_version, +230 self.transport.local_kex_init, self.transport.remote_kex_init, +231 host_key) +232 if not self.old_style: +233 hm.add_int(self.min_bits) +234 hm.add_int(self.preferred_bits) +235 if not self.old_style: +236 hm.add_int(self.max_bits) +237 hm.add_mpint(self.p) +238 hm.add_mpint(self.g) +239 hm.add_mpint(self.e) +240 hm.add_mpint(self.f) +241 hm.add_mpint(K) +242 self.transport._set_K_H(K, SHA.new(str(hm)).digest()) +243 self.transport._verify_key(host_key, sig) +244 self.transport._activate_outbound() +
245 +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + -- cgit v1.2.3